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 749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
760 } | 760 } |
761 | 761 |
762 // Flood the function with break points. | 762 // Flood the function with break points. |
763 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 763 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
764 for (BreakLocation::Iterator it(debug_info, type); !it.Done(); it.Next()) { | 764 for (BreakLocation::Iterator it(debug_info, type); !it.Done(); it.Next()) { |
765 it.GetBreakLocation().SetOneShot(); | 765 it.GetBreakLocation().SetOneShot(); |
766 } | 766 } |
767 } | 767 } |
768 | 768 |
769 | 769 |
770 void Debug::FloodHandlerWithOneShot() { | |
771 // Iterate through the JavaScript stack looking for handlers. | |
772 DCHECK_NE(StackFrame::NO_ID, break_frame_id()); | |
773 for (JavaScriptFrameIterator it(isolate_, break_frame_id()); !it.done(); | |
774 it.Advance()) { | |
775 JavaScriptFrame* frame = it.frame(); | |
776 int stack_slots = 0; // The computed stack slot count is not used. | |
777 if (frame->LookupExceptionHandlerInTable(&stack_slots, NULL) > 0) { | |
778 // Flood the function with the catch/finally block with break points. | |
779 FloodWithOneShot(Handle<JSFunction>(frame->function())); | |
780 return; | |
781 } | |
782 } | |
783 } | |
784 | |
785 | |
786 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) { | 770 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) { |
787 if (type == BreakUncaughtException) { | 771 if (type == BreakUncaughtException) { |
788 break_on_uncaught_exception_ = enable; | 772 break_on_uncaught_exception_ = enable; |
789 } else { | 773 } else { |
790 break_on_exception_ = enable; | 774 break_on_exception_ = enable; |
791 } | 775 } |
792 } | 776 } |
793 | 777 |
794 | 778 |
795 bool Debug::IsBreakOnException(ExceptionBreakType type) { | 779 bool Debug::IsBreakOnException(ExceptionBreakType type) { |
(...skipping 17 matching lines...) Expand all Loading... |
813 if (!IsStepping()) return; | 797 if (!IsStepping()) return; |
814 if (last_step_action() < StepIn) return; | 798 if (last_step_action() < StepIn) return; |
815 if (in_debug_scope()) return; | 799 if (in_debug_scope()) return; |
816 if (thread_local_.step_in_enabled_) { | 800 if (thread_local_.step_in_enabled_) { |
817 ClearStepOut(); | 801 ClearStepOut(); |
818 FloodWithOneShot(function); | 802 FloodWithOneShot(function); |
819 } | 803 } |
820 } | 804 } |
821 | 805 |
822 | 806 |
| 807 void Debug::PrepareStepOnThrow() { |
| 808 if (!is_active()) return; |
| 809 if (!IsStepping()) return; |
| 810 if (last_step_action() == StepNone) return; |
| 811 if (in_debug_scope()) return; |
| 812 |
| 813 ClearOneShot(); |
| 814 |
| 815 // Iterate through the JavaScript stack looking for handlers. |
| 816 JavaScriptFrameIterator it(isolate_); |
| 817 while (!it.done()) { |
| 818 JavaScriptFrame* frame = it.frame(); |
| 819 int stack_slots = 0; // The computed stack slot count is not used. |
| 820 if (frame->LookupExceptionHandlerInTable(&stack_slots, NULL) > 0) break; |
| 821 it.Advance(); |
| 822 } |
| 823 |
| 824 // Find the closest Javascript frame we can flood with one-shots. |
| 825 while (!it.done() && |
| 826 !it.frame()->function()->shared()->IsSubjectToDebugging()) { |
| 827 it.Advance(); |
| 828 } |
| 829 |
| 830 if (it.done()) return; // No suitable Javascript catch handler. |
| 831 |
| 832 FloodWithOneShot(Handle<JSFunction>(it.frame()->function())); |
| 833 } |
| 834 |
| 835 |
823 void Debug::PrepareStep(StepAction step_action, | 836 void Debug::PrepareStep(StepAction step_action, |
824 int step_count, | 837 int step_count, |
825 StackFrame::Id frame_id) { | 838 StackFrame::Id frame_id) { |
826 HandleScope scope(isolate_); | 839 HandleScope scope(isolate_); |
827 | 840 |
828 DCHECK(in_debug_scope()); | 841 DCHECK(in_debug_scope()); |
829 | 842 |
830 // Get the frame where the execution has stopped and skip the debug frame if | 843 // Get the frame where the execution has stopped and skip the debug frame if |
831 // any. The debug frame will only be present if execution was stopped due to | 844 // any. The debug frame will only be present if execution was stopped due to |
832 // hitting a break point. In other situations (e.g. unhandled exception) the | 845 // hitting a break point. In other situations (e.g. unhandled exception) the |
(...skipping 16 matching lines...) Expand all Loading... |
849 STATIC_ASSERT(StepFrame > StepIn); | 862 STATIC_ASSERT(StepFrame > StepIn); |
850 thread_local_.step_in_enabled_ = (step_action >= StepIn); | 863 thread_local_.step_in_enabled_ = (step_action >= StepIn); |
851 if (step_action == StepOut) { | 864 if (step_action == StepOut) { |
852 // For step out target frame will be found on the stack so there is no need | 865 // 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. | 866 // to set step counter for it. It's expected to always be 0 for StepOut. |
854 thread_local_.step_count_ = 0; | 867 thread_local_.step_count_ = 0; |
855 } else { | 868 } else { |
856 thread_local_.step_count_ = step_count; | 869 thread_local_.step_count_ = step_count; |
857 } | 870 } |
858 | 871 |
859 // First of all ensure there is one-shot break points in the top handler | |
860 // if any. | |
861 FloodHandlerWithOneShot(); | |
862 | |
863 // If the function on the top frame is unresolved perform step out. This will | 872 // If the function on the top frame is unresolved perform step out. This will |
864 // be the case when calling unknown function and having the debugger stopped | 873 // be the case when calling unknown function and having the debugger stopped |
865 // in an unhandled exception. | 874 // in an unhandled exception. |
866 if (!frame->function()->IsJSFunction()) { | 875 if (!frame->function()->IsJSFunction()) { |
867 // Step out: Find the calling JavaScript frame and flood it with | 876 // Step out: Find the calling JavaScript frame and flood it with |
868 // breakpoints. | 877 // breakpoints. |
869 frames_it.Advance(); | 878 frames_it.Advance(); |
870 // Fill the function to return to with one-shot break points. | 879 // Fill the function to return to with one-shot break points. |
871 JSFunction* function = frames_it.frame()->function(); | 880 JSFunction* function = frames_it.frame()->function(); |
872 FloodWithOneShot(Handle<JSFunction>(function)); | 881 FloodWithOneShot(Handle<JSFunction>(function)); |
(...skipping 779 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1652 | 1661 |
1653 MaybeHandle<Object> Debug::MakeAsyncTaskEvent(Handle<JSObject> task_event) { | 1662 MaybeHandle<Object> Debug::MakeAsyncTaskEvent(Handle<JSObject> task_event) { |
1654 // Create the async task event object. | 1663 // Create the async task event object. |
1655 Handle<Object> argv[] = { task_event }; | 1664 Handle<Object> argv[] = { task_event }; |
1656 return CallFunction("MakeAsyncTaskEvent", arraysize(argv), argv); | 1665 return CallFunction("MakeAsyncTaskEvent", arraysize(argv), argv); |
1657 } | 1666 } |
1658 | 1667 |
1659 | 1668 |
1660 void Debug::OnThrow(Handle<Object> exception) { | 1669 void Debug::OnThrow(Handle<Object> exception) { |
1661 if (in_debug_scope() || ignore_events()) return; | 1670 if (in_debug_scope() || ignore_events()) return; |
| 1671 PrepareStepOnThrow(); |
1662 // Temporarily clear any scheduled_exception to allow evaluating | 1672 // Temporarily clear any scheduled_exception to allow evaluating |
1663 // JavaScript from the debug event handler. | 1673 // JavaScript from the debug event handler. |
1664 HandleScope scope(isolate_); | 1674 HandleScope scope(isolate_); |
1665 Handle<Object> scheduled_exception; | 1675 Handle<Object> scheduled_exception; |
1666 if (isolate_->has_scheduled_exception()) { | 1676 if (isolate_->has_scheduled_exception()) { |
1667 scheduled_exception = handle(isolate_->scheduled_exception(), isolate_); | 1677 scheduled_exception = handle(isolate_->scheduled_exception(), isolate_); |
1668 isolate_->clear_scheduled_exception(); | 1678 isolate_->clear_scheduled_exception(); |
1669 } | 1679 } |
1670 OnException(exception, isolate_->GetPromiseOnStackOnThrow()); | 1680 OnException(exception, isolate_->GetPromiseOnStackOnThrow()); |
1671 if (!scheduled_exception.is_null()) { | 1681 if (!scheduled_exception.is_null()) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1713 // Uncaught exceptions are reported by either flags. | 1723 // Uncaught exceptions are reported by either flags. |
1714 if (!(break_on_uncaught_exception_ || break_on_exception_)) return; | 1724 if (!(break_on_uncaught_exception_ || break_on_exception_)) return; |
1715 } else { | 1725 } else { |
1716 // Caught exceptions are reported is activated. | 1726 // Caught exceptions are reported is activated. |
1717 if (!break_on_exception_) return; | 1727 if (!break_on_exception_) return; |
1718 } | 1728 } |
1719 | 1729 |
1720 DebugScope debug_scope(this); | 1730 DebugScope debug_scope(this); |
1721 if (debug_scope.failed()) return; | 1731 if (debug_scope.failed()) return; |
1722 | 1732 |
1723 // Clear all current stepping setup. | |
1724 ClearStepping(); | |
1725 | |
1726 // Create the event data object. | 1733 // Create the event data object. |
1727 Handle<Object> event_data; | 1734 Handle<Object> event_data; |
1728 // Bail out and don't call debugger if exception. | 1735 // Bail out and don't call debugger if exception. |
1729 if (!MakeExceptionEvent( | 1736 if (!MakeExceptionEvent( |
1730 exception, uncaught, promise).ToHandle(&event_data)) { | 1737 exception, uncaught, promise).ToHandle(&event_data)) { |
1731 return; | 1738 return; |
1732 } | 1739 } |
1733 | 1740 |
1734 // Process debug event. | 1741 // Process debug event. |
1735 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); | 1742 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); |
(...skipping 770 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2506 } | 2513 } |
2507 | 2514 |
2508 | 2515 |
2509 void LockingCommandMessageQueue::Clear() { | 2516 void LockingCommandMessageQueue::Clear() { |
2510 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2517 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
2511 queue_.Clear(); | 2518 queue_.Clear(); |
2512 } | 2519 } |
2513 | 2520 |
2514 } // namespace internal | 2521 } // namespace internal |
2515 } // namespace v8 | 2522 } // namespace v8 |
OLD | NEW |