| 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 #include "src/debug/debug.h" | 5 #include "src/debug/debug.h" |
| 6 | 6 |
| 7 #include "src/api.h" | 7 #include "src/api.h" |
| 8 #include "src/arguments.h" | 8 #include "src/arguments.h" |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 329 thread_local_.last_step_action_ = StepNone; | 329 thread_local_.last_step_action_ = StepNone; |
| 330 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; | 330 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; |
| 331 thread_local_.step_count_ = 0; | 331 thread_local_.step_count_ = 0; |
| 332 thread_local_.last_fp_ = 0; | 332 thread_local_.last_fp_ = 0; |
| 333 thread_local_.queued_step_count_ = 0; | 333 thread_local_.queued_step_count_ = 0; |
| 334 thread_local_.step_out_fp_ = 0; | 334 thread_local_.step_out_fp_ = 0; |
| 335 thread_local_.step_in_enabled_ = false; | 335 thread_local_.step_in_enabled_ = false; |
| 336 // TODO(isolates): frames_are_dropped_? | 336 // TODO(isolates): frames_are_dropped_? |
| 337 base::NoBarrier_Store(&thread_local_.current_debug_scope_, | 337 base::NoBarrier_Store(&thread_local_.current_debug_scope_, |
| 338 static_cast<base::AtomicWord>(0)); | 338 static_cast<base::AtomicWord>(0)); |
| 339 thread_local_.restarter_frame_function_pointer_ = NULL; | |
| 340 } | 339 } |
| 341 | 340 |
| 342 | 341 |
| 343 char* Debug::ArchiveDebug(char* storage) { | 342 char* Debug::ArchiveDebug(char* storage) { |
| 344 char* to = storage; | 343 char* to = storage; |
| 345 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); | 344 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); |
| 346 ThreadInit(); | 345 ThreadInit(); |
| 347 return storage + ArchiveSpacePerThread(); | 346 return storage + ArchiveSpacePerThread(); |
| 348 } | 347 } |
| 349 | 348 |
| (...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 821 } | 820 } |
| 822 | 821 |
| 823 | 822 |
| 824 void Debug::PrepareStep(StepAction step_action, | 823 void Debug::PrepareStep(StepAction step_action, |
| 825 int step_count, | 824 int step_count, |
| 826 StackFrame::Id frame_id) { | 825 StackFrame::Id frame_id) { |
| 827 HandleScope scope(isolate_); | 826 HandleScope scope(isolate_); |
| 828 | 827 |
| 829 DCHECK(in_debug_scope()); | 828 DCHECK(in_debug_scope()); |
| 830 | 829 |
| 831 // Remember this step action and count. | |
| 832 thread_local_.last_step_action_ = step_action; | |
| 833 STATIC_ASSERT(StepFrame > StepIn); | |
| 834 thread_local_.step_in_enabled_ = (step_action >= StepIn); | |
| 835 if (step_action == StepOut) { | |
| 836 // For step out target frame will be found on the stack so there is no need | |
| 837 // to set step counter for it. It's expected to always be 0 for StepOut. | |
| 838 thread_local_.step_count_ = 0; | |
| 839 } else { | |
| 840 thread_local_.step_count_ = step_count; | |
| 841 } | |
| 842 | |
| 843 // Get the frame where the execution has stopped and skip the debug frame if | 830 // Get the frame where the execution has stopped and skip the debug frame if |
| 844 // any. The debug frame will only be present if execution was stopped due to | 831 // any. The debug frame will only be present if execution was stopped due to |
| 845 // hitting a break point. In other situations (e.g. unhandled exception) the | 832 // hitting a break point. In other situations (e.g. unhandled exception) the |
| 846 // debug frame is not present. | 833 // debug frame is not present. |
| 847 StackFrame::Id id = break_frame_id(); | 834 StackFrame::Id id = break_frame_id(); |
| 848 if (id == StackFrame::NO_ID) { | 835 if (id == StackFrame::NO_ID) { |
| 849 // If there is no JavaScript stack don't do anything. | 836 // If there is no JavaScript stack don't do anything. |
| 850 return; | 837 return; |
| 851 } | 838 } |
| 852 if (frame_id != StackFrame::NO_ID) { | 839 if (frame_id != StackFrame::NO_ID) { |
| 853 id = frame_id; | 840 id = frame_id; |
| 854 } | 841 } |
| 855 JavaScriptFrameIterator frames_it(isolate_, id); | 842 JavaScriptFrameIterator frames_it(isolate_, id); |
| 856 JavaScriptFrame* frame = frames_it.frame(); | 843 JavaScriptFrame* frame = frames_it.frame(); |
| 857 | 844 |
| 858 feature_tracker()->Track(DebugFeatureTracker::kStepping); | 845 feature_tracker()->Track(DebugFeatureTracker::kStepping); |
| 859 | 846 |
| 847 // Remember this step action and count. |
| 848 thread_local_.last_step_action_ = step_action; |
| 849 STATIC_ASSERT(StepFrame > StepIn); |
| 850 thread_local_.step_in_enabled_ = (step_action >= StepIn); |
| 851 if (step_action == StepOut) { |
| 852 // For step out target frame will be found on the stack so there is no need |
| 853 // to set step counter for it. It's expected to always be 0 for StepOut. |
| 854 thread_local_.step_count_ = 0; |
| 855 } else { |
| 856 thread_local_.step_count_ = step_count; |
| 857 } |
| 858 |
| 860 // First of all ensure there is one-shot break points in the top handler | 859 // First of all ensure there is one-shot break points in the top handler |
| 861 // if any. | 860 // if any. |
| 862 FloodHandlerWithOneShot(); | 861 FloodHandlerWithOneShot(); |
| 863 | 862 |
| 864 // If the function on the top frame is unresolved perform step out. This will | 863 // If the function on the top frame is unresolved perform step out. This will |
| 865 // be the case when calling unknown function and having the debugger stopped | 864 // be the case when calling unknown function and having the debugger stopped |
| 866 // in an unhandled exception. | 865 // in an unhandled exception. |
| 867 if (!frame->function()->IsJSFunction()) { | 866 if (!frame->function()->IsJSFunction()) { |
| 868 // Step out: Find the calling JavaScript frame and flood it with | 867 // Step out: Find the calling JavaScript frame and flood it with |
| 869 // breakpoints. | 868 // breakpoints. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 924 // Set target frame pointer. | 923 // Set target frame pointer. |
| 925 ActivateStepOut(frames_it.frame()); | 924 ActivateStepOut(frames_it.frame()); |
| 926 } else { | 925 } else { |
| 927 // Stepping out to the embedder. Disable step-in to avoid stepping into | 926 // Stepping out to the embedder. Disable step-in to avoid stepping into |
| 928 // the next (unrelated) call that the embedder makes. | 927 // the next (unrelated) call that the embedder makes. |
| 929 thread_local_.step_in_enabled_ = false; | 928 thread_local_.step_in_enabled_ = false; |
| 930 } | 929 } |
| 931 return; | 930 return; |
| 932 } | 931 } |
| 933 | 932 |
| 934 STATIC_ASSERT(StepFrame > StepIn); | |
| 935 if (step_action >= StepIn) { | |
| 936 // If there's restarter frame on top of the stack, just get the pointer | |
| 937 // to function which is going to be restarted. | |
| 938 if (thread_local_.restarter_frame_function_pointer_ != NULL) { | |
| 939 Handle<JSFunction> restarted_function( | |
| 940 JSFunction::cast(*thread_local_.restarter_frame_function_pointer_)); | |
| 941 FloodWithOneShot(restarted_function); | |
| 942 } | |
| 943 } | |
| 944 | |
| 945 // Fill the current function with one-shot break points even for step in on | 933 // Fill the current function with one-shot break points even for step in on |
| 946 // a call target as the function called might be a native function for | 934 // a call target as the function called might be a native function for |
| 947 // which step in will not stop. It also prepares for stepping in | 935 // which step in will not stop. It also prepares for stepping in |
| 948 // getters/setters. | 936 // getters/setters. |
| 949 // If we are stepping into another frame, only fill calls and returns. | 937 // If we are stepping into another frame, only fill calls and returns. |
| 950 FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS | 938 FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS |
| 951 : ALL_BREAK_LOCATIONS); | 939 : ALL_BREAK_LOCATIONS); |
| 952 | 940 |
| 953 // Remember source position and frame to handle step next. | 941 // Remember source position and frame to handle step next. |
| 954 thread_local_.last_statement_position_ = | 942 thread_local_.last_statement_position_ = |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1042 } | 1030 } |
| 1043 | 1031 |
| 1044 | 1032 |
| 1045 void Debug::ClearStepping() { | 1033 void Debug::ClearStepping() { |
| 1046 // Clear the various stepping setup. | 1034 // Clear the various stepping setup. |
| 1047 ClearOneShot(); | 1035 ClearOneShot(); |
| 1048 ClearStepOut(); | 1036 ClearStepOut(); |
| 1049 | 1037 |
| 1050 thread_local_.step_count_ = 0; | 1038 thread_local_.step_count_ = 0; |
| 1051 thread_local_.last_step_action_ = StepNone; | 1039 thread_local_.last_step_action_ = StepNone; |
| 1040 thread_local_.step_in_enabled_ = false; |
| 1052 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; | 1041 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; |
| 1053 thread_local_.last_fp_ = 0; | 1042 thread_local_.last_fp_ = 0; |
| 1054 } | 1043 } |
| 1055 | 1044 |
| 1056 | 1045 |
| 1057 // Clears all the one-shot break points that are currently set. Normally this | 1046 // Clears all the one-shot break points that are currently set. Normally this |
| 1058 // function is called each time a break point is hit as one shot break points | 1047 // function is called each time a break point is hit as one shot break points |
| 1059 // are used to support stepping. | 1048 // are used to support stepping. |
| 1060 void Debug::ClearOneShot() { | 1049 void Debug::ClearOneShot() { |
| 1061 // The current implementation just runs through all the breakpoints. When the | 1050 // The current implementation just runs through all the breakpoints. When the |
| (...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1515 Address slot_pc = frame->pc() - Assembler::kDebugBreakSlotLength; | 1504 Address slot_pc = frame->pc() - Assembler::kDebugBreakSlotLength; |
| 1516 int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN); | 1505 int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN); |
| 1517 for (RelocIterator it(*code, mask); !it.done(); it.next()) { | 1506 for (RelocIterator it(*code, mask); !it.done(); it.next()) { |
| 1518 if (it.rinfo()->pc() == slot_pc) return true; | 1507 if (it.rinfo()->pc() == slot_pc) return true; |
| 1519 } | 1508 } |
| 1520 return false; | 1509 return false; |
| 1521 } | 1510 } |
| 1522 | 1511 |
| 1523 | 1512 |
| 1524 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, | 1513 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, |
| 1525 LiveEdit::FrameDropMode mode, | 1514 LiveEdit::FrameDropMode mode) { |
| 1526 Object** restarter_frame_function_pointer) { | |
| 1527 if (mode != LiveEdit::CURRENTLY_SET_MODE) { | 1515 if (mode != LiveEdit::CURRENTLY_SET_MODE) { |
| 1528 thread_local_.frame_drop_mode_ = mode; | 1516 thread_local_.frame_drop_mode_ = mode; |
| 1529 } | 1517 } |
| 1530 thread_local_.break_frame_id_ = new_break_frame_id; | 1518 thread_local_.break_frame_id_ = new_break_frame_id; |
| 1531 thread_local_.restarter_frame_function_pointer_ = | |
| 1532 restarter_frame_function_pointer; | |
| 1533 } | 1519 } |
| 1534 | 1520 |
| 1535 | 1521 |
| 1536 bool Debug::IsDebugGlobal(JSGlobalObject* global) { | 1522 bool Debug::IsDebugGlobal(JSGlobalObject* global) { |
| 1537 return is_loaded() && global == debug_context()->global_object(); | 1523 return is_loaded() && global == debug_context()->global_object(); |
| 1538 } | 1524 } |
| 1539 | 1525 |
| 1540 | 1526 |
| 1541 void Debug::ClearMirrorCache() { | 1527 void Debug::ClearMirrorCache() { |
| 1542 PostponeInterruptsScope postpone(isolate_); | 1528 PostponeInterruptsScope postpone(isolate_); |
| (...skipping 977 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2520 } | 2506 } |
| 2521 | 2507 |
| 2522 | 2508 |
| 2523 void LockingCommandMessageQueue::Clear() { | 2509 void LockingCommandMessageQueue::Clear() { |
| 2524 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2510 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
| 2525 queue_.Clear(); | 2511 queue_.Clear(); |
| 2526 } | 2512 } |
| 2527 | 2513 |
| 2528 } // namespace internal | 2514 } // namespace internal |
| 2529 } // namespace v8 | 2515 } // namespace v8 |
| OLD | NEW |