diff options
author | Michael Brasser <michael.brasser@live.com> | 2014-07-23 12:43:38 -0500 |
---|---|---|
committer | Michael Brasser <michael.brasser@live.com> | 2014-08-07 21:36:27 +0200 |
commit | b42c8c4de293af0b6e9c0691daa835939b54d4e1 (patch) | |
tree | 0df0321298af530c95d085063500799d82f7aaa4 /src | |
parent | ee616b3905106a3eedef9ee964ab283ef45c7dbc (diff) |
Accelerate property lookups for C++-based QObject singletons.
Change-Id: Icbdf06a077014db5dd57cba42f84591433ec4196
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/compiler/qqmlirbuilder.cpp | 7 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth_p.h | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_moth.cpp | 9 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_moth_p.h | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_p.cpp | 3 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_p.h | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4jsir_p.h | 5 | ||||
-rw-r--r-- | src/qml/jit/qv4isel_masm.cpp | 5 | ||||
-rw-r--r-- | src/qml/jit/qv4isel_masm_p.h | 2 | ||||
-rw-r--r-- | src/qml/jit/qv4regalloc.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 12 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmltypewrapper.cpp | 11 | ||||
-rw-r--r-- | src/qml/qml/qqmltypewrapper_p.h | 1 |
16 files changed, 61 insertions, 12 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index f02e92ceb2..b61297ee09 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -1820,6 +1820,13 @@ static QV4::IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, QV4::IR::Membe tdata->release(); resolver->flags |= AllPropertiesAreFinal; return resolver->resolveMember(qmlEngine, resolver, member); + } else if (type->isSingleton()) { + const QMetaObject *singletonMeta = type->singletonInstanceInfo()->instanceMetaObject; + if (singletonMeta) { // QJSValue-based singletons cannot be accelerated + initMetaObjectResolver(resolver, qmlEngine->cache(singletonMeta)); + member->kind = QV4::IR::Member::MemberOfSingletonObject; + return resolver->resolveMember(qmlEngine, resolver, member); + } } else if (const QMetaObject *attachedMeta = type->attachedPropertiesType()) { QQmlPropertyCache *cache = qmlEngine->cache(attachedMeta); initMetaObjectResolver(resolver, cache); diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index d70c82233f..f7b7d23a49 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -73,6 +73,7 @@ QT_BEGIN_NAMESPACE F(StoreQObjectProperty, storeQObjectProperty) \ F(LoadQObjectProperty, loadQObjectProperty) \ F(LoadAttachedQObjectProperty, loadAttachedQObjectProperty) \ + F(LoadSingletonQObjectProperty, loadQObjectProperty) \ F(Push, push) \ F(CallValue, callValue) \ F(CallProperty, callProperty) \ @@ -305,7 +306,6 @@ union Instr int propertyIndex; Param base; Param result; - int attachedPropertiesId; bool captureRequired; }; struct instr_loadAttachedQObjectProperty { diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp index 7c67ae2301..958dfc7fbb 100644 --- a/src/qml/compiler/qv4isel_moth.cpp +++ b/src/qml/compiler/qv4isel_moth.cpp @@ -713,7 +713,7 @@ void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *target addInstruction(store); } -void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Expr *target) +void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingletonProperty, int attachedPropertiesId, IR::Expr *target) { if (attachedPropertiesId != 0) { Instruction::LoadAttachedQObjectProperty load; @@ -721,6 +721,13 @@ void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, load.result = getResultParam(target); load.attachedPropertiesId = attachedPropertiesId; addInstruction(load); + } else if (isSingletonProperty) { + Instruction::LoadSingletonQObjectProperty load; + load.base = getParam(base); + load.propertyIndex = propertyIndex; + load.result = getResultParam(target); + load.captureRequired = captureRequired; + addInstruction(load); } else { Instruction::LoadQObjectProperty load; load.base = getParam(base); diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h index 2fdb7c007c..d64c604aba 100644 --- a/src/qml/compiler/qv4isel_moth_p.h +++ b/src/qml/compiler/qv4isel_moth_p.h @@ -124,7 +124,7 @@ protected: virtual void getProperty(IR::Expr *base, const QString &name, IR::Expr *target); virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName); virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex); - virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Expr *target); + virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target); virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target); virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex); virtual void copyValue(IR::Expr *source, IR::Expr *target); diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp index 1aa0c4dad8..2acf97f8c2 100644 --- a/src/qml/compiler/qv4isel_p.cpp +++ b/src/qml/compiler/qv4isel_p.cpp @@ -152,6 +152,7 @@ void IRDecoder::visitMove(IR::Move *s) Q_ASSERT(m->kind != IR::Member::MemberOfEnum); const int attachedPropertiesId = m->attachedPropertiesIdOrEnumValue; + const bool isSingletonProperty = m->kind == IR::Member::MemberOfSingletonObject; if (_function && attachedPropertiesId == 0 && !m->property->isConstant()) { if (m->kind == IR::Member::MemberOfQmlContextObject) { @@ -162,7 +163,7 @@ void IRDecoder::visitMove(IR::Move *s) captureRequired = false; } } - getQObjectProperty(m->base, m->property->coreIndex, captureRequired, attachedPropertiesId, s->target); + getQObjectProperty(m->base, m->property->coreIndex, captureRequired, isSingletonProperty, attachedPropertiesId, s->target); #endif // V4_BOOTSTRAP return; } else if (m->base->asTemp() || m->base->asConst() || m->base->asArgLocal()) { diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h index cbfc21c211..854fc5c444 100644 --- a/src/qml/compiler/qv4isel_p.h +++ b/src/qml/compiler/qv4isel_p.h @@ -154,7 +154,7 @@ public: // to implement by subclasses: virtual void setActivationProperty(IR::Expr *source, const QString &targetName) = 0; virtual void initClosure(IR::Closure *closure, IR::Expr *target) = 0; virtual void getProperty(IR::Expr *base, const QString &name, IR::Expr *target) = 0; - virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Expr *target) = 0; + virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingletonProperty, int attachedPropertiesId, IR::Expr *target) = 0; virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName) = 0; virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex) = 0; virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target) = 0; diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h index 606313d0c1..fcdcdf9038 100644 --- a/src/qml/compiler/qv4jsir_p.h +++ b/src/qml/compiler/qv4jsir_p.h @@ -568,14 +568,14 @@ struct Member: Expr { UnspecifiedMember, MemberOfEnum, MemberOfQmlScopeObject, - MemberOfQmlContextObject + MemberOfQmlContextObject, + MemberOfSingletonObject }; Expr *base; const QString *name; QQmlPropertyData *property; int attachedPropertiesIdOrEnumValue; // depending on kind - uchar memberIsEnum : 1; uchar freeOfSideEffects : 1; // This is set for example for for QObject properties. All sorts of extra behavior @@ -602,7 +602,6 @@ struct Member: Expr { this->name = name; this->property = property; this->attachedPropertiesIdOrEnumValue = attachedPropertiesIdOrEnumValue; - this->memberIsEnum = false; this->freeOfSideEffects = false; this->inhibitTypeConversionOnWrite = property != 0; this->kind = kind; diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp index 353a29425d..8449ff6c0c 100644 --- a/src/qml/jit/qv4isel_masm.cpp +++ b/src/qml/jit/qv4isel_masm.cpp @@ -659,10 +659,13 @@ void InstructionSelection::getProperty(IR::Expr *base, const QString &name, IR:: } } -void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Expr *target) +void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target) { if (attachedPropertiesId != 0) generateFunctionCall(target, Runtime::getQmlAttachedProperty, Assembler::ContextRegister, Assembler::TrustedImm32(attachedPropertiesId), Assembler::TrustedImm32(propertyIndex)); + else if (isSingleton) + generateFunctionCall(target, Runtime::getQmlSingletonQObjectProperty, Assembler::ContextRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(propertyIndex), + Assembler::TrustedImm32(captureRequired)); else generateFunctionCall(target, Runtime::getQmlQObjectProperty, Assembler::ContextRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(propertyIndex), Assembler::TrustedImm32(captureRequired)); diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h index 9c0bc73a65..9ed8be844b 100644 --- a/src/qml/jit/qv4isel_masm_p.h +++ b/src/qml/jit/qv4isel_masm_p.h @@ -115,7 +115,7 @@ protected: virtual void setActivationProperty(IR::Expr *source, const QString &targetName); virtual void initClosure(IR::Closure *closure, IR::Expr *target); virtual void getProperty(IR::Expr *base, const QString &name, IR::Expr *target); - virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Expr *target); + virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target); virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName); virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex); virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target); diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp index 52c2936352..8ba3320c58 100644 --- a/src/qml/jit/qv4regalloc.cpp +++ b/src/qml/jit/qv4regalloc.cpp @@ -538,7 +538,7 @@ protected: // IRDecoder addCall(); } - virtual void getQObjectProperty(IR::Expr *base, int /*propertyIndex*/, bool /*captureRequired*/, int /*attachedPropertiesId*/, IR::Expr *target) + virtual void getQObjectProperty(IR::Expr *base, int /*propertyIndex*/, bool /*captureRequired*/, bool /*isSingleton*/, int /*attachedPropertiesId*/, IR::Expr *target) { addDef(target); addUses(base->asTemp(), Use::CouldHaveRegister); diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 7ea8dbd0aa..05a2027f9b 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -53,6 +53,7 @@ #include "private/qlocale_tools_p.h" #include "qv4scopedvalue_p.h" #include <private/qqmlcontextwrapper_p.h> +#include <private/qqmltypewrapper_p.h> #include "qv4qobjectwrapper_p.h" #include <private/qv8engine_p.h> #endif @@ -1324,6 +1325,17 @@ QV4::ReturnedValue Runtime::getQmlAttachedProperty(ExecutionContext *ctx, int at return QV4::QObjectWrapper::getProperty(attachedObject, ctx, propertyIndex, /*captureRequired*/true); } +ReturnedValue Runtime::getQmlSingletonQObjectProperty(ExecutionContext *ctx, const ValueRef object, int propertyIndex, bool captureRequired) +{ + Scope scope(ctx); + QV4::Scoped<QmlTypeWrapper> wrapper(scope, object); + if (!wrapper) { + ctx->throwTypeError(QStringLiteral("Cannot read property of null")); + return Encode::undefined(); + } + return QV4::QObjectWrapper::getProperty(wrapper->singletonObject(), ctx, propertyIndex, captureRequired); +} + void Runtime::setQmlQObjectProperty(ExecutionContext *ctx, const ValueRef object, int propertyIndex, const ValueRef value) { Scope scope(ctx); diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h index 992b027379..d216f58db0 100644 --- a/src/qml/jsruntime/qv4runtime_p.h +++ b/src/qml/jsruntime/qv4runtime_p.h @@ -229,6 +229,7 @@ struct Q_QML_PRIVATE_EXPORT Runtime { static ReturnedValue getQmlSingleton(NoThrowContext *ctx, String *name); static ReturnedValue getQmlAttachedProperty(ExecutionContext *ctx, int attachedPropertiesId, int propertyIndex); static ReturnedValue getQmlQObjectProperty(ExecutionContext *ctx, const ValueRef object, int propertyIndex, bool captureRequired); + static ReturnedValue getQmlSingletonQObjectProperty(ExecutionContext *ctx, const ValueRef object, int propertyIndex, bool captureRequired); static void setQmlQObjectProperty(ExecutionContext *ctx, const ValueRef object, int propertyIndex, const ValueRef value); }; diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 7f058bf8b7..2df4bdd076 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -330,6 +330,10 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code STOREVALUE(instr.result, Runtime::getQmlAttachedProperty(context, instr.attachedPropertiesId, instr.propertyIndex)); MOTH_END_INSTR(LoadAttachedQObjectProperty) + MOTH_BEGIN_INSTR(LoadSingletonQObjectProperty) + STOREVALUE(instr.result, Runtime::getQmlSingletonQObjectProperty(context, VALUEPTR(instr.base), instr.propertyIndex, instr.captureRequired)); + MOTH_END_INSTR(LoadSingletonQObjectProperty) + MOTH_BEGIN_INSTR(Push) TRACE(inline, "stack size: %u", instr.value); stackSize = instr.value; diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 42f67f3345..900ac5a2e4 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -233,7 +233,10 @@ void QQmlType::SingletonInstanceInfo::init(QQmlEngine *e) v4->popContext(); } else if (qobjectCallback && !qobjectApi(e)) { v4->pushGlobalContext(); - setQObjectApi(e, qobjectCallback(e, e)); + QObject *o = qobjectCallback(e, e); + setQObjectApi(e, o); + // if this object can use a property cache, create it now + QQmlData::ensurePropertyCache(e, o); v4->popContext(); } else if (!url.isEmpty() && !qobjectApi(e)) { v4->pushGlobalContext(); diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index 53afd36437..0ae3e31ec0 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -75,6 +75,17 @@ bool QmlTypeWrapper::isSingleton() const return d()->type && d()->type->isSingleton(); } +QObject* QmlTypeWrapper::singletonObject() const +{ + if (!isSingleton()) + return 0; + + QQmlEngine *e = d()->v8->engine(); + QQmlType::SingletonInstanceInfo *siinfo = d()->type->singletonInstanceInfo(); + siinfo->init(e); + return siinfo->qobjectApi(e); +} + QVariant QmlTypeWrapper::toVariant() const { if (d()->type && d()->type->isSingleton()) { diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h index 27ecac991e..becd73eaf0 100644 --- a/src/qml/qml/qqmltypewrapper_p.h +++ b/src/qml/qml/qqmltypewrapper_p.h @@ -87,6 +87,7 @@ private: public: bool isSingleton() const; + QObject *singletonObject() const; QVariant toVariant() const; |