aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/compiler/qv4bytecodegenerator.cpp8
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h16
-rw-r--r--src/qml/jit/qv4jit.cpp17
-rw-r--r--tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp34
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"