-
Jani Heikkinen authored
- Renamed LICENSE.LGPL to LICENSE.LGPLv21 - Added LICENSE.LGPLv3 & LICENSE.GPLv2 - Removed LICENSE.GPL Change-Id: I84a565e2e0caa3b76bf291a7d188a57a4b00e1b0 Reviewed-by:
Jani Heikkinen <jani.heikkinen@digia.com>
e7ceacda
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qv4vme_moth_p.h"
#include "qv4instr_moth_p.h"
#include <private/qv4value_inl_p.h>
#include <private/qv4debugging_p.h>
#include <private/qv4math_p.h>
#include <private/qv4scopedvalue_p.h>
#include <private/qv4lookup_p.h>
#include <iostream>
#include "qv4alloca_p.h"
#ifdef DO_TRACE_INSTR
# define TRACE_INSTR(I) fprintf(stderr, "executing a %s\n", #I);
# define TRACE(n, str, ...) { char buf[4096]; snprintf(buf, 4096, str, __VA_ARGS__); fprintf(stderr, " %s : %s\n", #n, buf); }
#else
# define TRACE_INSTR(I)
# define TRACE(n, str, ...)
#endif // DO_TRACE_INSTR
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 *genericInstr->common.code; \
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
#else
# define MOTH_BEGIN_INSTR(I) \
case Instr::I: \
MOTH_BEGIN_INSTR_COMMON(I)
# define MOTH_END_INSTR(I) } \
continue;
#endif
#ifdef WITH_STATS
namespace {
struct VMStats {
quint64 paramIsValue;
quint64 paramIsArg;
quint64 paramIsLocal;
quint64 paramIsTemp;
quint64 paramIsScopedLocal;
VMStats()
: paramIsValue(0)
, paramIsArg(0)
, paramIsLocal(0)
, paramIsTemp(0)
, paramIsScopedLocal(0)
{}
~VMStats()
{ show(); }
void show() {
fprintf(stderr, "VM stats:\n");
fprintf(stderr, " value: %lu\n", paramIsValue);
fprintf(stderr, " arg: %lu\n", paramIsArg);
fprintf(stderr, " local: %lu\n", paramIsLocal);
fprintf(stderr, " temp: %lu\n", paramIsTemp);
fprintf(stderr, " scoped local: %lu\n", paramIsScopedLocal);
}
};
static VMStats vmStats;
#define VMSTATS(what) ++vmStats.what
}
#else // !WITH_STATS
#define VMSTATS(what) {}
#endif // WITH_STATS
#ifdef DO_TRACE_INSTR
Param traceParam(const Param ¶m)
{
if (param.isConstant()) {
fprintf(stderr, " constant\n");
} else if (param.isArgument()) {
fprintf(stderr, " argument %d@%d\n", param.index, param.scope);
} else if (param.isLocal()) {
fprintf(stderr, " local %d\n", param.index);
} else if (param.isTemp()) {
fprintf(stderr, " temp %d\n", param.index);
} else if (param.isScopedLocal()) {
fprintf(stderr, " temp %d@%d\n", param.index, param.scope);
} else {
Q_ASSERT(!"INVALID");
}
return Param
}
# define VALUE(param) (*VALUEPTR(param))
# define VALUEPTR(param) (scopes[traceParam(param).scope] + param.index)
#else
# define VALUE(param) (*VALUEPTR(param))
# define VALUEPTR(param) (scopes[param.scope] + param.index)
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
#endif
#define STOREVALUE(param, value) { \
QV4::ReturnedValue tmp = (value); \
if (engine->hasException) \
goto catchException; \
VALUE(param) = tmp; \
}
#define CHECK_EXCEPTION \
if (engine->hasException) \
goto catchException
QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
#ifdef MOTH_THREADED_INTERPRETER
, void ***storeJumpTable
#endif
)
{
#ifdef DO_TRACE_INSTR
qDebug("Starting VME with context=%p and code=%p", context, code);
#endif // DO_TRACE_INSTR
#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;
return QV4::Primitive::undefinedValue().asReturnedValue();
}
#endif
QV4::Value *stack = 0;
unsigned stackSize = 0;
const uchar *exceptionHandler = 0;
context->d()->lineNumber = -1;
QV4::ExecutionEngine *engine = context->d()->engine;
#ifdef DO_TRACE_INSTR
qDebug("Starting VME with context=%p and code=%p", context, code);
#endif // DO_TRACE_INSTR
QV4::StringValue * const runtimeStrings = context->d()->compilationUnit->runtimeStrings;
// setup lookup scopes
int scopeDepth = 0;
{
QV4::ExecutionContext *scope = context;
while (scope) {
++scopeDepth;
scope = scope->d()->outer;
}
}
QV4::Value **scopes = static_cast<QV4::Value **>(alloca(sizeof(QV4::Value *)*(2 + 2*scopeDepth)));
{
scopes[0] = const_cast<QV4::Value *>(context->d()->compilationUnit->data->constants());
// stack gets setup in push instruction
scopes[1] = 0;
QV4::ExecutionContext *scope = context;
int i = 0;
while (scope) {
if (scope->d()->type >= QV4::ExecutionContext::Type_SimpleCallContext) {
QV4::CallContext *cc = static_cast<QV4::CallContext *>(scope);
scopes[2*i + 2] = cc->d()->callData->args;
scopes[2*i + 3] = cc->d()->locals;
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
} else {
scopes[2*i + 2] = 0;
scopes[2*i + 3] = 0;
}
++i;
scope = scope->d()->outer;
}
}
for (;;) {
const Instr *genericInstr = reinterpret_cast<const Instr *>(code);
#ifdef MOTH_THREADED_INTERPRETER
goto *genericInstr->common.code;
#else
switch (genericInstr->common.instructionType) {
#endif
MOTH_BEGIN_INSTR(Move)
VALUE(instr.result) = VALUE(instr.source);
MOTH_END_INSTR(Move)
MOTH_BEGIN_INSTR(MoveConst)
VALUE(instr.result) = instr.source;
MOTH_END_INSTR(MoveConst)
MOTH_BEGIN_INSTR(SwapTemps)
qSwap(VALUE(instr.left), VALUE(instr.right));
MOTH_END_INSTR(MoveTemp)
MOTH_BEGIN_INSTR(LoadRuntimeString)
// TRACE(value, "%s", instr.value.toString(context)->toQString().toUtf8().constData());
VALUE(instr.result) = runtimeStrings[instr.stringId].asReturnedValue();
MOTH_END_INSTR(LoadRuntimeString)
MOTH_BEGIN_INSTR(LoadRegExp)
// TRACE(value, "%s", instr.value.toString(context)->toQString().toUtf8().constData());
VALUE(instr.result) = context->d()->compilationUnit->runtimeRegularExpressions[instr.regExpId];
MOTH_END_INSTR(LoadRegExp)
MOTH_BEGIN_INSTR(LoadClosure)
STOREVALUE(instr.result, Runtime::closure(context, instr.value));
MOTH_END_INSTR(LoadClosure)
MOTH_BEGIN_INSTR(LoadName)
TRACE(inline, "property name = %s", runtimeStrings[instr.name]->toQString().toUtf8().constData());
STOREVALUE(instr.result, Runtime::getActivationProperty(context, runtimeStrings[instr.name]));
MOTH_END_INSTR(LoadName)
MOTH_BEGIN_INSTR(GetGlobalLookup)
TRACE(inline, "property name = %s", runtimeStrings[instr.name]->toQString().toUtf8().constData());
QV4::Lookup *l = context->d()->lookups + instr.index;
STOREVALUE(instr.result, l->globalGetter(l, context));
MOTH_END_INSTR(GetGlobalLookup)
MOTH_BEGIN_INSTR(StoreName)
TRACE(inline, "property name = %s", runtimeStrings[instr.name]->toQString().toUtf8().constData());
Runtime::setActivationProperty(context, runtimeStrings[instr.name], VALUEPTR(instr.source));
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreName)
MOTH_BEGIN_INSTR(LoadElement)
STOREVALUE(instr.result, Runtime::getElement(context, VALUEPTR(instr.base), VALUEPTR(instr.index)));
MOTH_END_INSTR(LoadElement)
MOTH_BEGIN_INSTR(LoadElementLookup)
QV4::Lookup *l = context->d()->lookups + instr.lookup;
STOREVALUE(instr.result, l->indexedGetter(l, VALUEPTR(instr.base), VALUEPTR(instr.index)));
MOTH_END_INSTR(LoadElementLookup)
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
MOTH_BEGIN_INSTR(StoreElement)
Runtime::setElement(context, VALUEPTR(instr.base), VALUEPTR(instr.index), VALUEPTR(instr.source));
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreElement)
MOTH_BEGIN_INSTR(StoreElementLookup)
QV4::Lookup *l = context->d()->lookups + instr.lookup;
l->indexedSetter(l, VALUEPTR(instr.base), VALUEPTR(instr.index), VALUEPTR(instr.source));
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreElementLookup)
MOTH_BEGIN_INSTR(LoadProperty)
STOREVALUE(instr.result, Runtime::getProperty(context, VALUEPTR(instr.base), runtimeStrings[instr.name]));
MOTH_END_INSTR(LoadProperty)
MOTH_BEGIN_INSTR(GetLookup)
QV4::Lookup *l = context->d()->lookups + instr.index;
STOREVALUE(instr.result, l->getter(l, VALUEPTR(instr.base)));
MOTH_END_INSTR(GetLookup)
MOTH_BEGIN_INSTR(StoreProperty)
Runtime::setProperty(context, VALUEPTR(instr.base), runtimeStrings[instr.name], VALUEPTR(instr.source));
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreProperty)
MOTH_BEGIN_INSTR(SetLookup)
QV4::Lookup *l = context->d()->lookups + instr.index;
l->setter(l, VALUEPTR(instr.base), VALUEPTR(instr.source));
CHECK_EXCEPTION;
MOTH_END_INSTR(SetLookup)
MOTH_BEGIN_INSTR(StoreQObjectProperty)
Runtime::setQmlQObjectProperty(context, VALUEPTR(instr.base), instr.propertyIndex, VALUEPTR(instr.source));
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreQObjectProperty)
MOTH_BEGIN_INSTR(LoadQObjectProperty)
STOREVALUE(instr.result, Runtime::getQmlQObjectProperty(context, VALUEPTR(instr.base), instr.propertyIndex, instr.captureRequired));
MOTH_END_INSTR(LoadQObjectProperty)
MOTH_BEGIN_INSTR(LoadAttachedQObjectProperty)
STOREVALUE(instr.result, Runtime::getQmlAttachedProperty(context, instr.attachedPropertiesId, instr.propertyIndex));
MOTH_END_INSTR(LoadAttachedQObjectProperty)
MOTH_BEGIN_INSTR(LoadSingletonQObjectProperty)
STOREVALUE(instr.result, Runtime::getQmlSingletonQObjectProperty(context, VALUEPTR(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 = context->engine()->stackPush(stackSize);
#ifndef QT_NO_DEBUG
memset(stack, 0, stackSize * sizeof(QV4::Value));
#endif
scopes[1] = 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;
}
}
}
#endif // DO_TRACE_INSTR
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = QV4::Primitive::undefinedValue();
STOREVALUE(instr.result, Runtime::callValue(context, VALUEPTR(instr.dest), callData));
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(context)->toQString().toUtf8().constData());
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = VALUE(instr.base);
STOREVALUE(instr.result, Runtime::callProperty(context, runtimeStrings[instr.name], callData));
MOTH_END_INSTR(CallProperty)
MOTH_BEGIN_INSTR(CallPropertyLookup)
TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = VALUE(instr.base);
STOREVALUE(instr.result, Runtime::callPropertyLookup(context, instr.lookupIndex, callData));
MOTH_END_INSTR(CallPropertyLookup)
MOTH_BEGIN_INSTR(CallElement)
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = VALUE(instr.base);
STOREVALUE(instr.result, Runtime::callElement(context, VALUEPTR(instr.index), callData));
MOTH_END_INSTR(CallElement)
MOTH_BEGIN_INSTR(CallActivationProperty)
TRACE(args, "starting at %d, length %d", instr.args, instr.argc);
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = QV4::Primitive::undefinedValue();
STOREVALUE(instr.result, Runtime::callActivationProperty(context, runtimeStrings[instr.name], callData));
MOTH_END_INSTR(CallActivationProperty)
MOTH_BEGIN_INSTR(CallGlobalLookup)
TRACE(args, "starting at %d, length %d", instr.args, instr.argc);
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = QV4::Primitive::undefinedValue();
STOREVALUE(instr.result, Runtime::callGlobalLookup(context, instr.index, callData));
MOTH_END_INSTR(CallGlobalLookup)
MOTH_BEGIN_INSTR(SetExceptionHandler)
exceptionHandler = instr.offset ? ((uchar *)&instr.offset) + instr.offset : 0;
MOTH_END_INSTR(SetExceptionHandler)
MOTH_BEGIN_INSTR(CallBuiltinThrow)
Runtime::throwException(context, VALUEPTR(instr.arg));
CHECK_EXCEPTION;
MOTH_END_INSTR(CallBuiltinThrow)
MOTH_BEGIN_INSTR(CallBuiltinUnwindException)
STOREVALUE(instr.result, Runtime::unwindException(context));
MOTH_END_INSTR(CallBuiltinUnwindException)
MOTH_BEGIN_INSTR(CallBuiltinPushCatchScope)
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
context = Runtime::pushCatchScope(context, runtimeStrings[instr.name]);
MOTH_END_INSTR(CallBuiltinPushCatchScope)
MOTH_BEGIN_INSTR(CallBuiltinPushScope)
context = Runtime::pushWithScope(VALUEPTR(instr.arg), context);
MOTH_END_INSTR(CallBuiltinPushScope)
MOTH_BEGIN_INSTR(CallBuiltinPopScope)
context = Runtime::popScope(context);
MOTH_END_INSTR(CallBuiltinPopScope)
MOTH_BEGIN_INSTR(CallBuiltinForeachIteratorObject)
STOREVALUE(instr.result, Runtime::foreachIterator(context, VALUEPTR(instr.arg)));
MOTH_END_INSTR(CallBuiltinForeachIteratorObject)
MOTH_BEGIN_INSTR(CallBuiltinForeachNextPropertyName)
STOREVALUE(instr.result, Runtime::foreachNextPropertyName(VALUEPTR(instr.arg)));
MOTH_END_INSTR(CallBuiltinForeachNextPropertyName)
MOTH_BEGIN_INSTR(CallBuiltinDeleteMember)
STOREVALUE(instr.result, Runtime::deleteMember(context, VALUEPTR(instr.base), runtimeStrings[instr.member]));
MOTH_END_INSTR(CallBuiltinDeleteMember)
MOTH_BEGIN_INSTR(CallBuiltinDeleteSubscript)
STOREVALUE(instr.result, Runtime::deleteElement(context, VALUEPTR(instr.base), VALUEPTR(instr.index)));
MOTH_END_INSTR(CallBuiltinDeleteSubscript)
MOTH_BEGIN_INSTR(CallBuiltinDeleteName)
STOREVALUE(instr.result, Runtime::deleteName(context, runtimeStrings[instr.name]));
MOTH_END_INSTR(CallBuiltinDeleteName)
MOTH_BEGIN_INSTR(CallBuiltinTypeofMember)
STOREVALUE(instr.result, Runtime::typeofMember(context, VALUEPTR(instr.base), runtimeStrings[instr.member]));
MOTH_END_INSTR(CallBuiltinTypeofMember)
MOTH_BEGIN_INSTR(CallBuiltinTypeofSubscript)
STOREVALUE(instr.result, Runtime::typeofElement(context, VALUEPTR(instr.base), VALUEPTR(instr.index)));
MOTH_END_INSTR(CallBuiltinTypeofSubscript)
MOTH_BEGIN_INSTR(CallBuiltinTypeofName)
STOREVALUE(instr.result, Runtime::typeofName(context, runtimeStrings[instr.name]));
MOTH_END_INSTR(CallBuiltinTypeofName)
MOTH_BEGIN_INSTR(CallBuiltinTypeofValue)
STOREVALUE(instr.result, Runtime::typeofValue(context, VALUEPTR(instr.value)));
MOTH_END_INSTR(CallBuiltinTypeofValue)
MOTH_BEGIN_INSTR(CallBuiltinDeclareVar)
Runtime::declareVar(context, instr.isDeletable, runtimeStrings[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::arrayLiteral(context, args, instr.argc));
MOTH_END_INSTR(CallBuiltinDefineArray)
MOTH_BEGIN_INSTR(CallBuiltinDefineObjectLiteral)
QV4::Value *args = stack + instr.args;
STOREVALUE(instr.result, Runtime::objectLiteral(context, args, instr.internalClassId, instr.arrayValueCount, instr.arrayGetterSetterCountAndFlags));
MOTH_END_INSTR(CallBuiltinDefineObjectLiteral)
MOTH_BEGIN_INSTR(CallBuiltinSetupArgumentsObject)
STOREVALUE(instr.result, Runtime::setupArgumentsObject(context));
MOTH_END_INSTR(CallBuiltinSetupArgumentsObject)
MOTH_BEGIN_INSTR(CallBuiltinConvertThisToObject)
Runtime::convertThisToObject(context);
CHECK_EXCEPTION;
MOTH_END_INSTR(CallBuiltinConvertThisToObject)
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
MOTH_BEGIN_INSTR(CreateValue)
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = QV4::Primitive::undefinedValue();
STOREVALUE(instr.result, Runtime::constructValue(context, VALUEPTR(instr.func), callData));
MOTH_END_INSTR(CreateValue)
MOTH_BEGIN_INSTR(CreateProperty)
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = VALUE(instr.base);
STOREVALUE(instr.result, Runtime::constructProperty(context, runtimeStrings[instr.name], callData));
MOTH_END_INSTR(CreateProperty)
MOTH_BEGIN_INSTR(ConstructPropertyLookup)
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = VALUE(instr.base);
STOREVALUE(instr.result, Runtime::constructPropertyLookup(context, instr.index, callData));
MOTH_END_INSTR(ConstructPropertyLookup)
MOTH_BEGIN_INSTR(CreateActivationProperty)
TRACE(inline, "property name = %s, args = %d, argc = %d", runtimeStrings[instr.name]->toQString().toUtf8().constData(), instr.args, instr.argc);
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = QV4::Primitive::undefinedValue();
STOREVALUE(instr.result, Runtime::constructActivationProperty(context, runtimeStrings[instr.name], callData));
MOTH_END_INSTR(CreateActivationProperty)
MOTH_BEGIN_INSTR(ConstructGlobalLookup)
TRACE(inline, "property name = %s, args = %d, argc = %d", runtimeStrings[instr.name]->toQString().toUtf8().constData(), instr.args, instr.argc);
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = QV4::Primitive::undefinedValue();
STOREVALUE(instr.result, Runtime::constructGlobalLookup(context, instr.index, callData));
MOTH_END_INSTR(ConstructGlobalLookup)
MOTH_BEGIN_INSTR(Jump)
code = ((uchar *)&instr.offset) + instr.offset;
MOTH_END_INSTR(Jump)
MOTH_BEGIN_INSTR(JumpEq)
bool cond = VALUEPTR(instr.condition)->toBoolean();
TRACE(condition, "%s", cond ? "TRUE" : "FALSE");
if (cond)
code = ((uchar *)&instr.offset) + instr.offset;
MOTH_END_INSTR(JumpEq)
MOTH_BEGIN_INSTR(JumpNe)
bool cond = VALUEPTR(instr.condition)->toBoolean();
TRACE(condition, "%s", cond ? "TRUE" : "FALSE");
if (!cond)
code = ((uchar *)&instr.offset) + instr.offset;
MOTH_END_INSTR(JumpNe)
MOTH_BEGIN_INSTR(UNot)
STOREVALUE(instr.result, Runtime::uNot(VALUEPTR(instr.source)));
MOTH_END_INSTR(UNot)
561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
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::uPlus(VALUEPTR(instr.source)));
MOTH_END_INSTR(UPlus)
MOTH_BEGIN_INSTR(UMinus)
STOREVALUE(instr.result, Runtime::uMinus(VALUEPTR(instr.source)));
MOTH_END_INSTR(UMinus)
MOTH_BEGIN_INSTR(UCompl)
STOREVALUE(instr.result, Runtime::complement(VALUEPTR(instr.source)));
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::increment(VALUEPTR(instr.source)));
MOTH_END_INSTR(Increment)
MOTH_BEGIN_INSTR(Decrement)
STOREVALUE(instr.result, Runtime::decrement(VALUEPTR(instr.source)));
MOTH_END_INSTR(Decrement)
MOTH_BEGIN_INSTR(Binop)
STOREVALUE(instr.result, instr.alu(VALUEPTR(instr.lhs), VALUEPTR(instr.rhs)));
MOTH_END_INSTR(Binop)
MOTH_BEGIN_INSTR(Add)
STOREVALUE(instr.result, Runtime::add(context, VALUEPTR(instr.lhs), VALUEPTR(instr.rhs)));
MOTH_END_INSTR(Add)
MOTH_BEGIN_INSTR(BitAnd)
STOREVALUE(instr.result, Runtime::bitAnd(VALUEPTR(instr.lhs), VALUEPTR(instr.rhs)));
MOTH_END_INSTR(BitAnd)
MOTH_BEGIN_INSTR(BitOr)
STOREVALUE(instr.result, Runtime::bitOr(VALUEPTR(instr.lhs), VALUEPTR(instr.rhs)));
MOTH_END_INSTR(BitOr)
MOTH_BEGIN_INSTR(BitXor)
STOREVALUE(instr.result, Runtime::bitXor(VALUEPTR(instr.lhs), VALUEPTR(instr.rhs)));
MOTH_END_INSTR(BitXor)
MOTH_BEGIN_INSTR(Shr)
STOREVALUE(instr.result, QV4::Encode((int)(VALUEPTR(instr.lhs)->toInt32() >> (VALUEPTR(instr.rhs)->toInt32() & 0x1f))));
MOTH_END_INSTR(Shr)
MOTH_BEGIN_INSTR(Shl)
STOREVALUE(instr.result, QV4::Encode((int)(VALUEPTR(instr.lhs)->toInt32() << (VALUEPTR(instr.rhs)->toInt32() & 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)
MOTH_BEGIN_INSTR(BitOrConst)
int lhs = VALUEPTR(instr.lhs)->toInt32();
STOREVALUE(instr.result, QV4::Encode((int)(lhs | instr.rhs)));
MOTH_END_INSTR(BitOr)
MOTH_BEGIN_INSTR(BitXorConst)
int lhs = VALUEPTR(instr.lhs)->toInt32();
STOREVALUE(instr.result, QV4::Encode((int)(lhs ^ instr.rhs)));
631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
MOTH_END_INSTR(BitXor)
MOTH_BEGIN_INSTR(ShrConst)
STOREVALUE(instr.result, QV4::Encode((int)(VALUEPTR(instr.lhs)->toInt32() >> instr.rhs)));
MOTH_END_INSTR(ShrConst)
MOTH_BEGIN_INSTR(ShlConst)
STOREVALUE(instr.result, QV4::Encode((int)(VALUEPTR(instr.lhs)->toInt32() << instr.rhs)));
MOTH_END_INSTR(ShlConst)
MOTH_BEGIN_INSTR(Mul)
STOREVALUE(instr.result, Runtime::mul(VALUEPTR(instr.lhs), VALUEPTR(instr.rhs)));
MOTH_END_INSTR(Mul)
MOTH_BEGIN_INSTR(Sub)
STOREVALUE(instr.result, Runtime::sub(VALUEPTR(instr.lhs), VALUEPTR(instr.rhs)));
MOTH_END_INSTR(Sub)
MOTH_BEGIN_INSTR(BinopContext)
STOREVALUE(instr.result, instr.alu(context, VALUEPTR(instr.lhs), VALUEPTR(instr.rhs)));
MOTH_END_INSTR(BinopContext)
MOTH_BEGIN_INSTR(Ret)
context->engine()->stackPop(stackSize);
// TRACE(Ret, "returning value %s", result.toString(context)->toQString().toUtf8().constData());
return VALUE(instr.result).asReturnedValue();
MOTH_END_INSTR(Ret)
MOTH_BEGIN_INSTR(Debug)
context->d()->lineNumber = instr.lineNumber;
QV4::Debugging::Debugger *debugger = context->engine()->debugger;
if (debugger && debugger->pauseAtNextOpportunity())
debugger->maybeBreakAtInstruction();
MOTH_END_INSTR(Debug)
MOTH_BEGIN_INSTR(Line)
context->d()->lineNumber = instr.lineNumber;
MOTH_END_INSTR(Debug)
MOTH_BEGIN_INSTR(LoadThis)
VALUE(instr.result) = context->d()->callData->thisObject;
MOTH_END_INSTR(LoadThis)
MOTH_BEGIN_INSTR(LoadQmlIdArray)
VALUE(instr.result) = Runtime::getQmlIdArray(static_cast<QV4::NoThrowContext*>(context));
MOTH_END_INSTR(LoadQmlIdArray)
MOTH_BEGIN_INSTR(LoadQmlImportedScripts)
VALUE(instr.result) = Runtime::getQmlImportedScripts(static_cast<QV4::NoThrowContext*>(context));
MOTH_END_INSTR(LoadQmlImportedScripts)
MOTH_BEGIN_INSTR(LoadQmlContextObject)
VALUE(instr.result) = Runtime::getQmlContextObject(static_cast<QV4::NoThrowContext*>(context));
MOTH_END_INSTR(LoadContextObject)
MOTH_BEGIN_INSTR(LoadQmlScopeObject)
VALUE(instr.result) = Runtime::getQmlScopeObject(static_cast<QV4::NoThrowContext*>(context));
MOTH_END_INSTR(LoadScopeObject)
MOTH_BEGIN_INSTR(LoadQmlSingleton)
VALUE(instr.result) = Runtime::getQmlSingleton(static_cast<QV4::NoThrowContext*>(context), runtimeStrings[instr.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;
}
701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739
#endif
Q_ASSERT(false);
catchException:
Q_ASSERT(context->engine()->hasException);
if (!exceptionHandler) {
context->engine()->stackPop(stackSize);
return QV4::Encode::undefined();
}
code = exceptionHandler;
}
}
#ifdef MOTH_THREADED_INTERPRETER
void **VME::instructionJumpTable()
{
static void **jumpTable = 0;
if (!jumpTable) {
const uchar *code = 0;
VME().run(0, code, &jumpTable);
}
return jumpTable;
}
#endif
QV4::ReturnedValue VME::exec(QV4::ExecutionContext *ctxt, const uchar *code)
{
VME vme;
QV4::Debugging::Debugger *debugger = ctxt->engine()->debugger;
if (debugger)
debugger->enteringFunction();
QV4::ReturnedValue retVal = vme.run(ctxt, code);
if (debugger)
debugger->leavingFunction(retVal);
return retVal;
}