aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2011-11-03 16:52:53 +0000
committerQt by Nokia <qt-info@nokia.com>2011-11-04 16:22:04 +0100
commit3e84e81da776234bf62570b439f1e21848f83c4b (patch)
treef4d435300c7ee5f47b98bb1e85b40a34235eca51 /src
parent986367abdac654cea9c1fe37f9ff4226b7516fa5 (diff)
Optimization: Minimize refreshing when root context changes
Modifying a context requires expressions to be refreshed incase they depend on a name resolution that changes. As it is common to modify the root context, and the root context can't hide any names, it is easy to constrain the expressions that require refreshing. In a well behaving app, this should mean that no expressions are reevaluated when the root context is modified. Change-Id: Id3b48cd595fdd6b5a3dc6f26319f652dccaef79c Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/declarative/qml/qdeclarativecontext.cpp51
-rw-r--r--src/declarative/qml/qdeclarativecontext_p.h3
-rw-r--r--src/declarative/qml/v8/qv8contextwrapper.cpp6
3 files changed, 37 insertions, 23 deletions
diff --git a/src/declarative/qml/qdeclarativecontext.cpp b/src/declarative/qml/qdeclarativecontext.cpp
index d7a642460c..1723603d29 100644
--- a/src/declarative/qml/qdeclarativecontext.cpp
+++ b/src/declarative/qml/qdeclarativecontext.cpp
@@ -511,18 +511,18 @@ QObject *QDeclarativeContextPrivate::context_at(QDeclarativeListProperty<QObject
QDeclarativeContextData::QDeclarativeContextData()
: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false),
- isPragmaLibraryContext(false), publicContext(0), activeVMEData(0), propertyNames(0), contextObject(0),
- imports(0), childContexts(0), nextChild(0), prevChild(0), expressions(0), contextObjects(0),
- contextGuards(0), idValues(0), idValueCount(0), linkedContext(0), componentAttached(0),
- v4bindings(0), v8bindings(0)
+ isPragmaLibraryContext(false), unresolvedNames(false), publicContext(0), activeVMEData(0),
+ propertyNames(0), contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0),
+ expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), linkedContext(0),
+ componentAttached(0), v4bindings(0), v8bindings(0)
{
}
QDeclarativeContextData::QDeclarativeContextData(QDeclarativeContext *ctxt)
: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false),
- isPragmaLibraryContext(false), publicContext(ctxt), activeVMEData(0), propertyNames(0),
- contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0), expressions(0),
- contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), linkedContext(0),
+ isPragmaLibraryContext(false), unresolvedNames(false), publicContext(ctxt), activeVMEData(0),
+ propertyNames(0), contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0),
+ expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), linkedContext(0),
componentAttached(0), v4bindings(0), v8bindings(0)
{
}
@@ -664,26 +664,31 @@ void QDeclarativeContextData::refreshExpressionsRecursive(QDeclarativeAbstractEx
expression->refresh();
}
-void QDeclarativeContextData::refreshExpressionsRecursive()
+static inline bool expressions_to_run(QDeclarativeContextData *ctxt, bool isGlobalRefresh)
+{
+ return ctxt->expressions && (!isGlobalRefresh || ctxt->unresolvedNames);
+}
+
+void QDeclarativeContextData::refreshExpressionsRecursive(bool isGlobal)
{
// For efficiency, we try and minimize the number of guards we have to create
- if (expressions && (nextChild || childContexts)) {
+ if (expressions_to_run(this, isGlobal) && (nextChild || childContexts)) {
QDeclarativeGuardedContextData guard(this);
if (childContexts)
- childContexts->refreshExpressionsRecursive();
+ childContexts->refreshExpressionsRecursive(isGlobal);
if (guard.isNull()) return;
if (nextChild)
- nextChild->refreshExpressionsRecursive();
+ nextChild->refreshExpressionsRecursive(isGlobal);
if (guard.isNull()) return;
- if (expressions)
+ if (expressions_to_run(this, isGlobal))
refreshExpressionsRecursive(expressions);
- } else if (expressions) {
+ } else if (expressions_to_run(this, isGlobal)) {
refreshExpressionsRecursive(expressions);
@@ -691,18 +696,18 @@ void QDeclarativeContextData::refreshExpressionsRecursive()
QDeclarativeGuardedContextData guard(this);
- childContexts->refreshExpressionsRecursive();
+ childContexts->refreshExpressionsRecursive(isGlobal);
if (!guard.isNull() && nextChild)
- nextChild->refreshExpressionsRecursive();
+ nextChild->refreshExpressionsRecursive(isGlobal);
} else if (nextChild) {
- nextChild->refreshExpressionsRecursive();
+ nextChild->refreshExpressionsRecursive(isGlobal);
} else if (childContexts) {
- childContexts->refreshExpressionsRecursive();
+ childContexts->refreshExpressionsRecursive(isGlobal);
}
}
@@ -712,22 +717,24 @@ void QDeclarativeContextData::refreshExpressionsRecursive()
// *structure* (not values) changes.
void QDeclarativeContextData::refreshExpressions()
{
+ bool isGlobal = (parent == 0);
+
// For efficiency, we try and minimize the number of guards we have to create
- if (expressions && childContexts) {
+ if (expressions_to_run(this, isGlobal) && childContexts) {
QDeclarativeGuardedContextData guard(this);
- childContexts->refreshExpressionsRecursive();
+ childContexts->refreshExpressionsRecursive(isGlobal);
- if (!guard.isNull() && expressions)
+ if (!guard.isNull() && expressions_to_run(this, isGlobal))
refreshExpressionsRecursive(expressions);
- } else if (expressions) {
+ } else if (expressions_to_run(this, isGlobal)) {
refreshExpressionsRecursive(expressions);
} else if (childContexts) {
- childContexts->refreshExpressionsRecursive();
+ childContexts->refreshExpressionsRecursive(isGlobal);
}
}
diff --git a/src/declarative/qml/qdeclarativecontext_p.h b/src/declarative/qml/qdeclarativecontext_p.h
index 6676a0693c..fb6473cb7a 100644
--- a/src/declarative/qml/qdeclarativecontext_p.h
+++ b/src/declarative/qml/qdeclarativecontext_p.h
@@ -143,6 +143,7 @@ public:
quint32 ownedByParent:1; // unrelated to isInternal; parent context deletes children if true.
quint32 isJSContext:1;
quint32 isPragmaLibraryContext:1;
+ quint32 unresolvedNames:1; // True if expressions in this context failed to resolve a toplevel name
quint32 dummy:28;
QDeclarativeContext *publicContext;
@@ -216,7 +217,7 @@ public:
}
private:
- void refreshExpressionsRecursive();
+ void refreshExpressionsRecursive(bool isGlobal);
void refreshExpressionsRecursive(QDeclarativeAbstractExpression *);
~QDeclarativeContextData() {}
};
diff --git a/src/declarative/qml/v8/qv8contextwrapper.cpp b/src/declarative/qml/v8/qv8contextwrapper.cpp
index 46cf0e4298..20e479b28a 100644
--- a/src/declarative/qml/v8/qv8contextwrapper.cpp
+++ b/src/declarative/qml/v8/qv8contextwrapper.cpp
@@ -258,6 +258,7 @@ v8::Handle<v8::Value> QV8ContextWrapper::Getter(v8::Local<v8::String> property,
// Its possible we could delay the calculation of the "actual" context (in the case
// of sub contexts) until it is definately needed.
QDeclarativeContextData *context = resource->getContext();
+ QDeclarativeContextData *expressionContext = context;
if (!context)
return v8::Undefined();
@@ -362,6 +363,8 @@ v8::Handle<v8::Value> QV8ContextWrapper::Getter(v8::Local<v8::String> property,
context = context->parent;
}
+ expressionContext->unresolvedNames = true;
+
QString error = QLatin1String("Can't find variable: ") + engine->toString(property);
v8::ThrowException(v8::Exception::ReferenceError(engine->toString(error)));
return v8::Undefined();
@@ -394,6 +397,7 @@ v8::Handle<v8::Value> QV8ContextWrapper::Setter(v8::Local<v8::String> property,
// Its possible we could delay the calculation of the "actual" context (in the case
// of sub contexts) until it is definately needed.
QDeclarativeContextData *context = resource->getContext();
+ QDeclarativeContextData *expressionContext = context;
if (!context)
return v8::Undefined();
@@ -436,6 +440,8 @@ v8::Handle<v8::Value> QV8ContextWrapper::Setter(v8::Local<v8::String> property,
context = context->parent;
}
+ expressionContext->unresolvedNames = true;
+
if (!resource->readOnly) {
return v8::Handle<v8::Value>();
} else {