diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2019-03-26 13:57:33 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2019-03-27 09:23:07 +0000 |
commit | 60f766f5c68fc33322c6d095d81b1856828b2b0b (patch) | |
tree | 8196c19566407873570499e0be334470406321f4 | |
parent | b6d0ed435d2d57359b6eafb2728c024eab0b1ece (diff) |
Re-use existing IC when freezing properties
There is no reason to start from the empty class in that case.
Furthermore, if the properties are already frozen, starting from the
empty class will walk the IC hierarchy to the current IC. However, if
the garbage collector has removed the intermediate classes in the mean
time, we end up at a new IC which is equivalent but not the same.
Therefore, the freezing never terminates.
Task-number: QTBUG-74190
Change-Id: Id544bd00d3b4b563fb06dfce0edd0385e1d32a6c
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r-- | src/qml/jsruntime/qv4internalclass.cpp | 7 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4internalclass_p.h | 2 | ||||
-rw-r--r-- | tests/auto/qml/qqmlengine/tst_qqmlengine.cpp | 13 |
3 files changed, 17 insertions, 5 deletions
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp index 8e2657f4a5..3fb2465a45 100644 --- a/src/qml/jsruntime/qv4internalclass.cpp +++ b/src/qml/jsruntime/qv4internalclass.cpp @@ -658,11 +658,10 @@ Heap::InternalClass *InternalClass::frozen() return f; } -Heap::InternalClass *InternalClass::propertiesFrozen() const +Heap::InternalClass *InternalClass::propertiesFrozen() { Scope scope(engine); - Scoped<QV4::InternalClass> frozen(scope, engine->internalClasses(EngineBase::Class_Empty)->changeVTable(vtable)); - frozen = frozen->changePrototype(prototype); + Scoped<QV4::InternalClass> frozen(scope, this); for (uint i = 0; i < size; ++i) { PropertyAttributes attrs = propertyData.at(i); if (!nameMap.at(i).isValid()) @@ -671,7 +670,7 @@ Heap::InternalClass *InternalClass::propertiesFrozen() const attrs.setWritable(false); attrs.setConfigurable(false); } - frozen = frozen->addMember(nameMap.at(i), attrs); + frozen = frozen->changeMember(nameMap.at(i), attrs); } return frozen->d(); } diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h index c689637721..121238c555 100644 --- a/src/qml/jsruntime/qv4internalclass_p.h +++ b/src/qml/jsruntime/qv4internalclass_p.h @@ -428,7 +428,7 @@ struct InternalClass : Base { Q_REQUIRED_RESULT InternalClass *sealed(); Q_REQUIRED_RESULT InternalClass *frozen(); - Q_REQUIRED_RESULT InternalClass *propertiesFrozen() const; + Q_REQUIRED_RESULT InternalClass *propertiesFrozen(); Q_REQUIRED_RESULT InternalClass *asProtoClass(); diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp index f58ae38264..b9cb6b70d2 100644 --- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp +++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp @@ -80,6 +80,7 @@ private slots: void qrcUrls(); void cppSignalAndEval(); void singletonInstance(); + void aggressiveGc(); public slots: QObject *createAQObjectForOwnershipTest () @@ -1043,6 +1044,18 @@ void tst_qqmlengine::singletonInstance() } } +void tst_qqmlengine::aggressiveGc() +{ + const QByteArray origAggressiveGc = qgetenv("QV4_MM_AGGRESSIVE_GC"); + qputenv("QV4_MM_AGGRESSIVE_GC", "true"); + { + QQmlEngine engine; // freezing should not run into infinite recursion + QJSValue obj = engine.newObject(); + QVERIFY(obj.isObject()); + } + qputenv("QV4_MM_AGGRESSIVE_GC", origAggressiveGc); +} + QTEST_MAIN(tst_qqmlengine) #include "tst_qqmlengine.moc" |