From efe1926598c69a09c9365673bba6961a83936d49 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 17 Oct 2017 16:54:22 +0200 Subject: More fine-grained deferred property execution This allows Qt Quick Controls 2 to defer the execution of certain building blocks until needed. For example, a button control can defer its background item so that the default background is not executed at all when replaced by a custom background. First of all, this gives a massive performance boost for customized controls. Secondly, this avoids the most burning issue in QQC2, problems with asynchronous incubation ("Object destroyed during incubation"). Task-number: QTBUG-50992 Change-Id: If3616c9dac70e3a474a20070ad0452874d267164 Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlobjectcreator.cpp | 85 +++++++++++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 8 deletions(-) (limited to 'src/qml/qml/qqmlobjectcreator.cpp') diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index b2f1421bcb..3663b06d55 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -233,6 +233,7 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI return instance; } +// ### unify or keep in sync with populateDeferredBinding() bool QQmlObjectCreator::populateDeferredProperties(QObject *instance, QQmlData::DeferredData *deferredData) { QQmlData *declarativeData = QQmlData::get(instance); @@ -283,6 +284,80 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance, QQmlData:: qSwap(_qmlContext, qmlContext); qSwap(_scopeObject, scopeObject); + deferredData->bindings.clear(); + phase = ObjectsCreated; + + return errors.isEmpty(); +} + +// ### unify or keep in sync with populateDeferredProperties() +bool QQmlObjectCreator::populateDeferredBinding(const QQmlProperty &qmlProperty, QQmlData::DeferredData *deferredData, const QV4::CompiledData::Binding *binding) +{ + Q_ASSERT(binding->flags & QV4::CompiledData::Binding::IsDeferredBinding); + + QObject *instance = qmlProperty.object(); + QQmlData *declarativeData = QQmlData::get(instance); + context = deferredData->context; + sharedState->rootContext = context; + + QObject *bindingTarget = instance; + + QQmlRefPointer cache = declarativeData->propertyCache; + QQmlVMEMetaObject *vmeMetaObject = QQmlVMEMetaObject::get(instance); + + QObject *scopeObject = instance; + qSwap(_scopeObject, scopeObject); + + QV4::Scope valueScope(v4); + + Q_ASSERT(topLevelCreator); + if (!sharedState->allJavaScriptObjects) + sharedState->allJavaScriptObjects = valueScope.alloc(compilationUnit->totalObjectCount); + + QV4::QmlContext *qmlContext = static_cast(valueScope.alloc(1)); + + qSwap(_qmlContext, qmlContext); + + qSwap(_propertyCache, cache); + qSwap(_qobject, instance); + + int objectIndex = deferredData->deferredIdx; + qSwap(_compiledObjectIndex, objectIndex); + + const QV4::CompiledData::Object *obj = qmlUnit->objectAt(_compiledObjectIndex); + qSwap(_compiledObject, obj); + + qSwap(_ddata, declarativeData); + qSwap(_bindingTarget, bindingTarget); + qSwap(_vmeMetaObject, vmeMetaObject); + + QQmlListProperty savedList; + qSwap(_currentList, savedList); + + const QQmlPropertyData &property = QQmlPropertyPrivate::get(qmlProperty)->core; + + if (property.isQList()) { + void *argv[1] = { (void*)&_currentList }; + QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property.coreIndex(), argv); + } else if (_currentList.object) { + _currentList = QQmlListProperty(); + } + + setPropertyBinding(&property, binding); + + qSwap(_currentList, savedList); + + qSwap(_vmeMetaObject, vmeMetaObject); + qSwap(_bindingTarget, bindingTarget); + qSwap(_ddata, declarativeData); + qSwap(_compiledObject, obj); + qSwap(_compiledObjectIndex, objectIndex); + qSwap(_qobject, instance); + qSwap(_propertyCache, cache); + + qSwap(_qmlContext, qmlContext); + qSwap(_scopeObject, scopeObject); + phase = ObjectsCreated; return errors.isEmpty(); @@ -1341,14 +1416,8 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject * qSwap(_propertyCache, cache); qSwap(_vmeMetaObject, vmeMetaObject); - if (_compiledObject->flags & QV4::CompiledData::Object::HasDeferredBindings) { - QQmlData::DeferredData *deferData = new QQmlData::DeferredData; - deferData->deferredIdx = _compiledObjectIndex; - deferData->compilationUnit = compilationUnit; - deferData->compilationUnit->addref(); - deferData->context = context; - _ddata->deferredData.append(deferData); - } + if (_compiledObject->flags & QV4::CompiledData::Object::HasDeferredBindings) + _ddata->deferData(_compiledObjectIndex, compilationUnit, context); if (_compiledObject->nFunctions > 0) setupFunctions(); -- cgit v1.2.3