aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4vme_moth.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2017-11-21 12:29:40 +0100
committerSimon Hausmann <simon.hausmann@qt.io>2017-11-21 12:29:40 +0100
commitd373d5e7d70e968cfba8957596ed6fe4f46990c8 (patch)
treec52bf2b0fbbfdb13d644b4050aa7a931ef4b7109 /src/qml/jsruntime/qv4vme_moth.cpp
parent9880acb424fd814501ba5fc4ae1caa989e23fafa (diff)
parent9af8a47746b69b6040fc149c1d24602a1e25b08f (diff)
Merge remote-tracking branch 'origin/wip/new-backend' into dev
Conflicts: src/qml/compiler/qv4isel_moth.cpp src/qml/compiler/qv4jsir_p.h src/qml/jsruntime/qv4engine_p.h src/qml/jsruntime/qv4vme_moth.cpp tests/auto/qml/qml.pro Change-Id: Ia7b6ec24c7fcbcbb1786d9e798d2df294020ae37
Diffstat (limited to 'src/qml/jsruntime/qv4vme_moth.cpp')
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp1436
1 files changed, 919 insertions, 517 deletions
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index fdf47e772e..adf43812cf 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -53,19 +53,16 @@
#include <private/qv4regexp_p.h>
#include <private/qv4regexpobject_p.h>
#include <private/qv4string_p.h>
+#include <private/qv4profiling_p.h>
+#include <private/qv4jscall_p.h>
+#include <private/qqmljavascriptexpression_p.h>
#include <iostream>
#include "qv4alloca_p.h"
-#undef DO_TRACE_INSTR // define to enable instruction tracing
+#include <private/qv4jit_p.h>
-#ifdef DO_TRACE_INSTR
-# define TRACE_INSTR(I) qDebug("executing a %s\n", #I);
-# define TRACE(n, str, ...) { char buf[4096]; snprintf(buf, 4096, str, __VA_ARGS__); qDebug(" %s : %s", #n, buf); }
-#else
-# define TRACE_INSTR(I)
-# define TRACE(n, str, ...)
-#endif // DO_TRACE_INSTR
+#undef COUNT_INSTRUCTIONS
extern "C" {
@@ -146,7 +143,7 @@ Q_QML_EXPORT int qt_v4DebuggerHook(const char *json);
#if QT_CONFIG(qml_debug)
static int qt_v4BreakpointCount = 0;
-static bool qt_v4IsDebugging = true;
+static bool qt_v4IsDebugging = false;
static bool qt_v4IsStepping = false;
class Breakpoint
@@ -169,14 +166,6 @@ public:
static QVector<Breakpoint> qt_v4Breakpoints;
static Breakpoint qt_v4LastStop;
-static QV4::Function *qt_v4ExtractFunction(QV4::ExecutionContext *context)
-{
- if (QV4::Function *function = context->getFunction())
- return function;
- else
- return context->engine()->globalCode;
-}
-
static void qt_v4TriggerBreakpoint(const Breakpoint &bp, QV4::Function *function)
{
qt_v4LastStop = bp;
@@ -223,6 +212,7 @@ int qt_v4DebuggerHook(const char *json)
bp.fullName = ob.value(QLatin1String("fullName")).toString();
bp.condition = ob.value(QLatin1String("condition")).toString();
qt_v4Breakpoints.append(bp);
+ qt_v4IsDebugging = true;
return bp.bpNumber;
}
@@ -231,6 +221,7 @@ int qt_v4DebuggerHook(const char *json)
QString fullName = ob.value(QLatin1String("fullName")).toString();
if (qt_v4Breakpoints.last().matches(fullName, lineNumber)) {
qt_v4Breakpoints.removeLast();
+ qt_v4IsDebugging = !qt_v4Breakpoints.isEmpty();
return Success;
}
for (int i = 0; i + 1 < qt_v4Breakpoints.size(); ++i) {
@@ -251,13 +242,13 @@ int qt_v4DebuggerHook(const char *json)
return -NoSuchCommand; // Failure.
}
-static void qt_v4CheckForBreak(QV4::ExecutionContext *context)
+Q_NEVER_INLINE static void qt_v4CheckForBreak(QV4::CppStackFrame *frame)
{
if (!qt_v4IsStepping && !qt_v4Breakpoints.size())
return;
- const int lineNumber = context->d()->lineNumber;
- QV4::Function *function = qt_v4ExtractFunction(context);
+ const int lineNumber = frame->lineNumber();
+ QV4::Function *function = frame->v4Function;
QString engineName = function->sourceFile();
if (engineName.isEmpty())
@@ -287,74 +278,64 @@ static void qt_v4CheckForBreak(QV4::ExecutionContext *context)
}
}
+Q_NEVER_INLINE static void debug_slowPath(QV4::ExecutionEngine *engine)
+{
+ QV4::Debugging::Debugger *debugger = engine->debugger();
+ if (debugger && debugger->pauseAtNextOpportunity())
+ debugger->maybeBreakAtInstruction();
+ if (qt_v4IsDebugging)
+ qt_v4CheckForBreak(engine->currentStackFrame);
+}
+
#endif // QT_CONFIG(qml_debug)
// End of debugger interface
using namespace QV4;
using namespace QV4::Moth;
-#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; \
- Q_UNUSED(instr); \
- TRACE_INSTR(I)
-
-#ifdef MOTH_THREADED_INTERPRETER
-
-# define MOTH_BEGIN_INSTR(I) op_##I: \
- MOTH_BEGIN_INSTR_COMMON(I)
-
-# define MOTH_END_INSTR(I) } \
- genericInstr = reinterpret_cast<const Instr *>(code); \
- goto *jumpTable[genericInstr->common.instructionType]; \
-
-#else
-
-# define MOTH_BEGIN_INSTR(I) \
- case Instr::I: \
- MOTH_BEGIN_INSTR_COMMON(I)
-
-# define MOTH_END_INSTR(I) } \
- continue;
-
-#endif
-
-#ifdef DO_TRACE_INSTR
-Param traceParam(const Param &param)
-{
- if (param.isConstant()) {
- qDebug(" constant\n");
- } else if (param.isArgument()) {
- qDebug(" argument %d@%d\n", param.index, param.scope);
- } else if (param.isLocal()) {
- qDebug(" local %d\n", param.index);
- } else if (param.isTemp()) {
- qDebug(" temp %d\n", param.index);
- } else if (param.isScopedLocal()) {
- qDebug(" temp %d@%d\n", param.index, param.scope);
- } else {
- Q_ASSERT(!"INVALID");
+#ifdef COUNT_INSTRUCTIONS
+static struct InstrCount {
+ InstrCount() {
+ fprintf(stderr, "Counting instructions...\n");
+ for (int i = 0; i < MOTH_NUM_INSTRUCTIONS(); ++i)
+ hits[i] = 0;
+ }
+ ~InstrCount() {
+ fprintf(stderr, "Instruction count:\n");
+#define BLAH(I) \
+ fprintf(stderr, "%llu : %s\n", hits[int(Instr::Type::I)], #I);
+ FOR_EACH_MOTH_INSTR(BLAH)
+ #undef BLAH
+ }
+ quint64 hits[MOTH_NUM_INSTRUCTIONS()];
+ void hit(Instr::Type i) { hits[int(i)]++; }
+} instrCount;
+#endif // COUNT_INSTRUCTIONS
+
+#define MOTH_BEGIN_INSTR_COMMON(instr) \
+ { \
+ INSTR_##instr(MOTH_DECODE)
+
+#ifdef COUNT_INSTRUCTIONS
+# define MOTH_BEGIN_INSTR(instr) \
+ MOTH_BEGIN_INSTR_COMMON(instr) \
+ instrCount.hit(Instr::Type::instr);
+#else // !COUNT_INSTRUCTIONS
+# define MOTH_BEGIN_INSTR(instr) \
+ MOTH_BEGIN_INSTR_COMMON(instr)
+#endif // COUNT_INSTRUCTIONS
+
+#ifdef MOTH_COMPUTED_GOTO
+#define MOTH_END_INSTR(instr) \
+ MOTH_DISPATCH() \
+ }
+#else // !MOTH_COMPUTED_GOTO
+#define MOTH_END_INSTR(instr) \
+ continue; \
}
- return param;
-}
-# define VALUE(param) (*VALUEPTR(param))
-# define VALUEPTR(param) (scopes[traceParam(param).scope].values + param.index)
-#else
-# define VALUE(param) (*VALUEPTR(param))
-# define VALUEPTR(param) (scopes[param.scope].values + param.index)
#endif
-// ### add write barrier here
-#define STOREVALUE(param, value) { \
- QV4::ReturnedValue tmp = (value); \
- if (engine->hasException) \
- goto catchException; \
- if (Q_LIKELY(!engine->writeBarrierActive || !scopes[param.scope].base)) { \
- VALUE(param) = tmp; \
- } else { \
- QV4::WriteBarrier::write(engine, scopes[param.scope].base, VALUEPTR(param), QV4::Value::fromReturnedValue(tmp)); \
- } \
-}
+#define STACK_VALUE(temp) stack[temp]
// qv4scopedvalue_p.h also defines a CHECK_EXCEPTION macro
#ifdef CHECK_EXCEPTION
@@ -364,617 +345,1038 @@ Param traceParam(const Param &param)
if (engine->hasException) \
goto catchException
-QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code)
+static inline Heap::CallContext *getScope(Value *stack, int level)
{
-#ifdef DO_TRACE_INSTR
- qDebug("Starting VME with context=%p and code=%p", context, code);
-#endif // DO_TRACE_INSTR
+ Heap::ExecutionContext *scope = static_cast<ExecutionContext &>(stack[CallData::Context]).d();
+ while (level > 0) {
+ --level;
+ scope = scope->outer;
+ }
+ Q_ASSERT(scope);
+ return static_cast<Heap::CallContext *>(scope);
+}
- qt_v4ResolvePendingBreakpointsHook();
+static inline const QV4::Value &constant(Function *function, int index)
+{
+ return function->compilationUnit->constants[index];
+}
-#ifdef MOTH_THREADED_INTERPRETER
-#define MOTH_INSTR_ADDR(I, FMT) &&op_##I,
- static void *jumpTable[] = {
- FOR_EACH_MOTH_INSTR(MOTH_INSTR_ADDR)
- };
-#undef MOTH_INSTR_ADDR
-#endif
- QV4::Value *stack = 0;
- unsigned stackSize = 0;
+static bool compareEqual(Value lhs, Value rhs)
+{
+ redo:
+ if (lhs.asReturnedValue() == rhs.asReturnedValue())
+ return !lhs.isNaN();
+
+ int lt = lhs.quickType();
+ int rt = rhs.quickType();
+ if (rt < lt) {
+ qSwap(lhs, rhs);
+ qSwap(lt, rt);
+ }
- const uchar *exceptionHandler = 0;
+ switch (lt) {
+ case Value::QT_ManagedOrUndefined:
+ if (lhs.isUndefined())
+ return rhs.isNullOrUndefined();
+ Q_FALLTHROUGH();
+ case Value::QT_ManagedOrUndefined1:
+ case Value::QT_ManagedOrUndefined2:
+ case Value::QT_ManagedOrUndefined3:
+ // LHS: Managed
+ switch (rt) {
+ case Value::QT_ManagedOrUndefined:
+ if (rhs.isUndefined())
+ return false;
+ Q_FALLTHROUGH();
+ case Value::QT_ManagedOrUndefined1:
+ case Value::QT_ManagedOrUndefined2:
+ case Value::QT_ManagedOrUndefined3: {
+ // RHS: Managed
+ Heap::Base *l = lhs.m();
+ Heap::Base *r = rhs.m();
+ Q_ASSERT(l);
+ Q_ASSERT(r);
+ if (l->vtable()->isString == r->vtable()->isString)
+ return static_cast<QV4::Managed &>(lhs).isEqualTo(&static_cast<QV4::Managed &>(rhs));
+ if (l->vtable()->isString) {
+ rhs = Primitive::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(rhs), PREFERREDTYPE_HINT));
+ break;
+ } else {
+ Q_ASSERT(r->vtable()->isString);
+ lhs = Primitive::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(lhs), PREFERREDTYPE_HINT));
+ break;
+ }
+ return false;
+ }
+ case Value::QT_Empty:
+ Q_UNREACHABLE();
+ case Value::QT_Null:
+ return false;
+ case Value::QT_Bool:
+ case Value::QT_Int:
+ rhs = Primitive::fromDouble(rhs.int_32());
+ // fall through
+ default: // double
+ if (lhs.m()->vtable()->isString)
+ return RuntimeHelpers::toNumber(lhs) == rhs.doubleValue();
+ else
+ lhs = Primitive::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(lhs), PREFERREDTYPE_HINT));
+ }
+ goto redo;
+ case Value::QT_Empty:
+ Q_UNREACHABLE();
+ case Value::QT_Null:
+ return rhs.isNull();
+ case Value::QT_Bool:
+ case Value::QT_Int:
+ switch (rt) {
+ case Value::QT_ManagedOrUndefined:
+ case Value::QT_ManagedOrUndefined1:
+ case Value::QT_ManagedOrUndefined2:
+ case Value::QT_ManagedOrUndefined3:
+ case Value::QT_Empty:
+ case Value::QT_Null:
+ Q_UNREACHABLE();
+ case Value::QT_Bool:
+ case Value::QT_Int:
+ return lhs.int_32() == rhs.int_32();
+ default: // double
+ return lhs.int_32() == rhs.doubleValue();
+ }
+ default: // double
+ Q_ASSERT(rhs.isDouble());
+ return lhs.doubleValue() == rhs.doubleValue();
+ }
+}
- QV4::Scope scope(engine);
- engine->current->lineNumber = -1;
+static bool compareEqualInt(Value &accumulator, Value lhs, int rhs)
+{
+ redo:
+ switch (lhs.quickType()) {
+ case Value::QT_ManagedOrUndefined:
+ if (lhs.isUndefined())
+ return false;
+ Q_FALLTHROUGH();
+ case Value::QT_ManagedOrUndefined1:
+ case Value::QT_ManagedOrUndefined2:
+ case Value::QT_ManagedOrUndefined3:
+ // LHS: Managed
+ if (lhs.m()->vtable()->isString)
+ return RuntimeHelpers::stringToNumber(static_cast<String &>(lhs).toQString()) == rhs;
+ accumulator = lhs;
+ lhs = Primitive::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(accumulator), PREFERREDTYPE_HINT));
+ goto redo;
+ case Value::QT_Empty:
+ Q_UNREACHABLE();
+ case Value::QT_Null:
+ return false;
+ case Value::QT_Bool:
+ case Value::QT_Int:
+ return lhs.int_32() == rhs;
+ default: // double
+ return lhs.doubleValue() == rhs;
+ }
+}
-#ifdef DO_TRACE_INSTR
- qDebug("Starting VME with context=%p and code=%p", context, code);
-#endif // DO_TRACE_INSTR
+#define STORE_IP() frame.instructionPointer = int(code - codeStart);
+#define STORE_ACC() accumulator = acc;
+#define ACC Primitive::fromReturnedValue(acc)
+#define VALUE_TO_INT(i, val) \
+ int i; \
+ do { \
+ if (Q_LIKELY(val.integerCompatible())) { \
+ i = val.int_32(); \
+ } else { \
+ double d; \
+ if (val.isDouble()) \
+ d = val.doubleValue(); \
+ else { \
+ d = val.toNumberImpl(); \
+ CHECK_EXCEPTION; \
+ } \
+ i = Double::toInt32(d); \
+ } \
+ } while (false)
+
+QV4::ReturnedValue VME::exec(const FunctionObject *fo, const Value *thisObject, const Value *argv, int argc)
+{
+ qt_v4ResolvePendingBreakpointsHook();
+ ExecutionEngine *engine;
+ Value *stack;
+ CppStackFrame frame;
+ frame.originalArguments = argv;
+ frame.originalArgumentsCount = argc;
+ Function *function;
- // setup lookup scopes
- int scopeDepth = 0;
{
- QV4::Heap::ExecutionContext *scope = engine->current;
- while (scope) {
- ++scopeDepth;
- scope = scope->outer;
+ Heap::ExecutionContext *scope;
+
+ quintptr d = reinterpret_cast<quintptr>(fo);
+ if (d & 0x1) {
+ // we don't have a FunctionObject, but a ExecData
+ ExecData *data = reinterpret_cast<ExecData *>(d - 1);
+ function = data->function;
+ scope = data->scope->d();
+ fo = nullptr;
+ } else {
+ function = fo->function();
+ scope = fo->scope();
}
+
+ engine = function->internalClass->engine;
+
+ stack = engine->jsStackTop;
+ CallData *callData = reinterpret_cast<CallData *>(stack);
+ callData->function = fo ? fo->asReturnedValue() : Encode::undefined();
+ callData->context = scope;
+ callData->accumulator = Encode::undefined();
+ callData->thisObject = thisObject ? *thisObject : Primitive::undefinedValue();
+ if (argc > int(function->nFormals))
+ argc = int(function->nFormals);
+ callData->setArgc(argc);
+
+ int jsStackFrameSize = offsetof(CallData, args)/sizeof(Value) + function->compiledFunction->nRegisters;
+ engine->jsStackTop += jsStackFrameSize;
+ memcpy(callData->args, argv, argc*sizeof(Value));
+ for (Value *v = callData->args + argc; v < engine->jsStackTop; ++v)
+ *v = Encode::undefined();
+
+ frame.parent = engine->currentStackFrame;
+ frame.v4Function = function;
+ frame.instructionPointer = 0;
+ frame.jsFrame = callData;
+ engine->currentStackFrame = &frame;
}
+ CHECK_STACK_LIMITS(engine);
- struct Scopes {
- QV4::Value *values;
- QV4::Heap::Base *base; // non 0 if a write barrier is required
- };
- Q_ALLOCA_VAR(Scopes, scopes, sizeof(Scopes)*(2 + 2*scopeDepth));
- {
- scopes[0] = { const_cast<QV4::Value *>(static_cast<CompiledData::CompilationUnit*>(engine->current->compilationUnit)->constants), 0 };
- // stack gets setup in push instruction
- scopes[1] = { 0, 0 };
- QV4::Heap::ExecutionContext *scope = engine->current;
- int i = 0;
- while (scope) {
- if (scope->type == QV4::Heap::ExecutionContext::Type_SimpleCallContext) {
- QV4::Heap::SimpleCallContext *cc = static_cast<QV4::Heap::SimpleCallContext *>(scope);
- scopes[2*i + 2] = { cc->callData->args, 0 };
- scopes[2*i + 3] = { 0, 0 };
- } else if (scope->type == QV4::Heap::ExecutionContext::Type_CallContext) {
- QV4::Heap::CallContext *cc = static_cast<QV4::Heap::CallContext *>(scope);
- scopes[2*i + 2] = { cc->callData->args, cc };
- scopes[2*i + 3] = { cc->locals.values, cc };
- } else {
- scopes[2*i + 2] = { 0, 0 };
- scopes[2*i + 3] = { 0, 0 };
- }
- ++i;
- scope = scope->outer;
- }
+ Profiling::FunctionCallProfiler profiler(engine, function); // start execution profiling
+ QV4::Debugging::Debugger *debugger = engine->debugger();
+
+ const uchar *exceptionHandler = 0;
+
+ QV4::Value &accumulator = frame.jsFrame->accumulator;
+ QV4::ReturnedValue acc = Encode::undefined();
+
+#ifdef V4_ENABLE_JIT
+ static const bool forceInterpreter = qEnvironmentVariableIsSet("QV4_FORCE_INTERPRETER");
+ if (function->jittedCode == nullptr) {
+ if (ExecutionEngine::canJIT() && debugger == nullptr && !forceInterpreter)
+ QV4::JIT::BaselineJIT(function).generate();
}
+#endif // V4_ENABLE_JIT
+
+ if (debugger)
+ debugger->enteringFunction();
+ if (function->jittedCode != nullptr && debugger == nullptr) {
+ acc = function->jittedCode(&frame, engine);
+ } else {
+ // interpreter
+ const uchar *code = function->codeData;
+ const uchar *codeStart = code;
+
+ MOTH_JUMP_TABLE;
for (;;) {
- const Instr *genericInstr = reinterpret_cast<const Instr *>(code);
-#ifdef MOTH_THREADED_INTERPRETER
- goto *jumpTable[genericInstr->common.instructionType];
-#else
- switch (genericInstr->common.instructionType) {
-#endif
+ MOTH_DISPATCH()
+ Q_UNREACHABLE(); // only reached when the dispatch doesn't jump somewhere
+
+ MOTH_BEGIN_INSTR(LoadConst)
+ acc = constant(function, index).asReturnedValue();
+ MOTH_END_INSTR(LoadConst)
+
+ MOTH_BEGIN_INSTR(LoadNull)
+ acc = Encode::null();
+ MOTH_END_INSTR(LoadNull)
+
+ MOTH_BEGIN_INSTR(LoadZero)
+ acc = Encode(static_cast<int>(0));
+ MOTH_END_INSTR(LoadZero)
- MOTH_BEGIN_INSTR(Move)
- VALUE(instr.result) = VALUE(instr.source);
- MOTH_END_INSTR(Move)
+ MOTH_BEGIN_INSTR(LoadTrue)
+ acc = Encode(true);
+ MOTH_END_INSTR(LoadTrue)
+
+ MOTH_BEGIN_INSTR(LoadFalse)
+ acc = Encode(false);
+ MOTH_END_INSTR(LoadFalse)
+
+ MOTH_BEGIN_INSTR(LoadUndefined)
+ acc = Encode::undefined();
+ MOTH_END_INSTR(LoadUndefined)
+
+ MOTH_BEGIN_INSTR(LoadInt)
+ acc = Encode(value);
+ MOTH_END_INSTR(LoadInt)
MOTH_BEGIN_INSTR(MoveConst)
- VALUE(instr.result) = instr.source;
+ STACK_VALUE(destTemp) = constant(function, constIndex);
MOTH_END_INSTR(MoveConst)
- MOTH_BEGIN_INSTR(SwapTemps)
- qSwap(VALUE(instr.left), VALUE(instr.right));
- MOTH_END_INSTR(MoveTemp)
+ MOTH_BEGIN_INSTR(LoadReg)
+ acc = STACK_VALUE(reg).asReturnedValue();
+ MOTH_END_INSTR(LoadReg)
+
+ MOTH_BEGIN_INSTR(StoreReg)
+ STACK_VALUE(reg) = acc;
+ MOTH_END_INSTR(StoreReg)
+
+ MOTH_BEGIN_INSTR(MoveReg)
+ STACK_VALUE(destReg) = STACK_VALUE(srcReg);
+ MOTH_END_INSTR(MoveReg)
+
+ MOTH_BEGIN_INSTR(LoadLocal)
+ auto cc = static_cast<Heap::CallContext *>(stack[CallData::Context].m());
+ acc = cc->locals[index].asReturnedValue();
+ MOTH_END_INSTR(LoadLocal)
+
+ MOTH_BEGIN_INSTR(StoreLocal)
+ CHECK_EXCEPTION;
+ auto cc = static_cast<Heap::CallContext *>(stack[CallData::Context].m());
+ QV4::WriteBarrier::write(engine, cc, cc->locals.values + index, ACC);
+ MOTH_END_INSTR(StoreLocal)
+
+ MOTH_BEGIN_INSTR(LoadScopedLocal)
+ auto cc = getScope(stack, scope);
+ acc = cc->locals[index].asReturnedValue();
+ MOTH_END_INSTR(LoadScopedLocal)
+
+ MOTH_BEGIN_INSTR(StoreScopedLocal)
+ CHECK_EXCEPTION;
+ auto cc = getScope(stack, scope);
+ QV4::WriteBarrier::write(engine, cc, cc->locals.values + index, ACC);
+ MOTH_END_INSTR(StoreScopedLocal)
MOTH_BEGIN_INSTR(LoadRuntimeString)
-// TRACE(value, "%s", instr.value.toString(context)->toQString().toUtf8().constData());
- VALUE(instr.result) = engine->current->compilationUnit->runtimeStrings[instr.stringId];
+ acc = function->compilationUnit->runtimeStrings[stringId]->asReturnedValue();
MOTH_END_INSTR(LoadRuntimeString)
MOTH_BEGIN_INSTR(LoadRegExp)
-// TRACE(value, "%s", instr.value.toString(context)->toQString().toUtf8().constData());
- Heap::RegExpObject *ro = engine->newRegExpObject(
- static_cast<CompiledData::CompilationUnit*>(engine->current->compilationUnit)
- ->runtimeRegularExpressions[instr.regExpId].as<RegExp>());
- VALUE(instr.result) = ro;
+ acc = Runtime::method_regexpLiteral(engine, regExpId);
MOTH_END_INSTR(LoadRegExp)
MOTH_BEGIN_INSTR(LoadClosure)
- STOREVALUE(instr.result, Runtime::method_closure(engine, instr.value));
+ acc = Runtime::method_closure(engine, value);
MOTH_END_INSTR(LoadClosure)
MOTH_BEGIN_INSTR(LoadName)
- TRACE(inline, "property name = %s", runtimeStrings[instr.name]->toQString().toUtf8().constData());
- STOREVALUE(instr.result, Runtime::method_getActivationProperty(engine, instr.name));
+ STORE_IP();
+ acc = Runtime::method_loadName(engine, name);
+ CHECK_EXCEPTION;
MOTH_END_INSTR(LoadName)
- MOTH_BEGIN_INSTR(GetGlobalLookup)
- QV4::Lookup *l = engine->current->lookups + instr.index;
- STOREVALUE(instr.result, l->globalGetter(l, engine));
- MOTH_END_INSTR(GetGlobalLookup)
+ MOTH_BEGIN_INSTR(LoadGlobalLookup)
+ QV4::Lookup *l = function->compilationUnit->runtimeLookups + index;
+ acc = l->globalGetter(l, engine);
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(LoadGlobalLookup)
+
+ MOTH_BEGIN_INSTR(StoreNameStrict)
+ STORE_IP();
+ STORE_ACC();
+ Runtime::method_storeNameStrict(engine, name, accumulator);
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(StoreNameStrict)
- MOTH_BEGIN_INSTR(StoreName)
- TRACE(inline, "property name = %s", runtimeStrings[instr.name]->toQString().toUtf8().constData());
- Runtime::method_setActivationProperty(engine, instr.name, VALUE(instr.source));
+ MOTH_BEGIN_INSTR(StoreNameSloppy)
+ STORE_IP();
+ STORE_ACC();
+ Runtime::method_storeNameSloppy(engine, name, accumulator);
CHECK_EXCEPTION;
- MOTH_END_INSTR(StoreName)
+ MOTH_END_INSTR(StoreNameSloppy)
MOTH_BEGIN_INSTR(LoadElement)
- STOREVALUE(instr.result, Runtime::method_getElement(engine, VALUE(instr.base), VALUE(instr.index)));
+ STORE_IP();
+ acc = Runtime::method_loadElement(engine, STACK_VALUE(base), STACK_VALUE(index));
+ CHECK_EXCEPTION;
MOTH_END_INSTR(LoadElement)
- MOTH_BEGIN_INSTR(LoadElementLookup)
- QV4::Lookup *l = engine->current->lookups + instr.lookup;
- STOREVALUE(instr.result, l->indexedGetter(l, engine, VALUE(instr.base), VALUE(instr.index)));
- MOTH_END_INSTR(LoadElementLookup)
+ MOTH_BEGIN_INSTR(LoadElementA)
+ STORE_IP();
+ STORE_ACC();
+ acc = Runtime::method_loadElement(engine, STACK_VALUE(base), accumulator);
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(LoadElementA)
MOTH_BEGIN_INSTR(StoreElement)
- Runtime::method_setElement(engine, VALUE(instr.base), VALUE(instr.index), VALUE(instr.source));
+ STORE_IP();
+ STORE_ACC();
+ if (!Runtime::method_storeElement(engine, STACK_VALUE(base), STACK_VALUE(index), accumulator) && function->isStrict())
+ engine->throwTypeError();
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreElement)
- MOTH_BEGIN_INSTR(StoreElementLookup)
- QV4::Lookup *l = engine->current->lookups + instr.lookup;
- l->indexedSetter(l, engine, VALUE(instr.base), VALUE(instr.index), VALUE(instr.source));
- CHECK_EXCEPTION;
- MOTH_END_INSTR(StoreElementLookup)
-
MOTH_BEGIN_INSTR(LoadProperty)
- STOREVALUE(instr.result, Runtime::method_getProperty(engine, VALUE(instr.base), instr.name));
+ STORE_IP();
+ acc = Runtime::method_loadProperty(engine, STACK_VALUE(base), name);
+ CHECK_EXCEPTION;
MOTH_END_INSTR(LoadProperty)
+ MOTH_BEGIN_INSTR(LoadPropertyA)
+ STORE_IP();
+ STORE_ACC();
+ acc = Runtime::method_loadProperty(engine, accumulator, name);
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(LoadPropertyA)
+
MOTH_BEGIN_INSTR(GetLookup)
- QV4::Lookup *l = engine->current->lookups + instr.index;
- STOREVALUE(instr.result, l->getter(l, engine, VALUE(instr.base)));
+ STORE_IP();
+ QV4::Lookup *l = function->compilationUnit->runtimeLookups + index;
+ acc = l->getter(l, engine, STACK_VALUE(base));
+ CHECK_EXCEPTION;
MOTH_END_INSTR(GetLookup)
+ MOTH_BEGIN_INSTR(GetLookupA)
+ STORE_IP();
+ STORE_ACC();
+ QV4::Lookup *l = function->compilationUnit->runtimeLookups + index;
+ acc = l->getter(l, engine, accumulator);
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(GetLookupA)
+
MOTH_BEGIN_INSTR(StoreProperty)
- Runtime::method_setProperty(engine, VALUE(instr.base), instr.name, VALUE(instr.source));
+ STORE_IP();
+ STORE_ACC();
+ if (!Runtime::method_storeProperty(engine, STACK_VALUE(base), name, accumulator) && function->isStrict())
+ engine->throwTypeError();
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreProperty)
MOTH_BEGIN_INSTR(SetLookup)
- QV4::Lookup *l = engine->current->lookups + instr.index;
- l->setter(l, engine, VALUE(instr.base), VALUE(instr.source));
+ STORE_IP();
+ STORE_ACC();
+ QV4::Lookup *l = function->compilationUnit->runtimeLookups + index;
+ if (!l->setter(l, engine, STACK_VALUE(base), accumulator) && function->isStrict())
+ engine->throwTypeError();
CHECK_EXCEPTION;
MOTH_END_INSTR(SetLookup)
- MOTH_BEGIN_INSTR(StoreQObjectProperty)
- Runtime::method_setQmlQObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source));
- CHECK_EXCEPTION;
- MOTH_END_INSTR(StoreQObjectProperty)
-
- MOTH_BEGIN_INSTR(LoadQObjectProperty)
- STOREVALUE(instr.result, Runtime::method_getQmlQObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, instr.captureRequired));
- MOTH_END_INSTR(LoadQObjectProperty)
-
MOTH_BEGIN_INSTR(StoreScopeObjectProperty)
- Runtime::method_setQmlScopeObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source));
+ STORE_ACC();
+ Runtime::method_storeQmlScopeObjectProperty(engine, STACK_VALUE(base), propertyIndex, accumulator);
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreScopeObjectProperty)
MOTH_BEGIN_INSTR(LoadScopeObjectProperty)
- STOREVALUE(instr.result, Runtime::method_getQmlScopeObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, instr.captureRequired));
+ STORE_IP();
+ acc = Runtime::method_loadQmlScopeObjectProperty(engine, STACK_VALUE(base), propertyIndex, captureRequired);
+ CHECK_EXCEPTION;
MOTH_END_INSTR(LoadScopeObjectProperty)
MOTH_BEGIN_INSTR(StoreContextObjectProperty)
- Runtime::method_setQmlContextObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source));
+ STORE_IP();
+ STORE_ACC();
+ Runtime::method_storeQmlContextObjectProperty(engine, STACK_VALUE(base), propertyIndex, accumulator);
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreContextObjectProperty)
MOTH_BEGIN_INSTR(LoadContextObjectProperty)
- STOREVALUE(instr.result, Runtime::method_getQmlContextObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, instr.captureRequired));
+ STORE_IP();
+ acc = Runtime::method_loadQmlContextObjectProperty(engine, STACK_VALUE(base), propertyIndex, captureRequired);
+ CHECK_EXCEPTION;
MOTH_END_INSTR(LoadContextObjectProperty)
MOTH_BEGIN_INSTR(LoadIdObject)
- STOREVALUE(instr.result, Runtime::method_getQmlIdObject(engine, VALUE(instr.base), instr.index));
+ STORE_IP();
+ acc = Runtime::method_loadQmlIdObject(engine, STACK_VALUE(base), index);
+ CHECK_EXCEPTION;
MOTH_END_INSTR(LoadIdObject)
- MOTH_BEGIN_INSTR(LoadAttachedQObjectProperty)
- STOREVALUE(instr.result, Runtime::method_getQmlAttachedProperty(engine, instr.attachedPropertiesId, instr.propertyIndex));
- MOTH_END_INSTR(LoadAttachedQObjectProperty)
-
- MOTH_BEGIN_INSTR(LoadSingletonQObjectProperty)
- STOREVALUE(instr.result, Runtime::method_getQmlSingletonQObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, instr.captureRequired));
- MOTH_END_INSTR(LoadSingletonQObjectProperty)
-
- MOTH_BEGIN_INSTR(Push)
- TRACE(inline, "stack size: %u", instr.value);
- stackSize = instr.value;
- stack = scope.alloc(stackSize);
- scopes[1].values = stack;
- MOTH_END_INSTR(Push)
-
MOTH_BEGIN_INSTR(CallValue)
-#if 0 //def DO_TRACE_INSTR
- if (Debugging::Debugger *debugger = context->engine()->debugger) {
- if (QV4::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;
- }
- }
+ STORE_IP();
+ STORE_ACC();
+ Value func = Value::fromReturnedValue(acc);
+ if (Q_UNLIKELY(!func.isFunctionObject())) {
+ acc = engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow()));
+ goto catchException;
}
-#endif // DO_TRACE_INSTR
- Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
- QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = quint32(Value::ValueTypeInternal::Integer);
- callData->argc = instr.argc;
- callData->thisObject = QV4::Primitive::undefinedValue();
- STOREVALUE(instr.result, Runtime::method_callValue(engine, VALUE(instr.dest), callData));
+ acc = static_cast<const FunctionObject &>(func).call(nullptr, stack + argv, argc);
+ CHECK_EXCEPTION;
MOTH_END_INSTR(CallValue)
MOTH_BEGIN_INSTR(CallProperty)
- TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(engine)->toQString().toUtf8().constData());
- Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
- QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = quint32(Value::ValueTypeInternal::Integer);
- callData->argc = instr.argc;
- callData->thisObject = VALUE(instr.base);
- STOREVALUE(instr.result, Runtime::method_callProperty(engine, instr.name, callData));
+ STORE_IP();
+ acc = Runtime::method_callProperty(engine, stack + base, name, stack + argv, argc);
+ CHECK_EXCEPTION;
MOTH_END_INSTR(CallProperty)
MOTH_BEGIN_INSTR(CallPropertyLookup)
- Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
- QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = quint32(Value::ValueTypeInternal::Integer);
- callData->argc = instr.argc;
- callData->thisObject = VALUE(instr.base);
- STOREVALUE(instr.result, Runtime::method_callPropertyLookup(engine, instr.lookupIndex, callData));
- MOTH_END_INSTR(CallPropertyLookup)
+ STORE_IP();
+ Lookup *l = function->compilationUnit->runtimeLookups + lookupIndex;
+ // ok to have the value on the stack here
+ Value f = Value::fromReturnedValue(l->getter(l, engine, stack[base]));
+
+ if (Q_UNLIKELY(!f.isFunctionObject())) {
+ acc = engine->throwTypeError();
+ goto catchException;
+ }
- MOTH_BEGIN_INSTR(CallScopeObjectProperty)
- TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(engine)->toQString().toUtf8().constData());
- Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
- QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = quint32(Value::ValueTypeInternal::Integer);
- callData->argc = instr.argc;
- callData->thisObject = VALUE(instr.base);
- STOREVALUE(instr.result, Runtime::method_callQmlScopeObjectProperty(engine, instr.index, callData));
- MOTH_END_INSTR(CallScopeObjectProperty)
-
- MOTH_BEGIN_INSTR(CallContextObjectProperty)
- TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(engine)->toQString().toUtf8().constData());
- Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
- QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = quint32(Value::ValueTypeInternal::Integer);
- callData->argc = instr.argc;
- callData->thisObject = VALUE(instr.base);
- STOREVALUE(instr.result, Runtime::method_callQmlContextObjectProperty(engine, instr.index, callData));
- MOTH_END_INSTR(CallContextObjectProperty)
+ acc = static_cast<FunctionObject &>(f).call(stack + base, stack + argv, argc);
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(CallPropertyLookup)
MOTH_BEGIN_INSTR(CallElement)
- Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
- QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = quint32(Value::ValueTypeInternal::Integer);
- callData->argc = instr.argc;
- callData->thisObject = VALUE(instr.base);
- STOREVALUE(instr.result, Runtime::method_callElement(engine, VALUE(instr.index), callData));
+ STORE_IP();
+ acc = Runtime::method_callElement(engine, stack + base, STACK_VALUE(index), stack + argv, argc);
+ CHECK_EXCEPTION;
MOTH_END_INSTR(CallElement)
- MOTH_BEGIN_INSTR(CallActivationProperty)
- Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
- QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = quint32(Value::ValueTypeInternal::Integer);
- callData->argc = instr.argc;
- callData->thisObject = QV4::Primitive::undefinedValue();
- STOREVALUE(instr.result, Runtime::method_callActivationProperty(engine, instr.name, callData));
- MOTH_END_INSTR(CallActivationProperty)
+ MOTH_BEGIN_INSTR(CallName)
+ STORE_IP();
+ acc = Runtime::method_callName(engine, name, stack + argv, argc);
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(CallName)
+
+ MOTH_BEGIN_INSTR(CallPossiblyDirectEval)
+ STORE_IP();
+ acc = Runtime::method_callPossiblyDirectEval(engine, stack + argv, argc);
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(CallPossiblyDirectEval)
MOTH_BEGIN_INSTR(CallGlobalLookup)
- Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
- QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = quint32(Value::ValueTypeInternal::Integer);
- callData->argc = instr.argc;
- callData->thisObject = QV4::Primitive::undefinedValue();
- STOREVALUE(instr.result, Runtime::method_callGlobalLookup(engine, instr.index, callData));
+ STORE_IP();
+ acc = Runtime::method_callGlobalLookup(engine, index, stack + argv, argc);
+ CHECK_EXCEPTION;
MOTH_END_INSTR(CallGlobalLookup)
MOTH_BEGIN_INSTR(SetExceptionHandler)
- exceptionHandler = instr.offset ? ((const uchar *)&instr.offset) + instr.offset : 0;
+ exceptionHandler = offset ? code + offset : nullptr;
MOTH_END_INSTR(SetExceptionHandler)
- MOTH_BEGIN_INSTR(CallBuiltinThrow)
- Runtime::method_throwException(engine, VALUE(instr.arg));
+ MOTH_BEGIN_INSTR(ThrowException)
+ STORE_IP();
+ STORE_ACC();
+ Runtime::method_throwException(engine, accumulator);
+ goto catchException;
+ MOTH_END_INSTR(ThrowException)
+
+ MOTH_BEGIN_INSTR(GetException)
+ acc = engine->hasException ? engine->exceptionValue->asReturnedValue()
+ : Primitive::emptyValue().asReturnedValue();
+ engine->hasException = false;
+ MOTH_END_INSTR(HasException)
+
+ MOTH_BEGIN_INSTR(SetException)
+ *engine->exceptionValue = acc;
+ engine->hasException = true;
+ MOTH_END_INSTR(SetException)
+
+ MOTH_BEGIN_INSTR(PushCatchContext)
+ STACK_VALUE(reg) = STACK_VALUE(CallData::Context);
+ ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context);
+ STACK_VALUE(CallData::Context) = Runtime::method_createCatchContext(c, name);
+ MOTH_END_INSTR(PushCatchContext)
+
+ MOTH_BEGIN_INSTR(CreateCallContext)
+ stack[CallData::Context] = ExecutionContext::newCallContext(&frame);
+ MOTH_END_INSTR(CreateCallContext)
+
+ MOTH_BEGIN_INSTR(PushWithContext)
+ STORE_IP();
+ STORE_ACC();
+ accumulator = accumulator.toObject(engine);
+ CHECK_EXCEPTION;
+ STACK_VALUE(reg) = STACK_VALUE(CallData::Context);
+ ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context);
+ STACK_VALUE(CallData::Context) = Runtime::method_createWithContext(c, accumulator);
+ MOTH_END_INSTR(PushWithContext)
+
+ MOTH_BEGIN_INSTR(PopContext)
+ STACK_VALUE(CallData::Context) = STACK_VALUE(reg);
+ MOTH_END_INSTR(PopContext)
+
+ MOTH_BEGIN_INSTR(ForeachIteratorObject)
+ STORE_ACC();
+ acc = Runtime::method_foreachIterator(engine, accumulator);
CHECK_EXCEPTION;
- MOTH_END_INSTR(CallBuiltinThrow)
+ MOTH_END_INSTR(ForeachIteratorObject)
- MOTH_BEGIN_INSTR(CallBuiltinUnwindException)
- STOREVALUE(instr.result, Runtime::method_unwindException(engine));
- MOTH_END_INSTR(CallBuiltinUnwindException)
+ MOTH_BEGIN_INSTR(ForeachNextPropertyName)
+ STORE_ACC();
+ acc = Runtime::method_foreachNextPropertyName(accumulator);
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(ForeachNextPropertyName)
+
+ MOTH_BEGIN_INSTR(DeleteMember)
+ if (!Runtime::method_deleteMember(engine, STACK_VALUE(base), member)) {
+ if (function->isStrict()) {
+ STORE_IP();
+ engine->throwTypeError();
+ goto catchException;
+ }
+ acc = Encode(false);
+ } else {
+ acc = Encode(true);
+ }
+ MOTH_END_INSTR(DeleteMember)
+
+ MOTH_BEGIN_INSTR(DeleteSubscript)
+ if (!Runtime::method_deleteElement(engine, STACK_VALUE(base), STACK_VALUE(index))) {
+ if (function->isStrict()) {
+ STORE_IP();
+ engine->throwTypeError();
+ goto catchException;
+ }
+ acc = Encode(false);
+ } else {
+ acc = Encode(true);
+ }
+ MOTH_END_INSTR(DeleteSubscript)
+
+ MOTH_BEGIN_INSTR(DeleteName)
+ if (!Runtime::method_deleteName(engine, name)) {
+ if (function->isStrict()) {
+ STORE_IP();
+ QString n = function->compilationUnit->runtimeStrings[name]->toQString();
+ engine->throwSyntaxError(QStringLiteral("Can't delete property %1").arg(n));
+ goto catchException;
+ }
+ acc = Encode(false);
+ } else {
+ acc = Encode(true);
+ }
+ MOTH_END_INSTR(DeleteName)
+
+ MOTH_BEGIN_INSTR(TypeofName)
+ acc = Runtime::method_typeofName(engine, name);
+ MOTH_END_INSTR(TypeofName)
+
+ MOTH_BEGIN_INSTR(TypeofValue)
+ STORE_ACC();
+ acc = Runtime::method_typeofValue(engine, accumulator);
+ MOTH_END_INSTR(TypeofValue)
+
+ MOTH_BEGIN_INSTR(DeclareVar)
+ Runtime::method_declareVar(engine, isDeletable, varName);
+ MOTH_END_INSTR(DeclareVar)
+
+ MOTH_BEGIN_INSTR(DefineArray)
+ QV4::Value *arguments = stack + args;
+ acc = Runtime::method_arrayLiteral(engine, arguments, argc);
+ MOTH_END_INSTR(DefineArray)
+
+ MOTH_BEGIN_INSTR(DefineObjectLiteral)
+ QV4::Value *arguments = stack + args;
+ acc = Runtime::method_objectLiteral(engine, arguments, internalClassId, arrayValueCount, arrayGetterSetterCountAndFlags);
+ MOTH_END_INSTR(DefineObjectLiteral)
+
+ MOTH_BEGIN_INSTR(CreateMappedArgumentsObject)
+ acc = Runtime::method_createMappedArgumentsObject(engine);
+ MOTH_END_INSTR(CreateMappedArgumentsObject)
+
+ MOTH_BEGIN_INSTR(CreateUnmappedArgumentsObject)
+ acc = Runtime::method_createUnmappedArgumentsObject(engine);
+ MOTH_END_INSTR(CreateUnmappedArgumentsObject)
+
+ MOTH_BEGIN_INSTR(ConvertThisToObject)
+ Value *t = &stack[CallData::This];
+ if (!t->isObject()) {
+ if (t->isNullOrUndefined()) {
+ *t = engine->globalObject->asReturnedValue();
+ } else {
+ *t = t->toObject(engine)->asReturnedValue();
+ CHECK_EXCEPTION;
+ }
+ }
+ MOTH_END_INSTR(ConvertThisToObject)
- MOTH_BEGIN_INSTR(CallBuiltinPushCatchScope)
- Runtime::method_pushCatchScope(static_cast<QV4::NoThrowEngine*>(engine), instr.name);
- MOTH_END_INSTR(CallBuiltinPushCatchScope)
-
- MOTH_BEGIN_INSTR(CallBuiltinPushScope)
- Runtime::method_pushWithScope(VALUE(instr.arg), static_cast<QV4::NoThrowEngine*>(engine));
- CHECK_EXCEPTION;
- MOTH_END_INSTR(CallBuiltinPushScope)
-
- MOTH_BEGIN_INSTR(CallBuiltinPopScope)
- Runtime::method_popScope(static_cast<QV4::NoThrowEngine*>(engine));
- MOTH_END_INSTR(CallBuiltinPopScope)
-
- MOTH_BEGIN_INSTR(CallBuiltinForeachIteratorObject)
- STOREVALUE(instr.result, Runtime::method_foreachIterator(engine, VALUE(instr.arg)));
- MOTH_END_INSTR(CallBuiltinForeachIteratorObject)
-
- MOTH_BEGIN_INSTR(CallBuiltinForeachNextPropertyName)
- STOREVALUE(instr.result, Runtime::method_foreachNextPropertyName(VALUE(instr.arg)));
- MOTH_END_INSTR(CallBuiltinForeachNextPropertyName)
-
- MOTH_BEGIN_INSTR(CallBuiltinDeleteMember)
- STOREVALUE(instr.result, Runtime::method_deleteMember(engine, VALUE(instr.base), instr.member));
- MOTH_END_INSTR(CallBuiltinDeleteMember)
-
- MOTH_BEGIN_INSTR(CallBuiltinDeleteSubscript)
- STOREVALUE(instr.result, Runtime::method_deleteElement(engine, VALUE(instr.base), VALUE(instr.index)));
- MOTH_END_INSTR(CallBuiltinDeleteSubscript)
-
- MOTH_BEGIN_INSTR(CallBuiltinDeleteName)
- STOREVALUE(instr.result, Runtime::method_deleteName(engine, instr.name));
- MOTH_END_INSTR(CallBuiltinDeleteName)
-
- MOTH_BEGIN_INSTR(CallBuiltinTypeofScopeObjectProperty)
- STOREVALUE(instr.result, Runtime::method_typeofScopeObjectProperty(engine, VALUE(instr.base), instr.index));
- MOTH_END_INSTR(CallBuiltinTypeofMember)
-
- MOTH_BEGIN_INSTR(CallBuiltinTypeofContextObjectProperty)
- STOREVALUE(instr.result, Runtime::method_typeofContextObjectProperty(engine, VALUE(instr.base), instr.index));
- MOTH_END_INSTR(CallBuiltinTypeofMember)
-
- MOTH_BEGIN_INSTR(CallBuiltinTypeofMember)
- STOREVALUE(instr.result, Runtime::method_typeofMember(engine, VALUE(instr.base), instr.member));
- MOTH_END_INSTR(CallBuiltinTypeofMember)
-
- MOTH_BEGIN_INSTR(CallBuiltinTypeofSubscript)
- STOREVALUE(instr.result, Runtime::method_typeofElement(engine, VALUE(instr.base), VALUE(instr.index)));
- MOTH_END_INSTR(CallBuiltinTypeofSubscript)
-
- MOTH_BEGIN_INSTR(CallBuiltinTypeofName)
- STOREVALUE(instr.result, Runtime::method_typeofName(engine, instr.name));
- MOTH_END_INSTR(CallBuiltinTypeofName)
-
- MOTH_BEGIN_INSTR(CallBuiltinTypeofValue)
- STOREVALUE(instr.result, Runtime::method_typeofValue(engine, VALUE(instr.value)));
- MOTH_END_INSTR(CallBuiltinTypeofValue)
-
- MOTH_BEGIN_INSTR(CallBuiltinDeclareVar)
- Runtime::method_declareVar(engine, instr.isDeletable, instr.varName);
- MOTH_END_INSTR(CallBuiltinDeclareVar)
-
- MOTH_BEGIN_INSTR(CallBuiltinDefineArray)
- Q_ASSERT(instr.args + instr.argc <= stackSize);
- QV4::Value *args = stack + instr.args;
- STOREVALUE(instr.result, Runtime::method_arrayLiteral(engine, args, instr.argc));
- MOTH_END_INSTR(CallBuiltinDefineArray)
-
- MOTH_BEGIN_INSTR(CallBuiltinDefineObjectLiteral)
- QV4::Value *args = stack + instr.args;
- STOREVALUE(instr.result, Runtime::method_objectLiteral(engine, args, instr.internalClassId, instr.arrayValueCount, instr.arrayGetterSetterCountAndFlags));
- MOTH_END_INSTR(CallBuiltinDefineObjectLiteral)
-
- MOTH_BEGIN_INSTR(CallBuiltinSetupArgumentsObject)
- STOREVALUE(instr.result, Runtime::method_setupArgumentsObject(engine));
- MOTH_END_INSTR(CallBuiltinSetupArgumentsObject)
-
- MOTH_BEGIN_INSTR(CallBuiltinConvertThisToObject)
- Runtime::method_convertThisToObject(engine);
- CHECK_EXCEPTION;
- MOTH_END_INSTR(CallBuiltinConvertThisToObject)
-
- MOTH_BEGIN_INSTR(CreateValue)
- Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
- QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = quint32(Value::ValueTypeInternal::Integer);
- callData->argc = instr.argc;
- callData->thisObject = QV4::Primitive::undefinedValue();
- STOREVALUE(instr.result, Runtime::method_constructValue(engine, VALUE(instr.func), callData));
- MOTH_END_INSTR(CreateValue)
-
- MOTH_BEGIN_INSTR(CreateProperty)
- Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
- QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = quint32(Value::ValueTypeInternal::Integer);
- callData->argc = instr.argc;
- callData->thisObject = VALUE(instr.base);
- STOREVALUE(instr.result, Runtime::method_constructProperty(engine, instr.name, callData));
- MOTH_END_INSTR(CreateProperty)
-
- MOTH_BEGIN_INSTR(ConstructPropertyLookup)
- Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
- QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = quint32(Value::ValueTypeInternal::Integer);
- callData->argc = instr.argc;
- callData->thisObject = VALUE(instr.base);
- STOREVALUE(instr.result, Runtime::method_constructPropertyLookup(engine, instr.index, callData));
- MOTH_END_INSTR(ConstructPropertyLookup)
-
- MOTH_BEGIN_INSTR(CreateActivationProperty)
- Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
- QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = quint32(Value::ValueTypeInternal::Integer);
- callData->argc = instr.argc;
- callData->thisObject = QV4::Primitive::undefinedValue();
- STOREVALUE(instr.result, Runtime::method_constructActivationProperty(engine, instr.name, callData));
- MOTH_END_INSTR(CreateActivationProperty)
-
- MOTH_BEGIN_INSTR(ConstructGlobalLookup)
- Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
- QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = quint32(Value::ValueTypeInternal::Integer);
- callData->argc = instr.argc;
- callData->thisObject = QV4::Primitive::undefinedValue();
- STOREVALUE(instr.result, Runtime::method_constructGlobalLookup(engine, instr.index, callData));
- MOTH_END_INSTR(ConstructGlobalLookup)
+ MOTH_BEGIN_INSTR(Construct)
+ STORE_IP();
+ acc = Runtime::method_construct(engine, STACK_VALUE(func), stack + argv, argc);
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(Construct)
MOTH_BEGIN_INSTR(Jump)
- code = ((const uchar *)&instr.offset) + instr.offset;
+ code += offset;
MOTH_END_INSTR(Jump)
- MOTH_BEGIN_INSTR(JumpEq)
- bool cond = VALUEPTR(instr.condition)->toBoolean();
- TRACE(condition, "%s", cond ? "TRUE" : "FALSE");
- if (cond)
- code = ((const uchar *)&instr.offset) + instr.offset;
- MOTH_END_INSTR(JumpEq)
+ MOTH_BEGIN_INSTR(JumpTrue)
+ if (Q_LIKELY(ACC.integerCompatible())) {
+ if (ACC.int_32())
+ code += offset;
+ } else {
+ if (ACC.toBoolean())
+ code += offset;
+ }
+ MOTH_END_INSTR(JumpTrue)
+
+ MOTH_BEGIN_INSTR(JumpFalse)
+ if (Q_LIKELY(ACC.integerCompatible())) {
+ if (!ACC.int_32())
+ code += offset;
+ } else {
+ if (!ACC.toBoolean())
+ code += offset;
+ }
+ MOTH_END_INSTR(JumpFalse)
+
+ MOTH_BEGIN_INSTR(CmpEqNull)
+ acc = Encode(ACC.isNullOrUndefined());
+ MOTH_END_INSTR(CmpEqNull)
+
+ MOTH_BEGIN_INSTR(CmpNeNull)
+ acc = Encode(!ACC.isNullOrUndefined());
+ MOTH_END_INSTR(CmpNeNull)
+
+ MOTH_BEGIN_INSTR(CmpEqInt)
+ if (ACC.isIntOrBool()) {
+ acc = Encode(ACC.int_32() == lhs);
+ } else {
+ STORE_ACC();
+ acc = Encode(compareEqualInt(accumulator, ACC, lhs));
+ CHECK_EXCEPTION;
+ }
+ MOTH_END_INSTR(CmpEqInt)
+
+ MOTH_BEGIN_INSTR(CmpNeInt)
+ if (ACC.isIntOrBool()) {
+ acc = Encode(bool(ACC.int_32() != lhs));
+ } else {
+ STORE_ACC();
+ acc = Encode(!compareEqualInt(accumulator, ACC, lhs));
+ CHECK_EXCEPTION;
+ }
+ MOTH_END_INSTR(CmpNeInt)
+
+ MOTH_BEGIN_INSTR(CmpEq)
+ const Value left = STACK_VALUE(lhs);
+ if (Q_LIKELY(left.asReturnedValue() == ACC.asReturnedValue())) {
+ acc = Encode(!ACC.isNaN());
+ } else if (Q_LIKELY(left.isInteger() && ACC.isInteger())) {
+ acc = Encode(left.int_32() == ACC.int_32());
+ } else {
+ STORE_ACC();
+ acc = Encode(compareEqual(left, accumulator));
+ CHECK_EXCEPTION;
+ }
+ MOTH_END_INSTR(CmpEq)
+
+ MOTH_BEGIN_INSTR(CmpNe)
+ const Value left = STACK_VALUE(lhs);
+ if (Q_LIKELY(left.isInteger() && ACC.isInteger())) {
+ acc = Encode(bool(left.int_32() != ACC.int_32()));
+ } else {
+ STORE_ACC();
+ acc = Encode(!compareEqual(left, accumulator));
+ CHECK_EXCEPTION;
+ }
+ MOTH_END_INSTR(CmpNe)
+
+ MOTH_BEGIN_INSTR(CmpGt)
+ const Value left = STACK_VALUE(lhs);
+ if (Q_LIKELY(left.isInteger() && ACC.isInteger())) {
+ acc = Encode(left.int_32() > ACC.int_32());
+ } else if (left.isNumber() && ACC.isNumber()) {
+ acc = Encode(left.asDouble() > ACC.asDouble());
+ } else {
+ STORE_ACC();
+ acc = Encode(bool(Runtime::method_compareGreaterThan(left, accumulator)));
+ CHECK_EXCEPTION;
+ }
+ MOTH_END_INSTR(CmpGt)
+
+ MOTH_BEGIN_INSTR(CmpGe)
+ const Value left = STACK_VALUE(lhs);
+ if (Q_LIKELY(left.isInteger() && ACC.isInteger())) {
+ acc = Encode(left.int_32() >= ACC.int_32());
+ } else if (left.isNumber() && ACC.isNumber()) {
+ acc = Encode(left.asDouble() >= ACC.asDouble());
+ } else {
+ STORE_ACC();
+ acc = Encode(bool(Runtime::method_compareGreaterEqual(left, accumulator)));
+ CHECK_EXCEPTION;
+ }
+ MOTH_END_INSTR(CmpGe)
+
+ MOTH_BEGIN_INSTR(CmpLt)
+ const Value left = STACK_VALUE(lhs);
+ if (Q_LIKELY(left.isInteger() && ACC.isInteger())) {
+ acc = Encode(left.int_32() < ACC.int_32());
+ } else if (left.isNumber() && ACC.isNumber()) {
+ acc = Encode(left.asDouble() < ACC.asDouble());
+ } else {
+ STORE_ACC();
+ acc = Encode(bool(Runtime::method_compareLessThan(left, accumulator)));
+ CHECK_EXCEPTION;
+ }
+ MOTH_END_INSTR(CmpLt)
+
+ MOTH_BEGIN_INSTR(CmpLe)
+ const Value left = STACK_VALUE(lhs);
+ if (Q_LIKELY(left.isInteger() && ACC.isInteger())) {
+ acc = Encode(left.int_32() <= ACC.int_32());
+ } else if (left.isNumber() && ACC.isNumber()) {
+ acc = Encode(left.asDouble() <= ACC.asDouble());
+ } else {
+ STORE_ACC();
+ acc = Encode(bool(Runtime::method_compareLessEqual(left, accumulator)));
+ CHECK_EXCEPTION;
+ }
+ MOTH_END_INSTR(CmpLe)
+
+ MOTH_BEGIN_INSTR(CmpStrictEqual)
+ if (STACK_VALUE(lhs).rawValue() == ACC.rawValue() && !ACC.isNaN()) {
+ acc = Encode(true);
+ } else {
+ STORE_ACC();
+ acc = Encode(bool(RuntimeHelpers::strictEqual(STACK_VALUE(lhs), accumulator)));
+ CHECK_EXCEPTION;
+ }
+ MOTH_END_INSTR(CmpStrictEqual)
+
+ MOTH_BEGIN_INSTR(CmpStrictNotEqual)
+ if (STACK_VALUE(lhs).rawValue() != ACC.rawValue() || ACC.isNaN()) {
+ STORE_ACC();
+ acc = Encode(!RuntimeHelpers::strictEqual(STACK_VALUE(lhs), accumulator));
+ CHECK_EXCEPTION;
+ } else {
+ acc = Encode(false);
+ }
+ MOTH_END_INSTR(CmpStrictNotEqual)
+
+ MOTH_BEGIN_INSTR(CmpIn)
+ STORE_ACC();
+ acc = Runtime::method_in(engine, STACK_VALUE(lhs), accumulator);
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(CmpIn)
+
+ MOTH_BEGIN_INSTR(CmpInstanceOf)
+ // 11.8.6, 5: rval must be an Object
+ const Object *rhs = Primitive::fromReturnedValue(acc).as<Object>();
+ if (Q_UNLIKELY(!rhs)) {
+ acc = engine->throwTypeError();
+ goto catchException;
+ }
+
+ // 11.8.6, 7: call "HasInstance", which we term instanceOf, and return the result.
+ acc = rhs->instanceOf(STACK_VALUE(lhs));
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(CmpInstanceOf)
+
+ MOTH_BEGIN_INSTR(JumpStrictNotEqualStackSlotInt)
+ if (STACK_VALUE(lhs).int_32() != rhs || STACK_VALUE(lhs).isUndefined())
+ code += offset;
+ MOTH_END_INSTR(JumpStrictNotEqualStackSlotInt)
- MOTH_BEGIN_INSTR(JumpNe)
- bool cond = VALUEPTR(instr.condition)->toBoolean();
- TRACE(condition, "%s", cond ? "TRUE" : "FALSE");
- if (!cond)
- code = ((const uchar *)&instr.offset) + instr.offset;
- MOTH_END_INSTR(JumpNe)
+ MOTH_BEGIN_INSTR(JumpStrictEqualStackSlotInt)
+ if (STACK_VALUE(lhs).int_32() == rhs && !STACK_VALUE(lhs).isUndefined())
+ code += offset;
+ MOTH_END_INSTR(JumpStrictNotEqualStackSlotInt)
MOTH_BEGIN_INSTR(UNot)
- STOREVALUE(instr.result, Runtime::method_uNot(VALUE(instr.source)));
+ if (ACC.integerCompatible()) {
+ acc = Encode(!static_cast<bool>(ACC.int_32()));
+ } else {
+ acc = Encode(!Value::toBooleanImpl(ACC));
+ }
MOTH_END_INSTR(UNot)
- MOTH_BEGIN_INSTR(UNotBool)
- bool b = VALUE(instr.source).booleanValue();
- VALUE(instr.result) = QV4::Encode(!b);
- MOTH_END_INSTR(UNotBool)
-
MOTH_BEGIN_INSTR(UPlus)
- STOREVALUE(instr.result, Runtime::method_uPlus(VALUE(instr.source)));
+ if (Q_UNLIKELY(!ACC.isNumber())) {
+ acc = Encode(ACC.toNumberImpl());
+ CHECK_EXCEPTION;
+ }
MOTH_END_INSTR(UPlus)
MOTH_BEGIN_INSTR(UMinus)
- STOREVALUE(instr.result, Runtime::method_uMinus(VALUE(instr.source)));
+ if (Q_LIKELY(ACC.integerCompatible())) {
+ int a = ACC.int_32();
+ if (a == 0 || a == std::numeric_limits<int>::min()) {
+ acc = Encode(-static_cast<double>(a));
+ } else {
+ acc = sub_int32(0, ACC.int_32());
+ }
+ } else if (ACC.isDouble()) {
+ acc ^= (1ull << 63); // simply flip sign bit
+ } else {
+ acc = Encode(-ACC.toNumberImpl());
+ CHECK_EXCEPTION;
+ }
MOTH_END_INSTR(UMinus)
MOTH_BEGIN_INSTR(UCompl)
- STOREVALUE(instr.result, Runtime::method_complement(VALUE(instr.source)));
+ VALUE_TO_INT(a, ACC);
+ acc = Encode(~a);
MOTH_END_INSTR(UCompl)
- MOTH_BEGIN_INSTR(UComplInt)
- VALUE(instr.result) = QV4::Encode((int)~VALUE(instr.source).integerValue());
- MOTH_END_INSTR(UComplInt)
-
MOTH_BEGIN_INSTR(Increment)
- STOREVALUE(instr.result, Runtime::method_increment(VALUE(instr.source)));
+ if (Q_LIKELY(ACC.integerCompatible())) {
+ acc = add_int32(ACC.int_32(), 1);
+ } else if (ACC.isDouble()) {
+ acc = QV4::Encode(ACC.doubleValue() + 1.);
+ } else {
+ acc = Encode(ACC.toNumberImpl() + 1.);
+ CHECK_EXCEPTION;
+ }
MOTH_END_INSTR(Increment)
MOTH_BEGIN_INSTR(Decrement)
- STOREVALUE(instr.result, Runtime::method_decrement(VALUE(instr.source)));
+ if (Q_LIKELY(ACC.integerCompatible())) {
+ acc = sub_int32(ACC.int_32(), 1);
+ } else if (ACC.isDouble()) {
+ acc = QV4::Encode(ACC.doubleValue() - 1.);
+ } else {
+ acc = Encode(ACC.toNumberImpl() - 1.);
+ CHECK_EXCEPTION;
+ }
MOTH_END_INSTR(Decrement)
- MOTH_BEGIN_INSTR(Binop)
- QV4::Runtime::BinaryOperation op = *reinterpret_cast<QV4::Runtime::BinaryOperation *>(reinterpret_cast<char *>(&engine->runtime.runtimeMethods[instr.alu]));
- STOREVALUE(instr.result, op(VALUE(instr.lhs), VALUE(instr.rhs)));
- MOTH_END_INSTR(Binop)
-
MOTH_BEGIN_INSTR(Add)
- STOREVALUE(instr.result, Runtime::method_add(engine, VALUE(instr.lhs), VALUE(instr.rhs)));
+ const Value left = STACK_VALUE(lhs);
+ if (Q_LIKELY(Value::integerCompatible(left, ACC))) {
+ acc = add_int32(left.int_32(), ACC.int_32());
+ } else if (left.isNumber() && ACC.isNumber()) {
+ acc = Encode(left.asDouble() + ACC.asDouble());
+ } else {
+ STORE_ACC();
+ acc = Runtime::method_add(engine, left, accumulator);
+ CHECK_EXCEPTION;
+ }
MOTH_END_INSTR(Add)
+ MOTH_BEGIN_INSTR(Sub)
+ const Value left = STACK_VALUE(lhs);
+ if (Q_LIKELY(Value::integerCompatible(left, ACC))) {
+ acc = sub_int32(left.int_32(), ACC.int_32());
+ } else if (left.isNumber() && ACC.isNumber()) {
+ acc = Encode(left.asDouble() - ACC.asDouble());
+ } else {
+ STORE_ACC();
+ acc = Runtime::method_sub(left, accumulator);
+ CHECK_EXCEPTION;
+ }
+ MOTH_END_INSTR(Sub)
+
+ MOTH_BEGIN_INSTR(Mul)
+ const Value left = STACK_VALUE(lhs);
+ if (Q_LIKELY(Value::integerCompatible(left, ACC))) {
+ acc = mul_int32(left.int_32(), ACC.int_32());
+ } else if (left.isNumber() && ACC.isNumber()) {
+ acc = Encode(left.asDouble() * ACC.asDouble());
+ } else {
+ STORE_ACC();
+ acc = Runtime::method_mul(left, accumulator);
+ CHECK_EXCEPTION;
+ }
+ MOTH_END_INSTR(Mul)
+
+ MOTH_BEGIN_INSTR(Div)
+ STORE_ACC();
+ acc = Runtime::method_div(STACK_VALUE(lhs), accumulator);
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(Div)
+
+ MOTH_BEGIN_INSTR(Mod)
+ STORE_ACC();
+ acc = Runtime::method_mod(STACK_VALUE(lhs), accumulator);
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(Mod)
+
MOTH_BEGIN_INSTR(BitAnd)
- STOREVALUE(instr.result, Runtime::method_bitAnd(VALUE(instr.lhs), VALUE(instr.rhs)));
+ VALUE_TO_INT(l, STACK_VALUE(lhs));
+ VALUE_TO_INT(a, ACC);
+ acc = Encode(l & a);
MOTH_END_INSTR(BitAnd)
MOTH_BEGIN_INSTR(BitOr)
- STOREVALUE(instr.result, Runtime::method_bitOr(VALUE(instr.lhs), VALUE(instr.rhs)));
+ VALUE_TO_INT(l, STACK_VALUE(lhs));
+ VALUE_TO_INT(a, ACC);
+ acc = Encode(l | a);
MOTH_END_INSTR(BitOr)
MOTH_BEGIN_INSTR(BitXor)
- STOREVALUE(instr.result, Runtime::method_bitXor(VALUE(instr.lhs), VALUE(instr.rhs)));
+ VALUE_TO_INT(l, STACK_VALUE(lhs));
+ VALUE_TO_INT(a, ACC);
+ acc = Encode(l ^ a);
MOTH_END_INSTR(BitXor)
+ MOTH_BEGIN_INSTR(UShr)
+ uint l = STACK_VALUE(lhs).toUInt32();
+ VALUE_TO_INT(a, ACC);
+ acc = Encode(l >> uint(a & 0x1f));
+ MOTH_END_INSTR(UShr)
+
MOTH_BEGIN_INSTR(Shr)
- STOREVALUE(instr.result, QV4::Encode((int)(VALUEPTR(instr.lhs)->toInt32() >> (VALUEPTR(instr.rhs)->toInt32() & 0x1f))));
+ VALUE_TO_INT(l, STACK_VALUE(lhs));
+ VALUE_TO_INT(a, ACC);
+ acc = Encode(l >> (a & 0x1f));
MOTH_END_INSTR(Shr)
MOTH_BEGIN_INSTR(Shl)
- STOREVALUE(instr.result, QV4::Encode((int)(VALUEPTR(instr.lhs)->toInt32() << (VALUEPTR(instr.rhs)->toInt32() & 0x1f))));
+ VALUE_TO_INT(l, STACK_VALUE(lhs));
+ VALUE_TO_INT(a, ACC);
+ acc = Encode(l << (a & 0x1f));
MOTH_END_INSTR(Shl)
MOTH_BEGIN_INSTR(BitAndConst)
- int lhs = VALUEPTR(instr.lhs)->toInt32();
- STOREVALUE(instr.result, QV4::Encode((int)(lhs & instr.rhs)));
- MOTH_END_INSTR(BitAnd)
+ VALUE_TO_INT(a, ACC);
+ acc = Encode(a & rhs);
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(BitAndConst)
MOTH_BEGIN_INSTR(BitOrConst)
- int lhs = VALUEPTR(instr.lhs)->toInt32();
- STOREVALUE(instr.result, QV4::Encode((int)(lhs | instr.rhs)));
- MOTH_END_INSTR(BitOr)
+ VALUE_TO_INT(a, ACC);
+ acc = Encode(a | rhs);
+ MOTH_END_INSTR(BitOrConst)
MOTH_BEGIN_INSTR(BitXorConst)
- int lhs = VALUEPTR(instr.lhs)->toInt32();
- STOREVALUE(instr.result, QV4::Encode((int)(lhs ^ instr.rhs)));
- MOTH_END_INSTR(BitXor)
+ VALUE_TO_INT(a, ACC);
+ acc = Encode(a ^ rhs);
+ MOTH_END_INSTR(BitXorConst)
+
+ MOTH_BEGIN_INSTR(UShrConst)
+ acc = Encode(ACC.toUInt32() >> uint(rhs));
+ MOTH_END_INSTR(UShrConst)
MOTH_BEGIN_INSTR(ShrConst)
- STOREVALUE(instr.result, QV4::Encode((int)(VALUEPTR(instr.lhs)->toInt32() >> instr.rhs)));
+ VALUE_TO_INT(a, ACC);
+ acc = Encode(a >> rhs);
MOTH_END_INSTR(ShrConst)
MOTH_BEGIN_INSTR(ShlConst)
- STOREVALUE(instr.result, QV4::Encode((int)(VALUEPTR(instr.lhs)->toInt32() << instr.rhs)));
+ VALUE_TO_INT(a, ACC);
+ acc = Encode(a << rhs);
MOTH_END_INSTR(ShlConst)
- MOTH_BEGIN_INSTR(Mul)
- STOREVALUE(instr.result, Runtime::method_mul(VALUE(instr.lhs), VALUE(instr.rhs)));
- MOTH_END_INSTR(Mul)
-
- MOTH_BEGIN_INSTR(Sub)
- STOREVALUE(instr.result, Runtime::method_sub(VALUE(instr.lhs), VALUE(instr.rhs)));
- MOTH_END_INSTR(Sub)
-
- MOTH_BEGIN_INSTR(BinopContext)
- QV4::Runtime::BinaryOperationContext op = *reinterpret_cast<QV4::Runtime::BinaryOperationContext *>(reinterpret_cast<char *>(&engine->runtime.runtimeMethods[instr.alu]));
- STOREVALUE(instr.result, op(engine, VALUE(instr.lhs), VALUE(instr.rhs)));
- MOTH_END_INSTR(BinopContext)
-
MOTH_BEGIN_INSTR(Ret)
-// TRACE(Ret, "returning value %s", result.toString(context)->toQString().toUtf8().constData());
- return VALUE(instr.result).asReturnedValue();
+ goto functionExit;
MOTH_END_INSTR(Ret)
#if QT_CONFIG(qml_debug)
MOTH_BEGIN_INSTR(Debug)
- engine->current->lineNumber = instr.lineNumber;
- QV4::Debugging::Debugger *debugger = engine->debugger();
- if (debugger && debugger->pauseAtNextOpportunity())
- debugger->maybeBreakAtInstruction();
- if (qt_v4IsDebugging)
- qt_v4CheckForBreak(engine->currentContext);
+ STORE_IP();
+ debug_slowPath(engine);
MOTH_END_INSTR(Debug)
-
- MOTH_BEGIN_INSTR(Line)
- engine->current->lineNumber = instr.lineNumber;
- if (qt_v4IsDebugging)
- qt_v4CheckForBreak(engine->currentContext);
- MOTH_END_INSTR(Line)
#endif // QT_CONFIG(qml_debug)
- MOTH_BEGIN_INSTR(LoadThis)
- VALUE(instr.result) = engine->currentContext->thisObject();
- MOTH_END_INSTR(LoadThis)
-
MOTH_BEGIN_INSTR(LoadQmlContext)
- VALUE(instr.result) = Runtime::method_getQmlContext(static_cast<QV4::NoThrowEngine*>(engine));
+ STACK_VALUE(result) = Runtime::method_loadQmlContext(static_cast<QV4::NoThrowEngine*>(engine));
MOTH_END_INSTR(LoadQmlContext)
MOTH_BEGIN_INSTR(LoadQmlImportedScripts)
- VALUE(instr.result) = Runtime::method_getQmlImportedScripts(static_cast<QV4::NoThrowEngine*>(engine));
+ STACK_VALUE(result) = Runtime::method_loadQmlImportedScripts(static_cast<QV4::NoThrowEngine*>(engine));
MOTH_END_INSTR(LoadQmlImportedScripts)
MOTH_BEGIN_INSTR(LoadQmlSingleton)
- VALUE(instr.result) = Runtime::method_getQmlSingleton(static_cast<QV4::NoThrowEngine*>(engine), instr.name);
+ acc = Runtime::method_loadQmlSingleton(static_cast<QV4::NoThrowEngine*>(engine), name);
MOTH_END_INSTR(LoadQmlSingleton)
-#ifdef MOTH_THREADED_INTERPRETER
- // nothing to do
-#else
- default:
- qFatal("QQmlJS::Moth::VME: Internal error - unknown instruction %d", genericInstr->common.instructionType);
- break;
- }
-#endif
-
- Q_ASSERT(false);
catchException:
Q_ASSERT(engine->hasException);
- if (!exceptionHandler)
- return QV4::Encode::undefined();
+ if (!exceptionHandler) {
+ acc = Encode::undefined();
+ goto functionExit;
+ }
code = exceptionHandler;
}
-}
+ }
-QV4::ReturnedValue VME::exec(ExecutionEngine *engine, const uchar *code)
-{
- VME vme;
- QV4::Debugging::Debugger *debugger = engine->debugger();
- if (debugger)
- debugger->enteringFunction();
- QV4::ReturnedValue retVal = vme.run(engine, code);
- if (debugger)
- debugger->leavingFunction(retVal);
- return retVal;
+functionExit:
+ if (QV4::Debugging::Debugger *debugger = engine->debugger())
+ debugger->leavingFunction(ACC.asReturnedValue());
+ engine->currentStackFrame = frame.parent;
+ engine->jsStackTop = stack;
+
+ return acc;
}