diff options
author | Lars Knoll <lars.knoll@qt.io> | 2019-12-03 12:21:46 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2020-07-06 21:30:33 +0200 |
commit | fbce2e58e6f29dc8dde5618597d53e1b1007b503 (patch) | |
tree | 836e966a69b532e140bc3d83ad846999adb75e47 | |
parent | c01804bd1edf00006a76edb1bf33ba9f72a69296 (diff) |
Get rid of QArrayData::sharedNull()
Remove the last places where those got used and avoid
allocations when we resize to 0.
Change-Id: Ib553f4e7ce7cc24c31da15a55a86d18bdf1cc5c3
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r-- | src/corelib/text/qbytearray.cpp | 4 | ||||
-rw-r--r-- | src/corelib/tools/qarraydata.cpp | 25 | ||||
-rw-r--r-- | src/corelib/tools/qarraydata.h | 18 | ||||
-rw-r--r-- | src/corelib/tools/qarraydatapointer.h | 3 | ||||
-rw-r--r-- | tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp | 4 | ||||
-rw-r--r-- | tests/auto/corelib/text/qstring/tst_qstring.cpp | 2 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qarraydata/simplevector.h | 2 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp | 87 |
8 files changed, 22 insertions, 123 deletions
diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp index 350fa3be25..e0f720bc86 100644 --- a/src/corelib/text/qbytearray.cpp +++ b/src/corelib/text/qbytearray.cpp @@ -1732,7 +1732,7 @@ QByteArray QByteArray::nulTerminated() const QByteArray &QByteArray::prepend(const QByteArray &ba) { - if (size() == 0 && d->isStatic() && ba.d.isMutable()) { + if (size() == 0 && ba.d.isMutable()) { *this = ba; } else if (ba.size() != 0) { QByteArray tmp = *this; @@ -1825,7 +1825,7 @@ QByteArray &QByteArray::prepend(char ch) QByteArray &QByteArray::append(const QByteArray &ba) { - if (size() == 0 && d->isStatic() && ba.d.isMutable()) { + if (size() == 0 && ba.d.isMutable()) { *this = ba; } else if (ba.size() != 0) { if (d->needsDetach() || size() + ba.size() > capacity()) diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp index 42599bbf2a..1a369a879a 100644 --- a/src/corelib/tools/qarraydata.cpp +++ b/src/corelib/tools/qarraydata.cpp @@ -147,25 +147,7 @@ qCalculateGrowingBlockSize(size_t elementCount, size_t elementSize, size_t heade return result; } -// End of qtools_p.h implementation - -QT_WARNING_PUSH -QT_WARNING_DISABLE_GCC("-Wmissing-field-initializers") - -const QArrayData QArrayData::shared_null[2] = { - { Q_BASIC_ATOMIC_INITIALIZER(-1), 0, 0 }, // shared null - /* zero initialized terminator */}; - -static const QArrayData emptyNotNullShared[2] = { - { Q_BASIC_ATOMIC_INITIALIZER(-1), 0, 0 }, // shared empty - /* zero initialized terminator */}; - -QT_WARNING_POP - -static const QArrayData &qt_array_empty = emptyNotNullShared[0]; - -static inline size_t calculateBlockSize(size_t &capacity, size_t objectSize, size_t headerSize, - uint options) +static inline size_t calculateBlockSize(size_t &capacity, size_t objectSize, size_t headerSize, uint options) { // Calculate the byte size // allocSize = objectSize * capacity + headerSize, but checked for overflow @@ -199,9 +181,8 @@ void *QArrayData::allocate(QArrayData **dptr, size_t objectSize, size_t alignmen && !(alignment & (alignment - 1))); if (capacity == 0) { - // optimization for empty headers - *dptr = const_cast<QArrayData *>(&qt_array_empty); - return sharedNullData(); + *dptr = nullptr; + return nullptr; } size_t headerSize = sizeof(QArrayData); diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h index b3b559e222..fe8827afb8 100644 --- a/src/corelib/tools/qarraydata.h +++ b/src/corelib/tools/qarraydata.h @@ -77,24 +77,16 @@ struct Q_CORE_EXPORT QArrayData /// Returns true if sharing took place bool ref() { - if (!isStatic()) - ref_.ref(); + ref_.ref(); return true; } /// Returns false if deallocation is necessary bool deref() { - if (isStatic()) - return true; return ref_.deref(); } - bool isStatic() const - { - return ref_.loadRelaxed() == -1; - } - bool isShared() const { return ref_.loadRelaxed() != 1; @@ -133,14 +125,6 @@ struct Q_CORE_EXPORT QArrayData size_t objectSize, size_t newCapacity, ArrayOptions newOptions = DefaultAllocationFlags) Q_DECL_NOTHROW; static void deallocate(QArrayData *data, size_t objectSize, size_t alignment) noexcept; - - static const QArrayData shared_null[2]; - static QArrayData *sharedNull() noexcept { return const_cast<QArrayData*>(shared_null); } - static void *sharedNullData() - { - QArrayData *const null = const_cast<QArrayData *>(&shared_null[1]); - return null; - } }; Q_DECLARE_OPERATORS_FOR_FLAGS(QArrayData::ArrayOptions) diff --git a/src/corelib/tools/qarraydatapointer.h b/src/corelib/tools/qarraydatapointer.h index 8e30373211..1f9a9d840c 100644 --- a/src/corelib/tools/qarraydatapointer.h +++ b/src/corelib/tools/qarraydatapointer.h @@ -78,7 +78,6 @@ public: explicit QArrayDataPointer(QPair<QTypedArrayData<T> *, T *> adata, size_t n = 0) : d(adata.first), ptr(adata.second), size(int(n)) { - Q_CHECK_PTR(d); } static QArrayDataPointer fromRawData(const T *rawData, size_t length) @@ -183,7 +182,6 @@ public: void ref() noexcept { if (d) d->ref(); } bool deref() noexcept { return !d || d->deref(); } bool isMutable() const noexcept { return d; } - bool isStatic() const noexcept { return !d; } bool isShared() const noexcept { return !d || d->isShared(); } bool isSharedWith(const QArrayDataPointer &other) const noexcept { return d && d == other.d; } bool needsDetach() const noexcept { return !d || d->needsDetach(); } @@ -199,7 +197,6 @@ private: Q_REQUIRED_RESULT QPair<Data *, T *> clone(QArrayData::ArrayOptions options) const { QPair<Data *, T *> pair = Data::allocate(detachCapacity(size), options); - Q_CHECK_PTR(pair.first); QArrayDataPointer copy(pair.first, pair.second, 0); if (size) copy->copyAppend(begin(), end()); diff --git a/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp b/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp index e566cc21a2..80ad8e0515 100644 --- a/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp +++ b/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp @@ -167,8 +167,8 @@ QByteArray verifyZeroTermination(const QByteArray &ba) QByteArray::DataPointer baDataPtr = const_cast<QByteArray &>(ba).data_ptr(); - // Skip if isStatic() as those offer no guarantees - if (baDataPtr->isStatic()) + // Skip if !isMutable() as those offer no guarantees + if (!baDataPtr->isMutable()) return ba; int baSize = ba.size(); diff --git a/tests/auto/corelib/text/qstring/tst_qstring.cpp b/tests/auto/corelib/text/qstring/tst_qstring.cpp index 4d2e91a694..850def64ab 100644 --- a/tests/auto/corelib/text/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp @@ -618,7 +618,7 @@ QString verifyZeroTermination(const QString &str) QString::DataPointer strDataPtr = const_cast<QString &>(str).data_ptr(); // Skip if isStatic() or fromRawData(), as those offer no guarantees - if (strDataPtr->isStatic() || !strDataPtr->isMutable()) + if (!strDataPtr->isMutable()) return str; int strSize = str.size(); diff --git a/tests/auto/corelib/tools/qarraydata/simplevector.h b/tests/auto/corelib/tools/qarraydata/simplevector.h index 8109c463a3..6be785a628 100644 --- a/tests/auto/corelib/tools/qarraydata/simplevector.h +++ b/tests/auto/corelib/tools/qarraydata/simplevector.h @@ -85,7 +85,7 @@ public: bool isNull() const { return d.isNull(); } bool isEmpty() const { return this->empty(); } - bool isStatic() const { return d->isStatic(); } + bool isStatic() const { return !d.isMutable(); } bool isShared() const { return d->isShared(); } bool isSharedWith(const SimpleVector &other) const { return d == other.d; } diff --git a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp index 5c7484a49a..9ebcda4cef 100644 --- a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp +++ b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp @@ -33,29 +33,12 @@ #include "simplevector.h" -struct SharedNullVerifier -{ - SharedNullVerifier() - { - Q_ASSERT(QArrayData::shared_null[0].isStatic()); - Q_ASSERT(QArrayData::shared_null[0].isShared()); - } -}; - -// This is meant to verify/ensure that shared_null is not being dynamically -// initialized and stays away from the order-of-static-initialization fiasco. -// -// Of course, if this was to fail, qmake and the build should have crashed and -// burned before we ever got to this point :-) -SharedNullVerifier globalInit; - class tst_QArrayData : public QObject { Q_OBJECT private slots: void referenceCounting(); - void sharedNullEmpty(); void simpleVector(); void simpleVectorReserve_data(); void simpleVectorReserve(); @@ -87,8 +70,6 @@ void tst_QArrayData::referenceCounting() QCOMPARE(array.ref_.loadRelaxed(), 1); - QVERIFY(!array.isStatic()); - QVERIFY(array.ref()); QCOMPARE(array.ref_.loadRelaxed(), 2); @@ -108,37 +89,6 @@ void tst_QArrayData::referenceCounting() } } -void tst_QArrayData::sharedNullEmpty() -{ - QArrayData *null = const_cast<QArrayData *>(QArrayData::shared_null); - QArrayData *empty; - QArrayData::allocate(&empty, 1, alignof(QArrayData), 0); - - QVERIFY(null->isStatic()); - QVERIFY(null->isShared()); - - QVERIFY(empty->isStatic()); - QVERIFY(empty->isShared()); - - QCOMPARE(null->ref_.loadRelaxed(), -1); - QCOMPARE(empty->ref_.loadRelaxed(), -1); - - QCOMPARE(null->ref_.loadRelaxed(), -1); - QCOMPARE(empty->ref_.loadRelaxed(), -1); - - QVERIFY(null->deref()); - QVERIFY(empty->deref()); - - QCOMPARE(null->ref_.loadRelaxed(), -1); - QCOMPARE(empty->ref_.loadRelaxed(), -1); - - QVERIFY(null != empty); - - QCOMPARE(null->allocatedCapacity(), size_t(0)); - - QCOMPARE(empty->allocatedCapacity(), size_t(0)); -} - void tst_QArrayData::simpleVector() { int data[] = { 0, 1, 2, 3, 4, 5, 6 }; @@ -479,7 +429,6 @@ void tst_QArrayData::allocate_data() QTest::addColumn<size_t>("alignment"); QTest::addColumn<QArrayData::ArrayOptions>("allocateOptions"); QTest::addColumn<bool>("isCapacityReserved"); - QTest::addColumn<const QArrayData *>("commonEmpty"); struct { char const *typeName; @@ -491,19 +440,14 @@ void tst_QArrayData::allocate_data() { "void *", sizeof(void *), alignof(void *) } }; - QArrayData *shared_empty; - (void)QArrayData::allocate(&shared_empty, 1, alignof(QArrayData), 0); - QVERIFY(shared_empty); - struct { char const *description; QArrayData::ArrayOptions allocateOptions; bool isCapacityReserved; - const QArrayData *commonEmpty; } options[] = { - { "Default", QArrayData::DefaultAllocationFlags, false, shared_empty }, - { "Reserved", QArrayData::CapacityReserved, true, shared_empty }, - { "Grow", QArrayData::GrowsForward, false, shared_empty } + { "Default", QArrayData::DefaultAllocationFlags, false }, + { "Reserved", QArrayData::CapacityReserved, true }, + { "Grow", QArrayData::GrowsForward, false } }; for (size_t i = 0; i < sizeof(types)/sizeof(types[0]); ++i) @@ -513,8 +457,7 @@ void tst_QArrayData::allocate_data() + QLatin1String(": ") + QLatin1String(options[j].description))) << types[i].objectSize << types[i].alignment - << options[j].allocateOptions << options[j].isCapacityReserved - << options[j].commonEmpty; + << options[j].allocateOptions << options[j].isCapacityReserved; } void tst_QArrayData::allocate() @@ -523,21 +466,15 @@ void tst_QArrayData::allocate() QFETCH(size_t, alignment); QFETCH(QArrayData::ArrayOptions, allocateOptions); QFETCH(bool, isCapacityReserved); - QFETCH(const QArrayData *, commonEmpty); // Minimum alignment that can be requested is that of QArrayData. // Typically, this alignment is sizeof(void *) and ensured by malloc. size_t minAlignment = qMax(alignment, alignof(QArrayData)); - // Shared Empty - QArrayData *empty; - QCOMPARE((QArrayData::allocate(&empty, objectSize, minAlignment, 0, - QArrayData::ArrayOptions(allocateOptions)), empty), commonEmpty); - Deallocator keeper(objectSize, minAlignment); keeper.headers.reserve(1024); - for (int capacity = 1; capacity <= 1024; capacity <<= 1) { + for (qsizetype capacity = 1; capacity <= 1024; capacity <<= 1) { QArrayData *data; void *dataPointer = QArrayData::allocate(&data, objectSize, minAlignment, capacity, QArrayData::ArrayOptions(allocateOptions)); @@ -545,9 +482,9 @@ void tst_QArrayData::allocate() keeper.headers.append(data); if (allocateOptions & QArrayData::GrowsForward) - QVERIFY(data->allocatedCapacity() > uint(capacity)); + QVERIFY(data->allocatedCapacity() > capacity); else - QCOMPARE(data->allocatedCapacity(), size_t(capacity)); + QCOMPARE(data->allocatedCapacity(), capacity); QCOMPARE(bool(data->flags & QArrayData::CapacityReserved), isCapacityReserved); // Check that the allocated array can be used. Best tested with a @@ -587,9 +524,9 @@ void tst_QArrayData::reallocate() keeper.headers.append(data); if (allocateOptions & QArrayData::GrowsForward) - QVERIFY(data->allocatedCapacity() > size_t(newCapacity)); + QVERIFY(data->allocatedCapacity() > newCapacity); else - QCOMPARE(data->allocatedCapacity(), size_t(newCapacity)); + QCOMPARE(data->allocatedCapacity(), newCapacity); QCOMPARE(!(data->flags & QArrayData::CapacityReserved), !isCapacityReserved); for (int i = 0; i < capacity; ++i) @@ -658,7 +595,7 @@ void tst_QArrayData::typedData() keeper.headers.append(array); QVERIFY(array); - QCOMPARE(array->allocatedCapacity(), size_t(10)); + QCOMPARE(array->allocatedCapacity(), qsizetype(10)); // Check that the allocated array can be used. Best tested with a // memory checker, such as valgrind, running. @@ -678,7 +615,7 @@ void tst_QArrayData::typedData() keeper.headers.append(array); QVERIFY(array); - QCOMPARE(array->allocatedCapacity(), size_t(10)); + QCOMPARE(array->allocatedCapacity(), qsizetype(10)); // Check that the allocated array can be used. Best tested with a // memory checker, such as valgrind, running. @@ -698,7 +635,7 @@ void tst_QArrayData::typedData() keeper.headers.append(array); QVERIFY(array); - QCOMPARE(array->allocatedCapacity(), size_t(10)); + QCOMPARE(array->allocatedCapacity(), qsizetype(10)); // Check that the allocated array can be used. Best tested with a // memory checker, such as valgrind, running. |