Cleanup QArrayDataOps::reallocate() and related

Don't use QArrayData::GrowsForward/Backward anymore and replace
it with a simple 'bool grow'.

Change-Id: Ifddfef3ae860b11dda4c40854c71ef2aeb29df34
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Lars Knoll 2020-10-30 14:10:31 +01:00
parent 32a703e277
commit 419eaa0679
6 changed files with 26 additions and 21 deletions

View File

@ -671,7 +671,7 @@ QByteArray qUncompress(const uchar* data, qsizetype nbytes)
return invalidCompressedData(); return invalidCompressedData();
} else { } else {
// grow the block // grow the block
d->reallocate(d->allocatedCapacity()*2); d->reallocate(d->allocatedCapacity()*2, QArrayData::Grow);
if (Q_UNLIKELY(d.data() == nullptr)) if (Q_UNLIKELY(d.data() == nullptr))
return invalidCompressedData(); return invalidCompressedData();
} }
@ -1719,7 +1719,7 @@ void QByteArray::reallocData(qsizetype alloc, Data::ArrayOptions options)
dd.data()[dd.size] = 0; dd.data()[dd.size] = 0;
d = dd; d = dd;
} else { } else {
d->reallocate(alloc); d->reallocate(alloc, options & (QArrayData::GrowsBackwards|QArrayData::GrowsForward) ? QArrayData::Grow : QArrayData::KeepSize);
} }
} }
@ -1734,7 +1734,7 @@ void QByteArray::reallocGrowData(qsizetype n)
dd.data()[dd.size] = 0; dd.data()[dd.size] = 0;
d = dd; d = dd;
} else { } else {
d->reallocate(d.constAllocatedCapacity() + n); d->reallocate(d.constAllocatedCapacity() + n, QArrayData::Grow);
} }
} }

View File

@ -2516,7 +2516,7 @@ void QString::reallocData(qsizetype alloc, Data::ArrayOptions allocOptions)
dd.data()[dd.size] = 0; dd.data()[dd.size] = 0;
d = dd; d = dd;
} else { } else {
d->reallocate(alloc); d->reallocate(alloc, allocOptions & (QArrayData::GrowsBackwards|QArrayData::GrowsForward) ? QArrayData::Grow : QArrayData::KeepSize);
} }
} }
@ -2531,7 +2531,7 @@ void QString::reallocGrowData(qsizetype n)
dd.data()[dd.size] = 0; dd.data()[dd.size] = 0;
d = dd; d = dd;
} else { } else {
d->reallocate(d.constAllocatedCapacity() + n); d->reallocate(d.constAllocatedCapacity() + n, QArrayData::Grow);
} }
} }

View File

@ -159,12 +159,12 @@ static inline qsizetype reserveExtraBytes(qsizetype allocSize)
return allocSize; return allocSize;
} }
static inline qsizetype calculateBlockSize(qsizetype &capacity, qsizetype objectSize, qsizetype headerSize, uint options) static inline qsizetype calculateBlockSize(qsizetype &capacity, qsizetype objectSize, qsizetype headerSize, QArrayData::AllocationOption option)
{ {
// Calculate the byte size // Calculate the byte size
// allocSize = objectSize * capacity + headerSize, but checked for overflow // allocSize = objectSize * capacity + headerSize, but checked for overflow
// plus padded to grow in size // plus padded to grow in size
if (options & (QArrayData::GrowsForward | QArrayData::GrowsBackwards)) { if (option == QArrayData::Grow) {
auto r = qCalculateGrowingBlockSize(capacity, objectSize, headerSize); auto r = qCalculateGrowingBlockSize(capacity, objectSize, headerSize);
capacity = r.elementCount; capacity = r.elementCount;
return r.size; return r.size;
@ -173,12 +173,12 @@ static inline qsizetype calculateBlockSize(qsizetype &capacity, qsizetype object
} }
} }
static QArrayData *allocateData(qsizetype allocSize, uint options) static QArrayData *allocateData(qsizetype allocSize)
{ {
QArrayData *header = static_cast<QArrayData *>(::malloc(size_t(allocSize))); QArrayData *header = static_cast<QArrayData *>(::malloc(size_t(allocSize)));
if (header) { if (header) {
header->ref_.storeRelaxed(1); header->ref_.storeRelaxed(1);
header->flags = options; header->flags = 0;
header->alloc = 0; header->alloc = 0;
} }
return header; return header;
@ -208,18 +208,19 @@ void *QArrayData::allocate(QArrayData **dptr, qsizetype objectSize, qsizetype al
} }
Q_ASSERT(headerSize > 0); Q_ASSERT(headerSize > 0);
qsizetype allocSize = calculateBlockSize(capacity, objectSize, headerSize, options); qsizetype allocSize = calculateBlockSize(capacity, objectSize, headerSize, (options & (GrowsForward|GrowsBackwards)) ? QArrayData::Grow : QArrayData::KeepSize);
allocSize = reserveExtraBytes(allocSize); allocSize = reserveExtraBytes(allocSize);
if (Q_UNLIKELY(allocSize < 0)) { // handle overflow. cannot allocate reliably if (Q_UNLIKELY(allocSize < 0)) { // handle overflow. cannot allocate reliably
*dptr = nullptr; *dptr = nullptr;
return nullptr; return nullptr;
} }
QArrayData *header = allocateData(allocSize, options); QArrayData *header = allocateData(allocSize);
void *data = nullptr; void *data = nullptr;
if (header) { if (header) {
// find where offset should point to so that data() is aligned to alignment bytes // find where offset should point to so that data() is aligned to alignment bytes
data = QTypedArrayData<void>::dataStart(header, alignment); data = QTypedArrayData<void>::dataStart(header, alignment);
header->flags = options & CapacityReserved;
header->alloc = qsizetype(capacity); header->alloc = qsizetype(capacity);
} }
@ -229,12 +230,12 @@ void *QArrayData::allocate(QArrayData **dptr, qsizetype objectSize, qsizetype al
QPair<QArrayData *, void *> QPair<QArrayData *, void *>
QArrayData::reallocateUnaligned(QArrayData *data, void *dataPointer, QArrayData::reallocateUnaligned(QArrayData *data, void *dataPointer,
qsizetype objectSize, qsizetype capacity, ArrayOptions options) noexcept qsizetype objectSize, qsizetype capacity, AllocationOption option) noexcept
{ {
Q_ASSERT(!data || !data->isShared()); Q_ASSERT(!data || !data->isShared());
qsizetype headerSize = sizeof(QArrayData); qsizetype headerSize = sizeof(QArrayData);
qsizetype allocSize = calculateBlockSize(capacity, objectSize, headerSize, options); qsizetype allocSize = calculateBlockSize(capacity, objectSize, headerSize, option);
qptrdiff offset = dataPointer ? reinterpret_cast<char *>(dataPointer) - reinterpret_cast<char *>(data) : headerSize; qptrdiff offset = dataPointer ? reinterpret_cast<char *>(dataPointer) - reinterpret_cast<char *>(data) : headerSize;
allocSize = reserveExtraBytes(allocSize); allocSize = reserveExtraBytes(allocSize);
@ -243,7 +244,6 @@ QArrayData::reallocateUnaligned(QArrayData *data, void *dataPointer,
QArrayData *header = static_cast<QArrayData *>(::realloc(data, size_t(allocSize))); QArrayData *header = static_cast<QArrayData *>(::realloc(data, size_t(allocSize)));
if (header) { if (header) {
header->flags = options;
header->alloc = uint(capacity); header->alloc = uint(capacity);
dataPointer = reinterpret_cast<char *>(header) + offset; dataPointer = reinterpret_cast<char *>(header) + offset;
} }

View File

@ -51,6 +51,11 @@ template <class T> struct QTypedArrayData;
struct Q_CORE_EXPORT QArrayData struct Q_CORE_EXPORT QArrayData
{ {
enum AllocationOption {
Grow,
KeepSize
};
enum ArrayOption { enum ArrayOption {
/// this option is used by the allocate() function /// this option is used by the allocate() function
DefaultAllocationFlags = 0, DefaultAllocationFlags = 0,
@ -122,7 +127,7 @@ struct Q_CORE_EXPORT QArrayData
static void *allocate(QArrayData **pdata, qsizetype objectSize, qsizetype alignment, static void *allocate(QArrayData **pdata, qsizetype objectSize, qsizetype alignment,
qsizetype capacity, ArrayOptions options = DefaultAllocationFlags) noexcept; qsizetype capacity, ArrayOptions options = DefaultAllocationFlags) noexcept;
[[nodiscard]] static QPair<QArrayData *, void *> reallocateUnaligned(QArrayData *data, void *dataPointer, [[nodiscard]] static QPair<QArrayData *, void *> reallocateUnaligned(QArrayData *data, void *dataPointer,
qsizetype objectSize, qsizetype newCapacity, ArrayOptions newOptions = DefaultAllocationFlags) noexcept; qsizetype objectSize, qsizetype newCapacity, AllocationOption option) noexcept;
static void deallocate(QArrayData *data, qsizetype objectSize, static void deallocate(QArrayData *data, qsizetype objectSize,
qsizetype alignment) noexcept; qsizetype alignment) noexcept;
}; };
@ -221,12 +226,11 @@ struct QTypedArrayData
} }
static QPair<QTypedArrayData *, T *> static QPair<QTypedArrayData *, T *>
reallocateUnaligned(QTypedArrayData *data, T *dataPointer, qsizetype capacity, reallocateUnaligned(QTypedArrayData *data, T *dataPointer, qsizetype capacity, AllocationOption option)
ArrayOptions options = DefaultAllocationFlags)
{ {
static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData)); static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
QPair<QArrayData *, void *> pair = QPair<QArrayData *, void *> pair =
QArrayData::reallocateUnaligned(data, dataPointer, sizeof(T), capacity, options); QArrayData::reallocateUnaligned(data, dataPointer, sizeof(T), capacity, option);
return qMakePair(static_cast<QTypedArrayData *>(pair.first), static_cast<T *>(pair.second)); return qMakePair(static_cast<QTypedArrayData *>(pair.first), static_cast<T *>(pair.second));
} }

View File

@ -457,9 +457,9 @@ public:
} }
} }
void reallocate(qsizetype alloc) void reallocate(qsizetype alloc, QArrayData::AllocationOption option)
{ {
auto pair = Data::reallocateUnaligned(this->d, this->ptr, alloc, QArrayData::GrowsBackwards); auto pair = Data::reallocateUnaligned(this->d, this->ptr, alloc, option);
this->d = pair.first; this->d = pair.first;
this->ptr = pair.second; this->ptr = pair.second;
} }

View File

@ -547,7 +547,8 @@ void tst_QArrayData::reallocate()
// now try to reallocate // now try to reallocate
int newCapacity = 40; int newCapacity = 40;
auto pair = QArrayData::reallocateUnaligned(data, dataPointer, objectSize, newCapacity, auto pair = QArrayData::reallocateUnaligned(data, dataPointer, objectSize, newCapacity,
QArrayData::ArrayOptions(allocateOptions)); (allocateOptions & (QArrayData::GrowsBackwards|QArrayData::GrowsForward)) ?
QArrayData::Grow : QArrayData::KeepSize);
data = pair.first; data = pair.first;
dataPointer = pair.second; dataPointer = pair.second;
QVERIFY(data); QVERIFY(data);