From 4d7864f0517679ebe70a2a96afdae5dc4f5a2d62 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 22 Aug 2023 14:28:39 -0700 Subject: 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 --- src/corelib/tools/qarraydata.cpp | 64 +++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 18 deletions(-) (limited to 'src/corelib/tools/qarraydata.cpp') 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 -- cgit v1.2.3