2012-06-11 16:58:52 +00:00
|
|
|
#include "qv4vme_moth_p.h"
|
|
|
|
#include "qv4instr_moth_p.h"
|
2012-11-18 23:00:50 +00:00
|
|
|
#include "qmljs_value.h"
|
2012-06-11 16:58:52 +00:00
|
|
|
|
2012-10-23 14:06:52 +00:00
|
|
|
#ifdef DO_TRACE_INSTR
|
2012-10-24 11:45:43 +00:00
|
|
|
# define TRACE_INSTR(I) fprintf(stderr, "executing a %s\n", #I);
|
2012-11-06 11:31:02 +00:00
|
|
|
# define TRACE(n, str, ...) { fprintf(stderr, " %s : ", #n); fprintf(stderr, str, __VA_ARGS__); fprintf(stderr, "\n"); }
|
2012-10-23 14:06:52 +00:00
|
|
|
#else
|
|
|
|
# define TRACE_INSTR(I)
|
|
|
|
# define TRACE(n, str, ...)
|
|
|
|
#endif // DO_TRACE_INSTR
|
|
|
|
|
2012-11-06 11:31:02 +00:00
|
|
|
using namespace QQmlJS;
|
|
|
|
using namespace QQmlJS::Moth;
|
|
|
|
|
2012-06-11 16:58:52 +00:00
|
|
|
#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; \
|
2012-10-23 14:06:52 +00:00
|
|
|
Q_UNUSED(instr); \
|
|
|
|
TRACE_INSTR(I)
|
2012-06-11 16:58:52 +00:00
|
|
|
|
|
|
|
#ifdef MOTH_THREADED_INTERPRETER
|
|
|
|
|
|
|
|
# define MOTH_BEGIN_INSTR(I) op_##I: \
|
|
|
|
MOTH_BEGIN_INSTR_COMMON(I)
|
|
|
|
|
|
|
|
# define MOTH_NEXT_INSTR(I) { \
|
|
|
|
genericInstr = reinterpret_cast<const Instr *>(code); \
|
|
|
|
goto *genericInstr->common.code; \
|
|
|
|
}
|
|
|
|
|
|
|
|
# define MOTH_END_INSTR(I) } \
|
|
|
|
genericInstr = reinterpret_cast<const Instr *>(code); \
|
|
|
|
goto *genericInstr->common.code; \
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
# define MOTH_BEGIN_INSTR(I) \
|
|
|
|
case Instr::I: \
|
|
|
|
MOTH_BEGIN_INSTR_COMMON(I)
|
|
|
|
|
|
|
|
# define MOTH_NEXT_INSTR(I) { \
|
|
|
|
break; \
|
|
|
|
}
|
|
|
|
|
|
|
|
# define MOTH_END_INSTR(I) } \
|
|
|
|
break;
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2012-11-16 22:07:10 +00:00
|
|
|
static inline VM::Value *tempValue(QQmlJS::VM::ExecutionContext *context, QVector<VM::Value> &stack, int index)
|
2012-06-12 17:13:55 +00:00
|
|
|
{
|
2012-11-22 11:18:56 +00:00
|
|
|
VM::DeclarativeEnvironment *varEnv = context->variableEnvironment;
|
|
|
|
|
2012-11-13 11:25:23 +00:00
|
|
|
#ifdef DO_TRACE_INSTR
|
|
|
|
const char *kind;
|
|
|
|
int pos;
|
|
|
|
if (index < 0) {
|
|
|
|
kind = "arg";
|
|
|
|
pos = -index - 1;
|
2012-11-22 11:18:56 +00:00
|
|
|
} else if (index < (int) varEnv->varCount) {
|
2012-11-13 11:25:23 +00:00
|
|
|
kind = "local";
|
|
|
|
pos = index;
|
|
|
|
} else {
|
|
|
|
kind = "temp";
|
2012-11-22 11:18:56 +00:00
|
|
|
pos = index - varEnv->varCount;
|
2012-11-13 11:25:23 +00:00
|
|
|
}
|
|
|
|
fprintf(stderr, " tempValue: index = %d : %s = %d, stack size = %d\n",
|
|
|
|
index, kind, pos, stack.size());
|
|
|
|
#endif // DO_TRACE_INSTR
|
2012-10-23 14:06:52 +00:00
|
|
|
|
2012-06-12 17:13:55 +00:00
|
|
|
if (index < 0) {
|
|
|
|
const int arg = -index - 1;
|
2012-11-20 09:08:14 +00:00
|
|
|
|
|
|
|
Q_ASSERT(arg >= 0);
|
2012-11-22 11:18:56 +00:00
|
|
|
Q_ASSERT((unsigned) arg < varEnv->argumentCount);
|
|
|
|
Q_ASSERT(varEnv->arguments);
|
2012-11-20 09:08:14 +00:00
|
|
|
|
2012-11-22 11:18:56 +00:00
|
|
|
return varEnv->arguments + arg;
|
|
|
|
} else if (index < (int) varEnv->varCount) {
|
2012-11-20 09:08:14 +00:00
|
|
|
Q_ASSERT(index >= 0);
|
2012-11-22 11:18:56 +00:00
|
|
|
Q_ASSERT(varEnv->locals);
|
2012-11-20 09:08:14 +00:00
|
|
|
|
2012-11-22 11:18:56 +00:00
|
|
|
return varEnv->locals + index;
|
2012-06-12 17:13:55 +00:00
|
|
|
} else {
|
2012-11-22 11:18:56 +00:00
|
|
|
int off = index - varEnv->varCount;
|
2012-11-20 09:08:14 +00:00
|
|
|
|
|
|
|
Q_ASSERT(off >= 0);
|
|
|
|
Q_ASSERT(off < stack.size());
|
|
|
|
|
2012-11-06 11:31:53 +00:00
|
|
|
return stack.data() + off;
|
2012-06-12 17:13:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#define TEMP(index) *tempValue(context, stack, index)
|
|
|
|
|
2012-11-18 23:00:50 +00:00
|
|
|
VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *code
|
2012-06-11 16:58:52 +00:00
|
|
|
#ifdef MOTH_THREADED_INTERPRETER
|
|
|
|
, void ***storeJumpTable
|
|
|
|
#endif
|
|
|
|
)
|
|
|
|
{
|
|
|
|
|
|
|
|
#ifdef MOTH_THREADED_INTERPRETER
|
|
|
|
if (storeJumpTable) {
|
|
|
|
#define MOTH_INSTR_ADDR(I, FMT) &&op_##I,
|
|
|
|
static void *jumpTable[] = {
|
|
|
|
FOR_EACH_MOTH_INSTR(MOTH_INSTR_ADDR)
|
|
|
|
};
|
|
|
|
#undef MOTH_INSTR_ADDR
|
|
|
|
*storeJumpTable = jumpTable;
|
2012-11-18 23:00:50 +00:00
|
|
|
return VM::Value::undefinedValue();
|
2012-06-11 16:58:52 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-06-12 17:13:55 +00:00
|
|
|
QVector<VM::Value> stack;
|
|
|
|
|
2012-06-11 16:58:52 +00:00
|
|
|
#ifdef MOTH_THREADED_INTERPRETER
|
|
|
|
const Instr *genericInstr = reinterpret_cast<const Instr *>(code);
|
|
|
|
goto *genericInstr->common.code;
|
|
|
|
#else
|
|
|
|
for (;;) {
|
|
|
|
const Instr *genericInstr = reinterpret_cast<const Instr *>(code);
|
|
|
|
switch (genericInstr->common.instructionType) {
|
|
|
|
#endif
|
|
|
|
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_BEGIN_INSTR(MoveTemp)
|
2012-11-13 11:25:23 +00:00
|
|
|
VM::Value tmp = TEMP(instr.fromTempIndex);
|
|
|
|
TEMP(instr.toTempIndex) = tmp;
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_END_INSTR(MoveTemp)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(LoadUndefined)
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = VM::Value::undefinedValue();
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_END_INSTR(LoadUndefined)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(LoadNull)
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = VM::Value::nullValue();
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_END_INSTR(LoadNull)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(LoadTrue)
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = VM::Value::fromBoolean(true);
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_END_INSTR(LoadTrue)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(LoadFalse)
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = VM::Value::fromBoolean(false);
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_END_INSTR(LoadFalse)
|
2012-06-11 16:58:52 +00:00
|
|
|
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_BEGIN_INSTR(LoadNumber)
|
2012-11-06 11:31:02 +00:00
|
|
|
TRACE(inline, "number = %f", instr.value);
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = VM::Value::fromDouble(instr.value);
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_END_INSTR(LoadNumber)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(LoadString)
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = VM::Value::fromString(instr.value);
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_END_INSTR(LoadString)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(LoadClosure)
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = __qmljs_init_closure(instr.value, context);
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_END_INSTR(LoadClosure)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(LoadName)
|
2012-10-24 11:45:43 +00:00
|
|
|
TRACE(inline, "property name = %s", instr.name->toQString().toUtf8().constData());
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = __qmljs_get_activation_property(context, instr.name);
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_END_INSTR(LoadName)
|
|
|
|
|
2012-10-24 11:45:43 +00:00
|
|
|
MOTH_BEGIN_INSTR(StoreName)
|
|
|
|
TRACE(inline, "property name = %s", instr.name->toQString().toUtf8().constData());
|
2012-11-14 11:51:54 +00:00
|
|
|
VM::Value source = instr.sourceIsTemp ? TEMP(instr.source.tempIndex) : instr.source.value;
|
|
|
|
__qmljs_set_activation_property(context, instr.name, source);
|
2012-10-24 11:45:43 +00:00
|
|
|
MOTH_END_INSTR(StoreName)
|
|
|
|
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_BEGIN_INSTR(LoadElement)
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = __qmljs_get_element(context, TEMP(instr.base), TEMP(instr.index));
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_END_INSTR(LoadElement)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(StoreElement)
|
2012-11-14 11:51:54 +00:00
|
|
|
VM::Value source = instr.sourceIsTemp ? TEMP(instr.source.tempIndex) : instr.source.value;
|
|
|
|
__qmljs_set_element(context, TEMP(instr.base), TEMP(instr.index), source);
|
2012-11-06 11:54:20 +00:00
|
|
|
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);
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = __qmljs_get_property(context, base, instr.name);
|
2012-11-06 11:54:20 +00:00
|
|
|
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);
|
2012-11-14 11:51:54 +00:00
|
|
|
VM::Value source = instr.sourceIsTemp ? TEMP(instr.source.tempIndex) : instr.source.value;
|
|
|
|
__qmljs_set_property(context, base, instr.name, source);
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_END_INSTR(StoreProperty)
|
|
|
|
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_BEGIN_INSTR(Push)
|
2012-11-06 11:31:02 +00:00
|
|
|
TRACE(inline, "stack size: %u", instr.value);
|
2012-06-12 17:13:55 +00:00
|
|
|
stack.resize(instr.value);
|
|
|
|
MOTH_END_INSTR(Push)
|
|
|
|
|
2012-10-24 15:04:29 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallValue)
|
2012-11-13 11:25:23 +00:00
|
|
|
TRACE(Call, "argStart = %d, argc = %d, result temp index = %d", instr.args, instr.argc, instr.targetTempIndex);
|
2012-06-12 17:13:55 +00:00
|
|
|
VM::Value *args = stack.data() + instr.args;
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = __qmljs_call_value(context, VM::Value::undefinedValue(), TEMP(instr.destIndex), args, instr.argc);
|
2012-10-24 15:04:29 +00:00
|
|
|
MOTH_END_INSTR(CallValue)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallProperty)
|
|
|
|
VM::Value *args = stack.data() + instr.args;
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = __qmljs_call_property(context, TEMP(instr.baseTemp), instr.name, args, instr.argc);
|
2012-10-24 15:04:29 +00:00
|
|
|
MOTH_END_INSTR(CallProperty)
|
2012-06-12 17:13:55 +00:00
|
|
|
|
2012-10-25 08:08:22 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltin)
|
|
|
|
VM::Value *args = stack.data() + instr.args;
|
|
|
|
void *buf;
|
|
|
|
switch (instr.builtin) {
|
|
|
|
case Instr::instr_callBuiltin::builtin_typeof:
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = __qmljs_builtin_typeof(args[0], context);
|
2012-10-25 08:08:22 +00:00
|
|
|
break;
|
|
|
|
case Instr::instr_callBuiltin::builtin_throw:
|
2012-11-14 09:15:19 +00:00
|
|
|
TRACE(builtin_throw, "Throwing now...%s", "");
|
|
|
|
__qmljs_builtin_throw(args[0], context);
|
2012-10-25 08:08:22 +00:00
|
|
|
break;
|
2012-11-14 09:15:19 +00:00
|
|
|
case Instr::instr_callBuiltin::builtin_create_exception_handler: {
|
|
|
|
TRACE(builtin_create_exception_handler, "%s", "");
|
2012-10-25 08:08:22 +00:00
|
|
|
buf = __qmljs_create_exception_handler(context);
|
2012-11-14 09:15:19 +00:00
|
|
|
// The targetTempIndex is the only value we need from the instr to
|
|
|
|
// continue execution when an exception is caught.
|
|
|
|
int targetTempIndex = instr.targetTempIndex;
|
|
|
|
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.
|
2012-11-15 15:29:47 +00:00
|
|
|
restoreState(context, targetTempIndex, code);
|
2012-11-14 09:15:19 +00:00
|
|
|
else
|
|
|
|
// Save the state and any variables we need when catching an
|
|
|
|
// exception, so we can restore the state at that point.
|
2012-11-15 15:29:47 +00:00
|
|
|
saveState(context, targetTempIndex, code);
|
2012-11-14 09:15:19 +00:00
|
|
|
TEMP(targetTempIndex) = VM::Value::fromInt32(didThrow);
|
|
|
|
} break;
|
2012-10-25 08:08:22 +00:00
|
|
|
case Instr::instr_callBuiltin::builtin_delete_exception_handler:
|
2012-11-14 09:15:19 +00:00
|
|
|
TRACE(builtin_delete_exception_handler, "%s", "");
|
2012-10-25 08:08:22 +00:00
|
|
|
__qmljs_delete_exception_handler(context);
|
|
|
|
break;
|
|
|
|
case Instr::instr_callBuiltin::builtin_get_exception:
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = __qmljs_get_exception(context);
|
2012-10-25 08:08:22 +00:00
|
|
|
break;
|
2012-11-12 13:31:05 +00:00
|
|
|
case Instr::instr_callBuiltin::builtin_foreach_iterator_object:
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = __qmljs_foreach_iterator_object(args[0], context);
|
2012-11-12 13:31:05 +00:00
|
|
|
break;
|
|
|
|
case Instr::instr_callBuiltin::builtin_foreach_next_property_name:
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = __qmljs_foreach_next_property_name(args[0]);
|
2012-11-12 13:31:05 +00:00
|
|
|
break;
|
2012-10-25 08:08:22 +00:00
|
|
|
}
|
|
|
|
MOTH_END_INSTR(CallBuiltin)
|
|
|
|
|
2012-11-12 13:31:05 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinDeleteMember)
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = __qmljs_delete_member(context, TEMP(instr.base), instr.member);
|
2012-11-12 13:31:05 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinDeleteMember)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinDeleteSubscript)
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = __qmljs_delete_subscript(context, TEMP(instr.base), TEMP(instr.index));
|
2012-11-12 13:31:05 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinDeleteSubscript)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinDeleteName)
|
2012-11-24 23:26:28 +00:00
|
|
|
TEMP(instr.targetTempIndex) = __qmljs_delete_name(context, instr.name);
|
2012-11-12 13:31:05 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinDeleteName)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinDeleteValue)
|
2012-11-24 23:26:28 +00:00
|
|
|
TEMP(instr.targetTempIndex) = VM::Value::fromBoolean(false);
|
2012-11-12 13:31:05 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinDeleteValue)
|
|
|
|
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_BEGIN_INSTR(CreateValue)
|
|
|
|
VM::Value *args = stack.data() + instr.args;
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = __qmljs_construct_value(context, TEMP(instr.func), args, instr.argc);
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_END_INSTR(CreateValue)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CreateProperty)
|
|
|
|
VM::Value *args = stack.data() + instr.args;
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = __qmljs_construct_property(context, TEMP(instr.base), instr.name, args, instr.argc);
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_END_INSTR(CreateProperty)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CreateActivationProperty)
|
|
|
|
TRACE(inline, "property name = %s, argc = %d", instr.name->toQString().toUtf8().constData(), instr.argc);
|
|
|
|
VM::Value *args = stack.data() + instr.args;
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = __qmljs_construct_activation_property(context, instr.name, args, instr.argc);
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_END_INSTR(CreateActivationProperty)
|
|
|
|
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_BEGIN_INSTR(Jump)
|
2012-06-12 17:26:29 +00:00
|
|
|
code = ((uchar *)&instr.offset) + instr.offset;
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_END_INSTR(Jump)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CJump)
|
2012-11-13 11:25:23 +00:00
|
|
|
if (__qmljs_to_boolean(TEMP(instr.tempIndex), context))
|
2012-06-12 17:26:29 +00:00
|
|
|
code = ((uchar *)&instr.offset) + instr.offset;
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_END_INSTR(CJump)
|
|
|
|
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_BEGIN_INSTR(Unop)
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = instr.alu(TEMP(instr.e), context);
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_END_INSTR(Unop)
|
|
|
|
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_BEGIN_INSTR(Binop)
|
2012-11-12 08:39:06 +00:00
|
|
|
VM::Value lhs = instr.lhsIsTemp ? TEMP(instr.lhs.tempIndex) : instr.lhs.value;
|
|
|
|
VM::Value rhs = instr.rhsIsTemp ? TEMP(instr.rhs.tempIndex) : instr.rhs.value;
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = instr.alu(lhs, rhs, context);
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_END_INSTR(Binop)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(Ret)
|
2012-11-22 15:28:13 +00:00
|
|
|
VM::Value result = TEMP(instr.tempIndex);
|
|
|
|
TRACE(Ret, "returning value %s", result.toString(context)->toQString().toUtf8().constData());
|
|
|
|
return result;
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_END_INSTR(Ret)
|
2012-06-11 16:58:52 +00:00
|
|
|
|
2012-10-24 11:45:43 +00:00
|
|
|
MOTH_BEGIN_INSTR(LoadThis)
|
2012-11-13 11:25:23 +00:00
|
|
|
TEMP(instr.targetTempIndex) = __qmljs_get_thisObject(context);
|
2012-10-24 11:45:43 +00:00
|
|
|
MOTH_END_INSTR(LoadThis)
|
2012-10-23 14:06:52 +00:00
|
|
|
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_BEGIN_INSTR(InplaceElementOp)
|
2012-11-14 11:51:54 +00:00
|
|
|
VM::Value source = instr.sourceIsTemp ? TEMP(instr.source.tempIndex) : instr.source.value;
|
2012-11-06 11:54:20 +00:00
|
|
|
instr.alu(TEMP(instr.targetBase),
|
|
|
|
TEMP(instr.targetIndex),
|
2012-11-14 11:51:54 +00:00
|
|
|
source,
|
2012-11-06 11:54:20 +00:00
|
|
|
context);
|
|
|
|
MOTH_END_INSTR(InplaceElementOp)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(InplaceMemberOp)
|
2012-11-14 11:51:54 +00:00
|
|
|
VM::Value source = instr.sourceIsTemp ? TEMP(instr.source.tempIndex) : instr.source.value;
|
|
|
|
instr.alu(source,
|
2012-11-06 11:54:20 +00:00
|
|
|
TEMP(instr.targetBase),
|
|
|
|
instr.targetMember,
|
|
|
|
context);
|
|
|
|
MOTH_END_INSTR(InplaceMemberOp)
|
|
|
|
|
2012-11-07 15:31:10 +00:00
|
|
|
MOTH_BEGIN_INSTR(InplaceNameOp)
|
2012-11-14 11:51:54 +00:00
|
|
|
VM::Value source = instr.sourceIsTemp ? TEMP(instr.source.tempIndex) : instr.source.value;
|
|
|
|
instr.alu(source,
|
2012-11-07 15:31:10 +00:00
|
|
|
instr.targetName,
|
|
|
|
context);
|
|
|
|
MOTH_END_INSTR(InplaceNameOp)
|
|
|
|
|
2012-06-11 16:58:52 +00:00
|
|
|
#ifdef MOTH_THREADED_INTERPRETER
|
|
|
|
// nothing to do
|
|
|
|
#else
|
|
|
|
default:
|
|
|
|
qFatal("QQmlJS::Moth::VME: Internal error - unknown instruction %d", genericInstr->common.instructionType);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef MOTH_THREADED_INTERPRETER
|
|
|
|
void **VME::instructionJumpTable()
|
|
|
|
{
|
|
|
|
static void **jumpTable = 0;
|
|
|
|
if (!jumpTable) {
|
|
|
|
VME dummy;
|
|
|
|
dummy(0, 0, &jumpTable);
|
|
|
|
}
|
|
|
|
return jumpTable;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-11-18 23:00:50 +00:00
|
|
|
VM::Value VME::exec(VM::ExecutionContext *ctxt, const uchar *code)
|
2012-06-12 17:13:55 +00:00
|
|
|
{
|
|
|
|
VME vme;
|
2012-11-20 08:48:11 +00:00
|
|
|
return vme(ctxt, code);
|
2012-06-12 17:13:55 +00:00
|
|
|
}
|
|
|
|
|
2012-11-16 22:07:10 +00:00
|
|
|
void VME::restoreState(VM::ExecutionContext *context, int &targetTempIndex, const uchar *&code)
|
2012-11-14 09:15:19 +00:00
|
|
|
{
|
2012-11-15 15:29:47 +00:00
|
|
|
VM::ExecutionEngine::ExceptionHandler &handler = context->engine->unwindStack.last();
|
|
|
|
targetTempIndex = handler.targetTempIndex;
|
|
|
|
code = handler.code;
|
2012-11-14 09:15:19 +00:00
|
|
|
}
|
|
|
|
|
2012-11-16 22:07:10 +00:00
|
|
|
void VME::saveState(VM::ExecutionContext *context, int targetTempIndex, const uchar *code)
|
2012-11-14 09:15:19 +00:00
|
|
|
{
|
2012-11-15 15:29:47 +00:00
|
|
|
VM::ExecutionEngine::ExceptionHandler &handler = context->engine->unwindStack.last();
|
|
|
|
handler.targetTempIndex = targetTempIndex;
|
|
|
|
handler.code = code;
|
2012-11-14 09:15:19 +00:00
|
|
|
}
|