summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/declarative/qml/qmlcompiler.cpp175
-rw-r--r--src/declarative/qml/qmlcompiler_p.h26
-rw-r--r--src/declarative/qml/qmlscriptparser.cpp34
-rw-r--r--src/declarative/qml/qmlscriptparser_p.h2
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 <private/qmlcontext_p.h>
#include <private/qmlcomponent_p.h>
+#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<QString> 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<QString, int> 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<QString> ids;
- QHash<int, int> 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<QString, IdReference> ids;
+ int parserStatusCount;
+ QList<BindingReference> bindings;
+ };
+ ComponentCompileState compileState;
QList<QmlError> 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<QFxPerf::QmlParsing> 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<Import> _imports;
QStringList _typeNames;
QString _scriptFile;
+ QmlScriptParserJsASTData *data;
};
QT_END_NAMESPACE