| 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 |