aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4debugging.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime/qv4debugging.cpp')
-rw-r--r--src/qml/jsruntime/qv4debugging.cpp233
1 files changed, 32 insertions, 201 deletions
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp
index dade627206..7d19c7804e 100644
--- a/src/qml/jsruntime/qv4debugging.cpp
+++ b/src/qml/jsruntime/qv4debugging.cpp
@@ -115,14 +115,13 @@ Debugger::Debugger(QV4::ExecutionEngine *engine)
: m_engine(engine)
, m_agent(0)
, m_state(Running)
- , m_pauseRequested(false)
- , m_gatherSources(0)
- , m_havePendingBreakPoints(false)
- , m_currentInstructionPointer(0)
, m_stepping(NotStepping)
+ , m_pauseRequested(false)
+ , m_haveBreakPoints(false)
, m_stopForStepping(false)
- , m_returnedValue(Primitive::undefinedValue())
, m_breakOnThrow(false)
+ , m_returnedValue(Primitive::undefinedValue())
+ , m_gatherSources(0)
, m_runningJob(0)
{
qMetaTypeId<Debugger*>();
@@ -181,12 +180,6 @@ void Debugger::resume(Speed speed)
if (!m_returnedValue.isUndefined())
m_returnedValue = Encode::undefined();
- clearTemporaryBreakPoints();
- if (speed == StepOver)
- setTemporaryBreakPointOnNextLine();
- if (speed == StepOut)
- m_temporaryBreakPoints = TemporaryBreakPoint(getFunction(), m_engine->currentContext());
-
m_stepping = speed;
m_runningCondition.wakeAll();
}
@@ -194,20 +187,15 @@ void Debugger::resume(Speed speed)
void Debugger::addBreakPoint(const QString &fileName, int lineNumber, const QString &condition)
{
QMutexLocker locker(&m_lock);
- if (!m_pendingBreakPointsToRemove.remove(fileName, lineNumber))
- m_pendingBreakPointsToAdd.add(fileName, lineNumber);
- m_havePendingBreakPoints = !m_pendingBreakPointsToAdd.isEmpty() || !m_pendingBreakPointsToRemove.isEmpty();
- if (!condition.isEmpty())
- m_breakPointConditions.add(fileName, lineNumber, condition);
+ m_breakPoints.insert(DebuggerBreakPoint(fileName, lineNumber), condition);
+ m_haveBreakPoints = true;
}
void Debugger::removeBreakPoint(const QString &fileName, int lineNumber)
{
QMutexLocker locker(&m_lock);
- if (!m_pendingBreakPointsToAdd.remove(fileName, lineNumber))
- m_pendingBreakPointsToRemove.add(fileName, lineNumber);
- m_havePendingBreakPoints = !m_pendingBreakPointsToAdd.isEmpty() || !m_pendingBreakPointsToRemove.isEmpty();
- m_breakPointConditions.remove(fileName, lineNumber);
+ m_breakPoints.remove(DebuggerBreakPoint(fileName, lineNumber));
+ m_haveBreakPoints = !m_breakPoints.isEmpty();
}
void Debugger::setBreakOnThrow(bool onoff)
@@ -217,27 +205,17 @@ void Debugger::setBreakOnThrow(bool onoff)
m_breakOnThrow = onoff;
}
-Debugger::ExecutionState Debugger::currentExecutionState(const uchar *code) const
+Debugger::ExecutionState Debugger::currentExecutionState(int lineNumber) const
{
- if (!code)
- code = m_currentInstructionPointer;
// ### Locking
ExecutionState state;
-
state.function = getFunction();
state.fileName = state.function->sourceFile();
-
- qptrdiff relativeProgramCounter = code - state.function->codeData;
- state.lineNumber = state.function->lineNumberForProgramCounter(relativeProgramCounter);
+ state.lineNumber = lineNumber;
return state;
}
-void Debugger::setPendingBreakpoints(Function *function)
-{
- m_pendingBreakPointsToAddToFutureCode.applyToFunction(function, /*removeBreakPoints*/ false);
-}
-
QVector<StackFrame> Debugger::stackTrace(int frameLimit) const
{
return m_engine->stackTrace(frameLimit);
@@ -467,23 +445,16 @@ QVector<ExecutionContext::ContextType> Debugger::getScopeTypes(int frame) const
return types;
}
-void Debugger::maybeBreakAtInstruction(const uchar *code, bool breakPointHit)
+void Debugger::maybeBreakAtInstruction(int lineNumber)
{
if (m_runningJob) // do not re-enter when we're doing a job for the debugger.
return;
QMutexLocker locker(&m_lock);
- m_currentInstructionPointer = code;
-
- ExecutionState state = currentExecutionState();
+ if (m_breakPoints.isEmpty())
+ return;
- // Do debugger internal work
- if (m_havePendingBreakPoints) {
- if (breakPointHit)
- breakPointHit = !m_pendingBreakPointsToRemove.contains(state.fileName, state.lineNumber);
-
- applyPendingBreakPoints();
- }
+ ExecutionState state = currentExecutionState(lineNumber);
if (m_gatherSources) {
m_gatherSources->run();
@@ -491,23 +462,23 @@ void Debugger::maybeBreakAtInstruction(const uchar *code, bool breakPointHit)
m_gatherSources = 0;
}
- if (m_stopForStepping) {
- clearTemporaryBreakPoints();
- m_stopForStepping = false;
- m_pauseRequested = false;
+ switch (m_stepping) {
+ case StepOver:
+ case StepIn:
pauseAndWait(Step);
- } else if (m_pauseRequested) { // Serve debugging requests from the agent
- m_pauseRequested = false;
- pauseAndWait(PauseRequest);
- } else if (breakPointHit) {
- if (m_stepping == StepOver && m_temporaryBreakPoints.context == m_engine->currentContext())
+ break;
+ case StepOut:
+ case NotStepping:
+ if (m_stopForStepping) { // Serve debugging requests from the agent
+ m_stopForStepping = false;
pauseAndWait(Step);
- else if (reallyHitTheBreakPoint(state.fileName, state.lineNumber))
+ } else if (m_pauseRequested) { // Serve debugging requests from the agent
+ m_pauseRequested = false;
+ pauseAndWait(PauseRequest);
+ } else if (reallyHitTheBreakPoint(state.fileName, state.lineNumber)) {
pauseAndWait(BreakPoint);
+ }
}
-
- if (!m_pendingBreakPointsToAdd.isEmpty() || !m_pendingBreakPointsToRemove.isEmpty())
- applyPendingBreakPoints();
}
void Debugger::enteringFunction()
@@ -517,7 +488,6 @@ void Debugger::enteringFunction()
if (m_stepping == StepIn) {
m_stepping = NotStepping;
m_stopForStepping = true;
- m_pauseRequested = true;
}
}
@@ -527,12 +497,9 @@ void Debugger::leavingFunction(const ReturnedValue &retVal)
QMutexLocker locker(&m_lock);
- if ((m_stepping == StepOut || m_stepping == StepOver)
- && temporaryBreakPointInFunction(m_engine->currentContext())) {
- clearTemporaryBreakPoints();
+ if (m_stepping == StepOut || m_stepping == StepOver) {
m_stepping = NotStepping;
m_stopForStepping = true;
- m_pauseRequested = true;
m_returnedValue = retVal;
}
}
@@ -546,7 +513,6 @@ void Debugger::aboutToThrow()
return;
QMutexLocker locker(&m_lock);
- clearTemporaryBreakPoints();
pauseAndWait(Throwing);
}
@@ -584,84 +550,12 @@ void Debugger::pauseAndWait(PauseReason reason)
m_state = Running;
}
-void Debugger::setTemporaryBreakPointOnNextLine()
-{
- ExecutionState state = currentExecutionState();
- Function *function = state.function;
- if (!function)
- return;
-
- QList<qptrdiff> pcs = function->programCountersForAllLines();
- if (pcs.isEmpty())
- return;
-
- m_temporaryBreakPoints = TemporaryBreakPoint(function, m_engine->currentContext());
- 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_temporaryBreakPoints.codeOffsets.append(offset);
- }
-}
-
-void Debugger::clearTemporaryBreakPoints()
-{
- if (m_temporaryBreakPoints.function) {
- foreach (quintptr offset, m_temporaryBreakPoints.codeOffsets)
- setBreakOnInstruction(m_temporaryBreakPoints.function, offset, false);
- m_temporaryBreakPoints = TemporaryBreakPoint();
- }
-}
-
-bool Debugger::temporaryBreakPointInFunction(ExecutionContext *context) const
-{
- return m_temporaryBreakPoints.function == getFunction()
- && m_temporaryBreakPoints.context == context;
-}
-
-void Debugger::applyPendingBreakPoints()
-{
- foreach (QV4::CompiledData::CompilationUnit *unit, m_engine->compilationUnits) {
- foreach (Function *function, unit->runtimeFunctions) {
- m_pendingBreakPointsToAdd.applyToFunction(function, /*removeBreakPoints*/false);
- m_pendingBreakPointsToRemove.applyToFunction(function, /*removeBreakPoints*/true);
- }
- }
-
- for (BreakPoints::ConstIterator it = m_pendingBreakPointsToAdd.constBegin(),
- end = m_pendingBreakPointsToAdd.constEnd(); it != end; ++it) {
- foreach (int lineNumber, it.value())
- m_pendingBreakPointsToAddToFutureCode.add(it.key(), lineNumber);
- }
-
- m_pendingBreakPointsToAdd.clear();
- m_pendingBreakPointsToRemove.clear();
- m_havePendingBreakPoints = false;
-}
-
-void Debugger::setBreakOnInstruction(Function *function, qptrdiff codeOffset, bool onoff)
-{
- uchar *codePtr = const_cast<uchar *>(function->codeData) + codeOffset;
- Moth::Instr::instr_debug *debug = reinterpret_cast<Moth::Instr::instr_debug *>(codePtr);
- debug->breakPoint = onoff;
-}
-
-bool Debugger::hasBreakOnInstruction(Function *function, qptrdiff codeOffset)
-{
- uchar *codePtr = const_cast<uchar *>(function->codeData) + codeOffset;
- Moth::Instr::instr_debug *debug = reinterpret_cast<Moth::Instr::instr_debug *>(codePtr);
- return debug->breakPoint;
-}
-
bool Debugger::reallyHitTheBreakPoint(const QString &filename, int linenr)
{
- QString condition = m_breakPointConditions.condition(filename, linenr);
+ BreakPoints::iterator it = m_breakPoints.find(DebuggerBreakPoint(filename, linenr));
+ if (it == m_breakPoints.end())
+ return false;
+ QString condition = it.value();
if (condition.isEmpty())
return true;
@@ -798,69 +692,6 @@ DebuggerAgent::~DebuggerAgent()
Q_ASSERT(m_debuggers.isEmpty());
}
-void Debugger::BreakPoints::add(const QString &fileName, int lineNumber)
-{
- QList<int> &lines = (*this)[fileName];
- if (!lines.contains(lineNumber)) {
- lines.append(lineNumber);
- std::sort(lines.begin(), lines.end());
- }
-}
-
-bool Debugger::BreakPoints::remove(const QString &fileName, int lineNumber)
-{
- Iterator breakPoints = find(fileName);
- if (breakPoints == constEnd())
- return false;
- return breakPoints->removeAll(lineNumber) > 0;
-}
-
-bool Debugger::BreakPoints::contains(const QString &fileName, int lineNumber) const
-{
- ConstIterator breakPoints = find(fileName);
- if (breakPoints == constEnd())
- return false;
- return breakPoints->contains(lineNumber);
-}
-
-void Debugger::BreakPoints::applyToFunction(Function *function, bool removeBreakPoints)
-{
- Iterator breakPointsForFile = begin();
-
- while (breakPointsForFile != end()) {
- if (!function->sourceFile().endsWith(breakPointsForFile.key())) {
- ++breakPointsForFile;
- continue;
- }
-
- QList<int>::Iterator breakPoint = breakPointsForFile->begin();
- while (breakPoint != breakPointsForFile->end()) {
- bool breakPointFound = false;
- const quint32 *lineNumberMappings = function->compiledFunction->lineNumberMapping();
- for (quint32 i = 0; i < function->compiledFunction->nLineNumberMappingEntries; ++i) {
- const int codeOffset = lineNumberMappings[i * 2];
- const int lineNumber = lineNumberMappings[i * 2 + 1];
- if (lineNumber == *breakPoint) {
- setBreakOnInstruction(function, codeOffset, !removeBreakPoints);
- // Continue setting the next break point.
- breakPointFound = true;
- break;
- }
- }
- if (breakPointFound)
- breakPoint = breakPointsForFile->erase(breakPoint);
- else
- ++breakPoint;
- }
-
- if (breakPointsForFile->isEmpty())
- breakPointsForFile = erase(breakPointsForFile);
- else
- ++breakPointsForFile;
- }
-}
-
-
Debugger::Collector::~Collector()
{
}