diff options
Diffstat (limited to 'src/corelib/tools/qarraydata.cpp')
| -rw-r--r-- | src/corelib/tools/qarraydata.cpp | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp index 5452fddaa89..37d6dea35f9 100644 --- a/src/corelib/tools/qarraydata.cpp +++ b/src/corelib/tools/qarraydata.cpp @@ -2,6 +2,7 @@ // Copyright (C) 2016 Intel Corporation. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +#include <QtCore/qalloc.h> #include <QtCore/qarraydata.h> #include <QtCore/private/qnumeric_p.h> #include <QtCore/private/qtools_p.h> @@ -101,12 +102,34 @@ qCalculateGrowingBlockSize(qsizetype elementCount, qsizetype elementSize, qsizet } else { bytes = qsizetype(morebytes); } + size_t fittedBytes = QtPrivate::expectedAllocSize(bytes, alignof(std::max_align_t)); + if (fittedBytes != 0) + bytes = fittedBytes; result.elementCount = (bytes - headerSize) / elementSize; result.size = result.elementCount * elementSize + headerSize; return result; } +using QtPrivate::AlignedQArrayData; + +static qsizetype calculateHeaderSize(qsizetype alignment) +{ + qsizetype headerSize = sizeof(AlignedQArrayData); + const qsizetype headerAlignment = alignof(AlignedQArrayData); + + if (alignment > headerAlignment) { + // Allocate extra (alignment - Q_ALIGNOF(AlignedQArrayData)) 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! + // Effectively, we allocate one QTypedArrayData<T>::AlignmentDummy. + headerSize += alignment - headerAlignment; + } + Q_ASSERT(headerSize > 0); + + return headerSize; +} + /* Calculate the byte size for a block of \a capacity objects of size \a objectSize, with a header of size \a headerSize. If the \a option is @@ -140,7 +163,6 @@ struct AllocationResult { QArrayData *header; }; } -using QtPrivate::AlignedQArrayData; static inline AllocationResult allocateHelper(qsizetype objectSize, qsizetype alignment, qsizetype capacity, @@ -149,16 +171,7 @@ allocateHelper(qsizetype objectSize, qsizetype alignment, qsizetype capacity, if (capacity == 0) return {}; - qsizetype headerSize = sizeof(AlignedQArrayData); - const qsizetype headerAlignment = alignof(AlignedQArrayData); - - if (alignment > headerAlignment) { - // Allocate extra (alignment - Q_ALIGNOF(AlignedQArrayData)) 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! - // Effectively, we allocate one QTypedArrayData<T>::AlignmentDummy. - headerSize += alignment - headerAlignment; - } + const qsizetype headerSize = calculateHeaderSize(alignment); Q_ASSERT(headerSize > 0); auto blockSize = calculateBlockSize(capacity, objectSize, headerSize, option); @@ -248,10 +261,18 @@ void QArrayData::deallocate(QArrayData *data, qsizetype objectSize, // Alignment is a power of two Q_ASSERT(alignment >= qsizetype(alignof(QArrayData)) && !(alignment & (alignment - 1))); - Q_UNUSED(objectSize); - Q_UNUSED(alignment); - ::free(data); + const qsizetype capacity = data->alloc; + const qsizetype headerSize = calculateHeaderSize(alignment); + Q_ASSERT(headerSize > 0); + const auto blockSize = calculateBlockSize(capacity, objectSize, + headerSize, QArrayData::KeepSize); + const qsizetype allocSize = blockSize.size; + + if (Q_LIKELY(allocSize > 0)) + QtPrivate::sizedFree(data, size_t(allocSize)); + else // something went wrong, fallback to slow free() + free(data); } QT_END_NAMESPACE |
