2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 * Copyright (C) 2008, 2009, 2013, 2014 Apple Inc. All rights reserved.
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.
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.
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
25 #include "Breakpoint.h"
26 #include "DebuggerCallFrame.h"
27 #include "DebuggerPrimitives.h"
28 #include "JSCJSValue.h"
29 #include <wtf/HashMap.h>
30 #include <wtf/HashSet.h>
31 #include <wtf/RefPtr.h>
32 #include <wtf/text/TextPosition.h>
43 typedef ExecState CallFrame
;
45 class JS_EXPORT_PRIVATE Debugger
{
47 Debugger(bool isInWorkerThread
= false);
50 JSC::DebuggerCallFrame
* currentDebuggerCallFrame() const;
51 bool hasHandlerForExceptionCallback() const
53 ASSERT(m_reasonForPause
== PausedForException
);
54 return m_hasHandlerForExceptionCallback
;
56 JSValue
currentException()
58 ASSERT(m_reasonForPause
== PausedForException
);
59 return m_currentException
;
62 bool needsExceptionCallbacks() const { return m_pauseOnExceptionsState
!= DontPauseOnExceptions
; }
64 enum ReasonForDetach
{
65 TerminatingDebuggingSession
,
66 GlobalObjectIsDestructing
68 void attach(JSGlobalObject
*);
69 void detach(JSGlobalObject
*, ReasonForDetach
);
70 bool isAttached(JSGlobalObject
*);
72 BreakpointID
setBreakpoint(Breakpoint
, unsigned& actualLine
, unsigned& actualColumn
);
73 void removeBreakpoint(BreakpointID
);
74 void clearBreakpoints();
75 void setBreakpointsActivated(bool);
76 void activateBreakpoints() { setBreakpointsActivated(true); }
77 void deactivateBreakpoints() { setBreakpointsActivated(false); }
79 enum PauseOnExceptionsState
{
80 DontPauseOnExceptions
,
82 PauseOnUncaughtExceptions
84 PauseOnExceptionsState
pauseOnExceptionsState() const { return m_pauseOnExceptionsState
; }
85 void setPauseOnExceptionsState(PauseOnExceptionsState
);
93 PausedAtStartOfProgram
,
96 PausedForDebuggerStatement
,
98 ReasonForPause
reasonForPause() const { return m_reasonForPause
; }
99 BreakpointID
pausingBreakpointID() const { return m_pausingBreakpointID
; }
101 void setPauseOnNextStatement(bool);
103 void continueProgram();
104 void stepIntoStatement();
105 void stepOverStatement();
106 void stepOutOfFunction();
108 bool isPaused() const { return m_isPaused
; }
109 bool isStepping() const { return m_steppingMode
== SteppingModeEnabled
; }
111 virtual void sourceParsed(ExecState
*, SourceProvider
*, int errorLineNumber
, const WTF::String
& errorMessage
) = 0;
113 void exception(CallFrame
*, JSValue exceptionValue
, bool hasCatchHandler
);
114 void atStatement(CallFrame
*);
115 void callEvent(CallFrame
*);
116 void returnEvent(CallFrame
*);
117 void willExecuteProgram(CallFrame
*);
118 void didExecuteProgram(CallFrame
*);
119 void didReachBreakpoint(CallFrame
*);
121 void recompileAllJSFunctions(VM
*);
123 void registerCodeBlock(CodeBlock
*);
126 virtual bool needPauseHandling(JSGlobalObject
*) { return false; }
127 virtual void handleBreakpointHit(JSGlobalObject
*, const Breakpoint
&) { }
128 virtual void handleExceptionInBreakpointCondition(ExecState
*, Exception
*) const { }
129 virtual void handlePause(JSGlobalObject
*, ReasonForPause
) { }
130 virtual void notifyDoneProcessingDebuggerEvents() { }
133 typedef HashMap
<BreakpointID
, Breakpoint
*> BreakpointIDToBreakpointMap
;
135 typedef HashMap
<unsigned, RefPtr
<BreakpointsList
>, WTF::IntHash
<int>, WTF::UnsignedWithZeroKeyHashTraits
<int>> LineToBreakpointsMap
;
136 typedef HashMap
<SourceID
, LineToBreakpointsMap
, WTF::IntHash
<SourceID
>, WTF::UnsignedWithZeroKeyHashTraits
<SourceID
>> SourceIDToBreakpointsMap
;
138 class ClearCodeBlockDebuggerRequestsFunctor
;
139 class ClearDebuggerRequestsFunctor
;
140 class SetSteppingModeFunctor
;
141 class ToggleBreakpointFunctor
;
143 class PauseReasonDeclaration
{
145 PauseReasonDeclaration(Debugger
& debugger
, ReasonForPause reason
)
146 : m_debugger(debugger
)
148 m_debugger
.m_reasonForPause
= reason
;
151 ~PauseReasonDeclaration()
153 m_debugger
.m_reasonForPause
= NotPaused
;
156 Debugger
& m_debugger
;
159 bool hasBreakpoint(SourceID
, const TextPosition
&, Breakpoint
* hitBreakpoint
);
161 void updateNeedForOpDebugCallbacks();
163 // These update functions are only needed because our current breakpoints are
164 // key'ed off the source position instead of the bytecode PC. This ensures
165 // that we don't break on the same line more than once. Once we switch to a
166 // bytecode PC key'ed breakpoint, we will not need these anymore and should
167 // be able to remove them.
168 void updateCallFrame(JSC::CallFrame
*);
169 void updateCallFrameAndPauseIfNeeded(JSC::CallFrame
*);
170 void pauseIfNeeded(JSC::CallFrame
*);
173 SteppingModeDisabled
,
176 void setSteppingMode(SteppingMode
);
178 enum BreakpointState
{
182 void toggleBreakpoint(CodeBlock
*, Breakpoint
&, BreakpointState
);
183 void applyBreakpoints(CodeBlock
*);
184 void toggleBreakpoint(Breakpoint
&, BreakpointState
);
186 void clearDebuggerRequests(JSGlobalObject
*);
188 template<typename Functor
> inline void forEachCodeBlock(Functor
&);
191 HashSet
<JSGlobalObject
*> m_globalObjects
;
193 PauseOnExceptionsState m_pauseOnExceptionsState
;
194 bool m_pauseOnNextStatement
: 1;
196 bool m_breakpointsActivated
: 1;
197 bool m_hasHandlerForExceptionCallback
: 1;
198 bool m_isInWorkerThread
: 1;
199 unsigned m_steppingMode
: 1; // SteppingMode
201 ReasonForPause m_reasonForPause
;
202 JSValue m_currentException
;
203 CallFrame
* m_pauseOnCallFrame
;
204 CallFrame
* m_currentCallFrame
;
205 unsigned m_lastExecutedLine
;
206 SourceID m_lastExecutedSourceID
;
208 BreakpointID m_topBreakpointID
;
209 BreakpointID m_pausingBreakpointID
;
210 BreakpointIDToBreakpointMap m_breakpointIDToBreakpoint
;
211 SourceIDToBreakpointsMap m_sourceIDToBreakpoints
;
213 RefPtr
<JSC::DebuggerCallFrame
> m_currentDebuggerCallFrame
;
215 friend class DebuggerPausedScope
;
216 friend class TemporaryPausedState
;
217 friend class LLIntOffsetsExtractor
;