aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-11-27 13:46:58 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-11-29 19:11:02 +0100
commit0aadcf8077840068eb182269e9ed9c31ad12f45e (patch)
tree83eb200fc92ec32916c9ed88a1428cef8b00700d /src/qml/qml
parentdd1bd3b01b506a05b475514fb2ba7e387f7b17fa (diff)
Add support pre-compiled bindings for QML custom parsers
For example the x property in PropertyChanges { target: foo x: someItem.x - other.width / 2 } was compiled at run-time dynamically, which produces slower code (no type information available) and slows down the type instantiation, because the compilation happens every time at instantiation time (or later). With this change, when the custom parser behind PropertyChanges requests a binding ID for "x", the right hand side will be added to the bindings to compile, then compiled and later at run-time the QQmlBinding constructor that takes a QQmlBinding::Identifier can retrieve the correct compiled function from the QV4::CompiledData::CompilationUnit. Change-Id: I857fb2d39e82714b225bc9394b9904b795c6662b Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/qqmlbinding.cpp10
-rw-r--r--src/qml/qml/qqmlcompiler.cpp25
-rw-r--r--src/qml/qml/qqmlcompiler_p.h5
-rw-r--r--src/qml/qml/qqmlcustomparser.cpp3
4 files changed, 35 insertions, 8 deletions
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 557267d808..9e2fb07066 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -50,6 +50,7 @@
#include <private/qqmltrace_p.h>
#include <private/qqmlexpression_p.h>
#include <private/qqmlscriptstring_p.h>
+#include <private/qqmlcontextwrapper_p.h>
#include <QVariant>
#include <QtCore/qdebug.h>
@@ -85,7 +86,14 @@ QQmlBinding::createBinding(Identifier id, QObject *obj, QQmlContext *ctxt,
Q_ASSERT(typeData);
if (QQmlCompiledData *cdata = typeData->compiledData()) {
- rv = new QQmlBinding(cdata->primitives.at(id), obj, ctxtdata, url, lineNumber, 0);
+ QV4::ExecutionEngine *v4 = engine->v4engine();
+ QV4::Scope valueScope(v4);
+ QV4::ScopedObject scopeObject(valueScope, QV4::QmlContextWrapper::qmlScope(v4->v8Engine, ctxtdata, obj));
+ QV4::Scoped<QV4::QmlBindingWrapper> wrapper(valueScope, new (v4->memoryManager) QV4::QmlBindingWrapper(v4->rootContext, scopeObject));
+ QV4::ExecutionContext *qmlContext = wrapper->context();
+ QV4::Function *runtimeFunction = cdata->compilationUnit->runtimeFunctions[cdata->customParserBindings[id]];
+ QV4::ScopedValue function(valueScope, QV4::FunctionObject::creatScriptFunction(qmlContext, runtimeFunction));
+ rv = new QQmlBinding(function, obj, ctxtdata, url, lineNumber, 0);
}
typeData->release();
diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp
index 54fd002f7b..150ea549be 100644
--- a/src/qml/qml/qqmlcompiler.cpp
+++ b/src/qml/qml/qqmlcompiler.cpp
@@ -2682,9 +2682,24 @@ const QMetaObject *QQmlCompiler::resolveType(const QString& name) const
return qmltype->metaObject();
}
-int QQmlCompiler::bindingIdentifier(const Variant &value)
+int QQmlCompiler::bindingIdentifier(const QString &name, const Variant &value, const BindingContext &ctxt)
{
- return output->indexForString(value.asScript());
+ JSBindingReference *reference = pool->New<JSBindingReference>();
+ reference->expression = value;
+ reference->property = pool->New<Property>();
+ reference->property->setName(name);
+ reference->value = 0;
+ reference->bindingContext = ctxt;
+ reference->bindingContext.owner++;
+
+ const int id = output->customParserBindings.count();
+ output->customParserBindings.append(0); // Filled in later.
+ reference->customParserBindingsIndex = id;
+
+ compileState->totalBindingsCount++;
+ compileState->bindings.prepend(reference);
+
+ return id;
}
// Ensures that the dynamic meta specification on obj is valid
@@ -3648,7 +3663,7 @@ bool QQmlCompiler::completeComponentBuild()
binding.compiledIndex = cd->functionsToCompile.count() - 1;
cd->expressionNames.insert(binding.compiledIndex, binding.property->name().toString().prepend(QStringLiteral("expression for ")));
- if (componentStats)
+ if (componentStats && b->value)
componentStats->componentStat.scriptBindings.append(b->value->location);
}
@@ -3697,6 +3712,10 @@ bool QQmlCompiler::completeComponentBuild()
for (JSBindingReference *b = compileState->bindings.first(); b; b = b->nextReference) {
JSBindingReference &binding = *b;
binding.compiledIndex = compileState->jsCompileData[binding.bindingContext.object].runtimeFunctionIndices[binding.compiledIndex];
+ if (!binding.value) { // Must be a binding requested from custom parser
+ Q_ASSERT(binding.customParserBindingsIndex >= 0 && binding.customParserBindingsIndex < output->customParserBindings.count());
+ output->customParserBindings[binding.customParserBindingsIndex] = binding.compiledIndex;
+ }
}
}
diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h
index 05c877d98b..443a80d95c 100644
--- a/src/qml/qml/qqmlcompiler_p.h
+++ b/src/qml/qml/qqmlcompiler_p.h
@@ -150,6 +150,7 @@ public:
// index in first hash is component index, hash inside maps from object index in that scope to integer id
QHash<int, QHash<int, int> > objectIndexToIdPerComponent;
QHash<int, int> objectIndexToIdForRoot;
+ QVector<int> customParserBindings; // index is binding identifier, value is compiled function index.
bool isComponent(int objectIndex) const { return objectIndexToIdPerComponent.contains(objectIndex); }
bool isCompositeType() const { return !datas.at(qmlUnit->indexOfRootObject).isEmpty(); }
@@ -231,7 +232,7 @@ namespace QQmlCompilerTypes {
QQmlScript::Value *value;
int compiledIndex : 16;
- int sharedIndex : 16;
+ int customParserBindingsIndex : 16;
BindingContext bindingContext;
@@ -340,7 +341,7 @@ public:
int evaluateEnum(const QHashedStringRef &scope, const QByteArray& enumValue, bool *ok) const; // for QQmlCustomParser::evaluateEnum
const QMetaObject *resolveType(const QString& name) const; // for QQmlCustomParser::resolveType
- int bindingIdentifier(const QQmlScript::Variant& value); // for QQmlCustomParser::bindingIndex
+ int bindingIdentifier(const QString &name, const QQmlScript::Variant& value, const QQmlCompilerTypes::BindingContext &ctxt); // for QQmlCustomParser::bindingIndex
private:
typedef QQmlCompiledData::Instruction Instruction;
diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp
index eba2e14e51..19e49009ce 100644
--- a/src/qml/qml/qqmlcustomparser.cpp
+++ b/src/qml/qml/qqmlcustomparser.cpp
@@ -313,8 +313,7 @@ const QMetaObject *QQmlCustomParser::resolveType(const QString& name) const
*/
QQmlBinding::Identifier QQmlCustomParser::bindingIdentifier(const QQmlScript::Variant &value, const QString& name)
{
- Q_UNUSED(name);
- return compiler->bindingIdentifier(value);
+ return compiler->bindingIdentifier(name, value, QQmlCompilerTypes::BindingContext(object));
}
QT_END_NAMESPACE