| 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_H_ | 5 #ifndef V8_DEBUG_H_ |
| 6 #define V8_DEBUG_H_ | 6 #define V8_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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 | 59 |
| 60 | 60 |
| 61 // The different types of breakpoint position alignments. | 61 // The different types of breakpoint position alignments. |
| 62 // Must match Debug.BreakPositionAlignment in debug-debugger.js | 62 // Must match Debug.BreakPositionAlignment in debug-debugger.js |
| 63 enum BreakPositionAlignment { | 63 enum BreakPositionAlignment { |
| 64 STATEMENT_ALIGNED = 0, | 64 STATEMENT_ALIGNED = 0, |
| 65 BREAK_POSITION_ALIGNED = 1 | 65 BREAK_POSITION_ALIGNED = 1 |
| 66 }; | 66 }; |
| 67 | 67 |
| 68 | 68 |
| 69 // Class for iterating through the break points in a function and changing | 69 class BreakLocation { |
| 70 // them. | |
| 71 class BreakLocationIterator { | |
| 72 public: | 70 public: |
| 73 explicit BreakLocationIterator(Handle<DebugInfo> debug_info, | 71 // Find the break point at the supplied address, or the closest one before |
| 74 BreakLocatorType type); | 72 // the address. |
| 75 virtual ~BreakLocationIterator(); | 73 static BreakLocation FromAddress(Handle<DebugInfo> debug_info, |
| 74 BreakLocatorType type, Address pc); |
| 76 | 75 |
| 77 void Next(); | 76 static void FromAddressSameStatement(Handle<DebugInfo> debug_info, |
| 78 void Next(int count); | 77 BreakLocatorType type, Address pc, |
| 79 void FindBreakLocationFromAddress(Address pc); | 78 List<BreakLocation>* result_out); |
| 80 void FindBreakLocationFromPosition(int position, | 79 |
| 81 BreakPositionAlignment alignment); | 80 static BreakLocation FromPosition(Handle<DebugInfo> debug_info, |
| 82 void Reset(); | 81 BreakLocatorType type, int position, |
| 83 bool Done() const; | 82 BreakPositionAlignment alignment); |
| 83 |
| 84 bool IsDebugBreak() const; |
| 85 inline bool IsExit() const { return RelocInfo::IsJSReturn(rmode_); } |
| 86 inline bool IsConstructCall() const { |
| 87 return RelocInfo::IsConstructCall(rmode_); |
| 88 } |
| 89 inline bool IsCodeTarget() const { return RelocInfo::IsCodeTarget(rmode_); } |
| 90 |
| 91 Handle<Code> CodeTarget() const; |
| 92 Handle<Code> OriginalCodeTarget() const; |
| 93 |
| 94 bool IsStepInLocation() const; |
| 95 inline bool HasBreakPoint() const { |
| 96 return debug_info_->HasBreakPoint(pc_offset_); |
| 97 } |
| 98 |
| 99 Handle<Object> BreakPointObjects() const; |
| 100 |
| 84 void SetBreakPoint(Handle<Object> break_point_object); | 101 void SetBreakPoint(Handle<Object> break_point_object); |
| 85 void ClearBreakPoint(Handle<Object> break_point_object); | 102 void ClearBreakPoint(Handle<Object> break_point_object); |
| 103 |
| 86 void SetOneShot(); | 104 void SetOneShot(); |
| 87 void ClearOneShot(); | 105 void ClearOneShot(); |
| 88 bool IsStepInLocation(Isolate* isolate); | |
| 89 bool IsExit() const; | |
| 90 bool HasBreakPoint(); | |
| 91 bool IsDebugBreak(); | |
| 92 Object* BreakPointObjects(); | |
| 93 void ClearAllDebugBreak(); | |
| 94 | 106 |
| 95 | 107 inline RelocInfo rinfo() const { |
| 96 inline int code_position() { | 108 return RelocInfo(pc(), rmode(), data_, code()); |
| 97 return static_cast<int>(pc() - debug_info_->code()->entry()); | |
| 98 } | |
| 99 inline int break_point() { return break_point_; } | |
| 100 inline int position() { return position_; } | |
| 101 inline int statement_position() { return statement_position_; } | |
| 102 inline Address pc() { return reloc_iterator_->rinfo()->pc(); } | |
| 103 inline Code* code() { return debug_info_->code(); } | |
| 104 inline RelocInfo* rinfo() { return reloc_iterator_->rinfo(); } | |
| 105 inline RelocInfo::Mode rmode() const { | |
| 106 return reloc_iterator_->rinfo()->rmode(); | |
| 107 } | |
| 108 inline RelocInfo* original_rinfo() { | |
| 109 return reloc_iterator_original_->rinfo(); | |
| 110 } | |
| 111 inline RelocInfo::Mode original_rmode() const { | |
| 112 return reloc_iterator_original_->rinfo()->rmode(); | |
| 113 } | 109 } |
| 114 | 110 |
| 115 bool IsDebuggerStatement(); | 111 inline RelocInfo original_rinfo() const { |
| 112 return RelocInfo(original_pc(), original_rmode(), original_data_, |
| 113 original_code()); |
| 114 } |
| 116 | 115 |
| 117 protected: | 116 inline int position() const { return position_; } |
| 118 bool RinfoDone() const; | 117 inline int statement_position() const { return statement_position_; } |
| 119 void RinfoNext(); | |
| 120 | 118 |
| 121 BreakLocatorType type_; | 119 inline Address pc() const { return code()->entry() + pc_offset_; } |
| 122 int break_point_; | 120 inline Address original_pc() const { |
| 121 return original_code()->entry() + original_pc_offset_; |
| 122 } |
| 123 |
| 124 inline RelocInfo::Mode rmode() const { return rmode_; } |
| 125 inline RelocInfo::Mode original_rmode() const { return original_rmode_; } |
| 126 |
| 127 inline Code* code() const { return debug_info_->code(); } |
| 128 inline Code* original_code() const { return debug_info_->original_code(); } |
| 129 |
| 130 private: |
| 131 BreakLocation(Handle<DebugInfo> debug_info, RelocInfo* rinfo, |
| 132 RelocInfo* original_rinfo, int position, int statement_position) |
| 133 : debug_info_(debug_info), |
| 134 pc_offset_(static_cast<int>(rinfo->pc() - debug_info->code()->entry())), |
| 135 original_pc_offset_(static_cast<int>( |
| 136 original_rinfo->pc() - debug_info->original_code()->entry())), |
| 137 rmode_(rinfo->rmode()), |
| 138 original_rmode_(original_rinfo->rmode()), |
| 139 data_(rinfo->data()), |
| 140 original_data_(original_rinfo->data()), |
| 141 position_(position), |
| 142 statement_position_(statement_position) {} |
| 143 |
| 144 class Iterator { |
| 145 public: |
| 146 Iterator(Handle<DebugInfo> debug_info, BreakLocatorType type); |
| 147 |
| 148 BreakLocation GetBreakLocation() { |
| 149 return BreakLocation(debug_info_, rinfo(), original_rinfo(), position(), |
| 150 statement_position()); |
| 151 } |
| 152 |
| 153 inline bool Done() const { return RinfoDone(); } |
| 154 void Next(); |
| 155 |
| 156 void SkipTo(int count) { |
| 157 while (count-- > 0) Next(); |
| 158 } |
| 159 |
| 160 inline RelocInfo::Mode rmode() { return reloc_iterator_.rinfo()->rmode(); } |
| 161 inline RelocInfo::Mode original_rmode() { |
| 162 return reloc_iterator_.rinfo()->rmode(); |
| 163 } |
| 164 |
| 165 inline RelocInfo* rinfo() { return reloc_iterator_.rinfo(); } |
| 166 inline RelocInfo* original_rinfo() { |
| 167 return reloc_iterator_original_.rinfo(); |
| 168 } |
| 169 |
| 170 inline Address pc() { return rinfo()->pc(); } |
| 171 inline Address original_pc() { return original_rinfo()->pc(); } |
| 172 |
| 173 int break_index() const { return break_index_; } |
| 174 |
| 175 inline int position() const { return position_; } |
| 176 inline int statement_position() const { return statement_position_; } |
| 177 |
| 178 private: |
| 179 bool RinfoDone() const; |
| 180 void RinfoNext(); |
| 181 |
| 182 Handle<DebugInfo> debug_info_; |
| 183 BreakLocatorType type_; |
| 184 RelocIterator reloc_iterator_; |
| 185 RelocIterator reloc_iterator_original_; |
| 186 int break_index_; |
| 187 int position_; |
| 188 int statement_position_; |
| 189 |
| 190 DisallowHeapAllocation no_gc_; |
| 191 |
| 192 DISALLOW_COPY_AND_ASSIGN(Iterator); |
| 193 }; |
| 194 |
| 195 friend class Debug; |
| 196 |
| 197 static int BreakIndexFromAddress(Handle<DebugInfo> debug_info, |
| 198 BreakLocatorType type, Address pc); |
| 199 |
| 200 void ClearDebugBreak(); |
| 201 void RestoreFromOriginal(int length_in_bytes); |
| 202 |
| 203 void SetDebugBreak(); |
| 204 void SetDebugBreakAtReturn(); |
| 205 void SetDebugBreakAtSlot(); |
| 206 void SetDebugBreakAtIC(); |
| 207 |
| 208 inline bool IsDebuggerStatement() const { |
| 209 return RelocInfo::IsDebuggerStatement(rmode_); |
| 210 } |
| 211 inline bool IsDebugBreakSlot() const { |
| 212 return RelocInfo::IsDebugBreakSlot(rmode_); |
| 213 } |
| 214 |
| 215 Handle<DebugInfo> debug_info_; |
| 216 int pc_offset_; |
| 217 int original_pc_offset_; |
| 218 RelocInfo::Mode rmode_; |
| 219 RelocInfo::Mode original_rmode_; |
| 220 intptr_t data_; |
| 221 intptr_t original_data_; |
| 123 int position_; | 222 int position_; |
| 124 int statement_position_; | 223 int statement_position_; |
| 125 Handle<DebugInfo> debug_info_; | |
| 126 RelocIterator* reloc_iterator_; | |
| 127 RelocIterator* reloc_iterator_original_; | |
| 128 | |
| 129 private: | |
| 130 void SetDebugBreak(); | |
| 131 void ClearDebugBreak(); | |
| 132 | |
| 133 void SetDebugBreakAtIC(); | |
| 134 void ClearDebugBreakAtIC(); | |
| 135 | |
| 136 bool IsDebugBreakAtReturn(); | |
| 137 void SetDebugBreakAtReturn(); | |
| 138 void ClearDebugBreakAtReturn(); | |
| 139 | |
| 140 bool IsDebugBreakSlot(); | |
| 141 bool IsDebugBreakAtSlot(); | |
| 142 void SetDebugBreakAtSlot(); | |
| 143 void ClearDebugBreakAtSlot(); | |
| 144 | |
| 145 DISALLOW_COPY_AND_ASSIGN(BreakLocationIterator); | |
| 146 }; | 224 }; |
| 147 | 225 |
| 148 | 226 |
| 149 // Cache of all script objects in the heap. When a script is added a weak handle | 227 // Cache of all script objects in the heap. When a script is added a weak handle |
| 150 // to it is created and that weak handle is stored in the cache. The weak handle | 228 // to it is created and that weak handle is stored in the cache. The weak handle |
| 151 // callback takes care of removing the script from the cache. The key used in | 229 // callback takes care of removing the script from the cache. The key used in |
| 152 // the cache is the script id. | 230 // the cache is the script id. |
| 153 class ScriptCache : private HashMap { | 231 class ScriptCache : private HashMap { |
| 154 public: | 232 public: |
| 155 explicit ScriptCache(Isolate* isolate); | 233 explicit ScriptCache(Isolate* isolate); |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 void ChangeBreakOnException(ExceptionBreakType type, bool enable); | 474 void ChangeBreakOnException(ExceptionBreakType type, bool enable); |
| 397 bool IsBreakOnException(ExceptionBreakType type); | 475 bool IsBreakOnException(ExceptionBreakType type); |
| 398 | 476 |
| 399 // Stepping handling. | 477 // Stepping handling. |
| 400 void PrepareStep(StepAction step_action, | 478 void PrepareStep(StepAction step_action, |
| 401 int step_count, | 479 int step_count, |
| 402 StackFrame::Id frame_id); | 480 StackFrame::Id frame_id); |
| 403 void ClearStepping(); | 481 void ClearStepping(); |
| 404 void ClearStepOut(); | 482 void ClearStepOut(); |
| 405 bool IsStepping() { return thread_local_.step_count_ > 0; } | 483 bool IsStepping() { return thread_local_.step_count_ > 0; } |
| 406 bool StepNextContinue(BreakLocationIterator* break_location_iterator, | 484 bool StepNextContinue(BreakLocation* location, JavaScriptFrame* frame); |
| 407 JavaScriptFrame* frame); | |
| 408 bool StepInActive() { return thread_local_.step_into_fp_ != 0; } | 485 bool StepInActive() { return thread_local_.step_into_fp_ != 0; } |
| 409 void HandleStepIn(Handle<Object> function_obj, Handle<Object> holder, | 486 void HandleStepIn(Handle<Object> function_obj, Handle<Object> holder, |
| 410 Address fp, bool is_constructor); | 487 Address fp, bool is_constructor); |
| 411 bool StepOutActive() { return thread_local_.step_out_fp_ != 0; } | 488 bool StepOutActive() { return thread_local_.step_out_fp_ != 0; } |
| 412 | 489 |
| 413 // Purge all code objects that have no debug break slots. | 490 // Purge all code objects that have no debug break slots. |
| 414 void PrepareForBreakPoints(); | 491 void PrepareForBreakPoints(); |
| 415 | 492 |
| 416 // Returns whether the operation succeeded. Compilation can only be triggered | 493 // Returns whether the operation succeeded. Compilation can only be triggered |
| 417 // if a valid closure is passed as the second argument, otherwise the shared | 494 // if a valid closure is passed as the second argument, otherwise the shared |
| 418 // function needs to be compiled already. | 495 // function needs to be compiled already. |
| 419 bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared, | 496 bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared, |
| 420 Handle<JSFunction> function); | 497 Handle<JSFunction> function); |
| 421 static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared); | 498 static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared); |
| 422 static bool HasDebugInfo(Handle<SharedFunctionInfo> shared); | 499 static bool HasDebugInfo(Handle<SharedFunctionInfo> shared); |
| 423 | 500 |
| 424 // This function is used in FunctionNameUsing* tests. | 501 // This function is used in FunctionNameUsing* tests. |
| 425 Object* FindSharedFunctionInfoInScript(Handle<Script> script, int position); | 502 Handle<Object> FindSharedFunctionInfoInScript(Handle<Script> script, |
| 503 int position); |
| 426 | 504 |
| 427 // Returns true if the current stub call is patched to call the debugger. | 505 // Returns true if the current stub call is patched to call the debugger. |
| 428 static bool IsDebugBreak(Address addr); | 506 static bool IsDebugBreak(Address addr); |
| 429 // Returns true if the current return statement has been patched to be | |
| 430 // a debugger breakpoint. | |
| 431 static bool IsDebugBreakAtReturn(RelocInfo* rinfo); | |
| 432 | 507 |
| 433 static Handle<Object> GetSourceBreakLocations( | 508 static Handle<Object> GetSourceBreakLocations( |
| 434 Handle<SharedFunctionInfo> shared, | 509 Handle<SharedFunctionInfo> shared, |
| 435 BreakPositionAlignment position_aligment); | 510 BreakPositionAlignment position_aligment); |
| 436 | 511 |
| 437 // Check whether a global object is the debug global object. | 512 // Check whether a global object is the debug global object. |
| 438 bool IsDebugGlobal(GlobalObject* global); | 513 bool IsDebugGlobal(GlobalObject* global); |
| 439 | 514 |
| 440 // Check whether this frame is just about to return. | 515 // Check whether this frame is just about to return. |
| 441 bool IsBreakAtReturn(JavaScriptFrame* frame); | 516 bool IsBreakAtReturn(JavaScriptFrame* frame); |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 766 // several frames above. | 841 // several frames above. |
| 767 // There is no calling conventions here, because it never actually gets | 842 // There is no calling conventions here, because it never actually gets |
| 768 // called, it only gets returned to. | 843 // called, it only gets returned to. |
| 769 static void GenerateFrameDropperLiveEdit(MacroAssembler* masm); | 844 static void GenerateFrameDropperLiveEdit(MacroAssembler* masm); |
| 770 }; | 845 }; |
| 771 | 846 |
| 772 | 847 |
| 773 } } // namespace v8::internal | 848 } } // namespace v8::internal |
| 774 | 849 |
| 775 #endif // V8_DEBUG_H_ | 850 #endif // V8_DEBUG_H_ |
| OLD | NEW |