Refine {QString, QBA}::reallocData() logic
Fixed misleading naming of "slowReallocatePath". It's no longer "slow", it's downright dangerous now to reallocate under certain conditions While at it, added extra assert to QArrayData::reallocateUnaligned() and cleaned up that function a bit Change-Id: I05921fb5058eb563997e66107566c87fb4ea5599 Reviewed-by: Lars Knoll <lars.knoll@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
42f8afc2dc
commit
504972f838
@ -1708,12 +1708,11 @@ void QByteArray::reallocData(qsizetype alloc, QArrayData::AllocationOption optio
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// there's a case of slow reallocate path where we need to memmove the data
|
// don't use reallocate path when reducing capacity and there's free space
|
||||||
// before a call to ::realloc(), meaning that there's an extra "heavy"
|
// at the beginning: might shift data pointer outside of allocated space
|
||||||
// operation. just prefer ::malloc() branch in this case
|
const bool cannotUseReallocate = d.freeSpaceAtBegin() > 0 && alloc < d.constAllocatedCapacity();
|
||||||
const bool slowReallocatePath = d.freeSpaceAtBegin() > 0;
|
|
||||||
|
|
||||||
if (d->needsDetach() || slowReallocatePath) {
|
if (d->needsDetach() || cannotUseReallocate) {
|
||||||
DataPointer dd(Data::allocate(alloc, option), qMin(alloc, d.size));
|
DataPointer dd(Data::allocate(alloc, option), qMin(alloc, d.size));
|
||||||
if (dd.size > 0)
|
if (dd.size > 0)
|
||||||
::memcpy(dd.data(), d.data(), dd.size);
|
::memcpy(dd.data(), d.data(), dd.size);
|
||||||
|
@ -2504,12 +2504,11 @@ void QString::reallocData(qsizetype alloc, QArrayData::AllocationOption option)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// there's a case of slow reallocate path where we need to memmove the data
|
// don't use reallocate path when reducing capacity and there's free space
|
||||||
// before a call to ::realloc(), meaning that there's an extra "heavy"
|
// at the beginning: might shift data pointer outside of allocated space
|
||||||
// operation. just prefer ::malloc() branch in this case
|
const bool cannotUseReallocate = d.freeSpaceAtBegin() > 0 && alloc < d.constAllocatedCapacity();
|
||||||
const bool slowReallocatePath = d.freeSpaceAtBegin() > 0;
|
|
||||||
|
|
||||||
if (d->needsDetach() || slowReallocatePath) {
|
if (d->needsDetach() || cannotUseReallocate) {
|
||||||
DataPointer dd(Data::allocate(alloc, option), qMin(alloc, d.size));
|
DataPointer dd(Data::allocate(alloc, option), qMin(alloc, d.size));
|
||||||
if (dd.size > 0)
|
if (dd.size > 0)
|
||||||
::memcpy(dd.data(), d.data(), dd.size * sizeof(QChar));
|
::memcpy(dd.data(), d.data(), dd.size * sizeof(QChar));
|
||||||
|
@ -233,10 +233,13 @@ QArrayData::reallocateUnaligned(QArrayData *data, void *dataPointer,
|
|||||||
{
|
{
|
||||||
Q_ASSERT(!data || !data->isShared());
|
Q_ASSERT(!data || !data->isShared());
|
||||||
|
|
||||||
qsizetype headerSize = sizeof(QArrayData);
|
const qsizetype headerSize = sizeof(QArrayData);
|
||||||
qsizetype allocSize = calculateBlockSize(capacity, objectSize, headerSize, option);
|
qsizetype allocSize = calculateBlockSize(capacity, objectSize, headerSize, option);
|
||||||
qptrdiff offset = dataPointer ? reinterpret_cast<char *>(dataPointer) - reinterpret_cast<char *>(data) : headerSize;
|
const qptrdiff offset = dataPointer
|
||||||
|
? reinterpret_cast<char *>(dataPointer) - reinterpret_cast<char *>(data)
|
||||||
|
: headerSize;
|
||||||
Q_ASSERT(offset > 0);
|
Q_ASSERT(offset > 0);
|
||||||
|
Q_ASSERT(offset <= allocSize); // == when all free space is at the beginning
|
||||||
|
|
||||||
allocSize = reserveExtraBytes(allocSize);
|
allocSize = reserveExtraBytes(allocSize);
|
||||||
if (Q_UNLIKELY(allocSize < 0)) // handle overflow. cannot reallocate reliably
|
if (Q_UNLIKELY(allocSize < 0)) // handle overflow. cannot reallocate reliably
|
||||||
@ -244,7 +247,7 @@ 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->alloc = uint(capacity);
|
header->alloc = capacity;
|
||||||
dataPointer = reinterpret_cast<char *>(header) + offset;
|
dataPointer = reinterpret_cast<char *>(header) + offset;
|
||||||
} else {
|
} else {
|
||||||
dataPointer = nullptr;
|
dataPointer = nullptr;
|
||||||
|
Loading…
Reference in New Issue
Block a user