diff options
| author | Erik Verbruggen <erik.verbruggen@me.com> | 2013-11-14 14:16:50 +0100 |
|---|---|---|
| committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-11-14 14:43:38 +0100 |
| commit | f0349e789a984de7646865b07c125a63406516bd (patch) | |
| tree | 5985a6b19c14b72829dac4068d1c499a77478b4c /src/qml/jsruntime/qv4debugging.cpp | |
| parent | 0ca8351e261055984f82b28bd65e4e15c9820e73 (diff) | |
V4 debugging: fix step-over and step-out.
- step-out: only stop if we’re leaving the context for the function we
previously stopped at, so intermediate calls between the current
position and the end do not stop the engine
- step-over: set breakpoints on all lines in current function and
continue to run. When hitting a breakpoint, see if we are in the same
context, because recursive calls might happen. Breakpoints on all
lines are needed, because the (pure) next line might be jumped over
(like when doing step-over a single-line then clause, where the next
line might be in the else clause).
Change-Id: Idf35dc740ca64fae5079162162906490a96af2a7
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Reviewed-by: Kai Koehne <kai.koehne@digia.com>
Diffstat (limited to 'src/qml/jsruntime/qv4debugging.cpp')
| -rw-r--r-- | src/qml/jsruntime/qv4debugging.cpp | 49 |
1 files changed, 30 insertions, 19 deletions
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp index 0ba37fa547..95b4100651 100644 --- a/src/qml/jsruntime/qv4debugging.cpp +++ b/src/qml/jsruntime/qv4debugging.cpp @@ -181,11 +181,11 @@ void Debugger::resume(Speed speed) if (!m_returnedValue.isUndefined()) m_returnedValue = Primitive::undefinedValue(); - clearTemporaryBreakPoint(); + clearTemporaryBreakPoints(); if (speed == StepOver) setTemporaryBreakPointOnNextLine(); if (speed == StepOut) - m_temporaryBreakPoint.function = getFunction(); + m_temporaryBreakPoints = TemporaryBreakPoint(getFunction(), m_engine->current); m_stepping = speed; m_runningCondition.wakeAll(); @@ -491,7 +491,7 @@ void Debugger::maybeBreakAtInstruction(const uchar *code, bool breakPointHit) } if (m_stopForStepping) { - clearTemporaryBreakPoint(); + clearTemporaryBreakPoints(); m_stopForStepping = false; m_pauseRequested = false; pauseAndWait(Step); @@ -499,7 +499,7 @@ void Debugger::maybeBreakAtInstruction(const uchar *code, bool breakPointHit) m_pauseRequested = false; pauseAndWait(PauseRequest); } else if (breakPointHit) { - if (m_stepping == StepOver) + if (m_stepping == StepOver && m_temporaryBreakPoints.context == m_engine->current) pauseAndWait(Step); else if (reallyHitTheBreakPoint(state.fileName, state.lineNumber)) pauseAndWait(BreakPoint); @@ -526,8 +526,9 @@ void Debugger::leavingFunction(const ReturnedValue &retVal) QMutexLocker locker(&m_lock); - if (m_stepping == StepOut && temporaryBreakPointInFunction()) { - clearTemporaryBreakPoint(); + if ((m_stepping == StepOut || m_stepping == StepOver) + && temporaryBreakPointInFunction(m_engine->current)) { + clearTemporaryBreakPoints(); m_stepping = NotStepping; m_stopForStepping = true; m_pauseRequested = true; @@ -544,7 +545,7 @@ void Debugger::aboutToThrow() return; QMutexLocker locker(&m_lock); - clearTemporaryBreakPoint(); + clearTemporaryBreakPoints(); pauseAndWait(Throwing); } @@ -589,28 +590,38 @@ void Debugger::setTemporaryBreakPointOnNextLine() if (!function) return; - qptrdiff offset = function->programCounterForLine(state.lineNumber + 1); - if (offset < 0) + QList<qptrdiff> pcs = function->programCountersForAllLines(); + if (pcs.isEmpty()) return; - if (hasBreakOnInstruction(function, offset)) - return; + m_temporaryBreakPoints = TemporaryBreakPoint(function, m_engine->current); + m_temporaryBreakPoints.codeOffsets.reserve(pcs.size()); + for (QList<qptrdiff>::const_iterator i = pcs.begin(), ei = pcs.end(); i != ei; ++i) { + // note: we do set a breakpoint on the current line, because there could be a loop where + // a step-over would be jump back to the first instruction making up the current line. + qptrdiff offset = *i; + + if (hasBreakOnInstruction(function, offset)) + continue; // do not set a temporary breakpoint if there already is a breakpoint set by the user - setBreakOnInstruction(function, offset, true); - m_temporaryBreakPoint = TemporaryBreakPoint(function, offset); + setBreakOnInstruction(function, offset, true); + m_temporaryBreakPoints.codeOffsets.append(offset); + } } -void Debugger::clearTemporaryBreakPoint() +void Debugger::clearTemporaryBreakPoints() { - if (m_temporaryBreakPoint.function && m_temporaryBreakPoint.codeOffset) { - setBreakOnInstruction(m_temporaryBreakPoint.function, m_temporaryBreakPoint.codeOffset, false); - m_temporaryBreakPoint = TemporaryBreakPoint(); + if (m_temporaryBreakPoints.function) { + foreach (quintptr offset, m_temporaryBreakPoints.codeOffsets) + setBreakOnInstruction(m_temporaryBreakPoints.function, offset, false); + m_temporaryBreakPoints = TemporaryBreakPoint(); } } -bool Debugger::temporaryBreakPointInFunction() const +bool Debugger::temporaryBreakPointInFunction(ExecutionContext *context) const { - return m_temporaryBreakPoint.function == getFunction(); + return m_temporaryBreakPoints.function == getFunction() + && m_temporaryBreakPoints.context == context; } void Debugger::applyPendingBreakPoints() |
