aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp30
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h21
2 files changed, 39 insertions, 12 deletions
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 3d4d3596cc..713162a6c7 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -70,7 +70,7 @@ QQmlObjectCreator::QQmlObjectCreator(
sharedState->allCreatedBindings.allocate(compilationUnit->totalBindingsCount());
sharedState->allParserStatusCallbacks.allocate(compilationUnit->totalParserStatusCount());
sharedState->allCreatedObjects.allocate(compilationUnit->totalObjectCount());
- sharedState->allJavaScriptObjects = nullptr;
+ sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList();
sharedState->creationContext = creationContext;
sharedState->rootContext.reset();
sharedState->hadTopLevelRequiredProperties = false;
@@ -189,9 +189,9 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
QV4::Scope scope(v4);
- Q_ASSERT(sharedState->allJavaScriptObjects || topLevelCreator);
+ Q_ASSERT(sharedState->allJavaScriptObjects.canTrack() || topLevelCreator);
if (topLevelCreator)
- sharedState->allJavaScriptObjects = scope.alloc(compilationUnit->totalObjectCount());
+ sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList(scope, compilationUnit->totalObjectCount());
if (!isComponentRoot && sharedState->creationContext) {
// otherwise QQmlEnginePrivate::createInternalContext() handles it
@@ -206,7 +206,7 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
}
if (topLevelCreator)
- sharedState->allJavaScriptObjects = nullptr;
+ sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList();
phase = CreatingObjectsPhase2;
@@ -235,10 +235,11 @@ void QQmlObjectCreator::beginPopulateDeferred(const QQmlRefPointer<QQmlContextDa
sharedState->rootContext = newContext;
Q_ASSERT(topLevelCreator);
- Q_ASSERT(!sharedState->allJavaScriptObjects);
+ Q_ASSERT(!sharedState->allJavaScriptObjects.canTrack());
+ // FIXME (QTBUG-122956): allocating from the short lived scope does not make any sense
QV4::Scope valueScope(v4);
- sharedState->allJavaScriptObjects = valueScope.alloc(compilationUnit->totalObjectCount());
+ sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList(valueScope, compilationUnit->totalObjectCount());
}
void QQmlObjectCreator::populateDeferred(QObject *instance, int deferredIndex,
@@ -1406,9 +1407,8 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
QObject *scopeObject = instance;
qSwap(_scopeObject, scopeObject);
- Q_ASSERT(sharedState->allJavaScriptObjects);
- *sharedState->allJavaScriptObjects = QV4::QObjectWrapper::wrap(v4, instance);
- ++sharedState->allJavaScriptObjects;
+ Q_ASSERT(sharedState->allJavaScriptObjects.canTrack());
+ sharedState->allJavaScriptObjects.trackObject(v4, instance);
QV4::Scope valueScope(v4);
QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc());
@@ -1809,3 +1809,15 @@ QQmlObjectCreatorRecursionWatcher::QQmlObjectCreatorRecursionWatcher(QQmlObjectC
, watcher(creator->sharedState.data())
{
}
+
+void ObjectInCreationGCAnchorList::trackObject(QV4::ExecutionEngine *engine, QObject *instance)
+{
+ *allJavaScriptObjects = QV4::QObjectWrapper::wrap(engine, instance);
+ // we have to handle the case where the gc is already running, but the scope is discarded
+ // before the collector runs again. In that case, rescanning won't help us. Thus, mark the
+ // object.
+ QV4::WriteBarrier::markCustom(engine, [this](QV4::MarkStack *ms) {
+ allJavaScriptObjects->heapObject()->mark(ms);
+ });
+ ++allJavaScriptObjects;
+}
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index 733cfef3f2..eed1dceb3f 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -84,6 +84,20 @@ struct DeferredQPropertyBinding {
QUntypedPropertyBinding binding;
};
+class ObjectInCreationGCAnchorList {
+public:
+ // this is a non owning view, rule of zero applies
+ ObjectInCreationGCAnchorList() = default;
+ ObjectInCreationGCAnchorList(const QV4::Scope &scope, int totalObjectCount)
+ {
+ allJavaScriptObjects = scope.alloc(totalObjectCount);
+ }
+ void trackObject(QV4::ExecutionEngine *engine, QObject *instance);
+ bool canTrack() const { return allJavaScriptObjects; }
+private:
+ QV4::Value *allJavaScriptObjects = nullptr; // pointer to vector on JS stack to reference JS wrappers during creation phase.
+};
+
struct QQmlObjectCreatorSharedState final : QQmlRefCounted<QQmlObjectCreatorSharedState>
{
QQmlRefPointer<QQmlContextData> rootContext;
@@ -91,7 +105,7 @@ struct QQmlObjectCreatorSharedState final : QQmlRefCounted<QQmlObjectCreatorShar
QFiniteStack<QQmlAbstractBinding::Ptr> allCreatedBindings;
QFiniteStack<QQmlParserStatus*> allParserStatusCallbacks;
QFiniteStack<QQmlGuard<QObject> > allCreatedObjects;
- QV4::Value *allJavaScriptObjects; // pointer to vector on JS stack to reference JS wrappers during creation phase.
+ ObjectInCreationGCAnchorList allJavaScriptObjects; // pointer to vector on JS stack to reference JS wrappers during creation phase.
QQmlComponentAttached *componentAttached;
QList<QQmlFinalizerHook *> finalizeHooks;
QQmlVmeProfiler profiler;
@@ -254,8 +268,9 @@ private:
qt_ptr_swap(_scopeObject, scopeObject);
QV4::Scope valueScope(v4);
- QScopedValueRollback<QV4::Value*> jsObjectGuard(sharedState->allJavaScriptObjects,
- valueScope.alloc(compilationUnit->totalObjectCount()));
+ QScopedValueRollback<ObjectInCreationGCAnchorList> jsObjectGuard(
+ sharedState->allJavaScriptObjects,
+ ObjectInCreationGCAnchorList(valueScope, compilationUnit->totalObjectCount()));
Q_ASSERT(topLevelCreator);
QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc());