aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-08-29 12:35:05 +0200
committerErik Verbruggen <erik.verbruggen@qt.io>2017-08-29 10:42:35 +0000
commit77e0602021c74b5ec2d8bd9affff5e91bf6f5ae3 (patch)
tree2054bc9a29279db1cdcdb57e414a9532b99cd818 /src/qml/compiler
parent99d5cdad6c8580d5ef31c291b721bf6230e2502f (diff)
Fix line number mapping to work with non increasing line numbers
The old map assumed that line numbers are always increasing, something that isn't always true. So move to a format where we map blocks of bytecode to a line number instead. Change-Id: I1cd9dd1329d415122cd3d560294ef53007f879f8 Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/qv4bytecodegenerator.cpp16
-rw-r--r--src/qml/compiler/qv4compileddata_p.h15
-rw-r--r--src/qml/compiler/qv4compiler.cpp6
-rw-r--r--src/qml/compiler/qv4compilercontext_p.h3
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp13
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h11
6 files changed, 41 insertions, 23 deletions
diff --git a/src/qml/compiler/qv4bytecodegenerator.cpp b/src/qml/compiler/qv4bytecodegenerator.cpp
index 9feafb8bd4..dfdb71b253 100644
--- a/src/qml/compiler/qv4bytecodegenerator.cpp
+++ b/src/qml/compiler/qv4bytecodegenerator.cpp
@@ -40,6 +40,7 @@
#include <private/qv4bytecodegenerator_p.h>
#include <private/qv4compilercontext_p.h>
#include <private/qqmljsastfwd_p.h>
+#include <private/qv4compileddata_p.h>
QT_USE_NAMESPACE
using namespace QV4;
@@ -161,15 +162,16 @@ void BytecodeGenerator::finalize(Compiler::Context *context)
// collect content and line numbers
QByteArray code;
- QVector<int> lineNumbers;
- currentLine = startLine;
+ QVector<CompiledData::CodeOffsetToLine> lineNumbers;
+ currentLine = -1;
+ Q_UNUSED(startLine);
for (const auto &i : qAsConst(instructions)) {
if (i.line != currentLine) {
- Q_ASSERT(i.line > currentLine);
- while (currentLine < i.line) {
- lineNumbers.append(code.size());
- ++currentLine;
- }
+ currentLine = i.line;
+ CompiledData::CodeOffsetToLine entry;
+ entry.codeOffset = code.size();
+ entry.line = currentLine;
+ lineNumbers.append(entry);
}
code.append(i.packed, i.size);
}
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 445c3c7091..6c8e2bc121 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -71,7 +71,7 @@
QT_BEGIN_NAMESPACE
// Bump this whenever the compiler data structures change in an incompatible way.
-#define QV4_DATA_STRUCTURE_VERSION 0x13
+#define QV4_DATA_STRUCTURE_VERSION 0x14
class QIODevice;
class QQmlPropertyCache;
@@ -194,6 +194,11 @@ struct String
}
};
+struct CodeOffsetToLine {
+ quint32_le codeOffset;
+ quint32_le line;
+};
+
// Function is aligned on an 8-byte boundary to make sure there are no bus errors or penalties
// for unaligned access. The ordering of the fields is also from largest to smallest.
struct Function
@@ -242,7 +247,7 @@ struct Function
const quint32_le *formalsTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + formalsOffset); }
const quint32_le *localsTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + localsOffset); }
- const quint32_le *lineNumberTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + lineNumberOffset); }
+ const CodeOffsetToLine *lineNumberTable() const { return reinterpret_cast<const CodeOffsetToLine *>(reinterpret_cast<const char *>(this) + lineNumberOffset); }
const quint32_le *qmlIdObjectDependencyTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + dependingIdObjectsOffset); }
const quint32_le *qmlContextPropertiesDependencyTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + dependingContextPropertiesOffset); }
const quint32_le *qmlScopePropertiesDependencyTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + dependingScopePropertiesOffset); }
@@ -255,9 +260,9 @@ struct Function
inline bool hasQmlDependencies() const { return nDependingIdObjects > 0 || nDependingContextProperties > 0 || nDependingScopeProperties > 0; }
static int calculateSize(int nFormals, int nLocals, int nLines, int nInnerfunctions, int nIdObjectDependencies, int nPropertyDependencies) {
- int trailingData = nFormals + nLocals + nLines + nInnerfunctions + nIdObjectDependencies +
- 2 * nPropertyDependencies;
- return align(align(sizeof(Function)) + size_t(trailingData) * sizeof(quint32));
+ int trailingData = (nFormals + nLocals + nInnerfunctions + nIdObjectDependencies +
+ 2 * nPropertyDependencies)*sizeof (quint32) + nLines*sizeof(CodeOffsetToLine);
+ return align(align(sizeof(Function)) + size_t(trailingData));
}
static size_t align(size_t a) {
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index acfd5c56e7..aaa06efa8c 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -318,7 +318,7 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte
function->nLineNumbers = irFunction->lineNumberMapping.size();
function->lineNumberOffset = currentOffset;
- currentOffset += function->nLineNumbers * sizeof(quint32);
+ currentOffset += function->nLineNumbers * sizeof(CompiledData::CodeOffsetToLine);
function->nInnerFunctions = irFunction->nestedContexts.size();
@@ -363,9 +363,7 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte
locals[i] = getStringId(irFunction->locals.at(i));
// write line numbers
- quint32 *lineNumbers = (quint32 *)(f + function->lineNumberOffset);
- for (int i = 0; i < irFunction->lineNumberMapping.size(); ++i)
- lineNumbers[i] = irFunction->lineNumberMapping.at(i);
+ memcpy(f + function->lineNumberOffset, irFunction->lineNumberMapping.constData(), irFunction->lineNumberMapping.size()*sizeof(CompiledData::CodeOffsetToLine));
// write QML dependencies
quint32_le *writtenDeps = (quint32_le *)(f + function->dependingIdObjectsOffset);
diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h
index 796f313b5c..b796a5f149 100644
--- a/src/qml/compiler/qv4compilercontext_p.h
+++ b/src/qml/compiler/qv4compilercontext_p.h
@@ -52,6 +52,7 @@
#include "private/qv4global_p.h"
#include <private/qqmljsast_p.h>
+#include <private/qv4compileddata_p.h>
#include <QtCore/QStringList>
#include <QtCore/QDateTime>
#include <QtCore/QStack>
@@ -133,7 +134,7 @@ struct Context {
ControlFlow *controlFlow = 0;
QByteArray code;
- QVector<int> lineNumberMapping;
+ QVector<CompiledData::CodeOffsetToLine> lineNumberMapping;
int maxNumberOfArguments = 0;
bool hasDirectEval = false;
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index 056e8d6624..c51f604500 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qv4instr_moth_p.h"
+#include <private/qv4compileddata_p.h>
using namespace QV4;
using namespace QV4::Moth;
@@ -117,17 +118,21 @@ void dumpConstantTable(const Value *constants, uint count)
<< toString(constants[i].asReturnedValue()).toUtf8().constData() << "\n";
}
-void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int startLine, const QVector<int> &lineNumberMapping)
+void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*startLine*/, const QVector<CompiledData::CodeOffsetToLine> &lineNumberMapping)
{
-
MOTH_JUMP_TABLE;
+ auto findLine = [](const CompiledData::CodeOffsetToLine &entry, uint offset) {
+ return entry.codeOffset < offset;
+ };
+
int lastLine = -1;
const char *start = code;
const char *end = code + len;
while (code < end) {
- int line = startLine + ((code == start) ? 0 : lineNumberMapping.lastIndexOf(static_cast<uint>(code - start)) + 1);
- if (line > lastLine)
+ const CompiledData::CodeOffsetToLine *codeToLine = std::lower_bound(lineNumberMapping.constBegin(), lineNumberMapping.constEnd(), static_cast<uint>(code - start) + 1, findLine) - 1;
+ int line = codeToLine->line;
+ if (line != lastLine)
lastLine = line;
else
line = -1;
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index dc262f5a37..cc26c88155 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -414,6 +414,11 @@ QT_BEGIN_NAMESPACE
#endif
namespace QV4 {
+
+namespace CompiledData {
+struct CodeOffsetToLine;
+}
+
namespace Moth {
class StackSlot {
@@ -467,8 +472,10 @@ inline bool operator!=(const StackSlot &l, const StackSlot &r) { return l.stackS
// When making changes to the instructions, make sure to bump QV4_DATA_STRUCTURE_VERSION in qv4compileddata_p.h
void dumpConstantTable(const Value *constants, uint count);
-void dumpBytecode(const char *bytecode, int len, int nLocals, int nFormals, int startLine = 1, const QVector<int> &lineNumberMapping = QVector<int>());
-inline void dumpBytecode(const QByteArray &bytecode, int nLocals, int nFormals, int startLine = 1, const QVector<int> &lineNumberMapping = QVector<int>()) {
+void dumpBytecode(const char *bytecode, int len, int nLocals, int nFormals, int startLine = 1,
+ const QVector<CompiledData::CodeOffsetToLine> &lineNumberMapping = QVector<CompiledData::CodeOffsetToLine>());
+inline void dumpBytecode(const QByteArray &bytecode, int nLocals, int nFormals, int startLine = 1,
+ const QVector<CompiledData::CodeOffsetToLine> &lineNumberMapping = QVector<CompiledData::CodeOffsetToLine>()) {
dumpBytecode(bytecode.constData(), bytecode.length(), nLocals, nFormals, startLine, lineNumberMapping);
}