diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 30 | ||||
| -rw-r--r-- | src/qml/qml/qqmlobjectcreator_p.h | 21 |
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()); |
