diff options
author | Lars Knoll <lars.knoll@qt.io> | 2017-08-21 10:59:53 +0200 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2017-08-25 12:05:59 +0000 |
commit | 4e0174a88e66b9d9471c98eeb7d8be6209ba5c98 (patch) | |
tree | 573aac0c41d77fab6dfe37d4d75e0446165d78f0 /src/qml/compiler | |
parent | 3c201dd0d95020c4cb4c8ceaf779673d411664e7 (diff) |
Move line number information into a side table
Don't emit any Line instructions anymore, and instead store
the info in a side table in the compiled data, where it can
be looked up on demand.
Change-Id: Idcaf3bf4ee4129fd62f9e717bf1277dc6a34fe19
Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r-- | src/qml/compiler/qv4bytecodegenerator.cpp | 20 | ||||
-rw-r--r-- | src/qml/compiler/qv4bytecodegenerator_p.h | 10 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 7 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata_p.h | 9 | ||||
-rw-r--r-- | src/qml/compiler/qv4compiler.cpp | 11 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilercontext_p.h | 1 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth.cpp | 24 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth_p.h | 13 |
8 files changed, 60 insertions, 35 deletions
diff --git a/src/qml/compiler/qv4bytecodegenerator.cpp b/src/qml/compiler/qv4bytecodegenerator.cpp index c9b7c4ae7e..cae984a253 100644 --- a/src/qml/compiler/qv4bytecodegenerator.cpp +++ b/src/qml/compiler/qv4bytecodegenerator.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include <private/qv4bytecodegenerator_p.h> +#include <private/qv4compilercontext_p.h> #include <private/qqmljsastfwd_p.h> QT_USE_NAMESPACE @@ -46,12 +47,7 @@ using namespace Moth; void BytecodeGenerator::setLocation(const QQmlJS::AST::SourceLocation &loc) { - if (static_cast<int>(loc.startLine) == currentLine) - return; currentLine = static_cast<int>(loc.startLine); - Instruction::Line line; - line.lineNumber = currentLine; - addInstruction(line); //### put line numbers in a side-table, not in the instruction stream } int BytecodeGenerator::newRegister() @@ -71,14 +67,23 @@ int BytecodeGenerator::newRegisterArray(int n) return t; } -QByteArray BytecodeGenerator::finalize() +void BytecodeGenerator::finalize(Compiler::Context *context) { QByteArray code; // content QVector<int> instructionOffsets; + QVector<int> lineNumbers; + currentLine = startLine; instructionOffsets.reserve(instructions.size()); for (const auto &i : qAsConst(instructions)) { + if (i.line != currentLine) { + Q_ASSERT(i.line > currentLine); + while (currentLine < i.line) { + lineNumbers.append(code.size()); + ++currentLine; + } + } instructionOffsets.append(code.size()); code.append(reinterpret_cast<const char *>(&i.instr), i.size); } @@ -97,5 +102,6 @@ QByteArray BytecodeGenerator::finalize() memcpy(c, &linkedInstructionOffset, sizeof(ptrdiff_t)); } - return code; + context->code = code; + context->lineNumberMapping = lineNumbers; } diff --git a/src/qml/compiler/qv4bytecodegenerator_p.h b/src/qml/compiler/qv4bytecodegenerator_p.h index f53a720d2c..5ab8c880f3 100644 --- a/src/qml/compiler/qv4bytecodegenerator_p.h +++ b/src/qml/compiler/qv4bytecodegenerator_p.h @@ -65,6 +65,8 @@ namespace Moth { class BytecodeGenerator { public: + BytecodeGenerator(int line) + : startLine(line) {} struct Label { enum LinkMode { @@ -221,7 +223,7 @@ public: int newRegisterArray(int n); int registerCount() const { return regCount; } - QByteArray finalize(); + void finalize(Compiler::Context *context); template<int InstrT> Jump addJumpInstruction(const InstrData<InstrT> &data) @@ -239,7 +241,7 @@ private: int addInstructionHelper(uint size, const Instr &i) { int pos = instructions.size(); - instructions.append({size, i}); + instructions.append({size, currentLine, i}); return pos; } @@ -251,6 +253,7 @@ private: struct I { uint size; + int line; Instr instr; }; @@ -262,7 +265,8 @@ private: public: int currentReg = 0; private: - int currentLine = -1; + int startLine = 0; + int currentLine = 0; }; } diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 273856e541..7e8a823939 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -1932,7 +1932,7 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, // ### still needed? _context->maxNumberOfArguments = qMax(_context->maxNumberOfArguments, (int)QV4::Global::ReservedArgumentCount); - BytecodeGenerator bytecode; + BytecodeGenerator bytecode(_context->line); BytecodeGenerator *savedBytecodeGenerator; savedBytecodeGenerator = bytecodeGenerator; bytecodeGenerator = &bytecode; @@ -2025,13 +2025,14 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, bytecodeGenerator->addInstruction(Instruction::Ret()); } - _context->code = bytecodeGenerator->finalize(); + bytecodeGenerator->finalize(_context); _context->registerCount = bytecodeGenerator->registerCount(); static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE"); if (showCode) { qDebug() << "=== Bytecode for" << _context->name << "strict mode" << _context->isStrict << "register count" << _context->registerCount; - QV4::Moth::dumpBytecode(_context->code, _context->locals.size(), _context->arguments.size()); + QV4::Moth::dumpBytecode(_context->code, _context->locals.size(), _context->arguments.size(), + _context->line, _context->lineNumberMapping); qDebug(); } diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 91ef2eac20..445c3c7091 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 0x12 +#define QV4_DATA_STRUCTURE_VERSION 0x13 class QIODevice; class QQmlPropertyCache; @@ -217,6 +217,8 @@ struct Function quint32_le formalsOffset; quint32_le nLocals; quint32_le localsOffset; + quint32_le nLineNumbers; + quint32_le lineNumberOffset; quint32_le nInnerFunctions; quint32_le nRegisters; Location location; @@ -240,6 +242,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 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); } @@ -251,8 +254,8 @@ struct Function inline bool hasQmlDependencies() const { return nDependingIdObjects > 0 || nDependingContextProperties > 0 || nDependingScopeProperties > 0; } - static int calculateSize(int nFormals, int nLocals, int nInnerfunctions, int nIdObjectDependencies, int nPropertyDependencies) { - int trailingData = nFormals + nLocals + nInnerfunctions + nIdObjectDependencies + + 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)); } diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp index 84deb076b3..acfd5c56e7 100644 --- a/src/qml/compiler/qv4compiler.cpp +++ b/src/qml/compiler/qv4compiler.cpp @@ -316,6 +316,10 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte function->localsOffset = currentOffset; currentOffset += function->nLocals * sizeof(quint32); + function->nLineNumbers = irFunction->lineNumberMapping.size(); + function->lineNumberOffset = currentOffset; + currentOffset += function->nLineNumbers * sizeof(quint32); + function->nInnerFunctions = irFunction->nestedContexts.size(); function->nRegisters = irFunction->registerCount; @@ -358,6 +362,11 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte for (int i = 0; i < irFunction->locals.size(); ++i) 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); + // write QML dependencies quint32_le *writtenDeps = (quint32_le *)(f + function->dependingIdObjectsOffset); for (int id : irFunction->idObjectDependencies) { @@ -428,7 +437,7 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp const int qmlIdDepsCount = f->idObjectDependencies.count(); const int qmlPropertyDepsCount = f->scopeObjectPropertyDependencies.count() + f->contextObjectPropertyDependencies.count(); - nextOffset += QV4::CompiledData::Function::calculateSize(f->arguments.size(), f->locals.size(), f->nestedContexts.size(), qmlIdDepsCount, qmlPropertyDepsCount); + nextOffset += QV4::CompiledData::Function::calculateSize(f->arguments.size(), f->locals.size(), f->lineNumberMapping.size(), f->nestedContexts.size(), qmlIdDepsCount, qmlPropertyDepsCount); } if (option == GenerateWithStringTable) { diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h index 0a204d8c24..796f313b5c 100644 --- a/src/qml/compiler/qv4compilercontext_p.h +++ b/src/qml/compiler/qv4compilercontext_p.h @@ -133,6 +133,7 @@ struct Context { ControlFlow *controlFlow = 0; QByteArray code; + QVector<int> lineNumberMapping; int maxNumberOfArguments = 0; bool hasDirectEval = false; diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp index 9101537236..523fe88c02 100644 --- a/src/qml/compiler/qv4instr_moth.cpp +++ b/src/qml/compiler/qv4instr_moth.cpp @@ -59,6 +59,12 @@ static QByteArray alignedNumber(int n) { return number; } +static QByteArray alignedLineNumber(int line) { + if (line > 0) + return alignedNumber(static_cast<int>(line)); + return QByteArray(" "); +} + static QString toString(QV4::ReturnedValue v) { #ifdef V4_BOOTSTRAP @@ -91,7 +97,7 @@ size_t absoluteInstructionOffset(const char *codeStart, const T &instr) QDebug d = qDebug(); \ d.noquote(); \ d.nospace(); \ - d << alignedNumber(int(code - start)).constData() << ": " << #I << " "; \ + d << alignedLineNumber(line) << alignedNumber(int(code - start)).constData() << ": " << #I << " "; \ code += InstrMeta<int(Instr::I)>::Size; \ #define MOTH_END_INSTR(I) } break; @@ -109,12 +115,18 @@ 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) +void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int startLine, const QVector<int> &lineNumberMapping) { + int lastLine = -1; const char *start = code; const char *end = code + len; while (code < end) { const Instr *genericInstr = reinterpret_cast<const Instr *>(code); + int line = startLine + ((code == start) ? 0 : lineNumberMapping.lastIndexOf(static_cast<uint>(code - start)) + 1); + if (line > lastLine) + lastLine = line; + else + line = -1; switch (genericInstr->common.instructionType) { MOTH_BEGIN_INSTR(LoadReg) @@ -516,14 +528,10 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals) MOTH_BEGIN_INSTR(Ret) MOTH_END_INSTR(Ret) - #ifndef QT_NO_QML_DEBUGGER +#ifndef QT_NO_QML_DEBUGGER MOTH_BEGIN_INSTR(Debug) MOTH_END_INSTR(Debug) - - MOTH_BEGIN_INSTR(Line) - d << instr.lineNumber; - MOTH_END_INSTR(Line) - #endif // QT_NO_QML_DEBUGGER +#endif // QT_NO_QML_DEBUGGER MOTH_BEGIN_INSTR(LoadQmlContext) d << instr.result.dump(nFormals); diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index 2ce0ff7b22..588ee7c110 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -64,7 +64,6 @@ QT_BEGIN_NAMESPACE #define MOTH_DEBUG_INSTR(F) #else #define MOTH_DEBUG_INSTR(F) \ - F(Line, line) \ F(Debug, debug) #endif @@ -236,9 +235,9 @@ 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); -inline void dumpBytecode(const QByteArray &bytecode, int nLocals, int nFormals) { - dumpBytecode(bytecode.constData(), bytecode.length(), nLocals, nFormals); +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>()) { + dumpBytecode(bytecode.constData(), bytecode.length(), nLocals, nFormals, startLine, lineNumberMapping); } union Instr @@ -256,13 +255,8 @@ union Instr }; #ifndef QT_NO_QML_DEBUGGING - struct instr_line { - MOTH_INSTR_HEADER - qint32 lineNumber; - }; struct instr_debug { MOTH_INSTR_HEADER - qint32 lineNumber; }; #endif // QT_NO_QML_DEBUGGING @@ -714,7 +708,6 @@ union Instr instr_common common; instr_ret ret; - instr_line line; instr_debug debug; instr_loadConst loadConst; instr_loadZero loadZero; |