Change TEMP handling in the interpreter.
authorErik Verbruggen <erik.verbruggen@me.com>
Fri, 25 Jan 2013 18:32:30 +0000 (19:32 +0100)
committerLars Knoll <lars.knoll@digia.com>
Tue, 29 Jan 2013 08:24:15 +0000 (09:24 +0100)
By introducing the Param struct, and moving the ValueOrTemp into it
too, the parameter decoding for instructions is cleaner and less
error-prone: it de-couples the HIR/MIR representation from the
interpreter representation, and allows for proper handling of the
with-context.

Change-Id: I0bc8f72bc7ce62b8efa298cbea5711adac4a4d34
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
moth/qv4vme_moth_p.h
qmljs_engine.h
qv4mm.cpp
v4.pro

index 5f7d649..b5695b7 100644 (file)
@@ -75,9 +75,53 @@ namespace Moth {
 
 union Instr
 {
-    union ValueOrTemp {
+    struct Param {
+        enum {
+            ValueType    = 0,
+            ArgumentType = 1,
+            LocalType    = 2,
+            TempType     = 3
+        };
         VM::Value value;
-        int tempIndex;
+        unsigned type  : 2;
+        unsigned index : 30;
+
+        bool isValue() const { return type == ValueType; }
+        bool isArgument() const { return type == ArgumentType; }
+        bool isLocal() const { return type == LocalType; }
+        bool isTemp() const { return type == TempType; }
+
+        static Param createValue(const VM::Value &v)
+        {
+            Param p;
+            p.type = ValueType;
+            p.value = v;
+            return p;
+        }
+
+        static Param createArgument(unsigned idx)
+        {
+            Param p;
+            p.type = ArgumentType;
+            p.index = idx;
+            return p;
+        }
+
+        static Param createLocal(unsigned idx)
+        {
+            Param p;
+            p.type = LocalType;
+            p.index = idx;
+            return p;
+        }
+
+        static Param createTemp(unsigned idx)
+        {
+            Param p;
+            p.type = TempType;
+            p.index = idx;
+            return p;
+        }
     };
 
     enum Type {
@@ -86,63 +130,59 @@ union Instr
 
     struct instr_common {
         MOTH_INSTR_HEADER
-        int tempIndex;
     };
     struct instr_ret {
         MOTH_INSTR_HEADER
-        int tempIndex;
+        Param result;
     }; 
     struct instr_loadValue {
         MOTH_INSTR_HEADER
-        int targetTempIndex;
-        VM::Value value;
+        Param value;
+        Param result;
     };
     struct instr_moveTemp {
         MOTH_INSTR_HEADER
-        int fromTempIndex;
-        int toTempIndex;
+        Param source;
+        Param result;
     };
     struct instr_loadClosure {
         MOTH_INSTR_HEADER
         VM::Function *value;
-        int targetTempIndex;
+        Param result;
     };
     struct instr_loadName {
         MOTH_INSTR_HEADER
         VM::String *name;
-        int targetTempIndex;
+        Param result;
     };
     struct instr_storeName {
         MOTH_INSTR_HEADER
         VM::String *name;
-        ValueOrTemp source;
-        unsigned sourceIsTemp:1;
+        Param source;
     };
     struct instr_loadProperty {
         MOTH_INSTR_HEADER
-        int baseTemp;
-        int targetTempIndex;
         VM::String *name;
+        Param base;
+        Param result;
     };
     struct instr_storeProperty {
         MOTH_INSTR_HEADER
-        int baseTemp;
         VM::String *name;
-        ValueOrTemp source;
-        unsigned sourceIsTemp:1;
+        Param base;
+        Param source;
     };
     struct instr_loadElement {
         MOTH_INSTR_HEADER
-        int base;
-        int index;
-        int targetTempIndex;
+        Param base;
+        Param index;
+        Param result;
     };
     struct instr_storeElement {
         MOTH_INSTR_HEADER
-        int base;
-        int index;
-        ValueOrTemp source;
-        unsigned sourceIsTemp:1;
+        Param base;
+        Param index;
+        Param source;
     };
     struct instr_push {
         MOTH_INSTR_HEADER
@@ -152,31 +192,31 @@ union Instr
         MOTH_INSTR_HEADER
         quint32 argc;
         quint32 args;
-        int destIndex;
-        int targetTempIndex;
+        Param dest;
+        Param result;
     };
     struct instr_callProperty {
         MOTH_INSTR_HEADER
         VM::String *name;
-        int baseTemp;
         quint32 argc;
         quint32 args;
-        int targetTempIndex;
+        Param base;
+        Param result;
     };
     struct instr_callElement {
         MOTH_INSTR_HEADER
-        int index;
-        int baseTemp;
+        Param base;
+        Param index;
         quint32 argc;
         quint32 args;
-        int targetTempIndex;
+        Param result;
     };
     struct instr_callActivationProperty {
         MOTH_INSTR_HEADER
         VM::String *name;
         quint32 argc;
         quint32 args;
-        int targetTempIndex;
+        Param result;
     };
     struct instr_callBuiltin {
         MOTH_INSTR_HEADER
@@ -188,147 +228,147 @@ union Instr
             builtin_push_with_scope,
             builtin_pop_scope
         } builtin;
-        int argTemp;
-        int targetTempIndex;
+        Param arg;
+        Param result;
     };
     struct instr_callBuiltinForeachIteratorObject {
         MOTH_INSTR_HEADER
-        int argTemp;
-        int targetTempIndex;
+        Param arg;
+        Param result;
     };
     struct instr_callBuiltinForeachNextPropertyName {
         MOTH_INSTR_HEADER
-        int argTemp;
-        int targetTempIndex;
+        Param arg;
+        Param result;
     };
     struct instr_callBuiltinDeleteMember {
         MOTH_INSTR_HEADER
-        int base;
         VM::String *member;
-        int targetTempIndex;
+        Param base;
+        Param result;
     };
     struct instr_callBuiltinDeleteSubscript {
         MOTH_INSTR_HEADER
-        int base;
-        int index;
-        int targetTempIndex;
+        Param base;
+        Param index;
+        Param result;
     };
     struct instr_callBuiltinDeleteName {
         MOTH_INSTR_HEADER
         VM::String *name;
-        int targetTempIndex;
+        Param result;
     };
     struct instr_callBuiltinTypeofMember {
         MOTH_INSTR_HEADER
-        int base;
         VM::String *member;
-        int targetTempIndex;
+        Param base;
+        Param result;
     };
     struct instr_callBuiltinTypeofSubscript {
         MOTH_INSTR_HEADER
-        int base;
-        int index;
-        int targetTempIndex;
+        Param base;
+        Param index;
+        Param result;
     };
     struct instr_callBuiltinTypeofName {
         MOTH_INSTR_HEADER
         VM::String *name;
-        int targetTempIndex;
+        Param result;
     };
     struct instr_callBuiltinTypeofValue {
         MOTH_INSTR_HEADER
-        int tempIndex;
-        int targetTempIndex;
+        Param value;
+        Param result;
     };
     struct instr_callBuiltinPostIncMember {
         MOTH_INSTR_HEADER
-        int base;
+        Param base;
         VM::String *member;
-        int targetTempIndex;
+        Param result;
     };
     struct instr_callBuiltinPostIncSubscript {
         MOTH_INSTR_HEADER
-        int base;
-        int index;
-        int targetTempIndex;
+        Param base;
+        Param index;
+        Param result;
     };
     struct instr_callBuiltinPostIncName {
         MOTH_INSTR_HEADER
         VM::String *name;
-        int targetTempIndex;
+        Param result;
     };
     struct instr_callBuiltinPostIncValue {
         MOTH_INSTR_HEADER
-        int tempIndex;
-        int targetTempIndex;
+        Param value;
+        Param result;
     };
     struct instr_callBuiltinPostDecMember {
         MOTH_INSTR_HEADER
-        int base;
+        Param base;
         VM::String *member;
-        int targetTempIndex;
+        Param result;
     };
     struct instr_callBuiltinPostDecSubscript {
         MOTH_INSTR_HEADER
-        int base;
-        int index;
-        int targetTempIndex;
+        Param base;
+        Param index;
+        Param result;
     };
     struct instr_callBuiltinPostDecName {
         MOTH_INSTR_HEADER
         VM::String *name;
-        int targetTempIndex;
+        Param result;
     };
     struct instr_callBuiltinPostDecValue {
         MOTH_INSTR_HEADER
-        int tempIndex;
-        int targetTempIndex;
+        Param value;
+        Param result;
     };
     struct instr_callBuiltinDeclareVar {
         MOTH_INSTR_HEADER
-        bool isDeletable;
         VM::String *varName;
+        bool isDeletable;
     };
     struct instr_callBuiltinDefineGetterSetter {
         MOTH_INSTR_HEADER
-        int objectTemp;
         VM::String *name;
-        int getterTemp;
-        int setterTemp;
+        Param object;
+        Param getter;
+        Param setter;
     };
     struct instr_callBuiltinDefineProperty {
         MOTH_INSTR_HEADER
-        int objectTemp;
         VM::String *name;
-        int valueTemp;
+        Param object;
+        Param value;
     };
     struct instr_callBuiltinDefineArrayProperty {
         MOTH_INSTR_HEADER
-        int objectTemp;
+        Param object;
+        Param value;
         int index;
-        int valueTemp;
     };
     struct instr_createValue {
         MOTH_INSTR_HEADER
-        int func;
         quint32 argc;
         quint32 args;
-        int targetTempIndex;
+        Param func;
+        Param result;
     };
     struct instr_createProperty {
         MOTH_INSTR_HEADER
-        int base;
         VM::String *name;
         quint32 argc;
         quint32 args;
-        int targetTempIndex;
+        Param base;
+        Param result;
     };
     struct instr_createActivationProperty {
         MOTH_INSTR_HEADER
         VM::String *name;
         quint32 argc;
         quint32 args;
-        int targetTempIndex;
+        Param result;
     };
     struct instr_jump {
         MOTH_INSTR_HEADER
@@ -337,49 +377,44 @@ union Instr
     struct instr_cjump {
         MOTH_INSTR_HEADER
         ptrdiff_t offset;
-        int tempIndex;
+        Param condition;
     };
     struct instr_unop {
         MOTH_INSTR_HEADER
         VM::Value (*alu)(const VM::Value value, VM::ExecutionContext *ctx);
-        int e;
-        int targetTempIndex;
+        Param source;
+        Param result;
     };
     struct instr_binop {
         MOTH_INSTR_HEADER
         VM::Value (*alu)(const VM::Value , const VM::Value, VM::ExecutionContext *);
-        int targetTempIndex;
-        ValueOrTemp lhs;
-        ValueOrTemp rhs;
-        unsigned lhsIsTemp:1;
-        unsigned rhsIsTemp:1;
+        Param lhs;
+        Param rhs;
+        Param result;
     };
     struct instr_loadThis {
         MOTH_INSTR_HEADER
-        int targetTempIndex;
+        Param result;
     };
     struct instr_inplaceElementOp {
         MOTH_INSTR_HEADER
         void (*alu)(VM::Value, VM::Value, VM::Value, VM::ExecutionContext *);
-        int targetBase;
-        int targetIndex;
-        ValueOrTemp source;
-        unsigned sourceIsTemp:1;
+        Param base;
+        Param index;
+        Param source;
     };
     struct instr_inplaceMemberOp {
         MOTH_INSTR_HEADER
         void (*alu)(VM::Value, VM::Value, VM::String *, VM::ExecutionContext *);
-        int targetBase;
-        VM::String *targetMember;
-        ValueOrTemp source;
-        unsigned sourceIsTemp:1;
+        VM::String *member;
+        Param base;
+        Param source;
     };
     struct instr_inplaceNameOp {
         MOTH_INSTR_HEADER
         void (*alu)(VM::Value, VM::String *, VM::ExecutionContext *);
-        VM::String *targetName;
-        ValueOrTemp source;
-        unsigned sourceIsTemp:1;
+        VM::String *name;
+        Param source;
     };
 
     instr_common common;
index 46cff05..1e58314 100644 (file)
@@ -12,28 +12,18 @@ namespace {
 
 QTextStream qout(stderr, QIODevice::WriteOnly);
 
-static unsigned toValueOrTemp(IR::Expr *e, Instr::ValueOrTemp &vot)
-{
-    if (IR::Const *c = e->asConst()) {
-        vot.value = convertToValue(c);
-        return 0;
-    } else if (IR::Temp *t = e->asTemp()) {
-        vot.tempIndex = t->index;
-        return 1;
-    } else {
-        Q_UNREACHABLE();
-    }
-}
-
-#undef DEBUG_TEMP_COMPRESSION
+//#define DEBUG_TEMP_COMPRESSION
+#ifdef DEBUG_TEMP_COMPRESSION
+#  define DBTC(x) x
+#else // !DEBUG_TEMP_COMPRESSION
+#  define DBTC(x)
+#endif // DEBUG_TEMP_COMPRESSION
 class CompressTemps: public IR::StmtVisitor, IR::ExprVisitor
 {
 public:
     void run(IR::Function *function)
     {
-#ifdef DEBUG_TEMP_COMPRESSION
-        qDebug() << "starting on function" << (*function->name) << "with" << function->tempCount << "temps.";
-#endif // DEBUG_TEMP_COMPRESSION
+        DBTC(qDebug() << "starting on function" << (*function->name) << "with" << function->tempCount << "temps.";)
 
         _seenTemps.clear();
         _nextFree = 0;
@@ -57,27 +47,21 @@ public:
         int maxUsed = _nextFree;
 
         foreach (IR::BasicBlock *block, function->basicBlocks) {
-#ifdef DEBUG_TEMP_COMPRESSION
-            qDebug("L%d:", block->index);
-#endif // DEBUG_TEMP_COMPRESSION
+            DBTC(qDebug("L%d:", block->index));
 
             for (int i = 0, ei = block->statements.size(); i < ei; ++i ) {
                 _currentStatement = block->statements[i];
                 if (i == 0)
                     expireOld();
 
-#ifdef DEBUG_TEMP_COMPRESSION
-                _currentStatement->dump(qout);qout<<endl<<flush;
-#endif // DEBUG_TEMP_COMPRESSION
+                DBTC(_currentStatement->dump(qout);qout<<endl<<flush;)
 
                 if (_currentStatement->d)
                     _currentStatement->accept(this);
             }
             maxUsed = std::max(maxUsed, _nextFree);
         }
-#ifdef DEBUG_TEMP_COMPRESSION
-        qDebug() << "function" << (*function->name) << "uses" << maxUsed << "temps.";
-#endif // DEBUG_TEMP_COMPRESSION
+        DBTC(qDebug() << "function" << (*function->name) << "uses" << maxUsed << "temps.";)
         function->tempCount = maxUsed + _localCount;
     }
 
@@ -131,9 +115,7 @@ private:
     int remap(int tempIndex) {
         for (ActiveTemps::const_iterator i = _active.begin(), ei = _active.end(); i < ei; ++i) {
             if (i->first == tempIndex) {
-#ifdef DEBUG_TEMP_COMPRESSION
-                qDebug() << "    lookup" << (tempIndex + _localCount) << "->" << (i->second + _localCount);
-#endif // DEBUG_TEMP_COMPRESSION
+                DBTC(qDebug() << "    lookup" << (tempIndex + _localCount) << "->" << (i->second + _localCount);)
                 return i->second;
             }
         }
@@ -147,9 +129,7 @@ private:
         if (_nextFree <= firstFree)
             _nextFree = firstFree + 1;
         _active.prepend(qMakePair(tempIndex, firstFree));
-#ifdef DEBUG_TEMP_COMPRESSION
-        qDebug() << "    add" << (tempIndex + _localCount) << "->" << (firstFree+ _localCount);
-#endif // DEBUG_TEMP_COMPRESSION
+        DBTC(qDebug() << "    add" << (tempIndex + _localCount) << "->" << (firstFree+ _localCount);)
     }
 
     int expireOld() {
@@ -171,9 +151,7 @@ private:
                 inUse[p.second] = true;
                 ++i;
             } else {
-#ifdef DEBUG_TEMP_COMPRESSION
-                qDebug() << "    remove" << (p.first + _localCount) << "->" << (p.second + _localCount);
-#endif // DEBUG_TEMP_COMPRESSION
+                DBTC(qDebug() << "    remove" << (p.first + _localCount) << "->" << (p.second + _localCount);)
                 _active.remove(i);
             }
         }
@@ -192,6 +170,7 @@ private:
     int _nextFree;
     int _pinnedCount;
 };
+#undef DBTC
 
 typedef VM::Value (*ALUFunction)(const VM::Value, const VM::Value, VM::ExecutionContext*);
 inline ALUFunction aluOpFunction(IR::AluOp op)
@@ -297,7 +276,8 @@ void InstructionSelection::run(VM::Function *vmFunction, IR::Function *function)
     qSwap(codeNext, _codeNext);
     qSwap(codeEnd, _codeEnd);
 
-    CompressTemps().run(_function);
+    // TODO: FIXME: fix the temp compression with the new temp index layout.
+//    CompressTemps().run(_function);
 
     int locals = frameSize();
     assert(locals >= 0);
@@ -333,8 +313,8 @@ void InstructionSelection::callValue(IR::Temp *value, IR::ExprList *args, IR::Te
 {
     Instruction::CallValue call;
     prepareCallArgs(args, call.argc, call.args);
-    call.destIndex = value->index;
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.dest = getParam(value);
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
@@ -342,10 +322,10 @@ void InstructionSelection::callProperty(IR::Temp *base, const QString &name, IR:
 {
     // call the property on the loaded base
     Instruction::CallProperty call;
-    call.baseTemp = base->index;
+    call.base = getParam(base);
     call.name = engine()->newString(name);
     prepareCallArgs(args, call.argc, call.args);
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
@@ -353,10 +333,10 @@ void InstructionSelection::callSubscript(IR::Temp *base, IR::Temp *index, IR::Ex
 {
     // call the property on the loaded base
     Instruction::CallElement call;
-    call.baseTemp = base->index;
-    call.index = index->index;
+    call.base = getParam(base);
+    call.index = getParam(index);
     prepareCallArgs(args, call.argc, call.args);
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
@@ -367,33 +347,33 @@ void InstructionSelection::constructActivationProperty(IR::Name *func,
     Instruction::CreateActivationProperty create;
     create.name = engine()->newString(*func->id);
     prepareCallArgs(args, create.argc, create.args);
-    create.targetTempIndex = result->index;
+    create.result = getResultParam(result);
     addInstruction(create);
 }
 
 void InstructionSelection::constructProperty(IR::Temp *base, const QString &name, IR::ExprList *args, IR::Temp *result)
 {
     Instruction::CreateProperty create;
-    create.base = base->index;
+    create.base = getParam(base);
     create.name = engine()->newString(name);
     prepareCallArgs(args, create.argc, create.args);
-    create.targetTempIndex = result->index;
+    create.result = getResultParam(result);
     addInstruction(create);
 }
 
 void InstructionSelection::constructValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result)
 {
     Instruction::CreateValue create;
-    create.func = value->index;
+    create.func = getParam(value);
     prepareCallArgs(args, create.argc, create.args);
-    create.targetTempIndex = result->index;
+    create.result = getResultParam(result);
     addInstruction(create);
 }
 
 void InstructionSelection::loadThisObject(IR::Temp *temp)
 {
     Instruction::LoadThis load;
-    load.targetTempIndex = temp->index;
+    load.result = getResultParam(temp);
     addInstruction(load);
 }
 
@@ -402,26 +382,27 @@ void InstructionSelection::loadConst(IR::Const *sourceConst, IR::Temp *targetTem
     assert(sourceConst);
 
     Instruction::LoadValue load;
-    load.targetTempIndex = targetTemp->index;
-    load.value = convertToValue(sourceConst);
+    load.value = getParam(sourceConst);
+    load.result = getResultParam(targetTemp);
     addInstruction(load);
 }
 
 void InstructionSelection::loadString(const QString &str, IR::Temp *targetTemp)
 {
     Instruction::LoadValue load;
-    load.value = VM::Value::fromString(engine()->newString(str));
-    load.targetTempIndex = targetTemp->index;
+    load.value = Instr::Param::createValue(VM::Value::fromString(engine()->newString(str)));
+    load.result = getResultParam(targetTemp);
     addInstruction(load);
 }
 
 void InstructionSelection::loadRegexp(IR::RegExp *sourceRegexp, IR::Temp *targetTemp)
 {
     Instruction::LoadValue load;
-    load.value = VM::Value::fromObject(engine()->newRegExpObject(
-                                           *sourceRegexp->value,
-                                           sourceRegexp->flags));
-    load.targetTempIndex = targetTemp->index;
+    load.value = Instr::Param::createValue(
+                VM::Value::fromObject(engine()->newRegExpObject(
+                                          *sourceRegexp->value,
+                                          sourceRegexp->flags)));
+    load.result = getResultParam(targetTemp);
     addInstruction(load);
 }
 
@@ -429,14 +410,14 @@ void InstructionSelection::getActivationProperty(const QString &name, IR::Temp *
 {
     Instruction::LoadName load;
     load.name = engine()->newString(name);
-    load.targetTempIndex = temp->index;
+    load.result = getResultParam(temp);
     addInstruction(load);
 }
 
 void InstructionSelection::setActivationProperty(IR::Expr *source, const QString &targetName)
 {
     Instruction::StoreName store;
-    store.sourceIsTemp = toValueOrTemp(source, store.source);
+    store.source = getParam(source);
     store.name = engine()->newString(targetName);
     addInstruction(store);
 }
@@ -447,51 +428,51 @@ void InstructionSelection::initClosure(IR::Closure *closure, IR::Temp *target)
     assert(vmFunc);
     Instruction::LoadClosure load;
     load.value = vmFunc;
-    load.targetTempIndex = target->index;
+    load.result = getResultParam(target);
     addInstruction(load);
 }
 
 void InstructionSelection::getProperty(IR::Temp *base, const QString &name, IR::Temp *target)
 {
     Instruction::LoadProperty load;
-    load.baseTemp = base->index;
+    load.base = getParam(base);
     load.name = engine()->newString(name);
-    load.targetTempIndex = target->index;
+    load.result = getResultParam(target);
     addInstruction(load);
 }
 
 void InstructionSelection::setProperty(IR::Expr *source, IR::Temp *targetBase, const QString &targetName)
 {
     Instruction::StoreProperty store;
-    store.baseTemp = targetBase->index;
+    store.base = getParam(targetBase);
     store.name = engine()->newString(targetName);
-    store.sourceIsTemp = toValueOrTemp(source, store.source);
+    store.source = getParam(source);
     addInstruction(store);
 }
 
 void InstructionSelection::getElement(IR::Temp *base, IR::Temp *index, IR::Temp *target)
 {
     Instruction::LoadElement load;
-    load.base = base->index;
-    load.index = index->index;
-    load.targetTempIndex = target->index;
+    load.base = getParam(base);
+    load.index = getParam(index);
+    load.result = getResultParam(target);
     addInstruction(load);
 }
 
 void InstructionSelection::setElement(IR::Expr *source, IR::Temp *targetBase, IR::Temp *targetIndex)
 {
     Instruction::StoreElement store;
-    store.base = targetBase->index;
-    store.index = targetIndex->index;
-    store.sourceIsTemp = toValueOrTemp(source, store.source);
+    store.base = getParam(targetBase);
+    store.index = getParam(targetIndex);
+    store.source = getParam(source);
     addInstruction(store);
 }
 
 void InstructionSelection::copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp)
 {
     Instruction::MoveTemp move;
-    move.fromTempIndex = sourceTemp->index;
-    move.toTempIndex = targetTemp->index;
+    move.source = getParam(sourceTemp);
+    move.result = getResultParam(targetTemp);
     addInstruction(move);
 }
 
@@ -512,8 +493,8 @@ void InstructionSelection::unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp *
     if (op) {
         Instruction::Unop unop;
         unop.alu = op;
-        unop.e = sourceTemp->index;
-        unop.targetTempIndex = targetTemp->index;
+        unop.source = getParam(sourceTemp);
+        unop.result = getResultParam(targetTemp);
         addInstruction(unop);
     } else {
         qWarning("  UNOP1");
@@ -524,9 +505,9 @@ void InstructionSelection::binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr
 {
     Instruction::Binop binop;
     binop.alu = aluOpFunction(oper);
-    binop.lhsIsTemp = toValueOrTemp(leftSource, binop.lhs);
-    binop.rhsIsTemp = toValueOrTemp(rightSource, binop.rhs);
-    binop.targetTempIndex = target->index;
+    binop.lhs = getParam(leftSource);
+    binop.rhs = getParam(rightSource);
+    binop.result = getResultParam(target);
     addInstruction(binop);
 }
 
@@ -551,8 +532,8 @@ void InstructionSelection::inplaceNameOp(IR::AluOp oper, IR::Expr *sourceExpr, c
     if (op) {
         Instruction::InplaceNameOp ieo;
         ieo.alu = op;
-        ieo.targetName = engine()->newString(targetName);
-        ieo.sourceIsTemp = toValueOrTemp(sourceExpr, ieo.source);
+        ieo.name = engine()->newString(targetName);
+        ieo.source = getParam(sourceExpr);
         addInstruction(ieo);
     }
 }
@@ -577,9 +558,9 @@ void InstructionSelection::inplaceElementOp(IR::AluOp oper, IR::Expr *sourceExpr
 
     Instruction::InplaceElementOp ieo;
     ieo.alu = op;
-    ieo.targetBase = targetBaseTemp->index;
-    ieo.targetIndex = targetIndexTemp->index;
-    ieo.sourceIsTemp = toValueOrTemp(sourceExpr, ieo.source);
+    ieo.base = getParam(targetBaseTemp);
+    ieo.index = getParam(targetIndexTemp);
+    ieo.source = getParam(sourceExpr);
     addInstruction(ieo);
 }
 
@@ -603,9 +584,9 @@ void InstructionSelection::inplaceMemberOp(IR::AluOp oper, IR::Expr *source, IR:
 
     Instruction::InplaceMemberOp imo;
     imo.alu = op;
-    imo.targetBase = targetBase->index;
-    imo.targetMember = engine()->newString(targetName);
-    imo.sourceIsTemp = toValueOrTemp(source, imo.source);
+    imo.base = getParam(targetBase);
+    imo.member = engine()->newString(targetName);
+    imo.source = getParam(source);
     addInstruction(imo);
 }
 
@@ -623,7 +604,7 @@ void InstructionSelection::prepareCallArgs(IR::ExprList *e, quint32 &argc, quint
     if (singleArgIsTemp) {
         // We pass single arguments as references to the stack, but only if it's not a local or an argument.
         argc = 1;
-        args = e->expr->asTemp()->index;
+        args = e->expr->asTemp()->index - _function->locals.size();
     } else if (e) {
         // We need to move all the temps into the function arg array
         int argLocation = outgoingArgumentTempStart();
@@ -632,8 +613,8 @@ void InstructionSelection::prepareCallArgs(IR::ExprList *e, quint32 &argc, quint
         args = argLocation;
         while (e) {
             Instruction::MoveTemp move;
-            move.fromTempIndex = e->expr->asTemp()->index;
-            move.toTempIndex = argLocation;
+            move.source = getParam(e->expr);
+            move.result = Instr::Param::createTemp(argLocation);
             addInstruction(move);
             ++argLocation;
             ++argc;
@@ -656,24 +637,24 @@ void InstructionSelection::visitJump(IR::Jump *s)
 
 void InstructionSelection::visitCJump(IR::CJump *s)
 {
-    int tempIndex;
+    Instr::Param condition;
     if (IR::Temp *t = s->cond->asTemp()) {
-        tempIndex = t->index;
+        condition = getResultParam(t);
     } else if (IR::Binop *b = s->cond->asBinop()) {
-        tempIndex = scratchTempIndex();
+        condition = getResultParam(0);
         Instruction::Binop binop;
         binop.alu = aluOpFunction(b->op);
-        binop.lhsIsTemp = toValueOrTemp(b->left, binop.lhs);
-        binop.rhsIsTemp = toValueOrTemp(b->right, binop.rhs);
-        binop.targetTempIndex = tempIndex;
+        binop.lhs = getParam(b->left);
+        binop.rhs = getParam(b->right);
+        binop.result = condition;
         addInstruction(binop);
     } else {
-        Q_UNREACHABLE();
+        Q_UNIMPLEMENTED();
     }
 
     Instruction::CJump jump;
     jump.offset = 0;
-    jump.tempIndex = tempIndex;
+    jump.condition = condition;
     ptrdiff_t trueLoc = addInstruction(jump) + (((const char *)&jump.offset) - ((const char *)&jump));
     _patches[s->iftrue].append(trueLoc);
 
@@ -688,7 +669,7 @@ void InstructionSelection::visitCJump(IR::CJump *s)
 void InstructionSelection::visitRet(IR::Ret *s)
 {
     Instruction::Ret ret;
-    ret.tempIndex = s->expr->index;
+    ret.result = getParam(s->expr);
     addInstruction(ret);
 }
 
@@ -697,25 +678,25 @@ void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args
     Instruction::CallActivationProperty call;
     call.name = engine()->newString(*func->id);
     prepareCallArgs(args, call.argc, call.args);
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
 void InstructionSelection::callBuiltinTypeofMember(IR::Temp *base, const QString &name, IR::Temp *result)
 {
     Instruction::CallBuiltinTypeofMember call;
-    call.base = base->index;
+    call.base = getParam(base);
     call.member = engine()->identifier(name);
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
 void InstructionSelection::callBuiltinTypeofSubscript(IR::Temp *base, IR::Temp *index, IR::Temp *result)
 {
     Instruction::CallBuiltinTypeofSubscript call;
-    call.base = base->index;
-    call.index = index->index;
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.base = getParam(base);
+    call.index = getParam(index);
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
@@ -723,33 +704,33 @@ void InstructionSelection::callBuiltinTypeofName(const QString &name, IR::Temp *
 {
     Instruction::CallBuiltinTypeofName call;
     call.name = engine()->identifier(name);
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
 void InstructionSelection::callBuiltinTypeofValue(IR::Temp *value, IR::Temp *result)
 {
     Instruction::CallBuiltinTypeofValue call;
-    call.tempIndex = value->index;
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.value = getParam(value);
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
 void InstructionSelection::callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result)
 {
     Instruction::CallBuiltinDeleteMember call;
-    call.base = base->index;
+    call.base = getParam(base);
     call.member = engine()->newString(name);
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
 void InstructionSelection::callBuiltinDeleteSubscript(IR::Temp *base, IR::Temp *index, IR::Temp *result)
 {
     Instruction::CallBuiltinDeleteSubscript call;
-    call.base = base->index;
-    call.index = index->index;
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.base = getParam(base);
+    call.index = getParam(index);
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
@@ -757,33 +738,33 @@ void InstructionSelection::callBuiltinDeleteName(const QString &name, IR::Temp *
 {
     Instruction::CallBuiltinDeleteName call;
     call.name = engine()->newString(name);
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
 void InstructionSelection::callBuiltinDeleteValue(IR::Temp *result)
 {
     Instruction::LoadValue load;
-    load.value = VM::Value::fromBoolean(false);
-    load.targetTempIndex = result ? result->index : scratchTempIndex();
+    load.value = Instr::Param::createValue(VM::Value::fromBoolean(false));
+    load.result = getResultParam(result);
     addInstruction(load);
 }
 
 void InstructionSelection::callBuiltinPostDecrementMember(IR::Temp *base, const QString &name, IR::Temp *result)
 {
     Instruction::CallBuiltinPostDecMember call;
-    call.base = base->index;
+    call.base = getParam(base);
     call.member = engine()->identifier(name);
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
 void InstructionSelection::callBuiltinPostDecrementSubscript(IR::Temp *base, IR::Temp *index, IR::Temp *result)
 {
     Instruction::CallBuiltinPostDecSubscript call;
-    call.base = base->index;
-    call.index = index->index;
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.base = getParam(base);
+    call.index = getParam(index);
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
@@ -791,33 +772,33 @@ void InstructionSelection::callBuiltinPostDecrementName(const QString &name, IR:
 {
     Instruction::CallBuiltinPostDecName call;
     call.name = engine()->identifier(name);
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
 void InstructionSelection::callBuiltinPostDecrementValue(IR::Temp *value, IR::Temp *result)
 {
     Instruction::CallBuiltinPostDecValue call;
-    call.tempIndex = value->index;
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.value = getParam(value);
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
 void InstructionSelection::callBuiltinPostIncrementMember(IR::Temp *base, const QString &name, IR::Temp *result)
 {
     Instruction::CallBuiltinPostIncMember call;
-    call.base = base->index;
+    call.base = getParam(base);
     call.member = engine()->identifier(name);
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
 void InstructionSelection::callBuiltinPostIncrementSubscript(IR::Temp *base, IR::Temp *index, IR::Temp *result)
 {
     Instruction::CallBuiltinPostIncSubscript call;
-    call.base = base->index;
-    call.index = index->index;
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.base = getParam(base);
+    call.index = getParam(index);
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
@@ -825,15 +806,15 @@ void InstructionSelection::callBuiltinPostIncrementName(const QString &name, IR:
 {
     Instruction::CallBuiltinPostIncName call;
     call.name = engine()->identifier(name);
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
 void InstructionSelection::callBuiltinPostIncrementValue(IR::Temp *value, IR::Temp *result)
 {
     Instruction::CallBuiltinPostIncValue call;
-    call.tempIndex = value->index;
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.value = getParam(value);
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
@@ -841,7 +822,7 @@ void InstructionSelection::callBuiltinThrow(IR::Temp *arg)
 {
     Instruction::CallBuiltin call;
     call.builtin = Instruction::CallBuiltin::builtin_throw;
-    call.argTemp = arg->index;
+    call.arg = getParam(arg);
     addInstruction(call);
 }
 
@@ -849,7 +830,7 @@ void InstructionSelection::callBuiltinCreateExceptionHandler(IR::Temp *result)
 {
     Instruction::CallBuiltin call;
     call.builtin = Instruction::CallBuiltin::builtin_create_exception_handler;
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
@@ -864,23 +845,23 @@ void InstructionSelection::callBuiltinGetException(IR::Temp *result)
 {
     Instruction::CallBuiltin call;
     call.builtin = Instruction::CallBuiltin::builtin_get_exception;
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
 void InstructionSelection::callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result)
 {
     Instruction::CallBuiltinForeachIteratorObject call;
-    call.argTemp = arg->index;
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.arg = getParam(arg);
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
 void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result)
 {
     Instruction::CallBuiltinForeachNextPropertyName call;
-    call.argTemp = arg->index;
-    call.targetTempIndex = result ? result->index : scratchTempIndex();
+    call.arg = getParam(arg);
+    call.result = getResultParam(result);
     addInstruction(call);
 }
 
@@ -888,7 +869,7 @@ void InstructionSelection::callBuiltinPushWithScope(IR::Temp *arg)
 {
     Instruction::CallBuiltin call;
     call.builtin = Instruction::CallBuiltin::builtin_push_with_scope;
-    call.argTemp = arg->index;
+    call.arg = getParam(arg);
     addInstruction(call);
 }
 
@@ -910,28 +891,28 @@ void InstructionSelection::callBuiltinDeclareVar(bool deletable, const QString &
 void InstructionSelection::callBuiltinDefineGetterSetter(IR::Temp *object, const QString &name, IR::Temp *getter, IR::Temp *setter)
 {
     Instruction::CallBuiltinDefineGetterSetter call;
-    call.objectTemp = object->index;
+    call.object = getParam(object);
     call.name = engine()->newString(name);
-    call.getterTemp = getter->index;
-    call.setterTemp = setter->index;
+    call.getter = getParam(getter);
+    call.setter = getParam(setter);
     addInstruction(call);
 }
 
 void InstructionSelection::callBuiltinDefineProperty(IR::Temp *object, const QString &name, IR::Temp *value)
 {
     Instruction::CallBuiltinDefineProperty call;
-    call.objectTemp = object->index;
+    call.object = getParam(object);
     call.name = engine()->newString(name);
-    call.valueTemp = value->index;
+    call.value = getParam(value);
     addInstruction(call);
 }
 
 void InstructionSelection::callBuiltinDefineArrayProperty(IR::Temp *object, int index, IR::Temp *value)
 {
     Instruction::CallBuiltinDefineArrayProperty call;
-    call.objectTemp = object->index;
+    call.object = getParam(object);
     call.index = index;
-    call.valueTemp = value->index;
+    call.value = getParam(value);
     addInstruction(call);
 }
 
index c9b32d6..ad07dcb 100644 (file)
@@ -86,12 +86,44 @@ private:
         Instruction();
     };
 
+    Instr::Param getParam(IR::Expr *e)
+    {
+        Q_ASSERT(e);
+
+        typedef Instr::Param Param;
+        if (IR::Const *c = e->asConst()) {
+            return Param::createValue(convertToValue(c));
+        } else if (IR::Temp *t = e->asTemp()) {
+            const int index = t->index;
+            if (index < 0) {
+                return Param::createArgument(-index - 1);
+            } else {
+                const int localCount = _function->locals.size();
+                if (index < localCount)
+                    return Param::createLocal(index);
+                else
+                    return Param::createTemp(index - localCount);
+            }
+        } else {
+            Q_UNIMPLEMENTED();
+            return Param();
+        }
+    }
+
+    Instr::Param getResultParam(IR::Temp *result)
+    {
+        if (result)
+            return getParam(result);
+        else
+            return Instr::Param::createTemp(scratchTempIndex());
+    }
+
     void simpleMove(IR::Move *);
     void prepareCallArgs(IR::ExprList *, quint32 &, quint32 &);
 
-    int outgoingArgumentTempStart() const { return _function->tempCount; }
+    int outgoingArgumentTempStart() const { return _function->tempCount - _function->locals.size(); }
     int scratchTempIndex() const { return outgoingArgumentTempStart() + _function->maxNumberOfArguments; }
-    int frameSize() const { return scratchTempIndex() + 1 - _function->locals.size(); }
+    int frameSize() const { return scratchTempIndex() + 1; }
 
     template <int Instr>
     inline ptrdiff_t addInstruction(const InstrData<Instr> &data);
index 5786a54..1578b2c 100644 (file)
 using namespace QQmlJS;
 using namespace QQmlJS::Moth;
 
+class FunctionState: public Debugging::FunctionState
+{
+public:
+    FunctionState(QQmlJS::VM::ExecutionContext *context, const uchar **code)
+        : Debugging::FunctionState(context)
+        , stack(0)
+        , stackSize(0)
+        , code(code)
+    {}
+
+    virtual VM::Value *temp(unsigned idx) { return stack + idx; }
+
+    void setStack(VM::Value *stack, unsigned stackSize)
+    { this->stack = stack; this->stackSize = stackSize; }
+
+private:
+    VM::Value *stack;
+    unsigned stackSize;
+    const uchar **code;
+};
+
 #define MOTH_BEGIN_INSTR_COMMON(I) { \
     const InstrMeta<(int)Instr::I>::DataType &instr = InstrMeta<(int)Instr::I>::data(*genericInstr); \
     code += InstrMeta<(int)Instr::I>::Size; \
@@ -53,70 +74,58 @@ using namespace QQmlJS::Moth;
 
 #endif
 
-static inline VM::Value *tempValue(QQmlJS::VM::ExecutionContext *context, VM::Value* stack, int index)
+static inline VM::Value *getValueRef(QQmlJS::VM::ExecutionContext *context,
+                                     VM::Value* stack,
+                                     const Instr::Param &param
+#if !defined(QT_NO_DEBUG)
+                                     , unsigned stackSize
+#endif
+                                     )
 {
 #ifdef DO_TRACE_INSTR
-    const char *kind;
-    int pos;
-    if (index < 0) {
-        kind = "arg";
-        pos = -index - 1;
-    } else if (index < (int) context->variableCount()) {
-        kind = "local";
-        pos = index;
+    if (param.isValue()) {
+        fprintf(stderr, "    value\n");
+    } else if (param.isArgument()) {
+        fprintf(stderr, "    argument %d\n", param.index);
+    } else if (param.isLocal()) {
+        fprintf(stderr, "    local %d\n", param.index);
+    } else if (param.isTemp()) {
+        fprintf(stderr, "    temp %d\n", param.index);
     } else {
-        kind = "temp";
-        pos = index - context->variableCount();
+        Q_ASSERT(!"INVALID");
     }
-    fprintf(stderr, "    tempValue: index = %d : %s = %d\n",
-          index, kind, pos);
 #endif // DO_TRACE_INSTR
 
-    if (index < 0) {
-        const int arg = -index - 1;
-
+    if (param.isValue()) {
+        return const_cast<VM::Value *>(&param.value);
+    } else if (param.isArgument()) {
+        const unsigned arg = param.index;
         Q_ASSERT(arg >= 0);
         Q_ASSERT((unsigned) arg < context->argumentCount);
         Q_ASSERT(context->arguments);
-
         return context->arguments + arg;
-    } else if (index < (int) context->variableCount()) {
+    } else if (param.isLocal()) {
+        const unsigned index = param.index;
         Q_ASSERT(index >= 0);
+        Q_ASSERT(index < context->variableCount());
         Q_ASSERT(context->locals);
-
         return context->locals + index;
+    } else if (param.isTemp()) {
+        Q_ASSERT(param.index < stackSize);
+        return stack + param.index;
     } else {
-        int off = index - context->variableCount();
-
-        Q_ASSERT(off >= 0);
-
-        return stack + off;
+        Q_UNIMPLEMENTED();
+        return 0;
     }
 }
 
-class FunctionState: public Debugging::FunctionState
-{
-public:
-    FunctionState(QQmlJS::VM::ExecutionContext *context, const uchar **code)
-        : Debugging::FunctionState(context)
-        , stack(0)
-        , stackSize(0)
-        , code(code)
-    {}
-
-    virtual VM::Value *temp(unsigned idx) { return stack + idx; }
-
-    void setStack(VM::Value *stack, unsigned stackSize)
-    { this->stack = stack; this->stackSize = stackSize; }
-
-private:
-    VM::Value *stack;
-    unsigned stackSize;
-    const uchar **code;
-};
-
-#define TEMP(index) *tempValue(context, stack, index)
-#define TEMPPTR(index) tempValue(context, stack, index)
+#if defined(QT_NO_DEBUG)
+# define VALUE(param) *getValueRef(context, stack, param)
+# define VALUEPTR(param) getValueRef(context, stack, param)
+#else
+# define VALUE(param) *getValueRef(context, stack, param, stackSize)
+# define VALUEPTR(param) getValueRef(context, stack, param, stackSize)
+#endif
 
 VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *code
 #ifdef MOTH_THREADED_INTERPRETER
@@ -154,51 +163,42 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co
 #endif
 
     MOTH_BEGIN_INSTR(MoveTemp)
-        VM::Value tmp = TEMP(instr.fromTempIndex);
-        TEMP(instr.toTempIndex) = tmp;
+        VALUE(instr.result) = VALUE(instr.source);
     MOTH_END_INSTR(MoveTemp)
 
     MOTH_BEGIN_INSTR(LoadValue)
-        TEMP(instr.targetTempIndex) = instr.value;
+//        TRACE(value, "%s", instr.value.toString(context)->toQString().toUtf8().constData());
+        VALUE(instr.result) = VALUE(instr.value);
     MOTH_END_INSTR(LoadValue)
 
     MOTH_BEGIN_INSTR(LoadClosure)
-        VM::Value c = __qmljs_init_closure(instr.value, context);
-        TEMP(instr.targetTempIndex) = c;
+        VALUE(instr.result) = __qmljs_init_closure(instr.value, context);
     MOTH_END_INSTR(LoadClosure)
 
     MOTH_BEGIN_INSTR(LoadName)
         TRACE(inline, "property name = %s", instr.name->toQString().toUtf8().constData());
-        VM::Value val = __qmljs_get_activation_property(context, instr.name);
-        TEMP(instr.targetTempIndex) = val;
+        VALUE(instr.result) = __qmljs_get_activation_property(context, instr.name);
     MOTH_END_INSTR(LoadName)
 
     MOTH_BEGIN_INSTR(StoreName)
         TRACE(inline, "property name = %s", instr.name->toQString().toUtf8().constData());
-        VM::Value source = instr.sourceIsTemp ? TEMP(instr.source.tempIndex) : instr.source.value;
-        __qmljs_set_activation_property(context, instr.name, source);
+        __qmljs_set_activation_property(context, instr.name, VALUE(instr.source));
     MOTH_END_INSTR(StoreName)
 
     MOTH_BEGIN_INSTR(LoadElement)
-        TEMP(instr.targetTempIndex) = __qmljs_get_element(context, TEMP(instr.base), TEMP(instr.index));
+        VALUE(instr.result) = __qmljs_get_element(context, VALUE(instr.base), VALUE(instr.index));
     MOTH_END_INSTR(LoadElement)
 
     MOTH_BEGIN_INSTR(StoreElement)
-        VM::Value source = instr.sourceIsTemp ? TEMP(instr.source.tempIndex) : instr.source.value;
-        __qmljs_set_element(context, TEMP(instr.base), TEMP(instr.index), source);
+        __qmljs_set_element(context, VALUE(instr.base), VALUE(instr.index), VALUE(instr.source));
     MOTH_END_INSTR(StoreElement)
 
     MOTH_BEGIN_INSTR(LoadProperty)
-        TRACE(inline, "base temp = %d, property name = %s", instr.baseTemp, instr.name->toQString().toUtf8().constData());
-        VM::Value base = TEMP(instr.baseTemp);
-        TEMP(instr.targetTempIndex) = __qmljs_get_property(context, base, instr.name);
+        VALUE(instr.result) = __qmljs_get_property(context, VALUE(instr.base), instr.name);
     MOTH_END_INSTR(LoadProperty)
 
     MOTH_BEGIN_INSTR(StoreProperty)
-        TRACE(inline, "base temp = %d, property name = %s", instr.baseTemp, instr.name->toQString().toUtf8().constData());
-        VM::Value base = TEMP(instr.baseTemp);
-        VM::Value source = instr.sourceIsTemp ? TEMP(instr.source.tempIndex) : instr.source.value;
-        __qmljs_set_property(context, base, instr.name, source);
+        __qmljs_set_property(context, VALUE(instr.base), instr.name, VALUE(instr.source));
     MOTH_END_INSTR(StoreProperty)
 
     MOTH_BEGIN_INSTR(Push)
@@ -211,7 +211,7 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co
     MOTH_BEGIN_INSTR(CallValue)
 #ifdef DO_TRACE_INSTR
         if (Debugging::Debugger *debugger = context->engine->debugger) {
-            if (VM::FunctionObject *o = (TEMP(instr.destIndex)).asFunctionObject()) {
+            if (VM::FunctionObject *o = (VALUE(instr.dest)).asFunctionObject()) {
                 if (Debugging::FunctionDebugInfo *info = debugger->debugInfo(o)) {
                     QString n = debugger->name(o);
                     std::cerr << "*** Call to \"" << (n.isNull() ? "<no name>" : qPrintable(n)) << "\" defined @" << info->startLine << ":" << info->startColumn << std::endl;
@@ -219,37 +219,28 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co
             }
         }
 #endif // DO_TRACE_INSTR
-        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;
-        VM::Value result = __qmljs_call_value(context, VM::Value::undefinedValue(), TEMP(instr.destIndex), args, instr.argc);
-        TEMP(instr.targetTempIndex) = result;
+        Q_ASSERT(instr.args + instr.argc < stackSize);
+        VM::Value *args = stack + instr.args;
+        VALUE(instr.result) = __qmljs_call_value(context, VM::Value::undefinedValue(), VALUE(instr.dest), args, instr.argc);
     MOTH_END_INSTR(CallValue)
 
     MOTH_BEGIN_INSTR(CallProperty)
-        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);
+        TRACE(property name, "%s", qPrintable(instr.name->toQString()));
+        Q_ASSERT(instr.args + instr.argc < stackSize);
+        VM::Value *args = stack + instr.args;
+        VALUE(instr.result) = __qmljs_call_property(context, VALUE(instr.base), instr.name, args, instr.argc);
     MOTH_END_INSTR(CallProperty)
 
     MOTH_BEGIN_INSTR(CallElement)
-        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_element(context, base, TEMP(instr.index), args, instr.argc);
+        Q_ASSERT(instr.args + instr.argc < stackSize);
+        VM::Value *args = stack + instr.args;
+        VALUE(instr.result) = __qmljs_call_element(context, VALUE(instr.base), VALUE(instr.index), args, instr.argc);
     MOTH_END_INSTR(CallProperty)
 
     MOTH_BEGIN_INSTR(CallActivationProperty)
-        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;
-        TEMP(instr.targetTempIndex) = __qmljs_call_activation_property(context, instr.name, args, instr.argc);
+        Q_ASSERT(instr.args + instr.argc < stackSize);
+        VM::Value *args = stack + instr.args;
+        VALUE(instr.result) = __qmljs_call_activation_property(context, instr.name, args, instr.argc);
     MOTH_END_INSTR(CallActivationProperty)
 
     MOTH_BEGIN_INSTR(CallBuiltin)
@@ -257,116 +248,115 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co
         switch (instr.builtin) {
         case Instr::instr_callBuiltin::builtin_throw:
             TRACE(builtin_throw, "Throwing now...%s", "");
-            __qmljs_builtin_throw(TEMP(instr.argTemp), context);
+            __qmljs_builtin_throw(VALUE(instr.arg), context);
             break;
         case Instr::instr_callBuiltin::builtin_create_exception_handler: {
             TRACE(builtin_create_exception_handler, "%s", "");
             void *buf = __qmljs_create_exception_handler(context);
-            // The targetTempIndex is the only value we need from the instr to
+            // The resultIndex is the only value we need from the instr to
             // continue execution when an exception is caught.
-            int targetTempIndex = instr.targetTempIndex;
+            VM::Value *result = getValueRef(context, stack, instr.result, stackSize);
             int didThrow = setjmp(* static_cast<jmp_buf *>(buf));
             // Two ways to come here: after a create, or after a throw.
             if (didThrow)
                 // At this point, the interpreter state can be anything but
                 // valid, so first restore the state. This includes all relevant
                 // locals.
-                restoreState(context, targetTempIndex, code);
+                restoreState(context, result, code);
             else
                 // Save the state and any variables we need when catching an
                 // exception, so we can restore the state at that point.
-                saveState(context, targetTempIndex, code);
-            TEMP(targetTempIndex) = VM::Value::fromInt32(didThrow);
+                saveState(context, result, code);
+            *result = VM::Value::fromInt32(didThrow);
         } break;
         case Instr::instr_callBuiltin::builtin_delete_exception_handler:
             TRACE(builtin_delete_exception_handler, "%s", "");
             __qmljs_delete_exception_handler(context);
             break;
         case Instr::instr_callBuiltin::builtin_get_exception:
-            TEMP(instr.targetTempIndex) = __qmljs_get_exception(context);
+            TRACE(builtin_get_exception, "%s", "");
+            VALUE(instr.result) = __qmljs_get_exception(context);
             break;
         case Instr::instr_callBuiltin::builtin_push_with_scope:
-            context = __qmljs_builtin_push_with_scope(TEMP(instr.argTemp), context);
+            TRACE(builtin_push_with_scope, "%s", "");
+            context = __qmljs_builtin_push_with_scope(VALUE(instr.arg), context);
             break;
         case Instr::instr_callBuiltin::builtin_pop_scope:
+            TRACE(builtin_pop_scope, "%s", "");
             context = __qmljs_builtin_pop_scope(context);
             break;
         default:
-            assert(!"TODO!");
-            Q_UNREACHABLE();
+            Q_UNIMPLEMENTED();
+            return VM::Value();
         }
     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;
+        VALUE(instr.result) = __qmljs_foreach_iterator_object(VALUE(instr.arg), context);
     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;
+        VALUE(instr.result) = __qmljs_foreach_next_property_name(VALUE(instr.arg));
     MOTH_END_INSTR(CallBuiltinForeachNextPropertyName)
 
     MOTH_BEGIN_INSTR(CallBuiltinDeleteMember)
-        TEMP(instr.targetTempIndex) = __qmljs_delete_member(context, TEMP(instr.base), instr.member);
+        VALUE(instr.result) = __qmljs_delete_member(context, VALUE(instr.base), instr.member);
     MOTH_END_INSTR(CallBuiltinDeleteMember)
 
     MOTH_BEGIN_INSTR(CallBuiltinDeleteSubscript)
-        TEMP(instr.targetTempIndex) = __qmljs_delete_subscript(context, TEMP(instr.base), TEMP(instr.index));
+        VALUE(instr.result) = __qmljs_delete_subscript(context, VALUE(instr.base), VALUE(instr.index));
     MOTH_END_INSTR(CallBuiltinDeleteSubscript)
 
     MOTH_BEGIN_INSTR(CallBuiltinDeleteName)
-        TEMP(instr.targetTempIndex) = __qmljs_delete_name(context, instr.name);
+        VALUE(instr.result) = __qmljs_delete_name(context, instr.name);
     MOTH_END_INSTR(CallBuiltinDeleteName)
 
     MOTH_BEGIN_INSTR(CallBuiltinTypeofMember)
-        TEMP(instr.targetTempIndex) = __qmljs_builtin_typeof_member(TEMP(instr.base), instr.member, context);
+        VALUE(instr.result) = __qmljs_builtin_typeof_member(VALUE(instr.base), instr.member, context);
     MOTH_END_INSTR(CallBuiltinTypeofMember)
 
     MOTH_BEGIN_INSTR(CallBuiltinTypeofSubscript)
-        TEMP(instr.targetTempIndex) = __qmljs_builtin_typeof_element(TEMP(instr.base), TEMP(instr.index), context);
+        VALUE(instr.result) = __qmljs_builtin_typeof_element(VALUE(instr.base), VALUE(instr.index), context);
     MOTH_END_INSTR(CallBuiltinTypeofSubscript)
 
     MOTH_BEGIN_INSTR(CallBuiltinTypeofName)
-        TEMP(instr.targetTempIndex) = __qmljs_builtin_typeof_name(instr.name, context);
+        VALUE(instr.result) = __qmljs_builtin_typeof_name(instr.name, context);
     MOTH_END_INSTR(CallBuiltinTypeofName)
 
     MOTH_BEGIN_INSTR(CallBuiltinTypeofValue)
-        TEMP(instr.targetTempIndex) = __qmljs_builtin_typeof(TEMP(instr.tempIndex), context);
+        VALUE(instr.result) = __qmljs_builtin_typeof(VALUE(instr.value), context);
     MOTH_END_INSTR(CallBuiltinTypeofValue)
 
     MOTH_BEGIN_INSTR(CallBuiltinPostIncMember)
-        TEMP(instr.targetTempIndex) = __qmljs_builtin_post_increment_member(TEMP(instr.base), instr.member, context);
+        VALUE(instr.result) = __qmljs_builtin_post_increment_member(VALUE(instr.base), instr.member, context);
     MOTH_END_INSTR(CallBuiltinTypeofMember)
 
     MOTH_BEGIN_INSTR(CallBuiltinPostIncSubscript)
-        TEMP(instr.targetTempIndex) = __qmljs_builtin_post_increment_element(TEMP(instr.base), TEMP(instr.index), context);
+        VALUE(instr.result) = __qmljs_builtin_post_increment_element(VALUE(instr.base), VALUE(instr.index), context);
     MOTH_END_INSTR(CallBuiltinTypeofSubscript)
 
     MOTH_BEGIN_INSTR(CallBuiltinPostIncName)
-        TEMP(instr.targetTempIndex) = __qmljs_builtin_post_increment_name(instr.name, context);
+        VALUE(instr.result) = __qmljs_builtin_post_increment_name(instr.name, context);
     MOTH_END_INSTR(CallBuiltinTypeofName)
 
     MOTH_BEGIN_INSTR(CallBuiltinPostIncValue)
-        TEMP(instr.targetTempIndex) = __qmljs_builtin_post_increment(TEMPPTR(instr.tempIndex), context);
+        VALUE(instr.result) = __qmljs_builtin_post_increment(VALUEPTR(instr.value), context);
     MOTH_END_INSTR(CallBuiltinTypeofValue)
 
     MOTH_BEGIN_INSTR(CallBuiltinPostDecMember)
-        TEMP(instr.targetTempIndex) = __qmljs_builtin_post_decrement_member(TEMP(instr.base), instr.member, context);
+        VALUE(instr.result) = __qmljs_builtin_post_decrement_member(VALUE(instr.base), instr.member, context);
     MOTH_END_INSTR(CallBuiltinTypeofMember)
 
     MOTH_BEGIN_INSTR(CallBuiltinPostDecSubscript)
-        TEMP(instr.targetTempIndex) = __qmljs_builtin_post_decrement_element(TEMP(instr.base), TEMP(instr.index), context);
+        VALUE(instr.result) = __qmljs_builtin_post_decrement_element(VALUE(instr.base), VALUE(instr.index), context);
     MOTH_END_INSTR(CallBuiltinTypeofSubscript)
 
     MOTH_BEGIN_INSTR(CallBuiltinPostDecName)
-        TEMP(instr.targetTempIndex) = __qmljs_builtin_post_decrement_name(instr.name, context);
+        VALUE(instr.result) = __qmljs_builtin_post_decrement_name(instr.name, context);
     MOTH_END_INSTR(CallBuiltinTypeofName)
 
     MOTH_BEGIN_INSTR(CallBuiltinPostDecValue)
-        TEMP(instr.targetTempIndex) = __qmljs_builtin_post_decrement(TEMPPTR(instr.tempIndex), context);
+        VALUE(instr.result) = __qmljs_builtin_post_decrement(VALUEPTR(instr.value), context);
     MOTH_END_INSTR(CallBuiltinTypeofValue)
 
     MOTH_BEGIN_INSTR(CallBuiltinDeclareVar)
@@ -374,34 +364,34 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co
     MOTH_END_INSTR(CallBuiltinDeclareVar)
 
     MOTH_BEGIN_INSTR(CallBuiltinDefineGetterSetter)
-        __qmljs_builtin_define_getter_setter(TEMP(instr.objectTemp), instr.name, TEMP(instr.getterTemp), TEMP(instr.setterTemp), context);
+        __qmljs_builtin_define_getter_setter(VALUE(instr.object), instr.name, VALUE(instr.getter), VALUE(instr.setter), context);
     MOTH_END_INSTR(CallBuiltinDefineGetterSetter)
 
     MOTH_BEGIN_INSTR(CallBuiltinDefineProperty)
-        __qmljs_builtin_define_property(TEMP(instr.objectTemp), instr.name, TEMP(instr.valueTemp), context);
+        __qmljs_builtin_define_property(VALUE(instr.object), instr.name, VALUE(instr.value), context);
     MOTH_END_INSTR(CallBuiltinDefineProperty)
 
     MOTH_BEGIN_INSTR(CallBuiltinDefineArrayProperty)
-        __qmljs_builtin_define_array_property(TEMP(instr.objectTemp), instr.index, TEMP(instr.valueTemp), context);
+        __qmljs_builtin_define_array_property(VALUE(instr.object), instr.index, VALUE(instr.value), context);
     MOTH_END_INSTR(CallBuiltinDefineArrayProperty)
 
     MOTH_BEGIN_INSTR(CreateValue)
-        int argStart = instr.args - context->variableCount();
-        VM::Value *args = stack + argStart;
-        TEMP(instr.targetTempIndex) = __qmljs_construct_value(context, TEMP(instr.func), args, instr.argc);
+        Q_ASSERT(instr.args + instr.argc < stackSize);
+        VM::Value *args = stack + instr.args;
+        VALUE(instr.result) = __qmljs_construct_value(context, VALUE(instr.func), args, instr.argc);
     MOTH_END_INSTR(CreateValue)
 
     MOTH_BEGIN_INSTR(CreateProperty)
-        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);
+        Q_ASSERT(instr.args + instr.argc < stackSize);
+        VM::Value *args = stack + instr.args;
+        VALUE(instr.result) = __qmljs_construct_property(context, VALUE(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);
-        int argStart = instr.args - context->variableCount();
-        VM::Value *args = stack + argStart;
-        TEMP(instr.targetTempIndex) = __qmljs_construct_activation_property(context, instr.name, args, instr.argc);
+        TRACE(inline, "property name = %s, args = %d, argc = %d", instr.name->toQString().toUtf8().constData(), instr.args, instr.argc);
+        Q_ASSERT(instr.args + instr.argc < stackSize);
+        VM::Value *args = stack + instr.args;
+        VALUE(instr.result) = __qmljs_construct_activation_property(context, instr.name, args, instr.argc);
     MOTH_END_INSTR(CreateActivationProperty)
 
     MOTH_BEGIN_INSTR(Jump)
@@ -409,51 +399,48 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co
     MOTH_END_INSTR(Jump)
 
     MOTH_BEGIN_INSTR(CJump)
-        if (__qmljs_to_boolean(TEMP(instr.tempIndex), context))
+        uint cond = __qmljs_to_boolean(VALUE(instr.condition), context);
+        TRACE(condition, "%s", cond ? "TRUE" : "FALSE");
+        if (cond)
             code = ((uchar *)&instr.offset) + instr.offset;
     MOTH_END_INSTR(CJump)
 
     MOTH_BEGIN_INSTR(Unop)
-        TEMP(instr.targetTempIndex) = instr.alu(TEMP(instr.e), context);
+        VALUE(instr.result) = instr.alu(VALUE(instr.source), context);
     MOTH_END_INSTR(Unop)
 
     MOTH_BEGIN_INSTR(Binop)
-        VM::Value lhs = instr.lhsIsTemp ? TEMP(instr.lhs.tempIndex) : instr.lhs.value;
-        VM::Value rhs = instr.rhsIsTemp ? TEMP(instr.rhs.tempIndex) : instr.rhs.value;
-        TEMP(instr.targetTempIndex) = instr.alu(lhs, rhs, context);
+        VALUE(instr.result) = instr.alu(VALUE(instr.lhs), VALUE(instr.rhs), context);
     MOTH_END_INSTR(Binop)
 
     MOTH_BEGIN_INSTR(Ret)
-        VM::Value result = TEMP(instr.tempIndex);
+        VM::Value &result = VALUE(instr.result);
 //        TRACE(Ret, "returning value %s", result.toString(context)->toQString().toUtf8().constData());
         return result;
     MOTH_END_INSTR(Ret)
 
     MOTH_BEGIN_INSTR(LoadThis)
-        TEMP(instr.targetTempIndex) = __qmljs_get_thisObject(context);
+        VALUE(instr.result) = __qmljs_get_thisObject(context);
     MOTH_END_INSTR(LoadThis)
 
     MOTH_BEGIN_INSTR(InplaceElementOp)
-        VM::Value source = instr.sourceIsTemp ? TEMP(instr.source.tempIndex) : instr.source.value;
-        instr.alu(TEMP(instr.targetBase),
-                  TEMP(instr.targetIndex),
-                  source,
+        instr.alu(VALUE(instr.base),
+                  VALUE(instr.index),
+                  VALUE(instr.source),
                   context);
     MOTH_END_INSTR(InplaceElementOp)
 
     MOTH_BEGIN_INSTR(InplaceMemberOp)
-        VM::Value source = instr.sourceIsTemp ? TEMP(instr.source.tempIndex) : instr.source.value;
-        instr.alu(source,
-                  TEMP(instr.targetBase),
-                  instr.targetMember,
+        instr.alu(VALUE(instr.source),
+                  VALUE(instr.base),
+                  instr.member,
                   context);
     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,
+        TRACE(name, "%s", instr.name->toQString().toUtf8().constData());
+        instr.alu(VALUE(instr.source),
+                  instr.name,
                   context);
     MOTH_END_INSTR(InplaceNameOp)
 
@@ -487,16 +474,16 @@ VM::Value VME::exec(VM::ExecutionContext *ctxt, const uchar *code)
     return vme(ctxt, code);
 }
 
-void VME::restoreState(VM::ExecutionContext *context, int &targetTempIndex, const uchar *&code)
+void VME::restoreState(VM::ExecutionContext *context, VM::Value *&target, const uchar *&code)
 {
     VM::ExecutionEngine::ExceptionHandler &handler = context->engine->unwindStack.last();
-    targetTempIndex = handler.targetTempIndex;
+    target = handler.target;
     code = handler.code;
 }
 
-void VME::saveState(VM::ExecutionContext *context, int targetTempIndex, const uchar *code)
+void VME::saveState(VM::ExecutionContext *context, VM::Value *target, const uchar *code)
 {
     VM::ExecutionEngine::ExceptionHandler &handler = context->engine->unwindStack.last();
-    handler.targetTempIndex = targetTempIndex;
+    handler.target = target;
     handler.code = code;
 }
index c3ccccd..2fd877f 100644 (file)
@@ -27,8 +27,8 @@ public:
 #endif
 
 private:
-    static void restoreState(VM::ExecutionContext *context, int &targetTempIndex, const uchar *&code);
-    static void saveState(VM::ExecutionContext *context, int targetTempIndex, const uchar *code);
+    static void restoreState(VM::ExecutionContext *context, VM::Value *&target, const uchar *&code);
+    static void saveState(VM::ExecutionContext *context, VM::Value *target, const uchar *code);
 };
 
 } // namespace Moth
index 7bf3957..247e0b1 100644 (file)
@@ -160,7 +160,7 @@ struct ExecutionEngine
     struct ExceptionHandler {
         ExecutionContext *context;
         const uchar *code; // Interpreter state
-        int targetTempIndex; // Interpreter state
+        Value *target; // Interpreter state
         jmp_buf stackFrame;
     };
 
index 71e6def..ce7ad2e 100644 (file)
--- a/qv4mm.cpp
+++ b/qv4mm.cpp
@@ -293,9 +293,9 @@ void MemoryManager::setExecutionEngine(ExecutionEngine *engine)
 
 void MemoryManager::dumpStats() const
 {
+#ifdef DETAILED_MM_STATS
     std::cerr << "=================" << std::endl;
     std::cerr << "Allocation stats:" << std::endl;
-#ifdef DETAILED_MM_STATS
     std::cerr << "Requests for each chunk size:" << std::endl;
     for (int i = 0; i < m_d->allocSizeCounters.size(); ++i) {
         if (unsigned count = m_d->allocSizeCounters[i]) {
diff --git a/v4.pro b/v4.pro
index 980d0d6..12e9013 100644 (file)
--- a/v4.pro
+++ b/v4.pro
@@ -135,7 +135,7 @@ checktarget.depends = all
 QMAKE_EXTRA_TARGETS += checktarget
 
 checkmothtarget.target = check-interpreter
-checkmothtarget.commands = python $$TESTSCRIPT --command=\"$$V4CMD --interpret\" --parallel --with-test-expectations --update-expectations
+checkmothtarget.commands = python $$TESTSCRIPT --command=\"$$V4CMD --interpret\" --parallel --with-test-expectations
 checkmothtarget.depends = all
 QMAKE_EXTRA_TARGETS += checkmothtarget