summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qarraydata.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/tools/qarraydata.cpp')
-rw-r--r--src/corelib/tools/qarraydata.cpp49
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