aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKent Hansen <kent.hansen@nokia.com>2011-09-22 13:40:48 +0200
committerQt by Nokia <qt-info@nokia.com>2011-09-23 11:27:31 +0200
commit2403b2f5611d6faa2836d0c37327a507612c1620 (patch)
treef0a40277eb2614c00a4ef492abf397c76884d5de
parent4938e1aef35045554074a4340aed25f9796f65ea (diff)
Get rid of redundant type member from V4 instructions
When interpretation is threaded, the type member is redundant, since we can obtain the type from the instruction address. Getting rid of the type member can save at least one byte per instruction (possibly more because of alignment). On ia32, the Noop and Block instructions become 4 bytes smaller. The compiler has been refactored to leave it up to the Bytecode class to decide whether the instruction address or type (enum) should be stored. To achieve this, the "low-level" Instr union was renamed to V4Instr, and the new Instr struct used by the compiler provides typedefs for instantiating the data used by each particular instruction. Lastly, the gen() function (instruction emitter) was made template-based to provide the instruction type. The instructions Bool, Int, Real, String were renamed to Load{Bool,Int,Real,String} to make the new code more readable. This approach follows a similar refactoring in the QML-VME interpreter. Change-Id: I9bf16b099a85afdfb719a25fb18047408882d61e Reviewed-on: http://codereview.qt-project.org/5393 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
-rw-r--r--src/declarative/qml/v4/qdeclarativev4bindings.cpp18
-rw-r--r--src/declarative/qml/v4/qdeclarativev4compiler.cpp460
-rw-r--r--src/declarative/qml/v4/qdeclarativev4compiler_p_p.h18
-rw-r--r--src/declarative/qml/v4/qdeclarativev4instruction.cpp551
-rw-r--r--src/declarative/qml/v4/qdeclarativev4instruction_p.h118
5 files changed, 500 insertions, 665 deletions
diff --git a/src/declarative/qml/v4/qdeclarativev4bindings.cpp b/src/declarative/qml/v4/qdeclarativev4bindings.cpp
index 20d79dc46d..1a1f5cc8f6 100644
--- a/src/declarative/qml/v4/qdeclarativev4bindings.cpp
+++ b/src/declarative/qml/v4/qdeclarativev4bindings.cpp
@@ -789,7 +789,7 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks,
QDeclarativeEnginePrivate *engine = QDeclarativeEnginePrivate::get(context->engine);
const char *code = program->instructions();
code += instrIndex * QML_V4_INSTR_SIZE(Jump, jump);
- const Instr *instr = (const Instr *) code;
+ const V4Instr *instr = reinterpret_cast<const V4Instr *>(code);
const char *data = program->data();
@@ -1110,26 +1110,26 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(MathPIReal, unaryop)
- QML_V4_BEGIN_INSTR(Real, real_value)
+ QML_V4_BEGIN_INSTR(LoadReal, real_value)
registers[instr->real_value.reg].setqreal(instr->real_value.value);
- QML_V4_END_INSTR(Real, real_value)
+ QML_V4_END_INSTR(LoadReal, real_value)
- QML_V4_BEGIN_INSTR(Int, int_value)
+ QML_V4_BEGIN_INSTR(LoadInt, int_value)
registers[instr->int_value.reg].setint(instr->int_value.value);
- QML_V4_END_INSTR(Int, int_value)
+ QML_V4_END_INSTR(LoadInt, int_value)
- QML_V4_BEGIN_INSTR(Bool, bool_value)
+ QML_V4_BEGIN_INSTR(LoadBool, bool_value)
registers[instr->bool_value.reg].setbool(instr->bool_value.value);
- QML_V4_END_INSTR(Bool, bool_value)
+ QML_V4_END_INSTR(LoadBool, bool_value)
- QML_V4_BEGIN_INSTR(String, string_value)
+ QML_V4_BEGIN_INSTR(LoadString, string_value)
{
Register &output = registers[instr->string_value.reg];
QChar *string = (QChar *)(data + instr->string_value.offset);
new (output.getstringptr()) QString(string, instr->string_value.length);
STRING_REGISTER(instr->string_value.reg);
}
- QML_V4_END_INSTR(String, string_value)
+ QML_V4_END_INSTR(LoadString, string_value)
QML_V4_BEGIN_INSTR(EnableV4Test, string_value)
{
diff --git a/src/declarative/qml/v4/qdeclarativev4compiler.cpp b/src/declarative/qml/v4/qdeclarativev4compiler.cpp
index fa4cd25952..35ec92402b 100644
--- a/src/declarative/qml/v4/qdeclarativev4compiler.cpp
+++ b/src/declarative/qml/v4/qdeclarativev4compiler.cpp
@@ -106,10 +106,9 @@ void QDeclarativeV4CompilerPrivate::trace(int line, int column)
if (bytecode.isEmpty()) {
if (qmlBindingsTest || bindingsDump()) {
- Instr id;
- id.common.type = Instr::BindingId;
- id.id.column = column;
- id.id.line = line;
+ Instr::BindingId id;
+ id.column = column;
+ id.line = line;
gen(id);
}
@@ -119,11 +118,10 @@ void QDeclarativeV4CompilerPrivate::trace(int line, int column)
int offset = data.count();
data += strdata;
- Instr test;
- test.common.type = Instr::EnableV4Test;
- test.string_value.reg = 0;
- test.string_value.offset = offset;
- test.string_value.length = str.length();
+ Instr::EnableV4Test test;
+ test.reg = 0;
+ test.offset = offset;
+ test.length = str.length();
gen(test);
}
}
@@ -133,8 +131,8 @@ void QDeclarativeV4CompilerPrivate::trace(int line, int column)
qSwap(usedSubscriptionIdsChanged, usic);
int blockopIndex = bytecode.size();
- Instr blockop;
- blockop.block(currentBlockMask);
+ Instr::Block blockop;
+ blockop.block = currentBlockMask;
gen(blockop);
foreach (IR::Stmt *s, block->statements) {
@@ -169,8 +167,9 @@ void QDeclarativeV4CompilerPrivate::trace(int line, int column)
if (! _discarded) {
// back patching
foreach (const Patch &patch, patches) {
- Instr &instr = bytecode[patch.offset];
- instr.branchop.offset = patch.block->offset - patch.offset - instr.size();
+ V4Instr &instr = bytecode[patch.offset];
+ int size = V4Instr::size(instructionType(&instr));
+ instr.branchop.offset = patch.block->offset - patch.offset - size;
}
patches.clear();
@@ -211,22 +210,27 @@ void QDeclarativeV4CompilerPrivate::traceExpression(IR::Expr *e, quint8 r)
//
void QDeclarativeV4CompilerPrivate::visitConst(IR::Const *e)
{
- Instr i;
switch (e->type) {
- case IR::BoolType:
- i.move_reg_bool(currentReg, e->value);
+ case IR::BoolType: {
+ Instr::LoadBool i;
+ i.reg = currentReg;
+ i.value = e->value;
gen(i);
- break;
+ } break;
- case IR::IntType:
- i.move_reg_int(currentReg, e->value);
+ case IR::IntType: {
+ Instr::LoadInt i;
+ i.reg = currentReg;
+ i.value = e->value;
gen(i);
- break;
+ } break;
- case IR::RealType:
- i.move_reg_qreal(currentReg, e->value);
+ case IR::RealType: {
+ Instr::LoadReal i;
+ i.reg = currentReg;
+ i.value = e->value;
gen(i);
- break;
+ } break;
default:
if (qmlVerboseCompiler())
@@ -251,8 +255,8 @@ void QDeclarativeV4CompilerPrivate::visitName(IR::Name *e)
if (e->storage == IR::Name::RootStorage) {
- Instr instr;
- instr.load_root(currentReg);
+ Instr::LoadRoot instr;
+ instr.reg = currentReg;
gen(instr);
if (e->symbol == IR::Name::IdObject) {
@@ -262,23 +266,26 @@ void QDeclarativeV4CompilerPrivate::visitName(IR::Name *e)
} else if (e->storage == IR::Name::ScopeStorage) {
- Instr instr;
- instr.load_scope(currentReg);
+ Instr::LoadScope instr;
+ instr.reg = currentReg;
gen(instr);
_subscribeName << contextName();
} else if (e->storage == IR::Name::IdStorage) {
- Instr instr;
- instr.load_id(currentReg, e->index);
+ Instr::LoadId instr;
+ instr.reg = currentReg;
+ instr.index = e->index;
gen(instr);
_subscribeName << QLatin1String("$$$ID_") + *e->id;
if (blockNeedsSubscription(_subscribeName)) {
- Instr sub;
- sub.subscribeId(currentReg, subscriptionIndex(_subscribeName), instr.load.index);
+ Instr::SubscribeId sub;
+ sub.reg = currentReg;
+ sub.offset = subscriptionIndex(_subscribeName);
+ sub.index = instr.index;
gen(sub);
}
@@ -299,13 +306,12 @@ void QDeclarativeV4CompilerPrivate::visitName(IR::Name *e)
case IR::Name::AttachType: {
_subscribeName << *e->id;
- Instr attached;
- attached.common.type = Instr::LoadAttached;
- attached.attached.output = currentReg;
- attached.attached.reg = currentReg;
- attached.attached.exceptionId = exceptionId(e->line, e->column);
+ Instr::LoadAttached attached;
+ attached.output = currentReg;
+ attached.reg = currentReg;
+ attached.exceptionId = exceptionId(e->line, e->column);
Q_ASSERT(e->declarativeType->attachedPropertiesId() != -1);
- attached.attached.id = e->declarativeType->attachedPropertiesId();
+ attached.id = e->declarativeType->attachedPropertiesId();
gen(attached);
} break;
@@ -349,31 +355,31 @@ void QDeclarativeV4CompilerPrivate::visitName(IR::Name *e)
break;
} // switch
- Instr fetch;
-
if (fastFetchIndex != -1) {
- fetch.common.type = Instr::FetchAndSubscribe;
- fetch.fetchAndSubscribe.reg = currentReg;
- fetch.fetchAndSubscribe.function = fastFetchIndex;
- fetch.fetchAndSubscribe.subscription = subscriptionIndex(_subscribeName);
- fetch.fetchAndSubscribe.exceptionId = exceptionId(e->line, e->column);
- fetch.fetchAndSubscribe.valueType = regType;
+ Instr::FetchAndSubscribe fetch;
+ fetch.reg = currentReg;
+ fetch.function = fastFetchIndex;
+ fetch.subscription = subscriptionIndex(_subscribeName);
+ fetch.exceptionId = exceptionId(e->line, e->column);
+ fetch.valueType = regType;
+ gen(fetch);
} else {
if (blockNeedsSubscription(_subscribeName) && prop.hasNotifySignal() && prop.notifySignalIndex() != -1) {
- Instr sub;
- sub.subscribe(currentReg, subscriptionIndex(_subscribeName), prop.notifySignalIndex());
+ Instr::Subscribe sub;
+ sub.reg = currentReg;
+ sub.offset = subscriptionIndex(_subscribeName);
+ sub.index = prop.notifySignalIndex();
gen(sub);
}
- fetch.common.type = Instr::Fetch;
- fetch.fetch.reg = currentReg;
- fetch.fetch.index = e->index;
- fetch.fetch.exceptionId = exceptionId(e->line, e->column);
- fetch.fetch.valueType = regType;
+ Instr::Fetch fetch;
+ fetch.reg = currentReg;
+ fetch.index = e->index;
+ fetch.exceptionId = exceptionId(e->line, e->column);
+ fetch.valueType = regType;
+ gen(fetch);
}
- gen(fetch);
-
} break;
} // switch
}
@@ -381,16 +387,15 @@ void QDeclarativeV4CompilerPrivate::visitName(IR::Name *e)
void QDeclarativeV4CompilerPrivate::visitTemp(IR::Temp *e)
{
if (currentReg != e->index) {
- Instr i;
- i.move_reg_reg(currentReg, e->index);
+ Instr::Copy i;
+ i.reg = currentReg;
+ i.src = e->index;
gen(i);
}
}
void QDeclarativeV4CompilerPrivate::visitUnop(IR::Unop *e)
{
- Instr i;
-
quint8 src = currentReg;
if (IR::Temp *temp = e->expr->asTemp()) {
@@ -407,24 +412,32 @@ void QDeclarativeV4CompilerPrivate::visitUnop(IR::Unop *e)
case IR::OpIfTrue:
convertToBool(e->expr, src);
if (src != currentReg) {
- i.move_reg_reg(currentReg, src);
+ Instr::Copy i;
+ i.reg = currentReg;
+ i.src = src;
gen(i);
}
break;
- case IR::OpNot:
+ case IR::OpNot: {
+ Instr::UnaryNot i;
convertToBool(e->expr, src);
- i.unary_not(currentReg, src);
+ i.output = currentReg;
+ i.src = src;
gen(i);
- break;
+ } break;
case IR::OpUMinus:
if (e->expr->type == IR::RealType) {
- i.uminus_real(currentReg, src);
+ Instr::UnaryMinusReal i;
+ i.output = currentReg;
+ i.src = src;
gen(i);
} else if (e->expr->type == IR::IntType) {
convertToReal(e->expr, currentReg);
- i.uminus_real(currentReg, src);
+ Instr::UnaryMinusReal i;
+ i.output = currentReg;
+ i.src = src;
gen(i);
} else {
discard();
@@ -433,11 +446,15 @@ void QDeclarativeV4CompilerPrivate::visitUnop(IR::Unop *e)
case IR::OpUPlus:
if (e->expr->type == IR::RealType) {
- i.uplus_real(currentReg, src);
+ Instr::UnaryPlusReal i;
+ i.output = currentReg;
+ i.src = src;
gen(i);
} else if (e->expr->type == IR::IntType) {
convertToReal(e->expr, currentReg);
- i.uplus_real(currentReg, src);
+ Instr::UnaryPlusReal i;
+ i.output = currentReg;
+ i.src = src;
gen(i);
} else {
discard();
@@ -445,9 +462,8 @@ void QDeclarativeV4CompilerPrivate::visitUnop(IR::Unop *e)
break;
case IR::OpCompl:
- i.ucompl_real(currentReg, src);
- gen(i);
- discard(); // ???
+ // TODO
+ discard();
break;
case IR::OpBitAnd:
@@ -481,20 +497,18 @@ void QDeclarativeV4CompilerPrivate::convertToReal(IR::Expr *expr, int reg)
if (expr->type == IR::RealType)
return;
- Instr conv;
- conv.unaryop.output = reg;
- conv.unaryop.src = reg;
-
switch (expr->type) {
- case IR::BoolType:
- conv.common.type = Instr::ConvertBoolToReal;
- gen(conv);
- break;
+ case IR::BoolType: {
+ Instr::ConvertBoolToReal i;
+ i.output = i.src = reg;
+ gen(i);
+ } break;
- case IR::IntType:
- conv.common.type = Instr::ConvertIntToReal;
- gen(conv);
- break;
+ case IR::IntType: {
+ Instr::ConvertIntToReal i;
+ i.output = i.src = reg;
+ gen(i);
+ } break;
case IR::RealType:
// nothing to do
@@ -511,24 +525,22 @@ void QDeclarativeV4CompilerPrivate::convertToInt(IR::Expr *expr, int reg)
if (expr->type == IR::IntType)
return;
- Instr conv;
- conv.unaryop.output = reg;
- conv.unaryop.src = reg;
-
switch (expr->type) {
- case IR::BoolType:
- conv.common.type = Instr::ConvertBoolToInt;
- gen(conv);
- break;
+ case IR::BoolType: {
+ Instr::ConvertBoolToInt i;
+ i.output = i.src = reg;
+ gen(i);
+ } break;
case IR::IntType:
// nothing to do
return;
- case IR::RealType:
- conv.common.type = Instr::ConvertRealToInt;
- gen(conv);
- break;
+ case IR::RealType: {
+ Instr::ConvertRealToInt i;
+ i.output = i.src = reg;
+ gen(i);
+ } break;
default:
discard();
@@ -541,29 +553,28 @@ void QDeclarativeV4CompilerPrivate::convertToBool(IR::Expr *expr, int reg)
if (expr->type == IR::BoolType)
return;
- Instr conv;
- conv.unaryop.output = reg;
- conv.unaryop.src = reg;
-
switch (expr->type) {
case IR::BoolType:
// nothing to do
break;
- case IR::IntType:
- conv.common.type = Instr::ConvertIntToBool;
- gen(conv);
- break;
+ case IR::IntType: {
+ Instr::ConvertIntToBool i;
+ i.output = i.src = reg;
+ gen(i);
+ } break;
- case IR::RealType:
- conv.common.type = Instr::ConvertRealToBool;
- gen(conv);
- return;
+ case IR::RealType: {
+ Instr::ConvertRealToBool i;
+ i.output = i.src = reg;
+ gen(i);
+ } return;
- case IR::StringType:
- conv.common.type = Instr::ConvertStringToBool;
- gen(conv);
- return;
+ case IR::StringType: {
+ Instr::ConvertStringToBool i;
+ i.output = i.src = reg;
+ gen(i);
+ } return;
default:
discard();
@@ -575,97 +586,97 @@ quint8 QDeclarativeV4CompilerPrivate::instructionOpcode(IR::Binop *e)
{
switch (e->op) {
case IR::OpInvalid:
- return Instr::Noop;
+ return V4Instr::Noop;
case IR::OpIfTrue:
case IR::OpNot:
case IR::OpUMinus:
case IR::OpUPlus:
case IR::OpCompl:
- return Instr::Noop;
+ return V4Instr::Noop;
case IR::OpBitAnd:
- return Instr::BitAndInt;
+ return V4Instr::BitAndInt;
case IR::OpBitOr:
- return Instr::BitOrInt;
+ return V4Instr::BitOrInt;
case IR::OpBitXor:
- return Instr::BitXorInt;
+ return V4Instr::BitXorInt;
case IR::OpAdd:
if (e->type == IR::StringType)
- return Instr::AddString;
- return Instr::AddReal;
+ return V4Instr::AddString;
+ return V4Instr::AddReal;
case IR::OpSub:
- return Instr::SubReal;
+ return V4Instr::SubReal;
case IR::OpMul:
- return Instr::MulReal;
+ return V4Instr::MulReal;
case IR::OpDiv:
- return Instr::DivReal;
+ return V4Instr::DivReal;
case IR::OpMod:
- return Instr::ModReal;
+ return V4Instr::ModReal;
case IR::OpLShift:
- return Instr::LShiftInt;
+ return V4Instr::LShiftInt;
case IR::OpRShift:
- return Instr::RShiftInt;
+ return V4Instr::RShiftInt;
case IR::OpURShift:
- return Instr::URShiftInt;
+ return V4Instr::URShiftInt;
case IR::OpGt:
if (e->left->type == IR::StringType)
- return Instr::GtString;
- return Instr::GtReal;
+ return V4Instr::GtString;
+ return V4Instr::GtReal;
case IR::OpLt:
if (e->left->type == IR::StringType)
- return Instr::LtString;
- return Instr::LtReal;
+ return V4Instr::LtString;
+ return V4Instr::LtReal;
case IR::OpGe:
if (e->left->type == IR::StringType)
- return Instr::GeString;
- return Instr::GeReal;
+ return V4Instr::GeString;
+ return V4Instr::GeReal;
case IR::OpLe:
if (e->left->type == IR::StringType)
- return Instr::LeString;
- return Instr::LeReal;
+ return V4Instr::LeString;
+ return V4Instr::LeReal;
case IR::OpEqual:
if (e->left->type == IR::StringType)
- return Instr::EqualString;
- return Instr::EqualReal;
+ return V4Instr::EqualString;
+ return V4Instr::EqualReal;
case IR::OpNotEqual:
if (e->left->type == IR::StringType)
- return Instr::NotEqualString;
- return Instr::NotEqualReal;
+ return V4Instr::NotEqualString;
+ return V4Instr::NotEqualReal;
case IR::OpStrictEqual:
if (e->left->type == IR::StringType)
- return Instr::StrictEqualString;
- return Instr::StrictEqualReal;
+ return V4Instr::StrictEqualString;
+ return V4Instr::StrictEqualReal;
case IR::OpStrictNotEqual:
if (e->left->type == IR::StringType)
- return Instr::StrictNotEqualString;
- return Instr::StrictNotEqualReal;
+ return V4Instr::StrictNotEqualString;
+ return V4Instr::StrictNotEqualReal;
case IR::OpAnd:
case IR::OpOr:
- return Instr::Noop;
+ return V4Instr::Noop;
} // switch
- return Instr::Noop;
+ return V4Instr::Noop;
}
void QDeclarativeV4CompilerPrivate::visitBinop(IR::Binop *e)
@@ -754,13 +765,12 @@ void QDeclarativeV4CompilerPrivate::visitBinop(IR::Binop *e)
} // switch
const quint8 opcode = instructionOpcode(e);
- if (opcode != Instr::Noop) {
- Instr instr;
- instr.common.type = opcode;
+ if (opcode != V4Instr::Noop) {
+ V4Instr instr;
instr.binaryop.output = currentReg;
instr.binaryop.left = left;
instr.binaryop.right = right;
- gen(instr);
+ gen(static_cast<V4Instr::Type>(opcode), instr);
}
}
@@ -771,37 +781,37 @@ void QDeclarativeV4CompilerPrivate::visitCall(IR::Call *call)
if (arg != 0 && arg->type == IR::RealType) {
traceExpression(arg, currentReg);
- Instr instr;
- instr.common.type = Instr::Noop;
-
switch (name->builtin) {
case IR::NoBuiltinSymbol:
break;
- case IR::MathSinBultinFunction:
- instr.math_sin_real(currentReg);
- break;
-
- case IR::MathCosBultinFunction:
- instr.math_cos_real(currentReg);
- break;
-
- case IR::MathRoundBultinFunction:
- instr.math_round_real(currentReg);
- break;
-
- case IR::MathFloorBultinFunction:
- instr.math_floor_real(currentReg);
- break;
+ case IR::MathSinBultinFunction: {
+ Instr::MathSinReal i;
+ i.output = i.src = currentReg;
+ gen(i);
+ } return;
+
+ case IR::MathCosBultinFunction: {
+ Instr::MathCosReal i;
+ i.output = i.src = currentReg;
+ gen(i);
+ } return;
+
+ case IR::MathRoundBultinFunction: {
+ Instr::MathRoundReal i;
+ i.output = i.src = currentReg;
+ gen(i);
+ } return;
+
+ case IR::MathFloorBultinFunction: {
+ Instr::MathFloorReal i;
+ i.output = i.src = currentReg;
+ gen(i);
+ } return;
case IR::MathPIBuiltinConstant:
break;
} // switch
-
- if (instr.common.type != Instr::Noop) {
- gen(instr);
- return;
- }
}
}
@@ -834,47 +844,47 @@ void QDeclarativeV4CompilerPrivate::visitMove(IR::Move *s)
else
traceExpression(s->source, dest);
- Instr conv;
- conv.common.type = Instr::Noop;
+ V4Instr::Type opcode = V4Instr::Noop;
if (target->type == IR::BoolType) {
switch (s->source->type) {
- case IR::IntType: conv.common.type = Instr::ConvertIntToBool; break;
- case IR::RealType: conv.common.type = Instr::ConvertRealToBool; break;
- case IR::StringType: conv.common.type = Instr::ConvertStringToBool; break;
+ case IR::IntType: opcode = V4Instr::ConvertIntToBool; break;
+ case IR::RealType: opcode = V4Instr::ConvertRealToBool; break;
+ case IR::StringType: opcode = V4Instr::ConvertStringToBool; break;
default: break;
} // switch
} else if (target->type == IR::IntType) {
switch (s->source->type) {
- case IR::BoolType: conv.common.type = Instr::ConvertBoolToInt; break;
+ case IR::BoolType: opcode = V4Instr::ConvertBoolToInt; break;
case IR::RealType: {
if (s->isMoveForReturn)
- conv.common.type = Instr::MathRoundReal;
+ opcode = V4Instr::MathRoundReal;
else
- conv.common.type = Instr::ConvertRealToInt;
+ opcode = V4Instr::ConvertRealToInt;
break;
}
- case IR::StringType: conv.common.type = Instr::ConvertStringToInt; break;
+ case IR::StringType: opcode = V4Instr::ConvertStringToInt; break;
default: break;
} // switch
} else if (target->type == IR::RealType) {
switch (s->source->type) {
- case IR::BoolType: conv.common.type = Instr::ConvertBoolToReal; break;
- case IR::IntType: conv.common.type = Instr::ConvertIntToReal; break;
- case IR::StringType: conv.common.type = Instr::ConvertStringToReal; break;
+ case IR::BoolType: opcode = V4Instr::ConvertBoolToReal; break;
+ case IR::IntType: opcode = V4Instr::ConvertIntToReal; break;
+ case IR::StringType: opcode = V4Instr::ConvertStringToReal; break;
default: break;
} // switch
} else if (target->type == IR::StringType) {
switch (s->source->type) {
- case IR::BoolType: conv.common.type = Instr::ConvertBoolToString; break;
- case IR::IntType: conv.common.type = Instr::ConvertIntToString; break;
- case IR::RealType: conv.common.type = Instr::ConvertRealToString; break;
+ case IR::BoolType: opcode = V4Instr::ConvertBoolToString; break;
+ case IR::IntType: opcode = V4Instr::ConvertIntToString; break;
+ case IR::RealType: opcode = V4Instr::ConvertRealToString; break;
default: break;
} // switch
}
- if (conv.common.type != Instr::Noop) {
+ if (opcode != V4Instr::Noop) {
+ V4Instr conv;
conv.unaryop.output = dest;
conv.unaryop.src = src;
- gen(conv);
+ gen(opcode, conv);
} else {
discard();
}
@@ -887,8 +897,8 @@ void QDeclarativeV4CompilerPrivate::visitJump(IR::Jump *s)
{
patches.append(Patch(s->target, bytecode.size()));
- Instr i;
- i.branch(0); // ### backpatch
+ Instr::Branch i;
+ i.offset = 0; // ### backpatch
gen(i);
}
@@ -898,8 +908,9 @@ void QDeclarativeV4CompilerPrivate::visitCJump(IR::CJump *s)
patches.append(Patch(s->iftrue, bytecode.size()));
- Instr i;
- i.branch_true(currentReg, 0); // ### backpatch
+ Instr::BranchTrue i;
+ i.reg = currentReg;
+ i.offset = 0; // ### backpatch
gen(i);
}
@@ -916,33 +927,32 @@ void QDeclarativeV4CompilerPrivate::visitRet(IR::Ret *s)
}
if (qmlBindingsTest) {
- Instr test;
- test.common.type = Instr::TestV4Store;
- test.storetest.reg = storeReg;
+ Instr::TestV4Store test;
+ test.reg = storeReg;
switch (s->type) {
case IR::StringType:
- test.storetest.regType = QMetaType::QString;
+ test.regType = QMetaType::QString;
break;
case IR::UrlType:
- test.storetest.regType = QMetaType::QUrl;
+ test.regType = QMetaType::QUrl;
break;
case IR::AnchorLineType:
- test.storetest.regType = qMetaTypeId<QDeclarative1AnchorLine>();
+ test.regType = qMetaTypeId<QDeclarative1AnchorLine>();
break;
case IR::SGAnchorLineType:
- test.storetest.regType = qMetaTypeId<QSGAnchorLine>();
+ test.regType = qMetaTypeId<QSGAnchorLine>();
break;
case IR::ObjectType:
- test.storetest.regType = QMetaType::QObjectStar;
+ test.regType = QMetaType::QObjectStar;
break;
case IR::BoolType:
- test.storetest.regType = QMetaType::Bool;
+ test.regType = QMetaType::Bool;
break;
case IR::IntType:
- test.storetest.regType = QMetaType::Int;
+ test.regType = QMetaType::Int;
break;
case IR::RealType:
- test.storetest.regType = QMetaType::QReal;
+ test.regType = QMetaType::QReal;
break;
default:
discard();
@@ -951,12 +961,11 @@ void QDeclarativeV4CompilerPrivate::visitRet(IR::Ret *s)
gen(test);
}
- Instr store;
- store.common.type = Instr::Store;
- store.store.output = 0;
- store.store.index = expression->property->index;
- store.store.reg = storeReg;
- store.store.exceptionId = exceptionId(s->line, s->column);
+ Instr::Store store;
+ store.output = 0;
+ store.index = expression->property->index;
+ store.reg = storeReg;
+ store.exceptionId = exceptionId(s->line, s->column);
gen(store);
}
@@ -971,13 +980,9 @@ void QDeclarativeV4Compiler::dump(const QByteArray &programData)
const int programSize = program->instructionCount;
const char *start = program->instructions();
- const char *code = start;
- const char *end = code + programSize;
- while (code < end) {
- Instr *instr = (Instr *) code;
- instr->dump(code - start);
- code += instr->size();
- }
+ const char *end = start + programSize;
+ Bytecode bc;
+ bc.dump(start, end);
}
/*!
@@ -1079,11 +1084,10 @@ int QDeclarativeV4CompilerPrivate::registerLiteralString(quint8 reg, const QStri
int offset = data.count();
data += strdata;
- Instr string;
- string.common.type = Instr::String;
- string.string_value.reg = reg;
- string.string_value.offset = offset;
- string.string_value.length = str.length();
+ Instr::LoadString string;
+ string.reg = reg;
+ string.offset = offset;
+ string.length = str.length();
gen(string);
return reg;
@@ -1108,12 +1112,11 @@ int QDeclarativeV4CompilerPrivate::registerString(const QString &string)
*iter = qMakePair(registeredStrings.count(), rv);
}
- Instr reg;
- reg.common.type = Instr::InitString;
- reg.initstring.offset = iter->first;
- reg.initstring.dataIdx = iter->second;
+ Instr::InitString reg;
+ reg.offset = iter->first;
+ reg.dataIdx = iter->second;
gen(reg);
- return reg.initstring.offset;
+ return reg.offset;
}
/*!
@@ -1275,14 +1278,13 @@ QByteArray QDeclarativeV4Compiler::program() const
prog.bindings = d->committed.count();
Bytecode bc;
- Instr jump;
- jump.common.type = Instr::Jump;
- jump.jump.reg = -1;
+ QDeclarativeV4CompilerPrivate::Instr::Jump jump;
+ jump.reg = -1;
for (int ii = 0; ii < d->committed.count(); ++ii) {
- jump.jump.count = d->committed.count() - ii - 1;
- jump.jump.count*= jump.size();
- jump.jump.count+= d->committed.offsets.at(ii);
+ jump.count = d->committed.count() - ii - 1;
+ jump.count*= V4InstrMeta<V4Instr::Jump>::Size;
+ jump.count+= d->committed.offsets.at(ii);
bc.append(jump);
}
diff --git a/src/declarative/qml/v4/qdeclarativev4compiler_p_p.h b/src/declarative/qml/v4/qdeclarativev4compiler_p_p.h
index eab609a45d..aba713b916 100644
--- a/src/declarative/qml/v4/qdeclarativev4compiler_p_p.h
+++ b/src/declarative/qml/v4/qdeclarativev4compiler_p_p.h
@@ -209,8 +209,15 @@ public:
void convertToBool(QDeclarativeJS::IR::Expr *expr, int reg);
quint8 instructionOpcode(QDeclarativeJS::IR::Binop *e);
-protected:
+ struct Instr {
+#define QML_V4_INSTR_DATA_TYPEDEF(I, FMT) typedef QDeclarativeJS::V4InstrData<QDeclarativeJS::V4Instr::I> I;
+ FOR_EACH_V4_INSTR(QML_V4_INSTR_DATA_TYPEDEF)
+#undef QML_v4_INSTR_DATA_TYPEDEF
+ private:
+ Instr();
+ };
+protected:
//
// tracing
//
@@ -218,7 +225,14 @@ protected:
void trace(QVector<QDeclarativeJS::IR::BasicBlock *> *blocks);
void traceExpression(QDeclarativeJS::IR::Expr *e, quint8 r);
- inline void gen(const QDeclarativeJS::Instr &i) { bytecode.append(i); }
+ template <int Instr>
+ inline void gen(const QDeclarativeJS::V4InstrData<Instr> &i)
+ { bytecode.append(i); }
+ inline void gen(QDeclarativeJS::V4Instr::Type type, QDeclarativeJS::V4Instr &instr)
+ { bytecode.append(type, instr); }
+
+ inline QDeclarativeJS::V4Instr::Type instructionType(const QDeclarativeJS::V4Instr *i) const
+ { return bytecode.instructionType(i); }
//
// expressions
diff --git a/src/declarative/qml/v4/qdeclarativev4instruction.cpp b/src/declarative/qml/v4/qdeclarativev4instruction.cpp
index dd6892369b..6ae28f91da 100644
--- a/src/declarative/qml/v4/qdeclarativev4instruction.cpp
+++ b/src/declarative/qml/v4/qdeclarativev4instruction.cpp
@@ -52,30 +52,33 @@
QT_BEGIN_NAMESPACE
-DEFINE_BOOL_CONFIG_OPTION(qmlVerboseCompiler, QML_VERBOSE_COMPILER)
-
namespace QDeclarativeJS {
#ifdef DEBUG_INSTR_DUMP
static struct DumpInstrAtStartup {
DumpInstrAtStartup() {
-#define DUMP_INSTR_AT_STARTUP(Type, FMT) { Instr i; i.common.type = Instr::Type; i.dump(0); }
+ Bytecode bc;
+#define DUMP_INSTR_AT_STARTUP(I, FMT) { V4InstrData<V4Instr::I> i; bc.append(i); }
FOR_EACH_V4_INSTR(DUMP_INSTR_AT_STARTUP);
+#undef DUMP_INSTR_AT_STARTUP
+ const char *start = bc.constData();
+ const char *end = start + bc.size();
+ bc.dump(start, end);
}
} dump_instr_at_startup;
#endif
-int Instr::size() const
+int V4Instr::size(Type type)
{
#define V4_RETURN_INSTR_SIZE(I, FMT) case I: return QML_V4_INSTR_SIZE(I, FMT);
- switch (common.type) {
+ switch (type) {
FOR_EACH_V4_INSTR(V4_RETURN_INSTR_SIZE)
}
#undef V4_RETURN_INSTR_SIZE
return 0;
}
-void Instr::dump(int address) const
+void Bytecode::dump(const V4Instr *i, int address) const
{
QByteArray leading;
if (address != -1) {
@@ -86,241 +89,241 @@ void Instr::dump(int address) const
#define INSTR_DUMP qWarning().nospace() << leading.constData()
- switch (common.type) {
- case Instr::Noop:
+ switch (instructionType(i)) {
+ case V4Instr::Noop:
INSTR_DUMP << "\t" << "Noop";
break;
- case Instr::BindingId:
- INSTR_DUMP << id.line << ":" << id.column << ":";
+ case V4Instr::BindingId:
+ INSTR_DUMP << i->id.line << ":" << i->id.column << ":";
break;
- case Instr::Subscribe:
- INSTR_DUMP << "\t" << "Subscribe" << "\t\t" << "Object_Reg(" << subscribeop.reg << ") Notify_Signal(" << subscribeop.index << ") -> Subscribe_Slot(" << subscribeop.offset << ")";
+ case V4Instr::Subscribe:
+ INSTR_DUMP << "\t" << "Subscribe" << "\t\t" << "Object_Reg(" << i->subscribeop.reg << ") Notify_Signal(" << i->subscribeop.index << ") -> Subscribe_Slot(" << i->subscribeop.offset << ")";
break;
- case Instr::SubscribeId:
- INSTR_DUMP << "\t" << "SubscribeId" << "\t\t" << "Id_Offset(" << subscribeop.index << ") -> Subscribe_Slot(" << subscribeop.offset << ")";
+ case V4Instr::SubscribeId:
+ INSTR_DUMP << "\t" << "SubscribeId" << "\t\t" << "Id_Offset(" << i->subscribeop.index << ") -> Subscribe_Slot(" << i->subscribeop.offset << ")";
break;
- case Instr::FetchAndSubscribe:
- INSTR_DUMP << "\t" << "FetchAndSubscribe" << "\t" << "Object_Reg(" << fetchAndSubscribe.reg << ") Fast_Accessor(" << fetchAndSubscribe.function << ") -> Output_Reg(" << fetchAndSubscribe.reg << ") Subscription_Slot(" << fetchAndSubscribe.subscription << ")";
+ case V4Instr::FetchAndSubscribe:
+ INSTR_DUMP << "\t" << "FetchAndSubscribe" << "\t" << "Object_Reg(" << i->fetchAndSubscribe.reg << ") Fast_Accessor(" << i->fetchAndSubscribe.function << ") -> Output_Reg(" << i->fetchAndSubscribe.reg << ") Subscription_Slot(" << i->fetchAndSubscribe.subscription << ")";
break;
- case Instr::LoadId:
- INSTR_DUMP << "\t" << "LoadId" << "\t\t\t" << "Id_Offset(" << load.index << ") -> Output_Reg(" << load.reg << ")";
+ case V4Instr::LoadId:
+ INSTR_DUMP << "\t" << "LoadId" << "\t\t\t" << "Id_Offset(" << i->load.index << ") -> Output_Reg(" << i->load.reg << ")";
break;
- case Instr::LoadScope:
- INSTR_DUMP << "\t" << "LoadScope" << "\t\t" << "-> Output_Reg(" << load.reg << ")";
+ case V4Instr::LoadScope:
+ INSTR_DUMP << "\t" << "LoadScope" << "\t\t" << "-> Output_Reg(" << i->load.reg << ")";
break;
- case Instr::LoadRoot:
- INSTR_DUMP << "\t" << "LoadRoot" << "\t\t" << "-> Output_Reg(" << load.reg << ")";
+ case V4Instr::LoadRoot:
+ INSTR_DUMP << "\t" << "LoadRoot" << "\t\t" << "-> Output_Reg(" << i->load.reg << ")";
break;
- case Instr::LoadAttached:
- INSTR_DUMP << "\t" << "LoadAttached" << "\t\t" << "Object_Reg(" << attached.reg << ") Attached_Index(" << attached.id << ") -> Output_Reg(" << attached.output << ")";
+ case V4Instr::LoadAttached:
+ INSTR_DUMP << "\t" << "LoadAttached" << "\t\t" << "Object_Reg(" << i->attached.reg << ") Attached_Index(" << i->attached.id << ") -> Output_Reg(" << i->attached.output << ")";
break;
- case Instr::UnaryNot:
- INSTR_DUMP << "\t" << "UnaryNot" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
+ case V4Instr::UnaryNot:
+ INSTR_DUMP << "\t" << "UnaryNot" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case Instr::UnaryMinusReal:
- INSTR_DUMP << "\t" << "UnaryMinusReal" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
+ case V4Instr::UnaryMinusReal:
+ INSTR_DUMP << "\t" << "UnaryMinusReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case Instr::UnaryMinusInt:
- INSTR_DUMP << "\t" << "UnaryMinusInt" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
+ case V4Instr::UnaryMinusInt:
+ INSTR_DUMP << "\t" << "UnaryMinusInt" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case Instr::UnaryPlusReal:
- INSTR_DUMP << "\t" << "UnaryPlusReal" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
+ case V4Instr::UnaryPlusReal:
+ INSTR_DUMP << "\t" << "UnaryPlusReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case Instr::UnaryPlusInt:
- INSTR_DUMP << "\t" << "UnaryPlusInt" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
+ case V4Instr::UnaryPlusInt:
+ INSTR_DUMP << "\t" << "UnaryPlusInt" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case Instr::ConvertBoolToInt:
- INSTR_DUMP << "\t" << "ConvertBoolToInt" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
+ case V4Instr::ConvertBoolToInt:
+ INSTR_DUMP << "\t" << "ConvertBoolToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case Instr::ConvertBoolToReal:
- INSTR_DUMP << "\t" << "ConvertBoolToReal" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
+ case V4Instr::ConvertBoolToReal:
+ INSTR_DUMP << "\t" << "ConvertBoolToReal" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case Instr::ConvertBoolToString:
- INSTR_DUMP << "\t" << "ConvertBoolToString" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
+ case V4Instr::ConvertBoolToString:
+ INSTR_DUMP << "\t" << "ConvertBoolToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case Instr::ConvertIntToBool:
- INSTR_DUMP << "\t" << "ConvertIntToBool" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
+ case V4Instr::ConvertIntToBool:
+ INSTR_DUMP << "\t" << "ConvertIntToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case Instr::ConvertIntToReal:
- INSTR_DUMP << "\t" << "ConvertIntToReal" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
+ case V4Instr::ConvertIntToReal:
+ INSTR_DUMP << "\t" << "ConvertIntToReal" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case Instr::ConvertIntToString:
- INSTR_DUMP << "\t" << "ConvertIntToString" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
+ case V4Instr::ConvertIntToString:
+ INSTR_DUMP << "\t" << "ConvertIntToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case Instr::ConvertRealToBool:
- INSTR_DUMP << "\t" << "ConvertRealToBool" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
+ case V4Instr::ConvertRealToBool:
+ INSTR_DUMP << "\t" << "ConvertRealToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case Instr::ConvertRealToInt:
- INSTR_DUMP << "\t" << "ConvertRealToInt" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
+ case V4Instr::ConvertRealToInt:
+ INSTR_DUMP << "\t" << "ConvertRealToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case Instr::ConvertRealToString:
- INSTR_DUMP << "\t" << "ConvertRealToString" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
+ case V4Instr::ConvertRealToString:
+ INSTR_DUMP << "\t" << "ConvertRealToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case Instr::ConvertStringToBool:
- INSTR_DUMP << "\t" << "ConvertStringToBool" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
+ case V4Instr::ConvertStringToBool:
+ INSTR_DUMP << "\t" << "ConvertStringToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case Instr::ConvertStringToInt:
- INSTR_DUMP << "\t" << "ConvertStringToInt" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
+ case V4Instr::ConvertStringToInt:
+ INSTR_DUMP << "\t" << "ConvertStringToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case Instr::ConvertStringToReal:
- INSTR_DUMP << "\t" << "ConvertStringToReal" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
+ case V4Instr::ConvertStringToReal:
+ INSTR_DUMP << "\t" << "ConvertStringToReal" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case Instr::MathSinReal:
- INSTR_DUMP << "\t" << "MathSinReal" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
+ case V4Instr::MathSinReal:
+ INSTR_DUMP << "\t" << "MathSinReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case Instr::MathCosReal:
- INSTR_DUMP << "\t" << "MathCosReal" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
+ case V4Instr::MathCosReal:
+ INSTR_DUMP << "\t" << "MathCosReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case Instr::MathRoundReal:
- INSTR_DUMP << "\t" << "MathRoundReal" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
+ case V4Instr::MathRoundReal:
+ INSTR_DUMP << "\t" << "MathRoundReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case Instr::MathFloorReal:
- INSTR_DUMP << "\t" << "MathFloorReal" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
+ case V4Instr::MathFloorReal:
+ INSTR_DUMP << "\t" << "MathFloorReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case Instr::MathPIReal:
- INSTR_DUMP << "\t" << "MathPIReal" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
+ case V4Instr::MathPIReal:
+ INSTR_DUMP << "\t" << "MathPIReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case Instr::Real:
- INSTR_DUMP << "\t" << "Real" << "\t\t\t" << "Constant(" << real_value.value << ") -> Output_Reg(" << real_value.reg << ")";
+ case V4Instr::LoadReal:
+ INSTR_DUMP << "\t" << "LoadReal" << "\t\t" << "Constant(" << i->real_value.value << ") -> Output_Reg(" << i->real_value.reg << ")";
break;
- case Instr::Int:
- INSTR_DUMP << "\t" << "Int" << "\t\t\t" << "Constant(" << int_value.value << ") -> Output_Reg(" << int_value.reg << ")";
+ case V4Instr::LoadInt:
+ INSTR_DUMP << "\t" << "LoadInt" << "\t\t\t" << "Constant(" << i->int_value.value << ") -> Output_Reg(" << i->int_value.reg << ")";
break;
- case Instr::Bool:
- INSTR_DUMP << "\t" << "Bool" << "\t\t\t" << "Constant(" << bool_value.value << ") -> Output_Reg(" << bool_value.reg << ")";
+ case V4Instr::LoadBool:
+ INSTR_DUMP << "\t" << "LoadBool" << "\t\t" << "Constant(" << i->bool_value.value << ") -> Output_Reg(" << i->bool_value.reg << ")";
break;
- case Instr::String:
- INSTR_DUMP << "\t" << "String" << "\t\t\t" << "String_DataIndex(" << string_value.offset << ") String_Length(" << string_value.length << ") -> Output_Register(" << string_value.reg << ")";
+ case V4Instr::LoadString:
+ INSTR_DUMP << "\t" << "LoadString" << "\t\t" << "String_DataIndex(" << i->string_value.offset << ") String_Length(" << i->string_value.length << ") -> Output_Register(" << i->string_value.reg << ")";
break;
- case Instr::EnableV4Test:
- INSTR_DUMP << "\t" << "EnableV4Test" << "\t\t" << "String_DataIndex(" << string_value.offset << ") String_Length(" << string_value.length << ")";
+ case V4Instr::EnableV4Test:
+ INSTR_DUMP << "\t" << "EnableV4Test" << "\t\t" << "String_DataIndex(" << i->string_value.offset << ") String_Length(" << i->string_value.length << ")";
break;
- case Instr::TestV4Store:
- INSTR_DUMP << "\t" << "TestV4Store" << "\t\t" << "Input_Reg(" << storetest.reg << ") Reg_Type(" << storetest.regType << ")";
+ case V4Instr::TestV4Store:
+ INSTR_DUMP << "\t" << "TestV4Store" << "\t\t" << "Input_Reg(" << i->storetest.reg << ") Reg_Type(" << i->storetest.regType << ")";
break;
- case Instr::BitAndInt:
- INSTR_DUMP << "\t" << "BitAndInt" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::BitAndInt:
+ INSTR_DUMP << "\t" << "BitAndInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::BitOrInt:
- INSTR_DUMP << "\t" << "BitOrInt" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::BitOrInt:
+ INSTR_DUMP << "\t" << "BitOrInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::BitXorInt:
- INSTR_DUMP << "\t" << "BitXorInt" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::BitXorInt:
+ INSTR_DUMP << "\t" << "BitXorInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::AddReal:
- INSTR_DUMP << "\t" << "AddReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::AddReal:
+ INSTR_DUMP << "\t" << "AddReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::AddString:
- INSTR_DUMP << "\t" << "AddString" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::AddString:
+ INSTR_DUMP << "\t" << "AddString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::SubReal:
- INSTR_DUMP << "\t" << "SubReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::SubReal:
+ INSTR_DUMP << "\t" << "SubReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::MulReal:
- INSTR_DUMP << "\t" << "MulReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::MulReal:
+ INSTR_DUMP << "\t" << "MulReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::DivReal:
- INSTR_DUMP << "\t" << "DivReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::DivReal:
+ INSTR_DUMP << "\t" << "DivReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::ModReal:
- INSTR_DUMP << "\t" << "ModReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::ModReal:
+ INSTR_DUMP << "\t" << "ModReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::LShiftInt:
- INSTR_DUMP << "\t" << "LShiftInt" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::LShiftInt:
+ INSTR_DUMP << "\t" << "LShiftInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::RShiftInt:
- INSTR_DUMP << "\t" << "RShiftInt" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::RShiftInt:
+ INSTR_DUMP << "\t" << "RShiftInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::URShiftInt:
- INSTR_DUMP << "\t" << "URShiftInt" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::URShiftInt:
+ INSTR_DUMP << "\t" << "URShiftInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::GtReal:
- INSTR_DUMP << "\t" << "GtReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::GtReal:
+ INSTR_DUMP << "\t" << "GtReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::LtReal:
- INSTR_DUMP << "\t" << "LtReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::LtReal:
+ INSTR_DUMP << "\t" << "LtReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::GeReal:
- INSTR_DUMP << "\t" << "GeReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::GeReal:
+ INSTR_DUMP << "\t" << "GeReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::LeReal:
- INSTR_DUMP << "\t" << "LeReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::LeReal:
+ INSTR_DUMP << "\t" << "LeReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::EqualReal:
- INSTR_DUMP << "\t" << "EqualReal" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::EqualReal:
+ INSTR_DUMP << "\t" << "EqualReal" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::NotEqualReal:
- INSTR_DUMP << "\t" << "NotEqualReal" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::NotEqualReal:
+ INSTR_DUMP << "\t" << "NotEqualReal" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::StrictEqualReal:
- INSTR_DUMP << "\t" << "StrictEqualReal" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::StrictEqualReal:
+ INSTR_DUMP << "\t" << "StrictEqualReal" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::StrictNotEqualReal:
- INSTR_DUMP << "\t" << "StrictNotEqualReal" << "\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::StrictNotEqualReal:
+ INSTR_DUMP << "\t" << "StrictNotEqualReal" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::GtString:
- INSTR_DUMP << "\t" << "GtString" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::GtString:
+ INSTR_DUMP << "\t" << "GtString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::LtString:
- INSTR_DUMP << "\t" << "LtString" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::LtString:
+ INSTR_DUMP << "\t" << "LtString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::GeString:
- INSTR_DUMP << "\t" << "GeString" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::GeString:
+ INSTR_DUMP << "\t" << "GeString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::LeString:
- INSTR_DUMP << "\t" << "LeString" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::LeString:
+ INSTR_DUMP << "\t" << "LeString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::EqualString:
- INSTR_DUMP << "\t" << "EqualString" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::EqualString:
+ INSTR_DUMP << "\t" << "EqualString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::NotEqualString:
- INSTR_DUMP << "\t" << "NotEqualString" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::NotEqualString:
+ INSTR_DUMP << "\t" << "NotEqualString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::StrictEqualString:
- INSTR_DUMP << "\t" << "StrictEqualString" << "\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::StrictEqualString:
+ INSTR_DUMP << "\t" << "StrictEqualString" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::StrictNotEqualString:
- INSTR_DUMP << "\t" << "StrictNotEqualString" << "\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
+ case V4Instr::StrictNotEqualString:
+ INSTR_DUMP << "\t" << "StrictNotEqualString" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case Instr::NewString:
- INSTR_DUMP << "\t" << "NewString" << "\t\t" << "Register(" << construct.reg << ")";
+ case V4Instr::NewString:
+ INSTR_DUMP << "\t" << "NewString" << "\t\t" << "Register(" << i->construct.reg << ")";
break;
- case Instr::NewUrl:
- INSTR_DUMP << "\t" << "NewUrl" << "\t\t\t" << "Register(" << construct.reg << ")";
+ case V4Instr::NewUrl:
+ INSTR_DUMP << "\t" << "NewUrl" << "\t\t\t" << "Register(" << i->construct.reg << ")";
break;
- case Instr::CleanupRegister:
- INSTR_DUMP << "\t" << "CleanupRegister" << "\t\t" << "Register(" << cleanup.reg << ")";
+ case V4Instr::CleanupRegister:
+ INSTR_DUMP << "\t" << "CleanupRegister" << "\t\t" << "Register(" << i->cleanup.reg << ")";
break;
- case Instr::Fetch:
- INSTR_DUMP << "\t" << "Fetch" << "\t\t\t" << "Object_Reg(" << fetch.reg << ") Property_Index(" << fetch.index << ") -> Output_Reg(" << fetch.reg << ")";
+ case V4Instr::Fetch:
+ INSTR_DUMP << "\t" << "Fetch" << "\t\t\t" << "Object_Reg(" << i->fetch.reg << ") Property_Index(" << i->fetch.index << ") -> Output_Reg(" << i->fetch.reg << ")";
break;
- case Instr::Store:
- INSTR_DUMP << "\t" << "Store" << "\t\t\t" << "Input_Reg(" << store.reg << ") -> Object_Reg(" << store.output << ") Property_Index(" << store.index << ")";
+ case V4Instr::Store:
+ INSTR_DUMP << "\t" << "Store" << "\t\t\t" << "Input_Reg(" << i->store.reg << ") -> Object_Reg(" << i->store.output << ") Property_Index(" << i->store.index << ")";
break;
- case Instr::Copy:
- INSTR_DUMP << "\t" << "Copy" << "\t\t\t" << "Input_Reg(" << copy.src << ") -> Output_Reg(" << copy.reg << ")";
+ case V4Instr::Copy:
+ INSTR_DUMP << "\t" << "Copy" << "\t\t\t" << "Input_Reg(" << i->copy.src << ") -> Output_Reg(" << i->copy.reg << ")";
break;
- case Instr::Jump:
- if (jump.reg != -1) {
- INSTR_DUMP << "\t" << "Jump" << "\t\t\t" << "Address(" << (address + size() + jump.count) << ") [if false == Input_Reg(" << jump.reg << ")]";
+ case V4Instr::Jump:
+ if (i->jump.reg != -1) {
+ INSTR_DUMP << "\t" << "Jump" << "\t\t\t" << "Address(" << (address + size() + i->jump.count) << ") [if false == Input_Reg(" << i->jump.reg << ")]";
} else {
- INSTR_DUMP << "\t" << "Jump" << "\t\t\t" << "Address(" << (address + size() + jump.count) << ")";
+ INSTR_DUMP << "\t" << "Jump" << "\t\t\t" << "Address(" << (address + size() + i->jump.count) << ")";
}
break;
- case Instr::BranchFalse:
- INSTR_DUMP << "\t" << "BranchFalse" << "\t\t" << "Address(" << (address + size() + branchop.offset) << ") [if false == Input_Reg(" << branchop.reg << ")]";
+ case V4Instr::BranchFalse:
+ INSTR_DUMP << "\t" << "BranchFalse" << "\t\t" << "Address(" << (address + size() + i->branchop.offset) << ") [if false == Input_Reg(" << i->branchop.reg << ")]";
break;
- case Instr::BranchTrue:
- INSTR_DUMP << "\t" << "BranchTrue" << "\t\t" << "Address(" << (address + size() + branchop.offset) << ") [if true == Input_Reg(" << branchop.reg << ")]";
+ case V4Instr::BranchTrue:
+ INSTR_DUMP << "\t" << "BranchTrue" << "\t\t" << "Address(" << (address + size() + i->branchop.offset) << ") [if true == Input_Reg(" << i->branchop.reg << ")]";
break;
- case Instr::Branch:
- INSTR_DUMP << "\t" << "Branch" << "\t\t\t" << "Address(" << (address + size() + branchop.offset) << ")";
+ case V4Instr::Branch:
+ INSTR_DUMP << "\t" << "Branch" << "\t\t\t" << "Address(" << (address + size() + i->branchop.offset) << ")";
break;
- case Instr::InitString:
- INSTR_DUMP << "\t" << "InitString" << "\t\t" << "String_DataIndex(" << initstring.dataIdx << ") -> String_Slot(" << initstring.offset << ")";
+ case V4Instr::InitString:
+ INSTR_DUMP << "\t" << "InitString" << "\t\t" << "String_DataIndex(" << i->initstring.dataIdx << ") -> String_Slot(" << i->initstring.offset << ")";
break;
- case Instr::Block:
- INSTR_DUMP << "\t" << "Block" << "\t\t\t" << "Mask(" << QByteArray::number(blockop.block, 16).constData() << ")";
+ case V4Instr::Block:
+ INSTR_DUMP << "\t" << "Block" << "\t\t\t" << "Mask(" << QByteArray::number(i->blockop.block, 16).constData() << ")";
break;
default:
INSTR_DUMP << "\t" << "Unknown";
@@ -328,224 +331,68 @@ void Instr::dump(int address) const
}
}
-void Instr::noop()
-{
- common.type = Noop;
-}
-
-void Instr::load_root(quint8 reg)
-{
- common.type = LoadRoot;
- load.reg = reg;
- load.index = 0;
-}
-
-void Instr::load_scope(quint8 reg)
-{
- common.type = LoadScope;
- load.reg = reg;
- load.index = 0;
-}
-
-void Instr::load_id(quint8 reg, quint32 idIndex)
-{
- common.type = LoadId;
- load.reg = reg;
- load.index = idIndex;
-}
-
-void Instr::subscribe(qint8 reg, quint16 subscribeSlot, quint32 notifyIndex)
-{
- common.type = Instr::Subscribe;
- subscribeop.reg = reg;
- subscribeop.offset = subscribeSlot;
- subscribeop.index = notifyIndex;
-}
-
-void Instr::subscribeId(qint8 reg, quint16 subscribeSlot, quint32 idIndex)
-{
- common.type = Instr::SubscribeId;
- subscribeop.reg = reg;
- subscribeop.offset = subscribeSlot;
- subscribeop.index = idIndex;
-}
-
-void Instr::move_reg_bool(quint8 reg, bool value)
-{
- common.type = Bool;
- bool_value.reg = reg;
- bool_value.value = value;
-}
-
-void Instr::move_reg_int(quint8 reg, int value)
-{
- common.type = Int;
- int_value.reg = reg;
- int_value.value = value;
-}
-
-void Instr::move_reg_qreal(quint8 reg, qreal value)
-{
- common.type = Real;
- real_value.reg = reg;
- real_value.value = value;
-}
-
-void Instr::move_reg_reg(quint8 reg, quint8 src)
-{
- common.type = Copy;
- copy.reg = reg;
- copy.src = src;
-}
-
-void Instr::unary_not(quint8 dest, quint8 src)
-{
- common.type = UnaryNot;
- unaryop.src = src;
- unaryop.output = dest;
-}
-
-void Instr::uminus_real(quint8 dest, quint8 src)
-{
- common.type = UnaryMinusReal;
- unaryop.src = src;
- unaryop.output = dest;
-}
-
-void Instr::uminus_int(quint8 dest, quint8 src)
-{
- common.type = UnaryMinusInt;
- unaryop.src = src;
- unaryop.output = dest;
-}
-
-void Instr::uplus_real(quint8 dest, quint8 src)
-{
- common.type = UnaryPlusReal;
- unaryop.src = src;
- unaryop.output = dest;
-}
-
-void Instr::uplus_int(quint8 dest, quint8 src)
-{
- common.type = UnaryPlusInt;
- unaryop.src = src;
- unaryop.output = dest;
-}
-
-void Instr::ucompl_real(quint8 dest, quint8 src)
-{
- Q_UNUSED(dest);
- Q_UNUSED(src);
- if (qmlVerboseCompiler())
- qWarning() << "TODO" << Q_FUNC_INFO;
-}
-
-void Instr::ucompl_int(quint8 dest, quint8 src)
-{
- Q_UNUSED(dest);
- Q_UNUSED(src);
- if (qmlVerboseCompiler())
- qWarning() << "TODO" << Q_FUNC_INFO;
-}
-
-void Instr::math_sin_real(quint8 reg)
+void Bytecode::dump(const char *start, const char *end) const
{
- common.type = MathSinReal;
- unaryop.src = reg;
- unaryop.output = reg;
-}
-
-void Instr::math_cos_real(quint8 reg)
-{
- common.type = MathCosReal;
- unaryop.src = reg;
- unaryop.output = reg;
-}
-
-void Instr::math_round_real(quint8 reg)
-{
- common.type = MathRoundReal;
- unaryop.src = reg;
- unaryop.output = reg;
-}
-
-void Instr::math_floor_real(quint8 reg)
-{
- common.type = MathFloorReal;
- unaryop.src = reg;
- unaryop.output = reg;
-}
-
-void Instr::math_pi_real(quint8 reg)
-{
- common.type = MathPIReal;
- unaryop.src = reg;
- unaryop.output = reg;
-}
-
-void Instr::branch_true(quint8 reg, qint16 offset)
-{
- common.type = BranchTrue;
- branchop.reg = reg;
- branchop.offset = offset;
+ const char *code = start;
+ while (code < end) {
+ const V4Instr *instr = reinterpret_cast<const V4Instr *>(code);
+ dump(instr, code - start);
+ code += V4Instr::size(instructionType(instr));
+ }
}
-void Instr::branch_false(quint8 reg, qint16 offset)
+Bytecode::Bytecode()
{
- common.type = BranchFalse;
- branchop.reg = reg;
- branchop.offset = offset;
+#ifdef QML_THREADED_INTERPRETER
+ decodeInstr = QDeclarativeV4Bindings::getDecodeInstrTable();
+#endif
}
-void Instr::branch(qint16 offset)
+V4Instr::Type Bytecode::instructionType(const V4Instr *instr) const
{
- common.type = Branch;
- branchop.offset = offset;
-}
+#ifdef QML_THREADED_INTERPRETER
+ void *code = instr->common.code;
-void Instr::block(quint32 mask)
-{
- common.type = Block;
- blockop.block = mask;
-}
+# define CHECK_V4_INSTR_CODE(I, FMT) \
+ if (decodeInstr[static_cast<int>(V4Instr::I)] == code) \
+ return V4Instr::I;
-Bytecode::Bytecode()
-{
-#ifdef QML_THREADED_INTERPRETER
- decodeInstr = QDeclarativeV4Bindings::getDecodeInstrTable();
+ FOR_EACH_V4_INSTR(CHECK_V4_INSTR_CODE)
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid instruction address");
+ return static_cast<V4Instr::Type>(0);
+# undef CHECK_V4_INSTR_CODE
+#else
+ return static_cast<V4Instr::Type>(instr.common.type);
#endif
+
}
-void Bytecode::append(const Instr &instr)
+void Bytecode::append(V4Instr::Type type, V4Instr &instr)
{
- const char *it;
#ifdef QML_THREADED_INTERPRETER
- Instr i = instr;
- i.common.code = decodeInstr[i.common.type];
- it = (const char *) &i;
+ instr.common.code = decodeInstr[static_cast<int>(type)];
#else
- it = (const char *) &instr;
+ instr.common.type = type;
#endif
- d.append(it, instr.size());
+ d.append(reinterpret_cast<const char *>(&instr), V4Instr::size(type));
}
int Bytecode::remove(int offset)
{
- const Instr *instr = (const Instr *) (d.begin() + offset);
- const int instrSize = instr->size();
+ const V4Instr *instr = reinterpret_cast<const V4Instr *>(d.begin() + offset);
+ const int instrSize = V4Instr::size(instructionType(instr));
d.remove(offset, instrSize);
return instrSize;
}
-const Instr &Bytecode::operator[](int offset) const
+const V4Instr &Bytecode::operator[](int offset) const
{
- return *((const Instr *) (d.begin() + offset));
+ return *(reinterpret_cast<const V4Instr *>(d.begin() + offset));
}
-Instr &Bytecode::operator[](int offset)
+V4Instr &Bytecode::operator[](int offset)
{
- return *((Instr *) (d.begin() + offset));
+ return *(reinterpret_cast<V4Instr *>(d.begin() + offset));
}
}
diff --git a/src/declarative/qml/v4/qdeclarativev4instruction_p.h b/src/declarative/qml/v4/qdeclarativev4instruction_p.h
index 6efe9332d1..46336b4b75 100644
--- a/src/declarative/qml/v4/qdeclarativev4instruction_p.h
+++ b/src/declarative/qml/v4/qdeclarativev4instruction_p.h
@@ -94,10 +94,10 @@ QT_BEGIN_NAMESPACE
F(MathRoundReal, unaryop) \
F(MathFloorReal, unaryop) \
F(MathPIReal, unaryop) \
- F(Real, real_value) \
- F(Int, int_value) \
- F(Bool, bool_value) \
- F(String, string_value) \
+ F(LoadReal, real_value) \
+ F(LoadInt, int_value) \
+ F(LoadBool, bool_value) \
+ F(LoadString, string_value) \
F(EnableV4Test, string_value) \
F(TestV4Store, storetest) \
F(BitAndInt, binaryop) \
@@ -147,85 +147,52 @@ QT_BEGIN_NAMESPACE
#endif
#ifdef Q_ALIGNOF
-# define QML_V4_INSTR_ALIGN_MASK (Q_ALIGNOF(Instr) - 1)
+# define QML_V4_INSTR_ALIGN_MASK (Q_ALIGNOF(V4Instr) - 1)
#else
# define QML_V4_INSTR_ALIGN_MASK (sizeof(void *) - 1)
#endif
#define QML_V4_INSTR_ENUM(I, FMT) I,
#define QML_V4_INSTR_ADDR(I, FMT) &&op_##I,
-#define QML_V4_INSTR_SIZE(I, FMT) ((sizeof(Instr::instr_##FMT) + QML_V4_INSTR_ALIGN_MASK) & ~QML_V4_INSTR_ALIGN_MASK)
+#define QML_V4_INSTR_SIZE(I, FMT) ((sizeof(V4Instr::instr_##FMT) + QML_V4_INSTR_ALIGN_MASK) & ~QML_V4_INSTR_ALIGN_MASK)
#ifdef QML_THREADED_INTERPRETER
# define QML_V4_BEGIN_INSTR(I,FMT) op_##I:
-# define QML_V4_END_INSTR(I,FMT) code += QML_V4_INSTR_SIZE(I, FMT); instr = (const Instr *) code; goto *instr->common.code;
+# define QML_V4_END_INSTR(I,FMT) code += QML_V4_INSTR_SIZE(I, FMT); instr = (const V4Instr *) code; goto *instr->common.code;
# define QML_V4_INSTR_HEADER void *code;
#else
# define QML_V4_BEGIN_INSTR(I,FMT) case Instr::I:
-# define QML_V4_END_INSTR(I,FMT) code += QML_V4_INSTR_SIZE(I, FMT); instr = (const Instr *) code; break;
-# define QML_V4_INSTR_HEADER
+# define QML_V4_END_INSTR(I,FMT) code += QML_V4_INSTR_SIZE(I, FMT); instr = (const V4Instr *) code; break;
+# define QML_V4_INSTR_HEADER quint8 type;
#endif
namespace QDeclarativeJS {
-union Instr {
- int size() const;
- void dump(int = -1) const;
- void noop();
- void load_root(quint8 reg);
- void load_scope(quint8 reg);
- void load_id(quint8 reg, quint32 idIndex);
- void subscribe(qint8 reg, quint16 offset, quint32 index);
- void subscribeId(qint8 reg, quint16 offset, quint32 index);
- void move_reg_bool(quint8 reg, bool value);
- void move_reg_int(quint8 reg, int value);
- void move_reg_qreal(quint8 reg, qreal value);
- void move_reg_reg(quint8 reg, quint8 src);
-
- void unary_not(quint8 dest, quint8 src);
- void uminus_real(quint8 dest, quint8 src);
- void uminus_int(quint8 dest, quint8 src);
- void uplus_real(quint8 dest, quint8 src);
- void uplus_int(quint8 dest, quint8 src);
- void ucompl_real(quint8 dest, quint8 src);
- void ucompl_int(quint8 dest, quint8 src);
-
- void math_sin_real(quint8 reg);
- void math_cos_real(quint8 reg);
- void math_round_real(quint8 reg);
- void math_floor_real(quint8 reg);
- void math_pi_real(quint8 reg);
- void branch_true(quint8 reg, qint16 offset);
- void branch_false(quint8 reg, qint16 offset);
- void branch(qint16 offset);
- void block(quint32 mask);
-
- enum {
+union V4Instr {
+ enum Type {
FOR_EACH_V4_INSTR(QML_V4_INSTR_ENUM)
};
+ static int size(Type type);
+
struct instr_common {
QML_V4_INSTR_HEADER
- quint8 type;
};
struct instr_id {
QML_V4_INSTR_HEADER
- quint8 type;
quint16 column;
quint32 line;
};
struct instr_init {
QML_V4_INSTR_HEADER
- quint8 type;
quint16 subscriptions;
quint16 identifiers;
};
struct instr_subscribeop {
QML_V4_INSTR_HEADER
- quint8 type;
qint8 reg;
quint16 offset;
quint32 index;
@@ -233,14 +200,12 @@ union Instr {
struct instr_load {
QML_V4_INSTR_HEADER
- quint8 type;
qint8 reg;
quint32 index;
};
struct instr_attached {
QML_V4_INSTR_HEADER
- quint8 type;
qint8 output;
qint8 reg;
quint8 exceptionId;
@@ -249,7 +214,6 @@ union Instr {
struct instr_store {
QML_V4_INSTR_HEADER
- quint8 type;
qint8 output;
qint8 reg;
quint8 exceptionId;
@@ -258,14 +222,12 @@ union Instr {
struct instr_storetest {
QML_V4_INSTR_HEADER
- quint8 type;
qint8 reg;
qint32 regType;
};
struct instr_fetchAndSubscribe {
QML_V4_INSTR_HEADER
- quint8 type;
qint8 reg;
quint8 exceptionId;
quint8 valueType;
@@ -275,7 +237,6 @@ union Instr {
struct instr_fetch{
QML_V4_INSTR_HEADER
- quint8 type;
qint8 reg;
quint8 exceptionId;
quint8 valueType;
@@ -284,41 +245,35 @@ union Instr {
struct instr_copy {
QML_V4_INSTR_HEADER
- quint8 type;
qint8 reg;
qint8 src;
};
struct instr_construct {
QML_V4_INSTR_HEADER
- quint8 type;
qint8 reg;
};
struct instr_real_value {
QML_V4_INSTR_HEADER
- quint8 type;
qint8 reg;
qreal value; // XXX Makes the instruction 12 bytes
};
struct instr_int_value {
QML_V4_INSTR_HEADER
- quint8 type;
qint8 reg;
int value;
};
struct instr_bool_value {
QML_V4_INSTR_HEADER
- quint8 type;
qint8 reg;
bool value;
};
struct instr_string_value {
QML_V4_INSTR_HEADER
- quint8 type;
qint8 reg;
quint16 length;
quint32 offset;
@@ -326,7 +281,6 @@ union Instr {
struct instr_binaryop {
QML_V4_INSTR_HEADER
- quint8 type;
qint8 output;
qint8 left;
qint8 right;
@@ -334,21 +288,18 @@ union Instr {
struct instr_unaryop {
QML_V4_INSTR_HEADER
- quint8 type;
qint8 output;
qint8 src;
};
struct instr_jump {
QML_V4_INSTR_HEADER
- quint8 type;
qint8 reg;
quint32 count;
};
struct instr_find {
QML_V4_INSTR_HEADER
- quint8 type;
qint8 reg;
qint8 src;
quint8 exceptionId;
@@ -358,27 +309,23 @@ union Instr {
struct instr_cleanup {
QML_V4_INSTR_HEADER
- quint8 type;
qint8 reg;
};
struct instr_initstring {
QML_V4_INSTR_HEADER
- quint8 type;
quint16 offset;
quint32 dataIdx;
};
struct instr_branchop {
QML_V4_INSTR_HEADER
- quint8 type;
quint8 reg;
qint16 offset;
};
struct instr_blockop {
QML_V4_INSTR_HEADER
- quint8 type;
quint32 block;
};
@@ -408,6 +355,25 @@ union Instr {
instr_blockop blockop;
};
+template<int N>
+struct V4InstrMeta {
+};
+
+#define QML_V4_INSTR_META_TEMPLATE(I, FMT) \
+ template<> struct V4InstrMeta<(int)V4Instr::I> { \
+ enum { Size = QML_V4_INSTR_SIZE(I, FMT) }; \
+ typedef V4Instr::instr_##FMT DataType; \
+ static const DataType &data(const V4Instr &instr) { return instr.FMT; } \
+ static void setData(V4Instr &instr, const DataType &v) { instr.FMT = v; } \
+ };
+FOR_EACH_V4_INSTR(QML_V4_INSTR_META_TEMPLATE);
+#undef QML_V4_INSTR_META_TEMPLATE
+
+template<int Instr>
+class V4InstrData : public V4InstrMeta<Instr>::DataType
+{
+};
+
class Bytecode
{
Q_DISABLE_COPY(Bytecode)
@@ -420,21 +386,27 @@ public:
int count() const { return d.count(); }
void clear() { d.clear(); }
bool isEmpty() const { return d.isEmpty(); }
- void append(const Instr &instr);
+ V4Instr::Type instructionType(const V4Instr *instr) const;
- template <typename _It>
- void append(_It it, _It last)
+ template <int Instr>
+ void append(const V4InstrData<Instr> &data)
{
- for (; it != last; ++it)
- append(*it);
+ V4Instr genericInstr;
+ V4InstrMeta<Instr>::setData(genericInstr, data);
+ return append(static_cast<V4Instr::Type>(Instr), genericInstr);
}
+ void append(V4Instr::Type type, V4Instr &instr);
int remove(int index);
- const Instr &operator[](int offset) const;
- Instr &operator[](int offset);
+ const V4Instr &operator[](int offset) const;
+ V4Instr &operator[](int offset);
+
+ void dump(const char *start, const char *end) const;
private:
+ void dump(const V4Instr *instr, int = -1) const;
+
QVarLengthArray<char, 4 * 1024> d;
#ifdef QML_THREADED_INTERPRETER
void **decodeInstr;