From c8f180e7023308b8a051b53943b9a088a7f0c427 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 27 May 2009 20:40:28 +1000 Subject: Small cleanups --- src/declarative/qml/qmlcompiler.cpp | 175 +++++++++++++++----------------- src/declarative/qml/qmlcompiler_p.h | 26 ++++- src/declarative/qml/qmlscriptparser.cpp | 34 +++++-- src/declarative/qml/qmlscriptparser_p.h | 2 + 4 files changed, 132 insertions(+), 105 deletions(-) diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 09f4e0b..b9a848a 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -62,6 +62,7 @@ #include "private/qmlcustomparser_p_p.h" #include #include +#include "parser/javascriptast_p.h" #include "qmlscriptparser_p.h" @@ -516,6 +517,7 @@ bool QmlCompiler::compile(QmlEngine *engine, } output = 0; + return !isError(); } @@ -542,7 +544,7 @@ void QmlCompiler::compileTree(Object *tree) def.type = QmlInstruction::SetDefault; output->bytecode << def; - optimizeExpressions(0, output->bytecode.count() - 1, 0); + finalizeComponent(0); } bool QmlCompiler::compileObject(Object *obj, int ctxt) @@ -588,6 +590,8 @@ bool QmlCompiler::compileObject(Object *obj, int ctxt) begin.begin.castValue = parserStatusCast; begin.line = obj->location.start.line; output->bytecode << begin; + + compileState.parserStatusCount++; } // Check if this is a custom parser type. Custom parser types allow @@ -688,9 +692,14 @@ bool QmlCompiler::compileComponent(Object *obj, int ctxt) if (!isValidId(val)) COMPILE_EXCEPTION("Invalid id property value"); - if (ids.contains(val)) + if (compileState.ids.contains(val)) COMPILE_EXCEPTION("id is not unique"); - ids.insert(val); + + IdReference reference; + reference.id = val; + reference.object = obj; + reference.instructionIdx = output->bytecode.count(); + compileState.ids.insert(val, reference); int pref = output->indexForString(val); QmlInstruction id; @@ -699,8 +708,6 @@ bool QmlCompiler::compileComponent(Object *obj, int ctxt) id.setId.value = pref; id.setId.save = -1; - savedTypes.insert(output->bytecode.count(), -1); - output->bytecode << id; } @@ -724,16 +731,16 @@ bool QmlCompiler::compileComponentFromRoot(Object *obj, int ctxt) init.line = obj->location.start.line; output->bytecode << init; - QSet oldIds = ids; - ids.clear(); + ComponentCompileState oldComponentCompileState = compileState; + compileState = ComponentCompileState(); if (obj) COMPILE_CHECK(compileObject(obj, ctxt)); create.createComponent.count = output->bytecode.count() - count; - int inc = optimizeExpressions(count, count - 1 + create.createComponent.count, count); + int inc = finalizeComponent(count); create.createComponent.count += inc; - ids = oldIds; + compileState = oldComponentCompileState; return true; } @@ -950,41 +957,43 @@ bool QmlCompiler::compileIdProperty(QmlParser::Property *prop, if (prop->values.count() > 1) COMPILE_EXCEPTION2(prop, "The object id may only be set once"); - if (prop->values.count() == 1) { - if (prop->values.at(0)->object) - COMPILE_EXCEPTION("Cannot assign an object as an id"); - QString val = prop->values.at(0)->primitive(); - if (!isValidId(val)) - COMPILE_EXCEPTION(val << "is not a valid id"); - if (ids.contains(val)) - COMPILE_EXCEPTION("id is not unique"); - ids.insert(val); + if (prop->values.at(0)->object) + COMPILE_EXCEPTION("Cannot assign an object as an id"); + QString val = prop->values.at(0)->primitive(); + if (!isValidId(val)) + COMPILE_EXCEPTION(val << "is not a valid id"); + if (compileState.ids.contains(val)) + COMPILE_EXCEPTION("id is not unique"); - int pref = output->indexForString(val); + int pref = output->indexForString(val); - if (prop->type == QVariant::String) { - QmlInstruction assign; - assign.type = QmlInstruction::StoreString; - assign.storeString.propertyIndex = prop->index; - assign.storeString.value = pref; - assign.line = prop->values.at(0)->location.start.line; - output->bytecode << assign; + if (prop->type == QVariant::String) { + QmlInstruction assign; + assign.type = QmlInstruction::StoreString; + assign.storeString.propertyIndex = prop->index; + assign.storeString.value = pref; + assign.line = prop->values.at(0)->location.start.line; + output->bytecode << assign; - prop->values.at(0)->type = Value::Id; - } else { - prop->values.at(0)->type = Value::Literal; - } + prop->values.at(0)->type = Value::Id; + } else { + prop->values.at(0)->type = Value::Literal; + } - QmlInstruction id; - id.type = QmlInstruction::SetId; - id.line = prop->values.at(0)->location.start.line; - id.setId.value = pref; - id.setId.save = -1; - savedTypes.insert(output->bytecode.count(), obj->type); - output->bytecode << id; + IdReference reference; + reference.id = val; + reference.object = obj; + reference.instructionIdx = output->bytecode.count(); + compileState.ids.insert(val, reference); - obj->id = val.toLatin1(); - } + QmlInstruction id; + id.type = QmlInstruction::SetId; + id.line = prop->values.at(0)->location.start.line; + id.setId.value = pref; + id.setId.save = -1; + output->bytecode << id; + + obj->id = val.toLatin1(); return true; } @@ -1116,7 +1125,7 @@ bool QmlCompiler::compileListProperty(QmlParser::Property *prop, COMPILE_EXCEPTION("Can only assign one binding to lists"); assignedBinding = true; - COMPILE_CHECK(compileBinding(v->value.asScript(), prop, ctxt, + COMPILE_CHECK(compileBinding(v->value, prop, ctxt, obj->metaObject(), v->location.start.line)); v->type = Value::PropertyBinding; @@ -1287,7 +1296,7 @@ bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop, if (v->value.isScript()) { - COMPILE_CHECK(compileBinding(v->value.asScript(), prop, ctxt, + COMPILE_CHECK(compileBinding(v->value, prop, ctxt, obj->metaObject(), v->location.start.line)); @@ -1394,7 +1403,8 @@ bool QmlCompiler::compileDynamicMeta(QmlParser::Object *obj) return true; } -bool QmlCompiler::compileBinding(const QString &bind, QmlParser::Property *prop, +bool QmlCompiler::compileBinding(const QmlParser::Variant &bind, + QmlParser::Property *prop, int ctxt, const QMetaObject *mo, qint64 line) { Q_ASSERT(mo); @@ -1405,13 +1415,13 @@ bool QmlCompiler::compileBinding(const QString &bind, QmlParser::Property *prop, COMPILE_EXCEPTION2(prop, "Cannot assign binding to read-only property"); QmlBasicScript bs; - bs.compile(bind.toLatin1()); + bs.compile(bind.asScript().toLatin1()); int bref; if (bs.isValid()) { bref = output->indexForByteArray(QByteArray(bs.compileData(), bs.compileDataSize())); } else { - bref = output->indexForString(bind); + bref = output->indexForString(bind.asScript()); } QmlInstruction assign; @@ -1426,49 +1436,28 @@ bool QmlCompiler::compileBinding(const QString &bind, QmlParser::Property *prop, assign.assignBinding.property = prop->index; assign.assignBinding.value = bref; assign.assignBinding.category = QmlMetaProperty::propertyCategory(mp); - savedTypes.insert(output->bytecode.count(), prop->type); + BindingReference reference; + reference.expression = bind; + reference.property = prop; + reference.instructionIdx = output->bytecode.count(); + compileState.bindings << reference; + output->bytecode << assign; return true; } -int QmlCompiler::optimizeExpressions(int start, int end, int patch) +// Update the init instruction with final data, and optimize some simple +// bindings +int QmlCompiler::finalizeComponent(int patch) { - QHash ids; int saveCount = 0; int newInstrs = 0; - int bindingsCount = 0; - int parserStatusCount = 0; - for (int ii = start; ii <= end; ++ii) { - const QmlInstruction &instr = output->bytecode.at(ii); - - if (instr.type == QmlInstruction::CreateComponent) { - ii += instr.createComponent.count - 1; - continue; - } - - if (instr.type == QmlInstruction::SetId) { - QString id = output->primitives.at(instr.setId.value); - ids.insert(id, ii); - } - } - - for (int ii = start; ii <= end; ++ii) { - const QmlInstruction &instr = output->bytecode.at(ii); - - if (instr.type == QmlInstruction::CreateComponent) { - ii += instr.createComponent.count - 1; - continue; - } - - if (instr.type == QmlInstruction::StoreBinding || - instr.type == QmlInstruction::StoreCompiledBinding) { - ++bindingsCount; - } else if (instr.type == QmlInstruction::BeginObject) { - ++parserStatusCount; - } + for (int ii = 0; ii < compileState.bindings.count(); ++ii) { + const BindingReference &binding = compileState.bindings.at(ii); + QmlInstruction &instr = output->bytecode[binding.instructionIdx]; if (instr.type == QmlInstruction::StoreCompiledBinding) { QmlBasicScript s(output->datas.at(instr.assignBinding.value).constData()); @@ -1478,16 +1467,17 @@ int QmlCompiler::optimizeExpressions(int start, int end, int patch) if (!slt.at(0).isUpper()) continue; - if (ids.contains(slt) && + if (compileState.ids.contains(slt) && instr.assignBinding.category == QmlMetaProperty::Object) { - int id = ids[slt]; - int idType = savedTypes.value(id); - int storeType = savedTypes.value(ii); + IdReference reference = + compileState.ids[slt]; + + const QMetaObject *idMo = reference.object->metaObject(); + const QMetaObject *storeMo = QmlMetaType::rawMetaObjectForType(binding.property->type); - const QMetaObject *idMo = (idType == -1)?&QmlComponent::staticMetaObject:output->types.at(idType).metaObject(); - const QMetaObject *storeMo = - QmlMetaType::rawMetaObjectForType(storeType); + Q_ASSERT(idMo); + Q_ASSERT(storeMo); bool canAssign = false; while (!canAssign && idMo) { @@ -1502,19 +1492,19 @@ int QmlCompiler::optimizeExpressions(int start, int end, int patch) int saveId = -1; - if (output->bytecode.at(id).setId.save != -1) { - saveId = output->bytecode.at(id).setId.save; + int instructionIdx = reference.instructionIdx; + if (output->bytecode.at(instructionIdx).setId.save != -1) { + saveId = output->bytecode.at(instructionIdx).setId.save; } else { - output->bytecode[id].setId.save = saveCount; + output->bytecode[instructionIdx].setId.save = saveCount; saveId = saveCount; ++saveCount; } int prop = instr.assignBinding.property; - QmlInstruction &rwinstr = output->bytecode[ii]; - rwinstr.type = QmlInstruction::PushProperty; - rwinstr.pushProperty.property = prop; + instr.type = QmlInstruction::PushProperty; + instr.pushProperty.property = prop; QmlInstruction instr; instr.type = QmlInstruction::StoreStackObject; @@ -1529,8 +1519,9 @@ int QmlCompiler::optimizeExpressions(int start, int end, int patch) } output->bytecode[patch].init.dataSize = saveCount; - output->bytecode[patch].init.bindingsSize = bindingsCount; - output->bytecode[patch].init.parserStatusSize = parserStatusCount;; + output->bytecode[patch].init.bindingsSize = compileState.bindings.count(); + output->bytecode[patch].init.parserStatusSize = + compileState.parserStatusCount; return newInstrs; } diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 6e9bafb..b1963da 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -158,13 +158,31 @@ private: QmlParser::Value *value); bool compileDynamicMeta(QmlParser::Object *obj); - bool compileBinding(const QString &, QmlParser::Property *prop, + bool compileBinding(const QmlParser::Variant &, QmlParser::Property *prop, int ctxt, const QMetaObject *, qint64); - int optimizeExpressions(int start, int end, int patch = -1); + int finalizeComponent(int patch); - QSet ids; - QHash savedTypes; + struct IdReference { + QString id; + QmlParser::Object *object; + int instructionIdx; + }; + + struct BindingReference { + QmlParser::Variant expression; + QmlParser::Property *property; + int instructionIdx; + }; + + struct ComponentCompileState + { + ComponentCompileState() : parserStatusCount(0) {} + QHash ids; + int parserStatusCount; + QList bindings; + }; + ComponentCompileState compileState; QList exceptions; QmlCompiledData *output; diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp index b862953..b1ffc98 100644 --- a/src/declarative/qml/qmlscriptparser.cpp +++ b/src/declarative/qml/qmlscriptparser.cpp @@ -597,7 +597,7 @@ QmlParser::Variant ProcessAST::getVariant(AST::ExpressionNode *expr) } } - return QmlParser::Variant(asString(expr), expr); + return QmlParser::Variant(asString(expr), expr); } } @@ -716,33 +716,44 @@ bool ProcessAST::visit(AST::UiSourceElement *node) QmlScriptParser::QmlScriptParser() -: root(0) +: root(0), data(0) { } QmlScriptParser::~QmlScriptParser() { + clear(); } -bool QmlScriptParser::parse(const QByteArray &data, const QUrl &url) +class QmlScriptParserJsASTData +{ +public: + QmlScriptParserJsASTData(const QString &filename) + : nodePool(filename, &engine) {} + + Engine engine; + NodePool nodePool; +}; + +bool QmlScriptParser::parse(const QByteArray &qmldata, const QUrl &url) { #ifdef Q_ENABLE_PERFORMANCE_LOG QFxPerfTimer pt; #endif + clear(); + const QString fileName = url.toString(); - QTextStream stream(data, QIODevice::ReadOnly); + QTextStream stream(qmldata, QIODevice::ReadOnly); const QString code = stream.readAll(); - Engine engine; - - NodePool nodePool(fileName, &engine); + data = new QmlScriptParserJsASTData(fileName); - Lexer lexer(&engine); + Lexer lexer(&data->engine); lexer.setCode(code, /*line = */ 1); - Parser parser(&engine); + Parser parser(&data->engine); if (! parser.parse() || !_errors.isEmpty()) { @@ -808,6 +819,11 @@ void QmlScriptParser::clear() _nameSpacePaths.clear(); _typeNames.clear(); _errors.clear(); + + if (data) { + delete data; + data = 0; + } } int QmlScriptParser::findOrCreateTypeId(const QString &name) diff --git a/src/declarative/qml/qmlscriptparser_p.h b/src/declarative/qml/qmlscriptparser_p.h index a9ffa47..3993194 100644 --- a/src/declarative/qml/qmlscriptparser_p.h +++ b/src/declarative/qml/qmlscriptparser_p.h @@ -54,6 +54,7 @@ QT_MODULE(Declarative) class QByteArray; +class QmlScriptParserJsASTData; class QmlScriptParser { public: @@ -98,6 +99,7 @@ public: QList _imports; QStringList _typeNames; QString _scriptFile; + QmlScriptParserJsASTData *data; }; QT_END_NAMESPACE -- cgit v0.12