aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@theqtcompany.com>2015-04-09 10:23:17 +0200
committerSimon Hausmann <simon.hausmann@theqtcompany.com>2015-04-21 06:36:47 +0000
commit3db3c38b1055cc8b41a9aa951c33f5621babb5d0 (patch)
tree8ba17669737ab0bd06cae7ac8366c5709614c5a0 /src/qml/compiler
parenta41dc6147436f3c1c977ff8c04379ff4bde3f0a6 (diff)
Speed up property binding initialization on object creation
Avoid repeated string hashing and lookups in the property cache in order to retrieve the property details when initializing literal and script bindings. Instead we now cache the property data at type validation time, similar to how the property data was encoded in the VME instructions in the old engine. Change-Id: I3957c7c4c3e26dfa97c4880b23940a3755ee90e4 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp48
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h2
-rw-r--r--src/qml/compiler/qv4compileddata.cpp10
-rw-r--r--src/qml/compiler/qv4compileddata_p.h20
4 files changed, 55 insertions, 25 deletions
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index b249d9ad9e..25282df2e3 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -392,6 +392,11 @@ void QQmlTypeCompiler::setDeferredBindingsPerObject(const QHash<int, QBitArray>
compiledData->deferredBindingsPerObject = deferredBindingsPerObject;
}
+void QQmlTypeCompiler::setBindingPropertyDataPerObject(const QVector<QV4::CompiledData::BindingPropertyData> &propertyData)
+{
+ compiledData->compilationUnit->bindingPropertyDataPerObject = propertyData;
+}
+
QString QQmlTypeCompiler::bindingAsString(const QmlIR::Object *object, int scriptIndex) const
{
return object->bindingAsString(document, scriptIndex);
@@ -1712,9 +1717,11 @@ QQmlPropertyValidator::QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler)
bool QQmlPropertyValidator::validate()
{
+ _bindingPropertyDataPerObject.resize(qmlUnit->nObjects);
if (!validateObject(qmlUnit->indexOfRootObject, /*instantiatingBinding*/0))
return false;
compiler->setDeferredBindingsPerObject(_deferredBindingsPerObject);
+ compiler->setBindingPropertyDataPerObject(_bindingPropertyDataPerObject);
return true;
}
@@ -1818,6 +1825,8 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
defaultProperty = propertyCache->defaultProperty();
}
+ QV4::CompiledData::BindingPropertyData collectedBindingPropertyData(obj->nBindings);
+
binding = obj->bindingTable();
for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) {
QString name = stringAt(binding->propertyNameIndex);
@@ -1837,22 +1846,6 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
}
}
- // Signal handlers were resolved and checked earlier in the signal handler conversion pass.
- if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
- || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject)
- continue;
-
- if (name.constData()->isUpper() && !binding->isAttachedProperty()) {
- QQmlType *type = 0;
- QQmlImportNamespace *typeNamespace = 0;
- compiler->imports()->resolveType(stringAt(binding->propertyNameIndex), &type, 0, 0, &typeNamespace);
- if (typeNamespace)
- recordError(binding->location, tr("Invalid use of namespace"));
- else
- recordError(binding->location, tr("Invalid attached object assignment"));
- return false;
- }
-
bool bindingToDefaultProperty = false;
bool notInRevision = false;
@@ -1882,9 +1875,23 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
bindingToDefaultProperty = true;
}
+ if (pd)
+ collectedBindingPropertyData[i] = pd;
+
+ if (name.constData()->isUpper() && !binding->isAttachedProperty()) {
+ QQmlType *type = 0;
+ QQmlImportNamespace *typeNamespace = 0;
+ compiler->imports()->resolveType(stringAt(binding->propertyNameIndex), &type, 0, 0, &typeNamespace);
+ if (typeNamespace)
+ recordError(binding->location, tr("Invalid use of namespace"));
+ else
+ recordError(binding->location, tr("Invalid attached object assignment"));
+ return false;
+ }
+
bool seenSubObjectWithId = false;
- if (binding->type >= QV4::CompiledData::Binding::Type_Object && !customParser) {
+ if (binding->type >= QV4::CompiledData::Binding::Type_Object && (!customParser || binding->type == QV4::CompiledData::Binding::Type_AttachedProperty)) {
qSwap(_seenObjectWithId, seenSubObjectWithId);
const bool subObjectValid = validateObject(binding->value.objectIndex, binding, pd && QQmlValueTypeFactory::metaObjectForMetaType(pd->propType));
qSwap(_seenObjectWithId, seenSubObjectWithId);
@@ -1902,6 +1909,11 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
deferredBindings.setBit(i);
}
+ // Signal handlers were resolved and checked earlier in the signal handler conversion pass.
+ if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
+ || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject)
+ continue;
+
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
if (instantiatingBinding && (instantiatingBinding->isAttachedProperty() || instantiatingBinding->isGroupProperty())) {
recordError(binding->location, tr("Attached properties cannot be used here"));
@@ -2009,6 +2021,8 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
if (!deferredBindings.isEmpty())
_deferredBindingsPerObject.insert(objectIndex, deferredBindings);
+ _bindingPropertyDataPerObject[objectIndex] = collectedBindingPropertyData;
+
return true;
}
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index 0982058e14..75987af656 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -93,6 +93,7 @@ public:
QStringRef newStringRef(const QString &string);
const QV4::Compiler::StringTableGenerator *stringPool() const;
void setDeferredBindingsPerObject(const QHash<int, QBitArray> &deferredBindingsPerObject);
+ void setBindingPropertyDataPerObject(const QVector<QV4::CompiledData::BindingPropertyData> &propertyData);
const QHash<int, QQmlCustomParser*> &customParserCache() const { return customParsers; }
@@ -295,6 +296,7 @@ private:
// collected state variables, essentially write-only
mutable QHash<int, QBitArray> _deferredBindingsPerObject;
mutable bool _seenObjectWithId;
+ mutable QVector<QV4::CompiledData::BindingPropertyData> _bindingPropertyDataPerObject;
};
// ### merge with QtQml::JSCodeGen and operate directly on object->functionsAndExpressions once old compiler is gone.
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 653416783e..5d954eb4fc 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -40,6 +40,7 @@
#include <private/qv4objectproto_p.h>
#include <private/qv4lookup_p.h>
#include <private/qv4regexpobject_p.h>
+#include <private/qqmlpropertycache_p.h>
#endif
#include <private/qqmlirbuilder_p.h>
#include <QCoreApplication>
@@ -53,6 +54,15 @@ namespace QV4 {
namespace CompiledData {
#ifndef V4_BOOTSTRAP
+CompilationUnit::CompilationUnit()
+ : data(0)
+ , engine(0)
+ , runtimeStrings(0)
+ , runtimeLookups(0)
+ , runtimeRegularExpressions(0)
+ , runtimeClasses(0)
+{}
+
CompilationUnit::~CompilationUnit()
{
unlink();
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 7b40fa849a..f46e27fe98 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -46,6 +46,9 @@
QT_BEGIN_NAMESPACE
+class QQmlPropertyCache;
+class QQmlPropertyData;
+
namespace QmlIR {
struct Document;
}
@@ -556,6 +559,9 @@ struct TypeReferenceMap : QHash<int, TypeReference>
}
};
+// index is per-object binding index
+typedef QVector<QQmlPropertyData*> BindingPropertyData;
+
// This is how this hooks into the existing structures:
//VM::Function
@@ -570,14 +576,7 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount
{}
virtual ~CompilationUnit() {}
#else
- CompilationUnit()
- : data(0)
- , engine(0)
- , runtimeStrings(0)
- , runtimeLookups(0)
- , runtimeRegularExpressions(0)
- , runtimeClasses(0)
- {}
+ CompilationUnit();
virtual ~CompilationUnit();
#endif
@@ -598,6 +597,11 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount
QVector<QV4::Function *> runtimeFunctions;
mutable QQmlNullableValue<QUrl> m_url;
+ // index is object index. This allows fast access to the
+ // property data when initializing bindings, avoiding expensive
+ // lookups by string (property name).
+ QVector<BindingPropertyData> bindingPropertyDataPerObject;
+
QV4::Function *linkToEngine(QV4::ExecutionEngine *engine);
void unlink();