diff options
Diffstat (limited to 'src/corelib/tools/qarraydata.cpp')
-rw-r--r-- | src/corelib/tools/qarraydata.cpp | 111 |
1 files changed, 61 insertions, 50 deletions
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp index 3879b48cbb..497eae1f7f 100644 --- a/src/corelib/tools/qarraydata.cpp +++ b/src/corelib/tools/qarraydata.cpp @@ -153,18 +153,16 @@ QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wmissing-field-initializers") const QArrayData QArrayData::shared_null[2] = { - { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, sizeof(QArrayData) }, // shared null + { Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, 0 }, // shared null /* zero initialized terminator */}; -static const QArrayData qt_array[3] = { - { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, sizeof(QArrayData) }, // shared empty - { { Q_BASIC_ATOMIC_INITIALIZER(0) }, 0, 0, 0, sizeof(QArrayData) }, // unsharable empty +static const QArrayData emptyNotNullShared[2] = { + { Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, 0 }, // shared empty /* zero initialized terminator */}; QT_WARNING_POP -static const QArrayData &qt_array_empty = qt_array[0]; -static const QArrayData &qt_array_unsharable_empty = qt_array[1]; +static const QArrayData &qt_array_empty = emptyNotNullShared[0]; static inline size_t calculateBlockSize(size_t &capacity, size_t objectSize, size_t headerSize, uint options) @@ -172,7 +170,7 @@ static inline size_t calculateBlockSize(size_t &capacity, size_t objectSize, siz // Calculate the byte size // allocSize = objectSize * capacity + headerSize, but checked for overflow // plus padded to grow in size - if (options & QArrayData::Grow) { + if (options & QArrayData::GrowsForward) { auto r = qCalculateGrowingBlockSize(capacity, objectSize, headerSize); capacity = r.elementCount; return r.size; @@ -181,91 +179,104 @@ static inline size_t calculateBlockSize(size_t &capacity, size_t objectSize, siz } } +static QArrayData *allocateData(size_t allocSize, uint options) +{ + QArrayData *header = static_cast<QArrayData *>(::malloc(allocSize)); + if (header) { + header->ref_.storeRelaxed(1); + header->flags = options; + header->alloc = 0; + } + return header; +} + static QArrayData *reallocateData(QArrayData *header, size_t allocSize, uint options) { header = static_cast<QArrayData *>(::realloc(header, allocSize)); if (header) - header->capacityReserved = bool(options & QArrayData::CapacityReserved); + header->flags = options; return header; } -QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment, - size_t capacity, AllocationOptions options) noexcept +void *QArrayData::allocate(QArrayData **dptr, size_t objectSize, size_t alignment, + size_t capacity, ArrayOptions options) noexcept { + Q_ASSERT(dptr); // Alignment is a power of two - Q_ASSERT(alignment >= Q_ALIGNOF(QArrayData) + Q_ASSERT(alignment >= alignof(QArrayData) && !(alignment & (alignment - 1))); - // Don't allocate empty headers - if (!(options & RawData) && !capacity) { -#if !defined(QT_NO_UNSHARABLE_CONTAINERS) - if (options & Unsharable) - return const_cast<QArrayData *>(&qt_array_unsharable_empty); -#endif - return const_cast<QArrayData *>(&qt_array_empty); + if (capacity == 0) { + // optimization for empty headers + *dptr = const_cast<QArrayData *>(&qt_array_empty); + return sharedNullData(); } size_t headerSize = sizeof(QArrayData); - // Allocate extra (alignment - Q_ALIGNOF(QArrayData)) padding bytes so we - // can properly align the data array. This assumes malloc is able to - // provide appropriate alignment for the header -- as it should! - // Padding is skipped when allocating a header for RawData. - if (!(options & RawData)) - headerSize += (alignment - Q_ALIGNOF(QArrayData)); + if (alignment > alignof(QArrayData)) { + // Allocate extra (alignment - Q_ALIGNOF(QArrayData)) padding bytes so we + // can properly align the data array. This assumes malloc is able to + // provide appropriate alignment for the header -- as it should! + headerSize += alignment - alignof(QArrayData); + } if (headerSize > size_t(MaxAllocSize)) return nullptr; size_t allocSize = calculateBlockSize(capacity, objectSize, headerSize, options); - QArrayData *header = static_cast<QArrayData *>(::malloc(allocSize)); + options |= AllocatedDataType | MutableData; + options &= ~ImmutableHeader; + QArrayData *header = allocateData(allocSize, options); + quintptr data = 0; if (header) { - quintptr data = (quintptr(header) + sizeof(QArrayData) + alignment - 1) + // find where offset should point to so that data() is aligned to alignment bytes + data = (quintptr(header) + sizeof(QArrayData) + alignment - 1) & ~(alignment - 1); - -#if !defined(QT_NO_UNSHARABLE_CONTAINERS) - header->ref.atomic.storeRelaxed(bool(!(options & Unsharable))); -#else - header->ref.atomic.storeRelaxed(1); -#endif - header->size = 0; - header->alloc = capacity; - header->capacityReserved = bool(options & CapacityReserved); - header->offset = data - quintptr(header); + header->alloc = uint(capacity); } + *dptr = header; + return reinterpret_cast<void *>(data); +} + +QArrayData *QArrayData::prepareRawData(ArrayOptions options) Q_DECL_NOTHROW +{ + QArrayData *header = allocateData(sizeof(QArrayData), (options & ~DataTypeBits) | RawDataType); + if (header) + header->alloc = 0; return header; } -QArrayData *QArrayData::reallocateUnaligned(QArrayData *data, size_t objectSize, size_t capacity, - AllocationOptions options) noexcept +QPair<QArrayData *, void *> +QArrayData::reallocateUnaligned(QArrayData *data, void *dataPointer, + size_t objectSize, size_t capacity, ArrayOptions options) noexcept { Q_ASSERT(data); Q_ASSERT(data->isMutable()); - Q_ASSERT(!data->ref.isShared()); + Q_ASSERT(!data->isShared()); size_t headerSize = sizeof(QArrayData); size_t allocSize = calculateBlockSize(capacity, objectSize, headerSize, options); - QArrayData *header = static_cast<QArrayData *>(reallocateData(data, allocSize, options)); - if (header) - header->alloc = capacity; - return header; + qptrdiff offset = reinterpret_cast<char *>(dataPointer) - reinterpret_cast<char *>(data); + options |= AllocatedDataType | MutableData; + QArrayData *header = reallocateData(data, allocSize, options); + if (header) { + header->alloc = uint(capacity); + dataPointer = reinterpret_cast<char *>(header) + offset; + } + return qMakePair(static_cast<QArrayData *>(header), dataPointer); } void QArrayData::deallocate(QArrayData *data, size_t objectSize, size_t alignment) noexcept { // Alignment is a power of two - Q_ASSERT(alignment >= Q_ALIGNOF(QArrayData) + Q_ASSERT(alignment >= alignof(QArrayData) && !(alignment & (alignment - 1))); Q_UNUSED(objectSize) Q_UNUSED(alignment) -#if !defined(QT_NO_UNSHARABLE_CONTAINERS) - if (data == &qt_array_unsharable_empty) - return; -#endif - - Q_ASSERT_X(data == nullptr || !data->ref.isStatic(), "QArrayData::deallocate", + Q_ASSERT_X(data == nullptr || !data->isStatic(), "QArrayData::deallocate", "Static data cannot be deleted"); ::free(data); } |