aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-10-24 14:51:02 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-10-31 10:50:38 +0100
commit34c85bb56c92316a6ce1c79d25f9653fec14791c (patch)
tree6d3d43de33fa53a1353c52506e989ae126f1361b /src/qml/qml
parentbb7d26ebb0c2e7a9f06a030be8bfcd00e346e06f (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.cpp60
-rw-r--r--src/qml/qml/qqmlcompiler_p.h11
-rw-r--r--src/qml/qml/qqmlcontextwrapper.cpp25
-rw-r--r--src/qml/qml/qqmlscript_p.h1
-rw-r--r--src/qml/qml/qqmltypeloader.cpp6
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();