summaryrefslogtreecommitdiffstats
path: root/src/declarative/qml
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2009-08-05 04:15:10 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2009-08-05 04:23:22 (GMT)
commit3c85728f2cb69817d4b72d3aab16b7a7fe6bdbf0 (patch)
tree01e245219495204a92b395797dafa1686347a27b /src/declarative/qml
parent2995f6eee6f718487c5f982c23cc6a4318fc58bb (diff)
downloadQt-3c85728f2cb69817d4b72d3aab16b7a7fe6bdbf0.zip
Qt-3c85728f2cb69817d4b72d3aab16b7a7fe6bdbf0.tar.gz
Qt-3c85728f2cb69817d4b72d3aab16b7a7fe6bdbf0.tar.bz2
Rewrite bindings inside the compiler
To improve execution performance, binding expressions are rewritten as function closures inside QmlExpression. To improve startup performance, where possible, the expressions are rewritten inside the compiler instead of inside QmlExpression at runtime. This also has the sideeffect of removing the StoreBinding instruction, as all bindings are now "compiled". The QmlBinding::expression() method for rewritten bindings will now return the rewritten expression instead of the original (which is lost), but this API is internal anyway.
Diffstat (limited to 'src/declarative/qml')
-rw-r--r--src/declarative/qml/qmlcompiler.cpp43
-rw-r--r--src/declarative/qml/qmlexpression.cpp24
-rw-r--r--src/declarative/qml/qmlexpression_p.h8
-rw-r--r--src/declarative/qml/qmlinstruction.cpp3
-rw-r--r--src/declarative/qml/qmlinstruction_p.h1
-rw-r--r--src/declarative/qml/qmlvme.cpp22
6 files changed, 54 insertions, 47 deletions
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index 197bd44..6ef7cc2 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -64,7 +64,9 @@
#include <private/qmlcomponent_p.h>
#include "parser/qmljsast_p.h"
#include <private/qmlvmemetaobject_p.h>
+#include <private/qmlexpression_p.h>
#include "qmlmetaproperty_p.h"
+#include "qmlrewrite_p.h"
#include "qmlscriptparser_p.h"
@@ -2062,14 +2064,11 @@ void QmlCompiler::genBindingAssignment(QmlParser::Value *binding,
const BindingReference &ref = compileState.bindings.value(binding);
QmlInstruction store;
- int dataRef;
- if (ref.compiledData.isEmpty()) {
- dataRef = output->indexForString(ref.expression.asScript());
- store.type = QmlInstruction::StoreBinding;
- } else {
- dataRef = output->indexForByteArray(ref.compiledData);
- store.type = QmlInstruction::StoreCompiledBinding;
- }
+ store.type = QmlInstruction::StoreCompiledBinding;
+ store.assignBinding.value = output->indexForByteArray(ref.compiledData);
+ store.assignBinding.context = ref.bindingContext.stack;
+ store.assignBinding.owner = ref.bindingContext.owner;
+ store.line = prop->location.end.line;
Q_ASSERT(ref.bindingContext.owner == 0 ||
(ref.bindingContext.owner != 0 && valueTypeProperty));
@@ -2081,18 +2080,12 @@ void QmlCompiler::genBindingAssignment(QmlParser::Value *binding,
store.assignBinding.property =
QmlMetaPropertyPrivate::saveProperty(prop->index);
}
- store.assignBinding.value = dataRef;
- store.assignBinding.context = ref.bindingContext.stack;
- store.assignBinding.owner = ref.bindingContext.owner;
- store.line = prop->location.end.line;
output->bytecode << store;
}
bool QmlCompiler::completeComponentBuild()
{
- saveComponentState();
-
for (int ii = 0; ii < compileState.aliasingObjects.count(); ++ii) {
Object *aliasObject = compileState.aliasingObjects.at(ii);
COMPILE_CHECK(buildDynamicMeta(aliasObject, ResolveAliases));
@@ -2111,11 +2104,31 @@ bool QmlCompiler::completeComponentBuild()
expr.expression = binding.expression;
bs.compile(expr);
- if (bs.isValid())
+ quint32 type;
+ if (bs.isValid()) {
binding.compiledData =
QByteArray(bs.compileData(), bs.compileDataSize());
+ type = QmlExpressionPrivate::BasicScriptEngineData;
+ } else {
+ type = QmlExpressionPrivate::PreTransformedQtScriptData;
+
+ // Pre-rewrite the expression
+ QString expression = binding.expression.asScript();
+ QmlRewrite::RewriteBinding rewriteBinding;
+ expression = rewriteBinding(expression);
+
+ quint32 length = expression.length();
+ binding.compiledData =
+ QByteArray((const char *)&length, sizeof(quint32)) +
+ QByteArray((const char *)expression.constData(),
+ expression.length() * sizeof(QChar));
+ }
+ binding.compiledData.prepend(QByteArray((const char *)&type,
+ sizeof(quint32)));
}
+ saveComponentState();
+
return true;
}
diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp
index 2c06efa..148ff71 100644
--- a/src/declarative/qml/qmlexpression.cpp
+++ b/src/declarative/qml/qmlexpression.cpp
@@ -51,7 +51,7 @@ Q_DECLARE_METATYPE(QList<QObject *>);
QT_BEGIN_NAMESPACE
QmlExpressionPrivate::QmlExpressionPrivate()
-: ctxt(0), expressionFunctionValid(false), sseData(0), me(0), trackChange(true), line(-1), guardList(0), guardListLength(0)
+: ctxt(0), expressionFunctionValid(false), expressionRewritten(false), sseData(0), me(0), trackChange(true), line(-1), guardList(0), guardListLength(0)
{
}
@@ -73,7 +73,15 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc,
{
Q_Q(QmlExpression);
- sse.load((const char *)expr, rc);
+ quint32 *data = (quint32 *)expr;
+ Q_ASSERT(*data == BasicScriptEngineData ||
+ *data == PreTransformedQtScriptData);
+ if (*data == BasicScriptEngineData) {
+ sse.load((const char *)(data + 1), rc);
+ } else {
+ expression = QString::fromRawData((QChar *)(data + 2), data[1]);
+ expressionRewritten = true;
+ }
this->ctxt = ctxt;
if (ctxt)
@@ -203,6 +211,7 @@ void QmlExpression::setExpression(const QString &expression)
d->expression = expression;
d->expressionFunctionValid = false;
+ d->expressionRewritten = false;
d->expressionFunction = QScriptValue();
d->sse.clear();
@@ -250,10 +259,15 @@ QVariant QmlExpressionPrivate::evalQtScript()
scriptEngine->currentContext()->pushScope(ctxtPriv->scopeChain.at(i));
if (!expressionFunctionValid) {
- QmlRewrite::RewriteBinding rewriteBinding;
- const QString code = rewriteBinding(expression);
- expressionFunction = scriptEngine->evaluate(code, fileName, line);
+ if (expressionRewritten) {
+ expressionFunction = scriptEngine->evaluate(expression, fileName, line);
+ } else {
+ QmlRewrite::RewriteBinding rewriteBinding;
+
+ const QString code = rewriteBinding(expression);
+ expressionFunction = scriptEngine->evaluate(code, fileName, line);
+ }
expressionFunctionValid = true;
}
diff --git a/src/declarative/qml/qmlexpression_p.h b/src/declarative/qml/qmlexpression_p.h
index cb89ce0..5ecc24d 100644
--- a/src/declarative/qml/qmlexpression_p.h
+++ b/src/declarative/qml/qmlexpression_p.h
@@ -70,12 +70,18 @@ public:
QmlExpressionPrivate();
~QmlExpressionPrivate();
+ enum CompiledDataType {
+ BasicScriptEngineData = 1,
+ PreTransformedQtScriptData = 2
+ };
+
void init(QmlContext *, const QString &, QObject *);
void init(QmlContext *, void *, QmlRefCount *, QObject *);
QmlContext *ctxt;
QString expression;
- bool expressionFunctionValid;
+ bool expressionFunctionValid:1;
+ bool expressionRewritten:1;
QScriptValue expressionFunction;
QmlBasicScript sse;
diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp
index 9f77bc0..889a057 100644
--- a/src/declarative/qml/qmlinstruction.cpp
+++ b/src/declarative/qml/qmlinstruction.cpp
@@ -140,9 +140,6 @@ void QmlCompiledData::dump(QmlInstruction *instr, int idx)
case QmlInstruction::AssignCustomType:
qWarning() << idx << "\t" << line << "\t" << "ASSIGN_CUSTOMTYPE\t\t" << instr->assignCustomType.propertyIndex << "\t" << instr->assignCustomType.valueIndex;
break;
- case QmlInstruction::StoreBinding:
- qWarning() << idx << "\t" << line << "\t" << "STORE_BINDING\t\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t\t" << instr->assignBinding.context << primitives.at(instr->assignBinding.value);
- break;
case QmlInstruction::StoreCompiledBinding:
qWarning() << idx << "\t" << line << "\t" << "STORE_COMPILED_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t\t" << instr->assignBinding.context;
break;
diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h
index c3d676f..e6b8de6 100644
--- a/src/declarative/qml/qmlinstruction_p.h
+++ b/src/declarative/qml/qmlinstruction_p.h
@@ -124,7 +124,6 @@ public:
AssignSignalObject, /* assignSignalObject */
AssignCustomType, /* assignCustomType */
- StoreBinding, /* assignBinding */
StoreCompiledBinding, /* assignBinding */
StoreValueSource, /* assignValueSource */
diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp
index 7c02548..bf3b31a 100644
--- a/src/declarative/qml/qmlvme.cpp
+++ b/src/declarative/qml/qmlvme.cpp
@@ -549,28 +549,6 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledData
}
break;
- case QmlInstruction::StoreBinding:
- {
- QObject *target =
- stack.at(stack.count() - 1 - instr.assignBinding.owner);
- QObject *context =
- stack.at(stack.count() - 1 - instr.assignBinding.context);
-
- QmlMetaProperty mp;
- mp.restore(instr.assignBinding.property, target, ctxt);
-
- QmlBinding *bind = new QmlBinding(primitives.at(instr.assignBinding.value), context, ctxt);
- bindValues.append(bind);
- QmlBindingPrivate *p =
- static_cast<QmlBindingPrivate *>(QObjectPrivate::get(bind));
- p->mePtr = &bindValues.values[bindValues.count - 1];
- QFx_setParent_noEvent(bind, target);
-
- bind->setTarget(mp);
- bind->setSourceLocation(comp->url, instr.line);
- }
- break;
-
case QmlInstruction::StoreValueSource:
{
QmlPropertyValueSource *vs =