diff options
author | Lars Knoll <lars.knoll@qt.io> | 2017-08-29 12:35:05 +0200 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2017-08-29 10:42:35 +0000 |
commit | 77e0602021c74b5ec2d8bd9affff5e91bf6f5ae3 (patch) | |
tree | 2054bc9a29279db1cdcdb57e414a9532b99cd818 /src/qml/compiler | |
parent | 99d5cdad6c8580d5ef31c291b721bf6230e2502f (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.cpp | 16 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata_p.h | 15 | ||||
-rw-r--r-- | src/qml/compiler/qv4compiler.cpp | 6 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilercontext_p.h | 3 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth.cpp | 13 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth_p.h | 11 |
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); } |