diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2013-10-24 14:51:02 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-10-31 10:50:38 +0100 |
commit | 34c85bb56c92316a6ce1c79d25f9653fec14791c (patch) | |
tree | 6d3d43de33fa53a1353c52506e989ae126f1361b /src/qml/qml | |
parent | bb7d26ebb0c2e7a9f06a030be8bfcd00e346e06f (diff) |
Initial support for resolving meta-property access for the scope and context objects at QML compile time
This avoids having to do a string lookup for ids and in the import cache at
run-time, before we can do a string hash lookup in the property cache. Instead
we resolve final properties in the context and scope object at compile time and
look them up at run-time using their index instead. The dependencies to these
properties are also tracked separately and recorded in the compiled data.
This is merely the initial patch. There's a lot left to do, such as having
specialized getter and setters for specific property types. Setters are missing
altogether right now and will fall back to name lookup.
Change-Id: If3cb4e7c9454ef4850a615f0935b311c9395b165
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/qml')
-rw-r--r-- | src/qml/qml/qqmlcompiler.cpp | 60 | ||||
-rw-r--r-- | src/qml/qml/qqmlcompiler_p.h | 11 | ||||
-rw-r--r-- | src/qml/qml/qqmlcontextwrapper.cpp | 25 | ||||
-rw-r--r-- | src/qml/qml/qqmlscript_p.h | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 6 |
5 files changed, 69 insertions, 34 deletions
diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp index 58495bb1bf..3f57d7c2ef 100644 --- a/src/qml/qml/qqmlcompiler.cpp +++ b/src/qml/qml/qqmlcompiler.cpp @@ -1336,7 +1336,7 @@ void QQmlCompiler::genObjectBody(QQmlScript::Object *obj) } else if (v->type == Value::SignalExpression) { Instruction::StoreSignal store; - store.runtimeFunctionIndex = compileState->runtimeFunctionIndices.at(v->signalData.functionIndex); + store.runtimeFunctionIndex = compileState->jsCompileData[v->signalData.signalScopeObject].runtimeFunctionIndices.at(v->signalData.functionIndex); store.handlerName = output->indexForString(prop->name().toString()); store.parameters = output->indexForString(obj->metatype->signalParameterStringForJS(prop->index)); store.signalIndex = prop->index; @@ -1738,12 +1738,15 @@ bool QQmlCompiler::buildSignal(QQmlScript::Property *prop, QQmlScript::Object *o //to ensure all parameters are available (see qqmlboundsignal constructor for more details) prop->index = obj->metatype->originalClone(prop->index); prop->values.first()->signalData.signalExpressionContextStack = ctxt.stack; + prop->values.first()->signalData.signalScopeObject = ctxt.object; QList<QByteArray> parameters = obj->metatype->signalParameterNames(prop->index); AST::FunctionDeclaration *funcDecl = convertSignalHandlerExpressionToFunctionDeclaration(unit->parser().jsEngine(), prop->values.first()->value.asAST(), propName.toString(), parameters); - compileState->functionsToCompile.append(funcDecl); - prop->values.first()->signalData.functionIndex = compileState->functionsToCompile.count() - 1; + + ComponentCompileState::PerObjectCompileData *cd = &compileState->jsCompileData[ctxt.object]; + cd->functionsToCompile.append(funcDecl); + prop->values.first()->signalData.functionIndex = cd->functionsToCompile.count() - 1; QString errorString; obj->metatype->signalParameterStringForJS(prop->index, &errorString); @@ -3250,12 +3253,13 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod vmd->methodCount++; md = methodData; - QQmlCompilerTypes::ComponentCompileState::CompiledMetaMethod cmm; - cmm.obj = obj; + ComponentCompileState::PerObjectCompileData *cd = &compileState->jsCompileData[obj]; + + ComponentCompileState::CompiledMetaMethod cmm; cmm.methodIndex = vmd->methodCount - 1; - compileState->functionsToCompile.append(s->funcDecl); - cmm.compiledFunctionIndex = compileState->functionsToCompile.count() - 1; - compileState->compiledMetaMethods.append(cmm); + cd->functionsToCompile.append(s->funcDecl); + cmm.compiledFunctionIndex = cd->functionsToCompile.count() - 1; + cd->compiledMetaMethods.append(cmm); } if (aliasCount) @@ -3641,18 +3645,19 @@ bool QQmlCompiler::completeComponentBuild() node = new (pool) AST::ExpressionStatement(expr); } - compileState->functionsToCompile.append(node); - binding.compiledIndex = compileState->functionsToCompile.count() - 1; + ComponentCompileState::PerObjectCompileData *cd = &compileState->jsCompileData[b->bindingContext.object]; + cd->functionsToCompile.append(node); + binding.compiledIndex = cd->functionsToCompile.count() - 1; if (componentStats) componentStats->componentStat.scriptBindings.append(b->value->location); } - if (!compileState->functionsToCompile.isEmpty()) { + if (!compileState->jsCompileData.isEmpty()) { const QString &sourceCode = jsEngine->code(); AST::UiProgram *qmlRoot = parser.qmlRoot(); - JSCodeGen jsCodeGen(unit->finalUrlString(), sourceCode, jsModule.data(), jsEngine, qmlRoot); + JSCodeGen jsCodeGen(unit->finalUrlString(), sourceCode, jsModule.data(), jsEngine, qmlRoot, output->importCache); JSCodeGen::ObjectIdMapping idMapping; if (compileState->ids.count() > 0) { @@ -3665,21 +3670,28 @@ bool QQmlCompiler::completeComponentBuild() } } - const QVector<int> runtimeFunctionIndices = jsCodeGen.generateJSCodeForFunctionsAndBindings(compileState->root->astNode, - compileState->functionsToCompile, - idMapping); - compileState->runtimeFunctionIndices = runtimeFunctionIndices; + jsCodeGen.beginContextScope(idMapping, compileState->root->metatype); - for (JSBindingReference *b = compileState->bindings.first(); b; b = b->nextReference) { - JSBindingReference &binding = *b; - binding.compiledIndex = runtimeFunctionIndices[binding.compiledIndex]; + for (QHash<QQmlScript::Object *, ComponentCompileState::PerObjectCompileData>::Iterator it = compileState->jsCompileData.begin(); + it != compileState->jsCompileData.end(); ++it) { + QQmlScript::Object *scopeObject = it.key(); + ComponentCompileState::PerObjectCompileData *cd = &it.value(); + + jsCodeGen.beginObjectScope(scopeObject->metatype); + + cd->runtimeFunctionIndices = jsCodeGen.generateJSCodeForFunctionsAndBindings(cd->functionsToCompile); + + foreach (const QQmlCompilerTypes::ComponentCompileState::CompiledMetaMethod &cmm, cd->compiledMetaMethods) { + typedef QQmlVMEMetaData VMD; + VMD *vmd = (QQmlVMEMetaData *)scopeObject->synthdata.data(); + VMD::MethodData &md = *(vmd->methodData() + cmm.methodIndex); + md.runtimeFunctionIndex = cd->runtimeFunctionIndices.at(cmm.compiledFunctionIndex); + } } - foreach (const QQmlCompilerTypes::ComponentCompileState::CompiledMetaMethod &cmm, compileState->compiledMetaMethods) { - typedef QQmlVMEMetaData VMD; - VMD *vmd = (QQmlVMEMetaData *)cmm.obj->synthdata.data(); - VMD::MethodData &md = *(vmd->methodData() + cmm.methodIndex); - md.runtimeFunctionIndex = runtimeFunctionIndices.at(cmm.compiledFunctionIndex); + for (JSBindingReference *b = compileState->bindings.first(); b; b = b->nextReference) { + JSBindingReference &binding = *b; + binding.compiledIndex = compileState->jsCompileData[binding.bindingContext.object].runtimeFunctionIndices[binding.compiledIndex]; } } diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h index 142d8c68b1..2e3e6b8f4c 100644 --- a/src/qml/qml/qqmlcompiler_p.h +++ b/src/qml/qml/qqmlcompiler_p.h @@ -302,16 +302,21 @@ namespace QQmlCompilerTypes { typedef QFieldList<O, &O::nextAliasingObject> AliasingObjectsList; AliasingObjectsList aliasingObjects; QQmlScript::Object *root; - QList<QQmlJS::AST::Node*> functionsToCompile; - QVector<int> runtimeFunctionIndices; struct CompiledMetaMethod { - QQmlScript::Object *obj; int methodIndex; int compiledFunctionIndex; // index in functionToCompile }; + QList<CompiledMetaMethod> compiledMetaMethods; + struct PerObjectCompileData + { + QList<QQmlJS::AST::Node*> functionsToCompile; + QVector<int> runtimeFunctionIndices; + QVector<CompiledMetaMethod> compiledMetaMethods; + }; + QHash<QQmlScript::Object *, PerObjectCompileData> jsCompileData; }; }; diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp index 5e798e20ee..832d9421c2 100644 --- a/src/qml/qml/qqmlcontextwrapper.cpp +++ b/src/qml/qml/qqmlcontextwrapper.cpp @@ -374,10 +374,27 @@ void QmlContextWrapper::registerQmlDependencies(ExecutionEngine *engine, const C QV4::Scoped<QmlContextWrapper> contextWrapper(scope, engine->qmlContextObject()->getPointer()->as<QmlContextWrapper>()); QQmlContextData *qmlContext = contextWrapper->getContext(); - const quint32 *dependency = compiledFunction->qmlIdObjectDependencyTable(); - const int dependencyCount = compiledFunction->nDependingIdObjects; - for (int i = 0; i < dependencyCount; ++i, ++dependency) - capture->captureProperty(&qmlContext->idValues[*dependency].bindings); + const quint32 *idObjectDependency = compiledFunction->qmlIdObjectDependencyTable(); + const int idObjectDependencyCount = compiledFunction->nDependingIdObjects; + for (int i = 0; i < idObjectDependencyCount; ++i, ++idObjectDependency) + capture->captureProperty(&qmlContext->idValues[*idObjectDependency].bindings); + + const quint32 *contextPropertyDependency = compiledFunction->qmlContextPropertiesDependencyTable(); + const int contextPropertyDependencyCount = compiledFunction->nDependingContextProperties; + for (int i = 0; i < contextPropertyDependencyCount; ++i) { + const int propertyIndex = *contextPropertyDependency++; + const int notifyIndex = *contextPropertyDependency++; + capture->captureProperty(qmlContext->contextObject, propertyIndex, notifyIndex); + } + + QObject *scopeObject = contextWrapper->getScopeObject(); + const quint32 *scopePropertyDependency = compiledFunction->qmlScopePropertiesDependencyTable(); + const int scopePropertyDependencyCount = compiledFunction->nDependingScopeProperties; + for (int i = 0; i < scopePropertyDependencyCount; ++i) { + const int propertyIndex = *scopePropertyDependency++; + const int notifyIndex = *scopePropertyDependency++; + capture->captureProperty(scopeObject, propertyIndex, notifyIndex); + } } diff --git a/src/qml/qml/qqmlscript_p.h b/src/qml/qml/qqmlscript_p.h index b36fdc8861..fac31add5c 100644 --- a/src/qml/qml/qqmlscript_p.h +++ b/src/qml/qml/qqmlscript_p.h @@ -229,6 +229,7 @@ public: // Used by compiler struct SignalData { int signalExpressionContextStack; + Object *signalScopeObject; int functionIndex; // before gen() index in functionsToCompile, then index in runtime functions }; union { diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 6f718e5b5b..b3bc5eb4a1 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2357,8 +2357,8 @@ void QQmlTypeData::compile() // Compile JS binding expressions and signal handlers - JSCodeGen jsCodeGen(finalUrlString(), parsedQML->code, &parsedQML->jsModule, &parsedQML->jsParserEngine, parsedQML->program); - const QVector<int> runtimeFunctionIndices = jsCodeGen.generateJSCodeForFunctionsAndBindings(/*### context root*/0, parsedQML->functions); + JSCodeGen jsCodeGen(finalUrlString(), parsedQML->code, &parsedQML->jsModule, &parsedQML->jsParserEngine, parsedQML->program, m_compiledData->importCache); + const QVector<int> runtimeFunctionIndices = jsCodeGen.generateJSCodeForFunctionsAndBindings(parsedQML->functions); QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_typeLoader->engine()); @@ -2920,7 +2920,7 @@ void QQmlScriptBlob::done() QList<QQmlError> errors; QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_typeLoader->engine()); - m_scriptData->m_precompiledScript = QV4::Script::precompile(v4, m_scriptData->url, m_source, /*parseAsBinding*/true, &errors); + m_scriptData->m_precompiledScript = QV4::Script::precompile(v4, m_scriptData->url, m_source, &errors); if (m_scriptData->m_precompiledScript) m_scriptData->m_precompiledScript->ref(); m_source.clear(); |