aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <[email protected]>2014-03-04 10:35:11 +0100
committerThe Qt Project <[email protected]>2014-03-07 16:55:12 +0100
commit39b54d7293741c712116010b33f0d9823ab2ab1c (patch)
tree0af462863604bc130b1232a53477185b9d59c158
parent245f5ce7bb194438fc643e5c928382f47556e2f2 (diff)
Fixes to breakpoint handling
Make sure stepping works correctly, and we always break at a valid breakpoint. Change-Id: I6a3032b3ae204484b8a92b2031904a7f681c7f80 Reviewed-by: Simon Hausmann <[email protected]>
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp21
-rw-r--r--src/qml/compiler/qv4isel_moth_p.h2
-rw-r--r--src/qml/jsruntime/qv4debugging.cpp49
-rw-r--r--src/qml/jsruntime/qv4debugging_p.h7
4 files changed, 42 insertions, 37 deletions
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index 3993bc9acc..921af76151 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -385,8 +385,9 @@ void InstructionSelection::run(int functionIndex)
push.value = quint32(locals);
addInstruction(push);
- uint currentLine = -1;
+ currentLine = -1;
for (int i = 0, ei = _function->basicBlocks.size(); i != ei; ++i) {
+ blockNeedsDebugInstruction = irModule->debugMode;
_block = _function->basicBlocks[i];
_nextBlock = (i < ei - 1) ? _function->basicBlocks[i + 1] : 0;
_addrs.insert(_block, _codeNext - _codeStart);
@@ -408,6 +409,7 @@ void InstructionSelection::run(int functionIndex)
if (s->location.isValid()) {
if (s->location.startLine != currentLine) {
+ blockNeedsDebugInstruction = false;
currentLine = s->location.startLine;
if (irModule->debugMode) {
Instruction::Debug debug;
@@ -423,11 +425,6 @@ void InstructionSelection::run(int functionIndex)
s->accept(this);
}
- if (irModule->debugMode) {
- Instruction::Debug debug;
- debug.lineNumber = currentLine;
- addInstruction(debug);
- }
}
// TODO: patch stack size (the push instruction)
@@ -1039,6 +1036,12 @@ void InstructionSelection::visitJump(IR::Jump *s)
if (_removableJumps.contains(s))
return;
+ if (blockNeedsDebugInstruction) {
+ Instruction::Debug debug;
+ debug.lineNumber = currentLine;
+ addInstruction(debug);
+ }
+
Instruction::Jump jump;
jump.offset = 0;
ptrdiff_t loc = addInstruction(jump) + (((const char *)&jump.offset) - ((const char *)&jump));
@@ -1048,6 +1051,12 @@ void InstructionSelection::visitJump(IR::Jump *s)
void InstructionSelection::visitCJump(IR::CJump *s)
{
+ if (blockNeedsDebugInstruction) {
+ Instruction::Debug debug;
+ debug.lineNumber = currentLine;
+ addInstruction(debug);
+ }
+
Param condition;
if (IR::Temp *t = s->cond->asTemp()) {
condition = getResultParam(t);
diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h
index 000ff634e7..4c01434156 100644
--- a/src/qml/compiler/qv4isel_moth_p.h
+++ b/src/qml/compiler/qv4isel_moth_p.h
@@ -169,6 +169,8 @@ private:
QQmlEnginePrivate *qmlEngine;
+ bool blockNeedsDebugInstruction;
+ uint currentLine;
IR::BasicBlock *_block;
IR::BasicBlock *_nextBlock;
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp
index 92273417a9..04489903c3 100644
--- a/src/qml/jsruntime/qv4debugging.cpp
+++ b/src/qml/jsruntime/qv4debugging.cpp
@@ -113,12 +113,12 @@ public:
Debugger::Debugger(QV4::ExecutionEngine *engine)
: m_engine(engine)
+ , m_currentContext(0)
, m_agent(0)
, m_state(Running)
, m_stepping(NotStepping)
, m_pauseRequested(false)
, m_haveBreakPoints(false)
- , m_stopForStepping(false)
, m_breakOnThrow(false)
, m_returnedValue(Primitive::undefinedValue())
, m_gatherSources(0)
@@ -180,6 +180,7 @@ void Debugger::resume(Speed speed)
if (!m_returnedValue.isUndefined())
m_returnedValue = Encode::undefined();
+ m_currentContext = m_engine->currentContext();
m_stepping = speed;
m_runningCondition.wakeAll();
}
@@ -187,14 +188,14 @@ void Debugger::resume(Speed speed)
void Debugger::addBreakPoint(const QString &fileName, int lineNumber, const QString &condition)
{
QMutexLocker locker(&m_lock);
- m_breakPoints.insert(DebuggerBreakPoint(fileName, lineNumber), condition);
+ m_breakPoints.insert(DebuggerBreakPoint(fileName.mid(fileName.lastIndexOf('/') + 1), lineNumber), condition);
m_haveBreakPoints = true;
}
void Debugger::removeBreakPoint(const QString &fileName, int lineNumber)
{
QMutexLocker locker(&m_lock);
- m_breakPoints.remove(DebuggerBreakPoint(fileName, lineNumber));
+ m_breakPoints.remove(DebuggerBreakPoint(fileName.mid(fileName.lastIndexOf('/') + 1), lineNumber));
m_haveBreakPoints = !m_breakPoints.isEmpty();
}
@@ -207,10 +208,8 @@ void Debugger::setBreakOnThrow(bool onoff)
Debugger::ExecutionState Debugger::currentExecutionState() const
{
- // ### Locking
ExecutionState state;
- state.function = getFunction();
- state.fileName = state.function->sourceFile();
+ state.fileName = getFunction()->sourceFile();
state.lineNumber = engine()->currentContext()->lineNumber;
return state;
@@ -451,10 +450,7 @@ void Debugger::maybeBreakAtInstruction()
return;
QMutexLocker locker(&m_lock);
- if (m_breakPoints.isEmpty())
- return;
-
- ExecutionState state = currentExecutionState();
+ int lineNumber = engine()->currentContext()->lineNumber;
if (m_gatherSources) {
m_gatherSources->run();
@@ -464,20 +460,22 @@ void Debugger::maybeBreakAtInstruction()
switch (m_stepping) {
case StepOver:
+ if (m_currentContext != m_engine->currentContext())
+ break;
+ // fall through
case StepIn:
pauseAndWait(Step);
- break;
+ return;
case StepOut:
case NotStepping:
- if (m_stopForStepping) { // Serve debugging requests from the agent
- m_stopForStepping = false;
- pauseAndWait(Step);
- } else if (m_pauseRequested) { // Serve debugging requests from the agent
- m_pauseRequested = false;
- pauseAndWait(PauseRequest);
- } else if (reallyHitTheBreakPoint(state.fileName, state.lineNumber)) {
- pauseAndWait(BreakPoint);
- }
+ break;
+ }
+
+ if (m_pauseRequested) { // Serve debugging requests from the agent
+ m_pauseRequested = false;
+ pauseAndWait(PauseRequest);
+ } else if (m_haveBreakPoints && reallyHitTheBreakPoint(getFunction()->sourceFile(), lineNumber)) {
+ pauseAndWait(BreakPoint);
}
}
@@ -486,8 +484,7 @@ void Debugger::enteringFunction()
QMutexLocker locker(&m_lock);
if (m_stepping == StepIn) {
- m_stepping = NotStepping;
- m_stopForStepping = true;
+ m_currentContext = m_engine->currentContext();
}
}
@@ -497,9 +494,9 @@ void Debugger::leavingFunction(const ReturnedValue &retVal)
QMutexLocker locker(&m_lock);
- if (m_stepping == StepOut || m_stepping == StepOver) {
- m_stepping = NotStepping;
- m_stopForStepping = true;
+ if (m_stepping != NotStepping && m_currentContext == m_engine->currentContext()) {
+ m_currentContext = m_engine->currentContext()->parent;
+ m_stepping = StepOver;
m_returnedValue = retVal;
}
}
@@ -552,7 +549,7 @@ void Debugger::pauseAndWait(PauseReason reason)
bool Debugger::reallyHitTheBreakPoint(const QString &filename, int linenr)
{
- BreakPoints::iterator it = m_breakPoints.find(DebuggerBreakPoint(filename, linenr));
+ BreakPoints::iterator it = m_breakPoints.find(DebuggerBreakPoint(filename.mid(filename.lastIndexOf('/') + 1), linenr));
if (it == m_breakPoints.end())
return false;
QString condition = it.value();
diff --git a/src/qml/jsruntime/qv4debugging_p.h b/src/qml/jsruntime/qv4debugging_p.h
index 9c97dd5f9e..47a7d77b28 100644
--- a/src/qml/jsruntime/qv4debugging_p.h
+++ b/src/qml/jsruntime/qv4debugging_p.h
@@ -161,14 +161,12 @@ public:
void setBreakOnThrow(bool onoff);
+ // used for testing
struct ExecutionState
{
- ExecutionState() : lineNumber(-1), function(0) {}
QString fileName;
int lineNumber;
- Function *function;
};
-
ExecutionState currentExecutionState() const;
bool pauseAtNextOpportunity() const {
@@ -203,8 +201,8 @@ private:
void runInEngine_havingLock(Debugger::Job *job);
private:
-
QV4::ExecutionEngine *m_engine;
+ QV4::ExecutionContext *m_currentContext;
DebuggerAgent *m_agent;
QMutex m_lock;
QWaitCondition m_runningCondition;
@@ -212,7 +210,6 @@ private:
Speed m_stepping;
bool m_pauseRequested;
bool m_haveBreakPoints;
- bool m_stopForStepping;
bool m_breakOnThrow;
BreakPoints m_breakPoints;