2013-06-24 10:07:48 +00:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
2016-01-19 09:38:36 +00:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2013-06-24 10:07:48 +00:00
|
|
|
**
|
2013-06-24 11:50:51 +00:00
|
|
|
** This file is part of the QtQml module of the Qt Toolkit.
|
2013-06-24 10:07:48 +00:00
|
|
|
**
|
2016-01-19 09:38:36 +00:00
|
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
2013-06-24 10:07:48 +00:00
|
|
|
** 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
|
2015-01-28 11:55:39 +00:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
2016-01-19 09:38:36 +00:00
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2013-06-24 10:07:48 +00:00
|
|
|
**
|
|
|
|
** GNU Lesser General Public License Usage
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
2016-01-19 09:38:36 +00:00
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
|
|
|
** packaging of this file. Please review the following information to
|
|
|
|
** ensure the GNU Lesser General Public License version 3 requirements
|
|
|
|
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
2013-06-24 10:07:48 +00:00
|
|
|
**
|
2016-01-19 09:38:36 +00:00
|
|
|
** GNU General Public License Usage
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
** General Public License version 2.0 or (at your option) the GNU General
|
|
|
|
** Public license version 3 or any later version approved by the KDE Free
|
|
|
|
** Qt Foundation. The licenses are as published by the Free Software
|
|
|
|
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
|
|
|
** https://www.gnu.org/licenses/gpl-3.0.html.
|
2013-06-24 10:07:48 +00:00
|
|
|
**
|
|
|
|
** $QT_END_LICENSE$
|
|
|
|
**
|
|
|
|
****************************************************************************/
|
|
|
|
|
2012-06-11 16:58:52 +00:00
|
|
|
#include "qv4vme_moth_p.h"
|
|
|
|
#include "qv4instr_moth_p.h"
|
2014-12-11 18:14:30 +00:00
|
|
|
|
|
|
|
#include <QtCore/qjsondocument.h>
|
|
|
|
#include <QtCore/qjsonobject.h>
|
|
|
|
|
2015-02-14 21:46:41 +00:00
|
|
|
#include <private/qv4value_p.h>
|
2013-04-15 09:50:16 +00:00
|
|
|
#include <private/qv4debugging_p.h>
|
2014-12-11 18:14:30 +00:00
|
|
|
#include <private/qv4function_p.h>
|
|
|
|
#include <private/qv4functionobject_p.h>
|
2013-08-05 13:55:45 +00:00
|
|
|
#include <private/qv4math_p.h>
|
2013-09-05 12:49:55 +00:00
|
|
|
#include <private/qv4scopedvalue_p.h>
|
2013-10-10 09:51:42 +00:00
|
|
|
#include <private/qv4lookup_p.h>
|
2015-02-14 21:46:41 +00:00
|
|
|
#include <private/qv4string_p.h>
|
2012-11-29 13:41:26 +00:00
|
|
|
#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
|
|
|
|
2014-12-16 12:44:14 +00:00
|
|
|
#undef DO_TRACE_INSTR // define to enable instruction tracing
|
|
|
|
|
2012-10-23 14:06:52 +00:00
|
|
|
#ifdef DO_TRACE_INSTR
|
2014-12-16 12:44:14 +00:00
|
|
|
# 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); }
|
2012-10-23 14:06:52 +00:00
|
|
|
#else
|
|
|
|
# define TRACE_INSTR(I)
|
|
|
|
# define TRACE(n, str, ...)
|
|
|
|
#endif // DO_TRACE_INSTR
|
|
|
|
|
2014-12-11 18:14:30 +00:00
|
|
|
extern "C" {
|
|
|
|
|
|
|
|
// This is the interface to Qt Creator's (new) QML debugger.
|
|
|
|
|
|
|
|
/*! \internal
|
|
|
|
\since 5.5
|
|
|
|
|
|
|
|
This function is called uncondionally from VME::run().
|
|
|
|
|
|
|
|
An attached debugger can set a breakpoint here to
|
|
|
|
intercept calls to VME::run().
|
|
|
|
*/
|
|
|
|
|
|
|
|
Q_QML_EXPORT void qt_v4ResolvePendingBreakpointsHook()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \internal
|
|
|
|
\since 5.5
|
|
|
|
|
|
|
|
This function is called when a QML interpreter breakpoint
|
|
|
|
is hit.
|
|
|
|
|
|
|
|
An attached debugger can set a breakpoint here.
|
|
|
|
*/
|
|
|
|
Q_QML_EXPORT void qt_v4TriggeredBreakpointHook()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \internal
|
|
|
|
\since 5.5
|
|
|
|
|
|
|
|
The main entry point into "Native Mixed" Debugging.
|
|
|
|
|
|
|
|
Commands are passed as UTF-8 encoded JSON data.
|
|
|
|
The data has two compulsory fields:
|
|
|
|
\list
|
|
|
|
\li \c version: Version of the protocol (currently 1)
|
|
|
|
\li \c command: Name of the command
|
|
|
|
\endlist
|
|
|
|
|
|
|
|
Depending on \c command, more fields can be present.
|
|
|
|
|
|
|
|
Error is indicated by negative return values,
|
|
|
|
success by non-negative return values.
|
|
|
|
|
|
|
|
\c protocolVersion:
|
|
|
|
Returns version of implemented protocol.
|
|
|
|
|
|
|
|
\c insertBreakpoint:
|
|
|
|
Sets a breakpoint on a given file and line.
|
|
|
|
\list
|
|
|
|
\li \c fullName: Name of the QML/JS file
|
|
|
|
\li \c lineNumber: Line number in the file
|
|
|
|
\li \c condition: Breakpoint condition
|
|
|
|
\endlist
|
|
|
|
Returns a unique positive number as handle.
|
|
|
|
|
|
|
|
\c removeBreakpoint:
|
|
|
|
Removes a breakpoint from a given file and line.
|
|
|
|
\list
|
|
|
|
\li \c fullName: Name of the QML/JS file
|
|
|
|
\li \c lineNumber: Line number in the file
|
|
|
|
\li \c condition: Breakpoint condition
|
|
|
|
\endlist
|
|
|
|
Returns zero on success, a negative number on failure.
|
|
|
|
|
|
|
|
\c prepareStep:
|
|
|
|
Puts the interpreter in stepping mode.
|
|
|
|
Returns zero.
|
|
|
|
|
|
|
|
*/
|
|
|
|
Q_QML_EXPORT int qt_v4DebuggerHook(const char *json);
|
|
|
|
|
|
|
|
|
|
|
|
} // extern "C"
|
|
|
|
|
2016-07-25 13:58:04 +00:00
|
|
|
#ifndef QT_NO_QML_DEBUGGER
|
2014-12-11 18:14:30 +00:00
|
|
|
static int qt_v4BreakpointCount = 0;
|
|
|
|
static bool qt_v4IsDebugging = true;
|
|
|
|
static bool qt_v4IsStepping = false;
|
|
|
|
|
|
|
|
class Breakpoint
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Breakpoint() : bpNumber(0), lineNumber(-1) {}
|
|
|
|
|
|
|
|
bool matches(const QString &file, int line) const
|
|
|
|
{
|
|
|
|
return fullName == file && lineNumber == line;
|
|
|
|
}
|
|
|
|
|
|
|
|
int bpNumber;
|
|
|
|
int lineNumber;
|
|
|
|
QString fullName; // e.g. /opt/project/main.qml
|
|
|
|
QString engineName; // e.g. qrc:/main.qml
|
|
|
|
QString condition; // optional
|
|
|
|
};
|
|
|
|
|
|
|
|
static QVector<Breakpoint> qt_v4Breakpoints;
|
|
|
|
static Breakpoint qt_v4LastStop;
|
|
|
|
|
|
|
|
static QV4::Function *qt_v4ExtractFunction(QV4::ExecutionContext *context)
|
|
|
|
{
|
2016-11-30 15:20:32 +00:00
|
|
|
if (QV4::Function *function = context->getFunction())
|
|
|
|
return function;
|
2014-12-11 18:14:30 +00:00
|
|
|
else
|
|
|
|
return context->d()->engine->globalCode;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void qt_v4TriggerBreakpoint(const Breakpoint &bp, QV4::Function *function)
|
|
|
|
{
|
|
|
|
qt_v4LastStop = bp;
|
|
|
|
|
|
|
|
// Set up some auxiliary data for informational purpose.
|
|
|
|
// This is not part of the protocol.
|
|
|
|
QV4::Heap::String *functionName = function->name();
|
|
|
|
QByteArray functionNameUtf8;
|
|
|
|
if (functionName)
|
|
|
|
functionNameUtf8 = functionName->toQString().toUtf8();
|
|
|
|
|
|
|
|
qt_v4TriggeredBreakpointHook(); // Trigger Breakpoint.
|
|
|
|
}
|
|
|
|
|
|
|
|
int qt_v4DebuggerHook(const char *json)
|
|
|
|
{
|
|
|
|
const int ProtocolVersion = 1;
|
|
|
|
|
|
|
|
enum {
|
|
|
|
Success = 0,
|
|
|
|
WrongProtocol,
|
|
|
|
NoSuchCommand,
|
|
|
|
NoSuchBreakpoint
|
|
|
|
};
|
|
|
|
|
|
|
|
QJsonDocument doc = QJsonDocument::fromJson(json);
|
|
|
|
QJsonObject ob = doc.object();
|
2016-06-07 14:15:07 +00:00
|
|
|
QByteArray command = ob.value(QLatin1String("command")).toString().toUtf8();
|
2014-12-11 18:14:30 +00:00
|
|
|
|
|
|
|
if (command == "protocolVersion") {
|
|
|
|
return ProtocolVersion; // Version number.
|
|
|
|
}
|
|
|
|
|
|
|
|
int version = ob.value(QLatin1Literal("version")).toString().toInt();
|
|
|
|
if (version != ProtocolVersion) {
|
|
|
|
return -WrongProtocol;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (command == "insertBreakpoint") {
|
|
|
|
Breakpoint bp;
|
|
|
|
bp.bpNumber = ++qt_v4BreakpointCount;
|
2016-06-07 14:15:07 +00:00
|
|
|
bp.lineNumber = ob.value(QLatin1String("lineNumber")).toString().toInt();
|
|
|
|
bp.engineName = ob.value(QLatin1String("engineName")).toString();
|
|
|
|
bp.fullName = ob.value(QLatin1String("fullName")).toString();
|
|
|
|
bp.condition = ob.value(QLatin1String("condition")).toString();
|
2014-12-11 18:14:30 +00:00
|
|
|
qt_v4Breakpoints.append(bp);
|
|
|
|
return bp.bpNumber;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (command == "removeBreakpoint") {
|
2016-06-07 14:15:07 +00:00
|
|
|
int lineNumber = ob.value(QLatin1String("lineNumber")).toString().toInt();
|
|
|
|
QString fullName = ob.value(QLatin1String("fullName")).toString();
|
2014-12-11 18:14:30 +00:00
|
|
|
if (qt_v4Breakpoints.last().matches(fullName, lineNumber)) {
|
|
|
|
qt_v4Breakpoints.removeLast();
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
for (int i = 0; i + 1 < qt_v4Breakpoints.size(); ++i) {
|
|
|
|
if (qt_v4Breakpoints.at(i).matches(fullName, lineNumber)) {
|
|
|
|
qt_v4Breakpoints[i] = qt_v4Breakpoints.takeLast();
|
|
|
|
return Success; // Ok.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -NoSuchBreakpoint; // Failure
|
|
|
|
}
|
|
|
|
|
|
|
|
if (command == "prepareStep") {
|
|
|
|
qt_v4IsStepping = true;
|
|
|
|
return Success; // Ok.
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return -NoSuchCommand; // Failure.
|
|
|
|
}
|
|
|
|
|
|
|
|
static void qt_v4CheckForBreak(QV4::ExecutionContext *context, QV4::Value **scopes, int scopeDepth)
|
|
|
|
{
|
|
|
|
Q_UNUSED(scopes);
|
|
|
|
Q_UNUSED(scopeDepth);
|
|
|
|
const int lineNumber = context->d()->lineNumber;
|
|
|
|
QV4::Function *function = qt_v4ExtractFunction(context);
|
|
|
|
QString engineName = function->sourceFile();
|
|
|
|
|
|
|
|
if (engineName.isEmpty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (qt_v4IsStepping) {
|
|
|
|
if (qt_v4LastStop.lineNumber != lineNumber
|
|
|
|
|| qt_v4LastStop.engineName != engineName) {
|
|
|
|
qt_v4IsStepping = false;
|
|
|
|
Breakpoint bp;
|
|
|
|
bp.bpNumber = 0;
|
|
|
|
bp.lineNumber = lineNumber;
|
|
|
|
bp.engineName = engineName;
|
|
|
|
qt_v4TriggerBreakpoint(bp, function);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = qt_v4Breakpoints.size(); --i >= 0; ) {
|
|
|
|
const Breakpoint &bp = qt_v4Breakpoints.at(i);
|
|
|
|
if (bp.lineNumber != lineNumber)
|
|
|
|
continue;
|
|
|
|
if (bp.engineName != engineName)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
qt_v4TriggerBreakpoint(bp, function);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-25 13:58:04 +00:00
|
|
|
#endif // QT_NO_QML_DEBUGGER
|
2014-12-11 18:14:30 +00:00
|
|
|
// End of debugger interface
|
|
|
|
|
2014-02-14 12:58:40 +00:00
|
|
|
using namespace QV4;
|
|
|
|
using namespace QV4::Moth;
|
2012-11-06 11:31:02 +00:00
|
|
|
|
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_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_END_INSTR(I) } \
|
2013-10-28 15:04:07 +00:00
|
|
|
continue;
|
2012-06-11 16:58:52 +00:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2012-11-13 11:25:23 +00:00
|
|
|
#ifdef DO_TRACE_INSTR
|
2013-10-29 09:28:04 +00:00
|
|
|
Param traceParam(const Param ¶m)
|
|
|
|
{
|
|
|
|
if (param.isConstant()) {
|
2014-12-16 12:44:14 +00:00
|
|
|
qDebug(" constant\n");
|
2013-01-25 18:32:30 +00:00
|
|
|
} else if (param.isArgument()) {
|
2014-12-16 12:44:14 +00:00
|
|
|
qDebug(" argument %d@%d\n", param.index, param.scope);
|
2013-01-25 18:32:30 +00:00
|
|
|
} else if (param.isLocal()) {
|
2014-12-16 12:44:14 +00:00
|
|
|
qDebug(" local %d\n", param.index);
|
2013-01-25 18:32:30 +00:00
|
|
|
} else if (param.isTemp()) {
|
2014-12-16 12:44:14 +00:00
|
|
|
qDebug(" temp %d\n", param.index);
|
2013-02-15 12:36:49 +00:00
|
|
|
} else if (param.isScopedLocal()) {
|
2014-12-16 12:44:14 +00:00
|
|
|
qDebug(" temp %d@%d\n", param.index, param.scope);
|
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
|
|
|
}
|
2014-12-16 12:44:14 +00:00
|
|
|
return param;
|
2012-06-12 17:13:55 +00:00
|
|
|
}
|
2013-06-03 11:32:51 +00:00
|
|
|
# define VALUE(param) (*VALUEPTR(param))
|
2013-10-29 09:28:04 +00:00
|
|
|
# define VALUEPTR(param) (scopes[traceParam(param).scope] + param.index)
|
2013-01-25 18:32:30 +00:00
|
|
|
#else
|
2013-10-29 09:28:04 +00:00
|
|
|
# define VALUE(param) (*VALUEPTR(param))
|
|
|
|
# define VALUEPTR(param) (scopes[param.scope] + param.index)
|
2013-01-25 18:32:30 +00:00
|
|
|
#endif
|
2013-10-29 09:28:04 +00:00
|
|
|
|
2013-10-23 12:03:09 +00:00
|
|
|
#define STOREVALUE(param, value) { \
|
|
|
|
QV4::ReturnedValue tmp = (value); \
|
2014-02-05 15:12:16 +00:00
|
|
|
if (engine->hasException) \
|
2013-10-23 12:03:09 +00:00
|
|
|
goto catchException; \
|
|
|
|
VALUE(param) = tmp; \
|
|
|
|
}
|
2017-01-05 17:48:20 +00:00
|
|
|
// qv4scopedvalue_p.h also defines a CHECK_EXCEPTION macro
|
|
|
|
#ifdef CHECK_EXCEPTION
|
|
|
|
#undef CHECK_EXCEPTION
|
|
|
|
#endif
|
2013-10-23 12:03:09 +00:00
|
|
|
#define CHECK_EXCEPTION \
|
2014-02-05 15:12:16 +00:00
|
|
|
if (engine->hasException) \
|
2013-10-23 12:03:09 +00:00
|
|
|
goto catchException
|
2012-06-12 17:13:55 +00:00
|
|
|
|
2014-11-11 15:07:54 +00:00
|
|
|
QV4::ReturnedValue VME::run(ExecutionEngine *engine, 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
|
|
|
|
2014-12-11 18:14:30 +00:00
|
|
|
qt_v4ResolvePendingBreakpointsHook();
|
|
|
|
|
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;
|
2013-09-25 10:24:36 +00:00
|
|
|
return QV4::Primitive::undefinedValue().asReturnedValue();
|
2012-06-11 16:58:52 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-02-06 12:22:36 +00:00
|
|
|
QV4::Value *stack = 0;
|
|
|
|
unsigned stackSize = 0;
|
|
|
|
|
2013-10-16 10:29:47 +00:00
|
|
|
const uchar *exceptionHandler = 0;
|
|
|
|
|
2014-12-17 20:07:05 +00:00
|
|
|
QV4::Scope scope(engine);
|
2015-08-24 14:18:11 +00:00
|
|
|
QV4::ExecutionContext *context = engine->currentContext;
|
2015-08-24 14:16:56 +00:00
|
|
|
engine->current->lineNumber = -1;
|
2013-10-16 10:29:47 +00:00
|
|
|
|
|
|
|
#ifdef DO_TRACE_INSTR
|
|
|
|
qDebug("Starting VME with context=%p and code=%p", context, code);
|
|
|
|
#endif // DO_TRACE_INSTR
|
|
|
|
|
2013-10-29 09:28:04 +00:00
|
|
|
// setup lookup scopes
|
|
|
|
int scopeDepth = 0;
|
|
|
|
{
|
2014-11-07 04:46:20 +00:00
|
|
|
QV4::Heap::ExecutionContext *scope = context->d();
|
2013-10-29 09:28:04 +00:00
|
|
|
while (scope) {
|
|
|
|
++scopeDepth;
|
2014-11-07 04:46:20 +00:00
|
|
|
scope = scope->outer;
|
2013-10-29 09:28:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-04 13:12:54 +00:00
|
|
|
Q_ALLOCA_VAR(QV4::Value*, scopes, sizeof(QV4::Value *)*(2 + 2*scopeDepth));
|
2013-10-29 09:28:04 +00:00
|
|
|
{
|
2016-07-14 18:39:58 +00:00
|
|
|
scopes[0] = const_cast<QV4::Value *>(context->d()->compilationUnit->constants);
|
2013-10-29 09:28:04 +00:00
|
|
|
// stack gets setup in push instruction
|
|
|
|
scopes[1] = 0;
|
2014-11-07 04:46:20 +00:00
|
|
|
QV4::Heap::ExecutionContext *scope = context->d();
|
2013-10-29 09:28:04 +00:00
|
|
|
int i = 0;
|
|
|
|
while (scope) {
|
2014-11-07 04:46:20 +00:00
|
|
|
if (scope->type >= QV4::Heap::ExecutionContext::Type_SimpleCallContext) {
|
|
|
|
QV4::Heap::CallContext *cc = static_cast<QV4::Heap::CallContext *>(scope);
|
|
|
|
scopes[2*i + 2] = cc->callData->args;
|
|
|
|
scopes[2*i + 3] = cc->locals;
|
2013-10-29 09:28:04 +00:00
|
|
|
} else {
|
|
|
|
scopes[2*i + 2] = 0;
|
|
|
|
scopes[2*i + 3] = 0;
|
|
|
|
}
|
|
|
|
++i;
|
2014-11-07 04:46:20 +00:00
|
|
|
scope = scope->outer;
|
2013-10-29 09:28:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-23 12:03:09 +00:00
|
|
|
|
2012-06-11 16:58:52 +00:00
|
|
|
for (;;) {
|
|
|
|
const Instr *genericInstr = reinterpret_cast<const Instr *>(code);
|
2013-10-23 12:03:09 +00:00
|
|
|
#ifdef MOTH_THREADED_INTERPRETER
|
|
|
|
goto *genericInstr->common.code;
|
|
|
|
#else
|
2012-06-11 16:58:52 +00:00
|
|
|
switch (genericInstr->common.instructionType) {
|
|
|
|
#endif
|
|
|
|
|
2013-10-29 07:17:54 +00:00
|
|
|
MOTH_BEGIN_INSTR(Move)
|
2013-01-25 18:32:30 +00:00
|
|
|
VALUE(instr.result) = VALUE(instr.source);
|
2013-10-29 07:17:54 +00:00
|
|
|
MOTH_END_INSTR(Move)
|
2012-06-12 17:13:55 +00:00
|
|
|
|
2014-02-06 12:19:27 +00:00
|
|
|
MOTH_BEGIN_INSTR(MoveConst)
|
|
|
|
VALUE(instr.result) = instr.source;
|
|
|
|
MOTH_END_INSTR(MoveConst)
|
|
|
|
|
2013-09-01 13:45:53 +00:00
|
|
|
MOTH_BEGIN_INSTR(SwapTemps)
|
|
|
|
qSwap(VALUE(instr.left), VALUE(instr.right));
|
|
|
|
MOTH_END_INSTR(MoveTemp)
|
|
|
|
|
2013-08-19 09:57:03 +00:00
|
|
|
MOTH_BEGIN_INSTR(LoadRuntimeString)
|
2013-08-16 14:35:05 +00:00
|
|
|
// TRACE(value, "%s", instr.value.toString(context)->toQString().toUtf8().constData());
|
2014-11-12 15:07:56 +00:00
|
|
|
VALUE(instr.result) = context->d()->compilationUnit->runtimeStrings[instr.stringId];
|
2013-08-19 09:57:03 +00:00
|
|
|
MOTH_END_INSTR(LoadRuntimeString)
|
2013-08-16 14:35:05 +00:00
|
|
|
|
2013-08-16 14:40:21 +00:00
|
|
|
MOTH_BEGIN_INSTR(LoadRegExp)
|
|
|
|
// TRACE(value, "%s", instr.value.toString(context)->toQString().toUtf8().constData());
|
2014-05-06 07:23:59 +00:00
|
|
|
VALUE(instr.result) = context->d()->compilationUnit->runtimeRegularExpressions[instr.regExpId];
|
2013-08-16 14:40:21 +00:00
|
|
|
MOTH_END_INSTR(LoadRegExp)
|
|
|
|
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_BEGIN_INSTR(LoadClosure)
|
2015-10-09 07:23:20 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.closure(engine, instr.value));
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_END_INSTR(LoadClosure)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(LoadName)
|
2013-09-15 13:46:36 +00:00
|
|
|
TRACE(inline, "property name = %s", runtimeStrings[instr.name]->toQString().toUtf8().constData());
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.getActivationProperty(engine, instr.name));
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_END_INSTR(LoadName)
|
|
|
|
|
2013-10-10 09:51:42 +00:00
|
|
|
MOTH_BEGIN_INSTR(GetGlobalLookup)
|
2014-05-06 07:23:59 +00:00
|
|
|
QV4::Lookup *l = context->d()->lookups + instr.index;
|
2014-11-11 15:07:54 +00:00
|
|
|
STOREVALUE(instr.result, l->globalGetter(l, engine));
|
2013-10-10 09:51:42 +00:00
|
|
|
MOTH_END_INSTR(GetGlobalLookup)
|
|
|
|
|
2012-10-24 11:45:43 +00:00
|
|
|
MOTH_BEGIN_INSTR(StoreName)
|
2013-09-15 13:46:36 +00:00
|
|
|
TRACE(inline, "property name = %s", runtimeStrings[instr.name]->toQString().toUtf8().constData());
|
2015-10-09 07:16:42 +00:00
|
|
|
engine->runtime.setActivationProperty(engine, instr.name, VALUE(instr.source));
|
2013-10-23 12:03:09 +00:00
|
|
|
CHECK_EXCEPTION;
|
2012-10-24 11:45:43 +00:00
|
|
|
MOTH_END_INSTR(StoreName)
|
|
|
|
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_BEGIN_INSTR(LoadElement)
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.getElement(engine, VALUE(instr.base), VALUE(instr.index)));
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_END_INSTR(LoadElement)
|
|
|
|
|
2014-01-31 13:58:14 +00:00
|
|
|
MOTH_BEGIN_INSTR(LoadElementLookup)
|
2014-05-06 07:23:59 +00:00
|
|
|
QV4::Lookup *l = context->d()->lookups + instr.lookup;
|
2015-01-15 10:36:57 +00:00
|
|
|
STOREVALUE(instr.result, l->indexedGetter(l, VALUE(instr.base), VALUE(instr.index)));
|
2014-01-31 13:58:14 +00:00
|
|
|
MOTH_END_INSTR(LoadElementLookup)
|
|
|
|
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_BEGIN_INSTR(StoreElement)
|
2015-10-09 07:16:42 +00:00
|
|
|
engine->runtime.setElement(engine, VALUE(instr.base), VALUE(instr.index), VALUE(instr.source));
|
2013-10-23 12:03:09 +00:00
|
|
|
CHECK_EXCEPTION;
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_END_INSTR(StoreElement)
|
|
|
|
|
2014-01-31 13:58:14 +00:00
|
|
|
MOTH_BEGIN_INSTR(StoreElementLookup)
|
2014-05-06 07:23:59 +00:00
|
|
|
QV4::Lookup *l = context->d()->lookups + instr.lookup;
|
2015-01-15 10:36:57 +00:00
|
|
|
l->indexedSetter(l, VALUE(instr.base), VALUE(instr.index), VALUE(instr.source));
|
2014-01-31 13:58:14 +00:00
|
|
|
CHECK_EXCEPTION;
|
|
|
|
MOTH_END_INSTR(StoreElementLookup)
|
|
|
|
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_BEGIN_INSTR(LoadProperty)
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.getProperty(engine, VALUE(instr.base), instr.name));
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_END_INSTR(LoadProperty)
|
|
|
|
|
2013-10-10 09:51:42 +00:00
|
|
|
MOTH_BEGIN_INSTR(GetLookup)
|
2014-05-06 07:23:59 +00:00
|
|
|
QV4::Lookup *l = context->d()->lookups + instr.index;
|
2015-01-15 10:36:57 +00:00
|
|
|
STOREVALUE(instr.result, l->getter(l, engine, VALUE(instr.base)));
|
2013-10-10 09:51:42 +00:00
|
|
|
MOTH_END_INSTR(GetLookup)
|
|
|
|
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_BEGIN_INSTR(StoreProperty)
|
2015-10-09 07:16:42 +00:00
|
|
|
engine->runtime.setProperty(engine, VALUE(instr.base), instr.name, VALUE(instr.source));
|
2013-10-23 12:03:09 +00:00
|
|
|
CHECK_EXCEPTION;
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_END_INSTR(StoreProperty)
|
|
|
|
|
2013-10-10 09:51:42 +00:00
|
|
|
MOTH_BEGIN_INSTR(SetLookup)
|
2014-05-06 07:23:59 +00:00
|
|
|
QV4::Lookup *l = context->d()->lookups + instr.index;
|
2015-01-15 10:36:57 +00:00
|
|
|
l->setter(l, engine, VALUE(instr.base), VALUE(instr.source));
|
2013-10-10 09:51:42 +00:00
|
|
|
CHECK_EXCEPTION;
|
|
|
|
MOTH_END_INSTR(SetLookup)
|
|
|
|
|
2013-10-28 14:18:31 +00:00
|
|
|
MOTH_BEGIN_INSTR(StoreQObjectProperty)
|
2015-10-09 07:30:12 +00:00
|
|
|
engine->runtime.setQmlQObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source));
|
2013-10-28 14:18:31 +00:00
|
|
|
CHECK_EXCEPTION;
|
|
|
|
MOTH_END_INSTR(StoreQObjectProperty)
|
|
|
|
|
2013-10-24 12:51:02 +00:00
|
|
|
MOTH_BEGIN_INSTR(LoadQObjectProperty)
|
2015-10-09 07:30:12 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.getQmlQObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, instr.captureRequired));
|
2013-10-24 12:51:02 +00:00
|
|
|
MOTH_END_INSTR(LoadQObjectProperty)
|
|
|
|
|
2015-06-19 12:18:13 +00:00
|
|
|
MOTH_BEGIN_INSTR(StoreScopeObjectProperty)
|
2015-10-09 07:30:12 +00:00
|
|
|
engine->runtime.setQmlScopeObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source));
|
2015-06-19 12:18:13 +00:00
|
|
|
CHECK_EXCEPTION;
|
|
|
|
MOTH_END_INSTR(StoreScopeObjectProperty)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(LoadScopeObjectProperty)
|
2016-08-26 14:11:38 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.getQmlScopeObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, instr.captureRequired));
|
2015-06-19 12:18:13 +00:00
|
|
|
MOTH_END_INSTR(LoadScopeObjectProperty)
|
|
|
|
|
2015-06-22 05:46:32 +00:00
|
|
|
MOTH_BEGIN_INSTR(StoreContextObjectProperty)
|
2015-10-09 07:30:12 +00:00
|
|
|
engine->runtime.setQmlContextObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source));
|
2015-06-22 05:46:32 +00:00
|
|
|
CHECK_EXCEPTION;
|
|
|
|
MOTH_END_INSTR(StoreContextObjectProperty)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(LoadContextObjectProperty)
|
2016-08-26 14:11:38 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.getQmlContextObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, instr.captureRequired));
|
2015-06-22 05:46:32 +00:00
|
|
|
MOTH_END_INSTR(LoadContextObjectProperty)
|
|
|
|
|
2015-06-22 14:33:40 +00:00
|
|
|
MOTH_BEGIN_INSTR(LoadIdObject)
|
2015-10-09 07:30:12 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.getQmlIdObject(engine, VALUE(instr.base), instr.index));
|
2015-06-22 14:33:40 +00:00
|
|
|
MOTH_END_INSTR(LoadIdObject)
|
|
|
|
|
2013-11-14 23:06:18 +00:00
|
|
|
MOTH_BEGIN_INSTR(LoadAttachedQObjectProperty)
|
2015-10-09 07:30:12 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.getQmlAttachedProperty(engine, instr.attachedPropertiesId, instr.propertyIndex));
|
2013-11-14 23:06:18 +00:00
|
|
|
MOTH_END_INSTR(LoadAttachedQObjectProperty)
|
|
|
|
|
2014-07-23 17:43:38 +00:00
|
|
|
MOTH_BEGIN_INSTR(LoadSingletonQObjectProperty)
|
2015-10-09 07:30:12 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.getQmlSingletonQObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, instr.captureRequired));
|
2014-07-23 17:43:38 +00:00
|
|
|
MOTH_END_INSTR(LoadSingletonQObjectProperty)
|
|
|
|
|
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;
|
2014-12-17 20:07:05 +00:00
|
|
|
stack = scope.alloc(stackSize);
|
2013-10-29 09:28:04 +00:00
|
|
|
scopes[1] = stack;
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_END_INSTR(Push)
|
|
|
|
|
2012-10-24 15:04:29 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallValue)
|
2013-09-15 13:46:36 +00:00
|
|
|
#if 0 //def DO_TRACE_INSTR
|
2014-05-06 07:23:59 +00:00
|
|
|
if (Debugging::Debugger *debugger = context->engine()->debugger) {
|
2013-04-19 11:03:42 +00:00
|
|
|
if (QV4::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
|
2014-01-24 21:55:39 +00:00
|
|
|
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
2013-09-05 12:49:55 +00:00
|
|
|
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
2016-09-23 09:34:12 +00:00
|
|
|
callData->tag = QV4::Value::Integer_Type_Internal;
|
2013-09-05 12:49:55 +00:00
|
|
|
callData->argc = instr.argc;
|
2013-09-25 10:24:36 +00:00
|
|
|
callData->thisObject = QV4::Primitive::undefinedValue();
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.callValue(engine, VALUE(instr.dest), callData));
|
2012-10-24 15:04:29 +00:00
|
|
|
MOTH_END_INSTR(CallValue)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallProperty)
|
2013-09-15 13:46:36 +00:00
|
|
|
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());
|
2014-01-24 21:55:39 +00:00
|
|
|
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
2013-09-05 12:49:55 +00:00
|
|
|
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
2016-09-23 09:34:12 +00:00
|
|
|
callData->tag = QV4::Value::Integer_Type_Internal;
|
2013-09-05 12:49:55 +00:00
|
|
|
callData->argc = instr.argc;
|
|
|
|
callData->thisObject = VALUE(instr.base);
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.callProperty(engine, instr.name, callData));
|
2012-10-24 15:04:29 +00:00
|
|
|
MOTH_END_INSTR(CallProperty)
|
2012-06-12 17:13:55 +00:00
|
|
|
|
2013-10-10 09:51:42 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallPropertyLookup)
|
2014-01-24 21:55:39 +00:00
|
|
|
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
2013-10-10 09:51:42 +00:00
|
|
|
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
2016-09-23 09:34:12 +00:00
|
|
|
callData->tag = QV4::Value::Integer_Type_Internal;
|
2013-10-10 09:51:42 +00:00
|
|
|
callData->argc = instr.argc;
|
|
|
|
callData->thisObject = VALUE(instr.base);
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.callPropertyLookup(engine, instr.lookupIndex, callData));
|
2013-10-10 09:51:42 +00:00
|
|
|
MOTH_END_INSTR(CallPropertyLookup)
|
|
|
|
|
2015-06-19 12:18:13 +00:00
|
|
|
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(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);
|
2016-09-23 09:34:12 +00:00
|
|
|
callData->tag = QV4::Value::Integer_Type_Internal;
|
2015-06-19 12:18:13 +00:00
|
|
|
callData->argc = instr.argc;
|
|
|
|
callData->thisObject = VALUE(instr.base);
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.callQmlScopeObjectProperty(engine, instr.index, callData));
|
2015-06-19 12:18:13 +00:00
|
|
|
MOTH_END_INSTR(CallScopeObjectProperty)
|
|
|
|
|
2015-06-22 05:46:32 +00:00
|
|
|
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(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);
|
2016-09-23 09:34:12 +00:00
|
|
|
callData->tag = QV4::Value::Integer_Type_Internal;
|
2015-06-22 05:46:32 +00:00
|
|
|
callData->argc = instr.argc;
|
|
|
|
callData->thisObject = VALUE(instr.base);
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.callQmlContextObjectProperty(engine, instr.index, callData));
|
2015-06-22 05:46:32 +00:00
|
|
|
MOTH_END_INSTR(CallContextObjectProperty)
|
|
|
|
|
2013-01-27 21:39:01 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallElement)
|
2014-01-24 21:55:39 +00:00
|
|
|
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
2013-09-05 12:49:55 +00:00
|
|
|
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
2016-09-23 09:34:12 +00:00
|
|
|
callData->tag = QV4::Value::Integer_Type_Internal;
|
2013-09-05 12:49:55 +00:00
|
|
|
callData->argc = instr.argc;
|
|
|
|
callData->thisObject = VALUE(instr.base);
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.callElement(engine, VALUE(instr.index), callData));
|
2013-02-15 12:36:49 +00:00
|
|
|
MOTH_END_INSTR(CallElement)
|
2013-01-27 21:39:01 +00:00
|
|
|
|
2013-01-23 12:21:09 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallActivationProperty)
|
2014-01-24 21:55:39 +00:00
|
|
|
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
2013-09-05 12:49:55 +00:00
|
|
|
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
2016-09-23 09:34:12 +00:00
|
|
|
callData->tag = QV4::Value::Integer_Type_Internal;
|
2013-09-05 12:49:55 +00:00
|
|
|
callData->argc = instr.argc;
|
2013-09-25 10:24:36 +00:00
|
|
|
callData->thisObject = QV4::Primitive::undefinedValue();
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.callActivationProperty(engine, instr.name, callData));
|
2013-01-23 12:21:09 +00:00
|
|
|
MOTH_END_INSTR(CallActivationProperty)
|
|
|
|
|
2013-10-10 09:51:42 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallGlobalLookup)
|
2014-01-24 21:55:39 +00:00
|
|
|
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
2013-10-10 09:51:42 +00:00
|
|
|
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
2016-09-23 09:34:12 +00:00
|
|
|
callData->tag = QV4::Value::Integer_Type_Internal;
|
2013-10-10 09:51:42 +00:00
|
|
|
callData->argc = instr.argc;
|
|
|
|
callData->thisObject = QV4::Primitive::undefinedValue();
|
2015-10-09 06:58:36 +00:00
|
|
|
STOREVALUE(instr.result, Runtime::method_callGlobalLookup(engine, instr.index, callData));
|
2013-10-10 09:51:42 +00:00
|
|
|
MOTH_END_INSTR(CallGlobalLookup)
|
|
|
|
|
2013-10-23 12:03:09 +00:00
|
|
|
MOTH_BEGIN_INSTR(SetExceptionHandler)
|
2015-03-07 22:35:47 +00:00
|
|
|
exceptionHandler = instr.offset ? ((const uchar *)&instr.offset) + instr.offset : 0;
|
2013-10-23 12:03:09 +00:00
|
|
|
MOTH_END_INSTR(SetExceptionHandler)
|
|
|
|
|
2013-01-27 08:59:37 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinThrow)
|
2015-10-09 07:23:20 +00:00
|
|
|
engine->runtime.throwException(engine, VALUE(instr.arg));
|
2013-10-23 12:03:09 +00:00
|
|
|
CHECK_EXCEPTION;
|
2013-01-27 08:59:37 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinThrow)
|
|
|
|
|
2013-10-23 12:03:09 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinUnwindException)
|
2015-10-09 07:23:20 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.unwindException(engine));
|
2013-10-23 12:03:09 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinUnwindException)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinPushCatchScope)
|
2015-10-09 07:23:20 +00:00
|
|
|
engine->runtime.pushCatchScope(static_cast<QV4::NoThrowEngine*>(engine), instr.name);
|
2015-08-24 14:18:11 +00:00
|
|
|
context = engine->currentContext;
|
2013-10-23 12:03:09 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinPushCatchScope)
|
|
|
|
|
2013-01-27 08:59:37 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinPushScope)
|
2016-11-23 11:55:30 +00:00
|
|
|
engine->runtime.pushWithScope(VALUE(instr.arg), static_cast<QV4::NoThrowEngine*>(engine));
|
2015-08-24 14:18:11 +00:00
|
|
|
context = engine->currentContext;
|
2014-11-27 07:56:03 +00:00
|
|
|
CHECK_EXCEPTION;
|
2013-01-27 08:59:37 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinPushScope)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinPopScope)
|
2016-11-23 11:55:30 +00:00
|
|
|
engine->runtime.popScope(static_cast<QV4::NoThrowEngine*>(engine));
|
2015-08-24 14:18:11 +00:00
|
|
|
context = engine->currentContext;
|
2013-01-27 08:59:37 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinPopScope)
|
2012-10-25 08:08:22 +00:00
|
|
|
|
2013-01-23 09:11:05 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinForeachIteratorObject)
|
2015-10-09 07:23:20 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.foreachIterator(engine, VALUE(instr.arg)));
|
2013-01-23 09:11:05 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinForeachIteratorObject)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinForeachNextPropertyName)
|
2015-10-09 07:23:20 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.foreachNextPropertyName(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)
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.deleteMember(engine, VALUE(instr.base), instr.member));
|
2012-11-12 13:31:05 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinDeleteMember)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinDeleteSubscript)
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.deleteElement(engine, VALUE(instr.base), VALUE(instr.index)));
|
2012-11-12 13:31:05 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinDeleteSubscript)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinDeleteName)
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.deleteName(engine, instr.name));
|
2012-11-12 13:31:05 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinDeleteName)
|
|
|
|
|
2015-10-27 11:21:00 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinTypeofScopeObjectProperty)
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.typeofScopeObjectProperty(engine, VALUE(instr.base), instr.index));
|
2015-10-27 11:21:00 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinTypeofMember)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinTypeofContextObjectProperty)
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.typeofContextObjectProperty(engine, VALUE(instr.base), instr.index));
|
2015-10-27 11:21:00 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinTypeofMember)
|
|
|
|
|
2012-12-18 09:59:26 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinTypeofMember)
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.typeofMember(engine, VALUE(instr.base), instr.member));
|
2012-12-18 09:59:26 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinTypeofMember)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinTypeofSubscript)
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.typeofElement(engine, VALUE(instr.base), VALUE(instr.index)));
|
2012-12-18 09:59:26 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinTypeofSubscript)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinTypeofName)
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.typeofName(engine, instr.name));
|
2012-12-18 09:59:26 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinTypeofName)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinTypeofValue)
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.typeofValue(engine, VALUE(instr.value)));
|
2012-12-18 09:59:26 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinTypeofValue)
|
|
|
|
|
2012-11-27 11:17:19 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinDeclareVar)
|
2015-10-09 07:23:20 +00:00
|
|
|
engine->runtime.declareVar(engine, 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-03-01 15:47:07 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinDefineArray)
|
2013-03-04 08:32:16 +00:00
|
|
|
Q_ASSERT(instr.args + instr.argc <= stackSize);
|
2014-01-24 21:55:39 +00:00
|
|
|
QV4::Value *args = stack + instr.args;
|
2015-10-09 07:23:20 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.arrayLiteral(engine, args, instr.argc));
|
2013-03-01 15:47:07 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinDefineArray)
|
2013-01-24 11:53:47 +00:00
|
|
|
|
2013-04-23 05:31:02 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinDefineObjectLiteral)
|
2014-01-24 21:55:39 +00:00
|
|
|
QV4::Value *args = stack + instr.args;
|
2015-10-09 07:23:20 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.objectLiteral(engine, args, instr.internalClassId, instr.arrayValueCount, instr.arrayGetterSetterCountAndFlags));
|
2013-04-23 05:31:02 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinDefineObjectLiteral)
|
|
|
|
|
2013-08-16 10:54:30 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinSetupArgumentsObject)
|
2015-10-09 07:23:20 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.setupArgumentsObject(engine));
|
2013-08-16 10:54:30 +00:00
|
|
|
MOTH_END_INSTR(CallBuiltinSetupArgumentsObject)
|
|
|
|
|
2013-11-02 20:10:13 +00:00
|
|
|
MOTH_BEGIN_INSTR(CallBuiltinConvertThisToObject)
|
2015-10-09 07:23:20 +00:00
|
|
|
engine->runtime.convertThisToObject(engine);
|
2013-11-02 20:10:13 +00:00
|
|
|
CHECK_EXCEPTION;
|
|
|
|
MOTH_END_INSTR(CallBuiltinConvertThisToObject)
|
|
|
|
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_BEGIN_INSTR(CreateValue)
|
2014-01-24 21:55:39 +00:00
|
|
|
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
2013-09-05 12:49:55 +00:00
|
|
|
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
2016-09-23 09:34:12 +00:00
|
|
|
callData->tag = QV4::Value::Integer_Type_Internal;
|
2013-09-05 12:49:55 +00:00
|
|
|
callData->argc = instr.argc;
|
2013-09-25 10:24:36 +00:00
|
|
|
callData->thisObject = QV4::Primitive::undefinedValue();
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.constructValue(engine, VALUE(instr.func), callData));
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_END_INSTR(CreateValue)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(CreateProperty)
|
2014-01-24 21:55:39 +00:00
|
|
|
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
2013-09-05 12:49:55 +00:00
|
|
|
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
2016-09-23 09:34:12 +00:00
|
|
|
callData->tag = QV4::Value::Integer_Type_Internal;
|
2013-09-05 12:49:55 +00:00
|
|
|
callData->argc = instr.argc;
|
2013-11-13 10:45:51 +00:00
|
|
|
callData->thisObject = VALUE(instr.base);
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.constructProperty(engine, instr.name, callData));
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_END_INSTR(CreateProperty)
|
|
|
|
|
2013-11-13 10:45:51 +00:00
|
|
|
MOTH_BEGIN_INSTR(ConstructPropertyLookup)
|
2014-01-24 21:55:39 +00:00
|
|
|
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
2013-11-13 10:45:51 +00:00
|
|
|
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
2016-09-23 09:34:12 +00:00
|
|
|
callData->tag = QV4::Value::Integer_Type_Internal;
|
2013-11-13 10:45:51 +00:00
|
|
|
callData->argc = instr.argc;
|
|
|
|
callData->thisObject = VALUE(instr.base);
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.constructPropertyLookup(engine, instr.index, callData));
|
2013-11-13 10:45:51 +00:00
|
|
|
MOTH_END_INSTR(ConstructPropertyLookup)
|
|
|
|
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_BEGIN_INSTR(CreateActivationProperty)
|
2014-01-24 21:55:39 +00:00
|
|
|
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
2013-09-05 12:49:55 +00:00
|
|
|
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
2016-09-23 09:34:12 +00:00
|
|
|
callData->tag = QV4::Value::Integer_Type_Internal;
|
2013-09-05 12:49:55 +00:00
|
|
|
callData->argc = instr.argc;
|
2013-09-25 10:24:36 +00:00
|
|
|
callData->thisObject = QV4::Primitive::undefinedValue();
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.constructActivationProperty(engine, instr.name, callData));
|
2012-11-06 11:54:20 +00:00
|
|
|
MOTH_END_INSTR(CreateActivationProperty)
|
|
|
|
|
2013-10-10 09:51:42 +00:00
|
|
|
MOTH_BEGIN_INSTR(ConstructGlobalLookup)
|
2014-01-24 21:55:39 +00:00
|
|
|
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
2013-10-10 09:51:42 +00:00
|
|
|
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
2016-09-23 09:34:12 +00:00
|
|
|
callData->tag = QV4::Value::Integer_Type_Internal;
|
2013-10-10 09:51:42 +00:00
|
|
|
callData->argc = instr.argc;
|
|
|
|
callData->thisObject = QV4::Primitive::undefinedValue();
|
2015-10-09 07:16:42 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.constructGlobalLookup(engine, instr.index, callData));
|
2013-10-10 09:51:42 +00:00
|
|
|
MOTH_END_INSTR(ConstructGlobalLookup)
|
|
|
|
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_BEGIN_INSTR(Jump)
|
2015-03-07 22:35:47 +00:00
|
|
|
code = ((const uchar *)&instr.offset) + instr.offset;
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_END_INSTR(Jump)
|
|
|
|
|
2014-02-06 14:05:35 +00:00
|
|
|
MOTH_BEGIN_INSTR(JumpEq)
|
|
|
|
bool cond = VALUEPTR(instr.condition)->toBoolean();
|
2013-01-25 18:32:30 +00:00
|
|
|
TRACE(condition, "%s", cond ? "TRUE" : "FALSE");
|
|
|
|
if (cond)
|
2015-03-07 22:35:47 +00:00
|
|
|
code = ((const uchar *)&instr.offset) + instr.offset;
|
2014-02-06 14:05:35 +00:00
|
|
|
MOTH_END_INSTR(JumpEq)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(JumpNe)
|
|
|
|
bool cond = VALUEPTR(instr.condition)->toBoolean();
|
|
|
|
TRACE(condition, "%s", cond ? "TRUE" : "FALSE");
|
|
|
|
if (!cond)
|
2015-03-07 22:35:47 +00:00
|
|
|
code = ((const uchar *)&instr.offset) + instr.offset;
|
2014-02-06 14:05:35 +00:00
|
|
|
MOTH_END_INSTR(JumpNe)
|
2012-06-12 17:13:55 +00:00
|
|
|
|
2013-10-29 11:53:05 +00:00
|
|
|
MOTH_BEGIN_INSTR(UNot)
|
2015-10-09 07:41:49 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.uNot(VALUE(instr.source)));
|
2013-10-29 11:53:05 +00:00
|
|
|
MOTH_END_INSTR(UNot)
|
|
|
|
|
2013-10-29 15:06:43 +00:00
|
|
|
MOTH_BEGIN_INSTR(UNotBool)
|
|
|
|
bool b = VALUE(instr.source).booleanValue();
|
|
|
|
VALUE(instr.result) = QV4::Encode(!b);
|
|
|
|
MOTH_END_INSTR(UNotBool)
|
|
|
|
|
2013-10-29 11:53:05 +00:00
|
|
|
MOTH_BEGIN_INSTR(UPlus)
|
2015-10-09 07:41:49 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.uPlus(VALUE(instr.source)));
|
2013-10-29 11:53:05 +00:00
|
|
|
MOTH_END_INSTR(UPlus)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(UMinus)
|
2015-10-09 07:41:49 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.uMinus(VALUE(instr.source)));
|
2013-10-29 11:53:05 +00:00
|
|
|
MOTH_END_INSTR(UMinus)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(UCompl)
|
2015-10-09 07:41:49 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.complement(VALUE(instr.source)));
|
2013-10-29 11:53:05 +00:00
|
|
|
MOTH_END_INSTR(UCompl)
|
|
|
|
|
2013-10-29 15:06:43 +00:00
|
|
|
MOTH_BEGIN_INSTR(UComplInt)
|
|
|
|
VALUE(instr.result) = QV4::Encode((int)~VALUE(instr.source).integerValue());
|
|
|
|
MOTH_END_INSTR(UComplInt)
|
|
|
|
|
2013-10-29 11:53:05 +00:00
|
|
|
MOTH_BEGIN_INSTR(Increment)
|
2015-10-09 07:41:49 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.increment(VALUE(instr.source)));
|
2013-10-29 11:53:05 +00:00
|
|
|
MOTH_END_INSTR(Increment)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(Decrement)
|
2015-10-09 07:41:49 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.decrement(VALUE(instr.source)));
|
2013-10-29 11:53:05 +00:00
|
|
|
MOTH_END_INSTR(Decrement)
|
2012-11-06 11:54:20 +00:00
|
|
|
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_BEGIN_INSTR(Binop)
|
2015-10-12 12:37:37 +00:00
|
|
|
QV4::Runtime::BinaryOperation op = *reinterpret_cast<QV4::Runtime::BinaryOperation *>(reinterpret_cast<char *>(&engine->runtime) + instr.alu);
|
|
|
|
STOREVALUE(instr.result, op(VALUE(instr.lhs), VALUE(instr.rhs)));
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_END_INSTR(Binop)
|
|
|
|
|
2013-10-29 14:28:17 +00:00
|
|
|
MOTH_BEGIN_INSTR(Add)
|
2015-10-09 08:26:00 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.add(engine, VALUE(instr.lhs), VALUE(instr.rhs)));
|
2013-10-29 14:28:17 +00:00
|
|
|
MOTH_END_INSTR(Add)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(BitAnd)
|
2015-10-09 08:26:00 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.bitAnd(VALUE(instr.lhs), VALUE(instr.rhs)));
|
2013-10-29 14:28:17 +00:00
|
|
|
MOTH_END_INSTR(BitAnd)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(BitOr)
|
2015-10-09 08:26:00 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.bitOr(VALUE(instr.lhs), VALUE(instr.rhs)));
|
2013-10-29 14:28:17 +00:00
|
|
|
MOTH_END_INSTR(BitOr)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(BitXor)
|
2015-10-09 08:26:00 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.bitXor(VALUE(instr.lhs), VALUE(instr.rhs)));
|
2013-10-29 14:28:17 +00:00
|
|
|
MOTH_END_INSTR(BitXor)
|
|
|
|
|
2014-02-06 13:56:32 +00:00
|
|
|
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)
|
|
|
|
|
2013-10-29 15:06:43 +00:00
|
|
|
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)));
|
|
|
|
MOTH_END_INSTR(BitXor)
|
|
|
|
|
2014-02-06 13:56:32 +00:00
|
|
|
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)
|
|
|
|
|
2013-10-29 14:28:17 +00:00
|
|
|
MOTH_BEGIN_INSTR(Mul)
|
2015-10-09 08:26:00 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.mul(VALUE(instr.lhs), VALUE(instr.rhs)));
|
2013-10-29 14:28:17 +00:00
|
|
|
MOTH_END_INSTR(Mul)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(Sub)
|
2015-10-09 08:26:00 +00:00
|
|
|
STOREVALUE(instr.result, engine->runtime.sub(VALUE(instr.lhs), VALUE(instr.rhs)));
|
2013-10-29 14:28:17 +00:00
|
|
|
MOTH_END_INSTR(Sub)
|
|
|
|
|
2013-08-05 21:41:42 +00:00
|
|
|
MOTH_BEGIN_INSTR(BinopContext)
|
2015-10-12 12:37:37 +00:00
|
|
|
QV4::Runtime::BinaryOperationContext op = *reinterpret_cast<QV4::Runtime::BinaryOperationContext *>(reinterpret_cast<char *>(&engine->runtime) + instr.alu);
|
|
|
|
STOREVALUE(instr.result, op(engine, VALUE(instr.lhs), VALUE(instr.rhs)));
|
2013-08-05 21:41:42 +00:00
|
|
|
MOTH_END_INSTR(BinopContext)
|
|
|
|
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_BEGIN_INSTR(Ret)
|
2012-12-04 09:31:31 +00:00
|
|
|
// TRACE(Ret, "returning value %s", result.toString(context)->toQString().toUtf8().constData());
|
2013-09-27 14:15:38 +00:00
|
|
|
return VALUE(instr.result).asReturnedValue();
|
2012-06-12 17:13:55 +00:00
|
|
|
MOTH_END_INSTR(Ret)
|
2012-06-11 16:58:52 +00:00
|
|
|
|
2016-07-25 13:58:04 +00:00
|
|
|
#ifndef QT_NO_QML_DEBUGGER
|
2014-02-05 13:38:03 +00:00
|
|
|
MOTH_BEGIN_INSTR(Debug)
|
2015-08-24 14:16:56 +00:00
|
|
|
engine->current->lineNumber = instr.lineNumber;
|
2016-07-25 15:02:45 +00:00
|
|
|
QV4::Debugging::Debugger *debugger = context->engine()->debugger();
|
2014-03-03 13:20:54 +00:00
|
|
|
if (debugger && debugger->pauseAtNextOpportunity())
|
2014-03-03 13:41:31 +00:00
|
|
|
debugger->maybeBreakAtInstruction();
|
2014-12-11 18:14:30 +00:00
|
|
|
if (qt_v4IsDebugging)
|
|
|
|
qt_v4CheckForBreak(context, scopes, scopeDepth);
|
2014-03-03 13:41:31 +00:00
|
|
|
MOTH_END_INSTR(Debug)
|
|
|
|
|
|
|
|
MOTH_BEGIN_INSTR(Line)
|
2015-08-24 14:16:56 +00:00
|
|
|
engine->current->lineNumber = instr.lineNumber;
|
2014-12-11 18:14:30 +00:00
|
|
|
if (qt_v4IsDebugging)
|
|
|
|
qt_v4CheckForBreak(context, scopes, scopeDepth);
|
2015-05-22 10:31:44 +00:00
|
|
|
MOTH_END_INSTR(Line)
|
2016-07-25 13:58:04 +00:00
|
|
|
#endif // QT_NO_QML_DEBUGGER
|
2014-02-05 13:38:03 +00:00
|
|
|
|
2012-10-24 11:45:43 +00:00
|
|
|
MOTH_BEGIN_INSTR(LoadThis)
|
2015-01-15 20:54:12 +00:00
|
|
|
VALUE(instr.result) = context->thisObject();
|
2012-10-24 11:45:43 +00:00
|
|
|
MOTH_END_INSTR(LoadThis)
|
2012-10-23 14:06:52 +00:00
|
|
|
|
2015-06-18 11:12:31 +00:00
|
|
|
MOTH_BEGIN_INSTR(LoadQmlContext)
|
2015-10-09 07:30:12 +00:00
|
|
|
VALUE(instr.result) = engine->runtime.getQmlContext(static_cast<QV4::NoThrowEngine*>(engine));
|
2015-06-18 11:12:31 +00:00
|
|
|
MOTH_END_INSTR(LoadQmlContext)
|
|
|
|
|
2013-10-29 10:59:54 +00:00
|
|
|
MOTH_BEGIN_INSTR(LoadQmlImportedScripts)
|
2015-10-09 07:30:12 +00:00
|
|
|
VALUE(instr.result) = engine->runtime.getQmlImportedScripts(static_cast<QV4::NoThrowEngine*>(engine));
|
2013-10-29 10:59:54 +00:00
|
|
|
MOTH_END_INSTR(LoadQmlImportedScripts)
|
2013-10-28 16:02:54 +00:00
|
|
|
|
2013-11-02 21:46:25 +00:00
|
|
|
MOTH_BEGIN_INSTR(LoadQmlSingleton)
|
2015-10-09 07:30:12 +00:00
|
|
|
VALUE(instr.result) = engine->runtime.getQmlSingleton(static_cast<QV4::NoThrowEngine*>(engine), instr.name);
|
2013-11-02 21:46:25 +00:00
|
|
|
MOTH_END_INSTR(LoadQmlSingleton)
|
|
|
|
|
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
|
|
|
|
|
2013-10-23 12:03:09 +00:00
|
|
|
Q_ASSERT(false);
|
|
|
|
catchException:
|
2014-05-06 07:23:59 +00:00
|
|
|
Q_ASSERT(context->engine()->hasException);
|
2014-12-17 20:07:05 +00:00
|
|
|
if (!exceptionHandler)
|
2013-10-23 12:03:09 +00:00
|
|
|
return QV4::Encode::undefined();
|
|
|
|
code = exceptionHandler;
|
|
|
|
}
|
2012-06-11 16:58:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef MOTH_THREADED_INTERPRETER
|
|
|
|
void **VME::instructionJumpTable()
|
|
|
|
{
|
|
|
|
static void **jumpTable = 0;
|
|
|
|
if (!jumpTable) {
|
Implement JavaScript exceptions using C++ exceptions
Instead of registering catch handlers with setjmp and throwing JS exceptions
with longjmp, they are now thrown and caught as C++ exceptions. This allows for
tight interoperability between C++ and JS in the future and allows for clear
semantics with regards to cleaning up memory in the engine when throwing
exceptions. (destructors are guaranteed to be called, unlike with
setjmp/longjmp).
The recent unwind table additions allow for the exceptions to be thrown through
JIT generated code.
Catching the exception is done by re-using the existing IR semantics where the
beginning of a try block is marked by registering an exception handler.
Execution after the registration continues conditionally, based on the return
value of builtin_create_exception_handler. A return value of is 0 the try
block(s) are executed. If an exception is thrown during that time, execution
resumes at the point where builtin_create_exception_handler returns, but with a
return value of 1. If an exception is thrown within the catch handler, the
execution resumes again at the same point, but the inCatch IR variable will
guide execution straight to the finally block(s), which calls
delete_exception_handler.
In the JIT as well as the interpreter this is implemented by entering a C++
code section that contains a C++ try {} catch {} block, in which the calling
function is called again and continues right at the next instruction (or the
interpreter loop is recursively entered). An exception will throw us out of
that scope and back into the try {} catch {} wrapper, which can call again
into the calling function.
The IR guarantees that delete_exception_handler is always called, regardless of
how the try or catch blocks are terminated. That is where in the JIT and
interpreter we return from the nested function call and return back into the
original stack frame, effectively unregistering the catch handler.
Further cleanups with regards to the naming and the exception handler stack
will come in subsequent patches, this is merely the minimal patch set to
change to the new mechanism.
This patch set breaks ARM until ARM exception handler tables are implemented.
The interpreter changes are based on a patchset from Erik
from https://codereview.qt-project.org/#change,45750
Change-Id: I543f2bd37b2186f7e48ffcab177d57b5ce932a0c
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
2013-03-01 16:04:21 +00:00
|
|
|
const uchar *code = 0;
|
2014-02-06 12:22:36 +00:00
|
|
|
VME().run(0, code, &jumpTable);
|
2012-06-11 16:58:52 +00:00
|
|
|
}
|
|
|
|
return jumpTable;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-11-11 15:07:54 +00:00
|
|
|
QV4::ReturnedValue VME::exec(ExecutionEngine *engine, const uchar *code)
|
2012-06-12 17:13:55 +00:00
|
|
|
{
|
|
|
|
VME vme;
|
2016-07-25 15:02:45 +00:00
|
|
|
QV4::Debugging::Debugger *debugger = engine->debugger();
|
2013-10-16 10:29:47 +00:00
|
|
|
if (debugger)
|
|
|
|
debugger->enteringFunction();
|
2014-11-11 15:07:54 +00:00
|
|
|
QV4::ReturnedValue retVal = vme.run(engine, code);
|
2013-10-16 10:29:47 +00:00
|
|
|
if (debugger)
|
|
|
|
debugger->leavingFunction(retVal);
|
|
|
|
return retVal;
|
2012-06-12 17:13:55 +00:00
|
|
|
}
|