diff options
author | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2015-04-09 10:23:17 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2015-04-21 06:36:47 +0000 |
commit | 3db3c38b1055cc8b41a9aa951c33f5621babb5d0 (patch) | |
tree | 8ba17669737ab0bd06cae7ac8366c5709614c5a0 /src/qml/compiler | |
parent | a41dc6147436f3c1c977ff8c04379ff4bde3f0a6 (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.cpp | 48 | ||||
-rw-r--r-- | src/qml/compiler/qqmltypecompiler_p.h | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata.cpp | 10 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata_p.h | 20 |
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(); |