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();
}
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)
{
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);
}
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);
}
}
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) {
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();
//
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())
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) {
} 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);
}
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;
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
}
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()) {
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();
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();
break;
case IR::OpCompl:
- i.ucompl_real(currentReg, src);
- gen(i);
- discard(); // ???
+ // TODO
+ discard();
break;
case IR::OpBitAnd:
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
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();
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();
{
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)
} // 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);
}
}
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;
- }
}
}
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();
}
{
patches.append(Patch(s->target, bytecode.size()));
- Instr i;
- i.branch(0); // ### backpatch
+ Instr::Branch i;
+ i.offset = 0; // ### backpatch
gen(i);
}
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);
}
}
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();
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);
}
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);
}
/*!
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;
*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;
}
/*!
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);
}
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
//
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
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) {
#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";
}
}
-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));
}
}
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) \
#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;
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;
struct instr_store {
QML_V4_INSTR_HEADER
- quint8 type;
qint8 output;
qint8 reg;
quint8 exceptionId;
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;
struct instr_fetch{
QML_V4_INSTR_HEADER
- quint8 type;
qint8 reg;
quint8 exceptionId;
quint8 valueType;
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;
struct instr_binaryop {
QML_V4_INSTR_HEADER
- quint8 type;
qint8 output;
qint8 left;
qint8 right;
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;
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;
};
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)
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;