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 |