aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2019-01-03 17:00:36 +0100
committerSimon Hausmann <simon.hausmann@qt.io>2019-03-20 13:26:59 +0000
commit710580aa84c5c3273e883d9e650f3159ad8250f3 (patch)
tree40cedea160afc2d9e659a1c8ff029b9a8916e469
parent69d76d59cec0dcff4c52eef24e779fbef14beeca (diff)
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 <ulf.hermann@qt.io>
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h9
-rw-r--r--src/qml/jsruntime/qv4qmlcontext.cpp55
-rw-r--r--src/qml/jsruntime/qv4qmlcontext_p.h4
3 files changed, 65 insertions, 3 deletions
diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
index e4d9ad8328..2384a1194e 100644
--- a/src/qml/jsruntime/qv4lookup_p.h
+++ b/src/qml/jsruntime/qv4lookup_p.h
@@ -129,6 +129,15 @@ struct Lookup {
QQmlPropertyCache *propertyCache;
QQmlPropertyData *propertyData;
} qgadgetLookup;
+ struct {
+ quintptr unused1;
+ quintptr unused2;
+ int scriptIndex;
+ } qmlContextScriptLookup;
+ struct {
+ Heap::Object *singleton;
+ quintptr unused;
+ } qmlContextSingletonLookup;
};
uint nameIndex;
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<Heap::Object*>(
+ 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<QQmlContextWrapper> 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> 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);
diff --git a/src/qml/jsruntime/qv4qmlcontext_p.h b/src/qml/jsruntime/qv4qmlcontext_p.h
index f704280bf4..5eacea5830 100644
--- a/src/qml/jsruntime/qv4qmlcontext_p.h
+++ b/src/qml/jsruntime/qv4qmlcontext_p.h
@@ -100,11 +100,13 @@ struct Q_QML_EXPORT QQmlContextWrapper : Object
inline QQmlContextData *getContext() const { return *d()->context; }
static ReturnedValue getPropertyAndBase(const QQmlContextWrapper *resource, PropertyKey id, const Value *receiver,
- bool *hasProperty, Value *base);
+ bool *hasProperty, Value *base, Lookup *lookup = nullptr);
static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
static bool virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver);
static ReturnedValue resolveQmlContextPropertyLookupGetter(Lookup *l, ExecutionEngine *engine, Value *base);
+ static ReturnedValue lookupScript(Lookup *l, ExecutionEngine *engine, Value *base);
+ static ReturnedValue lookupSingleton(Lookup *l, ExecutionEngine *engine, Value *base);
};
struct Q_QML_EXPORT QmlContext : public ExecutionContext