Use the QmlContext to access properties of the scope object
authorLars Knoll <lars.knoll@theqtcompany.com>
Fri, 19 Jun 2015 12:18:13 +0000 (14:18 +0200)
committerSimon Hausmann <simon.hausmann@theqtcompany.com>
Mon, 10 Aug 2015 01:21:57 +0000 (01:21 +0000)
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 <simon.hausmann@theqtcompany.com>
19 files changed:
src/qml/compiler/qqmlirbuilder.cpp
src/qml/compiler/qqmlirbuilder_p.h
src/qml/compiler/qqmltypecompiler.cpp
src/qml/compiler/qv4instr_moth_p.h
src/qml/compiler/qv4isel_moth.cpp
src/qml/compiler/qv4isel_moth_p.h
src/qml/compiler/qv4isel_p.cpp
src/qml/compiler/qv4isel_p.h
src/qml/compiler/qv4jsir.cpp
src/qml/compiler/qv4jsir_p.h
src/qml/jit/qv4isel_masm.cpp
src/qml/jit/qv4isel_masm_p.h
src/qml/jit/qv4regalloc.cpp
src/qml/jsruntime/qv4engine.cpp
src/qml/jsruntime/qv4qobjectwrapper.cpp
src/qml/jsruntime/qv4qobjectwrapper_p.h
src/qml/jsruntime/qv4runtime.cpp
src/qml/jsruntime/qv4runtime_p.h
src/qml/jsruntime/qv4vme_moth.cpp

index d70b04a..dbbc6a0 100644 (file)
@@ -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<QV4::IR::MemberExpressionResolver>();
-    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<QV4::IR::MemberExpressionResolver>();
             initMetaObjectResolver(base->memberResolver, _scopeObject);
             return _block->MEMBER(base, _function->newString(name), pd, QV4::IR::Member::MemberOfQmlScopeObject);
index 63bf677..afb09fe 100644 (file)
@@ -497,7 +497,6 @@ private:
     QQmlPropertyCache *_scopeObject;
     int _qmlContextTemp;
     int _contextObjectTemp;
-    int _scopeObjectTemp;
     int _importedScriptsTemp;
     int _idArrayTemp;
 };
index 9beeda0..7e69823 100644 (file)
@@ -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;
         }
index c4b4d10..7716c1c 100644 (file)
@@ -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);
index 30ec6f2..e90dab3 100644 (file)
@@ -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) {
index bda6556..138448b 100644 (file)
@@ -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);
index 36d8422..a4a3bc3 100644 (file)
@@ -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);
index d1ad4c8..086cc2c 100644 (file)
@@ -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;
index e15d511..036aef7 100644 (file)
@@ -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";
     }
index 391c226..b7b3a28 100644 (file)
@@ -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;
index fd1edb0..1b12238 100644 (file)
@@ -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)
 {
index 072e867..e18a2f4 100644 (file)
@@ -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);
index 9007694..b8e747e 100644 (file)
@@ -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);
index a55755c..4f22f90 100644 (file)
@@ -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;
 }
index 2ac1dfd..5dc1cfe 100644 (file)
@@ -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)
index f1bca62..8b86300 100644 (file)
@@ -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:
index 9239094..16a71ff 100644 (file)
@@ -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<const QmlContext &>(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<const QmlContext &>(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);
index 109caeb..9554481 100644 (file)
@@ -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);
 };
 
index e7b2a18..299eaea 100644 (file)
@@ -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<QV4::CallData *>(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<QV4::CallData *>(stack + instr.callData);
@@ -881,10 +900,6 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
         VALUE(instr.result) = Runtime::getQmlContextObject(static_cast<QV4::NoThrowEngine*>(engine));
     MOTH_END_INSTR(LoadContextObject)
 
-    MOTH_BEGIN_INSTR(LoadQmlScopeObject)
-        VALUE(instr.result) = Runtime::getQmlScopeObject(static_cast<QV4::NoThrowEngine*>(engine));
-    MOTH_END_INSTR(LoadScopeObject)
-
     MOTH_BEGIN_INSTR(LoadQmlSingleton)
         VALUE(instr.result) = Runtime::getQmlSingleton(static_cast<QV4::NoThrowEngine*>(engine), instr.name);
     MOTH_END_INSTR(LoadQmlSingleton)