From b2889568170b20ca8f870a7f4a1a1c3ac9f698c5 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 19 Jun 2015 14:18:13 +0200 Subject: [PATCH] Use the QmlContext to access properties of the scope object Add some runtime methods to access properties of the scope object directly (using the QmlContext), and generate proper code to call those. Change-Id: I0b29357c9a3b9ad53ba568ec6cb763e8ecb10f21 Reviewed-by: Simon Hausmann --- src/qml/compiler/qqmlirbuilder.cpp | 9 +------ src/qml/compiler/qqmlirbuilder_p.h | 1 - src/qml/compiler/qqmltypecompiler.cpp | 3 +-- src/qml/compiler/qv4instr_moth_p.h | 32 +++++++++++++++++----- src/qml/compiler/qv4isel_moth.cpp | 48 ++++++++++++++++++++++++++++----- src/qml/compiler/qv4isel_moth_p.h | 4 ++- src/qml/compiler/qv4isel_p.cpp | 22 +++++++++++++-- src/qml/compiler/qv4isel_p.h | 4 ++- src/qml/compiler/qv4jsir.cpp | 2 -- src/qml/compiler/qv4jsir_p.h | 3 +-- src/qml/jit/qv4isel_masm.cpp | 35 ++++++++++++++++++++---- src/qml/jit/qv4isel_masm_p.h | 4 ++- src/qml/jit/qv4regalloc.cpp | 32 ++++++++++++++++------ src/qml/jsruntime/qv4engine.cpp | 2 ++ src/qml/jsruntime/qv4qobjectwrapper.cpp | 11 +++++--- src/qml/jsruntime/qv4qobjectwrapper_p.h | 1 + src/qml/jsruntime/qv4runtime.cpp | 29 ++++++++++++++++---- src/qml/jsruntime/qv4runtime_p.h | 4 ++- src/qml/jsruntime/qv4vme_moth.cpp | 23 +++++++++++++--- 19 files changed, 210 insertions(+), 59 deletions(-) diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index d70b04a..dbbc6a0 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -1458,7 +1458,6 @@ JSCodeGen::JSCodeGen(const QString &fileName, const QString &sourceCode, QV4::IR , _scopeObject(0) , _qmlContextTemp(-1) , _contextObjectTemp(-1) - , _scopeObjectTemp(-1) , _importedScriptsTemp(-1) , _idArrayTemp(-1) { @@ -1767,7 +1766,6 @@ void JSCodeGen::beginFunctionBodyHook() { _qmlContextTemp = _block->newTemp(); _contextObjectTemp = _block->newTemp(); - _scopeObjectTemp = _block->newTemp(); _importedScriptsTemp = _block->newTemp(); _idArrayTemp = _block->newTemp(); @@ -1780,11 +1778,6 @@ void JSCodeGen::beginFunctionBodyHook() initMetaObjectResolver(temp->memberResolver, _contextObject); move(temp, _block->NAME(QV4::IR::Name::builtin_qml_context_object, 0, 0)); - temp = _block->TEMP(_scopeObjectTemp); - temp->memberResolver = _function->New(); - initMetaObjectResolver(temp->memberResolver, _scopeObject); - move(temp, _block->NAME(QV4::IR::Name::builtin_qml_scope_object, 0, 0)); - move(_block->TEMP(_importedScriptsTemp), _block->NAME(QV4::IR::Name::builtin_qml_imported_scripts_object, 0, 0)); move(_block->TEMP(_idArrayTemp), _block->NAME(QV4::IR::Name::builtin_qml_id_array, 0, 0)); #endif @@ -1862,7 +1855,7 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int if (propertyExistsButForceNameLookup) return 0; if (pd) { - QV4::IR::Temp *base = _block->TEMP(_scopeObjectTemp); + QV4::IR::Temp *base = _block->TEMP(_qmlContextTemp); base->memberResolver = _function->New(); initMetaObjectResolver(base->memberResolver, _scopeObject); return _block->MEMBER(base, _function->newString(name), pd, QV4::IR::Member::MemberOfQmlScopeObject); diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index 63bf677..afb09fe 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -497,7 +497,6 @@ private: QQmlPropertyCache *_scopeObject; int _qmlContextTemp; int _contextObjectTemp; - int _scopeObjectTemp; int _importedScriptsTemp; int _idArrayTemp; }; diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 9beeda0..7e69823 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -2626,8 +2626,7 @@ void QQmlJavaScriptBindingExpressionSimplificationPass::visitMove(QV4::IR::Move if (n->builtin == QV4::IR::Name::builtin_qml_context || n->builtin == QV4::IR::Name::builtin_qml_id_array || n->builtin == QV4::IR::Name::builtin_qml_imported_scripts_object - || n->builtin == QV4::IR::Name::builtin_qml_context_object - || n->builtin == QV4::IR::Name::builtin_qml_scope_object) { + || n->builtin == QV4::IR::Name::builtin_qml_context_object) { // these are free of side-effects return; } diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index c4b4d10..7716c1c 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -64,12 +64,15 @@ QT_BEGIN_NAMESPACE F(SetLookup, setLookup) \ F(StoreQObjectProperty, storeQObjectProperty) \ F(LoadQObjectProperty, loadQObjectProperty) \ + F(StoreScopeObjectProperty, storeScopeObjectProperty) \ + F(LoadScopeObjectProperty, loadScopeObjectProperty) \ F(LoadAttachedQObjectProperty, loadAttachedQObjectProperty) \ F(LoadSingletonQObjectProperty, loadQObjectProperty) \ F(Push, push) \ F(CallValue, callValue) \ F(CallProperty, callProperty) \ F(CallPropertyLookup, callPropertyLookup) \ + F(CallScopeObjectProperty, callScopeObjectProperty) \ F(CallElement, callElement) \ F(CallActivationProperty, callActivationProperty) \ F(CallGlobalLookup, callGlobalLookup) \ @@ -129,7 +132,6 @@ QT_BEGIN_NAMESPACE F(LoadQmlIdArray, loadQmlIdArray) \ F(LoadQmlImportedScripts, loadQmlImportedScripts) \ F(LoadQmlContextObject, loadQmlContextObject) \ - F(LoadQmlScopeObject, loadQmlScopeObject) \ F(LoadQmlSingleton, loadQmlSingleton) #if defined(Q_CC_GNU) && (!defined(Q_CC_INTEL) || __INTEL_COMPILER >= 1200) @@ -294,6 +296,12 @@ union Instr Param base; Param result; }; + struct instr_loadScopeObjectProperty { + MOTH_INSTR_HEADER + int propertyIndex; + Param base; + Param result; + }; struct instr_loadQObjectProperty { MOTH_INSTR_HEADER int propertyIndex; @@ -319,6 +327,12 @@ union Instr Param base; Param source; }; + struct instr_storeScopeObjectProperty { + MOTH_INSTR_HEADER + Param base; + int propertyIndex; + Param source; + }; struct instr_storeQObjectProperty { MOTH_INSTR_HEADER Param base; @@ -378,6 +392,14 @@ union Instr Param base; Param result; }; + struct instr_callScopeObjectProperty { + MOTH_INSTR_HEADER + int index; + quint32 argc; + quint32 callData; + Param base; + Param result; + }; struct instr_callElement { MOTH_INSTR_HEADER Param base; @@ -701,10 +723,6 @@ union Instr MOTH_INSTR_HEADER Param result; }; - struct instr_loadQmlScopeObject { - MOTH_INSTR_HEADER - Param result; - }; struct instr_loadQmlSingleton { MOTH_INSTR_HEADER Param result; @@ -730,15 +748,18 @@ union Instr instr_storeElementLookup storeElementLookup; instr_loadProperty loadProperty; instr_getLookup getLookup; + instr_loadScopeObjectProperty loadScopeObjectProperty; instr_loadQObjectProperty loadQObjectProperty; instr_loadAttachedQObjectProperty loadAttachedQObjectProperty; instr_storeProperty storeProperty; instr_setLookup setLookup; + instr_storeScopeObjectProperty storeScopeObjectProperty; instr_storeQObjectProperty storeQObjectProperty; instr_push push; instr_callValue callValue; instr_callProperty callProperty; instr_callPropertyLookup callPropertyLookup; + instr_callScopeObjectProperty callScopeObjectProperty; instr_callElement callElement; instr_callActivationProperty callActivationProperty; instr_callGlobalLookup callGlobalLookup; @@ -798,7 +819,6 @@ union Instr instr_loadQmlIdArray loadQmlIdArray; instr_loadQmlImportedScripts loadQmlImportedScripts; instr_loadQmlContextObject loadQmlContextObject; - instr_loadQmlScopeObject loadQmlScopeObject; instr_loadQmlSingleton loadQmlSingleton; static int size(Type type); diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp index 30ec6f2..e90dab3 100644 --- a/src/qml/compiler/qv4isel_moth.cpp +++ b/src/qml/compiler/qv4isel_moth.cpp @@ -461,6 +461,21 @@ void InstructionSelection::callValue(IR::Expr *value, IR::ExprList *args, IR::Ex addInstruction(call); } +void InstructionSelection::callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::ExprList *args, IR::Expr *result) +{ + if (kind == IR::Member::MemberOfQmlScopeObject) { + Instruction::CallScopeObjectProperty call; + call.base = getParam(base); + call.index = propertyIndex; + prepareCallArgs(args, call.argc); + call.callData = callDataStart(); + call.result = getResultParam(result); + addInstruction(call); + } else { + Q_ASSERT(false); + } +} + void InstructionSelection::callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result) { @@ -593,13 +608,6 @@ void InstructionSelection::loadQmlContextObject(IR::Expr *e) addInstruction(load); } -void InstructionSelection::loadQmlScopeObject(IR::Expr *e) -{ - Instruction::LoadQmlScopeObject load; - load.result = getResultParam(e); - addInstruction(load); -} - void InstructionSelection::loadQmlSingleton(const QString &name, IR::Expr *e) { Instruction::LoadQmlSingleton load; @@ -701,6 +709,19 @@ void InstructionSelection::setProperty(IR::Expr *source, IR::Expr *targetBase, addInstruction(store); } +void InstructionSelection::setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex) +{ + if (kind == IR::Member::MemberOfQmlScopeObject) { + Instruction::StoreScopeObjectProperty store; + store.base = getParam(targetBase); + store.propertyIndex = propertyIndex; + store.source = getParam(source); + addInstruction(store); + } else { + Q_ASSERT(false); + } +} + void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex) { Instruction::StoreQObjectProperty store; @@ -710,6 +731,19 @@ 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) +{ + if (kind == IR::Member::MemberOfQmlScopeObject) { + Instruction::LoadScopeObjectProperty load; + load.base = getParam(source); + load.propertyIndex = index; + load.result = getResultParam(target); + addInstruction(load); + } else { + Q_ASSERT(false); + } +} + void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingletonProperty, int attachedPropertiesId, IR::Expr *target) { if (attachedPropertiesId != 0) { diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h index bda6556..138448b 100644 --- a/src/qml/compiler/qv4isel_moth_p.h +++ b/src/qml/compiler/qv4isel_moth_p.h @@ -95,6 +95,7 @@ protected: virtual void callBuiltinSetupArgumentObject(IR::Expr *result); virtual void callBuiltinConvertThisToObject(); virtual void callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result); + virtual void callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::ExprList *args, IR::Expr *result); virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result); virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Expr *result); virtual void convertType(IR::Expr *source, IR::Expr *target); @@ -106,7 +107,6 @@ protected: virtual void loadQmlIdArray(IR::Expr *e); virtual void loadQmlImportedScripts(IR::Expr *e); virtual void loadQmlContextObject(IR::Expr *e); - virtual void loadQmlScopeObject(IR::Expr *e); virtual void loadQmlSingleton(const QString &name, IR::Expr *e); virtual void loadConst(IR::Const *sourceConst, IR::Expr *e); virtual void loadString(const QString &str, IR::Expr *target); @@ -116,7 +116,9 @@ protected: virtual void initClosure(IR::Closure *closure, IR::Expr *target); 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 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 getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target); virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex); diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp index 36d8422..a4a3bc3 100644 --- a/src/qml/compiler/qv4isel_p.cpp +++ b/src/qml/compiler/qv4isel_p.cpp @@ -97,8 +97,6 @@ void IRDecoder::visitMove(IR::Move *s) loadQmlIdArray(s->target); else if (n->builtin == IR::Name::builtin_qml_context_object) loadQmlContextObject(s->target); - else if (n->builtin == IR::Name::builtin_qml_scope_object) - loadQmlScopeObject(s->target); else if (n->builtin == IR::Name::builtin_qml_imported_scripts_object) loadQmlImportedScripts(s->target); else if (n->qmlSingleton) @@ -155,6 +153,10 @@ void IRDecoder::visitMove(IR::Move *s) captureRequired = false; } } + if (m->kind == IR::Member::MemberOfQmlScopeObject) { + getQmlContextProperty(m->base, (IR::Member::MemberKind)m->kind, m->property->coreIndex, s->target); + return; + } getQObjectProperty(m->base, m->property->coreIndex, captureRequired, isSingletonProperty, attachedPropertiesId, s->target); #endif // V4_BOOTSTRAP return; @@ -176,6 +178,12 @@ void IRDecoder::visitMove(IR::Move *s) callBuiltin(c, s->target); return; } else if (Member *member = c->base->asMember()) { +#ifndef V4_BOOTSTRAP + if (member->kind == IR::Member::MemberOfQmlScopeObject) { + callQmlContextProperty(member->base, (IR::Member::MemberKind)member->kind, member->property->coreIndex, c->args, s->target); + return; + } +#endif callProperty(member->base, *member->name, c->args, s->target); return; } else if (Subscript *ss = c->base->asSubscript()) { @@ -199,6 +207,10 @@ void IRDecoder::visitMove(IR::Move *s) #ifdef V4_BOOTSTRAP Q_UNIMPLEMENTED(); #else + if (m->kind == IR::Member::MemberOfQmlScopeObject) { + setQmlContextProperty(s->source, m->base, (IR::Member::MemberKind)m->kind, m->property->coreIndex); + return; + } setQObjectProperty(s->source, m->base, m->property->coreIndex); #endif return; @@ -240,6 +252,12 @@ void IRDecoder::visitExp(IR::Exp *s) callValue(c->base, c->args, 0); } else if (Member *member = c->base->asMember()) { Q_ASSERT(member->base->asTemp() || member->base->asArgLocal()); +#ifndef V4_BOOTSTRAP + if (member->kind == IR::Member::MemberOfQmlScopeObject) { + callQmlContextProperty(member->base, (IR::Member::MemberKind)member->kind, member->property->coreIndex, c->args, 0); + return; + } +#endif callProperty(member->base, *member->name, c->args, 0); } else if (Subscript *s = c->base->asSubscript()) { callSubscript(s->base, s->index, c->args, 0); diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h index d1ad4c8..086cc2c 100644 --- a/src/qml/compiler/qv4isel_p.h +++ b/src/qml/compiler/qv4isel_p.h @@ -129,6 +129,7 @@ public: // to implement by subclasses: virtual void callBuiltinSetupArgumentObject(IR::Expr *result) = 0; virtual void callBuiltinConvertThisToObject() = 0; virtual void callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result) = 0; + virtual void callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::ExprList *args, IR::Expr *result) = 0; virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result) = 0; virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Expr *result) = 0; virtual void convertType(IR::Expr *source, IR::Expr *target) = 0; @@ -140,7 +141,6 @@ public: // to implement by subclasses: virtual void loadQmlIdArray(IR::Expr *target) = 0; virtual void loadQmlImportedScripts(IR::Expr *target) = 0; virtual void loadQmlContextObject(IR::Expr *target) = 0; - virtual void loadQmlScopeObject(IR::Expr *target) = 0; virtual void loadQmlSingleton(const QString &name, IR::Expr *target) = 0; virtual void loadConst(IR::Const *sourceConst, IR::Expr *target) = 0; virtual void loadString(const QString &str, IR::Expr *target) = 0; @@ -150,7 +150,9 @@ public: // to implement by subclasses: 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 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; virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target) = 0; virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex) = 0; diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp index e15d511..036aef7 100644 --- a/src/qml/compiler/qv4jsir.cpp +++ b/src/qml/compiler/qv4jsir.cpp @@ -347,8 +347,6 @@ const char *builtin_to_string(Name::Builtin b) return "builtin_qml_id_array"; case IR::Name::builtin_qml_imported_scripts_object: return "builtin_qml_imported_scripts_object"; - case IR::Name::builtin_qml_scope_object: - return "builtin_qml_scope_object"; case IR::Name::builtin_qml_context_object: return "builtin_qml_context_object"; } diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h index 391c226..b7b3a28 100644 --- a/src/qml/compiler/qv4jsir_p.h +++ b/src/qml/compiler/qv4jsir_p.h @@ -340,8 +340,7 @@ struct Name: Expr { builtin_qml_context, builtin_qml_id_array, builtin_qml_imported_scripts_object, - builtin_qml_context_object, - builtin_qml_scope_object + builtin_qml_context_object }; const QString *id; diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp index fd1edb0..1b12238 100644 --- a/src/qml/jit/qv4isel_masm.cpp +++ b/src/qml/jit/qv4isel_masm.cpp @@ -594,11 +594,6 @@ void InstructionSelection::loadQmlContextObject(IR::Expr *temp) generateFunctionCall(temp, Runtime::getQmlContextObject, Assembler::EngineRegister); } -void InstructionSelection::loadQmlScopeObject(IR::Expr *temp) -{ - generateFunctionCall(temp, Runtime::getQmlScopeObject, Assembler::EngineRegister); -} - void InstructionSelection::loadQmlSingleton(const QString &name, IR::Expr *temp) { generateFunctionCall(temp, Runtime::getQmlSingleton, Assembler::EngineRegister, Assembler::StringToIndex(name)); @@ -685,6 +680,14 @@ 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) +{ + if (kind == IR::Member::MemberOfQmlScopeObject) + generateFunctionCall(target, Runtime::getQmlScopeObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index)); + else + Q_ASSERT(false); +} + void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target) { if (attachedPropertiesId != 0) @@ -713,6 +716,15 @@ void InstructionSelection::setProperty(IR::Expr *source, IR::Expr *targetBase, } } +void InstructionSelection::setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex) +{ + if (kind == IR::Member::MemberOfQmlScopeObject) + generateFunctionCall(Assembler::Void, Runtime::setQmlScopeObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(targetBase), + Assembler::TrustedImm32(propertyIndex), Assembler::PointerToValue(source)); + else + Q_ASSERT(false); +} + void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex) { generateFunctionCall(Assembler::Void, Runtime::setQmlQObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(targetBase), @@ -906,6 +918,19 @@ void InstructionSelection::binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr binop.generate(leftSource, rightSource, target); } +void InstructionSelection::callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::ExprList *args, IR::Expr *result) +{ + prepareCallData(args, base); + + if (kind == IR::Member::MemberOfQmlScopeObject) + generateFunctionCall(result, Runtime::callQmlScopeObjectProperty, + Assembler::EngineRegister, + Assembler::TrustedImm32(propertyIndex), + baseAddressForCallData()); + else + Q_ASSERT(false); +} + void InstructionSelection::callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result) { diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h index 072e867..e18a2f4 100644 --- a/src/qml/jit/qv4isel_masm_p.h +++ b/src/qml/jit/qv4isel_masm_p.h @@ -91,6 +91,7 @@ protected: virtual void callBuiltinSetupArgumentObject(IR::Expr *result); virtual void callBuiltinConvertThisToObject(); virtual void callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result); + virtual void callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::ExprList *args, IR::Expr *result); virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result); virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Expr *result); virtual void convertType(IR::Expr *source, IR::Expr *target); @@ -99,7 +100,6 @@ protected: virtual void loadQmlIdArray(IR::Expr *target); virtual void loadQmlImportedScripts(IR::Expr *target); virtual void loadQmlContextObject(IR::Expr *target); - virtual void loadQmlScopeObject(IR::Expr *target); virtual void loadQmlSingleton(const QString &name, IR::Expr *target); virtual void loadConst(IR::Const *sourceConst, IR::Expr *target); virtual void loadString(const QString &str, IR::Expr *target); @@ -108,8 +108,10 @@ 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 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 getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target); virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex); diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp index 9007694..b8e747e 100644 --- a/src/qml/jit/qv4regalloc.cpp +++ b/src/qml/jit/qv4regalloc.cpp @@ -299,6 +299,16 @@ protected: // IRDecoder addCall(); } + virtual void callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind /*kind*/, int propertyIndex, IR::ExprList *args, IR::Expr *result) + { + Q_UNUSED(propertyIndex) + + addDef(result); + addUses(base->asTemp(), Use::CouldHaveRegister); + addUses(args, Use::CouldHaveRegister); + addCall(); + } + virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result) { @@ -445,14 +455,6 @@ protected: // IRDecoder addCall(); } - virtual void loadQmlScopeObject(Expr *temp) - { - Q_UNUSED(temp); - - addDef(temp); - addCall(); - } - virtual void loadQmlSingleton(const QString &/*name*/, Expr *temp) { Q_UNUSED(temp); @@ -517,6 +519,13 @@ protected: // IRDecoder addCall(); } + virtual void setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind /*kind*/, int /*propertyIndex*/) + { + addUses(source->asTemp(), Use::CouldHaveRegister); + addUses(targetBase->asTemp(), Use::CouldHaveRegister); + addCall(); + } + virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int /*propertyIndex*/) { addUses(source->asTemp(), Use::CouldHaveRegister); @@ -524,6 +533,13 @@ protected: // IRDecoder addCall(); } + virtual void getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind /*kind*/, 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) { addDef(target); diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index a55755c..4f22f90 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -743,6 +743,8 @@ Heap::QmlContext *ExecutionEngine::qmlContext() const Heap::QmlContextWrapper *ExecutionEngine::qmlContextObject() const { Heap::QmlContext *ctx = qmlContext(); + if (!ctx) + return 0; Q_ASSERT(ctx->qml); return ctx->qml; } diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 2ac1dfd..5dc1cfe 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -657,9 +657,14 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *obje void QObjectWrapper::setProperty(ExecutionEngine *engine, int propertyIndex, const Value &value) { - if (QQmlData::wasDeleted(d()->object)) + setProperty(engine, d()->object, propertyIndex, value); +} + +void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, const Value &value) +{ + if (QQmlData::wasDeleted(object)) return; - QQmlData *ddata = QQmlData::get(d()->object, /*create*/false); + QQmlData *ddata = QQmlData::get(object, /*create*/false); if (!ddata) return; @@ -667,7 +672,7 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, int propertyIndex, con Q_ASSERT(cache); QQmlPropertyData *property = cache->property(propertyIndex); Q_ASSERT(property); // We resolved this property earlier, so it better exist! - return setProperty(engine, d()->object, property, value); + return setProperty(engine, object, property, value); } bool QObjectWrapper::isEqualTo(Managed *a, Managed *b) diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index f1bca62..8b86300 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -115,6 +115,7 @@ struct Q_QML_EXPORT QObjectWrapper : public Object using Object::get; static ReturnedValue getProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, bool captureRequired); + static void setProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, const Value &value); void setProperty(ExecutionEngine *engine, int propertyIndex, const Value &value); protected: diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 9239094..16a71ff 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -948,6 +948,18 @@ ReturnedValue Runtime::callActivationProperty(ExecutionEngine *engine, int nameI return o->call(callData); } +ReturnedValue Runtime::callQmlScopeObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData) +{ + Scope scope(engine); + ScopedFunctionObject o(scope, getQmlScopeObjectProperty(engine, callData->thisObject, propertyIndex)); + if (!o) { + QString error = QStringLiteral("Property '%1' of object %2 is not a function").arg(propertyIndex).arg(callData->thisObject.toQStringNoThrow()); + return engine->throwTypeError(error); + } + + return o->call(callData); +} + ReturnedValue Runtime::callProperty(ExecutionEngine *engine, int nameIndex, CallData *callData) { Scope scope(engine); @@ -1351,11 +1363,6 @@ ReturnedValue Runtime::getQmlContextObject(NoThrowEngine *engine) return QObjectWrapper::wrap(engine, context->contextObject); } -ReturnedValue Runtime::getQmlScopeObject(NoThrowEngine *engine) -{ - return QObjectWrapper::wrap(engine, engine->qmlScopeObject()); -} - ReturnedValue Runtime::getQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired) { Scope scope(engine); @@ -1377,6 +1384,12 @@ QV4::ReturnedValue Runtime::getQmlAttachedProperty(ExecutionEngine *engine, int return QV4::QObjectWrapper::getProperty(engine, attachedObject, propertyIndex, /*captureRequired*/true); } +ReturnedValue Runtime::getQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex) +{ + const QmlContext &c = static_cast(context); + return QV4::QObjectWrapper::getProperty(engine, c.d()->qml->scopeObject, propertyIndex, false); +} + ReturnedValue Runtime::getQmlSingletonQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired) { Scope scope(engine); @@ -1388,6 +1401,12 @@ ReturnedValue Runtime::getQmlSingletonQObjectProperty(ExecutionEngine *engine, c return QV4::QObjectWrapper::getProperty(scope.engine, wrapper->singletonObject(), propertyIndex, captureRequired); } +void Runtime::setQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value) +{ + const QmlContext &c = static_cast(context); + return QV4::QObjectWrapper::setProperty(engine, c.d()->qml->scopeObject, propertyIndex, value); +} + void Runtime::setQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, const Value &value) { Scope scope(engine); diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h index 109caeb..9554481 100644 --- a/src/qml/jsruntime/qv4runtime_p.h +++ b/src/qml/jsruntime/qv4runtime_p.h @@ -91,6 +91,7 @@ struct Q_QML_PRIVATE_EXPORT Runtime { // call static ReturnedValue callGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData); static ReturnedValue callActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData); + static ReturnedValue callQmlScopeObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData); static ReturnedValue callProperty(ExecutionEngine *engine, int nameIndex, CallData *callData); static ReturnedValue callPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData); static ReturnedValue callElement(ExecutionEngine *engine, const Value &index, CallData *callData); @@ -211,11 +212,12 @@ struct Q_QML_PRIVATE_EXPORT Runtime { static ReturnedValue getQmlIdArray(NoThrowEngine *engine); static ReturnedValue getQmlImportedScripts(NoThrowEngine *engine); static ReturnedValue getQmlContextObject(NoThrowEngine *engine); - static ReturnedValue getQmlScopeObject(NoThrowEngine *engine); static ReturnedValue getQmlSingleton(NoThrowEngine *engine, int nameIndex); static ReturnedValue getQmlAttachedProperty(ExecutionEngine *engine, int attachedPropertiesId, int propertyIndex); + static ReturnedValue getQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex); static ReturnedValue getQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired); static ReturnedValue getQmlSingletonQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired); + static void setQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value); static void setQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, const Value &value); }; diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index e7b2a18..299eaea 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -513,6 +513,15 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code STOREVALUE(instr.result, Runtime::getQmlQObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, instr.captureRequired)); MOTH_END_INSTR(LoadQObjectProperty) + MOTH_BEGIN_INSTR(StoreScopeObjectProperty) + Runtime::setQmlScopeObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source)); + CHECK_EXCEPTION; + MOTH_END_INSTR(StoreScopeObjectProperty) + + MOTH_BEGIN_INSTR(LoadScopeObjectProperty) + STOREVALUE(instr.result, Runtime::getQmlScopeObjectProperty(engine, VALUE(instr.base), instr.propertyIndex)); + MOTH_END_INSTR(LoadScopeObjectProperty) + MOTH_BEGIN_INSTR(LoadAttachedQObjectProperty) STOREVALUE(instr.result, Runtime::getQmlAttachedProperty(engine, instr.attachedPropertiesId, instr.propertyIndex)); MOTH_END_INSTR(LoadAttachedQObjectProperty) @@ -566,6 +575,16 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code STOREVALUE(instr.result, Runtime::callPropertyLookup(engine, instr.lookupIndex, callData)); MOTH_END_INSTR(CallPropertyLookup) + MOTH_BEGIN_INSTR(CallScopeObjectProperty) + TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData()); + Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); + QV4::CallData *callData = reinterpret_cast(stack + instr.callData); + callData->tag = QV4::Value::Integer_Type; + callData->argc = instr.argc; + callData->thisObject = VALUE(instr.base); + STOREVALUE(instr.result, Runtime::callQmlScopeObjectProperty(engine, instr.index, callData)); + MOTH_END_INSTR(CallScopeObjectProperty) + MOTH_BEGIN_INSTR(CallElement) Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast(stack + instr.callData); @@ -881,10 +900,6 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code VALUE(instr.result) = Runtime::getQmlContextObject(static_cast(engine)); MOTH_END_INSTR(LoadContextObject) - MOTH_BEGIN_INSTR(LoadQmlScopeObject) - VALUE(instr.result) = Runtime::getQmlScopeObject(static_cast(engine)); - MOTH_END_INSTR(LoadScopeObject) - MOTH_BEGIN_INSTR(LoadQmlSingleton) VALUE(instr.result) = Runtime::getQmlSingleton(static_cast(engine), instr.name); MOTH_END_INSTR(LoadQmlSingleton) -- 2.7.4