aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2024-09-10 15:42:59 +0200
committerUlf Hermann <ulf.hermann@qt.io>2024-09-10 23:11:53 +0200
commitd07c9071b4b172c69d0f5a7474e1e1c22de28e8e (patch)
tree043cb66129f7da9811ff4ea4cc0d807bd84bbf24
parent9ea281b3b5a8a6eeef9db597761de84fe8ccbaf2 (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.h1
-rw-r--r--src/qml/qml/qqmlengine.cpp18
-rw-r--r--tests/auto/qml/qqmlengine/tst_qqmlengine.cpp9
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