diff options
author | Erik Verbruggen <erik.verbruggen@digia.com> | 2016-04-12 14:52:23 +0200 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@theqtcompany.com> | 2016-04-12 15:17:04 +0000 |
commit | f6fee09942de7901a708c4e16db0c7c82550e8c5 (patch) | |
tree | 525cb565096b0c12ae25d254dfa02a469ea84a03 /src | |
parent | 8ca22ca7eb5216513410651411fd2e0f07e50f34 (diff) |
QML: When available, use QQmlAccessors to read properties.
When a property is read from a QObject or the QML scope object, and we
can statically resolve the type to qreal/QObject/int/bool/QString, and
the property has an accessor declared for it, then use that accessor to
do the read.
This collapses the path of e.g.:
Runtime::getQmlScopeObjectProperty
-> QObjectWrapper::getProperty
-> QObjectWrapper::getProperty
-> LoadProperty
-> QQmlAccessor::read
(all of which do various checks for all the stuff mentioned above) to:
Runtime::accessQmlScopeObjectQRealProperty
-> QQmlAccessor::read
which is a simple 4-line function, and doesn't need to do any check.
According to valgrind, this saves 170 instructions on x86 for the
simple binding:
Item {
width: height
}
Change-Id: I0761d01e8f1a3c13ecbffe2d8e0317ce9c0a4db0
Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/compiler/qv4instr_moth_p.h | 90 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_moth.cpp | 104 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_moth_p.h | 4 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_p.cpp | 7 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_p.h | 5 | ||||
-rw-r--r-- | src/qml/compiler/qv4jsir.cpp | 12 | ||||
-rw-r--r-- | src/qml/jit/qv4isel_masm.cpp | 79 | ||||
-rw-r--r-- | src/qml/jit/qv4isel_masm_p.h | 4 | ||||
-rw-r--r-- | src/qml/jit/qv4regalloc.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qobjectwrapper_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 110 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime_p.h | 68 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtimeapi_p.h | 21 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 40 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycache_p.h | 2 |
15 files changed, 529 insertions, 22 deletions
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index 93a7170e68..93043135a4 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -81,9 +81,19 @@ QT_BEGIN_NAMESPACE F(SetLookup, setLookup) \ F(StoreQObjectProperty, storeQObjectProperty) \ F(LoadQObjectProperty, loadQObjectProperty) \ + F(LoadQRealQObjectPropertyDirectly, loadQRealQObjectPropertyDirectly) \ + F(LoadQObjectQObjectPropertyDirectly, loadQObjectQObjectPropertyDirectly) \ + F(LoadIntQObjectPropertyDirectly, loadIntQObjectPropertyDirectly) \ + F(LoadBoolQObjectPropertyDirectly, loadBoolQObjectPropertyDirectly) \ + F(LoadQStringQObjectPropertyDirectly, loadQStringQObjectPropertyDirectly) \ F(StoreScopeObjectProperty, storeScopeObjectProperty) \ F(StoreContextObjectProperty, storeContextObjectProperty) \ F(LoadScopeObjectProperty, loadScopeObjectProperty) \ + F(LoadScopeObjectQRealPropertyDirectly, loadScopeObjectQRealPropertyDirectly) \ + F(LoadScopeObjectQObjectPropertyDirectly, loadScopeObjectQObjectPropertyDirectly) \ + F(LoadScopeObjectIntPropertyDirectly, loadScopeObjectIntPropertyDirectly) \ + F(LoadScopeObjectBoolPropertyDirectly, loadScopeObjectBoolPropertyDirectly) \ + F(LoadScopeObjectQStringPropertyDirectly, loadScopeObjectQStringPropertyDirectly) \ F(LoadContextObjectProperty, loadContextObjectProperty) \ F(LoadIdObject, loadIdObject) \ F(LoadAttachedQObjectProperty, loadAttachedQObjectProperty) \ @@ -323,6 +333,36 @@ union Instr Param base; Param result; }; + struct instr_loadScopeObjectQRealPropertyDirectly { + MOTH_INSTR_HEADER + Param base; + Param result; + QQmlAccessors *accessors; + }; + struct instr_loadScopeObjectQObjectPropertyDirectly { + MOTH_INSTR_HEADER + Param base; + Param result; + QQmlAccessors *accessors; + }; + struct instr_loadScopeObjectIntPropertyDirectly { + MOTH_INSTR_HEADER + Param base; + Param result; + QQmlAccessors *accessors; + }; + struct instr_loadScopeObjectBoolPropertyDirectly { + MOTH_INSTR_HEADER + Param base; + Param result; + QQmlAccessors *accessors; + }; + struct instr_loadScopeObjectQStringPropertyDirectly { + MOTH_INSTR_HEADER + Param base; + Param result; + QQmlAccessors *accessors; + }; struct instr_loadContextObjectProperty { MOTH_INSTR_HEADER int propertyIndex; @@ -342,6 +382,46 @@ union Instr Param result; bool captureRequired; }; + struct instr_loadQRealQObjectPropertyDirectly { + MOTH_INSTR_HEADER + Param base; + Param result; + QQmlAccessors *accessors; + int coreIndex; + int notifyIndex; + }; + struct instr_loadQObjectQObjectPropertyDirectly { + MOTH_INSTR_HEADER + Param base; + Param result; + QQmlAccessors *accessors; + int coreIndex; + int notifyIndex; + }; + struct instr_loadIntQObjectPropertyDirectly { + MOTH_INSTR_HEADER + Param base; + Param result; + QQmlAccessors *accessors; + int coreIndex; + int notifyIndex; + }; + struct instr_loadBoolQObjectPropertyDirectly { + MOTH_INSTR_HEADER + Param base; + Param result; + QQmlAccessors *accessors; + int coreIndex; + int notifyIndex; + }; + struct instr_loadQStringQObjectPropertyDirectly { + MOTH_INSTR_HEADER + Param base; + Param result; + QQmlAccessors *accessors; + int coreIndex; + int notifyIndex; + }; struct instr_loadAttachedQObjectProperty { MOTH_INSTR_HEADER int propertyIndex; @@ -800,9 +880,19 @@ union Instr instr_loadProperty loadProperty; instr_getLookup getLookup; instr_loadScopeObjectProperty loadScopeObjectProperty; + instr_loadScopeObjectQRealPropertyDirectly loadScopeObjectQRealPropertyDirectly; + instr_loadScopeObjectQObjectPropertyDirectly loadScopeObjectQObjectPropertyDirectly; + instr_loadScopeObjectIntPropertyDirectly loadScopeObjectIntPropertyDirectly; + instr_loadScopeObjectBoolPropertyDirectly loadScopeObjectBoolPropertyDirectly; + instr_loadScopeObjectQStringPropertyDirectly loadScopeObjectQStringPropertyDirectly; instr_loadContextObjectProperty loadContextObjectProperty; instr_loadIdObject loadIdObject; instr_loadQObjectProperty loadQObjectProperty; + instr_loadQRealQObjectPropertyDirectly loadQRealQObjectPropertyDirectly; + instr_loadQObjectQObjectPropertyDirectly loadQObjectQObjectPropertyDirectly; + instr_loadIntQObjectPropertyDirectly loadIntQObjectPropertyDirectly; + instr_loadBoolQObjectPropertyDirectly loadBoolQObjectPropertyDirectly; + instr_loadQStringQObjectPropertyDirectly loadQStringQObjectPropertyDirectly; instr_loadAttachedQObjectProperty loadAttachedQObjectProperty; instr_storeProperty storeProperty; instr_setLookup setLookup; diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp index edd8425678..b452c4b3d9 100644 --- a/src/qml/compiler/qv4isel_moth.cpp +++ b/src/qml/compiler/qv4isel_moth.cpp @@ -46,6 +46,8 @@ #include <private/qv4regexpobject_p.h> #include <private/qv4compileddata_p.h> #include <private/qqmlengine_p.h> +#include "qml/qqmlaccessors_p.h" +#include "qml/qqmlpropertycache_p.h" #undef USE_TYPE_INFO @@ -737,8 +739,51 @@ void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *target addInstruction(store); } -void InstructionSelection::getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target) -{ +void InstructionSelection::getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, + QQmlPropertyData *property, int index, + IR::Expr *target) +{ + if (property && property->hasAccessors() && property->isFullyResolved()) { + if (kind == IR::Member::MemberOfQmlScopeObject) { + if (property->propType == QMetaType::QReal) { + Instruction::LoadScopeObjectQRealPropertyDirectly load; + load.base = getParam(source); + load.accessors = property->accessors; + load.result = getResultParam(target); + addInstruction(load); + return; + } else if (property->isQObject()) { + Instruction::LoadScopeObjectQObjectPropertyDirectly load; + load.base = getParam(source); + load.accessors = property->accessors; + load.result = getResultParam(target); + addInstruction(load); + return; + } else if (property->propType == QMetaType::Int) { + Instruction::LoadScopeObjectIntPropertyDirectly load; + load.base = getParam(source); + load.accessors = property->accessors; + load.result = getResultParam(target); + addInstruction(load); + return; + } else if (property->propType == QMetaType::Bool) { + Instruction::LoadScopeObjectBoolPropertyDirectly load; + load.base = getParam(source); + load.accessors = property->accessors; + load.result = getResultParam(target); + addInstruction(load); + return; + } else if (property->propType == QMetaType::QString) { + Instruction::LoadScopeObjectQStringPropertyDirectly load; + load.base = getParam(source); + load.accessors = property->accessors; + load.result = getResultParam(target); + addInstruction(load); + return; + } + } + } + if (kind == IR::Member::MemberOfQmlScopeObject) { Instruction::LoadScopeObjectProperty load; load.base = getParam(source); @@ -762,8 +807,59 @@ void InstructionSelection::getQmlContextProperty(IR::Expr *source, IR::Member::M } } -void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingletonProperty, int attachedPropertiesId, IR::Expr *target) -{ +void InstructionSelection::getQObjectProperty(IR::Expr *base, QQmlPropertyData *property, bool captureRequired, bool isSingletonProperty, int attachedPropertiesId, IR::Expr *target) +{ + if (property && property->hasAccessors() && property->isFullyResolved()) { + if (!attachedPropertiesId && !isSingletonProperty) { + if (property->propType == QMetaType::QReal) { + Instruction::LoadQRealQObjectPropertyDirectly load; + load.base = getParam(base); + load.accessors = property->accessors; + load.coreIndex = property->coreIndex; + load.notifyIndex = captureRequired ? property->notifyIndex : -1; + load.result = getResultParam(target); + addInstruction(load); + return; + } else if (property->isQObject()) { + Instruction::LoadQObjectQObjectPropertyDirectly load; + load.base = getParam(base); + load.accessors = property->accessors; + load.coreIndex = property->coreIndex; + load.notifyIndex = captureRequired ? property->notifyIndex : -1; + load.result = getResultParam(target); + addInstruction(load); + return; + } else if (property->propType == QMetaType::Int) { + Instruction::LoadIntQObjectPropertyDirectly load; + load.base = getParam(base); + load.accessors = property->accessors; + load.coreIndex = property->coreIndex; + load.notifyIndex = captureRequired ? property->notifyIndex : -1; + load.result = getResultParam(target); + addInstruction(load); + return; + } else if (property->propType == QMetaType::Bool) { + Instruction::LoadBoolQObjectPropertyDirectly load; + load.base = getParam(base); + load.accessors = property->accessors; + load.coreIndex = property->coreIndex; + load.notifyIndex = captureRequired ? property->notifyIndex : -1; + load.result = getResultParam(target); + addInstruction(load); + return; + } else if (property->propType == QMetaType::QString) { + Instruction::LoadQStringQObjectPropertyDirectly load; + load.base = getParam(base); + load.accessors = property->accessors; + load.coreIndex = property->coreIndex; + load.notifyIndex = captureRequired ? property->notifyIndex : -1; + load.result = getResultParam(target); + addInstruction(load); + return; + } + } + } + const int propertyIndex = property->coreIndex; if (attachedPropertiesId != 0) { Instruction::LoadAttachedQObjectProperty load; load.propertyIndex = propertyIndex; diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h index 29d117af38..bf3909682d 100644 --- a/src/qml/compiler/qv4isel_moth_p.h +++ b/src/qml/compiler/qv4isel_moth_p.h @@ -134,8 +134,8 @@ protected: virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName); virtual void setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex); virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex); - virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target); - virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target); + virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, QQmlPropertyData *property, int index, IR::Expr *target); + virtual void getQObjectProperty(IR::Expr *base, QQmlPropertyData *property, 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 0ae08160ab..6ba23a0951 100644 --- a/src/qml/compiler/qv4isel_p.cpp +++ b/src/qml/compiler/qv4isel_p.cpp @@ -156,14 +156,15 @@ void IRDecoder::visitMove(IR::Move *s) } } if (m->kind == IR::Member::MemberOfQmlScopeObject || m->kind == IR::Member::MemberOfQmlContextObject) { - getQmlContextProperty(m->base, (IR::Member::MemberKind)m->kind, m->property->coreIndex, s->target); + getQmlContextProperty(m->base, (IR::Member::MemberKind)m->kind, m->property, + m->property->coreIndex, s->target); return; } - getQObjectProperty(m->base, m->property->coreIndex, captureRequired, isSingletonProperty, attachedPropertiesId, s->target); + getQObjectProperty(m->base, m->property, captureRequired, isSingletonProperty, attachedPropertiesId, s->target); #endif // V4_BOOTSTRAP return; } else if (m->kind == IR::Member::MemberOfIdObjectsArray) { - getQmlContextProperty(m->base, (IR::Member::MemberKind)m->kind, m->idIndex, s->target); + getQmlContextProperty(m->base, (IR::Member::MemberKind)m->kind, nullptr, m->idIndex, s->target); return; } else if (m->base->asTemp() || m->base->asConst() || m->base->asArgLocal()) { getProperty(m->base, *m->name, s->target); diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h index 88d2071c52..2ee776adf4 100644 --- a/src/qml/compiler/qv4isel_p.h +++ b/src/qml/compiler/qv4isel_p.h @@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE +class QQmlAccessors; class QQmlEnginePrivate; namespace QV4 { @@ -165,8 +166,8 @@ 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, bool isSingletonProperty, int attachedPropertiesId, IR::Expr *target) = 0; - virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target) = 0; + virtual void getQObjectProperty(IR::Expr *base, QQmlPropertyData *property, bool captureRequired, bool isSingletonProperty, int attachedPropertiesId, IR::Expr *target) = 0; + virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, QQmlPropertyData *property, int index, IR::Expr *target) = 0; virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName) = 0; virtual void setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex) = 0; virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex) = 0; diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp index b28db59190..370dfd0fae 100644 --- a/src/qml/compiler/qv4jsir.cpp +++ b/src/qml/compiler/qv4jsir.cpp @@ -927,12 +927,16 @@ void IRPrinter::visitMember(Member *e) e->base->accept(this); *out << '.' << *e->name; #ifndef V4_BOOTSTRAP - if (e->property) + if (e->property) { *out << " (meta-property " << e->property->coreIndex - << " <" << QMetaType::typeName(e->property->propType) - << ">)"; - else if (e->kind == Member::MemberOfIdObjectsArray) + << " <" << QMetaType::typeName(e->property->propType) << ">"; + if (e->property->hasAccessors() && e->property->isFullyResolved()) { + *out << ", accessible"; + } + *out << ")"; + } else if (e->kind == Member::MemberOfIdObjectsArray) { *out << "(id object " << e->idIndex << ")"; + } #endif } diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp index 149037939b..1f5a247a17 100644 --- a/src/qml/jit/qv4isel_masm.cpp +++ b/src/qml/jit/qv4isel_masm.cpp @@ -49,6 +49,7 @@ #include "qv4assembler_p.h" #include "qv4unop_p.h" #include "qv4binop_p.h" +#include <private/qqmlpropertycache_p.h> #include <QtCore/QBuffer> #include <QtCore/QCoreApplication> @@ -753,8 +754,39 @@ void InstructionSelection::getProperty(IR::Expr *base, const QString &name, IR:: } } -void InstructionSelection::getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int index, IR::Expr *target) +void InstructionSelection::getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, QQmlPropertyData *property, int index, IR::Expr *target) { + if (property && property->hasAccessors() && property->isFullyResolved()) { + if (kind == IR::Member::MemberOfQmlScopeObject) { + if (property->propType == QMetaType::QReal) { + generateRuntimeCall(target, accessQmlScopeObjectQRealProperty, + Assembler::PointerToValue(base), + Assembler::TrustedImmPtr(property->accessors)); + return; + } else if (property->isQObject()) { + generateRuntimeCall(target, accessQmlScopeObjectQObjectProperty, + Assembler::PointerToValue(base), + Assembler::TrustedImmPtr(property->accessors)); + return; + } else if (property->propType == QMetaType::Int) { + generateRuntimeCall(target, accessQmlScopeObjectIntProperty, + Assembler::PointerToValue(base), + Assembler::TrustedImmPtr(property->accessors)); + return; + } else if (property->propType == QMetaType::Bool) { + generateRuntimeCall(target, accessQmlScopeObjectBoolProperty, + Assembler::PointerToValue(base), + Assembler::TrustedImmPtr(property->accessors)); + return; + } else if (property->propType == QMetaType::QString) { + generateRuntimeCall(target, accessQmlScopeObjectQStringProperty, + Assembler::PointerToValue(base), + Assembler::TrustedImmPtr(property->accessors)); + return; + } + } + } + if (kind == IR::Member::MemberOfQmlScopeObject) generateRuntimeCall(target, getQmlScopeObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index)); else if (kind == IR::Member::MemberOfQmlContextObject) @@ -765,8 +797,51 @@ void InstructionSelection::getQmlContextProperty(IR::Expr *base, IR::Member::Mem Q_ASSERT(false); } -void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target) +void InstructionSelection::getQObjectProperty(IR::Expr *base, QQmlPropertyData *property, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target) { + if (property && property->hasAccessors() && property->isFullyResolved()) { + if (!attachedPropertiesId && !isSingleton) { + const int notifyIndex = captureRequired ? property->notifyIndex : -1; + if (property->propType == QMetaType::QReal) { + generateRuntimeCall(target, accessQObjectQRealProperty, + Assembler::EngineRegister, Assembler::PointerToValue(base), + Assembler::TrustedImmPtr(property->accessors), + Assembler::TrustedImm32(property->coreIndex), + Assembler::TrustedImm32(notifyIndex)); + return; + } else if (property->isQObject()) { + generateRuntimeCall(target, accessQObjectQObjectProperty, + Assembler::EngineRegister, Assembler::PointerToValue(base), + Assembler::TrustedImmPtr(property->accessors), + Assembler::TrustedImm32(property->coreIndex), + Assembler::TrustedImm32(notifyIndex)); + return; + } else if (property->propType == QMetaType::Int) { + generateRuntimeCall(target, accessQObjectIntProperty, + Assembler::EngineRegister, Assembler::PointerToValue(base), + Assembler::TrustedImmPtr(property->accessors), + Assembler::TrustedImm32(property->coreIndex), + Assembler::TrustedImm32(notifyIndex)); + return; + } else if (property->propType == QMetaType::Bool) { + generateRuntimeCall(target, accessQObjectBoolProperty, + Assembler::EngineRegister, Assembler::PointerToValue(base), + Assembler::TrustedImmPtr(property->accessors), + Assembler::TrustedImm32(property->coreIndex), + Assembler::TrustedImm32(notifyIndex)); + return; + } else if (property->propType == QMetaType::QString) { + generateRuntimeCall(target, accessQObjectQStringProperty, + Assembler::EngineRegister, Assembler::PointerToValue(base), + Assembler::TrustedImmPtr(property->accessors), + Assembler::TrustedImm32(property->coreIndex), + Assembler::TrustedImm32(notifyIndex)); + return; + } + } + } + + const int propertyIndex = property->coreIndex; if (attachedPropertiesId != 0) generateRuntimeCall(target, getQmlAttachedProperty, Assembler::EngineRegister, Assembler::TrustedImm32(attachedPropertiesId), Assembler::TrustedImm32(propertyIndex)); else if (isSingleton) diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h index a92196f5f7..db9d440e83 100644 --- a/src/qml/jit/qv4isel_masm_p.h +++ b/src/qml/jit/qv4isel_masm_p.h @@ -124,8 +124,8 @@ 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 getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target); - virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target); + virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, QQmlPropertyData *property, int index, IR::Expr *target); + virtual void getQObjectProperty(IR::Expr *base, QQmlPropertyData *property, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target); virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName); virtual void setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex); virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex); diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp index 131e0a5b0a..6b5b79e458 100644 --- a/src/qml/jit/qv4regalloc.cpp +++ b/src/qml/jit/qv4regalloc.cpp @@ -528,14 +528,14 @@ protected: // IRDecoder addCall(); } - virtual void getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind /*kind*/, int /*index*/, IR::Expr *target) + virtual void getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind /*kind*/, QQmlPropertyData * /*property*/, int /*index*/, IR::Expr *target) { addDef(target); addUses(base->asTemp(), Use::CouldHaveRegister); addCall(); } - virtual void getQObjectProperty(IR::Expr *base, int /*propertyIndex*/, bool /*captureRequired*/, bool /*isSingleton*/, int /*attachedPropertiesId*/, IR::Expr *target) + virtual void getQObjectProperty(IR::Expr *base, QQmlPropertyData * /*property*/, bool /*captureRequired*/, bool /*isSingleton*/, int /*attachedPropertiesId*/, IR::Expr *target) { addDef(target); addUses(base->asTemp(), Use::CouldHaveRegister); diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index f527afbcc7..0186a8381a 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -59,6 +59,7 @@ #include <private/qqmldata_p.h> #include <private/qqmlpropertycache_p.h> #include <private/qintrusivelist_p.h> +#include <private/qqmlaccessors_p.h> #include <private/qv4value_p.h> #include <private/qv4functionobject_p.h> diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 2abe6eeb06..a974909798 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1415,6 +1415,116 @@ ReturnedValue Runtime::method_getQmlQObjectProperty(ExecutionEngine *engine, con return QV4::QObjectWrapper::getProperty(scope.engine, wrapper->object(), propertyIndex, captureRequired); } +template <typename PropertyType> +static inline PropertyType getQObjectProperty(QObject *object, ExecutionEngine *engine, QQmlAccessors *accessors, int coreIndex, int notifyIndex) +{ + PropertyType t; + accessors->read(object, &t); + if (notifyIndex != -1) { + QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0; + if (ep && ep->propertyCapture) { + if (accessors->notifier) { + QQmlNotifier *n = nullptr; + accessors->notifier(object, &n); + if (n) { + ep->propertyCapture->captureProperty(n); + } + } else { + ep->propertyCapture->captureProperty(object, coreIndex, notifyIndex); + } + } + } + + return t; +} + +ReturnedValue Runtime::method_accessQObjectQRealProperty(ExecutionEngine *engine, + const Value &object, + QQmlAccessors *accessors, int coreIndex, + int notifyIndex) +{ + auto casted = object.as<QObjectWrapper>(); + QObject *o = casted ? casted->object() : nullptr; + if (Q_LIKELY(o)) { + return QV4::Encode(getQObjectProperty<qreal>(o, engine, accessors, coreIndex, notifyIndex)); + } + engine->throwTypeError(QStringLiteral("Cannot read property of null")); + return Encode::undefined(); +} + +ReturnedValue Runtime::method_accessQObjectQObjectProperty(ExecutionEngine *engine, + const Value &object, + QQmlAccessors *accessors, int coreIndex, + int notifyIndex) +{ + auto casted = object.as<QObjectWrapper>(); + QObject *o = casted ? casted->object() : nullptr; + if (Q_LIKELY(o)) { + return QV4::QObjectWrapper::wrap(engine, getQObjectProperty<QObject *>(o, engine, accessors, + coreIndex, + notifyIndex)); + } + + engine->throwTypeError(QStringLiteral("Cannot read property of null")); + return Encode::undefined(); +} + +ReturnedValue Runtime::method_accessQObjectIntProperty(ExecutionEngine *engine, const Value &object, + QQmlAccessors *accessors, int coreIndex, + int notifyIndex) +{ + auto casted = object.as<QObjectWrapper>(); + QObject *o = casted ? casted->object() : nullptr; + if (Q_LIKELY(o)) { + return QV4::Encode(getQObjectProperty<int>(o, engine, accessors, coreIndex, notifyIndex)); + } + engine->throwTypeError(QStringLiteral("Cannot read property of null")); + return Encode::undefined(); +} + +ReturnedValue Runtime::method_accessQObjectBoolProperty(ExecutionEngine *engine, const Value &object, + QQmlAccessors *accessors, int coreIndex, + int notifyIndex) +{ + auto casted = object.as<QObjectWrapper>(); + QObject *o = casted ? casted->object() : nullptr; + if (Q_LIKELY(o)) { + return QV4::Encode(getQObjectProperty<bool>(o, engine, accessors, coreIndex, notifyIndex)); + } + engine->throwTypeError(QStringLiteral("Cannot read property of null")); + return Encode::undefined(); +} + +ReturnedValue Runtime::method_accessQObjectQStringProperty(ExecutionEngine *engine, + const Value &object, + QQmlAccessors *accessors, int coreIndex, + int notifyIndex) +{ + auto casted = object.as<QObjectWrapper>(); + QObject *o = casted ? casted->object() : nullptr; + if (Q_LIKELY(o)) { + return QV4::Encode(engine->newString(getQObjectProperty<QString>(o, engine, accessors, + coreIndex, notifyIndex))); + } + engine->throwTypeError(QStringLiteral("Cannot read property of null")); + return Encode::undefined(); +} + +ReturnedValue Runtime::method_accessQmlScopeObjectQObjectProperty(const Value &context, + QQmlAccessors *accessors) +{ +#ifndef V4_BOOTSTRAP + const QmlContext &c = static_cast<const QmlContext &>(context); + QObject *rv = 0; + accessors->read(c.d()->qml->scopeObject, &rv); + return QV4::QObjectWrapper::wrap(c.engine(), rv); +#else + Q_UNUSED(context); + Q_UNUSED(accessors); + return QV4::Encode::undefined(); +#endif +} + QV4::ReturnedValue Runtime::method_getQmlAttachedProperty(ExecutionEngine *engine, int attachedPropertiesId, int propertyIndex) { QObject *scopeObject = engine->qmlScopeObject(); diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h index d9b46606c9..ffae55995f 100644 --- a/src/qml/jsruntime/qv4runtime_p.h +++ b/src/qml/jsruntime/qv4runtime_p.h @@ -56,8 +56,12 @@ #include "qv4engine_p.h" #include "qv4math_p.h" #include "qv4runtimeapi_p.h" -#include <QtCore/qnumeric.h> +#ifndef V4_BOOTSTRAP +#include <private/qqmlaccessors_p.h> +#include <private/qqmlcontextwrapper_p.h> +#endif +#include <QtCore/qnumeric.h> QT_BEGIN_NAMESPACE @@ -417,6 +421,68 @@ inline Bool Runtime::method_toBoolean(const Value &value) return value.toBoolean(); } +inline ReturnedValue Runtime::method_accessQmlScopeObjectQRealProperty(const Value &context, + QQmlAccessors *accessors) +{ +#ifndef V4_BOOTSTRAP + const QmlContext &c = static_cast<const QmlContext &>(context); + qreal rv = 0; + accessors->read(c.d()->qml->scopeObject, &rv); + return QV4::Encode(rv); +#else + Q_UNUSED(context); + Q_UNUSED(accessors); + return QV4::Encode::undefined(); +#endif +} + +inline ReturnedValue Runtime::method_accessQmlScopeObjectIntProperty(const Value &context, + QQmlAccessors *accessors) +{ +#ifndef V4_BOOTSTRAP + const QmlContext &c = static_cast<const QmlContext &>(context); + int rv = 0; + accessors->read(c.d()->qml->scopeObject, &rv); + return QV4::Encode(rv); +#else + Q_UNUSED(context); + Q_UNUSED(accessors); + return QV4::Encode::undefined(); +#endif +} + +inline ReturnedValue Runtime::method_accessQmlScopeObjectBoolProperty(const Value &context, + QQmlAccessors *accessors) +{ +#ifndef V4_BOOTSTRAP + const QmlContext &c = static_cast<const QmlContext &>(context); + bool rv = false; + accessors->read(c.d()->qml->scopeObject, &rv); + return QV4::Encode(rv); +#else + Q_UNUSED(context); + Q_UNUSED(accessors); + return QV4::Encode::undefined(); +#endif +} + +inline ReturnedValue Runtime::method_accessQmlScopeObjectQStringProperty(ExecutionEngine *engine, + const Value &context, + QQmlAccessors *accessors) +{ +#ifndef V4_BOOTSTRAP + const QmlContext &c = static_cast<const QmlContext &>(context); + QString rv; + accessors->read(c.d()->qml->scopeObject, &rv); + return QV4::Encode(engine->newString(rv)); +#else + Q_UNUSED(engine); + Q_UNUSED(context); + Q_UNUSED(accessors); + return QV4::Encode::undefined(); +#endif +} + } // namespace QV4 QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h index 9eb6a124b4..bf153223a0 100644 --- a/src/qml/jsruntime/qv4runtimeapi_p.h +++ b/src/qml/jsruntime/qv4runtimeapi_p.h @@ -156,6 +156,16 @@ struct Q_QML_PRIVATE_EXPORT Runtime { , INIT_RUNTIME_METHOD(setQmlScopeObjectProperty) , INIT_RUNTIME_METHOD(setQmlContextObjectProperty) , INIT_RUNTIME_METHOD(setQmlQObjectProperty) + , INIT_RUNTIME_METHOD(accessQObjectQRealProperty) + , INIT_RUNTIME_METHOD(accessQObjectQObjectProperty) + , INIT_RUNTIME_METHOD(accessQObjectIntProperty) + , INIT_RUNTIME_METHOD(accessQObjectBoolProperty) + , INIT_RUNTIME_METHOD(accessQObjectQStringProperty) + , INIT_RUNTIME_METHOD(accessQmlScopeObjectQRealProperty) + , INIT_RUNTIME_METHOD(accessQmlScopeObjectQObjectProperty) + , INIT_RUNTIME_METHOD(accessQmlScopeObjectIntProperty) + , INIT_RUNTIME_METHOD(accessQmlScopeObjectBoolProperty) + , INIT_RUNTIME_METHOD(accessQmlScopeObjectQStringProperty) { } // call @@ -292,6 +302,17 @@ struct Q_QML_PRIVATE_EXPORT Runtime { RUNTIME_METHOD(void, setQmlScopeObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value)); RUNTIME_METHOD(void, setQmlContextObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value)); RUNTIME_METHOD(void, setQmlQObjectProperty, (ExecutionEngine *engine, const Value &object, int propertyIndex, const Value &value)); + + RUNTIME_METHOD(ReturnedValue, accessQObjectQRealProperty, (ExecutionEngine *engine, const Value &object, QQmlAccessors *accessors, int coreIndex, int notifyIndex)); + RUNTIME_METHOD(ReturnedValue, accessQObjectQObjectProperty, (ExecutionEngine *engine, const Value &object, QQmlAccessors *accessors, int coreIndex, int notifyIndex)); + RUNTIME_METHOD(ReturnedValue, accessQObjectIntProperty, (ExecutionEngine *engine, const Value &object, QQmlAccessors *accessors, int coreIndex, int notifyIndex)); + RUNTIME_METHOD(ReturnedValue, accessQObjectBoolProperty, (ExecutionEngine *engine, const Value &object, QQmlAccessors *accessors, int coreIndex, int notifyIndex)); + RUNTIME_METHOD(ReturnedValue, accessQObjectQStringProperty, (ExecutionEngine *engine, const Value &object, QQmlAccessors *accessors, int coreIndex, int notifyIndex)); + RUNTIME_METHOD(ReturnedValue, accessQmlScopeObjectQRealProperty, (const Value &context, QQmlAccessors *accessors)); + RUNTIME_METHOD(ReturnedValue, accessQmlScopeObjectQObjectProperty, (const Value &context, QQmlAccessors *accessors)); + RUNTIME_METHOD(ReturnedValue, accessQmlScopeObjectIntProperty, (const Value &context, QQmlAccessors *accessors)); + RUNTIME_METHOD(ReturnedValue, accessQmlScopeObjectBoolProperty, (const Value &context, QQmlAccessors *accessors)); + RUNTIME_METHOD(ReturnedValue, accessQmlScopeObjectQStringProperty, (ExecutionEngine *engine, const Value &context, QQmlAccessors *accessors)); }; #undef RUNTIME_METHOD diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index ec4509a5cc..9ad21305f7 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -519,6 +519,26 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code STOREVALUE(instr.result, engine->runtime.getQmlQObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, instr.captureRequired)); MOTH_END_INSTR(LoadQObjectProperty) + MOTH_BEGIN_INSTR(LoadQRealQObjectPropertyDirectly) + STOREVALUE(instr.result, engine->runtime.accessQObjectQRealProperty(engine, VALUE(instr.base), instr.accessors, instr.coreIndex, instr.notifyIndex)); + MOTH_END_INSTR(LoadQRealQObjectPropertyDirectly) + + MOTH_BEGIN_INSTR(LoadQObjectQObjectPropertyDirectly) + STOREVALUE(instr.result, engine->runtime.accessQObjectQObjectProperty(engine, VALUE(instr.base), instr.accessors, instr.coreIndex, instr.notifyIndex)); + MOTH_END_INSTR(LoadQObjectQObjectPropertyDirectly) + + MOTH_BEGIN_INSTR(LoadIntQObjectPropertyDirectly) + STOREVALUE(instr.result, engine->runtime.accessQObjectIntProperty(engine, VALUE(instr.base), instr.accessors, instr.coreIndex, instr.notifyIndex)); + MOTH_END_INSTR(LoadIntQObjectPropertyDirectly) + + MOTH_BEGIN_INSTR(LoadBoolQObjectPropertyDirectly) + STOREVALUE(instr.result, engine->runtime.accessQObjectBoolProperty(engine, VALUE(instr.base), instr.accessors, instr.coreIndex, instr.notifyIndex)); + MOTH_END_INSTR(LoadQRealQObjectPropertyDirectly) + + MOTH_BEGIN_INSTR(LoadQStringQObjectPropertyDirectly) + STOREVALUE(instr.result, engine->runtime.accessQObjectQStringProperty(engine, VALUE(instr.base), instr.accessors, instr.coreIndex, instr.notifyIndex)); + MOTH_END_INSTR(LoadQStringQObjectPropertyDirectly) + MOTH_BEGIN_INSTR(StoreScopeObjectProperty) engine->runtime.setQmlScopeObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source)); CHECK_EXCEPTION; @@ -528,6 +548,26 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code STOREVALUE(instr.result, engine->runtime.getQmlScopeObjectProperty(engine, VALUE(instr.base), instr.propertyIndex)); MOTH_END_INSTR(LoadScopeObjectProperty) + MOTH_BEGIN_INSTR(LoadScopeObjectQRealPropertyDirectly) + STOREVALUE(instr.result, engine->runtime.accessQmlScopeObjectQRealProperty(VALUE(instr.base), instr.accessors)); + MOTH_END_INSTR(LoadScopeObjectQRealPropertyDirectly) + + MOTH_BEGIN_INSTR(LoadScopeObjectQObjectPropertyDirectly) + STOREVALUE(instr.result, engine->runtime.accessQmlScopeObjectQObjectProperty(VALUE(instr.base), instr.accessors)); + MOTH_END_INSTR(LoadScopeObjectQObjectPropertyDirectly) + + MOTH_BEGIN_INSTR(LoadScopeObjectIntPropertyDirectly) + STOREVALUE(instr.result, engine->runtime.accessQmlScopeObjectIntProperty(VALUE(instr.base), instr.accessors)); + MOTH_END_INSTR(LoadScopeObjectIntPropertyDirectly) + + MOTH_BEGIN_INSTR(LoadScopeObjectBoolPropertyDirectly) + STOREVALUE(instr.result, engine->runtime.accessQmlScopeObjectBoolProperty(VALUE(instr.base), instr.accessors)); + MOTH_END_INSTR(LoadScopeObjectBoolPropertyDirectly) + + MOTH_BEGIN_INSTR(LoadScopeObjectQStringPropertyDirectly) + STOREVALUE(instr.result, engine->runtime.accessQmlScopeObjectQStringProperty(engine, VALUE(instr.base), instr.accessors)); + MOTH_END_INSTR(LoadScopeObjectQStringPropertyDirectly) + MOTH_BEGIN_INSTR(StoreContextObjectProperty) engine->runtime.setQmlContextObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source)); CHECK_EXCEPTION; diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h index bb39a5e371..4fb84198d9 100644 --- a/src/qml/qml/qqmlpropertycache_p.h +++ b/src/qml/qml/qqmlpropertycache_p.h @@ -162,6 +162,8 @@ public: overrideIndex >= 0; } bool hasRevision() const { return !(flags & HasAccessors) && revision != 0; } + bool isFullyResolved() const { return !(flags & NotFullyResolved); } + // Returns -1 if not a value type virtual property inline int getValueTypeCoreIndex() const; |