diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2021-03-24 10:40:44 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2021-03-29 08:24:40 +0100 |
commit | aa05de42962f7dce931f965b6affd0d27f24c50a (patch) | |
tree | f21d0ad3a2ad4399a744ee74615e953d0672ac89 /src/qml/qml/qqml.cpp | |
parent | a0499808be44ea15db53abf5091398ddd7c56de5 (diff) |
Optimize some common lookups for AOT compiled code
Getting a property of an object and getting an object by ID should not
require any type transformations.
Change-Id: I7ba06cf7c09cdf4ce7b0093b670fd7879ecf799a
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/qml/qqml.cpp')
-rw-r--r-- | src/qml/qml/qqml.cpp | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp index fa040e0604..23e66722fa 100644 --- a/src/qml/qml/qqml.cpp +++ b/src/qml/qml/qqml.cpp @@ -730,6 +730,73 @@ bool QQmlPrivate::AOTCompiledContext::captureQmlContextPropertyLookup(uint index return true; } +QObject *QQmlPrivate::AOTCompiledContext::loadQmlContextPropertyIdLookup(uint index) const +{ + QV4::Lookup *l = compilationUnit->runtimeLookups + index; + if (l->qmlContextPropertyGetter == QV4::QQmlContextWrapper::lookupIdObject) { + // Shortcut this to avoid the wrapping when returning from lookupIdObject(). + if (!qmlContext) + return nullptr; + + const auto context = QQmlContextData::get(qmlContext); + QQmlEnginePrivate *qmlEngine = QQmlEnginePrivate::get(context->engine()); + const int objectId = l->qmlContextIdObjectLookup.objectId; + + if (qmlEngine->propertyCapture) + qmlEngine->propertyCapture->captureProperty(context->idValueBindings(objectId)); + return context->idValue(objectId); + } + + QV4::Scope scope(engine->handle()); + QV4::Scoped<QV4::QObjectWrapper> o( + scope, l->qmlContextPropertyGetter(l, scope.engine, nullptr)); + return o ? o->object() : nullptr; +} + +bool QQmlPrivate::AOTCompiledContext::getObjectLookup( + uint index, QObject *object, void *target, QMetaType type) const +{ + QV4::Lookup *l = compilationUnit->runtimeLookups + index; + + if (!object) { + QString message = QStringLiteral("Cannot read property '%1' of null") + .arg(compilationUnit->runtimeStrings[l->nameIndex]->toQString()); + engine->handle()->throwTypeError(message); + return false; + } + + if (l->getter == QV4::QObjectWrapper::lookupGetter + && !QQmlData::wasDeleted(object) + && QQmlData::get(object)->propertyCache == l->qobjectLookup.propertyCache) { + QQmlPropertyData *property = l->qobjectLookup.propertyData; + if (property->propType() == type) { + // We can directly read the property into the target, without conversion. + if (!property->isConstant()) { + if (QQmlEngine *engine = qmlContext->engine()) { + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); + if (ep->propertyCapture) { + ep->propertyCapture->captureProperty(object, property->coreIndex(), + property->notifyIndex()); + } + } + } + property->readProperty(object, target); + return true; + } + } + + QV4::Scope scope(engine->handle()); + QV4::ScopedValue o(scope, QV4::QObjectWrapper::wrap(scope.engine, object)); + QV4::ScopedValue result(scope, l->getter(l, scope.engine, o)); + if (type == QMetaType::fromType<QVariant>()) { + // Special case QVariant in order to retain JS objects. + // We don't want to convert JS arrays into QVariantList, for example. + *static_cast<QVariant *>(target) = scope.engine->toVariant(result, QMetaType {}); + return true; + } + return scope.engine->metaTypeFromJS(result, type, target); +} + QJSValue QQmlPrivate::AOTCompiledContext::callQmlContextPropertyLookup( uint index, const QJSValueList &args) const { |