aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-08-21 10:59:53 +0200
committerErik Verbruggen <erik.verbruggen@qt.io>2017-08-25 12:05:59 +0000
commit4e0174a88e66b9d9471c98eeb7d8be6209ba5c98 (patch)
tree573aac0c41d77fab6dfe37d4d75e0446165d78f0 /src/qml/compiler
parent3c201dd0d95020c4cb4c8ceaf779673d411664e7 (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.cpp20
-rw-r--r--src/qml/compiler/qv4bytecodegenerator_p.h10
-rw-r--r--src/qml/compiler/qv4codegen.cpp7
-rw-r--r--src/qml/compiler/qv4compileddata_p.h9
-rw-r--r--src/qml/compiler/qv4compiler.cpp11
-rw-r--r--src/qml/compiler/qv4compilercontext_p.h1
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp24
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h13
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;