From 34c85bb56c92316a6ce1c79d25f9653fec14791c Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 24 Oct 2013 14:51:02 +0200 Subject: 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 --- src/qml/qml/qqmlcompiler.cpp | 60 ++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 24 deletions(-) (limited to 'src/qml/qml/qqmlcompiler.cpp') 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 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 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::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]; } } -- cgit v1.2.3