aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2014-04-01 11:00:27 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-04-02 14:04:17 +0200
commitc494da09794209d120c8df6b78074c07ad594a15 (patch)
treedd3c689c102ab05fc3d603ee33bc534a530cec46
parent4e012093462f07e7ffd42d4061539c54b4f43ace (diff)
Reduce memory consumption of runtime compiled QML types
Don't store the string of binding scripts in the compiled data. The only exception to the rule are properties of type QQmlScriptString as well as types with custom parsers. Change-Id: I7f53262bf957b442bac4db71d0a2c0bed74a9b54 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp19
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h1
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp57
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h17
4 files changed, 87 insertions, 7 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index e85703e9aa..1c10a49fd1 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -188,6 +188,17 @@ void Object::insertSorted(Binding *b)
bindings->insertAfter(insertionPoint, b);
}
+QString Object::bindingAsString(Document *doc, int scriptIndex) const
+{
+ CompiledFunctionOrExpression *foe = functionsAndExpressions->slowAt(scriptIndex);
+ QQmlJS::AST::Node *node = foe->node;
+ if (QQmlJS::AST::ExpressionStatement *exprStmt = QQmlJS::AST::cast<QQmlJS::AST::ExpressionStatement *>(node))
+ node = exprStmt->expression;
+ QQmlJS::AST::SourceLocation start = node->firstSourceLocation();
+ QQmlJS::AST::SourceLocation end = node->lastSourceLocation();
+ return doc->code.mid(start.offset, end.offset + end.length - start.offset);
+}
+
QStringList Signal::parameterStringList(const QV4::Compiler::StringTableGenerator *stringPool) const
{
QStringList result;
@@ -1252,11 +1263,9 @@ void IRBuilder::setBindingValue(QV4::CompiledData::Binding *binding, QQmlJS::AST
expr->disableAcceleratedLookups = false;
const int index = bindingsTarget()->functionsAndExpressions->append(expr);
binding->value.compiledScriptIndex = index;
-
- QQmlJS::AST::Node *nodeForString = statement;
- if (exprStmt)
- nodeForString = exprStmt->expression;
- binding->stringIndex = registerString(asStringRef(nodeForString).toString());
+ // We don't need to store the binding script as string, except for script strings
+ // and types with custom parsers. Those will be added later in the compilation phase.
+ binding->stringIndex = emptyStringIndex;
}
}
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index cd67c52ed7..4ea7e05639 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -283,6 +283,7 @@ public:
Binding *findBinding(quint32 nameIndex) const;
Binding *unlinkBinding(Binding *before, Binding *binding) { return bindings->unlink(before, binding); }
void insertSorted(Binding *b);
+ QString bindingAsString(Document *doc, int scriptIndex) const;
PoolList<CompiledFunctionOrExpression> *functionsAndExpressions;
FixedPoolArray<int> *runtimeFunctionIndices;
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index d79143fdc3..b44d4e285a 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -167,6 +167,11 @@ bool QQmlTypeCompiler::compile()
}
{
+ QQmlCustomParserScriptIndexer cpi(this);
+ cpi.annotateBindingsWithScriptStrings();
+ }
+
+ {
QQmlAliasAnnotator annotator(this);
annotator.annotateBindingsToAliases();
}
@@ -403,6 +408,11 @@ void QQmlTypeCompiler::setDeferredBindingsPerObject(const QHash<int, QBitArray>
compiledData->deferredBindingsPerObject = deferredBindingsPerObject;
}
+QString QQmlTypeCompiler::bindingAsString(const QmlIR::Object *object, int scriptIndex) const
+{
+ return object->bindingAsString(document, scriptIndex);
+}
+
QQmlCompilePass::QQmlCompilePass(QQmlTypeCompiler *typeCompiler)
: compiler(typeCompiler)
{
@@ -1144,8 +1154,8 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
COMPILE_EXCEPTION(binding, tr("Invalid property assignment: \"%1\" is a read-only property").arg(stringAt(binding->propertyNameIndex)));
Q_ASSERT(binding->type = QV4::CompiledData::Binding::Type_Script);
- QString string = stringAt(binding->stringIndex);
- if (!string.at(0).isUpper())
+ const QString string = compiler->bindingAsString(obj, binding->value.compiledScriptIndex);
+ if (!string.constData()->isUpper())
return true;
int dot = string.indexOf(QLatin1Char('.'));
@@ -1234,6 +1244,35 @@ int QQmlEnumTypeResolver::evaluateEnum(const QString &scope, const QByteArray &e
return -1;
}
+QQmlCustomParserScriptIndexer::QQmlCustomParserScriptIndexer(QQmlTypeCompiler *typeCompiler)
+ : QQmlCompilePass(typeCompiler)
+ , qmlObjects(*typeCompiler->qmlObjects())
+ , customParsers(typeCompiler->customParserCache())
+{
+}
+
+void QQmlCustomParserScriptIndexer::annotateBindingsWithScriptStrings()
+{
+ scanObjectRecursively(compiler->rootObjectIndex());
+}
+
+void QQmlCustomParserScriptIndexer::scanObjectRecursively(int objectIndex, bool annotateScriptBindings)
+{
+ const QmlIR::Object * const obj = qmlObjects.at(objectIndex);
+ if (!annotateScriptBindings)
+ annotateScriptBindings = customParsers.contains(obj->inheritedTypeNameIndex);
+ for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
+ if (binding->type >= QV4::CompiledData::Binding::Type_Object) {
+ scanObjectRecursively(binding->value.objectIndex, annotateScriptBindings);
+ continue;
+ } else if (binding->type != QV4::CompiledData::Binding::Type_Script)
+ continue;
+ if (!annotateScriptBindings)
+ continue;
+ const QString script = compiler->bindingAsString(obj, binding->value.compiledScriptIndex);
+ binding->stringIndex = compiler->registerString(script);
+ }
+}
QQmlAliasAnnotator::QQmlAliasAnnotator(QQmlTypeCompiler *typeCompiler)
: QQmlCompilePass(typeCompiler)
@@ -1297,6 +1336,9 @@ void QQmlScriptStringScanner::scan()
QmlIR::CompiledFunctionOrExpression *foe = obj->functionsAndExpressions->slowAt(binding->value.compiledScriptIndex);
if (foe)
foe->disableAcceleratedLookups = true;
+
+ QString script = compiler->bindingAsString(obj, binding->value.compiledScriptIndex);
+ binding->stringIndex = compiler->registerString(script);
}
}
}
@@ -1702,6 +1744,17 @@ QQmlBinding::Identifier QQmlPropertyValidator::bindingIdentifier(const QV4::Comp
return id;
}
+QString QQmlPropertyValidator::bindingAsString(int objectIndex, const QV4::CompiledData::Binding *binding) const
+{
+ const QmlIR::Object *object = compiler->qmlObjects()->value(objectIndex);
+ if (!object)
+ return QString();
+ int reverseIndex = object->runtimeFunctionIndices->indexOf(binding->value.compiledScriptIndex);
+ if (reverseIndex == -1)
+ return QString();
+ return compiler->bindingAsString(object, reverseIndex);
+}
+
typedef QVarLengthArray<const QV4::CompiledData::Binding *, 8> GroupPropertyVector;
static bool compareNameIndices(const QV4::CompiledData::Binding *binding, quint32 name)
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index 3b449bf9bd..fb8ac94fcd 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -105,6 +105,8 @@ public:
const QHash<int, QQmlCustomParser*> &customParserCache() const { return customParsers; }
+ QString bindingAsString(const QmlIR::Object *object, int scriptIndex) const;
+
private:
QList<QQmlError> errors;
QQmlEnginePrivate *engine;
@@ -195,6 +197,20 @@ private:
QHash<int, QQmlCompiledData::TypeReference *> *resolvedTypes;
};
+class QQmlCustomParserScriptIndexer: public QQmlCompilePass
+{
+public:
+ QQmlCustomParserScriptIndexer(QQmlTypeCompiler *typeCompiler);
+
+ void annotateBindingsWithScriptStrings();
+
+private:
+ void scanObjectRecursively(int objectIndex, bool annotateScriptBindings = false);
+
+ const QList<QmlIR::Object*> &qmlObjects;
+ const QHash<int, QQmlCustomParser*> &customParsers;
+};
+
// Annotate properties bound to aliases with a flag
class QQmlAliasAnnotator : public QQmlCompilePass
{
@@ -267,6 +283,7 @@ public:
// Re-implemented for QQmlCustomParser
virtual const QQmlImports &imports() const;
virtual QQmlBinding::Identifier bindingIdentifier(const QV4::CompiledData::Binding *binding, QQmlCustomParser *parser);
+ virtual QString bindingAsString(int objectIndex, const QV4::CompiledData::Binding *binding) const;
private:
bool validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty = false);