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-11-29 13:41:26 +00:00
|
|
|
#include "debugging.h"
|
|
|
|
|
|
|
|
#include <iostream>
|
2012-06-11 16:58:52 +00:00
|
|
|
|
2013-02-08 08:30:40 +00:00
|
|
|
#include "qv4alloca_p.h"
|
2012-12-19 10:21:06 +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-12-04 09:31:31 +00:00
|
|
|
# define TRACE(n, str, ...) { char buf[4096]; snprintf(buf, 4096, str, __VA_ARGS__); fprintf(stderr, " %s : %s\n", #n, buf); }
|
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;
|
|
|
|
|
2013-01-25 18:32:30 +00:00
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
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
|
|
|
|
|
2013-01-25 18:32:30 +00:00
|
|
|
static inline VM::Value *getValueRef(QQmlJS::VM::ExecutionContext *context,
|
|
|
|
VM::Value* stack,
|
|
|
|
const Instr::Param ¶m
|
|
|
|
#if !defined(QT_NO_DEBUG)
|
|
|
|
, unsigned stackSize
|
|
|
|
#endif
|
|
|
|
)
|
2012-06-12 17:13:55 +00:00
|
|
|
{
|
2012-11-13 11:25:23 +00:00
|
|
|
#ifdef DO_TRACE_INSTR
|
2013-01-25 18:32:30 +00:00
|
|
|
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);
|
2012-11-13 11:25:23 +00:00
|
|
|
} else {
|
2013-01-25 18:32:30 +00:00
|
|
|
Q_ASSERT(!"INVALID");
|
2012-11-13 11:25:23 +00:00
|
|
|
}
|
|
|
|
#endif // DO_TRACE_INSTR
|
2012-10-23 14:06:52 +00:00
|
|
|
|
2013-01-25 18:32:30 +00:00
|
|
|
if (param.isValue()) {
|
|
|
|
return const_cast<VM::Value *>(¶m.value);
|
|
|
|
} else if (param.isArgument()) {
|
|
|
|
const unsigned arg = param.index;
|
2012-11-20 09:08:14 +00:00
|
|
|
Q_ASSERT(arg >= 0);
|
2012-12-01 13:05:07 +00:00
|
|
|
Q_ASSERT((unsigned) arg < context->argumentCount);
|
|
|
|
Q_ASSERT(context->arguments);
|
|
|
|
return context->arguments + arg;
|
2013-01-25 18:32:30 +00:00
|
|
|
} else if (param.isLocal()) {
|
|
|
|
const unsigned index = param.index;
|
2012-11-20 09:08:14 +00:00
|
|
|
Q_ASSERT(index >= 0);
|
2013-01-25 18:32:30 +00:00
|
|
|
Q_ASSERT(index < context->variableCount());
|
2012-12-01 13:05:07 +00:00
|
|
|
Q_ASSERT(context->locals);
|
|
|
|
return context->locals + index;
|
2013-01-25 18:32:30 +00:00
|
|
|
} else if (param.isTemp()) {
|
|
|
|
Q_ASSERT(param.index < stackSize);
|
|
|
|
return stack + param.index;
|
2012-06-12 17:13:55 +00:00
|
|
|
} else {
|
2013-01-25 18:32:30 +00:00
|
|
|
Q_UNIMPLEMENTED();
|
|
|
|
return 0;
|
2012-06-12 17:13:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-25 18:32:30 +00:00
|
|
|
#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
|
2012-06-12 17:13:55 +00:00
|
|
|
|
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
|
|
|
|
)
|
|
|
|
{
|
2013-01-23 09:11:05 +00:00
|
|
|
#ifdef DO_TRACE_INSTR
|
|
|
|
qDebug("Starting VME with context=%p and code=%p", context, code);
|
|
|
|
#endif // DO_TRACE_INSTR
|
2012-06-11 16:58:52 +00:00
|
|
|
|
|
|
|
#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-12-04 12:40:18 +00:00
|
|
|
VM::Value *stack = 0;
|
|
|
|
unsigned stackSize = 0;
|
|
|
|
FunctionState state(context, &code);
|
2012-06-12 17:13:55 +00:00
|
|
|
|
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)
|
2013-01-25 18:32:30 +00:00
|
|
|
VALUE(instr.result) = VALUE(instr.source);
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_END_INSTR(MoveTemp)
|
|
|
|
|
2012-12-04 09:55:01 +00:00
|
|
|
MOTH_BEGIN_INSTR(LoadValue)
|
2013-01-25 18:32:30 +00:00
|
|
|
// TRACE(value, "%s", instr.value.toString(context)->toQString().toUtf8().constData());
|
|
|
|
VALUE(instr.result) = VALUE(instr.value);
|
2013-01-16 14:49:42 +00:00
|
|
|
MOTH_END_INSTR(LoadValue)
|
2012-06-12 17:13:55 +00:00
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(LoadClosure)
|
2013-01-25 18:32:30 +00:00
|
|
|
VALUE(instr.result) = __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());
|
2013-02-13 13:15:08 +00:00
|
|
|
__qmljs_get_activation_property(context, VALUEPTR(instr.result), 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());
|
2013-02-14 09:45:49 +00:00
|
|
|
__qmljs_set_activation_property(context, instr.name, VALUE(instr.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)
|
2013-01-25 18:32:30 +00:00
|
|
|
VALUE(instr.result) = __qmljs_get_element(context, VALUE(instr.base), VALUE(instr.index));
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_END_INSTR(LoadElement)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(StoreElement)
|
2013-01-25 18:32:30 +00:00
|
|
|
__qmljs_set_element(context, VALUE(instr.base), VALUE(instr.index), VALUE(instr.source));
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_END_INSTR(StoreElement)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(LoadProperty)
|
2013-02-14 09:45:49 +00:00
|
|
|
__qmljs_get_property(context, VALUEPTR(instr.result), VALUE(instr.base), instr.name);
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_END_INSTR(LoadProperty)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(StoreProperty)
|
2013-02-14 09:45:49 +00:00
|
|
|
__qmljs_set_property(context, VALUE(instr.base), instr.name, VALUE(instr.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-12-04 12:40:18 +00:00
|
|
|
stackSize = instr.value;
|
2012-12-19 10:21:06 +00:00
|
|
|
stack = static_cast<VM::Value *>(alloca(stackSize * sizeof(VM::Value)));
|
2012-12-04 12:40:18 +00:00
|
|
|
state.setStack(stack, stackSize);
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_END_INSTR(Push)
|
|
|
|
|
2012-10-24 15:04:29 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallValue)
|
2012-11-29 13:35:18 +00:00
|
|
|
#ifdef DO_TRACE_INSTR
|
|
|
|
if (Debugging::Debugger *debugger = context->engine->debugger) {
|
2013-01-25 18:32:30 +00:00
|
|
|
if (VM::FunctionObject *o = (VALUE(instr.dest)).asFunctionObject()) {
|
2012-11-29 13:35:18 +00:00
|
|
|
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
|
2013-01-25 18:32:30 +00:00
|
|
|
Q_ASSERT(instr.args + instr.argc < stackSize);
|
|
|
|
VM::Value *args = stack + instr.args;
|
2013-02-14 12:28:49 +00:00
|
|
|
__qmljs_call_value(context, VALUEPTR(instr.result), /*thisObject*/0, VALUE(instr.dest), args, instr.argc);
|
2012-10-24 15:04:29 +00:00
|
|
|
MOTH_END_INSTR(CallValue)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallProperty)
|
2013-02-03 11:19:15 +00:00
|
|
|
TRACE(property name, "%s, args=%u, argc=%u", qPrintable(instr.name->toQString()), instr.args, instr.argc);
|
2013-01-25 18:32:30 +00:00
|
|
|
Q_ASSERT(instr.args + instr.argc < stackSize);
|
|
|
|
VM::Value *args = stack + instr.args;
|
2013-02-14 12:28:49 +00:00
|
|
|
__qmljs_call_property(context, VALUEPTR(instr.result), VALUE(instr.base), 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
|
|
|
|
2013-01-27 21:39:01 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallElement)
|
2013-01-25 18:32:30 +00:00
|
|
|
Q_ASSERT(instr.args + instr.argc < stackSize);
|
|
|
|
VM::Value *args = stack + instr.args;
|
2013-02-14 12:28:49 +00:00
|
|
|
__qmljs_call_element(context, VALUEPTR(instr.result), VALUE(instr.base), VALUE(instr.index), args, instr.argc);
|
2013-01-27 21:39:01 +00:00
|
|
|
MOTH_END_INSTR(CallProperty)
|
|
|
|
|
2013-01-23 12:21:09 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallActivationProperty)
|
2013-01-25 18:32:30 +00:00
|
|
|
Q_ASSERT(instr.args + instr.argc < stackSize);
|
|
|
|
VM::Value *args = stack + instr.args;
|
2013-02-13 13:15:08 +00:00
|
|
|
__qmljs_call_activation_property(context, VALUEPTR(instr.result), instr.name, args, instr.argc);
|
2013-01-23 12:21:09 +00:00
|
|
|
MOTH_END_INSTR(CallActivationProperty)
|
|
|
|
|
2013-01-27 08:59:37 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinThrow)
|
2013-02-14 15:15:19 +00:00
|
|
|
__qmljs_builtin_throw(context, VALUE(instr.arg));
|
2013-01-27 08:59:37 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinThrow)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinCreateExceptionHandler)
|
|
|
|
void *buf = __qmljs_create_exception_handler(context);
|
|
|
|
// The result is the only value we need from the instr to
|
|
|
|
// continue execution when an exception is caught.
|
|
|
|
VM::Value *result = getValueRef(context, stack, instr.result
|
|
|
|
#if !defined(QT_NO_DEBUG)
|
|
|
|
, stackSize
|
|
|
|
#endif
|
|
|
|
);
|
2013-02-06 12:15:10 +00:00
|
|
|
VM::ExecutionContext *oldContext = context;
|
2013-01-27 08:59:37 +00:00
|
|
|
int didThrow = setjmp(* static_cast<jmp_buf *>(buf));
|
2013-02-06 12:15:10 +00:00
|
|
|
context = oldContext;
|
2013-01-27 08:59:37 +00:00
|
|
|
// 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.
|
|
|
|
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, result, code);
|
|
|
|
*result = VM::Value::fromInt32(didThrow);
|
|
|
|
MOTH_END_INSTR(CallBuiltinCreateExceptionHandler)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinDeleteExceptionHandler)
|
|
|
|
__qmljs_delete_exception_handler(context);
|
|
|
|
MOTH_END_INSTR(CallBuiltinDeleteExceptionHandler)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinGetException)
|
2013-02-14 15:04:15 +00:00
|
|
|
__qmljs_get_exception(context, VALUEPTR(instr.result));
|
2013-01-27 08:59:37 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinGetException)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinPushScope)
|
|
|
|
context = __qmljs_builtin_push_with_scope(VALUE(instr.arg), context);
|
|
|
|
MOTH_END_INSTR(CallBuiltinPushScope)
|
|
|
|
|
2013-02-08 12:33:50 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinPushCatchScope)
|
|
|
|
context = __qmljs_builtin_push_catch_scope(instr.varName, context);
|
|
|
|
MOTH_END_INSTR(CallBuiltinPushCatchScope)
|
|
|
|
|
2013-01-27 08:59:37 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinPopScope)
|
|
|
|
context = __qmljs_builtin_pop_scope(context);
|
|
|
|
MOTH_END_INSTR(CallBuiltinPopScope)
|
2012-10-25 08:08:22 +00:00
|
|
|
|
2013-01-23 09:11:05 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinForeachIteratorObject)
|
2013-01-25 18:32:30 +00:00
|
|
|
VALUE(instr.result) = __qmljs_foreach_iterator_object(VALUE(instr.arg), context);
|
2013-01-23 09:11:05 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinForeachIteratorObject)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinForeachNextPropertyName)
|
2013-01-25 18:32:30 +00:00
|
|
|
VALUE(instr.result) = __qmljs_foreach_next_property_name(VALUE(instr.arg));
|
2013-01-23 09:11:05 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinForeachNextPropertyName)
|
|
|
|
|
2012-11-12 13:31:05 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinDeleteMember)
|
2013-02-14 15:02:40 +00:00
|
|
|
__qmljs_delete_member(context, VALUEPTR(instr.result), VALUE(instr.base), instr.member);
|
2012-11-12 13:31:05 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinDeleteMember)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinDeleteSubscript)
|
2013-02-14 15:02:40 +00:00
|
|
|
__qmljs_delete_subscript(context, VALUEPTR(instr.result), VALUE(instr.base), VALUE(instr.index));
|
2012-11-12 13:31:05 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinDeleteSubscript)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinDeleteName)
|
2013-02-14 15:02:40 +00:00
|
|
|
__qmljs_delete_name(context, VALUEPTR(instr.result), instr.name);
|
2012-11-12 13:31:05 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinDeleteName)
|
|
|
|
|
2012-12-18 09:59:26 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinTypeofMember)
|
2013-02-14 11:16:30 +00:00
|
|
|
__qmljs_builtin_typeof_member(context, VALUEPTR(instr.result), VALUE(instr.base), instr.member);
|
2012-12-18 09:59:26 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinTypeofMember)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinTypeofSubscript)
|
2013-02-14 11:56:05 +00:00
|
|
|
__qmljs_builtin_typeof_element(context, VALUEPTR(instr.result), VALUE(instr.base), VALUE(instr.index));
|
2012-12-18 09:59:26 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinTypeofSubscript)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinTypeofName)
|
2013-02-14 11:56:05 +00:00
|
|
|
__qmljs_builtin_typeof_name(context, VALUEPTR(instr.result), instr.name);
|
2012-12-18 09:59:26 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinTypeofName)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinTypeofValue)
|
2013-02-14 11:56:05 +00:00
|
|
|
__qmljs_builtin_typeof(context, VALUEPTR(instr.result), VALUE(instr.value));
|
2012-12-18 09:59:26 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinTypeofValue)
|
|
|
|
|
2013-01-27 20:16:09 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinPostIncMember)
|
2013-02-14 09:45:49 +00:00
|
|
|
__qmljs_builtin_post_increment_member(context, VALUEPTR(instr.result), VALUE(instr.base), instr.member);
|
2013-01-27 20:16:09 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinTypeofMember)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinPostIncSubscript)
|
2013-02-14 09:45:49 +00:00
|
|
|
__qmljs_builtin_post_increment_element(context, VALUEPTR(instr.result), VALUE(instr.base), VALUEPTR(instr.index));
|
2013-01-27 20:16:09 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinTypeofSubscript)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinPostIncName)
|
2013-02-13 21:13:53 +00:00
|
|
|
__qmljs_builtin_post_increment_name(context, VALUEPTR(instr.result), instr.name);
|
2013-01-27 20:16:09 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinTypeofName)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinPostIncValue)
|
2013-02-13 21:13:53 +00:00
|
|
|
__qmljs_builtin_post_increment(context, VALUEPTR(instr.result), VALUEPTR(instr.value));
|
2013-01-27 20:16:09 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinTypeofValue)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinPostDecMember)
|
2013-02-14 09:45:49 +00:00
|
|
|
__qmljs_builtin_post_decrement_member(context, VALUEPTR(instr.result), VALUE(instr.base), instr.member);
|
2013-01-27 20:16:09 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinTypeofMember)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinPostDecSubscript)
|
2013-02-14 09:45:49 +00:00
|
|
|
__qmljs_builtin_post_decrement_element(context, VALUEPTR(instr.result), VALUE(instr.base), VALUE(instr.index));
|
2013-01-27 20:16:09 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinTypeofSubscript)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinPostDecName)
|
2013-02-13 21:13:53 +00:00
|
|
|
__qmljs_builtin_post_decrement_name(context, VALUEPTR(instr.result), instr.name);
|
2013-01-27 20:16:09 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinTypeofName)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinPostDecValue)
|
2013-02-13 21:13:53 +00:00
|
|
|
__qmljs_builtin_post_decrement(context, VALUEPTR(instr.result), VALUEPTR(instr.value));
|
2013-01-27 20:16:09 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinTypeofValue)
|
|
|
|
|
2012-11-27 11:17:19 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinDeclareVar)
|
|
|
|
__qmljs_builtin_declare_var(context, instr.isDeletable, instr.varName);
|
2013-01-16 14:49:42 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinDeclareVar)
|
2012-11-27 11:17:19 +00:00
|
|
|
|
2013-01-08 15:09:48 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinDefineGetterSetter)
|
2013-01-25 18:32:30 +00:00
|
|
|
__qmljs_builtin_define_getter_setter(VALUE(instr.object), instr.name, VALUE(instr.getter), VALUE(instr.setter), context);
|
2013-01-08 15:09:48 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinDefineGetterSetter)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinDefineProperty)
|
2013-01-25 18:32:30 +00:00
|
|
|
__qmljs_builtin_define_property(VALUE(instr.object), instr.name, VALUE(instr.value), context);
|
2013-01-08 15:09:48 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinDefineProperty)
|
|
|
|
|
2013-01-24 11:53:47 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinDefineArrayProperty)
|
2013-01-25 18:32:30 +00:00
|
|
|
__qmljs_builtin_define_array_property(VALUE(instr.object), instr.index, VALUE(instr.value), context);
|
2013-01-24 11:53:47 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinDefineArrayProperty)
|
|
|
|
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_BEGIN_INSTR(CreateValue)
|
2013-01-25 18:32:30 +00:00
|
|
|
Q_ASSERT(instr.args + instr.argc < stackSize);
|
|
|
|
VM::Value *args = stack + instr.args;
|
2013-02-14 14:47:06 +00:00
|
|
|
__qmljs_construct_value(context, VALUEPTR(instr.result), VALUE(instr.func), args, instr.argc);
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_END_INSTR(CreateValue)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CreateProperty)
|
2013-01-25 18:32:30 +00:00
|
|
|
Q_ASSERT(instr.args + instr.argc < stackSize);
|
|
|
|
VM::Value *args = stack + instr.args;
|
2013-02-14 14:47:06 +00:00
|
|
|
__qmljs_construct_property(context, VALUEPTR(instr.result), VALUE(instr.base), instr.name, args, instr.argc);
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_END_INSTR(CreateProperty)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CreateActivationProperty)
|
2013-01-25 18:32:30 +00:00
|
|
|
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;
|
2013-02-13 13:15:08 +00:00
|
|
|
__qmljs_construct_activation_property(context, VALUEPTR(instr.result), 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)
|
2013-01-25 18:32:30 +00:00
|
|
|
uint cond = __qmljs_to_boolean(VALUE(instr.condition), context);
|
|
|
|
TRACE(condition, "%s", cond ? "TRUE" : "FALSE");
|
|
|
|
if (cond)
|
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)
|
2013-02-14 15:11:16 +00:00
|
|
|
instr.alu(context, VALUEPTR(instr.result), VALUE(instr.source));
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_END_INSTR(Unop)
|
|
|
|
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_BEGIN_INSTR(Binop)
|
2013-02-14 09:45:49 +00:00
|
|
|
instr.alu(context, VALUEPTR(instr.result), VALUE(instr.lhs), VALUE(instr.rhs));
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_END_INSTR(Binop)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(Ret)
|
2013-01-25 18:32:30 +00:00
|
|
|
VM::Value &result = VALUE(instr.result);
|
2012-12-04 09:31:31 +00:00
|
|
|
// TRACE(Ret, "returning value %s", result.toString(context)->toQString().toUtf8().constData());
|
2012-11-22 15:28:13 +00:00
|
|
|
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)
|
2013-01-25 18:32:30 +00:00
|
|
|
VALUE(instr.result) = __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)
|
2013-02-13 20:14:17 +00:00
|
|
|
instr.alu(context,
|
2013-02-14 09:45:49 +00:00
|
|
|
VALUE(instr.base),
|
|
|
|
VALUE(instr.index),
|
|
|
|
VALUE(instr.source));
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_END_INSTR(InplaceElementOp)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(InplaceMemberOp)
|
2013-02-13 20:14:17 +00:00
|
|
|
instr.alu(context,
|
2013-02-14 09:45:49 +00:00
|
|
|
VALUE(instr.base),
|
2013-01-25 18:32:30 +00:00
|
|
|
instr.member,
|
2013-02-14 09:45:49 +00:00
|
|
|
VALUE(instr.source));
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_END_INSTR(InplaceMemberOp)
|
|
|
|
|
2012-11-07 15:31:10 +00:00
|
|
|
MOTH_BEGIN_INSTR(InplaceNameOp)
|
2013-01-25 18:32:30 +00:00
|
|
|
TRACE(name, "%s", instr.name->toQString().toUtf8().constData());
|
2013-02-14 09:45:49 +00:00
|
|
|
instr.alu(context, instr.name, VALUE(instr.source));
|
2012-11-07 15:31:10 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2013-01-25 18:32:30 +00:00
|
|
|
void VME::restoreState(VM::ExecutionContext *context, VM::Value *&target, 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();
|
2013-01-25 18:32:30 +00:00
|
|
|
target = handler.target;
|
2012-11-15 15:29:47 +00:00
|
|
|
code = handler.code;
|
2012-11-14 09:15:19 +00:00
|
|
|
}
|
|
|
|
|
2013-01-25 18:32:30 +00:00
|
|
|
void VME::saveState(VM::ExecutionContext *context, VM::Value *target, 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();
|
2013-01-25 18:32:30 +00:00
|
|
|
handler.target = target;
|
2012-11-15 15:29:47 +00:00
|
|
|
handler.code = code;
|
2012-11-14 09:15:19 +00:00
|
|
|
}
|