From 245f5ce7bb194438fc643e5c928382f47556e2f2 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 3 Mar 2014 14:41:31 +0100 Subject: Add a Line instruction to the interpreter This unifies the way we handle line numbers in the JIT and Interpreter. Remove the now unused lineNumberMapping code and data. Change-Id: I1d60b1fbb77e70b531fa73d93410683e84dd1e3c Reviewed-by: Simon Hausmann --- src/qml/compiler/qv4compiler.cpp | 22 ----------- src/qml/compiler/qv4compiler_p.h | 3 -- src/qml/compiler/qv4instr_moth_p.h | 6 +++ src/qml/compiler/qv4isel_moth.cpp | 20 +++++----- src/qml/jsruntime/qv4context_p.h | 2 - src/qml/jsruntime/qv4debugging.cpp | 8 ++-- src/qml/jsruntime/qv4debugging_p.h | 4 +- src/qml/jsruntime/qv4engine.cpp | 29 +-------------- src/qml/jsruntime/qv4function.cpp | 76 -------------------------------------- src/qml/jsruntime/qv4function_p.h | 2 - src/qml/jsruntime/qv4vme_moth.cpp | 9 ++++- 11 files changed, 31 insertions(+), 150 deletions(-) (limited to 'src/qml') diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp index b28195960f..a93252b26e 100644 --- a/src/qml/compiler/qv4compiler.cpp +++ b/src/qml/compiler/qv4compiler.cpp @@ -146,11 +146,6 @@ int QV4::Compiler::JSUnitGenerator::registerConstant(QV4::ReturnedValue v) return constants.size() - 1; } -void QV4::Compiler::JSUnitGenerator::registerLineNumberMapping(QV4::IR::Function *function, const QVector &mappings) -{ - lineNumberMappingsPerFunction.insert(function, mappings); -} - int QV4::Compiler::JSUnitGenerator::registerJSClass(int count, IR::ExprList *args) { // ### re-use existing class definitions. @@ -200,9 +195,6 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(int *total functionOffsets.insert(f, functionDataSize + unitSize + stringDataSize); int lineNumberMappingCount = 0; - QHash >::ConstIterator lineNumberMapping = lineNumberMappingsPerFunction.find(f); - if (lineNumberMapping != lineNumberMappingsPerFunction.constEnd()) - lineNumberMappingCount = lineNumberMapping->count() / 2; const int qmlIdDepsCount = f->idObjectDependencies.count(); const int qmlPropertyDepsCount = f->scopeObjectPropertyDependencies.count() + f->contextObjectPropertyDependencies.count(); @@ -327,14 +319,6 @@ int QV4::Compiler::JSUnitGenerator::writeFunction(char *f, int index, QV4::IR::F function->localsOffset = currentOffset; currentOffset += function->nLocals * sizeof(quint32); - function->nLineNumberMappingEntries = 0; - QHash >::ConstIterator lineNumberMapping = lineNumberMappingsPerFunction.find(irFunction); - if (lineNumberMapping != lineNumberMappingsPerFunction.constEnd()) { - function->nLineNumberMappingEntries = lineNumberMapping->count() / 2; - } - function->lineNumberMappingOffset = currentOffset; - currentOffset += function->nLineNumberMappingEntries * 2 * sizeof(quint32); - function->nInnerFunctions = irFunction->nestedFunctions.size(); function->innerFunctionsOffset = currentOffset; currentOffset += function->nInnerFunctions * sizeof(quint32); @@ -374,12 +358,6 @@ int QV4::Compiler::JSUnitGenerator::writeFunction(char *f, int index, QV4::IR::F for (int i = 0; i < irFunction->locals.size(); ++i) locals[i] = getStringId(*irFunction->locals.at(i)); - // write line number mappings - if (function->nLineNumberMappingEntries) { - 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) diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h index a917ea3d94..6fd597a3b3 100644 --- a/src/qml/compiler/qv4compiler_p.h +++ b/src/qml/compiler/qv4compiler_p.h @@ -77,8 +77,6 @@ struct Q_QML_EXPORT JSUnitGenerator { int registerConstant(ReturnedValue v); - void registerLineNumberMapping(IR::Function *function, const QVector &mappings); - int registerJSClass(int count, IR::ExprList *args); QV4::CompiledData::Unit *generateUnit(int *totalUnitSize = 0); @@ -92,7 +90,6 @@ struct Q_QML_EXPORT JSUnitGenerator { QList lookups; QVector regexps; QVector constants; - QHash > lineNumberMappingsPerFunction; QList > jsClasses; uint jsClassDataSize; uint headerSize; diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index 4f8173fb80..12ef3bc0af 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE #define FOR_EACH_MOTH_INSTR(F) \ F(Ret, ret) \ + F(Line, line) \ F(Debug, debug) \ F(LoadRuntimeString, loadRuntimeString) \ F(LoadRegExp, loadRegExp) \ @@ -234,6 +235,10 @@ union Instr MOTH_INSTR_HEADER Param result; }; + struct instr_line { + MOTH_INSTR_HEADER + qint32 lineNumber; + }; struct instr_debug { MOTH_INSTR_HEADER qint32 lineNumber; @@ -711,6 +716,7 @@ union Instr instr_common common; instr_ret ret; + instr_line line; instr_debug debug; instr_loadRuntimeString loadRuntimeString; instr_loadRegExp loadRegExp; diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp index 7f2af0829c..3993bc9acc 100644 --- a/src/qml/compiler/qv4isel_moth.cpp +++ b/src/qml/compiler/qv4isel_moth.cpp @@ -385,9 +385,6 @@ void InstructionSelection::run(int functionIndex) push.value = quint32(locals); addInstruction(push); - QVector lineNumberMappings; - lineNumberMappings.reserve(_function->basicBlocks.size() * 2); - uint currentLine = -1; for (int i = 0, ei = _function->basicBlocks.size(); i != ei; ++i) { _block = _function->basicBlocks[i]; @@ -410,12 +407,17 @@ void InstructionSelection::run(int functionIndex) _currentStatement = s; if (s->location.isValid()) { - lineNumberMappings << _codeNext - _codeStart << s->location.startLine; - if (irModule->debugMode && s->location.startLine != currentLine) { + if (s->location.startLine != currentLine) { currentLine = s->location.startLine; - Instruction::Debug debug; - debug.lineNumber = currentLine; - addInstruction(debug); + if (irModule->debugMode) { + Instruction::Debug debug; + debug.lineNumber = currentLine; + addInstruction(debug); + } else { + Instruction::Line line; + line.lineNumber = currentLine; + addInstruction(line); + } } } @@ -428,8 +430,6 @@ void InstructionSelection::run(int functionIndex) } } - jsGenerator->registerLineNumberMapping(_function, lineNumberMappings); - // TODO: patch stack size (the push instruction) patchJumpAddresses(); diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index f9511d98e3..c22d983329 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -95,7 +95,6 @@ struct Q_QML_EXPORT ExecutionContext : public Managed lookups = 0; compilationUnit = 0; currentEvalCode = 0; - interpreterInstructionPointer = 0; lineNumber = -1; engine->current = this; } @@ -118,7 +117,6 @@ struct Q_QML_EXPORT ExecutionContext : public Managed }; EvalCode *currentEvalCode; - const uchar **interpreterInstructionPointer; int lineNumber; CallContext *newCallContext(FunctionObject *f, CallData *callData); diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp index 7d19c7804e..92273417a9 100644 --- a/src/qml/jsruntime/qv4debugging.cpp +++ b/src/qml/jsruntime/qv4debugging.cpp @@ -205,13 +205,13 @@ void Debugger::setBreakOnThrow(bool onoff) m_breakOnThrow = onoff; } -Debugger::ExecutionState Debugger::currentExecutionState(int lineNumber) const +Debugger::ExecutionState Debugger::currentExecutionState() const { // ### Locking ExecutionState state; state.function = getFunction(); state.fileName = state.function->sourceFile(); - state.lineNumber = lineNumber; + state.lineNumber = engine()->currentContext()->lineNumber; return state; } @@ -445,7 +445,7 @@ QVector Debugger::getScopeTypes(int frame) const return types; } -void Debugger::maybeBreakAtInstruction(int lineNumber) +void Debugger::maybeBreakAtInstruction() { if (m_runningJob) // do not re-enter when we're doing a job for the debugger. return; @@ -454,7 +454,7 @@ void Debugger::maybeBreakAtInstruction(int lineNumber) if (m_breakPoints.isEmpty()) return; - ExecutionState state = currentExecutionState(lineNumber); + ExecutionState state = currentExecutionState(); if (m_gatherSources) { m_gatherSources->run(); diff --git a/src/qml/jsruntime/qv4debugging_p.h b/src/qml/jsruntime/qv4debugging_p.h index aec2cc64ae..9c97dd5f9e 100644 --- a/src/qml/jsruntime/qv4debugging_p.h +++ b/src/qml/jsruntime/qv4debugging_p.h @@ -169,7 +169,7 @@ public: Function *function; }; - ExecutionState currentExecutionState(int lineNumber) const; + ExecutionState currentExecutionState() const; bool pauseAtNextOpportunity() const { return m_pauseRequested || m_haveBreakPoints || m_gatherSources || m_stepping >= StepOver; @@ -184,7 +184,7 @@ public: QVector getScopeTypes(int frame = 0) const; public: // compile-time interface - void maybeBreakAtInstruction(int line); + void maybeBreakAtInstruction(); public: // execution hooks void enteringFunction(); diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 321e821e26..65165d4487 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -668,32 +668,8 @@ Returned *ExecutionEngine::qmlContextObject() const return static_cast(ctx)->activation->asReturned(); } -namespace { - struct LineNumberResolver { - const ExecutionEngine* engine; - - LineNumberResolver(const ExecutionEngine *engine) - : engine(engine) - { - } - - void resolve(StackFrame *frame, ExecutionContext *context, Function *function) - { - qptrdiff offset; - if (context->interpreterInstructionPointer) { - offset = *context->interpreterInstructionPointer - 1 - function->codeData; - frame->line = function->lineNumberForProgramCounter(offset); - } else { - frame->line = context->lineNumber; - } - } - }; -} - QVector ExecutionEngine::stackTrace(int frameLimit) const { - LineNumberResolver lineNumbers(this); - QVector stack; QV4::ExecutionContext *c = currentContext(); @@ -708,7 +684,7 @@ QVector ExecutionEngine::stackTrace(int frameLimit) const frame.column = -1; if (callCtx->function->function) - lineNumbers.resolve(&frame, callCtx, callCtx->function->function); + frame.line = callCtx->lineNumber; stack.append(frame); --frameLimit; @@ -720,10 +696,9 @@ QVector ExecutionEngine::stackTrace(int frameLimit) const StackFrame frame; frame.source = globalCode->sourceFile(); frame.function = globalCode->name()->toQString(); - frame.line = -1; + frame.line = rootContext->lineNumber; frame.column = -1; - lineNumbers.resolve(&frame, rootContext, globalCode); stack.append(frame); } diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index e01febcfa3..6fdf61f2c3 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -86,80 +86,4 @@ Function::~Function() { } - -namespace QV4 { -template -struct LineNumberMappingHelper -{ - const quint32 *table; - int lowerBound(int begin, int end, SearchType value) { - int middle; - int n = int(end - begin); - int half; - - while (n > 0) { - half = n >> 1; - middle = begin + half; - if (table[middle * 2 + field] < static_cast(value)) { - begin = middle + 1; - n -= half + 1; - } else { - n = half; - } - } - return begin; - } - int upperBound(int begin, int end, SearchType value) { - int middle; - int n = int(end - begin); - int half; - - while (n > 0) { - half = n >> 1; - middle = begin + half; - if (value < table[middle * 2 + field]) { - n = half; - } else { - begin = middle + 1; - n -= half + 1; - } - } - return begin; - } -}; -} - -int Function::lineNumberForProgramCounter(qptrdiff offset) const -{ - // Access the first field, the program counter - LineNumberMappingHelper<0, qptrdiff> helper; - helper.table = compiledFunction->lineNumberMapping(); - const uint count = compiledFunction->nLineNumberMappingEntries; - - int pos = helper.lowerBound(0, count, offset); - if (pos != 0 && count > 0) - --pos; - if (static_cast(pos) == count) - return -1; - return helper.table[pos * 2 + 1]; -} - -QList Function::programCountersForAllLines() const -{ - // Only store 1 breakpoint per line... - QHash offsetsPerLine; - const quint32 *mapping = compiledFunction->lineNumberMapping(); - - // ... and make it the first instruction by walking backwards over the line mapping table - // and inserting all entries keyed on line. - for (quint32 i = compiledFunction->nLineNumberMappingEntries; i > 0; ) { - --i; // the loop is written this way, because starting at endIndex-1 and checking for i>=0 will never end: i>=0 is always true for unsigned. - quint32 offset = mapping[i * 2]; - quint32 line = mapping[i * 2 + 1]; - offsetsPerLine.insert(line, offset); - } - - return offsetsPerLine.values(); -} - QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h index 553c7484b8..2fc3cf7827 100644 --- a/src/qml/jsruntime/qv4function_p.h +++ b/src/qml/jsruntime/qv4function_p.h @@ -106,8 +106,6 @@ struct Function { inline bool needsActivation() const { return compiledFunction->nInnerFunctions > 0 || (compiledFunction->flags & (CompiledData::Function::HasDirectEval | CompiledData::Function::UsesArgumentsObject)); } - int lineNumberForProgramCounter(qptrdiff offset) const; - QList programCountersForAllLines() const; }; } diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index fbf32e106a..b498581249 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -185,6 +185,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code const uchar *exceptionHandler = 0; + context->lineNumber = -1; QV4::ExecutionEngine *engine = context->engine; #ifdef DO_TRACE_INSTR @@ -192,7 +193,6 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code #endif // DO_TRACE_INSTR QV4::StringValue * const runtimeStrings = context->compilationUnit->runtimeStrings; - context->interpreterInstructionPointer = &code; // setup lookup scopes int scopeDepth = 0; @@ -661,9 +661,14 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code MOTH_END_INSTR(Ret) MOTH_BEGIN_INSTR(Debug) + context->lineNumber = instr.lineNumber; QV4::Debugging::Debugger *debugger = context->engine->debugger; if (debugger && debugger->pauseAtNextOpportunity()) - debugger->maybeBreakAtInstruction(instr.lineNumber); + debugger->maybeBreakAtInstruction(); + MOTH_END_INSTR(Debug) + + MOTH_BEGIN_INSTR(Line) + context->lineNumber = instr.lineNumber; MOTH_END_INSTR(Debug) MOTH_BEGIN_INSTR(LoadThis) -- cgit v1.2.3