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