aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2019-03-19 13:39:10 +0100
committerUlf Hermann <ulf.hermann@qt.io>2019-03-20 11:06:40 +0000
commit69d76d59cec0dcff4c52eef24e779fbef14beeca (patch)
tree506a08df8d801b6ab94ae4b6bf47629a44a2e402
parent5cfccf30898aed5ca96c0f8779b0f8a1117118b7 (diff)
V4: Don't mark InternalClass::parent when garbage collecting
The parent pointer is only kept so that we can update the parent's transitions when removing a child. There is no need to keep the parents alive for the children. Fixes: QTBUG-58559 Change-Id: Ia28183966bde6d478ca030fe11195489925dfc13 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp12
-rw-r--r--tests/auto/qml/qv4mm/tst_qv4mm.cpp26
2 files changed, 33 insertions, 5 deletions
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index ddb8542e07..9906e2b1a0 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -257,11 +257,15 @@ void InternalClass::init(Heap::InternalClass *other)
void InternalClass::destroy()
{
-#ifndef QT_NO_DEBUG
for (const auto &t : transitions) {
- Q_ASSERT(!t.lookup || !t.lookup->isMarked());
- }
+ if (t.lookup) {
+#ifndef QT_NO_DEBUG
+ Q_ASSERT(t.lookup->parent == this);
#endif
+ t.lookup->parent = nullptr;
+ }
+ }
+
if (parent && parent->engine && parent->isMarked())
parent->removeChildEntry(this);
@@ -659,8 +663,6 @@ void InternalClass::markObjects(Heap::Base *b, MarkStack *stack)
Heap::InternalClass *ic = static_cast<Heap::InternalClass *>(b);
if (ic->prototype)
ic->prototype->mark(stack);
- if (ic->parent)
- ic->parent->mark(stack);
ic->nameMap.mark(stack);
}
diff --git a/tests/auto/qml/qv4mm/tst_qv4mm.cpp b/tests/auto/qml/qv4mm/tst_qv4mm.cpp
index 578a47d5fa..b57b716ed6 100644
--- a/tests/auto/qml/qv4mm/tst_qv4mm.cpp
+++ b/tests/auto/qml/qv4mm/tst_qv4mm.cpp
@@ -33,6 +33,7 @@
#include <private/qv4mm_p.h>
#include <private/qv4qobjectwrapper_p.h>
+#include <private/qjsvalue_p.h>
#include "../../shared/util.h"
@@ -46,6 +47,7 @@ private slots:
void gcStats();
void multiWrappedQObjects();
void accessParentOnDestruction();
+ void clearICParent();
};
void tst_qv4mm::gcStats()
@@ -108,6 +110,30 @@ void tst_qv4mm::accessParentOnDestruction()
QCOMPARE(obj->property("destructions").toInt(), 100);
}
+void tst_qv4mm::clearICParent()
+{
+ QJSEngine engine;
+ QJSValue value = engine.evaluate(
+ "(function() {\n"
+ " var test = Object.create(null);\n"
+ " for (var i = 0; i < 100; i++)\n"
+ " test[(\"key_\"+i)] = true;\n"
+ " for (var i = 0; i < 100; i++)\n"
+ " delete test[\"key_\" + i];\n"
+ " return test;\n"
+ "})();"
+ );
+ engine.collectGarbage();
+ QV4::Value *v4Value = QJSValuePrivate::getValue(&value);
+ QVERIFY(v4Value);
+ QV4::Heap::Object *v4Object = v4Value->toObject(engine.handle());
+ QVERIFY(v4Object);
+
+ // It should garbage collect the parents of the internalClass,
+ // as those aren't used anywhere else.
+ QCOMPARE(v4Object->internalClass->parent, nullptr);
+}
+
QTEST_MAIN(tst_qv4mm)
#include "tst_qv4mm.moc"