From bb34abcc05d11f23c329f4c52aab638d991c1b98 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 4 Jan 2019 15:32:33 +0100 Subject: Fix lookup fallback into the global object in QML bindings This change addresses in particular qmlbench's fib10.qml, where usage of properties of the global object needs to go be accelerated in order to avoid regressing in performance. Task-number: QTBUG-69898 Change-Id: Ic43c64f4dd5459c4e92f87f03235ea836f971515 Reviewed-by: Ulf Hermann --- src/qml/jsruntime/qv4lookup_p.h | 7 +++++++ src/qml/jsruntime/qv4qmlcontext.cpp | 33 +++++++++++++++++++++++++++++++-- src/qml/jsruntime/qv4qmlcontext_p.h | 1 + 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h index 68da224273..ee6da21121 100644 --- a/src/qml/jsruntime/qv4lookup_p.h +++ b/src/qml/jsruntime/qv4lookup_p.h @@ -143,6 +143,13 @@ struct Lookup { quintptr unused2; int objectId; } qmlContextIdObjectLookup; + struct { + // Same as protoLookup, as used for global lookups + quintptr reserved1; + quintptr reserved2; + quintptr reserved3; + ReturnedValue (*getterTrampoline)(Lookup *l, ExecutionEngine *engine); + } qmlContextGlobalLookup; }; uint nameIndex; diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp index 3d9e1cc0f8..e728cfb457 100644 --- a/src/qml/jsruntime/qv4qmlcontext.cpp +++ b/src/qml/jsruntime/qv4qmlcontext.cpp @@ -213,6 +213,7 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r } QQmlEnginePrivate *ep = QQmlEnginePrivate::get(v4->qmlEngine()); + Lookup * const originalLookup = lookup; while (context) { // Search context properties @@ -295,8 +296,24 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r // Do a lookup in the global object here to avoid expressionContext->unresolvedNames becoming // true if we access properties of the global object. - if (performGobalLookUp()) - return result->asReturnedValue(); + if (originalLookup) { + // Try a lookup in the global object. It's theoretically possible to first find a property + // in the global object and then later a context property with the same name is added, but that + // never really worked as we used to detect access to global properties at type compile time anyway. + lookup = originalLookup; + result = lookup->resolveGlobalGetter(v4); + if (lookup->globalGetter != Lookup::globalGetterGeneric) { + if (hasProperty) + *hasProperty = true; + lookup->qmlContextGlobalLookup.getterTrampoline = lookup->globalGetter; + lookup->qmlContextPropertyGetter = QQmlContextWrapper::lookupInGlobalObject; + return result->asReturnedValue(); + } + lookup->qmlContextPropertyGetter = QQmlContextWrapper::resolveQmlContextPropertyLookupGetter; + } else { + if (performGobalLookUp()) + return result->asReturnedValue(); + } expressionContext->unresolvedNames = true; @@ -449,6 +466,18 @@ ReturnedValue QQmlContextWrapper::lookupIdObject(Lookup *l, ExecutionEngine *eng return QV4::QObjectWrapper::wrap(engine, context->idValues[objectId]); } +ReturnedValue QQmlContextWrapper::lookupInGlobalObject(Lookup *l, ExecutionEngine *engine, Value *base) +{ + Q_UNUSED(base); + ReturnedValue result = l->qmlContextGlobalLookup.getterTrampoline(l, engine); + // In the unlikely event of mutation of the global object, update the trampoline. + if (l->qmlContextPropertyGetter != lookupInGlobalObject) { + l->qmlContextGlobalLookup.getterTrampoline = l->globalGetter; + l->qmlContextPropertyGetter = QQmlContextWrapper::lookupInGlobalObject; + } + return result; +} + void Heap::QmlContext::init(QV4::ExecutionContext *outerContext, QV4::QQmlContextWrapper *qml) { Heap::ExecutionContext::init(Heap::ExecutionContext::Type_QmlContext); diff --git a/src/qml/jsruntime/qv4qmlcontext_p.h b/src/qml/jsruntime/qv4qmlcontext_p.h index caf9281540..cfcc53c7c9 100644 --- a/src/qml/jsruntime/qv4qmlcontext_p.h +++ b/src/qml/jsruntime/qv4qmlcontext_p.h @@ -108,6 +108,7 @@ struct Q_QML_EXPORT QQmlContextWrapper : Object static ReturnedValue lookupScript(Lookup *l, ExecutionEngine *engine, Value *base); static ReturnedValue lookupSingleton(Lookup *l, ExecutionEngine *engine, Value *base); static ReturnedValue lookupIdObject(Lookup *l, ExecutionEngine *engine, Value *base); + static ReturnedValue lookupInGlobalObject(Lookup *l, ExecutionEngine *engine, Value *base); }; struct Q_QML_EXPORT QmlContext : public ExecutionContext -- cgit v1.2.3