diff options
| author | Ulf Hermann <ulf.hermann@qt.io> | 2024-09-10 15:42:59 +0200 |
|---|---|---|
| committer | Ulf Hermann <ulf.hermann@qt.io> | 2024-09-10 23:11:53 +0200 |
| commit | d07c9071b4b172c69d0f5a7474e1e1c22de28e8e (patch) | |
| tree | 043cb66129f7da9811ff4ea4cc0d807bd84bbf24 | |
| parent | 9ea281b3b5a8a6eeef9db597761de84fe8ccbaf2 (diff) | |
QtQml: Never clear all executable CUs from the QQmlEngine
Since the executable CUs are used as entry points for marking by the GC,
dropping them from QQmlEngine means their strings, lookups, regexes etc
won't get marked anymore. If, however, the CUs are still referenced
elsewhere, their inner objects will still get used, despite having
potentially been swept by the GC.
Also fix the documentation of clearComponentCache() to clarify that it
does in fact not clear all components.
Pick-to: 6.8
Fixes: QTBUG-128638
Fixes: QTBUG-128782
Change-Id: I96480914733c399c18778202ae8dca7e332c3a85
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
| -rw-r--r-- | src/qml/jsruntime/qv4engine_p.h | 1 | ||||
| -rw-r--r-- | src/qml/qml/qqmlengine.cpp | 18 | ||||
| -rw-r--r-- | tests/auto/qml/qqmlengine/tst_qqmlengine.cpp | 9 |
3 files changed, 19 insertions, 9 deletions
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 0958ab3ab5..6b262cede6 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -767,7 +767,6 @@ public: { return m_compilationUnits; } - void clearCompilationUnits() { m_compilationUnits.clear(); } void trimCompilationUnits(); QV4::Value *registerNativeModule(const QUrl &url, const QV4::Value &module); diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 0f31e24e03..9098063fce 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -575,14 +575,16 @@ QQmlEngine::~QQmlEngine() /*! Clears the engine's internal component cache. - This function causes the property metadata of all components previously - loaded by the engine to be destroyed. All previously loaded components and - the property bindings for all extant objects created from those components will - cease to function. + This function causes the property metadata of most components previously + loaded by the engine to be destroyed. It does so by dropping unreferenced + components from the engine's component cache. It does not drop components that + are still referenced since that would almost certainly lead to crashes further + down the line. - This function returns the engine to a state where it does not contain any loaded - component data. This may be useful in order to reload a smaller subset of the - previous component set, or to load a new version of a previously loaded component. + If no components are referenced, this function returns the engine to a state + where it does not contain any loaded component data. This may be useful in + order to reload a smaller subset of the previous component set, or to load a + new version of a previously loaded component. Once the component cache has been cleared, components must be loaded before any new objects can be created. @@ -611,7 +613,7 @@ void QQmlEngine::clearComponentCache() mm->runGC(); mm->gcStateMachine->timeLimit = std::move(oldLimit); - handle()->clearCompilationUnits(); + handle()->trimCompilationUnits(); d->typeLoader.lock(); d->typeLoader.clearCache(); d->typeLoader.unlock(); diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp index 25615d5020..d71d6e292b 100644 --- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp +++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp @@ -408,12 +408,21 @@ void tst_qqmlengine::clearComponentCache() // Clear cache engine.clearComponentCache(); + // Nothing holds on to any CU anymore. They should all be gone. + QVERIFY(QQmlEnginePrivate::get(&engine)->v4engine()->compilationUnits().isEmpty()); + // Test cache refresh { QQmlComponent component(&engine, fileUrl); std::unique_ptr<QObject> obj { component.create() }; QVERIFY(obj.get() != nullptr); QCOMPARE(obj->property("test").toInt(), 11); + + engine.clearComponentCache(); + + // The CU we are holding on to is still alive. + // Otherwise we cannot mark its objects for GC anymore. + QVERIFY(!QQmlEnginePrivate::get(&engine)->v4engine()->compilationUnits().isEmpty()); } // Regular Synchronous loading will leave us with an event posted |
