aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorMichael Brasser <michael.brasser@live.com>2014-07-23 12:43:38 -0500
committerMichael Brasser <michael.brasser@live.com>2014-08-07 21:36:27 +0200
commitb42c8c4de293af0b6e9c0691daa835939b54d4e1 (patch)
tree0df0321298af530c95d085063500799d82f7aaa4 /src/qml
parentee616b3905106a3eedef9ee964ab283ef45c7dbc (diff)
Accelerate property lookups for C++-based QObject singletons.
Change-Id: Icbdf06a077014db5dd57cba42f84591433ec4196 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp7
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h2
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp9
-rw-r--r--src/qml/compiler/qv4isel_moth_p.h2
-rw-r--r--src/qml/compiler/qv4isel_p.cpp3
-rw-r--r--src/qml/compiler/qv4isel_p.h2
-rw-r--r--src/qml/compiler/qv4jsir_p.h5
-rw-r--r--src/qml/jit/qv4isel_masm.cpp5
-rw-r--r--src/qml/jit/qv4isel_masm_p.h2
-rw-r--r--src/qml/jit/qv4regalloc.cpp2
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp12
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h1
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp4
-rw-r--r--src/qml/qml/qqmlmetatype.cpp5
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp11
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h1
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;