aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@qt.io>2018-10-09 14:58:01 +0200
committerErik Verbruggen <erik.verbruggen@qt.io>2019-01-25 10:26:13 +0000
commit784a55a15ddc65b59cc4709e54453238438eae48 (patch)
tree2903e0c690a8aef0b49f3e5d6c26ef4ac90543aa /src/qml/compiler
parent923fef3ad3076e337eba4e603a6f759c54cc404c (diff)
V4: Collect trace information in the interpreter
Collect type information about values used in a function. These include all parameters, and the results of many bytecode instructions. For array loads/stores, it also tracks if the access is in-bounds of a SimpleArrayData. Collection is only enabled when the qml-tracing feature is turned on while configuring. In subsequent patches this is used to generated optimized JITted code. Change-Id: I63985c334c3fdc55fca7fb4addfe3e535989aac5 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/qv4bytecodegenerator_p.h60
-rw-r--r--src/qml/compiler/qv4bytecodehandler.cpp6
-rw-r--r--src/qml/compiler/qv4bytecodehandler_p.h6
-rw-r--r--src/qml/compiler/qv4codegen.cpp84
-rw-r--r--src/qml/compiler/qv4compileddata.cpp5
-rw-r--r--src/qml/compiler/qv4compileddata_p.h7
-rw-r--r--src/qml/compiler/qv4compiler.cpp2
-rw-r--r--src/qml/compiler/qv4compilercontext.cpp24
-rw-r--r--src/qml/compiler/qv4compilercontext_p.h3
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp77
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h65
11 files changed, 223 insertions, 116 deletions
diff --git a/src/qml/compiler/qv4bytecodegenerator_p.h b/src/qml/compiler/qv4bytecodegenerator_p.h
index 4f3dc27acc..5a27d3948c 100644
--- a/src/qml/compiler/qv4bytecodegenerator_p.h
+++ b/src/qml/compiler/qv4bytecodegenerator_p.h
@@ -51,6 +51,7 @@
// We mean it.
//
#include <private/qv4instr_moth_p.h>
+#include <private/qv4compileddata_p.h>
QT_BEGIN_NAMESPACE
@@ -65,6 +66,8 @@ namespace Moth {
class BytecodeGenerator {
public:
+ typedef CompiledData::Function::TraceInfoCount TraceInfoCount;
+
BytecodeGenerator(int line, bool debug)
: startLine(line), debugMode(debug) {}
@@ -161,6 +164,15 @@ public:
addInstructionHelper(Moth::Instr::Type(InstrT), genericInstr);
}
+ // Same as addInstruction, but also add a trace slot. Move only, because the instruction cannot
+ // be reused afterwards.
+ template<int InstrT>
+ void addTracingInstruction(InstrData<InstrT> data)
+ {
+ data.traceSlot = nextTraceInfo();
+ addInstruction(data);
+ }
+
Q_REQUIRED_RESULT Jump jump()
{
QT_WARNING_PUSH
@@ -172,14 +184,12 @@ QT_WARNING_POP
Q_REQUIRED_RESULT Jump jumpTrue()
{
- Instruction::JumpTrue data;
- return addJumpInstruction(data);
+ return addTracingJumpInstruction(Instruction::JumpTrue());
}
Q_REQUIRED_RESULT Jump jumpFalse()
{
- Instruction::JumpFalse data;
- return addJumpInstruction(data);
+ return addTracingJumpInstruction(Instruction::JumpFalse());
}
Q_REQUIRED_RESULT Jump jumpNotUndefined()
@@ -198,16 +208,16 @@ QT_WARNING_POP
{
Instruction::CmpStrictEqual cmp;
cmp.lhs = lhs;
- addInstruction(cmp);
- addJumpInstruction(Instruction::JumpTrue()).link(target);
+ addInstruction(std::move(cmp));
+ addTracingJumpInstruction(Instruction::JumpTrue()).link(target);
}
void jumpStrictNotEqual(const StackSlot &lhs, const Label &target)
{
Instruction::CmpStrictNotEqual cmp;
cmp.lhs = lhs;
- addInstruction(cmp);
- addJumpInstruction(Instruction::JumpTrue()).link(target);
+ addInstruction(std::move(cmp));
+ addTracingJumpInstruction(Instruction::JumpTrue()).link(target);
}
void setUnwindHandler(ExceptionHandler *handler)
@@ -248,6 +258,13 @@ QT_WARNING_POP
void finalize(Compiler::Context *context);
template<int InstrT>
+ Jump addTracingJumpInstruction(InstrData<InstrT> &&data)
+ {
+ data.traceSlot = nextTraceInfo();
+ return addJumpInstruction(data);
+ }
+
+ template<int InstrT>
Jump addJumpInstruction(const InstrData<InstrT> &data)
{
Instr genericInstr;
@@ -258,9 +275,9 @@ QT_WARNING_POP
void addCJumpInstruction(bool jumpOnFalse, const Label *trueLabel, const Label *falseLabel)
{
if (jumpOnFalse)
- addJumpInstruction(Instruction::JumpFalse()).link(*falseLabel);
+ addTracingJumpInstruction(Instruction::JumpFalse()).link(*falseLabel);
else
- addJumpInstruction(Instruction::JumpTrue()).link(*trueLabel);
+ addTracingJumpInstruction(Instruction::JumpTrue()).link(*trueLabel);
}
void clearLastInstruction()
@@ -268,6 +285,27 @@ QT_WARNING_POP
lastInstrType = -1;
}
+ TraceInfoCount nextTraceInfo()
+ {
+ // If tracing is disabled, use slot 0 to unconditionally store all trace info
+ if (nTraceInfos == CompiledData::Function::NoTracing())
+ return TraceInfoCount(0);
+ return nTraceInfos++;
+ }
+
+ void setTracing(bool onoff, int argumentCount)
+ {
+ if (onoff)
+ nTraceInfos = argumentCount;
+ else
+ nTraceInfos = CompiledData::Function::NoTracing();
+ }
+
+ TraceInfoCount traceInfoCount() const
+ {
+ return nTraceInfos;
+ }
+
private:
friend struct Jump;
friend struct Label;
@@ -302,6 +340,8 @@ private:
int lastInstrType = -1;
Moth::Instr lastInstr;
+
+ TraceInfoCount nTraceInfos = TraceInfoCount(0);
};
}
diff --git a/src/qml/compiler/qv4bytecodehandler.cpp b/src/qml/compiler/qv4bytecodehandler.cpp
index af86b70014..1508790926 100644
--- a/src/qml/compiler/qv4bytecodehandler.cpp
+++ b/src/qml/compiler/qv4bytecodehandler.cpp
@@ -95,6 +95,12 @@ void ByteCodeHandler::decode(const char *code, uint len)
Q_UNUSED(arg2); \
Q_UNUSED(arg3); \
Q_UNUSED(arg4);
+#define MOTH_UNUSED_ARGS5(arg1, arg2, arg3, arg4, arg5) \
+ Q_UNUSED(arg1); \
+ Q_UNUSED(arg2); \
+ Q_UNUSED(arg3); \
+ Q_UNUSED(arg4); \
+ Q_UNUSED(arg5);
#define MOTH_MARK_ARGS_UNUSED_PLEASE(nargs, ...) \
MOTH_EXPAND_FOR_MSVC(MOTH_UNUSED_ARGS##nargs(__VA_ARGS__))
diff --git a/src/qml/compiler/qv4bytecodehandler_p.h b/src/qml/compiler/qv4bytecodehandler_p.h
index ca6abf3dc3..b37c8810bd 100644
--- a/src/qml/compiler/qv4bytecodehandler_p.h
+++ b/src/qml/compiler/qv4bytecodehandler_p.h
@@ -75,6 +75,12 @@ namespace Moth {
int arg2, \
int arg3, \
int arg4
+#define BYTECODE_HANDLER_DEFINE_ARGS5(arg1, arg2, arg3, arg4, arg5) \
+ int arg1, \
+ int arg2, \
+ int arg3, \
+ int arg4, \
+ int arg5
#define BYTECODE_HANDLER_DEFINE_VIRTUAL_BYTECODE_HANDLER_INSTRUCTION(name, nargs, ...) \
virtual void generate_##name( \
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index cdba21604d..6ad26c41dd 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -287,8 +287,8 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr)
switch (op) {
case UMinus: {
expr.loadInAccumulator();
- Instruction::UMinus uminus;
- bytecodeGenerator->addInstruction(uminus);
+ Instruction::UMinus uminus = {};
+ bytecodeGenerator->addTracingInstruction(uminus);
return Reference::fromAccumulator(this);
}
case UPlus: {
@@ -316,8 +316,8 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr)
Instruction::UPlus uplus;
bytecodeGenerator->addInstruction(uplus);
Reference originalValue = Reference::fromStackSlot(this).storeRetainAccumulator();
- Instruction::Increment inc;
- bytecodeGenerator->addInstruction(inc);
+ Instruction::Increment inc = {};
+ bytecodeGenerator->addTracingInstruction(inc);
e.storeConsumeAccumulator();
return originalValue;
} else {
@@ -328,8 +328,8 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr)
case PreIncrement: {
Reference e = expr.asLValue();
e.loadInAccumulator();
- Instruction::Increment inc;
- bytecodeGenerator->addInstruction(inc);
+ Instruction::Increment inc = {};
+ bytecodeGenerator->addTracingInstruction(inc);
if (_expr.accept(nx))
return e.storeConsumeAccumulator();
else
@@ -342,8 +342,8 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr)
Instruction::UPlus uplus;
bytecodeGenerator->addInstruction(uplus);
Reference originalValue = Reference::fromStackSlot(this).storeRetainAccumulator();
- Instruction::Decrement dec;
- bytecodeGenerator->addInstruction(dec);
+ Instruction::Decrement dec = {};
+ bytecodeGenerator->addTracingInstruction(dec);
e.storeConsumeAccumulator();
return originalValue;
} else {
@@ -354,8 +354,8 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr)
case PreDecrement: {
Reference e = expr.asLValue();
e.loadInAccumulator();
- Instruction::Decrement dec;
- bytecodeGenerator->addInstruction(dec);
+ Instruction::Decrement dec = {};
+ bytecodeGenerator->addTracingInstruction(dec);
if (_expr.accept(nx))
return e.storeConsumeAccumulator();
else
@@ -1179,8 +1179,8 @@ bool Codegen::visit(ArrayPattern *ast)
slot.storeConsumeAccumulator();
index.loadInAccumulator();
- Instruction::Increment inc;
- bytecodeGenerator->addInstruction(inc);
+ Instruction::Increment inc = {};
+ bytecodeGenerator->addTracingInstruction(inc);
index.storeConsumeAccumulator();
};
@@ -1243,7 +1243,7 @@ bool Codegen::visit(ArrayPattern *ast)
next.value = lhsValue.stackSlot();
next.done = iteratorDone.stackSlot();
bytecodeGenerator->addInstruction(next);
- bytecodeGenerator->addJumpInstruction(Instruction::JumpFalse()).link(body);
+ bytecodeGenerator->addTracingJumpInstruction(Instruction::JumpFalse()).link(body);
bytecodeGenerator->jump().link(done);
end.link();
@@ -1527,24 +1527,24 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
{
switch (oper) {
case QSOperator::Add: {
- //### Todo: when we add type hints, we can generate an Increment when both the lhs is a number and the rhs == 1
left = left.storeOnStack();
right.loadInAccumulator();
Instruction::Add add;
add.lhs = left.stackSlot();
- bytecodeGenerator->addInstruction(add);
+ bytecodeGenerator->addTracingInstruction(add);
break;
}
case QSOperator::Sub: {
if (right.isConstant() && right.constant == Encode(int(1))) {
left.loadInAccumulator();
- bytecodeGenerator->addInstruction(Instruction::Decrement());
+ Instruction::Decrement dec = {};
+ bytecodeGenerator->addTracingInstruction(dec);
} else {
left = left.storeOnStack();
right.loadInAccumulator();
Instruction::Sub sub;
sub.lhs = left.stackSlot();
- bytecodeGenerator->addInstruction(sub);
+ bytecodeGenerator->addTracingInstruction(sub);
}
break;
}
@@ -1561,7 +1561,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
right.loadInAccumulator();
Instruction::Mul mul;
mul.lhs = left.stackSlot();
- bytecodeGenerator->addInstruction(mul);
+ bytecodeGenerator->addTracingInstruction(mul);
break;
}
case QSOperator::Div: {
@@ -1577,7 +1577,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
right.loadInAccumulator();
Instruction::Mod mod;
mod.lhs = left.stackSlot();
- bytecodeGenerator->addInstruction(mod);
+ bytecodeGenerator->addTracingInstruction(mod);
break;
}
case QSOperator::BitAnd:
@@ -1961,7 +1961,7 @@ bool Codegen::visit(CallExpression *ast)
call.thisObject = baseObject.stackSlot();
call.argc = calldata.argc;
call.argv = calldata.argv;
- bytecodeGenerator->addInstruction(call);
+ bytecodeGenerator->addTracingInstruction(call);
} else {
Instruction::TailCall call;
call.func = base.stackSlot();
@@ -1989,14 +1989,14 @@ void Codegen::handleCall(Reference &base, Arguments calldata, int slotForFunctio
call.name = base.qmlCoreIndex;
call.argc = calldata.argc;
call.argv = calldata.argv;
- bytecodeGenerator->addInstruction(call);
+ bytecodeGenerator->addTracingInstruction(call);
} else if (base.type == Reference::QmlContextObject) {
Instruction::CallContextObjectProperty call;
call.base = base.qmlBase.stackSlot();
call.name = base.qmlCoreIndex;
call.argc = calldata.argc;
call.argv = calldata.argv;
- bytecodeGenerator->addInstruction(call);
+ bytecodeGenerator->addTracingInstruction(call);
} else if (base.type == Reference::Member) {
if (!disable_lookups && useFastLookups) {
Instruction::CallPropertyLookup call;
@@ -2004,14 +2004,14 @@ void Codegen::handleCall(Reference &base, Arguments calldata, int slotForFunctio
call.lookupIndex = registerGetterLookup(base.propertyNameIndex);
call.argc = calldata.argc;
call.argv = calldata.argv;
- bytecodeGenerator->addInstruction(call);
+ bytecodeGenerator->addTracingInstruction(call);
} else {
Instruction::CallProperty call;
call.base = base.propertyBase.stackSlot();
call.name = base.propertyNameIndex;
call.argc = calldata.argc;
call.argv = calldata.argv;
- bytecodeGenerator->addInstruction(call);
+ bytecodeGenerator->addTracingInstruction(call);
}
} else if (base.type == Reference::Subscript) {
Instruction::CallElement call;
@@ -2019,25 +2019,25 @@ void Codegen::handleCall(Reference &base, Arguments calldata, int slotForFunctio
call.index = base.elementSubscript.stackSlot();
call.argc = calldata.argc;
call.argv = calldata.argv;
- bytecodeGenerator->addInstruction(call);
+ bytecodeGenerator->addTracingInstruction(call);
} else if (base.type == Reference::Name) {
if (base.name == QStringLiteral("eval")) {
Instruction::CallPossiblyDirectEval call;
call.argc = calldata.argc;
call.argv = calldata.argv;
- bytecodeGenerator->addInstruction(call);
+ bytecodeGenerator->addTracingInstruction(call);
} else if (!disable_lookups && useFastLookups && base.global) {
Instruction::CallGlobalLookup call;
call.index = registerGlobalGetterLookup(base.nameAsIndex());
call.argc = calldata.argc;
call.argv = calldata.argv;
- bytecodeGenerator->addInstruction(call);
+ bytecodeGenerator->addTracingInstruction(call);
} else {
Instruction::CallName call;
call.name = base.nameAsIndex();
call.argc = calldata.argc;
call.argv = calldata.argv;
- bytecodeGenerator->addInstruction(call);
+ bytecodeGenerator->addTracingInstruction(call);
}
} else if (base.type == Reference::SuperProperty) {
Reference receiver = base.baseObject();
@@ -2054,14 +2054,14 @@ void Codegen::handleCall(Reference &base, Arguments calldata, int slotForFunctio
call.thisObject = receiver.stackSlot();
call.argc = calldata.argc;
call.argv = calldata.argv;
- bytecodeGenerator->addInstruction(call);
+ bytecodeGenerator->addTracingInstruction(call);
} else {
Q_ASSERT(base.isStackSlot());
Instruction::CallValue call;
call.name = base.stackSlot();
call.argc = calldata.argc;
call.argv = calldata.argv;
- bytecodeGenerator->addInstruction(call);
+ bytecodeGenerator->addTracingInstruction(call);
}
_expr.setResult(Reference::fromAccumulator(this));
@@ -2805,14 +2805,14 @@ bool Codegen::visit(TemplateLiteral *ast)
Instruction::Add instr;
instr.lhs = temp2;
- bytecodeGenerator->addInstruction(instr);
+ bytecodeGenerator->addTracingInstruction(instr);
} else {
expr.loadInAccumulator();
}
Instruction::Add instr;
instr.lhs = temp;
- bytecodeGenerator->addInstruction(instr);
+ bytecodeGenerator->addTracingInstruction(instr);
}
auto r = Reference::fromAccumulator(this);
@@ -3070,6 +3070,7 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
bool savedFunctionEndsWithReturn = functionEndsWithReturn;
functionEndsWithReturn = endsWithReturn(_module, body);
+ bytecodeGenerator->setTracing(_functionContext->canUseTracingJit(), _context->arguments.size());
// reserve the js stack frame (Context & js Function & accumulator)
bytecodeGenerator->newRegisterArray(sizeof(CallData)/sizeof(Value) - 1 + _context->arguments.size());
@@ -3158,6 +3159,7 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
Q_ASSERT(_context == _functionContext);
bytecodeGenerator->finalize(_context);
_context->registerCountInFunction = bytecodeGenerator->registerCount();
+ _context->nTraceInfos = bytecodeGenerator->traceInfoCount();
static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE");
if (showCode) {
qDebug() << "=== Bytecode for" << _context->name << "strict mode" << _context->isStrict
@@ -3393,7 +3395,7 @@ bool Codegen::visit(ForEachStatement *ast)
next.value = lhsValue.stackSlot();
next.done = iteratorDone.stackSlot();
bytecodeGenerator->addInstruction(next);
- bytecodeGenerator->addJumpInstruction(Instruction::JumpFalse()).link(body);
+ bytecodeGenerator->addTracingJumpInstruction(Instruction::JumpFalse()).link(body);
bytecodeGenerator->jump().link(done);
end.link();
@@ -4281,7 +4283,7 @@ void Codegen::Reference::storeAccumulator() const
Instruction::StoreElement store;
store.base = elementBase;
store.index = elementSubscript.stackSlot();
- codegen->bytecodeGenerator->addInstruction(store);
+ codegen->bytecodeGenerator->addTracingInstruction(store);
} return;
case QmlScopeObject: {
Instruction::StoreScopeObjectProperty store;
@@ -4383,12 +4385,12 @@ QT_WARNING_POP
if (!scope) {
Instruction::LoadLocal load;
load.index = index;
- codegen->bytecodeGenerator->addInstruction(load);
+ codegen->bytecodeGenerator->addTracingInstruction(load);
} else {
Instruction::LoadScopedLocal load;
load.index = index;
load.scope = scope;
- codegen->bytecodeGenerator->addInstruction(load);
+ codegen->bytecodeGenerator->addTracingInstruction(load);
}
tdzCheck(requiresTDZCheck);
return;
@@ -4411,11 +4413,11 @@ QT_WARNING_POP
if (!disable_lookups && global) {
Instruction::LoadGlobalLookup load;
load.index = codegen->registerGlobalGetterLookup(nameAsIndex());
- codegen->bytecodeGenerator->addInstruction(load);
+ codegen->bytecodeGenerator->addTracingInstruction(load);
} else {
Instruction::LoadName load;
load.name = nameAsIndex();
- codegen->bytecodeGenerator->addInstruction(load);
+ codegen->bytecodeGenerator->addTracingInstruction(load);
}
return;
case Member:
@@ -4424,11 +4426,11 @@ QT_WARNING_POP
if (!disable_lookups && codegen->useFastLookups) {
Instruction::GetLookup load;
load.index = codegen->registerGetterLookup(propertyNameIndex);
- codegen->bytecodeGenerator->addInstruction(load);
+ codegen->bytecodeGenerator->addTracingInstruction(load);
} else {
Instruction::LoadProperty load;
load.name = propertyNameIndex;
- codegen->bytecodeGenerator->addInstruction(load);
+ codegen->bytecodeGenerator->addTracingInstruction(load);
}
return;
case Import: {
@@ -4443,7 +4445,7 @@ QT_WARNING_POP
tdzCheck(subscriptRequiresTDZCheck);
Instruction::LoadElement load;
load.base = elementBase;
- codegen->bytecodeGenerator->addInstruction(load);
+ codegen->bytecodeGenerator->addTracingInstruction(load);
} return;
case QmlScopeObject: {
Instruction::LoadScopeObjectProperty load;
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index a69e862fb7..c90bbf03e6 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -188,7 +188,7 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
runtimeFunctions.resize(data->functionTableSize);
for (int i = 0 ;i < runtimeFunctions.size(); ++i) {
const QV4::CompiledData::Function *compiledFunction = data->functionAt(i);
- runtimeFunctions[i] = new QV4::Function(engine, this, compiledFunction);
+ runtimeFunctions[i] = QV4::Function::create(engine, this, compiledFunction);
}
Scope scope(engine);
@@ -287,7 +287,8 @@ void CompilationUnit::unlink()
runtimeRegularExpressions = nullptr;
free(runtimeClasses);
runtimeClasses = nullptr;
- qDeleteAll(runtimeFunctions);
+ for (QV4::Function *f : qAsConst(runtimeFunctions))
+ f->destroy();
runtimeFunctions.clear();
}
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 5732855cc9..52c8e9f651 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -73,7 +73,7 @@
QT_BEGIN_NAMESPACE
// Bump this whenever the compiler data structures change in an incompatible way.
-#define QV4_DATA_STRUCTURE_VERSION 0x19
+#define QV4_DATA_STRUCTURE_VERSION 0x1a
class QIODevice;
class QQmlPropertyCache;
@@ -299,6 +299,9 @@ struct Function
size_t dependingScopePropertiesOffset() const { return dependingContextPropertiesOffset() + nDependingContextProperties * sizeof(quint32); }
// Qml Extensions End
+ typedef quint16_le TraceInfoCount;
+ TraceInfoCount nTraceInfos;
+ static constexpr TraceInfoCount NoTracing() { return TraceInfoCount::max(); }
// Keep all unaligned data at the end
quint8 flags;
quint8 padding1;
@@ -334,7 +337,7 @@ struct Function
return (a + 7) & ~size_t(7);
}
};
-static_assert(sizeof(Function) == 52, "Function structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
+static_assert(sizeof(Function) == 56, "Function structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct Method {
enum Type {
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index 3076c6b526..8735cc074b 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -420,7 +420,7 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte
Q_ASSERT(function->lineNumberOffset() == currentOffset);
currentOffset += function->nLineNumbers * sizeof(CompiledData::CodeOffsetToLine);
-
+ function->nTraceInfos = irFunction->nTraceInfos;
function->nRegisters = irFunction->registerCountInFunction;
function->nDependingIdObjects = 0;
diff --git a/src/qml/compiler/qv4compilercontext.cpp b/src/qml/compiler/qv4compilercontext.cpp
index 5772bff7bf..419c77fc03 100644
--- a/src/qml/compiler/qv4compilercontext.cpp
+++ b/src/qml/compiler/qv4compilercontext.cpp
@@ -407,4 +407,28 @@ void Context::setupFunctionIndices(Moth::BytecodeGenerator *bytecodeGenerator)
nRegisters = bytecodeGenerator->currentRegister() - registerOffset;
}
+bool Context::canUseTracingJit() const
+{
+#if QT_CONFIG(qml_tracing)
+ static bool forceTracing = !qEnvironmentVariableIsEmpty("QV4_FORCE_TRACING");
+ if (forceTracing) //### we can probably remove this when tracing is turned on by default
+ return true; // to be used by unittests
+
+ static bool disableTracing = !qEnvironmentVariableIsEmpty("QV4_DISABLE_TRACING");
+ if (disableTracing)
+ return false;
+
+ static QStringList onlyTrace =
+ qEnvironmentVariable("QV4_ONLY_TRACE").split(QLatin1Char(','), QString::SkipEmptyParts);
+ if (!onlyTrace.isEmpty())
+ return onlyTrace.contains(name);
+
+ //### the next condition should be refined and have the IR distinguish between escaping and
+ // non-escaping locals
+ return !hasTry && !requiresExecutionContext && !hasNestedFunctions;
+#else
+ return false;
+#endif
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h
index 328715da07..0fa1074580 100644
--- a/src/qml/compiler/qv4compilercontext_p.h
+++ b/src/qml/compiler/qv4compilercontext_p.h
@@ -162,6 +162,7 @@ struct Context {
int line = 0;
int column = 0;
int registerCountInFunction = 0;
+ uint nTraceInfos = 0;
int functionIndex = -1;
int blockIndex = -1;
@@ -366,6 +367,8 @@ struct Context {
return parent->canHaveTailCalls();
return false;
}
+
+ bool canUseTracingJit() const;
};
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index 6edf5a4ae7..def58de9a8 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -156,7 +156,7 @@ QString dumpRegister(int reg, int nFormals)
return QStringLiteral("(this)");
else if (reg == CallData::Argc)
return QStringLiteral("(argc)");
- reg -= CallData::OffsetCount;
+ reg -= CallData::HeaderSize();
if (reg <= nFormals)
return QStringLiteral("a%1").arg(reg);
reg -= nFormals;
@@ -171,6 +171,7 @@ QString dumpArguments(int argc, int argv, int nFormals)
return QStringLiteral("(") + dumpRegister(argv, nFormals) + QStringLiteral(", ") + QString::number(argc) + QStringLiteral(")");
}
+#define TRACE_SLOT QStringLiteral(" {%1}").arg(traceSlot)
void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*startLine*/, const QVector<CompiledData::CodeOffsetToLine> &lineNumberMapping)
{
@@ -240,9 +241,9 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_BEGIN_INSTR(LoadLocal)
if (index < nLocals)
- d << "l" << index;
+ d << "l" << index << TRACE_SLOT;
else
- d << "a" << (index - nLocals);
+ d << "a" << (index - nLocals) << TRACE_SLOT;
MOTH_END_INSTR(LoadLocal)
MOTH_BEGIN_INSTR(StoreLocal)
@@ -254,9 +255,9 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_BEGIN_INSTR(LoadScopedLocal)
if (index < nLocals)
- d << "l" << index << "@" << scope;
+ d << "l" << index << "@" << scope << TRACE_SLOT;
else
- d << "a" << (index - nLocals) << "@" << scope;
+ d << "a" << (index - nLocals) << "@" << scope << TRACE_SLOT;
MOTH_END_INSTR(LoadScopedLocal)
MOTH_BEGIN_INSTR(StoreScopedLocal)
@@ -279,11 +280,11 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_END_INSTR(LoadClosure)
MOTH_BEGIN_INSTR(LoadName)
- d << name;
+ d << name << TRACE_SLOT;
MOTH_END_INSTR(LoadName)
MOTH_BEGIN_INSTR(LoadGlobalLookup)
- d << index;
+ d << index << TRACE_SLOT;
MOTH_END_INSTR(LoadGlobalLookup)
MOTH_BEGIN_INSTR(StoreNameSloppy)
@@ -295,19 +296,20 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_END_INSTR(StoreNameStrict)
MOTH_BEGIN_INSTR(LoadElement)
- d << dumpRegister(base, nFormals) << "[acc]";
+ d << dumpRegister(base, nFormals) << "[acc]" << TRACE_SLOT;
MOTH_END_INSTR(LoadElement)
MOTH_BEGIN_INSTR(StoreElement)
- d << dumpRegister(base, nFormals) << "[" << dumpRegister(index, nFormals) << "]";
+ d << dumpRegister(base, nFormals) << "[" << dumpRegister(index, nFormals) << "]"
+ << TRACE_SLOT;
MOTH_END_INSTR(StoreElement)
MOTH_BEGIN_INSTR(LoadProperty)
- d << "acc[" << name << "]";
+ d << "acc[" << name << "]" << TRACE_SLOT;
MOTH_END_INSTR(LoadProperty)
MOTH_BEGIN_INSTR(GetLookup)
- d << "acc(" << index << ")";
+ d << "acc(" << index << ")" << TRACE_SLOT;
MOTH_END_INSTR(GetLookup)
MOTH_BEGIN_INSTR(StoreProperty)
@@ -357,55 +359,63 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_END_INSTR(Resume)
MOTH_BEGIN_INSTR(CallValue)
- d << dumpRegister(name, nFormals) << dumpArguments(argc, argv, nFormals);
+ d << dumpRegister(name, nFormals) << dumpArguments(argc, argv, nFormals) << TRACE_SLOT;
MOTH_END_INSTR(CallValue)
MOTH_BEGIN_INSTR(CallWithReceiver)
- d << dumpRegister(name, nFormals) << dumpRegister(thisObject, nFormals) << dumpArguments(argc, argv, nFormals);
+ d << dumpRegister(name, nFormals) << dumpRegister(thisObject, nFormals)
+ << dumpArguments(argc, argv, nFormals) << TRACE_SLOT;
MOTH_END_INSTR(CallWithReceiver)
MOTH_BEGIN_INSTR(CallProperty)
- d << dumpRegister(base, nFormals) << "." << name << dumpArguments(argc, argv, nFormals);
+ d << dumpRegister(base, nFormals) << "." << name << dumpArguments(argc, argv, nFormals)
+ << TRACE_SLOT;
MOTH_END_INSTR(CallProperty)
MOTH_BEGIN_INSTR(CallPropertyLookup)
- d << dumpRegister(base, nFormals) << "." << lookupIndex << dumpArguments(argc, argv, nFormals);
+ d << dumpRegister(base, nFormals) << "." << lookupIndex
+ << dumpArguments(argc, argv, nFormals) << TRACE_SLOT;
MOTH_END_INSTR(CallPropertyLookup)
MOTH_BEGIN_INSTR(CallElement)
- d << dumpRegister(base, nFormals) << "[" << dumpRegister(index, nFormals) << "]" << dumpArguments(argc, argv, nFormals);
+ d << dumpRegister(base, nFormals) << "[" << dumpRegister(index, nFormals) << "]"
+ << dumpArguments(argc, argv, nFormals) << TRACE_SLOT;
MOTH_END_INSTR(CallElement)
MOTH_BEGIN_INSTR(CallName)
- d << name << dumpArguments(argc, argv, nFormals);
+ d << name << dumpArguments(argc, argv, nFormals) << TRACE_SLOT;
MOTH_END_INSTR(CallName)
MOTH_BEGIN_INSTR(CallPossiblyDirectEval)
- d << dumpArguments(argc, argv, nFormals);
+ d << dumpArguments(argc, argv, nFormals) << TRACE_SLOT;
MOTH_END_INSTR(CallPossiblyDirectEval)
MOTH_BEGIN_INSTR(CallGlobalLookup)
- d << index << dumpArguments(argc, argv, nFormals);
+ d << index << dumpArguments(argc, argv, nFormals) << TRACE_SLOT;
MOTH_END_INSTR(CallGlobalLookup)
MOTH_BEGIN_INSTR(CallScopeObjectProperty)
- d << dumpRegister(base, nFormals) << "." << name << dumpArguments(argc, argv, nFormals);
+ d << dumpRegister(base, nFormals) << "." << name << dumpArguments(argc, argv, nFormals)
+ << TRACE_SLOT;
MOTH_END_INSTR(CallScopeObjectProperty)
MOTH_BEGIN_INSTR(CallContextObjectProperty)
- d << dumpRegister(base, nFormals) << "." << name << dumpArguments(argc, argv, nFormals);
+ d << dumpRegister(base, nFormals) << "." << name << dumpArguments(argc, argv, nFormals)
+ << TRACE_SLOT;
MOTH_END_INSTR(CallContextObjectProperty)
MOTH_BEGIN_INSTR(CallWithSpread)
- d << "new" << dumpRegister(func, nFormals) << dumpRegister(thisObject, nFormals) << dumpArguments(argc, argv, nFormals);
+ d << "new " << dumpRegister(func, nFormals) << dumpRegister(thisObject, nFormals)
+ << dumpArguments(argc, argv, nFormals)
+ << TRACE_SLOT;
MOTH_END_INSTR(CallWithSpread)
MOTH_BEGIN_INSTR(Construct)
- d << "new" << dumpRegister(func, nFormals) << dumpArguments(argc, argv, nFormals);
+ d << "new " << dumpRegister(func, nFormals) << dumpArguments(argc, argv, nFormals);
MOTH_END_INSTR(Construct)
MOTH_BEGIN_INSTR(ConstructWithSpread)
- d << "new" << dumpRegister(func, nFormals) << dumpArguments(argc, argv, nFormals);
+ d << "new " << dumpRegister(func, nFormals) << dumpArguments(argc, argv, nFormals);
MOTH_END_INSTR(ConstructWithSpread)
MOTH_BEGIN_INSTR(SetUnwindHandler)
@@ -540,11 +550,11 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_END_INSTR(Jump)
MOTH_BEGIN_INSTR(JumpTrue)
- d << ABSOLUTE_OFFSET();
+ d << ABSOLUTE_OFFSET() << TRACE_SLOT;
MOTH_END_INSTR(JumpTrue)
MOTH_BEGIN_INSTR(JumpFalse)
- d << ABSOLUTE_OFFSET();
+ d << ABSOLUTE_OFFSET() << TRACE_SLOT;
MOTH_END_INSTR(JumpFalse)
MOTH_BEGIN_INSTR(JumpNotUndefined)
@@ -608,19 +618,22 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_END_INSTR(UPlus)
MOTH_BEGIN_INSTR(UMinus)
+ d << TRACE_SLOT;
MOTH_END_INSTR(UMinus)
MOTH_BEGIN_INSTR(UCompl)
MOTH_END_INSTR(UCompl)
MOTH_BEGIN_INSTR(Increment)
- MOTH_END_INSTR(PreIncrement)
+ d << TRACE_SLOT;
+ MOTH_END_INSTR(Increment)
MOTH_BEGIN_INSTR(Decrement)
- MOTH_END_INSTR(PreDecrement)
+ d << TRACE_SLOT;
+ MOTH_END_INSTR(Decrement)
MOTH_BEGIN_INSTR(Add)
- d << dumpRegister(lhs, nFormals) << ", acc";
+ d << dumpRegister(lhs, nFormals) << ", acc" << TRACE_SLOT;
MOTH_END_INSTR(Add)
MOTH_BEGIN_INSTR(BitAnd)
@@ -676,7 +689,7 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_END_INSTR(Exp)
MOTH_BEGIN_INSTR(Mul)
- d << dumpRegister(lhs, nFormals) << ", acc";
+ d << dumpRegister(lhs, nFormals) << ", acc" << TRACE_SLOT;
MOTH_END_INSTR(Mul)
MOTH_BEGIN_INSTR(Div)
@@ -684,11 +697,11 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_END_INSTR(Div)
MOTH_BEGIN_INSTR(Mod)
- d << dumpRegister(lhs, nFormals) << ", acc";
+ d << dumpRegister(lhs, nFormals) << ", acc" << TRACE_SLOT;
MOTH_END_INSTR(Mod)
MOTH_BEGIN_INSTR(Sub)
- d << dumpRegister(lhs, nFormals) << ", acc";
+ d << dumpRegister(lhs, nFormals) << ", acc" << TRACE_SLOT;
MOTH_END_INSTR(Sub)
MOTH_BEGIN_INSTR(CmpIn)
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 2ca8f692b8..080f4b42b6 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -77,19 +77,19 @@ QT_BEGIN_NAMESPACE
#define INSTR_StoreReg(op) INSTRUCTION(op, StoreReg, 1, reg)
#define INSTR_MoveReg(op) INSTRUCTION(op, MoveReg, 2, srcReg, destReg)
#define INSTR_LoadImport(op) INSTRUCTION(op, LoadImport, 1, index)
-#define INSTR_LoadLocal(op) INSTRUCTION(op, LoadLocal, 1, index)
+#define INSTR_LoadLocal(op) INSTRUCTION(op, LoadLocal, 2, index, traceSlot)
#define INSTR_StoreLocal(op) INSTRUCTION(op, StoreLocal, 1, index)
-#define INSTR_LoadScopedLocal(op) INSTRUCTION(op, LoadScopedLocal, 2, scope, index)
+#define INSTR_LoadScopedLocal(op) INSTRUCTION(op, LoadScopedLocal, 3, scope, index, traceSlot)
#define INSTR_StoreScopedLocal(op) INSTRUCTION(op, StoreScopedLocal, 2, scope, index)
#define INSTR_LoadRuntimeString(op) INSTRUCTION(op, LoadRuntimeString, 1, stringId)
#define INSTR_MoveRegExp(op) INSTRUCTION(op, MoveRegExp, 2, regExpId, destReg)
#define INSTR_LoadClosure(op) INSTRUCTION(op, LoadClosure, 1, value)
-#define INSTR_LoadName(op) INSTRUCTION(op, LoadName, 1, name)
-#define INSTR_LoadGlobalLookup(op) INSTRUCTION(op, LoadGlobalLookup, 1, index)
+#define INSTR_LoadName(op) INSTRUCTION(op, LoadName, 2, name, traceSlot)
+#define INSTR_LoadGlobalLookup(op) INSTRUCTION(op, LoadGlobalLookup, 2, index, traceSlot)
#define INSTR_StoreNameSloppy(op) INSTRUCTION(op, StoreNameSloppy, 1, name)
#define INSTR_StoreNameStrict(op) INSTRUCTION(op, StoreNameStrict, 1, name)
-#define INSTR_LoadProperty(op) INSTRUCTION(op, LoadProperty, 1, name)
-#define INSTR_GetLookup(op) INSTRUCTION(op, GetLookup, 1, index)
+#define INSTR_LoadProperty(op) INSTRUCTION(op, LoadProperty, 2, name, traceSlot)
+#define INSTR_GetLookup(op) INSTRUCTION(op, GetLookup, 2, index, traceSlot)
#define INSTR_LoadScopeObjectProperty(op) INSTRUCTION(op, LoadScopeObjectProperty, 3, propertyIndex, base, captureRequired)
#define INSTR_LoadContextObjectProperty(op) INSTRUCTION(op, LoadContextObjectProperty, 3, propertyIndex, base, captureRequired)
#define INSTR_LoadIdObject(op) INSTRUCTION(op, LoadIdObject, 2, index, base)
@@ -103,19 +103,19 @@ QT_BEGIN_NAMESPACE
#define INSTR_StoreSuperProperty(op) INSTRUCTION(op, StoreSuperProperty, 1, property)
#define INSTR_StoreScopeObjectProperty(op) INSTRUCTION(op, StoreScopeObjectProperty, 2, base, propertyIndex)
#define INSTR_StoreContextObjectProperty(op) INSTRUCTION(op, StoreContextObjectProperty, 2, base, propertyIndex)
-#define INSTR_LoadElement(op) INSTRUCTION(op, LoadElement, 1, base)
-#define INSTR_StoreElement(op) INSTRUCTION(op, StoreElement, 2, base, index)
-#define INSTR_CallValue(op) INSTRUCTION(op, CallValue, 3, name, argc, argv)
-#define INSTR_CallWithReceiver(op) INSTRUCTION(op, CallWithReceiver, 4, name, thisObject, argc, argv)
-#define INSTR_CallProperty(op) INSTRUCTION(op, CallProperty, 4, name, base, argc, argv)
-#define INSTR_CallPropertyLookup(op) INSTRUCTION(op, CallPropertyLookup, 4, lookupIndex, base, argc, argv)
-#define INSTR_CallElement(op) INSTRUCTION(op, CallElement, 4, base, index, argc, argv)
-#define INSTR_CallName(op) INSTRUCTION(op, CallName, 3, name, argc, argv)
-#define INSTR_CallPossiblyDirectEval(op) INSTRUCTION(op, CallPossiblyDirectEval, 2, argc, argv)
-#define INSTR_CallGlobalLookup(op) INSTRUCTION(op, CallGlobalLookup, 3, index, argc, argv)
-#define INSTR_CallScopeObjectProperty(op) INSTRUCTION(op, CallScopeObjectProperty, 4, name, base, argc, argv)
-#define INSTR_CallContextObjectProperty(op) INSTRUCTION(op, CallContextObjectProperty, 4, name, base, argc, argv)
-#define INSTR_CallWithSpread(op) INSTRUCTION(op, CallWithSpread, 4, func, thisObject, argc, argv)
+#define INSTR_LoadElement(op) INSTRUCTION(op, LoadElement, 2, base, traceSlot)
+#define INSTR_StoreElement(op) INSTRUCTION(op, StoreElement, 3, base, index, traceSlot)
+#define INSTR_CallValue(op) INSTRUCTION(op, CallValue, 4, name, argc, argv, traceSlot)
+#define INSTR_CallWithReceiver(op) INSTRUCTION(op, CallWithReceiver, 5, name, thisObject, argc, argv, traceSlot)
+#define INSTR_CallProperty(op) INSTRUCTION(op, CallProperty, 5, name, base, argc, argv, traceSlot)
+#define INSTR_CallPropertyLookup(op) INSTRUCTION(op, CallPropertyLookup, 5, lookupIndex, base, argc, argv, traceSlot)
+#define INSTR_CallElement(op) INSTRUCTION(op, CallElement, 5, base, index, argc, argv, traceSlot)
+#define INSTR_CallName(op) INSTRUCTION(op, CallName, 4, name, argc, argv, traceSlot)
+#define INSTR_CallPossiblyDirectEval(op) INSTRUCTION(op, CallPossiblyDirectEval, 3, argc, argv, traceSlot)
+#define INSTR_CallGlobalLookup(op) INSTRUCTION(op, CallGlobalLookup, 4, index, argc, argv, traceSlot)
+#define INSTR_CallScopeObjectProperty(op) INSTRUCTION(op, CallScopeObjectProperty, 5, name, base, argc, argv, traceSlot)
+#define INSTR_CallContextObjectProperty(op) INSTRUCTION(op, CallContextObjectProperty, 5, name, base, argc, argv, traceSlot)
+#define INSTR_CallWithSpread(op) INSTRUCTION(op, CallWithSpread, 5, func, thisObject, argc, argv, traceSlot)
#define INSTR_Construct(op) INSTRUCTION(op, Construct, 3, func, argc, argv)
#define INSTR_ConstructWithSpread(op) INSTRUCTION(op, ConstructWithSpread, 3, func, argc, argv)
#define INSTR_SetUnwindHandler(op) INSTRUCTION(op, SetUnwindHandler, 1, offset)
@@ -152,8 +152,8 @@ QT_BEGIN_NAMESPACE
#define INSTR_LoadSuperConstructor(op) INSTRUCTION(op, LoadSuperConstructor, 0)
#define INSTR_ToObject(op) INSTRUCTION(op, ToObject, 0)
#define INSTR_Jump(op) INSTRUCTION(op, Jump, 1, offset)
-#define INSTR_JumpTrue(op) INSTRUCTION(op, JumpTrue, 1, offset)
-#define INSTR_JumpFalse(op) INSTRUCTION(op, JumpFalse, 1, offset)
+#define INSTR_JumpTrue(op) INSTRUCTION(op, JumpTrue, 2, traceSlot, offset)
+#define INSTR_JumpFalse(op) INSTRUCTION(op, JumpFalse, 2, traceSlot, offset)
#define INSTR_JumpNotUndefined(op) INSTRUCTION(op, JumpNotUndefined, 1, offset)
#define INSTR_JumpNoException(op) INSTRUCTION(op, JumpNoException, 1, offset)
#define INSTR_CmpEqNull(op) INSTRUCTION(op, CmpEqNull, 0)
@@ -172,11 +172,11 @@ QT_BEGIN_NAMESPACE
#define INSTR_CmpInstanceOf(op) INSTRUCTION(op, CmpInstanceOf, 1, lhs)
#define INSTR_UNot(op) INSTRUCTION(op, UNot, 0)
#define INSTR_UPlus(op) INSTRUCTION(op, UPlus, 0)
-#define INSTR_UMinus(op) INSTRUCTION(op, UMinus, 0)
+#define INSTR_UMinus(op) INSTRUCTION(op, UMinus, 1, traceSlot)
#define INSTR_UCompl(op) INSTRUCTION(op, UCompl, 0)
-#define INSTR_Increment(op) INSTRUCTION(op, Increment, 0)
-#define INSTR_Decrement(op) INSTRUCTION(op, Decrement, 0)
-#define INSTR_Add(op) INSTRUCTION(op, Add, 1, lhs)
+#define INSTR_Increment(op) INSTRUCTION(op, Increment, 1, traceSlot)
+#define INSTR_Decrement(op) INSTRUCTION(op, Decrement, 1, traceSlot)
+#define INSTR_Add(op) INSTRUCTION(op, Add, 2, lhs, traceSlot)
#define INSTR_BitAnd(op) INSTRUCTION(op, BitAnd, 1, lhs)
#define INSTR_BitOr(op) INSTRUCTION(op, BitOr, 1, lhs)
#define INSTR_BitXor(op) INSTRUCTION(op, BitXor, 1, lhs)
@@ -190,10 +190,10 @@ QT_BEGIN_NAMESPACE
#define INSTR_ShrConst(op) INSTRUCTION(op, ShrConst, 1, rhs)
#define INSTR_ShlConst(op) INSTRUCTION(op, ShlConst, 1, rhs)
#define INSTR_Exp(op) INSTRUCTION(op, Exp, 1, lhs)
-#define INSTR_Mul(op) INSTRUCTION(op, Mul, 1, lhs)
+#define INSTR_Mul(op) INSTRUCTION(op, Mul, 2, lhs, traceSlot)
#define INSTR_Div(op) INSTRUCTION(op, Div, 1, lhs)
-#define INSTR_Mod(op) INSTRUCTION(op, Mod, 1, lhs)
-#define INSTR_Sub(op) INSTRUCTION(op, Sub, 1, lhs)
+#define INSTR_Mod(op) INSTRUCTION(op, Mod, 2, lhs, traceSlot)
+#define INSTR_Sub(op) INSTRUCTION(op, Sub, 2, lhs, traceSlot)
#define INSTR_LoadQmlContext(op) INSTRUCTION(op, LoadQmlContext, 1, result)
#define INSTR_LoadQmlImportedScripts(op) INSTRUCTION(op, LoadQmlImportedScripts, 1, result)
#define INSTR_InitializeBlockDeadTemporalZone(op) INSTRUCTION(op, InitializeBlockDeadTemporalZone, 2, firstReg, count)
@@ -377,6 +377,12 @@ QT_BEGIN_NAMESPACE
int arg2; \
int arg3; \
int arg4;
+#define MOTH_DEFINE_ARGS5(arg1, arg2, arg3, arg4, arg5) \
+ int arg1; \
+ int arg2; \
+ int arg3; \
+ int arg4; \
+ int arg5;
#define MOTH_COLLECT_ENUMS(instr) \
INSTR_##instr(MOTH_GET_ENUM)
@@ -447,6 +453,9 @@ QT_BEGIN_NAMESPACE
#define MOTH_DECODE_ARGS4(name, type, nargs, arg1, arg2, arg3, arg4) \
MOTH_DECODE_ARGS3(name, type, nargs, arg1, arg2, arg3); \
MOTH_DECODE_ARG(arg4, type, nargs, 3);
+#define MOTH_DECODE_ARGS5(name, type, nargs, arg1, arg2, arg3, arg4, arg5) \
+ MOTH_DECODE_ARGS4(name, type, nargs, arg1, arg2, arg3, arg4); \
+ MOTH_DECODE_ARG(arg5, type, nargs, 4);
#ifdef MOTH_COMPUTED_GOTO
/* collect jump labels */