diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2013-11-27 13:46:58 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-11-29 19:11:02 +0100 |
commit | 0aadcf8077840068eb182269e9ed9c31ad12f45e (patch) | |
tree | 83eb200fc92ec32916c9ed88a1428cef8b00700d /src/qml/qml | |
parent | dd1bd3b01b506a05b475514fb2ba7e387f7b17fa (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.cpp | 10 | ||||
-rw-r--r-- | src/qml/qml/qqmlcompiler.cpp | 25 | ||||
-rw-r--r-- | src/qml/qml/qqmlcompiler_p.h | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmlcustomparser.cpp | 3 |
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 |