diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2024-02-09 21:44:02 +0100 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2024-03-05 14:06:29 +0100 |
commit | bb3999a22d3282911005865135c9d6d49ae65728 (patch) | |
tree | 62c9ecc64940b380c2ddd84b02a4a5475281b1d6 | |
parent | d6d224892e6672dc3ed8f027b54277fe8a7971f9 (diff) |
QV4 garbage collection: Allocate white during gc run
Now that we properly employ the WriteBarrier, we no longer need to use
black allocations. This reduces the amount of floating garbage, and
avoids potential bugs with heap classes like QV4::MemberData where we
rely on it being marked so that its constituents don't have to be
protected during initialization – which would fail when we it is already
black, as it wouldn't be pushed on the MarkStack afterwards.
Fixes: QTBUG-121910
Change-Id: Ie5e0f9461fa5c0e4a293da3d3c978da73743e417
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
-rw-r--r-- | src/qml/memory/qv4mm.cpp | 24 | ||||
-rw-r--r-- | src/qml/memory/qv4mm_p.h | 6 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 7 |
3 files changed, 2 insertions, 35 deletions
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 53c702305c..adea75b198 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -882,13 +882,6 @@ Heap::Base *MemoryManager::allocString(std::size_t unmanagedSize) HeapItem *m = allocate(&blockAllocator, stringSize); memset(m, 0, stringSize); - if (m_markStack) { - // If the gc is running right now, it will not have a chance to mark the newly created item - // and may therefore sweep it right away. - // Protect the new object from the current GC run to avoid this. - m->as<Heap::Base>()->setMarkBit(); - } - return *m; } @@ -904,13 +897,6 @@ Heap::Base *MemoryManager::allocData(std::size_t size) HeapItem *m = allocate(&blockAllocator, size); memset(m, 0, size); - if (m_markStack) { - // If the gc is running right now, it will not have a chance to mark the newly created item - // and may therefore sweep it right away. - // Protect the new object from the current GC run to avoid this. - m->as<Heap::Base>()->setMarkBit(); - } - return *m; } @@ -942,16 +928,6 @@ Heap::Object *MemoryManager::allocObjectWithMemberData(const QV4::VTable *vtable Chunk::setBit(c->objectBitmap, index); Chunk::clearBit(c->extendsBitmap, index); } - /* If the gc is running, then o will be black,as allocData allocates black during gc - However, m points to "clear" memory. We must mark it, too, otherwise it might be - collected. Note that this must happen after (un)setting the object and extends bit - otherwise we hit an assertion. - Actually, the write barrier of o->memberData would save us (at leas as long as we - keep using a Dijkstra style barrier; however, setting the mark bit directly avoids - some unnecessary work. - */ - if (m_markStack) // gc running - m->setMarkBit(); o->memberData.set(engine, m); m->internalClass.set(engine, engine->internalClasses(EngineBase::Class_MemberData)); Q_ASSERT(o->memberData->internalClass); diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index 74aa0b639f..a16ea580b1 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -320,12 +320,6 @@ public: typename ManagedType::Data *allocIC() { Heap::Base *b = *allocate(&icAllocator, align(sizeof(typename ManagedType::Data))); - if (m_markStack) { - // If the gc is running right now, it will not have a chance to mark the newly created item - // and may therefore sweep it right away. - // Protect the new object from the current GC run to avoid this. - b->setMarkBit(); - } return static_cast<typename ManagedType::Data *>(b); } diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index c1e6c4c96f..bd60093a7b 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -8122,12 +8122,9 @@ void tst_qqmlecmascript::onDestructionViaGC() v4->memoryManager->allocate<QV4::WeakReferenceSentinel>(weakRef.data(), &sentinelResult); } gc(engine); - + QVERIFY2(weakRef->isNullOrUndefined(), "The weak value was not cleared"); QVERIFY2(mutatorResult, "We failed to re-assign the weak reference a new value during GC"); - QVERIFY2(!sentinelResult, "The weak value was cleared on first GC run"); - QVERIFY2(!weakRef->isNullOrUndefined(), "The weak value was cleared on first GC run"); - gc(engine); - QVERIFY2(weakRef->isNullOrUndefined(), "The weak value was not cleared on second gc run"); + QVERIFY2(sentinelResult, "The weak reference was not cleared properly"); } struct EventProcessor : public QObject |