aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/qml/qdeclarativecompiler.cpp
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2011-09-05 17:31:41 +1000
committerQt by Nokia <qt-info@nokia.com>2011-09-29 06:12:49 +0200
commit703c808a5649169dd6b9605af273374cd62951d1 (patch)
tree7248cc72bfa632a51c814d6622f0b12a7f2bd443 /src/declarative/qml/qdeclarativecompiler.cpp
parent600e56ad053362dd5d4150f5dec6b93c2fee575b (diff)
Asynchronous component instantiation
This introduces two main: * the QML compiler executes in a separate thread * item instantiation can be interrupted and resumed to allow it to be split across multiple frames. Task-number: QTBUG-21151 Change-Id: I9631c62bb77da3a2e0c37f0da3719533fdce4fef Reviewed-on: http://codereview.qt-project.org/5676 Reviewed-by: Martin Jones <martin.jones@nokia.com>
Diffstat (limited to 'src/declarative/qml/qdeclarativecompiler.cpp')
-rw-r--r--src/declarative/qml/qdeclarativecompiler.cpp162
1 files changed, 111 insertions, 51 deletions
diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp
index fe0375fcff..8c26a3bfa6 100644
--- a/src/declarative/qml/qdeclarativecompiler.cpp
+++ b/src/declarative/qml/qdeclarativecompiler.cpp
@@ -650,7 +650,14 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine,
Q_ASSERT(out);
reset(out);
- output = out;
+ QDeclarativeScript::Object *root = unit->parser().tree();
+ Q_ASSERT(root);
+
+ this->engine = engine;
+ this->enginePrivate = QDeclarativeEnginePrivate::get(engine);
+ this->unit = unit;
+ this->unitRoot = root;
+ this->output = out;
// Compile types
const QList<QDeclarativeTypeData::TypeReference> &resolvedTypes = unit->resolvedTypes();
@@ -673,12 +680,10 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine,
if (ref.type->containsRevisionedAttributes()) {
QDeclarativeError cacheError;
- ref.typePropertyCache =
- QDeclarativeEnginePrivate::get(engine)->cache(ref.type, resolvedTypes.at(ii).minorVersion, cacheError);
-
- if (!ref.typePropertyCache) {
+ ref.typePropertyCache = enginePrivate->cache(ref.type, resolvedTypes.at(ii).minorVersion,
+ cacheError);
+ if (!ref.typePropertyCache)
COMPILE_EXCEPTION(parserRef->refObjects.first(), cacheError.description());
- }
ref.typePropertyCache->addref();
}
@@ -689,13 +694,6 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine,
out->types << ref;
}
- QDeclarativeScript::Object *root = unit->parser().tree();
- Q_ASSERT(root);
-
- this->engine = engine;
- this->enginePrivate = QDeclarativeEnginePrivate::get(engine);
- this->unit = unit;
- this->unitRoot = root;
compileTree(root);
if (!isError()) {
@@ -731,20 +729,12 @@ void QDeclarativeCompiler::compileTree(QDeclarativeScript::Object *tree)
foreach (const QDeclarativeTypeData::ScriptReference &script, unit->resolvedScripts()) {
importedScriptIndexes.append(script.qualifier);
-
- Instruction::StoreImportedScript import;
- import.value = output->scripts.count();
-
- QDeclarativeScriptData *scriptData = script.script->scriptData();
- scriptData->addref();
- output->scripts << scriptData;
- output->addInstruction(import);
}
// We generate the importCache before we build the tree so that
// it can be used in the binding compiler. Given we "expect" the
// QML compilation to succeed, this isn't a waste.
- output->importCache = new QDeclarativeTypeNameCache(engine);
+ output->importCache = new QDeclarativeTypeNameCache();
for (int ii = 0; ii < importedScriptIndexes.count(); ++ii)
output->importCache->add(importedScriptIndexes.at(ii), ii);
unit->imports().populateCache(output->importCache, engine);
@@ -753,15 +743,27 @@ void QDeclarativeCompiler::compileTree(QDeclarativeScript::Object *tree)
return;
Instruction::Init init;
- init.bindingsSize = compileState->bindings.count();
+ init.bindingsSize = compileState->totalBindingsCount;
init.parserStatusSize = compileState->parserStatusCount;
init.contextCache = genContextCache();
+ init.objectStackSize = compileState->objectDepth.maxDepth();
+ init.listStackSize = compileState->listDepth.maxDepth();
if (compileState->compiledBindingData.isEmpty())
init.compiledBinding = -1;
else
init.compiledBinding = output->indexForByteArray(compileState->compiledBindingData);
output->addInstruction(init);
+ foreach (const QDeclarativeTypeData::ScriptReference &script, unit->resolvedScripts()) {
+ Instruction::StoreImportedScript import;
+ import.value = output->scripts.count();
+
+ QDeclarativeScriptData *scriptData = script.script->scriptData();
+ scriptData->addref();
+ output->scripts << scriptData;
+ output->addInstruction(import);
+ }
+
if (!compileState->v8BindingProgram.isEmpty()) {
Instruction::InitV8Bindings bindings;
bindings.program = output->indexForString(compileState->v8BindingProgram);
@@ -805,8 +807,7 @@ bool QDeclarativeCompiler::buildObject(QDeclarativeScript::Object *obj, const Bi
componentStats->componentStat.objects++;
Q_ASSERT (obj->type != -1);
- const QDeclarativeCompiledData::TypeReference &tr =
- output->types.at(obj->type);
+ const QDeclarativeCompiledData::TypeReference &tr = output->types.at(obj->type);
obj->metatype = tr.metaObject();
if (tr.type)
@@ -818,6 +819,20 @@ bool QDeclarativeCompiler::buildObject(QDeclarativeScript::Object *obj, const Bi
return true;
}
+ if (tr.component) {
+ typedef QDeclarativeInstruction I;
+ const I *init = ((const I *)tr.component->bytecode.constData());
+ Q_ASSERT(init && tr.component->instructionType(init) == QDeclarativeInstruction::Init);
+
+ // Adjust stack depths to include nested components
+ compileState->objectDepth.pushPop(init->init.objectStackSize);
+ compileState->listDepth.pushPop(init->init.listStackSize);
+ compileState->parserStatusCount += init->init.parserStatusSize;
+ compileState->totalBindingsCount += init->init.bindingsSize;
+ }
+
+ compileState->objectDepth.push();
+
// Object instantiations reset the binding context
BindingContext objCtxt(obj);
@@ -1006,6 +1021,8 @@ bool QDeclarativeCompiler::buildObject(QDeclarativeScript::Object *obj, const Bi
}
}
+ compileState->objectDepth.pop();
+
return true;
}
@@ -1031,23 +1048,35 @@ void QDeclarativeCompiler::genObject(QDeclarativeScript::Object *obj)
} else {
- Instruction::CreateObject create;
- create.line = obj->location.start.line;
- create.column = obj->location.start.column;
- create.data = -1;
- if (!obj->custom.isEmpty())
- create.data = output->indexForByteArray(obj->custom);
- create.type = obj->type;
- if (!output->types.at(create.type).type &&
- !obj->bindingBitmask.isEmpty()) {
- Q_ASSERT(obj->bindingBitmask.size() % 4 == 0);
- create.bindingBits =
- output->indexForByteArray(obj->bindingBitmask);
+ if (output->types.at(obj->type).type) {
+ Instruction::CreateCppObject create;
+ create.line = obj->location.start.line;
+ create.column = obj->location.start.column;
+ create.data = -1;
+ if (!obj->custom.isEmpty())
+ create.data = output->indexForByteArray(obj->custom);
+ create.type = obj->type;
+ create.isRoot = (compileState->root == obj);
+ output->addInstruction(create);
} else {
- create.bindingBits = -1;
- }
- output->addInstruction(create);
+ Instruction::CreateQMLObject create;
+ create.type = obj->type;
+ create.isRoot = (compileState->root == obj);
+ if (!obj->bindingBitmask.isEmpty()) {
+ Q_ASSERT(obj->bindingBitmask.size() % 4 == 0);
+ create.bindingBits = output->indexForByteArray(obj->bindingBitmask);
+ } else {
+ create.bindingBits = -1;
+ }
+ output->addInstruction(create);
+
+ Instruction::CompleteQMLObject complete;
+ complete.line = obj->location.start.line;
+ complete.column = obj->location.start.column;
+ complete.isRoot = (compileState->root == obj);
+ output->addInstruction(complete);
+ }
}
// Setup the synthesized meta object if necessary
@@ -1132,12 +1161,13 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeScript::Object *obj)
int deferIdx = output->addInstruction(defer);
int nextInstructionIndex = output->nextInstructionIndex();
- Instruction::Init init;
- init.bindingsSize = compileState->bindings.count(); // XXX - bigger than necessary
- init.parserStatusSize = compileState->parserStatusCount; // XXX - bigger than necessary
- init.contextCache = -1;
- init.compiledBinding = -1;
- output->addInstruction(init);
+ Instruction::DeferInit dinit;
+ // XXX - these are now massive over allocations
+ dinit.bindingsSize = compileState->totalBindingsCount;
+ dinit.parserStatusSize = compileState->parserStatusCount;
+ dinit.objectStackSize = compileState->objectDepth.maxDepth();
+ dinit.listStackSize = compileState->listDepth.maxDepth();
+ output->addInstruction(dinit);
for (Property *prop = obj->valueProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
if (!prop->isDeferred)
@@ -1269,6 +1299,7 @@ void QDeclarativeCompiler::genComponent(QDeclarativeScript::Object *obj)
create.line = root->location.start.line;
create.column = root->location.start.column;
create.endLine = root->location.end.line;
+ create.isRoot = (compileState->root == obj);
int createInstruction = output->addInstruction(create);
int nextInstructionIndex = output->nextInstructionIndex();
@@ -1276,9 +1307,11 @@ void QDeclarativeCompiler::genComponent(QDeclarativeScript::Object *obj)
compileState = componentState(root);
Instruction::Init init;
- init.bindingsSize = compileState->bindings.count();
+ init.bindingsSize = compileState->totalBindingsCount;
init.parserStatusSize = compileState->parserStatusCount;
init.contextCache = genContextCache();
+ init.objectStackSize = compileState->objectDepth.maxDepth();
+ init.listStackSize = compileState->listDepth.maxDepth();
if (compileState->compiledBindingData.isEmpty())
init.compiledBinding = -1;
else
@@ -1325,6 +1358,8 @@ bool QDeclarativeCompiler::buildComponent(QDeclarativeScript::Object *obj,
// The special "Component" element can only have the id property and a
// default property, that actually defines the component's tree
+ compileState->objectDepth.push();
+
// Find, check and set the "id" property (if any)
Property *idProp = 0;
if (obj->properties.isMany() ||
@@ -1371,6 +1406,8 @@ bool QDeclarativeCompiler::buildComponent(QDeclarativeScript::Object *obj,
// Build the component tree
COMPILE_CHECK(buildComponentFromRoot(root, ctxt));
+ compileState->objectDepth.pop();
+
return true;
}
@@ -1849,6 +1886,7 @@ bool QDeclarativeCompiler::buildIdProperty(QDeclarativeScript::Property *prop,
void QDeclarativeCompiler::addId(const QString &id, QDeclarativeScript::Object *obj)
{
+ Q_UNUSED(id);
Q_ASSERT(!compileState->ids.value(id));
Q_ASSERT(obj->id == id);
obj->idIndex = compileState->ids.count();
@@ -1859,6 +1897,7 @@ void QDeclarativeCompiler::addBindingReference(BindingReference *ref)
{
Q_ASSERT(ref->value && !ref->value->bindingReference);
ref->value->bindingReference = ref;
+ compileState->totalBindingsCount++;
compileState->bindings.prepend(ref);
}
@@ -1892,10 +1931,14 @@ bool QDeclarativeCompiler::buildAttachedProperty(QDeclarativeScript::Property *p
Q_ASSERT(prop->value);
Q_ASSERT(prop->index != -1); // This is set in buildProperty()
+ compileState->objectDepth.push();
+
obj->addAttachedProperty(prop);
COMPILE_CHECK(buildSubObject(prop->value, ctxt.incr()));
+ compileState->objectDepth.pop();
+
return true;
}
@@ -1953,7 +1996,11 @@ bool QDeclarativeCompiler::buildGroupedProperty(QDeclarativeScript::Property *pr
obj->addGroupedProperty(prop);
+ compileState->objectDepth.push();
+
COMPILE_CHECK(buildSubObject(prop->value, ctxt.incr()));
+
+ compileState->objectDepth.pop();
}
return true;
@@ -1964,6 +2011,8 @@ bool QDeclarativeCompiler::buildValueTypeProperty(QObject *type,
QDeclarativeScript::Object *baseObj,
const BindingContext &ctxt)
{
+ compileState->objectDepth.push();
+
if (obj->defaultProperty)
COMPILE_EXCEPTION(obj, tr("Invalid property use"));
obj->metatype = type->metaObject();
@@ -2026,6 +2075,8 @@ bool QDeclarativeCompiler::buildValueTypeProperty(QObject *type,
obj->addValueProperty(prop);
}
+ compileState->objectDepth.pop();
+
return true;
}
@@ -2038,6 +2089,8 @@ bool QDeclarativeCompiler::buildListProperty(QDeclarativeScript::Property *prop,
{
Q_ASSERT(prop->core.isQList());
+ compileState->listDepth.push();
+
int t = prop->type;
obj->addValueProperty(prop);
@@ -2071,6 +2124,8 @@ bool QDeclarativeCompiler::buildListProperty(QDeclarativeScript::Property *prop,
}
}
+ compileState->listDepth.pop();
+
return true;
}
@@ -2408,7 +2463,6 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeScript::Object *obj)
QHashField methodNames;
// Check properties
- int dpCount = obj->dynamicProperties.count();
for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
const QDeclarativeScript::Object::DynamicProperty &prop = *p;
@@ -2983,7 +3037,7 @@ bool QDeclarativeCompiler::compileAlias(QFastMetaBuilder &builder,
// update the property type
type = aliasProperty.type();
- if (type >= QVariant::UserType)
+ if (type >= (int)QVariant::UserType)
type = 0;
}
@@ -3070,6 +3124,7 @@ void QDeclarativeCompiler::genBindingAssignment(QDeclarativeScript::Value *bindi
((prop->index & 0xFF) << 24);
else
store.property = prop->index;
+ store.isRoot = (compileState->root == obj);
store.line = binding->location.start.line;
output->addInstruction(store);
} else if (ref.dataType == BindingReference::V8) {
@@ -3077,6 +3132,7 @@ void QDeclarativeCompiler::genBindingAssignment(QDeclarativeScript::Value *bindi
store.value = ref.compiledIndex;
store.context = ref.bindingContext.stack;
store.owner = ref.bindingContext.owner;
+ store.isRoot = (compileState->root == obj);
store.line = binding->location.start.line;
Q_ASSERT(ref.bindingContext.owner == 0 ||
@@ -3093,6 +3149,7 @@ void QDeclarativeCompiler::genBindingAssignment(QDeclarativeScript::Value *bindi
store.assignBinding.value = output->indexForString(ref.rewrittenExpression);
store.assignBinding.context = ref.bindingContext.stack;
store.assignBinding.owner = ref.bindingContext.owner;
+ store.assignBinding.isRoot = (compileState->root == obj);
store.assignBinding.line = binding->location.start.line;
Q_ASSERT(ref.bindingContext.owner == 0 ||
@@ -3241,6 +3298,10 @@ bool QDeclarativeCompiler::completeComponentBuild()
if (bindingCompiler.isValid())
compileState->compiledBindingData = bindingCompiler.program();
+ // Check pop()'s matched push()'s
+ Q_ASSERT(compileState->objectDepth.depth() == 0);
+ Q_ASSERT(compileState->listDepth.depth() == 0);
+
saveComponentState();
return true;
@@ -3302,8 +3363,7 @@ void QDeclarativeCompiler::dumpStats()
*/
bool QDeclarativeCompiler::canCoerce(int to, QDeclarativeScript::Object *from)
{
- const QMetaObject *toMo =
- enginePrivate->rawMetaObjectForType(to);
+ const QMetaObject *toMo = enginePrivate->rawMetaObjectForType(to);
const QMetaObject *fromMo = from->metaObject();
while (fromMo) {