aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4bytecodegenerator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/compiler/qv4bytecodegenerator.cpp')
-rw-r--r--src/qml/compiler/qv4bytecodegenerator.cpp48
1 files changed, 32 insertions, 16 deletions
diff --git a/src/qml/compiler/qv4bytecodegenerator.cpp b/src/qml/compiler/qv4bytecodegenerator.cpp
index 4d50654d27..7e1f49ee86 100644
--- a/src/qml/compiler/qv4bytecodegenerator.cpp
+++ b/src/qml/compiler/qv4bytecodegenerator.cpp
@@ -70,14 +70,14 @@ int BytecodeGenerator::newRegisterArray(int n)
void BytecodeGenerator::packInstruction(I &i)
{
- uchar type = *reinterpret_cast<uchar *>(i.packed);
- Q_ASSERT(type >= MOTH_NUM_INSTRUCTIONS());
- if (type >= MOTH_NUM_INSTRUCTIONS())
- type -= MOTH_NUM_INSTRUCTIONS();
+ Instr::Type type = Instr::unpack(i.packed);
+ Q_ASSERT(int(type) < MOTH_NUM_INSTRUCTIONS());
+ type = Instr::narrowInstructionType(type);
int instructionsAsInts[sizeof(Instr)/sizeof(int)] = {};
int nMembers = Moth::InstrInfo::argumentCount[static_cast<int>(i.type)];
+ uchar *code = i.packed + Instr::encodedLength(type);
for (int j = 0; j < nMembers; ++j) {
- instructionsAsInts[j] = qFromLittleEndian<qint32>(i.packed + 1 + j * sizeof(int));
+ instructionsAsInts[j] = qFromLittleEndian<qint32>(code + j * sizeof(int));
}
enum {
Normal,
@@ -89,11 +89,10 @@ void BytecodeGenerator::packInstruction(I &i)
break;
}
}
- char *code = i.packed;
+ code = i.packed;
switch (width) {
case Normal:
- *reinterpret_cast<uchar *>(code) = type;
- ++code;
+ code = Instr::pack(code, type);
for (int n = 0; n < nMembers; ++n) {
qint8 v = static_cast<qint8>(instructionsAsInts[n]);
memcpy(code, &v, 1);
@@ -122,7 +121,7 @@ void BytecodeGenerator::adjustJumpOffsets()
// qDebug() << "adjusting jump offset for instruction" << index << i.position << i.size << "offsetForJump" << i.offsetForJump << "target"
// << labels.at(i.linkedLabel) << linkedInstruction.position << "jumpOffset" << jumpOffset;
uchar type = *reinterpret_cast<const uchar *>(i.packed);
- if (type >= MOTH_NUM_INSTRUCTIONS()) {
+ if (Instr::isWide(Instr::Type(type))) {
Q_ASSERT(i.offsetForJump == i.size - 4);
qToLittleEndian<qint32>(jumpOffset, c);
} else {
@@ -177,7 +176,7 @@ void BytecodeGenerator::finalize(Compiler::Context *context)
entry.line = currentLine;
lineNumbers.append(entry);
}
- code.append(i.packed, i.size);
+ code.append(reinterpret_cast<const char *>(i.packed), i.size);
}
context->code = code;
@@ -185,6 +184,25 @@ void BytecodeGenerator::finalize(Compiler::Context *context)
}
int BytecodeGenerator::addInstructionHelper(Instr::Type type, const Instr &i, int offsetOfOffset) {
+ if (lastInstrType == int(Instr::Type::StoreReg)) {
+ if (type == Instr::Type::LoadReg) {
+ if (i.LoadReg.reg == lastInstr.StoreReg.reg) {
+ // value is already in the accumulator
+ return -1;
+ }
+ }
+ if (type == Instr::Type::MoveReg) {
+ if (i.MoveReg.srcReg == lastInstr.StoreReg.reg) {
+ Instruction::StoreReg store;
+ store.reg = i.MoveReg.destReg;
+ addInstruction(store);
+ return -1;
+ }
+ }
+ }
+ lastInstrType = int(type);
+ lastInstr = i;
+
#if QT_CONFIG(qml_debug)
if (debugMode && type != Instr::Type::Debug) {
QT_WARNING_PUSH
@@ -207,12 +225,10 @@ QT_WARNING_POP
const int argCount = Moth::InstrInfo::argumentCount[static_cast<int>(type)];
int s = argCount*sizeof(int);
if (offsetOfOffset != -1)
- offsetOfOffset += 1;
- I instr{type, static_cast<short>(s + 1), 0, currentLine, offsetOfOffset, -1, "\0\0" };
- char *code = instr.packed;
- *reinterpret_cast<uchar *>(code) = static_cast<uchar>(MOTH_NUM_INSTRUCTIONS() + static_cast<int>(type));
- ++code;
- Q_ASSERT(MOTH_NUM_INSTRUCTIONS() + static_cast<int>(type) < 256);
+ offsetOfOffset += Instr::encodedLength(type);
+ I instr{type, static_cast<short>(s + Instr::encodedLength(type)), 0, currentLine, offsetOfOffset, -1, "\0\0" };
+ uchar *code = instr.packed;
+ code = Instr::pack(code, Instr::wideInstructionType(type));
for (int j = 0; j < argCount; ++j) {
qToLittleEndian<qint32>(i.argumentsAsInts[j], code);