diff options
author | Erik Verbruggen <erik.verbruggen@digia.com> | 2016-04-05 13:43:03 +0200 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2016-06-24 07:51:08 +0000 |
commit | 9ab8b9e4bdf313bb4304be206dd479d4d0848211 (patch) | |
tree | a8ac32dca10968a0712f5ae53fac1d6de70c39c6 /src/qml/qml/qqmljavascriptexpression.cpp | |
parent | 199ac27505468f222105008fe2729cf559600e2b (diff) |
QML: Do not register static QML dependencies on every call.
QML objects can be re-parented on the fly, resulting in different
dependencies for expressions like 'parent.width'. So, because of this,
dependencies are cleared and re-calculated after every binding
evaluation.
However, dependencies on properties of the scope and context objects
cannot change, because these objects do not get changed for the
life-time of a binding. So we can permanently register them. This is
only done for bindings, not for functions, because those might be
conditionally executed.
According to valgrind, this is a reduction of ~186 instructions on x86
for every evaluation of:
Item {
height: width
}
Change-Id: Ib095497323d4f08caf712d480007e2627a176369
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/qml/qqmljavascriptexpression.cpp')
-rw-r--r-- | src/qml/qml/qqmljavascriptexpression.cpp | 43 |
1 files changed, 32 insertions, 11 deletions
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp index eff1a6e039..7fb66a49bf 100644 --- a/src/qml/qml/qqmljavascriptexpression.cpp +++ b/src/qml/qml/qqmljavascriptexpression.cpp @@ -106,7 +106,8 @@ QQmlJavaScriptExpression::~QQmlJavaScriptExpression() m_nextExpression->m_prevExpression = m_prevExpression; } - clearGuards(); + clearActiveGuards(); + clearPermanentGuards(); if (m_scopeObject.isT2()) // notify DeleteWatcher of our deletion. m_scopeObject.asT2()->_s = 0; } @@ -114,12 +115,12 @@ QQmlJavaScriptExpression::~QQmlJavaScriptExpression() void QQmlJavaScriptExpression::setNotifyOnValueChanged(bool v) { activeGuards.setFlagValue(v); - if (!v) clearGuards(); + if (!v) clearActiveGuards(); } void QQmlJavaScriptExpression::resetNotifyOnValueChanged() { - clearGuards(); + clearActiveGuards(); } void QQmlJavaScriptExpression::setContext(QQmlContextData *context) @@ -214,7 +215,7 @@ void QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, bool *isUndefin ep->propertyCapture = lastPropertyCapture; } -void QQmlPropertyCapture::captureProperty(QQmlNotifier *n) +void QQmlPropertyCapture::captureProperty(QQmlNotifier *n, Duration duration) { if (watcher->wasDeleted()) return; @@ -234,14 +235,17 @@ void QQmlPropertyCapture::captureProperty(QQmlNotifier *n) g->connect(n); } - expression->activeGuards.prepend(g); + if (duration == OnlyOnce) + expression->permanentGuards.prepend(g); + else + expression->activeGuards.prepend(g); } /*! \internal \a n is in the signal index range (see QObjectPrivate::signalIndex()). */ -void QQmlPropertyCapture::captureProperty(QObject *o, int c, int n) +void QQmlPropertyCapture::captureProperty(QObject *o, int c, int n, Duration duration) { if (watcher->wasDeleted()) return; @@ -280,7 +284,10 @@ void QQmlPropertyCapture::captureProperty(QObject *o, int c, int n) g->connect(o, n, engine); } - expression->activeGuards.prepend(g); + if (duration == Permanently) + expression->permanentGuards.prepend(g); + else + expression->activeGuards.prepend(g); } } @@ -297,6 +304,11 @@ void QQmlPropertyCapture::registerQmlDependencies(const QV4::CompiledData::Funct if (!capture) return; + if (capture->expression->m_permanentDependenciesRegistered) + return; + + capture->expression->m_permanentDependenciesRegistered = true; + QV4::Scoped<QV4::QmlContext> context(scope, engine->qmlContext()); QQmlContextData *qmlContext = context->qmlContext(); @@ -304,7 +316,8 @@ void QQmlPropertyCapture::registerQmlDependencies(const QV4::CompiledData::Funct const int idObjectDependencyCount = compiledFunction->nDependingIdObjects; for (int i = 0; i < idObjectDependencyCount; ++i, ++idObjectDependency) { Q_ASSERT(int(*idObjectDependency) < qmlContext->idValueCount); - capture->captureProperty(&qmlContext->idValues[*idObjectDependency].bindings); + capture->captureProperty(&qmlContext->idValues[*idObjectDependency].bindings, + QQmlPropertyCapture::Permanently); } Q_ASSERT(qmlContext->contextObject); @@ -313,7 +326,8 @@ void QQmlPropertyCapture::registerQmlDependencies(const QV4::CompiledData::Funct for (int i = 0; i < contextPropertyDependencyCount; ++i) { const int propertyIndex = *contextPropertyDependency++; const int notifyIndex = *contextPropertyDependency++; - capture->captureProperty(qmlContext->contextObject, propertyIndex, notifyIndex); + capture->captureProperty(qmlContext->contextObject, propertyIndex, notifyIndex, + QQmlPropertyCapture::Permanently); } QObject *scopeObject = context->qmlScope(); @@ -322,7 +336,8 @@ void QQmlPropertyCapture::registerQmlDependencies(const QV4::CompiledData::Funct for (int i = 0; i < scopePropertyDependencyCount; ++i) { const int propertyIndex = *scopePropertyDependency++; const int notifyIndex = *scopePropertyDependency++; - capture->captureProperty(scopeObject, propertyIndex, notifyIndex); + capture->captureProperty(scopeObject, propertyIndex, notifyIndex, + QQmlPropertyCapture::Permanently); } } @@ -406,12 +421,18 @@ void QQmlJavaScriptExpression::createQmlBinding(QQmlContextData *ctxt, QObject * } -void QQmlJavaScriptExpression::clearGuards() +void QQmlJavaScriptExpression::clearActiveGuards() { while (QQmlJavaScriptExpressionGuard *g = activeGuards.takeFirst()) g->Delete(); } +void QQmlJavaScriptExpression::clearPermanentGuards() +{ + while (QQmlJavaScriptExpressionGuard *g = permanentGuards.takeFirst()) + g->Delete(); +} + void QQmlJavaScriptExpressionGuard_callback(QQmlNotifierEndpoint *e, void **) { QQmlJavaScriptExpression *expression = |