diff options
-rw-r--r-- | src/qml/compiler/qv4bytecodegenerator.cpp | 8 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth_p.h | 16 | ||||
-rw-r--r-- | src/qml/jit/qv4jit.cpp | 17 | ||||
-rw-r--r-- | tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp | 34 |
4 files changed, 57 insertions, 18 deletions
diff --git a/src/qml/compiler/qv4bytecodegenerator.cpp b/src/qml/compiler/qv4bytecodegenerator.cpp index 05bbf25292..03105d2b71 100644 --- a/src/qml/compiler/qv4bytecodegenerator.cpp +++ b/src/qml/compiler/qv4bytecodegenerator.cpp @@ -82,7 +82,7 @@ void BytecodeGenerator::packInstruction(I &i) Wide } width = Normal; for (int n = 0; n < nMembers; ++n) { - if (width == Normal && (static_cast<char>(instructionsAsInts[n]) != instructionsAsInts[n])) + if (width == Normal && (static_cast<qint8>(instructionsAsInts[n]) != instructionsAsInts[n])) width = Wide; } char *code = i.packed; @@ -91,7 +91,7 @@ void BytecodeGenerator::packInstruction(I &i) *reinterpret_cast<uchar *>(code) = type; ++code; for (int n = 0; n < nMembers; ++n) { - char v = static_cast<char>(instructionsAsInts[n]); + qint8 v = static_cast<qint8>(instructionsAsInts[n]); memcpy(code, &v, 1); code += 1; } @@ -113,7 +113,7 @@ void BytecodeGenerator::adjustJumpOffsets() 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; + qint8 *c = reinterpret_cast<qint8*>(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; @@ -123,7 +123,7 @@ void BytecodeGenerator::adjustJumpOffsets() memcpy(c, &jumpOffset, sizeof(int)); } else { Q_ASSERT(i.offsetForJump == i.size - 1); - char o = jumpOffset; + qint8 o = jumpOffset; Q_ASSERT(o == jumpOffset); *c = o; } diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index a9de71e7ad..789f875ba7 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -366,9 +366,9 @@ QT_BEGIN_NAMESPACE MOTH_ADJUST_CODE(int, nargs); \ MOTH_DECODE_ARGS(name, int, nargs, __VA_ARGS__) \ goto op_main_##name; \ - op_char_##name: \ - MOTH_ADJUST_CODE(char, nargs); \ - MOTH_DECODE_ARGS(name, char, nargs, __VA_ARGS__) \ + op_byte_##name: \ + MOTH_ADJUST_CODE(qint8, nargs); \ + MOTH_DECODE_ARGS(name, qint8, nargs, __VA_ARGS__) \ op_main_##name: \ ; \ @@ -380,10 +380,10 @@ QT_BEGIN_NAMESPACE MOTH_ADJUST_CODE(int, nargs); \ MOTH_DECODE_ARGS(name, int, nargs, __VA_ARGS__) \ goto op_main_##name; \ - op_char_##name: \ + op_byte_##name: \ base_ptr = code; \ - MOTH_ADJUST_CODE(char, nargs); \ - MOTH_DECODE_ARGS(name, char, nargs, __VA_ARGS__) \ + MOTH_ADJUST_CODE(qint8, nargs); \ + MOTH_DECODE_ARGS(name, qint8, nargs, __VA_ARGS__) \ op_main_##name: \ ; \ @@ -408,7 +408,7 @@ QT_BEGIN_NAMESPACE #define COLLECT_LABELS(instr) \ INSTR_##instr(GET_LABEL) #define GET_LABEL_INSTRUCTION(name, ...) \ - &&op_char_##name, + &&op_byte_##name, #define COLLECT_LABELS_WIDE(instr) \ INSTR_##instr(GET_LABEL_WIDE) #define GET_LABEL_WIDE_INSTRUCTION(name, ...) \ @@ -428,7 +428,7 @@ QT_BEGIN_NAMESPACE #define MOTH_INSTR_CASE_AND_JUMP(instr) \ INSTR_##instr(GET_CASE_AND_JUMP) #define GET_CASE_AND_JUMP_INSTRUCTION(name, ...) \ - case static_cast<uchar>(Instr::Type::name): goto op_char_##name; + case static_cast<uchar>(Instr::Type::name): goto op_byte_##name; #define MOTH_INSTR_CASE_AND_JUMP_WIDE(instr) \ INSTR_##instr(GET_CASE_AND_JUMP_WIDE) #define GET_CASE_AND_JUMP_WIDE_INSTRUCTION(name, ...) \ diff --git a/src/qml/jit/qv4jit.cpp b/src/qml/jit/qv4jit.cpp index 4922e60747..1ab45d6765 100644 --- a/src/qml/jit/qv4jit.cpp +++ b/src/qml/jit/qv4jit.cpp @@ -946,6 +946,11 @@ void BaselineJIT::collectLabelsInBytecode() { MOTH_JUMP_TABLE; + const auto addLabel = [&](int offset) { + Q_ASSERT(offset >= 0 && offset < static_cast<int>(function->compiledFunction->codeSize)); + labels.push_back(offset); + }; + const char *code = reinterpret_cast<const char *>(function->codeData); const char *start = code; const char *end = code + function->compiledFunction->codeSize; @@ -1083,7 +1088,7 @@ void BaselineJIT::collectLabelsInBytecode() MOTH_END_INSTR(CallGlobalLookup) MOTH_BEGIN_INSTR(SetExceptionHandler) - labels.push_back(code - start + offset); + addLabel(code - start + offset); MOTH_END_INSTR(SetExceptionHandler) MOTH_BEGIN_INSTR(ThrowException) @@ -1150,15 +1155,15 @@ void BaselineJIT::collectLabelsInBytecode() MOTH_END_INSTR(Construct) MOTH_BEGIN_INSTR(Jump) - labels.push_back(code - start + offset); + addLabel(code - start + offset); MOTH_END_INSTR(Jump) MOTH_BEGIN_INSTR(JumpTrue) - labels.push_back(code - start + offset); + addLabel(code - start + offset); MOTH_END_INSTR(JumpTrue) MOTH_BEGIN_INSTR(JumpFalse) - labels.push_back(code - start + offset); + addLabel(code - start + offset); MOTH_END_INSTR(JumpFalse) MOTH_BEGIN_INSTR(CmpEqNull) @@ -1204,11 +1209,11 @@ void BaselineJIT::collectLabelsInBytecode() MOTH_END_INSTR(CmpInstanceOf) MOTH_BEGIN_INSTR(JumpStrictEqualStackSlotInt) - labels.push_back(code - start + offset); + addLabel(code - start + offset); MOTH_END_INSTR(JumpStrictEqualStackSlotInt) MOTH_BEGIN_INSTR(JumpStrictNotEqualStackSlotInt) - labels.push_back(code - start + offset); + addLabel(code - start + offset); MOTH_END_INSTR(JumpStrictNotEqualStackSlotInt) MOTH_BEGIN_INSTR(UNot) diff --git a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp index 7e81df93b9..fb1072e67f 100644 --- a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp +++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp @@ -45,6 +45,7 @@ private slots: void translationExpressionSupport(); void signalHandlerParameters(); void errorOnArgumentsInSignalHandler(); + void aheadOfTimeCompilation(); }; // A wrapper around QQmlComponent to ensure the temporary reference counts @@ -225,6 +226,39 @@ void tst_qmlcachegen::errorOnArgumentsInSignalHandler() QVERIFY2(errorOutput.contains("error: The use of the arguments object in signal handlers is"), errorOutput); } +void tst_qmlcachegen::aheadOfTimeCompilation() +{ + QTemporaryDir tempDir; + QVERIFY(tempDir.isValid()); + + const auto writeTempFile = [&tempDir](const QString &fileName, const char *contents) { + QFile f(tempDir.path() + '/' + fileName); + const bool ok = f.open(QIODevice::WriteOnly | QIODevice::Truncate); + Q_ASSERT(ok); + f.write(contents); + return f.fileName(); + }; + + const QString testFilePath = writeTempFile("test.qml", "import QtQml 2.0\n" + "QtObject {\n" + " function runTest() { var x = 0; while (x < 42) { ++x }; return x; }\n" + "}"); + + QVERIFY(generateCache(testFilePath)); + + const QString cacheFilePath = testFilePath + QLatin1Char('c'); + QVERIFY(QFile::exists(cacheFilePath)); + QVERIFY(QFile::remove(testFilePath)); + + QQmlEngine engine; + CleanlyLoadingComponent component(&engine, QUrl::fromLocalFile(testFilePath)); + QScopedPointer<QObject> obj(component.create()); + QVERIFY(!obj.isNull()); + QVariant result; + QMetaObject::invokeMethod(obj.data(), "runTest", Q_RETURN_ARG(QVariant, result)); + QCOMPARE(result.toInt(), 42); +} + QTEST_GUILESS_MAIN(tst_qmlcachegen) #include "tst_qmlcachegen.moc" |