diff options
author | Simon Hausmann <simon.hausmann@qt.io> | 2018-01-16 13:47:51 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2018-01-17 13:14:09 +0000 |
commit | 15a81d9689cad5c957aed09161fdab253b27c130 (patch) | |
tree | 1da3bc2eff92d4a430b9e5f0dc3ab58e4adb97f9 /src/qml/qml/qqmlproperty.cpp | |
parent | e4ffad84fecebb3c1fc554b3252fd5d059c0ff38 (diff) |
Optimize QQmlProperty constructor for the common property case
The common case is that QQmlProperty is constructed on the property of
an object, not a group property. Therefore we should do the
QVector<QStringRef> split on the property name by '.' only if a dot
exists, and can avoid the allocation and deallocation of the vector.
Shaves off ~1.2% off delegates_item_states.qml.
Task-number: QTBUG-65708
Change-Id: Iffbde176e616beec0ae0a47216360558adc793ee
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/qml/qml/qqmlproperty.cpp')
-rw-r--r-- | src/qml/qml/qqmlproperty.cpp | 136 |
1 files changed, 70 insertions, 66 deletions
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp index b79418761b..50d9f13049 100644 --- a/src/qml/qml/qqmlproperty.cpp +++ b/src/qml/qml/qqmlproperty.cpp @@ -229,7 +229,7 @@ QQmlProperty QQmlPropertyPrivate::create(QObject *target, const QString &propert auto d = new QQmlPropertyPrivate; result.d = d; d->context = context; - d->engine = context->engine; + d->engine = context ? context->engine : nullptr; d->initProperty(target, propertyName); if (!result.isValid()) { d->object = nullptr; @@ -257,89 +257,93 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name) QQmlTypeNameCache *typeNameCache = context?context->imports:0; - const auto path = name.splitRef(QLatin1Char('.')); - if (path.isEmpty()) return; - QObject *currentObject = obj; - - // Everything up to the last property must be an "object type" property - for (int ii = 0; ii < path.count() - 1; ++ii) { - const QStringRef &pathName = path.at(ii); - - if (typeNameCache) { - QQmlTypeNameCache::Result r = typeNameCache->query(pathName); - if (r.isValid()) { - if (r.type.isValid()) { - QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine); - QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(enginePrivate); - if (!func) return; // Not an attachable type - - currentObject = qmlAttachedPropertiesObjectById(r.type.attachedPropertiesId(enginePrivate), currentObject); - if (!currentObject) return; // Something is broken with the attachable type - } else if (r.importNamespace) { - if ((ii + 1) == path.count()) return; // No type following the namespace - - ++ii; r = typeNameCache->query(path.at(ii), r.importNamespace); - if (!r.type.isValid()) return; // Invalid type in namespace - - QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine); - QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(enginePrivate); - if (!func) return; // Not an attachable type - - currentObject = qmlAttachedPropertiesObjectById(r.type.attachedPropertiesId(enginePrivate), currentObject); - if (!currentObject) return; // Something is broken with the attachable type - - } else if (r.scriptIndex != -1) { - return; // Not a type - } else { - Q_ASSERT(!"Unreachable"); + QVector<QStringRef> path; + QStringRef terminal(&name); + + if (name.contains(QLatin1Char('.'))) { + path = name.splitRef(QLatin1Char('.')); + if (path.isEmpty()) return; + + // Everything up to the last property must be an "object type" property + for (int ii = 0; ii < path.count() - 1; ++ii) { + const QStringRef &pathName = path.at(ii); + + if (typeNameCache) { + QQmlTypeNameCache::Result r = typeNameCache->query(pathName); + if (r.isValid()) { + if (r.type.isValid()) { + QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine); + QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(enginePrivate); + if (!func) return; // Not an attachable type + + currentObject = qmlAttachedPropertiesObjectById(r.type.attachedPropertiesId(enginePrivate), currentObject); + if (!currentObject) return; // Something is broken with the attachable type + } else if (r.importNamespace) { + if ((ii + 1) == path.count()) return; // No type following the namespace + + ++ii; r = typeNameCache->query(path.at(ii), r.importNamespace); + if (!r.type.isValid()) return; // Invalid type in namespace + + QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine); + QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(enginePrivate); + if (!func) return; // Not an attachable type + + currentObject = qmlAttachedPropertiesObjectById(r.type.attachedPropertiesId(enginePrivate), currentObject); + if (!currentObject) return; // Something is broken with the attachable type + + } else if (r.scriptIndex != -1) { + return; // Not a type + } else { + Q_ASSERT(!"Unreachable"); + } + continue; } - continue; + } - } + QQmlPropertyData local; + QQmlPropertyData *property = + QQmlPropertyCache::property(engine, currentObject, pathName, context, local); - QQmlPropertyData local; - QQmlPropertyData *property = - QQmlPropertyCache::property(engine, currentObject, pathName, context, local); + if (!property) return; // Not a property + if (property->isFunction()) + return; // Not an object property - if (!property) return; // Not a property - if (property->isFunction()) - return; // Not an object property + if (ii == (path.count() - 2) && QQmlValueTypeFactory::isValueType(property->propType())) { + // We're now at a value type property + const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property->propType()); + if (!valueTypeMetaObject) return; // Not a value type - if (ii == (path.count() - 2) && QQmlValueTypeFactory::isValueType(property->propType())) { - // We're now at a value type property - const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property->propType()); - if (!valueTypeMetaObject) return; // Not a value type + int idx = valueTypeMetaObject->indexOfProperty(path.last().toUtf8().constData()); + if (idx == -1) return; // Value type property does not exist - int idx = valueTypeMetaObject->indexOfProperty(path.last().toUtf8().constData()); - if (idx == -1) return; // Value type property does not exist + QMetaProperty vtProp = valueTypeMetaObject->property(idx); - QMetaProperty vtProp = valueTypeMetaObject->property(idx); + Q_ASSERT(vtProp.userType() <= 0x0000FFFF); + Q_ASSERT(idx <= 0x0000FFFF); - Q_ASSERT(vtProp.userType() <= 0x0000FFFF); - Q_ASSERT(idx <= 0x0000FFFF); + object = currentObject; + core = *property; + valueTypeData.setFlags(QQmlPropertyData::flagsForProperty(vtProp)); + valueTypeData.setPropType(vtProp.userType()); + valueTypeData.setCoreIndex(idx); - object = currentObject; - core = *property; - valueTypeData.setFlags(QQmlPropertyData::flagsForProperty(vtProp)); - valueTypeData.setPropType(vtProp.userType()); - valueTypeData.setCoreIndex(idx); + return; + } else { + if (!property->isQObject()) + return; // Not an object property - return; - } else { - if (!property->isQObject()) - return; // Not an object property + property->readProperty(currentObject, ¤tObject); + if (!currentObject) return; // No value - property->readProperty(currentObject, ¤tObject); - if (!currentObject) return; // No value + } } + terminal = path.last(); } - const QStringRef &terminal = path.last(); - if (terminal.count() >= 3 && terminal.at(0) == QLatin1Char('o') && terminal.at(1) == QLatin1Char('n') && |