Split off 2 builtins into their own instruction.
authorErik Verbruggen <erik.verbruggen@me.com>
Wed, 23 Jan 2013 09:11:05 +0000 (10:11 +0100)
committerLars Knoll <lars.knoll@digia.com>
Wed, 23 Jan 2013 09:59:56 +0000 (10:59 +0100)
The foreach-iterator-object and foreach-next-property-name now have
their own interpreter instructions. Also cleaned up the parameter
passing helper methods.

Change-Id: I3f375ba29e1ae914e707039b157fa011878b88b6
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
moth/qv4instr_moth_p.h
moth/qv4isel_moth.cpp
moth/qv4isel_moth_p.h
moth/qv4vme_moth.cpp

index e3cc843..bafa9aa 100644 (file)
@@ -19,6 +19,8 @@
     F(CallValue, callValue) \
     F(CallProperty, callProperty) \
     F(CallBuiltin, callBuiltin) \
+    F(CallBuiltinForeachIteratorObject, callBuiltinForeachIteratorObject) \
+    F(CallBuiltinForeachNextPropertyName, callBuiltinForeachNextPropertyName) \
     F(CallBuiltinDeleteMember, callBuiltinDeleteMember) \
     F(CallBuiltinDeleteSubscript, callBuiltinDeleteSubscript) \
     F(CallBuiltinDeleteName, callBuiltinDeleteName) \
@@ -158,13 +160,20 @@ union Instr
             builtin_create_exception_handler,
             builtin_delete_exception_handler,
             builtin_get_exception,
-            builtin_foreach_iterator_object,
-            builtin_foreach_next_property_name,
             builtin_push_with,
             builtin_pop_with
         } builtin;
-        quint32 argc;
-        quint32 args;
+        int argTemp;
+        int targetTempIndex;
+    };
+    struct instr_callBuiltinForeachIteratorObject {
+        MOTH_INSTR_HEADER
+        int argTemp;
+        int targetTempIndex;
+    };
+    struct instr_callBuiltinForeachNextPropertyName {
+        MOTH_INSTR_HEADER
+        int argTemp;
         int targetTempIndex;
     };
     struct instr_callBuiltinDeleteMember {
@@ -313,6 +322,8 @@ union Instr
     instr_callValue callValue;
     instr_callProperty callProperty;
     instr_callBuiltin callBuiltin;
+    instr_callBuiltinForeachIteratorObject callBuiltinForeachIteratorObject;
+    instr_callBuiltinForeachNextPropertyName callBuiltinForeachNextPropertyName;
     instr_callBuiltinDeleteMember callBuiltinDeleteMember;
     instr_callBuiltinDeleteSubscript callBuiltinDeleteSubscript;
     instr_callBuiltinDeleteName callBuiltinDeleteName;
index ce890e0..1a7c8d1 100644 (file)
@@ -608,24 +608,15 @@ void InstructionSelection::inplaceMemberOp(IR::AluOp oper, IR::Expr *source, IR:
     addInstruction(imo);
 }
 
-void InstructionSelection::prepareCallArg(IR::Expr *e, quint32 &argc, quint32 &args)
-{
-    IR::ExprList exprs;
-    exprs.init(e);
-    prepareCallArgs(&exprs, argc, args);
-}
-
 void InstructionSelection::prepareCallArgs(IR::ExprList *e, quint32 &argc, quint32 &args)
 {
     bool singleArgIsTemp = false;
     if (e && e->next == 0) {
-        // ok, only 1 argument in the cal...
+        // ok, only 1 argument in the call...
         const int idx = e->expr->asTemp()->index;
-        if (idx >= 0) {
-            // not an argument to this function...
-            // so if it's not a local, we're in:
-            singleArgIsTemp = idx >= _function->locals.size();
-        }
+        // We can only pass a reference into the stack, which holds temps that
+        // are not arguments (idx >= 0) nor locals (idx >= localCound).
+        singleArgIsTemp = idx >= _function->locals.size();
     }
 
     if (singleArgIsTemp) {
@@ -790,7 +781,7 @@ void InstructionSelection::callBuiltinThrow(IR::Temp *arg)
 {
     Instruction::CallBuiltin call;
     call.builtin = Instruction::CallBuiltin::builtin_throw;
-    prepareCallArg(arg, call.argc, call.args);
+    call.argTemp = arg->index;
     addInstruction(call);
 }
 
@@ -826,18 +817,17 @@ void InstructionSelection::callBuiltinGetException(IR::Temp *result)
 
 void InstructionSelection::callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result)
 {
-    Instruction::CallBuiltin call;
-    call.builtin = Instruction::CallBuiltin::builtin_foreach_iterator_object;
-    prepareCallArg(arg, call.argc, call.args);
+    Instruction::CallBuiltinForeachIteratorObject call;
+    call.argTemp = arg->index;
     call.targetTempIndex = result ? result->index : scratchTempIndex();
     addInstruction(call);
 }
 
 void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result)
 {
-    Instruction::CallBuiltin call;
-    call.builtin = Instruction::CallBuiltin::builtin_foreach_next_property_name;
-    prepareCallArg(arg, call.argc, call.args);
+    Instruction::CallBuiltinForeachNextPropertyName call;
+    call.argTemp = arg->index;
+    qDebug("result index: %d", result ? result->index : -1);
     call.targetTempIndex = result ? result->index : scratchTempIndex();
     addInstruction(call);
 }
@@ -846,8 +836,7 @@ void InstructionSelection::callBuiltinPushWith(IR::Temp *arg)
 {
     Instruction::CallBuiltin call;
     call.builtin = Instruction::CallBuiltin::builtin_push_with;
-    prepareCallArg(arg, call.argc, call.args);
-    assert(call.argc == 1);
+    call.argTemp = arg->index;
     addInstruction(call);
 }
 
index e109064..0350033 100644 (file)
@@ -78,7 +78,6 @@ private:
     };
 
     void simpleMove(IR::Move *);
-    void prepareCallArg(IR::Expr *e, quint32 &argc, quint32 &args);
     void prepareCallArgs(IR::ExprList *, quint32 &, quint32 &);
 
     int outgoingArgumentTempStart() const { return _function->tempCount; }
index 27b92a4..f861996 100644 (file)
@@ -123,6 +123,9 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co
 #endif
         )
 {
+#ifdef DO_TRACE_INSTR
+    qDebug("Starting VME with context=%p and code=%p", context, code);
+#endif // DO_TRACE_INSTR
 
 #ifdef MOTH_THREADED_INTERPRETER
     if (storeJumpTable) {
@@ -165,7 +168,8 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co
 
     MOTH_BEGIN_INSTR(LoadName)
         TRACE(inline, "property name = %s", instr.name->toQString().toUtf8().constData());
-        TEMP(instr.targetTempIndex) = __qmljs_get_activation_property(context, instr.name);
+        VM::Value val = __qmljs_get_activation_property(context, instr.name);
+        TEMP(instr.targetTempIndex) = val;
     MOTH_END_INSTR(LoadName)
 
     MOTH_BEGIN_INSTR(StoreName)
@@ -214,35 +218,34 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co
             }
         }
 #endif // DO_TRACE_INSTR
-        quint32 argStart = instr.args - context->variableCount();
+        int argStart = instr.args - context->variableCount();
         TRACE(Call, "value index = %d, argStart = %d, argc = %d, result temp index = %d", instr.destIndex, argStart, instr.argc, instr.targetTempIndex);
         VM::Value *args = stack + argStart;
         TEMP(instr.targetTempIndex) = __qmljs_call_value(context, VM::Value::undefinedValue(), TEMP(instr.destIndex), args, instr.argc);
     MOTH_END_INSTR(CallValue)
 
     MOTH_BEGIN_INSTR(CallProperty)
-        quint32 argStart = instr.args - context->variableCount();
+        int argStart = instr.args - context->variableCount();
+    // TODO: change this assert everywhere to include a minimum
+    // TODO: the args calculation is duplicate code, fix that
         VM::Value *args = stack + argStart;
         VM::Value base = TEMP(instr.baseTemp);
         TEMP(instr.targetTempIndex) = __qmljs_call_property(context, base, instr.name, args, instr.argc);
     MOTH_END_INSTR(CallProperty)
 
     MOTH_BEGIN_INSTR(CallBuiltin)
-        quint32 argStart = instr.args - context->variableCount();
-        VM::Value *args = stack + argStart;
-        void *buf;
+        // TODO: split this into separate instructions
         switch (instr.builtin) {
         case Instr::instr_callBuiltin::builtin_throw:
             TRACE(builtin_throw, "Throwing now...%s", "");
-            Q_ASSERT(instr.argc == 1);
-            __qmljs_builtin_throw(args[0], context);
+            __qmljs_builtin_throw(TEMP(instr.argTemp), context);
             break;
         case Instr::instr_callBuiltin::builtin_rethrow:
             __qmljs_builtin_rethrow(context);
             break;
         case Instr::instr_callBuiltin::builtin_create_exception_handler: {
             TRACE(builtin_create_exception_handler, "%s", "");
-            buf = __qmljs_create_exception_handler(context);
+            void *buf = __qmljs_create_exception_handler(context);
             // The targetTempIndex is the only value we need from the instr to
             // continue execution when an exception is caught.
             int targetTempIndex = instr.targetTempIndex;
@@ -266,17 +269,8 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co
         case Instr::instr_callBuiltin::builtin_get_exception:
             TEMP(instr.targetTempIndex) = __qmljs_get_exception(context);
             break;
-        case Instr::instr_callBuiltin::builtin_foreach_iterator_object:
-            Q_ASSERT(instr.argc == 1);
-            TEMP(instr.targetTempIndex) = __qmljs_foreach_iterator_object(args[0], context);
-            break;
-        case Instr::instr_callBuiltin::builtin_foreach_next_property_name:
-            Q_ASSERT(instr.argc == 1);
-            TEMP(instr.targetTempIndex) = __qmljs_foreach_next_property_name(args[0]);
-            break;
         case Instr::instr_callBuiltin::builtin_push_with:
-            Q_ASSERT(instr.argc == 1);
-            __qmljs_builtin_push_with(args[0], context);
+            __qmljs_builtin_push_with(TEMP(instr.argTemp), context);
             break;
         case Instr::instr_callBuiltin::builtin_pop_with:
             __qmljs_builtin_pop_with(context);
@@ -287,6 +281,18 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co
         }
     MOTH_END_INSTR(CallBuiltin)
 
+    MOTH_BEGIN_INSTR(CallBuiltinForeachIteratorObject)
+        VM::Value &obj = TEMP(instr.argTemp);
+        VM::Value it = __qmljs_foreach_iterator_object(obj, context);
+        TEMP(instr.targetTempIndex) = it;
+    MOTH_END_INSTR(CallBuiltinForeachIteratorObject)
+
+    MOTH_BEGIN_INSTR(CallBuiltinForeachNextPropertyName)
+        VM::Value &iter = TEMP(instr.argTemp);
+        VM::Value val = __qmljs_foreach_next_property_name(iter);
+        TEMP(instr.targetTempIndex) = val;
+    MOTH_END_INSTR(CallBuiltinForeachNextPropertyName)
+
     MOTH_BEGIN_INSTR(CallBuiltinDeleteMember)
         TEMP(instr.targetTempIndex) = __qmljs_delete_member(context, TEMP(instr.base), instr.member);
     MOTH_END_INSTR(CallBuiltinDeleteMember)
@@ -328,20 +334,20 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co
     MOTH_END_INSTR(CallBuiltinDefineProperty)
 
     MOTH_BEGIN_INSTR(CreateValue)
-        quint32 argStart = instr.args - context->variableCount();
+        int argStart = instr.args - context->variableCount();
         VM::Value *args = stack + argStart;
         TEMP(instr.targetTempIndex) = __qmljs_construct_value(context, TEMP(instr.func), args, instr.argc);
     MOTH_END_INSTR(CreateValue)
 
     MOTH_BEGIN_INSTR(CreateProperty)
-        quint32 argStart = instr.args - context->variableCount();
+        int argStart = instr.args - context->variableCount();
         VM::Value *args = stack + argStart;
         TEMP(instr.targetTempIndex) = __qmljs_construct_property(context, TEMP(instr.base), instr.name, args, instr.argc);
     MOTH_END_INSTR(CreateProperty)
 
     MOTH_BEGIN_INSTR(CreateActivationProperty)
         TRACE(inline, "property name = %s, argc = %d", instr.name->toQString().toUtf8().constData(), instr.argc);
-        quint32 argStart = instr.args - context->variableCount();
+        int argStart = instr.args - context->variableCount();
         VM::Value *args = stack + argStart;
         TEMP(instr.targetTempIndex) = __qmljs_construct_activation_property(context, instr.name, args, instr.argc);
     MOTH_END_INSTR(CreateActivationProperty)
@@ -392,6 +398,7 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co
     MOTH_END_INSTR(InplaceMemberOp)
 
     MOTH_BEGIN_INSTR(InplaceNameOp)
+        TRACE(name, "%s", instr.targetName->toQString().toUtf8().constData());
         VM::Value source = instr.sourceIsTemp ? TEMP(instr.source.tempIndex) : instr.source.value;
         instr.alu(source,
                   instr.targetName,