aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlobjectcreator.cpp
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/qml/qqmlobjectcreator.cpp
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/qml/qqmlobjectcreator.cpp')
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp76
1 files changed, 33 insertions, 43 deletions
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 4c86e6a307..f4f42f706b 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -124,6 +124,7 @@ void QQmlObjectCreator::init(QQmlContextData *providedParentContext)
_scopeObject = 0;
_valueTypeProperty = 0;
_compiledObject = 0;
+ _compiledObjectIndex = -1;
_ddata = 0;
_propertyCache = 0;
_vmeMetaObject = 0;
@@ -233,9 +234,7 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
QQmlData *declarativeData = QQmlData::get(instance);
context = declarativeData->deferredData->context;
sharedState->rootContext = context;
- const int objectIndex = declarativeData->deferredData->deferredIdx;
- const QV4::CompiledData::Object *obj = qmlUnit->objectAt(objectIndex);
QObject *bindingTarget = instance;
QQmlRefPointer<QQmlPropertyCache> cache = declarativeData->propertyCache;
@@ -256,12 +255,18 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
qSwap(_propertyCache, cache);
qSwap(_qobject, instance);
+
+ int objectIndex = declarativeData->deferredData->deferredIdx;
+ qSwap(_compiledObjectIndex, objectIndex);
+
+ const QV4::CompiledData::Object *obj = qmlUnit->objectAt(_compiledObjectIndex);
qSwap(_compiledObject, obj);
+
qSwap(_ddata, declarativeData);
qSwap(_bindingTarget, bindingTarget);
qSwap(_vmeMetaObject, vmeMetaObject);
- QBitArray bindingSkipList = compiledData->deferredBindingsPerObject.value(objectIndex);
+ QBitArray bindingSkipList = compiledData->deferredBindingsPerObject.value(_compiledObjectIndex);
for (int i = 0; i < bindingSkipList.count(); ++i)
bindingSkipList.setBit(i, !bindingSkipList.testBit(i));
@@ -271,6 +276,7 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
qSwap(_bindingTarget, bindingTarget);
qSwap(_ddata, declarativeData);
qSwap(_compiledObject, obj);
+ qSwap(_compiledObjectIndex, objectIndex);
qSwap(_qobject, instance);
qSwap(_propertyCache, cache);
@@ -282,7 +288,7 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
return errors.isEmpty();
}
-void QQmlObjectCreator::setPropertyValue(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
+void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
{
QQmlPropertyPrivate::WriteFlags propertyWriteFlags = QQmlPropertyPrivate::BypassInterceptor |
QQmlPropertyPrivate::RemoveBindingOnAliasWrite;
@@ -636,8 +642,6 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
QQmlListProperty<void> savedList;
qSwap(_currentList, savedList);
- QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultProperty != -1 ? _propertyCache->parent()->defaultProperty() : _propertyCache->defaultProperty();
-
if (_compiledObject->idIndex) {
QQmlPropertyData *idProperty = _propertyCache->property(QStringLiteral("id"), _qobject, context);
if (idProperty && idProperty->isWritable() && idProperty->propType == QMetaType::QString) {
@@ -666,6 +670,8 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
if (qmlTypeForObject(_bindingTarget)) {
quint32 bindingSkipList = 0;
+ QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultProperty != -1 ? _propertyCache->parent()->defaultProperty() : _propertyCache->defaultProperty();
+
const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
QQmlPropertyData *property = binding->propertyNameIndex != 0 ? _propertyCache->property(stringAt(binding->propertyNameIndex), _qobject, context) : defaultProperty;
@@ -678,38 +684,21 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
}
}
- QQmlPropertyData *property = 0;
+ const QV4::CompiledData::BindingPropertyData &propertyData = compiledData->compilationUnit->bindingPropertyDataPerObject.at(_compiledObjectIndex);
+
const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
-
- QString name = stringAt(binding->propertyNameIndex);
- if (name.isEmpty())
- property = 0;
-
- if (!property
- || (i > 0 && ((binding - 1)->propertyNameIndex != binding->propertyNameIndex
- || (binding - 1)->flags != binding->flags))
- ) {
- if (!name.isEmpty()) {
- if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
- || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject)
- property = QmlIR::PropertyResolver(_propertyCache).signal(name, /*notInRevision*/0, _qobject, context);
- else
- property = _propertyCache->property(name, _qobject, context);
- } else
- property = defaultProperty;
-
- if (property && property->isQList()) {
- void *argv[1] = { (void*)&_currentList };
- QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex, argv);
- } else if (_currentList.object)
- _currentList = QQmlListProperty<void>();
-
- }
-
if (static_cast<int>(i) < bindingsToSkip.size() && bindingsToSkip.testBit(i))
continue;
+ const QQmlPropertyData *property = propertyData.at(i);
+
+ if (property && property->isQList()) {
+ void *argv[1] = { (void*)&_currentList };
+ QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex, argv);
+ } else if (_currentList.object)
+ _currentList = QQmlListProperty<void>();
+
if (!setPropertyBinding(property, binding))
return;
}
@@ -717,7 +706,7 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
qSwap(_currentList, savedList);
}
-bool QQmlObjectCreator::setPropertyBinding(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
+bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
{
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
Q_ASSERT(stringAt(qmlUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex).isEmpty());
@@ -765,7 +754,7 @@ bool QQmlObjectCreator::setPropertyBinding(QQmlPropertyData *property, const QV4
QObject *groupObject = 0;
QQmlValueType *valueType = 0;
- QQmlPropertyData *valueTypeProperty = 0;
+ const QQmlPropertyData *valueTypeProperty = 0;
QObject *bindingTarget = _bindingTarget;
if (QQmlValueTypeFactory::isValueType(property->propType)) {
@@ -1263,14 +1252,14 @@ void QQmlObjectCreator::clear()
phase = Done;
}
-bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *bindingTarget, QQmlPropertyData *valueTypeProperty, const QBitArray &bindingsToSkip)
+bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *bindingTarget, const QQmlPropertyData *valueTypeProperty, const QBitArray &bindingsToSkip)
{
- const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
-
QQmlData *declarativeData = QQmlData::get(instance, /*create*/true);
qSwap(_qobject, instance);
qSwap(_valueTypeProperty, valueTypeProperty);
+ qSwap(_compiledObjectIndex, index);
+ const QV4::CompiledData::Object *obj = qmlUnit->objectAt(_compiledObjectIndex);
qSwap(_compiledObject, obj);
qSwap(_ddata, declarativeData);
qSwap(_bindingTarget, bindingTarget);
@@ -1278,10 +1267,10 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
QV4::Scope valueScope(v4);
QV4::ScopedValue scopeObjectProtector(valueScope);
- QQmlRefPointer<QQmlPropertyCache> cache = propertyCaches.at(index);
+ QQmlRefPointer<QQmlPropertyCache> cache = propertyCaches.at(_compiledObjectIndex);
QQmlVMEMetaObject *vmeMetaObject = 0;
- const QByteArray data = vmeMetaObjectData.value(index);
+ const QByteArray data = vmeMetaObjectData.value(_compiledObjectIndex);
if (!data.isEmpty()) {
Q_ASSERT(!cache.isNull());
// install on _object
@@ -1295,14 +1284,14 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
vmeMetaObject = QQmlVMEMetaObject::get(_qobject);
}
- registerObjectWithContextById(index, _qobject);
+ registerObjectWithContextById(_compiledObjectIndex, _qobject);
qSwap(_propertyCache, cache);
qSwap(_vmeMetaObject, vmeMetaObject);
QBitArray bindingSkipList = bindingsToSkip;
{
- QHash<int, QBitArray>::ConstIterator deferredBindings = compiledData->deferredBindingsPerObject.find(index);
+ QHash<int, QBitArray>::ConstIterator deferredBindings = compiledData->deferredBindingsPerObject.find(_compiledObjectIndex);
if (deferredBindings != compiledData->deferredBindingsPerObject.constEnd()) {
if (bindingSkipList.isEmpty())
bindingSkipList.resize(deferredBindings->count());
@@ -1311,7 +1300,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
if (deferredBindings->testBit(i))
bindingSkipList.setBit(i);
QQmlData::DeferredData *deferData = new QQmlData::DeferredData;
- deferData->deferredIdx = index;
+ deferData->deferredIdx = _compiledObjectIndex;
deferData->compiledData = compiledData;
deferData->compiledData->addref();
deferData->context = context;
@@ -1327,6 +1316,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
qSwap(_bindingTarget, bindingTarget);
qSwap(_ddata, declarativeData);
qSwap(_compiledObject, obj);
+ qSwap(_compiledObjectIndex, index);
qSwap(_valueTypeProperty, valueTypeProperty);
qSwap(_qobject, instance);
qSwap(_propertyCache, cache);