OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_DEBUG_DEBUG_H_ | 5 #ifndef V8_DEBUG_DEBUG_H_ |
6 #define V8_DEBUG_DEBUG_H_ | 6 #define V8_DEBUG_DEBUG_H_ |
7 | 7 |
8 #include "src/allocation.h" | 8 #include "src/allocation.h" |
9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
10 #include "src/assembler.h" | 10 #include "src/assembler.h" |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 enum BreakLocatorType { ALL_BREAK_LOCATIONS, CALLS_AND_RETURNS }; | 54 enum BreakLocatorType { ALL_BREAK_LOCATIONS, CALLS_AND_RETURNS }; |
55 | 55 |
56 | 56 |
57 // The different types of breakpoint position alignments. | 57 // The different types of breakpoint position alignments. |
58 // Must match Debug.BreakPositionAlignment in debug.js | 58 // Must match Debug.BreakPositionAlignment in debug.js |
59 enum BreakPositionAlignment { | 59 enum BreakPositionAlignment { |
60 STATEMENT_ALIGNED = 0, | 60 STATEMENT_ALIGNED = 0, |
61 BREAK_POSITION_ALIGNED = 1 | 61 BREAK_POSITION_ALIGNED = 1 |
62 }; | 62 }; |
63 | 63 |
| 64 enum DebugBreakType { |
| 65 NOT_DEBUG_BREAK, |
| 66 DEBUGGER_STATEMENT, |
| 67 DEBUG_BREAK_SLOT, |
| 68 DEBUG_BREAK_SLOT_AT_CALL, |
| 69 DEBUG_BREAK_SLOT_AT_RETURN, |
| 70 DEBUG_BREAK_SLOT_AT_TAIL_CALL, |
| 71 }; |
64 | 72 |
65 class BreakLocation { | 73 class BreakLocation { |
66 public: | 74 public: |
67 // Find the break point at the supplied address, or the closest one before | |
68 // the address. | |
69 static BreakLocation FromCodeOffset(Handle<DebugInfo> debug_info, int offset); | |
70 | |
71 static BreakLocation FromFrame(Handle<DebugInfo> debug_info, | 75 static BreakLocation FromFrame(Handle<DebugInfo> debug_info, |
72 JavaScriptFrame* frame); | 76 JavaScriptFrame* frame); |
73 | 77 |
74 static void AllForStatementPosition(Handle<DebugInfo> debug_info, | 78 static void AllAtCurrentStatement(Handle<DebugInfo> debug_info, |
75 int statement_position, | 79 JavaScriptFrame* frame, |
76 List<BreakLocation>* result_out); | 80 List<BreakLocation>* result_out); |
77 | |
78 // Find break location (for a break point) from source positon. | |
79 static BreakLocation FromPosition(Handle<DebugInfo> debug_info, int position, | |
80 BreakPositionAlignment alignment); | |
81 | |
82 bool IsDebugBreak() const; | |
83 | 81 |
84 inline bool IsReturn() const { return type_ == DEBUG_BREAK_SLOT_AT_RETURN; } | 82 inline bool IsReturn() const { return type_ == DEBUG_BREAK_SLOT_AT_RETURN; } |
85 inline bool IsCall() const { return type_ == DEBUG_BREAK_SLOT_AT_CALL; } | 83 inline bool IsCall() const { return type_ == DEBUG_BREAK_SLOT_AT_CALL; } |
86 inline bool IsTailCall() const { | 84 inline bool IsTailCall() const { |
87 return type_ == DEBUG_BREAK_SLOT_AT_TAIL_CALL; | 85 return type_ == DEBUG_BREAK_SLOT_AT_TAIL_CALL; |
88 } | 86 } |
89 inline bool IsDebugBreakSlot() const { return type_ >= DEBUG_BREAK_SLOT; } | 87 inline bool IsDebugBreakSlot() const { return type_ >= DEBUG_BREAK_SLOT; } |
90 inline bool IsDebuggerStatement() const { | 88 inline bool IsDebuggerStatement() const { |
91 return type_ == DEBUGGER_STATEMENT; | 89 return type_ == DEBUGGER_STATEMENT; |
92 } | 90 } |
93 | 91 |
94 bool HasBreakPoint() const; | 92 bool HasBreakPoint(Handle<DebugInfo> debug_info) const; |
95 | |
96 Handle<Object> BreakPointObjects() const; | |
97 | |
98 void SetBreakPoint(Handle<Object> break_point_object); | |
99 void ClearBreakPoint(Handle<Object> break_point_object); | |
100 | |
101 void SetOneShot(); | |
102 void ClearOneShot(); | |
103 | 93 |
104 inline int position() const { return position_; } | 94 inline int position() const { return position_; } |
105 inline int statement_position() const { return statement_position_; } | |
106 | 95 |
107 inline int code_offset() const { return code_offset_; } | 96 private: |
108 inline Isolate* isolate() { return debug_info_->GetIsolate(); } | 97 BreakLocation(Handle<AbstractCode> abstract_code, DebugBreakType type, |
109 | 98 int code_offset, int position) |
110 inline AbstractCode* abstract_code() const { | 99 : abstract_code_(abstract_code), |
111 return debug_info_->abstract_code(); | 100 code_offset_(code_offset), |
| 101 type_(type), |
| 102 position_(position) { |
| 103 DCHECK_NE(NOT_DEBUG_BREAK, type_); |
112 } | 104 } |
113 | 105 |
114 protected: | 106 static int BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info, |
115 enum DebugBreakType { | 107 Handle<AbstractCode> abstract_code, |
116 NOT_DEBUG_BREAK, | 108 int offset); |
117 DEBUGGER_STATEMENT, | |
118 DEBUG_BREAK_SLOT, | |
119 DEBUG_BREAK_SLOT_AT_CALL, | |
120 DEBUG_BREAK_SLOT_AT_RETURN, | |
121 DEBUG_BREAK_SLOT_AT_TAIL_CALL, | |
122 }; | |
123 | |
124 BreakLocation(Handle<DebugInfo> debug_info, DebugBreakType type, | |
125 int code_offset, int position, int statement_position); | |
126 | |
127 class Iterator { | |
128 public: | |
129 virtual ~Iterator() {} | |
130 | |
131 virtual BreakLocation GetBreakLocation() = 0; | |
132 virtual bool Done() const = 0; | |
133 virtual void Next() = 0; | |
134 | |
135 void SkipTo(int count) { | |
136 while (count-- > 0) Next(); | |
137 } | |
138 | |
139 virtual int code_offset() = 0; | |
140 int break_index() const { return break_index_; } | |
141 inline int position() const { return position_; } | |
142 inline int statement_position() const { return statement_position_; } | |
143 | |
144 protected: | |
145 explicit Iterator(Handle<DebugInfo> debug_info); | |
146 | |
147 Isolate* isolate() { return debug_info_->GetIsolate(); } | |
148 | |
149 Handle<DebugInfo> debug_info_; | |
150 int break_index_; | |
151 int position_; | |
152 int statement_position_; | |
153 | |
154 private: | |
155 DisallowHeapAllocation no_gc_; | |
156 DISALLOW_COPY_AND_ASSIGN(Iterator); | |
157 }; | |
158 | |
159 class CodeIterator : public Iterator { | |
160 public: | |
161 CodeIterator(Handle<DebugInfo> debug_info, BreakLocatorType type); | |
162 ~CodeIterator() override {} | |
163 | |
164 BreakLocation GetBreakLocation() override; | |
165 bool Done() const override { return reloc_iterator_.done(); } | |
166 void Next() override; | |
167 | |
168 int code_offset() override { | |
169 return static_cast<int>( | |
170 rinfo()->pc() - | |
171 debug_info_->abstract_code()->GetCode()->instruction_start()); | |
172 } | |
173 | |
174 private: | |
175 int GetModeMask(BreakLocatorType type); | |
176 RelocInfo::Mode rmode() { return reloc_iterator_.rinfo()->rmode(); } | |
177 RelocInfo* rinfo() { return reloc_iterator_.rinfo(); } | |
178 | |
179 RelocIterator reloc_iterator_; | |
180 SourcePositionTableIterator source_position_iterator_; | |
181 DISALLOW_COPY_AND_ASSIGN(CodeIterator); | |
182 }; | |
183 | |
184 class BytecodeArrayIterator : public Iterator { | |
185 public: | |
186 BytecodeArrayIterator(Handle<DebugInfo> debug_info, BreakLocatorType type); | |
187 ~BytecodeArrayIterator() override {} | |
188 | |
189 BreakLocation GetBreakLocation() override; | |
190 bool Done() const override { return source_position_iterator_.done(); } | |
191 void Next() override; | |
192 | |
193 int code_offset() override { | |
194 return source_position_iterator_.code_offset(); | |
195 } | |
196 | |
197 private: | |
198 DebugBreakType GetDebugBreakType(); | |
199 | |
200 SourcePositionTableIterator source_position_iterator_; | |
201 BreakLocatorType break_locator_type_; | |
202 DISALLOW_COPY_AND_ASSIGN(BytecodeArrayIterator); | |
203 }; | |
204 | |
205 static Iterator* GetIterator(Handle<DebugInfo> debug_info, | |
206 BreakLocatorType type = ALL_BREAK_LOCATIONS); | |
207 | |
208 private: | |
209 friend class Debug; | |
210 | |
211 static int BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info, int offset); | |
212 | 109 |
213 void SetDebugBreak(); | 110 void SetDebugBreak(); |
214 void ClearDebugBreak(); | 111 void ClearDebugBreak(); |
215 | 112 |
216 Handle<DebugInfo> debug_info_; | 113 Handle<AbstractCode> abstract_code_; |
217 int code_offset_; | 114 int code_offset_; |
218 DebugBreakType type_; | 115 DebugBreakType type_; |
219 int position_; | 116 int position_; |
220 int statement_position_; | 117 |
| 118 friend class CodeBreakIterator; |
| 119 friend class BytecodeArrayBreakIterator; |
221 }; | 120 }; |
222 | 121 |
| 122 class BreakIterator { |
| 123 public: |
| 124 static std::unique_ptr<BreakIterator> GetIterator( |
| 125 Handle<DebugInfo> debug_info, Handle<AbstractCode> abstract_code, |
| 126 BreakLocatorType type = ALL_BREAK_LOCATIONS); |
| 127 |
| 128 virtual ~BreakIterator() {} |
| 129 |
| 130 virtual BreakLocation GetBreakLocation() = 0; |
| 131 virtual bool Done() const = 0; |
| 132 virtual void Next() = 0; |
| 133 |
| 134 void SkipTo(int count) { |
| 135 while (count-- > 0) Next(); |
| 136 } |
| 137 |
| 138 virtual int code_offset() = 0; |
| 139 int break_index() const { return break_index_; } |
| 140 inline int position() const { return position_; } |
| 141 inline int statement_position() const { return statement_position_; } |
| 142 |
| 143 virtual bool IsDebugBreak() = 0; |
| 144 virtual void ClearDebugBreak() = 0; |
| 145 virtual void SetDebugBreak() = 0; |
| 146 |
| 147 protected: |
| 148 explicit BreakIterator(Handle<DebugInfo> debug_info, |
| 149 BreakLocatorType break_locator_type); |
| 150 |
| 151 int BreakIndexFromPosition(int position, BreakPositionAlignment alignment); |
| 152 |
| 153 Isolate* isolate() { return debug_info_->GetIsolate(); } |
| 154 |
| 155 Handle<DebugInfo> debug_info_; |
| 156 int break_index_; |
| 157 int position_; |
| 158 int statement_position_; |
| 159 BreakLocatorType break_locator_type_; |
| 160 |
| 161 private: |
| 162 DisallowHeapAllocation no_gc_; |
| 163 DISALLOW_COPY_AND_ASSIGN(BreakIterator); |
| 164 }; |
| 165 |
| 166 class CodeBreakIterator : public BreakIterator { |
| 167 public: |
| 168 CodeBreakIterator(Handle<DebugInfo> debug_info, BreakLocatorType type); |
| 169 ~CodeBreakIterator() override {} |
| 170 |
| 171 BreakLocation GetBreakLocation() override; |
| 172 bool Done() const override { return reloc_iterator_.done(); } |
| 173 void Next() override; |
| 174 |
| 175 bool IsDebugBreak() override; |
| 176 void ClearDebugBreak() override; |
| 177 void SetDebugBreak() override; |
| 178 |
| 179 void SkipToPosition(int position, BreakPositionAlignment alignment); |
| 180 |
| 181 int code_offset() override { |
| 182 return static_cast<int>(rinfo()->pc() - |
| 183 debug_info_->DebugCode()->instruction_start()); |
| 184 } |
| 185 |
| 186 private: |
| 187 int GetModeMask(BreakLocatorType type); |
| 188 DebugBreakType GetDebugBreakType(); |
| 189 |
| 190 RelocInfo::Mode rmode() { return reloc_iterator_.rinfo()->rmode(); } |
| 191 RelocInfo* rinfo() { return reloc_iterator_.rinfo(); } |
| 192 |
| 193 RelocIterator reloc_iterator_; |
| 194 SourcePositionTableIterator source_position_iterator_; |
| 195 DISALLOW_COPY_AND_ASSIGN(CodeBreakIterator); |
| 196 }; |
| 197 |
| 198 class BytecodeArrayBreakIterator : public BreakIterator { |
| 199 public: |
| 200 BytecodeArrayBreakIterator(Handle<DebugInfo> debug_info, |
| 201 BreakLocatorType type); |
| 202 ~BytecodeArrayBreakIterator() override {} |
| 203 |
| 204 BreakLocation GetBreakLocation() override; |
| 205 bool Done() const override { return source_position_iterator_.done(); } |
| 206 void Next() override; |
| 207 |
| 208 bool IsDebugBreak() override; |
| 209 void ClearDebugBreak() override; |
| 210 void SetDebugBreak() override; |
| 211 |
| 212 void SkipToPosition(int position, BreakPositionAlignment alignment); |
| 213 |
| 214 int code_offset() override { return source_position_iterator_.code_offset(); } |
| 215 |
| 216 private: |
| 217 DebugBreakType GetDebugBreakType(); |
| 218 |
| 219 SourcePositionTableIterator source_position_iterator_; |
| 220 DISALLOW_COPY_AND_ASSIGN(BytecodeArrayBreakIterator); |
| 221 }; |
223 | 222 |
224 // Linked list holding debug info objects. The debug info objects are kept as | 223 // Linked list holding debug info objects. The debug info objects are kept as |
225 // weak handles to avoid a debug info object to keep a function alive. | 224 // weak handles to avoid a debug info object to keep a function alive. |
226 class DebugInfoListNode { | 225 class DebugInfoListNode { |
227 public: | 226 public: |
228 explicit DebugInfoListNode(DebugInfo* debug_info); | 227 explicit DebugInfoListNode(DebugInfo* debug_info); |
229 ~DebugInfoListNode(); | 228 ~DebugInfoListNode(); |
230 | 229 |
231 DebugInfoListNode* next() { return next_; } | 230 DebugInfoListNode* next() { return next_; } |
232 void set_next(DebugInfoListNode* next) { next_ = next; } | 231 void set_next(DebugInfoListNode* next) { next_ = next; } |
233 Handle<DebugInfo> debug_info() { return Handle<DebugInfo>(debug_info_); } | 232 Handle<DebugInfo> debug_info() { return Handle<DebugInfo>(debug_info_); } |
234 | 233 |
235 private: | 234 private: |
236 // Global (weak) handle to the debug info object. | 235 // Global (weak) handle to the debug info object. |
237 DebugInfo** debug_info_; | 236 DebugInfo** debug_info_; |
238 | 237 |
239 // Next pointer for linked list. | 238 // Next pointer for linked list. |
240 DebugInfoListNode* next_; | 239 DebugInfoListNode* next_; |
241 }; | 240 }; |
242 | 241 |
243 | 242 |
244 | |
245 // Message delivered to the message handler callback. This is either a debugger | 243 // Message delivered to the message handler callback. This is either a debugger |
246 // event or the response to a command. | 244 // event or the response to a command. |
247 class MessageImpl: public v8::Debug::Message { | 245 class MessageImpl: public v8::Debug::Message { |
248 public: | 246 public: |
249 // Create a message object for a debug event. | 247 // Create a message object for a debug event. |
250 static MessageImpl NewEvent(DebugEvent event, | 248 static MessageImpl NewEvent(DebugEvent event, |
251 bool running, | 249 bool running, |
252 Handle<JSObject> exec_state, | 250 Handle<JSObject> exec_state, |
253 Handle<JSObject> event_data); | 251 Handle<JSObject> event_data); |
254 | 252 |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
442 | 440 |
443 // Break point handling. | 441 // Break point handling. |
444 bool SetBreakPoint(Handle<JSFunction> function, | 442 bool SetBreakPoint(Handle<JSFunction> function, |
445 Handle<Object> break_point_object, | 443 Handle<Object> break_point_object, |
446 int* source_position); | 444 int* source_position); |
447 bool SetBreakPointForScript(Handle<Script> script, | 445 bool SetBreakPointForScript(Handle<Script> script, |
448 Handle<Object> break_point_object, | 446 Handle<Object> break_point_object, |
449 int* source_position, | 447 int* source_position, |
450 BreakPositionAlignment alignment); | 448 BreakPositionAlignment alignment); |
451 void ClearBreakPoint(Handle<Object> break_point_object); | 449 void ClearBreakPoint(Handle<Object> break_point_object); |
452 void ClearAllBreakPoints(); | |
453 void FloodWithOneShot(Handle<JSFunction> function, | |
454 BreakLocatorType type = ALL_BREAK_LOCATIONS); | |
455 void ChangeBreakOnException(ExceptionBreakType type, bool enable); | 450 void ChangeBreakOnException(ExceptionBreakType type, bool enable); |
456 bool IsBreakOnException(ExceptionBreakType type); | 451 bool IsBreakOnException(ExceptionBreakType type); |
457 | 452 |
458 // Stepping handling. | 453 // Stepping handling. |
459 void PrepareStep(StepAction step_action); | 454 void PrepareStep(StepAction step_action); |
460 void PrepareStepIn(Handle<JSFunction> function); | 455 void PrepareStepIn(Handle<JSFunction> function); |
461 void PrepareStepInSuspendedGenerator(); | 456 void PrepareStepInSuspendedGenerator(); |
462 void PrepareStepOnThrow(); | 457 void PrepareStepOnThrow(); |
463 void ClearStepping(); | 458 void ClearStepping(); |
464 void ClearStepOut(); | 459 void ClearStepOut(); |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
609 void ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script); | 604 void ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script); |
610 void ProcessDebugEvent(v8::DebugEvent event, | 605 void ProcessDebugEvent(v8::DebugEvent event, |
611 Handle<JSObject> event_data, | 606 Handle<JSObject> event_data, |
612 bool auto_continue); | 607 bool auto_continue); |
613 void NotifyMessageHandler(v8::DebugEvent event, | 608 void NotifyMessageHandler(v8::DebugEvent event, |
614 Handle<JSObject> exec_state, | 609 Handle<JSObject> exec_state, |
615 Handle<JSObject> event_data, | 610 Handle<JSObject> event_data, |
616 bool auto_continue); | 611 bool auto_continue); |
617 void InvokeMessageHandler(MessageImpl message); | 612 void InvokeMessageHandler(MessageImpl message); |
618 | 613 |
| 614 // Find the closest source position for a break point for a given position. |
| 615 int FindBreakablePosition(Handle<DebugInfo> debug_info, int source_position, |
| 616 BreakPositionAlignment alignment); |
| 617 // Instrument code to break at break points. |
| 618 void ApplyBreakPoints(Handle<DebugInfo> debug_info); |
| 619 // Clear code from instrumentation. |
| 620 void ClearBreakPoints(Handle<DebugInfo> debug_info); |
| 621 // Clear all code from instrumentation. |
| 622 void ClearAllBreakPoints(); |
| 623 // Instrument a function with one-shots. |
| 624 void FloodWithOneShot(Handle<JSFunction> function, |
| 625 BreakLocatorType type = ALL_BREAK_LOCATIONS); |
| 626 // Clear all one-shot instrumentations, but restore break points. |
619 void ClearOneShot(); | 627 void ClearOneShot(); |
| 628 |
620 void ActivateStepOut(StackFrame* frame); | 629 void ActivateStepOut(StackFrame* frame); |
621 void RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info); | 630 void RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info); |
622 Handle<Object> CheckBreakPoints(BreakLocation* location, | 631 Handle<Object> CheckBreakPoints(Handle<DebugInfo> debug_info, |
| 632 BreakLocation* location, |
623 bool* has_break_points = nullptr); | 633 bool* has_break_points = nullptr); |
624 bool IsMutedAtCurrentLocation(JavaScriptFrame* frame); | 634 bool IsMutedAtCurrentLocation(JavaScriptFrame* frame); |
625 bool CheckBreakPoint(Handle<Object> break_point_object); | 635 bool CheckBreakPoint(Handle<Object> break_point_object); |
626 MaybeHandle<Object> CallFunction(const char* name, int argc, | 636 MaybeHandle<Object> CallFunction(const char* name, int argc, |
627 Handle<Object> args[]); | 637 Handle<Object> args[]); |
628 | 638 |
629 inline void AssertDebugContext() { | 639 inline void AssertDebugContext() { |
630 DCHECK(isolate_->context() == *debug_context()); | 640 DCHECK(isolate_->context() == *debug_context()); |
631 DCHECK(in_debug_scope()); | 641 DCHECK(in_debug_scope()); |
632 } | 642 } |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
811 Handle<Code> code); | 821 Handle<Code> code); |
812 static bool DebugBreakSlotIsPatched(Address pc); | 822 static bool DebugBreakSlotIsPatched(Address pc); |
813 static void ClearDebugBreakSlot(Isolate* isolate, Address pc); | 823 static void ClearDebugBreakSlot(Isolate* isolate, Address pc); |
814 }; | 824 }; |
815 | 825 |
816 | 826 |
817 } // namespace internal | 827 } // namespace internal |
818 } // namespace v8 | 828 } // namespace v8 |
819 | 829 |
820 #endif // V8_DEBUG_DEBUG_H_ | 830 #endif // V8_DEBUG_DEBUG_H_ |
OLD | NEW |