aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlobjectcreator.cpp
diff options
context:
space:
mode:
authorJ-P Nurmi <jpnurmi@qt.io>2017-10-17 16:54:22 +0200
committerJ-P Nurmi <jpnurmi@qt.io>2017-11-25 06:21:04 +0000
commitefe1926598c69a09c9365673bba6961a83936d49 (patch)
treec944b5e30f90ea1e1a5525b3974b67e6f8da1ad6 /src/qml/qml/qqmlobjectcreator.cpp
parentc5567cc706afb954ff6f679f35fe96a078bd4f46 (diff)
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 <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/qml/qqmlobjectcreator.cpp')
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp85
1 files changed, 77 insertions, 8 deletions
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<QQmlPropertyCache> 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<QV4::QmlContext *>(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<void> 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<void>();
+ }
+
+ 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();