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 {
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
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
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
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;
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;
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;
}
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;
}
}
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() {
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);
}
}
int _nextFree;
int _pinnedCount;
};
+#undef DBTC
typedef VM::Value (*ALUFunction)(const VM::Value, const VM::Value, VM::ExecutionContext*);
inline ALUFunction aluOpFunction(IR::AluOp op)
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);
{
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);
}
{
// 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);
}
{
// 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);
}
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);
}
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);
}
{
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);
}
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);
}
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");
{
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);
}
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);
}
}
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);
}
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);
}
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();
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;
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);
void InstructionSelection::visitRet(IR::Ret *s)
{
Instruction::Ret ret;
- ret.tempIndex = s->expr->index;
+ ret.result = getParam(s->expr);
addInstruction(ret);
}
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);
}
{
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);
}
{
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);
}
{
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);
}
{
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);
}
{
Instruction::CallBuiltin call;
call.builtin = Instruction::CallBuiltin::builtin_throw;
- call.argTemp = arg->index;
+ call.arg = getParam(arg);
addInstruction(call);
}
{
Instruction::CallBuiltin call;
call.builtin = Instruction::CallBuiltin::builtin_create_exception_handler;
- call.targetTempIndex = result ? result->index : scratchTempIndex();
+ call.result = getResultParam(result);
addInstruction(call);
}
{
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);
}
{
Instruction::CallBuiltin call;
call.builtin = Instruction::CallBuiltin::builtin_push_with_scope;
- call.argTemp = arg->index;
+ call.arg = getParam(arg);
addInstruction(call);
}
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);
}
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);
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; \
#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 ¶m
+#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 *>(¶m.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
#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)
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;
}
}
#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)
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)
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)
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)
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;
}
#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
struct ExceptionHandler {
ExecutionContext *context;
const uchar *code; // Interpreter state
- int targetTempIndex; // Interpreter state
+ Value *target; // Interpreter state
jmp_buf stackFrame;
};
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]) {
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