]> git.saurik.com Git - apple/javascriptcore.git/blob - debugger/Debugger.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / debugger / Debugger.h
1 /*
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.
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 #ifndef Debugger_h
23 #define Debugger_h
24
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>
33
34 namespace JSC {
35
36 class CodeBlock;
37 class Exception;
38 class ExecState;
39 class JSGlobalObject;
40 class SourceProvider;
41 class VM;
42
43 typedef ExecState CallFrame;
44
45 class JS_EXPORT_PRIVATE Debugger {
46 public:
47 Debugger(bool isInWorkerThread = false);
48 virtual ~Debugger();
49
50 JSC::DebuggerCallFrame* currentDebuggerCallFrame() const;
51 bool hasHandlerForExceptionCallback() const
52 {
53 ASSERT(m_reasonForPause == PausedForException);
54 return m_hasHandlerForExceptionCallback;
55 }
56 JSValue currentException()
57 {
58 ASSERT(m_reasonForPause == PausedForException);
59 return m_currentException;
60 }
61
62 bool needsExceptionCallbacks() const { return m_pauseOnExceptionsState != DontPauseOnExceptions; }
63
64 enum ReasonForDetach {
65 TerminatingDebuggingSession,
66 GlobalObjectIsDestructing
67 };
68 void attach(JSGlobalObject*);
69 void detach(JSGlobalObject*, ReasonForDetach);
70 bool isAttached(JSGlobalObject*);
71
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); }
78
79 enum PauseOnExceptionsState {
80 DontPauseOnExceptions,
81 PauseOnAllExceptions,
82 PauseOnUncaughtExceptions
83 };
84 PauseOnExceptionsState pauseOnExceptionsState() const { return m_pauseOnExceptionsState; }
85 void setPauseOnExceptionsState(PauseOnExceptionsState);
86
87 enum ReasonForPause {
88 NotPaused,
89 PausedForException,
90 PausedAtStatement,
91 PausedAfterCall,
92 PausedBeforeReturn,
93 PausedAtStartOfProgram,
94 PausedAtEndOfProgram,
95 PausedForBreakpoint,
96 PausedForDebuggerStatement,
97 };
98 ReasonForPause reasonForPause() const { return m_reasonForPause; }
99 BreakpointID pausingBreakpointID() const { return m_pausingBreakpointID; }
100
101 void setPauseOnNextStatement(bool);
102 void breakProgram();
103 void continueProgram();
104 void stepIntoStatement();
105 void stepOverStatement();
106 void stepOutOfFunction();
107
108 bool isPaused() const { return m_isPaused; }
109 bool isStepping() const { return m_steppingMode == SteppingModeEnabled; }
110
111 virtual void sourceParsed(ExecState*, SourceProvider*, int errorLineNumber, const WTF::String& errorMessage) = 0;
112
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*);
120
121 void recompileAllJSFunctions(VM*);
122
123 void registerCodeBlock(CodeBlock*);
124
125 protected:
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() { }
131
132 private:
133 typedef HashMap<BreakpointID, Breakpoint*> BreakpointIDToBreakpointMap;
134
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;
137
138 class ClearCodeBlockDebuggerRequestsFunctor;
139 class ClearDebuggerRequestsFunctor;
140 class SetSteppingModeFunctor;
141 class ToggleBreakpointFunctor;
142
143 class PauseReasonDeclaration {
144 public:
145 PauseReasonDeclaration(Debugger& debugger, ReasonForPause reason)
146 : m_debugger(debugger)
147 {
148 m_debugger.m_reasonForPause = reason;
149 }
150
151 ~PauseReasonDeclaration()
152 {
153 m_debugger.m_reasonForPause = NotPaused;
154 }
155 private:
156 Debugger& m_debugger;
157 };
158
159 bool hasBreakpoint(SourceID, const TextPosition&, Breakpoint* hitBreakpoint);
160
161 void updateNeedForOpDebugCallbacks();
162
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*);
171
172 enum SteppingMode {
173 SteppingModeDisabled,
174 SteppingModeEnabled
175 };
176 void setSteppingMode(SteppingMode);
177
178 enum BreakpointState {
179 BreakpointDisabled,
180 BreakpointEnabled
181 };
182 void toggleBreakpoint(CodeBlock*, Breakpoint&, BreakpointState);
183 void applyBreakpoints(CodeBlock*);
184 void toggleBreakpoint(Breakpoint&, BreakpointState);
185
186 void clearDebuggerRequests(JSGlobalObject*);
187
188 template<typename Functor> inline void forEachCodeBlock(Functor&);
189
190 VM* m_vm;
191 HashSet<JSGlobalObject*> m_globalObjects;
192
193 PauseOnExceptionsState m_pauseOnExceptionsState;
194 bool m_pauseOnNextStatement : 1;
195 bool m_isPaused : 1;
196 bool m_breakpointsActivated : 1;
197 bool m_hasHandlerForExceptionCallback : 1;
198 bool m_isInWorkerThread : 1;
199 unsigned m_steppingMode : 1; // SteppingMode
200
201 ReasonForPause m_reasonForPause;
202 JSValue m_currentException;
203 CallFrame* m_pauseOnCallFrame;
204 CallFrame* m_currentCallFrame;
205 unsigned m_lastExecutedLine;
206 SourceID m_lastExecutedSourceID;
207
208 BreakpointID m_topBreakpointID;
209 BreakpointID m_pausingBreakpointID;
210 BreakpointIDToBreakpointMap m_breakpointIDToBreakpoint;
211 SourceIDToBreakpointsMap m_sourceIDToBreakpoints;
212
213 RefPtr<JSC::DebuggerCallFrame> m_currentDebuggerCallFrame;
214
215 friend class DebuggerPausedScope;
216 friend class TemporaryPausedState;
217 friend class LLIntOffsetsExtractor;
218 };
219
220 } // namespace JSC
221
222 #endif // Debugger_h