aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-08-16 08:57:58 +0200
committerLars Knoll <lars.knoll@digia.com>2013-08-16 10:14:22 +0200
commitd017fe9b38c74d2cc2fa754af3bf9e32357f149c (patch)
treed56a6421c026d4ec03165722b66540c7752a9d1e /src
parentb88626a3a59f7dcd01be6fe2a8236b14ca1176f5 (diff)
Store line number mappings in the compiled function
Change-Id: I4e37aac3618b20ccd52ce4833098781374a3daf6 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/qml/compiler/qv4compileddata.cpp5
-rw-r--r--src/qml/compiler/qv4compileddata_p.h8
-rw-r--r--src/qml/compiler/qv4compiler.cpp37
-rw-r--r--src/qml/compiler/qv4compiler_p.h6
-rw-r--r--src/qml/compiler/qv4isel_masm.cpp10
-rw-r--r--src/qml/compiler/qv4isel_p.h1
-rw-r--r--src/qml/jsruntime/qv4debugging.cpp10
-rw-r--r--src/qml/jsruntime/qv4function.cpp38
8 files changed, 84 insertions, 31 deletions
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 08c4d80b4e..6ac7a4843d 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -50,11 +50,6 @@ namespace QV4 {
namespace CompiledData {
-int Function::calculateSize(QQmlJS::V4IR::Function *f)
-{
- return calculateSize(f->formals.size(), f->locals.size(), f->nestedFunctions.size());
-}
-
CompilationUnit::~CompilationUnit()
{
engine->compilationUnits.erase(engine->compilationUnits.find(this));
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index e267f0fecb..0c5bf15c02 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -141,6 +141,8 @@ struct Function
quint32 formalsOffset;
quint32 nLocals;
quint32 localsOffset;
+ quint32 nLineNumberMappingEntries;
+ quint32 lineNumberMappingOffset; // Array of uint pairs (offset and line number)
quint32 nInnerFunctions;
quint32 innerFunctionsOffset;
// quint32 formalsIndex[nFormals]
@@ -150,11 +152,11 @@ struct Function
const quint32 *formalsTable() const { return reinterpret_cast<const quint32 *>(reinterpret_cast<const char *>(this) + formalsOffset); }
const quint32 *localsTable() const { return reinterpret_cast<const quint32 *>(reinterpret_cast<const char *>(this) + localsOffset); }
+ const quint32 *lineNumberMapping() const { return reinterpret_cast<const quint32 *>(reinterpret_cast<const char *>(this) + lineNumberMappingOffset); }
- static int calculateSize(int nFormals, int nLocals, int nInnerfunctions) {
- return (sizeof(Function) + (nFormals + nLocals + nInnerfunctions) * sizeof(quint32) + 7) & ~0x7;
+ static int calculateSize(int nFormals, int nLocals, int nInnerfunctions, int lineNumberMappings) {
+ return (sizeof(Function) + (nFormals + nLocals + nInnerfunctions + 2 * lineNumberMappings) * sizeof(quint32) + 7) & ~0x7;
}
- static int calculateSize(QQmlJS::V4IR::Function *f);
};
struct String
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index d67b7deef7..7f2f611898 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -111,6 +111,11 @@ int QV4::Compiler::JSUnitGenerator::registerRegExp(QQmlJS::V4IR::RegExp *regexp)
return regexps.size() - 1;
}
+void QV4::Compiler::JSUnitGenerator::registerLineNumberMapping(QQmlJS::V4IR::Function *function, const QVector<uint> &mappings)
+{
+ lineNumberMappingsPerFunction.insert(function, mappings);
+}
+
QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit()
{
registerString(irModule->fileName);
@@ -128,7 +133,13 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit()
for (int i = 0; i < irModule->functions.size(); ++i) {
QQmlJS::V4IR::Function *f = irModule->functions.at(i);
functionOffsets.insert(f, functionDataSize + unitSize + stringDataSize);
- functionDataSize += QV4::CompiledData::Function::calculateSize(f);
+
+ int lineNumberMappingCount = 0;
+ QHash<QQmlJS::V4IR::Function *, QVector<uint> >::ConstIterator lineNumberMapping = lineNumberMappingsPerFunction.find(f);
+ if (lineNumberMapping != lineNumberMappingsPerFunction.constEnd())
+ lineNumberMappingCount = lineNumberMapping->count() / 2;
+
+ functionDataSize += QV4::CompiledData::Function::calculateSize(f->formals.size(), f->locals.size(), f->nestedFunctions.size(), lineNumberMappingCount);
}
const uint lookupDataSize = CompiledData::Lookup::calculateSize() * lookups.count();
@@ -180,8 +191,8 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit()
if (function == irModule->rootFunction)
unit->indexOfRootFunction = i;
- writeFunction(f, i, function);
- f += QV4::CompiledData::Function::calculateSize(function);
+ const int bytes = writeFunction(f, i, function);
+ f += bytes;
}
CompiledData::Lookup *lookupsToWrite = (CompiledData::Lookup*)(data + unit->offsetToLookupTable);
@@ -194,9 +205,12 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit()
return unit;
}
-void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, int index, QQmlJS::V4IR::Function *irFunction)
+int QV4::Compiler::JSUnitGenerator::writeFunction(char *f, int index, QQmlJS::V4IR::Function *irFunction)
{
QV4::CompiledData::Function *function = (QV4::CompiledData::Function *)f;
+
+ QHash<QQmlJS::V4IR::Function *, QVector<uint> >::ConstIterator lineNumberMapping = lineNumberMappingsPerFunction.find(irFunction);
+
function->index = index;
function->nameIndex = getStringId(*irFunction->name);
function->flags = 0;
@@ -212,8 +226,15 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, int index, QQmlJS::V
function->formalsOffset = sizeof(QV4::CompiledData::Function);
function->nLocals = irFunction->locals.size();
function->localsOffset = function->formalsOffset + function->nFormals * sizeof(quint32);
+
+ function->nLineNumberMappingEntries = 0;
+ if (lineNumberMapping != lineNumberMappingsPerFunction.constEnd()) {
+ function->nLineNumberMappingEntries = lineNumberMapping->count() / 2;
+ }
+ function->lineNumberMappingOffset = function->localsOffset + function->nLocals * sizeof(quint32);
+
function->nInnerFunctions = irFunction->nestedFunctions.size();
- function->innerFunctionsOffset = function->localsOffset + function->nLocals * sizeof(quint32);
+ function->innerFunctionsOffset = function->lineNumberMappingOffset + function->nLineNumberMappingEntries * 2 * sizeof(quint32);
// write formals
quint32 *formals = (quint32 *)(f + function->formalsOffset);
@@ -225,10 +246,16 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, int index, QQmlJS::V
for (int i = 0; i < irFunction->locals.size(); ++i)
locals[i] = getStringId(*irFunction->locals.at(i));
+ // write line number mappings
+ quint32 *mappingsToWrite = (quint32*)(f + function->lineNumberMappingOffset);
+ memcpy(mappingsToWrite, lineNumberMapping->constData(), 2 * function->nLineNumberMappingEntries * sizeof(quint32));
+
// write inner functions
quint32 *innerFunctions = (quint32 *)(f + function->innerFunctionsOffset);
for (int i = 0; i < irFunction->nestedFunctions.size(); ++i)
innerFunctions[i] = functionOffsets.value(irFunction->nestedFunctions.at(i));
+
+ return CompiledData::Function::calculateSize(function->nFormals, function->nLocals, function->nInnerFunctions, function->nLineNumberMappingEntries);
}
diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h
index 753e4627e7..1032369a53 100644
--- a/src/qml/compiler/qv4compiler_p.h
+++ b/src/qml/compiler/qv4compiler_p.h
@@ -70,8 +70,11 @@ struct JSUnitGenerator {
int registerRegExp(QQmlJS::V4IR::RegExp *regexp);
+ void registerLineNumberMapping(QQmlJS::V4IR::Function *function, const QVector<uint> &mappings);
+
QV4::CompiledData::Unit *generateUnit();
- void writeFunction(char *f, int index, QQmlJS::V4IR::Function *irFunction);
+ // Returns bytes written
+ int writeFunction(char *f, int index, QQmlJS::V4IR::Function *irFunction);
QHash<QString, int> stringToId;
QStringList strings;
@@ -79,6 +82,7 @@ struct JSUnitGenerator {
QHash<QQmlJS::V4IR::Function *, uint> functionOffsets;
QList<CompiledData::Lookup> lookups;
QVector<CompiledData::RegExp> regexps;
+ QHash<QQmlJS::V4IR::Function *, QVector<uint> > lineNumberMappingsPerFunction;
};
}
diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp
index d93a67a163..df5fa94c59 100644
--- a/src/qml/compiler/qv4isel_masm.cpp
+++ b/src/qml/compiler/qv4isel_masm.cpp
@@ -586,13 +586,13 @@ JSC::MacroAssemblerCodeRef Assembler::link(QV4::Function *vmFunc)
JSC::LinkBuffer linkBuffer(dummy, this, 0);
vmFunc->codeSize = linkBuffer.offsetOf(endOfCode);
- vmFunc->lineNumberMappings.resize(codeLineNumberMappings.count());
+ QVector<uint> lineNumberMapping(codeLineNumberMappings.count() * 2);
+
for (int i = 0; i < codeLineNumberMappings.count(); ++i) {
- QV4::LineNumberMapping mapping;
- mapping.codeOffset = linkBuffer.offsetOf(codeLineNumberMappings.at(i).location);
- mapping.lineNumber = codeLineNumberMappings.at(i).lineNumber;
- vmFunc->lineNumberMappings[i] = mapping;
+ lineNumberMapping[i * 2] = linkBuffer.offsetOf(codeLineNumberMappings.at(i).location);
+ lineNumberMapping[i * 2 + 1] = codeLineNumberMappings.at(i).lineNumber;
}
+ _isel->registerLineNumberMapping(_function, lineNumberMapping);
QHash<void*, const char*> functions;
foreach (CallToLink ctl, _callsToLink) {
diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h
index 24ad5812f0..3553d9dc78 100644
--- a/src/qml/compiler/qv4isel_p.h
+++ b/src/qml/compiler/qv4isel_p.h
@@ -73,6 +73,7 @@ public:
uint registerGetterLookup(const QString &str) { return jsUnitGenerator.registerGetterLookup(str); }
uint registerSetterLookup(const QString &str) { return jsUnitGenerator.registerSetterLookup(str); }
uint registerGlobalGetterLookup(const QString &str) { return jsUnitGenerator.registerGlobalGetterLookup(str); }
+ void registerLineNumberMapping(V4IR::Function *function, const QVector<uint> &mappings) { jsUnitGenerator.registerLineNumberMapping(function, mappings); }
protected:
QV4::Function *createFunctionMapping(QV4::Function *outer, V4IR::Function *irFunction);
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp
index 5965af8cfd..3bb031116e 100644
--- a/src/qml/jsruntime/qv4debugging.cpp
+++ b/src/qml/jsruntime/qv4debugging.cpp
@@ -350,10 +350,12 @@ void Debugger::BreakPoints::applyToFunction(Function *function, bool removeBreak
QList<int>::Iterator breakPoint = breakPointsForFile->begin();
while (breakPoint != breakPointsForFile->end()) {
bool breakPointFound = false;
- for (QVector<LineNumberMapping>::ConstIterator mapping = function->lineNumberMappings.constBegin(),
- end = function->lineNumberMappings.constEnd(); mapping != end; ++mapping) {
- if (mapping->lineNumber == *breakPoint) {
- uchar *codePtr = const_cast<uchar *>(function->codeData) + mapping->codeOffset;
+ const quint32 *lineNumberMappings = function->compiledFunction->lineNumberMapping();
+ for (int i = 0; i < function->compiledFunction->nLineNumberMappingEntries; ++i) {
+ const int codeOffset = lineNumberMappings[i * 2];
+ const int lineNumber = lineNumberMappings[i * 2 + 1];
+ if (lineNumber == *breakPoint) {
+ uchar *codePtr = const_cast<uchar *>(function->codeData) + codeOffset;
QQmlJS::Moth::Instr *instruction = reinterpret_cast<QQmlJS::Moth::Instr*>(codePtr);
instruction->common.breakPoint = !removeBreakPoints;
// Continue setting the next break point.
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index 24ea1fbb32..b814637e12 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -99,20 +99,42 @@ void Function::mark()
}
namespace QV4 {
-bool operator<(const LineNumberMapping &mapping, qptrdiff pc)
+struct LineNumberMappingHelper
{
- return mapping.codeOffset < pc;
-}
+ const quint32 *table;
+ int lowerBound(int begin, int end, qptrdiff offset) {
+ int middle;
+ int n = int(end - begin);
+ int half;
+
+ while (n > 0) {
+ half = n >> 1;
+ middle = begin + half;
+ if (table[middle * 2] < offset) {
+ begin = middle + 1;
+ n -= half + 1;
+ } else {
+ n = half;
+ }
+ }
+ return begin;
+ }
+};
+
}
int Function::lineNumberForProgramCounter(qptrdiff offset) const
{
- QVector<LineNumberMapping>::ConstIterator it = qLowerBound(lineNumberMappings.begin(), lineNumberMappings.end(), offset);
- if (it != lineNumberMappings.constBegin() && lineNumberMappings.count() > 0)
- --it;
- if (it == lineNumberMappings.constEnd())
+ LineNumberMappingHelper helper;
+ helper.table = compiledFunction->lineNumberMapping();
+ const uint count = compiledFunction->nLineNumberMappingEntries;
+
+ int pos = helper.lowerBound(0, count, offset);
+ if (pos != 0 && count > 0)
+ --pos;
+ if (pos == count)
return -1;
- return it->lineNumber;
+ return helper.table[pos * 2 + 1];
}
QT_END_NAMESPACE