summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brasser <michael.brasser@nokia.com>2010-12-15 02:08:13 (GMT)
committerMichael Brasser <michael.brasser@nokia.com>2010-12-17 06:35:17 (GMT)
commit488e616b50707e5b37162e6d0cfc71a1ffdf9bef (patch)
tree86b02b1665e7dcc29aed479c9ed2ce7d6f5ba214
parent139ecc0e74af2795faa55cfd532aeb10c631049e (diff)
downloadQt-488e616b50707e5b37162e6d0cfc71a1ffdf9bef.zip
Qt-488e616b50707e5b37162e6d0cfc71a1ffdf9bef.tar.gz
Qt-488e616b50707e5b37162e6d0cfc71a1ffdf9bef.tar.bz2
Rewrite/cache bindings created by PropertyChanges.
This provides a significant optimization for initial evaluation of bindings specified in a PropertyChanges. Reviewed-by: Aaron Kennedy
-rw-r--r--src/declarative/qml/qdeclarativebinding.cpp14
-rw-r--r--src/declarative/qml/qdeclarativebinding_p.h3
-rw-r--r--src/declarative/qml/qdeclarativecompiler.cpp29
-rw-r--r--src/declarative/qml/qdeclarativecompiler_p.h1
-rw-r--r--src/declarative/qml/qdeclarativecontext_p.h1
-rw-r--r--src/declarative/qml/qdeclarativecustomparser.cpp9
-rw-r--r--src/declarative/qml/qdeclarativecustomparser_p.h3
-rw-r--r--src/declarative/util/qdeclarativepropertychanges.cpp26
8 files changed, 82 insertions, 4 deletions
diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp
index 309d372..1ead6ce 100644
--- a/src/declarative/qml/qdeclarativebinding.cpp
+++ b/src/declarative/qml/qdeclarativebinding.cpp
@@ -46,6 +46,7 @@
#include "qdeclarativecontext.h"
#include "qdeclarativeinfo.h"
#include "private/qdeclarativecontext_p.h"
+#include "private/qdeclarativecompiler_p.h"
#include "private/qdeclarativedata_p.h"
#include "private/qdeclarativestringconverters_p.h"
#include "private/qdeclarativestate_p_p.h"
@@ -233,6 +234,19 @@ QDeclarativeBinding::QDeclarativeBinding(void *data, QDeclarativeRefCount *rc, Q
setNotifyOnValueChanged(true);
}
+QDeclarativeBinding *
+QDeclarativeBinding::createBinding(Identifier id, QObject *obj, QDeclarativeContext *ctxt,
+ const QString &url, int lineNumber, QObject *parent)
+{
+ QDeclarativeContextData *ctxtdata = QDeclarativeContextData::get(ctxt);
+
+ QDeclarativeEnginePrivate *engine = QDeclarativeEnginePrivate::get(qmlEngine(obj));
+ QDeclarativeCompiledData *cdata = 0;
+ if (engine && ctxtdata && !ctxtdata->url.isEmpty())
+ cdata = engine->typeLoader.get(ctxtdata->url)->compiledData();
+ return cdata ? new QDeclarativeBinding((void*)cdata->datas.at(id).constData(), cdata, obj, ctxtdata, url, lineNumber, parent) : 0;
+}
+
QDeclarativeBinding::QDeclarativeBinding(const QString &str, QObject *obj, QDeclarativeContext *ctxt,
QObject *parent)
: QDeclarativeExpression(QDeclarativeContextData::get(ctxt), obj, str, *new QDeclarativeBindingPrivate)
diff --git a/src/declarative/qml/qdeclarativebinding_p.h b/src/declarative/qml/qdeclarativebinding_p.h
index 7823a3d..787a3b9 100644
--- a/src/declarative/qml/qdeclarativebinding_p.h
+++ b/src/declarative/qml/qdeclarativebinding_p.h
@@ -162,6 +162,9 @@ public:
virtual void update(QDeclarativePropertyPrivate::WriteFlags flags);
virtual QString expression() const;
+ typedef int Identifier;
+ static QDeclarativeBinding *createBinding(Identifier, QObject *, QDeclarativeContext *, const QString &, int, QObject *parent=0);
+
public Q_SLOTS:
void update() { update(QDeclarativePropertyPrivate::DontRemoveBinding); }
diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp
index 4749bf8..4f4ad3f 100644
--- a/src/declarative/qml/qdeclarativecompiler.cpp
+++ b/src/declarative/qml/qdeclarativecompiler.cpp
@@ -2262,6 +2262,35 @@ const QMetaObject *QDeclarativeCompiler::resolveType(const QByteArray& name) con
return qmltype->metaObject();
}
+// similar to logic of completeComponentBuild, but also sticks data
+// into datas at the end
+int QDeclarativeCompiler::rewriteBinding(const QString& expression, const QByteArray& name)
+{
+ QDeclarativeRewrite::RewriteBinding rewriteBinding;
+ rewriteBinding.setName('$' + name);
+ bool isSharable = false;
+ QString rewrite = rewriteBinding(expression, 0, &isSharable);
+
+ quint32 length = rewrite.length();
+ quint32 pc;
+
+ if (isSharable) {
+ pc = output->cachedClosures.count();
+ pc |= 0x80000000;
+ output->cachedClosures.append(0);
+ } else {
+ pc = output->cachedPrograms.length();
+ output->cachedPrograms.append(0);
+ }
+
+ QByteArray compiledData =
+ QByteArray((const char *)&pc, sizeof(quint32)) +
+ QByteArray((const char *)&length, sizeof(quint32)) +
+ QByteArray((const char *)rewrite.constData(),
+ rewrite.length() * sizeof(QChar));
+
+ return output->indexForByteArray(compiledData);
+}
// Ensures that the dynamic meta specification on obj is valid
bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj)
diff --git a/src/declarative/qml/qdeclarativecompiler_p.h b/src/declarative/qml/qdeclarativecompiler_p.h
index 7d76ad9..bface8f 100644
--- a/src/declarative/qml/qdeclarativecompiler_p.h
+++ b/src/declarative/qml/qdeclarativecompiler_p.h
@@ -161,6 +161,7 @@ public:
int evaluateEnum(const QByteArray& script) const; // for QDeclarativeCustomParser::evaluateEnum
const QMetaObject *resolveType(const QByteArray& name) const; // for QDeclarativeCustomParser::resolveType
+ int rewriteBinding(const QString& expression, const QByteArray& name); // for QDeclarativeCustomParser::rewriteBinding
private:
static void reset(QDeclarativeCompiledData *);
diff --git a/src/declarative/qml/qdeclarativecontext_p.h b/src/declarative/qml/qdeclarativecontext_p.h
index 6c14feb..6b71381 100644
--- a/src/declarative/qml/qdeclarativecontext_p.h
+++ b/src/declarative/qml/qdeclarativecontext_p.h
@@ -77,7 +77,6 @@ class QDeclarativeEngine;
class QDeclarativeExpression;
class QDeclarativeExpressionPrivate;
class QDeclarativeAbstractExpression;
-class QDeclarativeBinding_Id;
class QDeclarativeCompiledBindings;
class QDeclarativeContextData;
diff --git a/src/declarative/qml/qdeclarativecustomparser.cpp b/src/declarative/qml/qdeclarativecustomparser.cpp
index 97a6a00..58ffc56 100644
--- a/src/declarative/qml/qdeclarativecustomparser.cpp
+++ b/src/declarative/qml/qdeclarativecustomparser.cpp
@@ -304,5 +304,14 @@ const QMetaObject *QDeclarativeCustomParser::resolveType(const QByteArray& name)
return compiler->resolveType(name);
}
+/*!
+ Rewrites \a expression and returns an identifier that can be
+ used to construct the binding later. \a name
+ is used as the name of the rewritten function.
+*/
+QDeclarativeBinding::Identifier QDeclarativeCustomParser::rewriteBinding(const QString& expression, const QByteArray& name)
+{
+ return compiler->rewriteBinding(expression, name);
+}
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativecustomparser_p.h b/src/declarative/qml/qdeclarativecustomparser_p.h
index c3f9dd2..9b419c2 100644
--- a/src/declarative/qml/qdeclarativecustomparser_p.h
+++ b/src/declarative/qml/qdeclarativecustomparser_p.h
@@ -56,6 +56,7 @@
#include "private/qdeclarativemetatype_p.h"
#include "qdeclarativeerror.h"
#include "private/qdeclarativeparser_p.h"
+#include "private/qdeclarativebinding_p.h"
#include <QtCore/qbytearray.h>
#include <QtCore/qxmlstream.h>
@@ -140,6 +141,8 @@ protected:
const QMetaObject *resolveType(const QByteArray&) const;
+ QDeclarativeBinding::Identifier rewriteBinding(const QString&, const QByteArray&);
+
private:
QList<QDeclarativeError> exceptions;
QDeclarativeCompiler *compiler;
diff --git a/src/declarative/util/qdeclarativepropertychanges.cpp b/src/declarative/util/qdeclarativepropertychanges.cpp
index 8d01b80..400803e 100644
--- a/src/declarative/util/qdeclarativepropertychanges.cpp
+++ b/src/declarative/util/qdeclarativepropertychanges.cpp
@@ -42,6 +42,9 @@
#include "private/qdeclarativepropertychanges_p.h"
#include "private/qdeclarativeopenmetaobject_p.h"
+#include "private/qdeclarativerewrite_p.h"
+#include "private/qdeclarativeengine_p.h"
+#include "private/qdeclarativecompiler_p.h"
#include <qdeclarativeinfo.h>
#include <qdeclarativecustomparser_p.h>
@@ -219,6 +222,7 @@ public:
QList<QPair<QByteArray, QVariant> > properties;
QList<QPair<QByteArray, QDeclarativeExpression *> > expressions;
+ QList<QDeclarativeBinding::Identifier> ids;
QList<QDeclarativeReplaceSignalHandler*> signalReplacements;
QDeclarativeProperty property(const QByteArray &);
@@ -267,6 +271,7 @@ QDeclarativePropertyChangesParser::compile(const QList<QDeclarativeCustomParserP
QDeclarativeParser::Variant v = qvariant_cast<QDeclarativeParser::Variant>(data.at(ii).second);
QVariant var;
bool isScript = v.isScript();
+ QDeclarativeBinding::Identifier id;
switch(v.type()) {
case QDeclarativeParser::Variant::Boolean:
var = QVariant(v.asBoolean());
@@ -280,10 +285,17 @@ QDeclarativePropertyChangesParser::compile(const QList<QDeclarativeCustomParserP
case QDeclarativeParser::Variant::Invalid:
case QDeclarativeParser::Variant::Script:
var = QVariant(v.asScript());
+ {
+ // Pre-rewrite the expression
+ QString expression = v.asScript();
+ id = rewriteBinding(expression, data.at(ii).first); //### recreates the AST, which is slow
+ }
break;
}
ds << data.at(ii).first << isScript << var;
+ if (isScript)
+ ds << id;
}
return rv;
@@ -303,9 +315,12 @@ void QDeclarativePropertyChangesPrivate::decode()
QByteArray name;
bool isScript;
QVariant data;
+ QDeclarativeBinding::Identifier id;
ds >> name;
ds >> isScript;
ds >> data;
+ if (isScript)
+ ds >> id;
QDeclarativeProperty prop = property(name); //### better way to check for signal property?
if (prop.type() & QDeclarativeProperty::SignalProperty) {
@@ -323,6 +338,7 @@ void QDeclarativePropertyChangesPrivate::decode()
if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty())
expression->setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber);
expressions << qMakePair(name, expression);
+ ids << id;
} else {
properties << qMakePair(name, data);
}
@@ -452,10 +468,14 @@ QDeclarativePropertyChanges::ActionList QDeclarativePropertyChanges::actions()
a.toValue = d->expressions.at(ii).second->evaluate();
} else {
QDeclarativeExpression *e = d->expressions.at(ii).second;
- QDeclarativeBinding *newBinding =
- new QDeclarativeBinding(e->expression(), object(), qmlContext(this));
+
+ QDeclarativeBinding::Identifier id = d->ids.at(ii);
+ QDeclarativeBinding *newBinding = QDeclarativeBinding::createBinding(id, object(), qmlContext(this), e->sourceFile(), e->lineNumber());
+ if (!newBinding) {
+ newBinding = new QDeclarativeBinding(e->expression(), object(), qmlContext(this));
+ newBinding->setSourceLocation(e->sourceFile(), e->lineNumber());
+ }
newBinding->setTarget(prop);
- newBinding->setSourceLocation(e->sourceFile(), e->lineNumber());
a.toBinding = newBinding;
a.deletableToBinding = true;
}