4d7871ff8fc035f2eefc44aaee2ad1c0d0163304
[WebKit-https.git] / Source / JavaScriptCore / debugger / Debugger.cpp
1 /*
2  *  Copyright (C) 2008, 2013, 2014 Apple Inc. All rights reserved.
3  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
4  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #include "config.h"
23 #include "Debugger.h"
24
25 #include "CodeBlock.h"
26 #include "DebuggerCallFrame.h"
27 #include "Error.h"
28 #include "HeapIterationScope.h"
29 #include "Interpreter.h"
30 #include "JSCJSValueInlines.h"
31 #include "JSFunction.h"
32 #include "JSGlobalObject.h"
33 #include "JSCInlines.h"
34 #include "Parser.h"
35 #include "Protect.h"
36 #include "VMEntryScope.h"
37
38 namespace {
39
40 using namespace JSC;
41
42 class Recompiler : public MarkedBlock::VoidFunctor {
43 public:
44     Recompiler(JSC::Debugger*);
45     ~Recompiler();
46     IterationStatus operator()(JSCell*);
47
48 private:
49     typedef HashSet<FunctionExecutable*> FunctionExecutableSet;
50     typedef HashMap<SourceProvider*, ExecState*> SourceProviderMap;
51     
52     void visit(JSCell*);
53     
54     JSC::Debugger* m_debugger;
55     FunctionExecutableSet m_functionExecutables;
56     SourceProviderMap m_sourceProviders;
57 };
58
59 inline Recompiler::Recompiler(JSC::Debugger* debugger)
60     : m_debugger(debugger)
61 {
62 }
63
64 inline Recompiler::~Recompiler()
65 {
66     // Call sourceParsed() after reparsing all functions because it will execute
67     // JavaScript in the inspector.
68     SourceProviderMap::const_iterator end = m_sourceProviders.end();
69     for (SourceProviderMap::const_iterator iter = m_sourceProviders.begin(); iter != end; ++iter)
70         m_debugger->sourceParsed(iter->value, iter->key, -1, String());
71 }
72
73 inline void Recompiler::visit(JSCell* cell)
74 {
75     if (!cell->inherits(JSFunction::info()))
76         return;
77
78     JSFunction* function = jsCast<JSFunction*>(cell);
79     if (function->executable()->isHostFunction())
80         return;
81
82     FunctionExecutable* executable = function->jsExecutable();
83
84     // Check if the function is already in the set - if so,
85     // we've already retranslated it, nothing to do here.
86     if (!m_functionExecutables.add(executable).isNewEntry)
87         return;
88
89     ExecState* exec = function->scope()->globalObject()->JSGlobalObject::globalExec();
90     executable->clearCode();
91     executable->clearUnlinkedCodeForRecompilation();
92     if (m_debugger == function->scope()->globalObject()->debugger())
93         m_sourceProviders.add(executable->source().provider(), exec);
94 }
95
96 inline IterationStatus Recompiler::operator()(JSCell* cell)
97 {
98     visit(cell);
99     return IterationStatus::Continue;
100 }
101
102 } // namespace
103
104 namespace JSC {
105
106 class DebuggerPausedScope {
107 public:
108     DebuggerPausedScope(Debugger& debugger)
109         : m_debugger(debugger)
110     {
111         ASSERT(!m_debugger.m_currentDebuggerCallFrame);
112         if (m_debugger.m_currentCallFrame)
113             m_debugger.m_currentDebuggerCallFrame = DebuggerCallFrame::create(debugger.m_currentCallFrame);
114     }
115
116     ~DebuggerPausedScope()
117     {
118         if (m_debugger.m_currentDebuggerCallFrame) {
119             m_debugger.m_currentDebuggerCallFrame->invalidate();
120             m_debugger.m_currentDebuggerCallFrame = nullptr;
121         }
122     }
123
124 private:
125     Debugger& m_debugger;
126 };
127
128 // This is very similar to TemporaryChange<bool>, but that cannot be used
129 // as the m_isPaused field uses only one bit.
130 class TemporaryPausedState {
131 public:
132     TemporaryPausedState(Debugger& debugger)
133         : m_debugger(debugger)
134     {
135         ASSERT(!m_debugger.m_isPaused);
136         m_debugger.m_isPaused = true;
137     }
138
139     ~TemporaryPausedState()
140     {
141         m_debugger.m_isPaused = false;
142     }
143
144 private:
145     Debugger& m_debugger;
146 };
147
148 template<typename Functor>
149 void Debugger::forEachCodeBlock(Functor& functor)
150 {
151     m_vm->prepareToDeleteCode();
152     m_vm->heap.forEachCodeBlock(functor);
153 }
154
155 Debugger::Debugger(bool isInWorkerThread)
156     : m_vm(nullptr)
157     , m_pauseOnExceptionsState(DontPauseOnExceptions)
158     , m_pauseOnNextStatement(false)
159     , m_isPaused(false)
160     , m_breakpointsActivated(true)
161     , m_hasHandlerForExceptionCallback(false)
162     , m_isInWorkerThread(isInWorkerThread)
163     , m_steppingMode(SteppingModeDisabled)
164     , m_reasonForPause(NotPaused)
165     , m_pauseOnCallFrame(0)
166     , m_currentCallFrame(0)
167     , m_lastExecutedLine(UINT_MAX)
168     , m_lastExecutedSourceID(noSourceID)
169     , m_topBreakpointID(noBreakpointID)
170     , m_pausingBreakpointID(noBreakpointID)
171 {
172 }
173
174 Debugger::~Debugger()
175 {
176     HashSet<JSGlobalObject*>::iterator end = m_globalObjects.end();
177     for (HashSet<JSGlobalObject*>::iterator it = m_globalObjects.begin(); it != end; ++it)
178         (*it)->setDebugger(0);
179 }
180
181 void Debugger::attach(JSGlobalObject* globalObject)
182 {
183     ASSERT(!globalObject->debugger());
184     if (!m_vm)
185         m_vm = &globalObject->vm();
186     else
187         ASSERT(m_vm == &globalObject->vm());
188     globalObject->setDebugger(this);
189     m_globalObjects.add(globalObject);
190 }
191
192 void Debugger::detach(JSGlobalObject* globalObject, ReasonForDetach reason)
193 {
194     // If we're detaching from the currently executing global object, manually tear down our
195     // stack, since we won't get further debugger callbacks to do so. Also, resume execution,
196     // since there's no point in staying paused once a window closes.
197     if (m_currentCallFrame && m_currentCallFrame->vmEntryGlobalObject() == globalObject) {
198         m_currentCallFrame = 0;
199         m_pauseOnCallFrame = 0;
200         continueProgram();
201     }
202
203     ASSERT(m_globalObjects.contains(globalObject));
204     m_globalObjects.remove(globalObject);
205
206     // If the globalObject is destructing, then its CodeBlocks will also be
207     // destructed. There is no need to do the debugger requests clean up, and
208     // it is not safe to access those CodeBlocks at this time anyway.
209     if (reason != GlobalObjectIsDestructing)
210         clearDebuggerRequests(globalObject);
211
212     globalObject->setDebugger(0);
213     if (!m_globalObjects.size())
214         m_vm = nullptr;
215 }
216
217 bool Debugger::isAttached(JSGlobalObject* globalObject)
218 {
219     return globalObject->debugger() == this;
220 }
221
222 class Debugger::SetSteppingModeFunctor {
223 public:
224     SetSteppingModeFunctor(Debugger* debugger, SteppingMode mode)
225         : m_debugger(debugger)
226         , m_mode(mode)
227     {
228     }
229
230     bool operator()(CodeBlock* codeBlock)
231     {
232         if (m_debugger == codeBlock->globalObject()->debugger()) {
233             if (m_mode == SteppingModeEnabled)
234                 codeBlock->setSteppingMode(CodeBlock::SteppingModeEnabled);
235             else
236                 codeBlock->setSteppingMode(CodeBlock::SteppingModeDisabled);
237         }
238         return false;
239     }
240
241 private:
242     Debugger* m_debugger;
243     SteppingMode m_mode;
244 };
245
246 void Debugger::setSteppingMode(SteppingMode mode)
247 {
248     if (mode == m_steppingMode || !m_vm)
249         return;
250
251     m_vm->prepareToDeleteCode();
252
253     m_steppingMode = mode;
254     SetSteppingModeFunctor functor(this, mode);
255     m_vm->heap.forEachCodeBlock(functor);
256 }
257
258 void Debugger::registerCodeBlock(CodeBlock* codeBlock)
259 {
260     // FIXME: We should never have to jettison a code block (due to pending breakpoints
261     // or stepping mode) that is being registered. operationOptimize() should have
262     // prevented the optimizing of such code blocks in the first place. Find a way to
263     // express this with greater clarity in the code. See <https://webkit.org/b131771>.
264     applyBreakpoints(codeBlock);
265     if (isStepping())
266         codeBlock->setSteppingMode(CodeBlock::SteppingModeEnabled);
267 }
268
269 void Debugger::toggleBreakpoint(CodeBlock* codeBlock, Breakpoint& breakpoint, BreakpointState enabledOrNot)
270 {
271     ScriptExecutable* executable = codeBlock->ownerExecutable();
272
273     SourceID sourceID = static_cast<SourceID>(executable->sourceID());
274     if (breakpoint.sourceID != sourceID)
275         return;
276
277     unsigned line = breakpoint.line;
278     unsigned column = breakpoint.column;
279
280     unsigned startLine = executable->firstLine();
281     unsigned startColumn = executable->startColumn();
282     unsigned endLine = executable->lastLine();
283     unsigned endColumn = executable->endColumn();
284
285     // Inspector breakpoint line and column values are zero-based but the executable
286     // and CodeBlock line and column values are one-based.
287     line += 1;
288     column = column ? column + 1 : Breakpoint::unspecifiedColumn;
289
290     if (line < startLine || line > endLine)
291         return;
292     if (column != Breakpoint::unspecifiedColumn) {
293         if (line == startLine && column < startColumn)
294             return;
295         if (line == endLine && column > endColumn)
296             return;
297     }
298     if (!codeBlock->hasOpDebugForLineAndColumn(line, column))
299         return;
300
301     if (enabledOrNot == BreakpointEnabled)
302         codeBlock->addBreakpoint(1);
303     else
304         codeBlock->removeBreakpoint(1);
305 }
306
307 void Debugger::applyBreakpoints(CodeBlock* codeBlock)
308 {
309     BreakpointIDToBreakpointMap& breakpoints = m_breakpointIDToBreakpoint;
310     for (auto it = breakpoints.begin(); it != breakpoints.end(); ++it) {
311         Breakpoint& breakpoint = *it->value;
312         toggleBreakpoint(codeBlock, breakpoint, BreakpointEnabled);
313     }
314 }
315
316 class Debugger::ToggleBreakpointFunctor {
317 public:
318     ToggleBreakpointFunctor(Debugger* debugger, Breakpoint& breakpoint, BreakpointState enabledOrNot)
319         : m_debugger(debugger)
320         , m_breakpoint(breakpoint)
321         , m_enabledOrNot(enabledOrNot)
322     {
323     }
324
325     bool operator()(CodeBlock* codeBlock)
326     {
327         if (m_debugger == codeBlock->globalObject()->debugger())
328             m_debugger->toggleBreakpoint(codeBlock, m_breakpoint, m_enabledOrNot);
329         return false;
330     }
331
332 private:
333     Debugger* m_debugger;
334     Breakpoint& m_breakpoint;
335     BreakpointState m_enabledOrNot;
336 };
337
338 void Debugger::toggleBreakpoint(Breakpoint& breakpoint, Debugger::BreakpointState enabledOrNot)
339 {
340     if (!m_vm)
341         return;
342     ToggleBreakpointFunctor functor(this, breakpoint, enabledOrNot);
343     forEachCodeBlock(functor);
344 }
345
346 void Debugger::recompileAllJSFunctions(VM* vm)
347 {
348     // If JavaScript is running, it's not safe to recompile, since we'll end
349     // up throwing away code that is live on the stack.
350     if (vm->entryScope) {
351         auto listener = [] (VM& vm, JSGlobalObject* globalObject) 
352         {
353             if (Debugger* debugger = globalObject->debugger())
354                 debugger->recompileAllJSFunctions(&vm);
355         };
356
357         vm->entryScope->setEntryScopeDidPopListener(this, listener);
358         return;
359     }
360
361     vm->prepareToDeleteCode();
362
363     Recompiler recompiler(this);
364     HeapIterationScope iterationScope(vm->heap);
365     vm->heap.objectSpace().forEachLiveCell(iterationScope, recompiler);
366 }
367
368 BreakpointID Debugger::setBreakpoint(Breakpoint breakpoint, unsigned& actualLine, unsigned& actualColumn)
369 {
370     SourceID sourceID = breakpoint.sourceID;
371     unsigned line = breakpoint.line;
372     unsigned column = breakpoint.column;
373
374     SourceIDToBreakpointsMap::iterator it = m_sourceIDToBreakpoints.find(sourceID);
375     if (it == m_sourceIDToBreakpoints.end())
376         it = m_sourceIDToBreakpoints.set(sourceID, LineToBreakpointsMap()).iterator;
377     LineToBreakpointsMap::iterator breaksIt = it->value.find(line);
378     if (breaksIt == it->value.end())
379         breaksIt = it->value.set(line, adoptRef(new BreakpointsList)).iterator;
380
381     BreakpointsList& breakpoints = *breaksIt->value;
382     for (Breakpoint* current = breakpoints.head(); current; current = current->next()) {
383         if (current->column == column) {
384             // The breakpoint already exists. We're not allowed to create a new
385             // breakpoint at this location. Rather than returning the breakpointID
386             // of the pre-existing breakpoint, we need to return noBreakpointID
387             // to indicate that we're not creating a new one.
388             return noBreakpointID;
389         }
390     }
391
392     BreakpointID id = ++m_topBreakpointID;
393     RELEASE_ASSERT(id != noBreakpointID);
394
395     breakpoint.id = id;
396     actualLine = line;
397     actualColumn = column;
398
399     Breakpoint* newBreakpoint = new Breakpoint(breakpoint);
400     breakpoints.append(newBreakpoint);
401     m_breakpointIDToBreakpoint.set(id, newBreakpoint);
402
403     toggleBreakpoint(breakpoint, BreakpointEnabled);
404
405     return id;
406 }
407
408 void Debugger::removeBreakpoint(BreakpointID id)
409 {
410     ASSERT(id != noBreakpointID);
411
412     BreakpointIDToBreakpointMap::iterator idIt = m_breakpointIDToBreakpoint.find(id);
413     ASSERT(idIt != m_breakpointIDToBreakpoint.end());
414     Breakpoint* breakpoint = idIt->value;
415
416     SourceID sourceID = breakpoint->sourceID;
417     ASSERT(sourceID);
418     SourceIDToBreakpointsMap::iterator it = m_sourceIDToBreakpoints.find(sourceID);
419     ASSERT(it != m_sourceIDToBreakpoints.end());
420     LineToBreakpointsMap::iterator breaksIt = it->value.find(breakpoint->line);
421     ASSERT(breaksIt != it->value.end());
422
423     toggleBreakpoint(*breakpoint, BreakpointDisabled);
424
425     BreakpointsList& breakpoints = *breaksIt->value;
426 #if !ASSERT_DISABLED
427     bool found = false;
428     for (Breakpoint* current = breakpoints.head(); current && !found; current = current->next()) {
429         if (current->id == breakpoint->id)
430             found = true;
431     }
432     ASSERT(found);
433 #endif
434
435     m_breakpointIDToBreakpoint.remove(idIt);
436     breakpoints.remove(breakpoint);
437     delete breakpoint;
438
439     if (breakpoints.isEmpty()) {
440         it->value.remove(breaksIt);
441         if (it->value.isEmpty())
442             m_sourceIDToBreakpoints.remove(it);
443     }
444 }
445
446 bool Debugger::hasBreakpoint(SourceID sourceID, const TextPosition& position, Breakpoint *hitBreakpoint)
447 {
448     if (!m_breakpointsActivated)
449         return false;
450
451     SourceIDToBreakpointsMap::const_iterator it = m_sourceIDToBreakpoints.find(sourceID);
452     if (it == m_sourceIDToBreakpoints.end())
453         return false;
454
455     unsigned line = position.m_line.zeroBasedInt();
456     unsigned column = position.m_column.zeroBasedInt();
457
458     LineToBreakpointsMap::const_iterator breaksIt = it->value.find(line);
459     if (breaksIt == it->value.end())
460         return false;
461
462     bool hit = false;
463     const BreakpointsList& breakpoints = *breaksIt->value;
464     Breakpoint* breakpoint;
465     for (breakpoint = breakpoints.head(); breakpoint; breakpoint = breakpoint->next()) {
466         unsigned breakLine = breakpoint->line;
467         unsigned breakColumn = breakpoint->column;
468         // Since frontend truncates the indent, the first statement in a line must match the breakpoint (line,0).
469         ASSERT(this == m_currentCallFrame->codeBlock()->globalObject()->debugger());
470         if ((line != m_lastExecutedLine && line == breakLine && !breakColumn)
471             || (line == breakLine && column == breakColumn)) {
472             hit = true;
473             break;
474         }
475     }
476     if (!hit)
477         return false;
478
479     if (hitBreakpoint)
480         *hitBreakpoint = *breakpoint;
481
482     if (breakpoint->condition.isEmpty())
483         return true;
484
485     // We cannot stop in the debugger while executing condition code,
486     // so make it looks like the debugger is already paused.
487     TemporaryPausedState pausedState(*this);
488
489     NakedPtr<Exception> exception;
490     DebuggerCallFrame* debuggerCallFrame = currentDebuggerCallFrame();
491     JSValue result = debuggerCallFrame->evaluate(breakpoint->condition, exception);
492
493     // We can lose the debugger while executing JavaScript.
494     if (!m_currentCallFrame)
495         return false;
496
497     if (exception) {
498         // An erroneous condition counts as "false".
499         handleExceptionInBreakpointCondition(m_currentCallFrame, exception);
500         return false;
501     }
502
503     return result.toBoolean(m_currentCallFrame);
504 }
505
506 class Debugger::ClearCodeBlockDebuggerRequestsFunctor {
507 public:
508     ClearCodeBlockDebuggerRequestsFunctor(Debugger* debugger)
509         : m_debugger(debugger)
510     {
511     }
512
513     bool operator()(CodeBlock* codeBlock)
514     {
515         if (codeBlock->hasDebuggerRequests() && m_debugger == codeBlock->globalObject()->debugger())
516             codeBlock->clearDebuggerRequests();
517         return false;
518     }
519
520 private:
521     Debugger* m_debugger;
522 };
523
524 void Debugger::clearBreakpoints()
525 {
526     m_topBreakpointID = noBreakpointID;
527     m_breakpointIDToBreakpoint.clear();
528     m_sourceIDToBreakpoints.clear();
529
530     if (!m_vm)
531         return;
532     ClearCodeBlockDebuggerRequestsFunctor functor(this);
533     forEachCodeBlock(functor);
534 }
535
536 class Debugger::ClearDebuggerRequestsFunctor {
537 public:
538     ClearDebuggerRequestsFunctor(JSGlobalObject* globalObject)
539         : m_globalObject(globalObject)
540     {
541     }
542
543     bool operator()(CodeBlock* codeBlock)
544     {
545         if (codeBlock->hasDebuggerRequests() && m_globalObject == codeBlock->globalObject())
546             codeBlock->clearDebuggerRequests();
547         return false;
548     }
549
550 private:
551     JSGlobalObject* m_globalObject;
552 };
553
554 void Debugger::clearDebuggerRequests(JSGlobalObject* globalObject)
555 {
556     ASSERT(m_vm);
557     ClearDebuggerRequestsFunctor functor(globalObject);
558     forEachCodeBlock(functor);
559 }
560
561 void Debugger::setBreakpointsActivated(bool activated)
562 {
563     m_breakpointsActivated = activated;
564 }
565
566 void Debugger::setPauseOnExceptionsState(PauseOnExceptionsState pause)
567 {
568     m_pauseOnExceptionsState = pause;
569 }
570
571 void Debugger::setPauseOnNextStatement(bool pause)
572 {
573     m_pauseOnNextStatement = pause;
574     if (pause)
575         setSteppingMode(SteppingModeEnabled);
576 }
577
578 void Debugger::breakProgram()
579 {
580     if (m_isPaused)
581         return;
582
583     m_pauseOnNextStatement = true;
584     setSteppingMode(SteppingModeEnabled);
585     m_currentCallFrame = m_vm->topCallFrame;
586     ASSERT(m_currentCallFrame);
587     pauseIfNeeded(m_currentCallFrame);
588 }
589
590 void Debugger::continueProgram()
591 {
592     if (!m_isPaused)
593         return;
594
595     m_pauseOnNextStatement = false;
596     notifyDoneProcessingDebuggerEvents();
597 }
598
599 void Debugger::stepIntoStatement()
600 {
601     if (!m_isPaused)
602         return;
603
604     m_pauseOnNextStatement = true;
605     setSteppingMode(SteppingModeEnabled);
606     notifyDoneProcessingDebuggerEvents();
607 }
608
609 void Debugger::stepOverStatement()
610 {
611     if (!m_isPaused)
612         return;
613
614     m_pauseOnCallFrame = m_currentCallFrame;
615     notifyDoneProcessingDebuggerEvents();
616 }
617
618 void Debugger::stepOutOfFunction()
619 {
620     if (!m_isPaused)
621         return;
622
623     VMEntryFrame* topVMEntryFrame = m_vm->topVMEntryFrame;
624     m_pauseOnCallFrame = m_currentCallFrame ? m_currentCallFrame->callerFrame(topVMEntryFrame) : 0;
625     notifyDoneProcessingDebuggerEvents();
626 }
627
628 void Debugger::updateCallFrame(CallFrame* callFrame)
629 {
630     m_currentCallFrame = callFrame;
631     SourceID sourceID = DebuggerCallFrame::sourceIDForCallFrame(callFrame);
632     if (m_lastExecutedSourceID != sourceID) {
633         m_lastExecutedLine = UINT_MAX;
634         m_lastExecutedSourceID = sourceID;
635     }
636 }
637
638 void Debugger::updateCallFrameAndPauseIfNeeded(CallFrame* callFrame)
639 {
640     updateCallFrame(callFrame);
641     pauseIfNeeded(callFrame);
642     if (!isStepping())
643         m_currentCallFrame = 0;
644 }
645
646 void Debugger::pauseIfNeeded(CallFrame* callFrame)
647 {
648     if (m_isPaused)
649         return;
650
651     JSGlobalObject* vmEntryGlobalObject = callFrame->vmEntryGlobalObject();
652     if (!needPauseHandling(vmEntryGlobalObject))
653         return;
654
655     Breakpoint breakpoint;
656     bool didHitBreakpoint = false;
657     bool pauseNow = m_pauseOnNextStatement;
658     pauseNow |= (m_pauseOnCallFrame == m_currentCallFrame);
659
660     DebuggerPausedScope debuggerPausedScope(*this);
661
662     intptr_t sourceID = DebuggerCallFrame::sourceIDForCallFrame(m_currentCallFrame);
663     TextPosition position = DebuggerCallFrame::positionForCallFrame(m_currentCallFrame);
664     pauseNow |= didHitBreakpoint = hasBreakpoint(sourceID, position, &breakpoint);
665     m_lastExecutedLine = position.m_line.zeroBasedInt();
666     if (!pauseNow)
667         return;
668
669     // Make sure we are not going to pause again on breakpoint actions by
670     // reseting the pause state before executing any breakpoint actions.
671     TemporaryPausedState pausedState(*this);
672     m_pauseOnCallFrame = 0;
673     m_pauseOnNextStatement = false;
674
675     if (didHitBreakpoint) {
676         handleBreakpointHit(vmEntryGlobalObject, breakpoint);
677         // Note that the actions can potentially stop the debugger, so we need to check that
678         // we still have a current call frame when we get back.
679         if (breakpoint.autoContinue || !m_currentCallFrame)
680             return;
681         m_pausingBreakpointID = breakpoint.id;
682     }
683
684     {
685         PauseReasonDeclaration reason(*this, didHitBreakpoint ? PausedForBreakpoint : m_reasonForPause);
686         handlePause(vmEntryGlobalObject, m_reasonForPause);
687     }
688
689     m_pausingBreakpointID = noBreakpointID;
690
691     if (!m_pauseOnNextStatement && !m_pauseOnCallFrame) {
692         setSteppingMode(SteppingModeDisabled);
693         m_currentCallFrame = nullptr;
694     }
695 }
696
697 void Debugger::exception(CallFrame* callFrame, JSValue exception, bool hasCatchHandler)
698 {
699     if (m_isPaused)
700         return;
701
702     PauseReasonDeclaration reason(*this, PausedForException);
703     if (m_pauseOnExceptionsState == PauseOnAllExceptions || (m_pauseOnExceptionsState == PauseOnUncaughtExceptions && !hasCatchHandler)) {
704         m_pauseOnNextStatement = true;
705         setSteppingMode(SteppingModeEnabled);
706     }
707
708     m_hasHandlerForExceptionCallback = true;
709     m_currentException = exception;
710     updateCallFrameAndPauseIfNeeded(callFrame);
711     m_currentException = JSValue();
712     m_hasHandlerForExceptionCallback = false;
713 }
714
715 void Debugger::atStatement(CallFrame* callFrame)
716 {
717     if (m_isPaused)
718         return;
719
720     PauseReasonDeclaration reason(*this, PausedAtStatement);
721     updateCallFrameAndPauseIfNeeded(callFrame);
722 }
723
724 void Debugger::callEvent(CallFrame* callFrame)
725 {
726     if (m_isPaused)
727         return;
728
729     PauseReasonDeclaration reason(*this, PausedAfterCall);
730     updateCallFrameAndPauseIfNeeded(callFrame);
731 }
732
733 void Debugger::returnEvent(CallFrame* callFrame)
734 {
735     if (m_isPaused)
736         return;
737
738     PauseReasonDeclaration reason(*this, PausedBeforeReturn);
739     updateCallFrameAndPauseIfNeeded(callFrame);
740
741     // detach may have been called during pauseIfNeeded
742     if (!m_currentCallFrame)
743         return;
744
745     // Treat stepping over a return statement like stepping out.
746     if (m_currentCallFrame == m_pauseOnCallFrame) {
747         VMEntryFrame* topVMEntryFrame = m_vm->topVMEntryFrame;
748         m_pauseOnCallFrame = m_currentCallFrame->callerFrame(topVMEntryFrame);
749     }
750
751     VMEntryFrame* topVMEntryFrame = m_vm->topVMEntryFrame;
752     m_currentCallFrame = m_currentCallFrame->callerFrame(topVMEntryFrame);
753 }
754
755 void Debugger::willExecuteProgram(CallFrame* callFrame)
756 {
757     if (m_isPaused)
758         return;
759
760     PauseReasonDeclaration reason(*this, PausedAtStartOfProgram);
761     // FIXME: This check for whether we're debugging a worker thread is a workaround
762     // for https://bugs.webkit.org/show_bug.cgi?id=102637. Remove it when we rework
763     // the debugger implementation to not require callbacks.
764     if (!m_isInWorkerThread)
765         updateCallFrameAndPauseIfNeeded(callFrame);
766     else if (isStepping())
767         updateCallFrame(callFrame);
768 }
769
770 void Debugger::didExecuteProgram(CallFrame* callFrame)
771 {
772     if (m_isPaused)
773         return;
774
775     PauseReasonDeclaration reason(*this, PausedAtEndOfProgram);
776     updateCallFrameAndPauseIfNeeded(callFrame);
777
778     // Treat stepping over the end of a program like stepping out.
779     if (!m_currentCallFrame)
780         return;
781     if (m_currentCallFrame == m_pauseOnCallFrame) {
782         VMEntryFrame* topVMEntryFrame = m_vm->topVMEntryFrame;
783         m_pauseOnCallFrame = m_currentCallFrame->callerFrame(topVMEntryFrame);
784         if (!m_currentCallFrame)
785             return;
786     }
787     VMEntryFrame* topVMEntryFrame = m_vm->topVMEntryFrame;
788     m_currentCallFrame = m_currentCallFrame->callerFrame(topVMEntryFrame);
789 }
790
791 void Debugger::didReachBreakpoint(CallFrame* callFrame)
792 {
793     if (m_isPaused)
794         return;
795
796     PauseReasonDeclaration reason(*this, PausedForDebuggerStatement);
797     m_pauseOnNextStatement = true;
798     setSteppingMode(SteppingModeEnabled);
799     updateCallFrameAndPauseIfNeeded(callFrame);
800 }
801
802 DebuggerCallFrame* Debugger::currentDebuggerCallFrame() const
803 {
804     ASSERT(m_currentDebuggerCallFrame);
805     return m_currentDebuggerCallFrame.get();
806 }
807
808 } // namespace JSC