diff options
author | Lars Knoll <lars.knoll@qt.io> | 2017-08-25 10:53:51 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2017-08-28 13:19:14 +0000 |
commit | 2daf6cb390d3c84dd456d9597e5728a3277eb0d4 (patch) | |
tree | 35c1ab80376ca6177af2565e08a47c08349069ad /src/qml/compiler/qv4bytecodegenerator.cpp | |
parent | 41a4e387222a117e1cb47c119858c69e0d193e4f (diff) |
Compress jump instructions as well
Change-Id: If95a5733594a1beaa41063249a364988190844c5
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/compiler/qv4bytecodegenerator.cpp')
-rw-r--r-- | src/qml/compiler/qv4bytecodegenerator.cpp | 111 |
1 files changed, 73 insertions, 38 deletions
diff --git a/src/qml/compiler/qv4bytecodegenerator.cpp b/src/qml/compiler/qv4bytecodegenerator.cpp index aa459a7556..401730c275 100644 --- a/src/qml/compiler/qv4bytecodegenerator.cpp +++ b/src/qml/compiler/qv4bytecodegenerator.cpp @@ -71,7 +71,10 @@ void BytecodeGenerator::packInstruction(I &i) { int instructionsAsInts[sizeof(Instr)/sizeof(int)]; int nMembers = Moth::Instr::argumentCount[static_cast<int>(i.type)]; - memcpy(instructionsAsInts, &i.instr, nMembers*sizeof(int)); + char *data = i.packed; + Q_ASSERT(*data == static_cast<char>(Instr::Type::XWide)); + data += 2; + memcpy(instructionsAsInts, data, nMembers*sizeof(int)); enum { Normal, Wide, @@ -92,6 +95,9 @@ void BytecodeGenerator::packInstruction(I &i) memcpy(code, &v, 1); code += 1; } + i.size = code - i.packed; + if (i.offsetForJump != -1) + i.offsetForJump = i.size - 1; break; case Wide: *code++ = static_cast<char>(Instr::Type::Wide); @@ -101,18 +107,43 @@ void BytecodeGenerator::packInstruction(I &i) memcpy(code, &v, 2); code += 2; } + i.size = code - i.packed; + if (i.offsetForJump != -1) + i.offsetForJump = i.size - 2; break; case XWide: - *code++ = static_cast<char>(Instr::Type::XWide); - *code++ = static_cast<char>(i.type); - for (int n = 0; n < nMembers; ++n) { - int v = instructionsAsInts[n]; - memcpy(code, &v, 4); - code += 4; - } + // nothing to do break; } - i.size = code - i.packed; +} + +void BytecodeGenerator::adjustJumpOffsets() +{ + for (int index = 0; index < instructions.size(); ++index) { + auto &i = instructions[index]; + if (i.offsetForJump == -1) // no jump + continue; + Q_ASSERT(i.linkedLabel != -1 && labels.at(i.linkedLabel) != -1); + const auto &linkedInstruction = instructions.at(labels.at(i.linkedLabel)); + char *c = i.packed + i.offsetForJump; + int jumpOffset = linkedInstruction.position - (i.position + i.size); +// qDebug() << "adjusting jump offset for instruction" << index << i.position << i.size << "offsetForJump" << i.offsetForJump << "target" +// << labels.at(i.linkedLabel) << linkedInstruction.position << "jumpOffset" << jumpOffset; + if (*i.packed == static_cast<char>(Instr::Type::XWide)) { + Q_ASSERT(i.offsetForJump == i.size - 4); + memcpy(c, &jumpOffset, sizeof(int)); + } else if (*i.packed == static_cast<char>(Instr::Type::Wide)) { + Q_ASSERT(i.offsetForJump == i.size - 2); + short o = jumpOffset; + Q_ASSERT(o == jumpOffset); + memcpy(c, &o, sizeof(short)); + } else { + Q_ASSERT(i.offsetForJump == i.size - 1); + char o = jumpOffset; + Q_ASSERT(o == jumpOffset); + *c = o; + } + } } void BytecodeGenerator::compressInstructions() @@ -120,28 +151,35 @@ void BytecodeGenerator::compressInstructions() // first round: compress all non jump instructions int position = 0; for (auto &i : instructions) { - if (i.offsetForJump != -1) { - int dummy = INT_MAX; - memcpy(reinterpret_cast<char *>(&i.instr) + i.offsetForJump, &dummy, 4); - i.offsetForJump += 2; - } i.position = position; - packInstruction(i); + if (i.offsetForJump == -1) + packInstruction(i); + position += i.size; + } + + adjustJumpOffsets(); + + // compress all jumps + position = 0; + for (auto &i : instructions) { + i.position = position; + if (i.offsetForJump != -1) + packInstruction(i); position += i.size; } + + // adjust once again, as the packing above could have changed offsets + adjustJumpOffsets(); } void BytecodeGenerator::finalize(Compiler::Context *context) { - QByteArray code; - compressInstructions(); - // content - QVector<int> instructionOffsets; + // collect content and line numbers + QByteArray code; QVector<int> lineNumbers; currentLine = startLine; - instructionOffsets.reserve(instructions.size()); for (const auto &i : qAsConst(instructions)) { if (i.line != currentLine) { Q_ASSERT(i.line > currentLine); @@ -150,27 +188,24 @@ void BytecodeGenerator::finalize(Compiler::Context *context) ++currentLine; } } - instructionOffsets.append(code.size()); code.append(i.packed, i.size); } - // resolve jumps -// qDebug() << "resolving jumps"; - for (int index = 0; index < instructions.size(); ++index) { - const auto &i = instructions.at(index); - if (i.offsetForJump == -1) // no jump - continue; - Q_ASSERT(i.linkedLabel != -1); - int linkedInstruction = labels.at(i.linkedLabel); - Q_ASSERT(linkedInstruction != -1); - int offset = instructionOffsets.at(index) + i.offsetForJump; -// qDebug() << "offset data is at" << offset; - char *c = code.data() + offset; - int linkedInstructionOffset = instructionOffsets.at(linkedInstruction) - instructionOffsets.at(index + 1); -// qDebug() << "linked instruction" << linkedInstruction << "at " << instructionOffsets.at(linkedInstruction); - memcpy(c, &linkedInstructionOffset, sizeof(int)); - } - context->code = code; context->lineNumberMapping = lineNumbers; } + +int BytecodeGenerator::addInstructionHelper(Instr::Type type, const Instr &i, int offsetOfOffset) { + int pos = instructions.size(); + int s = Moth::Instr::argumentCount[static_cast<int>(type)]*sizeof(int); + if (offsetOfOffset != -1) + offsetOfOffset += 2; + I instr{type, static_cast<short>(s + 2), 0, currentLine, offsetOfOffset, -1, "\0\0" }; + char *code = instr.packed; + *code++ = static_cast<char>(Instr::Type::XWide); + *code++ = static_cast<char>(type); + memcpy(code, &i, s); + instructions.append(instr); + + return pos; +} |