aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqml.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2021-03-24 10:40:44 +0100
committerUlf Hermann <ulf.hermann@qt.io>2021-03-29 08:24:40 +0100
commitaa05de42962f7dce931f965b6affd0d27f24c50a (patch)
treef21d0ad3a2ad4399a744ee74615e953d0672ac89 /src/qml/qml/qqml.cpp
parenta0499808be44ea15db53abf5091398ddd7c56de5 (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.cpp67
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
{