summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qarraydata.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2023-08-22 14:28:39 -0700
committerMarc Mutz <marc.mutz@qt.io>2023-12-11 18:41:56 +0000
commit4d7864f0517679ebe70a2a96afdae5dc4f5a2d62 (patch)
tree457dba7e4e93b6a6c7cbf6a1d3cbcacebdcfccb8 /src/corelib/tools/qarraydata.cpp
parent7a829eaf51853e0852db28b8b8223e1a62a3db0c (diff)
QArrayData: add allocate1 and allocate2 for 1- and 2-byte types
This makes the two most-often used QTypedArrayData::allocate() -- the ones for char (for QByteArray) and char16_t (for QString) -- go to specialized versions, which have much simpler code. After all, multiplications by 1 are quite trivial. I didn't check whether an LTO compiler was const-propagating the sizes in inlined calls from qstring.cpp and qbytearray.cpp. But not everyone uses LTO, so this benefits everyone, in a very hot path, for minimal cost. Pick-to: 6.7 Change-Id: Ifa1111900d6945ea8e05fffd177dd1ce659b3fd5 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Diffstat (limited to 'src/corelib/tools/qarraydata.cpp')
-rw-r--r--src/corelib/tools/qarraydata.cpp64
1 files changed, 46 insertions, 18 deletions
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp
index 56f1461644..ff3bf2d6b8 100644
--- a/src/corelib/tools/qarraydata.cpp
+++ b/src/corelib/tools/qarraydata.cpp
@@ -151,21 +151,19 @@ namespace {
struct alignas(std::max_align_t) AlignedQArrayData : QArrayData
{
};
-}
+struct AllocationResult {
+ void *data;
+ QArrayData *header;
+};
+}
-void *QArrayData::allocate(QArrayData **dptr, qsizetype objectSize, qsizetype alignment,
- qsizetype capacity, QArrayData::AllocationOption option) noexcept
+static inline AllocationResult
+allocateHelper(qsizetype objectSize, qsizetype alignment, qsizetype capacity,
+ QArrayData::AllocationOption option) noexcept
{
- Q_ASSERT(dptr);
- // Alignment is a power of two
- Q_ASSERT(alignment >= qsizetype(alignof(QArrayData))
- && !(alignment & (alignment - 1)));
-
- if (capacity == 0) {
- *dptr = nullptr;
- return nullptr;
- }
+ if (capacity == 0)
+ return {};
qsizetype headerSize = sizeof(AlignedQArrayData);
const qsizetype headerAlignment = alignof(AlignedQArrayData);
@@ -181,10 +179,8 @@ void *QArrayData::allocate(QArrayData **dptr, qsizetype objectSize, qsizetype al
auto blockSize = calculateBlockSize(capacity, objectSize, headerSize, option);
capacity = blockSize.elementCount;
qsizetype allocSize = blockSize.size;
- if (Q_UNLIKELY(allocSize < 0)) { // handle overflow. cannot allocate reliably
- *dptr = nullptr;
- return nullptr;
- }
+ if (Q_UNLIKELY(allocSize < 0)) // handle overflow. cannot allocate reliably
+ return {};
QArrayData *header = allocateData(allocSize);
void *data = nullptr;
@@ -194,8 +190,40 @@ void *QArrayData::allocate(QArrayData **dptr, qsizetype objectSize, qsizetype al
header->alloc = qsizetype(capacity);
}
- *dptr = header;
- return data;
+ return { data, header };
+}
+
+// Generic size and alignment allocation function
+void *QArrayData::allocate(QArrayData **dptr, qsizetype objectSize, qsizetype alignment,
+ qsizetype capacity, AllocationOption option) noexcept
+{
+ Q_ASSERT(dptr);
+ // Alignment is a power of two
+ Q_ASSERT(alignment >= qsizetype(alignof(QArrayData))
+ && !(alignment & (alignment - 1)));
+
+ auto r = allocateHelper(objectSize, alignment, capacity, option);
+ *dptr = r.header;
+ return r.data;
+}
+
+// Fixed size and alignment allocation functions
+void *QArrayData::allocate1(QArrayData **dptr, qsizetype capacity, AllocationOption option) noexcept
+{
+ Q_ASSERT(dptr);
+
+ auto r = allocateHelper(1, alignof(AlignedQArrayData), capacity, option);
+ *dptr = r.header;
+ return r.data;
+}
+
+void *QArrayData::allocate2(QArrayData **dptr, qsizetype capacity, AllocationOption option) noexcept
+{
+ Q_ASSERT(dptr);
+
+ auto r = allocateHelper(2, alignof(AlignedQArrayData), capacity, option);
+ *dptr = r.header;
+ return r.data;
}
QPair<QArrayData *, void *>