From 710580aa84c5c3273e883d9e650f3159ad8250f3 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 3 Jan 2019 17:00:36 +0100 Subject: Accelerate access to singletons and imported scripts Use a dedicated lookup type to provide super fast access to engine wide singleton objects as well as scripts Task-number: QTBUG-69898 Change-Id: Ie430f48f6576a9171018ef18742dcf6b2adb4310 Reviewed-by: Ulf Hermann --- src/qml/jsruntime/qv4qmlcontext.cpp | 55 +++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) (limited to 'src/qml/jsruntime/qv4qmlcontext.cpp') diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp index ae458c604a..ab80e6bc45 100644 --- a/src/qml/jsruntime/qv4qmlcontext.cpp +++ b/src/qml/jsruntime/qv4qmlcontext.cpp @@ -79,7 +79,7 @@ void Heap::QQmlContextWrapper::destroy() Object::destroy(); } -ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *resource, PropertyKey id, const Value *receiver, bool *hasProperty, Value *base) +ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *resource, PropertyKey id, const Value *receiver, bool *hasProperty, Value *base, Lookup *lookup) { if (!id.isString()) return Object::virtualGet(resource, id, receiver, hasProperty); @@ -159,6 +159,8 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r // Note: The scope object is only a QADMO for example when somebody registers a QQmlPropertyMap // sub-class as QML type and then instantiates it in .qml. if (scopeObject && QQmlPropertyCache::isDynamicMetaObject(scopeObject->metaObject())) { + // all bets are off, so don't try to optimize any lookups + lookup = nullptr; if (performGobalLookUp()) return result->asReturnedValue(); } @@ -171,11 +173,35 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r if (hasProperty) *hasProperty = true; if (r.scriptIndex != -1) { + if (lookup) { + lookup->qmlContextScriptLookup.scriptIndex = r.scriptIndex; + lookup->qmlContextPropertyGetter = QQmlContextWrapper::lookupScript; + return lookup->qmlContextPropertyGetter(lookup, v4, base); + } QV4::ScopedObject scripts(scope, context->importedScripts.valueRef()); if (scripts) return scripts->get(r.scriptIndex); return QV4::Encode::null(); } else if (r.type.isValid()) { + if (lookup) { + if (r.type.isSingleton()) { + QQmlEngine *e = v4->qmlEngine(); + QQmlType::SingletonInstanceInfo *siinfo = r.type.singletonInstanceInfo(); + siinfo->init(e); + if (siinfo->qobjectApi(e)) { + lookup->qmlContextSingletonLookup.singleton = + static_cast( + Value::fromReturnedValue( + QQmlTypeWrapper::create(v4, nullptr, r.type) + ).heapObject()); + } else { + QV4::ScopedObject o(scope, QJSValuePrivate::convertedToValue(v4, siinfo->scriptApi(e))); + lookup->qmlContextSingletonLookup.singleton = o->d(); + } + lookup->qmlContextPropertyGetter = QQmlContextWrapper::lookupSingleton; + return lookup->qmlContextPropertyGetter(lookup, v4, base); + } + } return QQmlTypeWrapper::create(v4, scopeObject, r.type); } else if (r.importNamespace) { return QQmlTypeWrapper::create(v4, scopeObject, context->imports, r.importNamespace); @@ -361,12 +387,37 @@ ReturnedValue QQmlContextWrapper::resolveQmlContextPropertyLookupGetter(Lookup * Scoped qmlContext(scope, engine->qmlContext()->qml()); bool hasProperty = false; ScopedValue result(scope, QQmlContextWrapper::getPropertyAndBase(qmlContext, name, /*receiver*/nullptr, - &hasProperty, base)); + &hasProperty, base, l)); if (!hasProperty) return engine->throwReferenceError(name.toQString()); return result->asReturnedValue(); } +ReturnedValue QQmlContextWrapper::lookupScript(Lookup *l, ExecutionEngine *engine, Value *base) +{ + Q_UNUSED(base) + Scope scope(engine); + Scoped qmlContext(scope, engine->qmlContext()); + if (!qmlContext) + return QV4::Encode::null(); + + QQmlContextData *context = qmlContext->qmlContext(); + if (!context) + return QV4::Encode::null(); + + QV4::ScopedObject scripts(scope, context->importedScripts.valueRef()); + if (!scripts) + return QV4::Encode::null(); + return scripts->get(l->qmlContextScriptLookup.scriptIndex); +} + +ReturnedValue QQmlContextWrapper::lookupSingleton(Lookup *l, ExecutionEngine *engine, Value *base) +{ + Q_UNUSED(engine) + Q_UNUSED(base) + return Value::fromHeapObject(l->qmlContextSingletonLookup.singleton).asReturnedValue(); +} + void Heap::QmlContext::init(QV4::ExecutionContext *outerContext, QV4::QQmlContextWrapper *qml) { Heap::ExecutionContext::init(Heap::ExecutionContext::Type_QmlContext); -- cgit v1.2.3