| 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 // Threading support. | 329 // Threading support. |
| 330 void Debug::ThreadInit() { | 330 void Debug::ThreadInit() { |
| 331 thread_local_.break_count_ = 0; | 331 thread_local_.break_count_ = 0; |
| 332 thread_local_.break_id_ = 0; | 332 thread_local_.break_id_ = 0; |
| 333 thread_local_.break_frame_id_ = StackFrame::NO_ID; | 333 thread_local_.break_frame_id_ = StackFrame::NO_ID; |
| 334 thread_local_.last_step_action_ = StepNone; | 334 thread_local_.last_step_action_ = StepNone; |
| 335 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; | 335 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; |
| 336 thread_local_.step_count_ = 0; | 336 thread_local_.step_count_ = 0; |
| 337 thread_local_.last_fp_ = 0; | 337 thread_local_.last_fp_ = 0; |
| 338 thread_local_.queued_step_count_ = 0; | 338 thread_local_.queued_step_count_ = 0; |
| 339 thread_local_.step_into_fp_ = 0; | |
| 340 thread_local_.step_out_fp_ = 0; | 339 thread_local_.step_out_fp_ = 0; |
| 340 thread_local_.step_in_enabled_ = false; |
| 341 // TODO(isolates): frames_are_dropped_? | 341 // TODO(isolates): frames_are_dropped_? |
| 342 base::NoBarrier_Store(&thread_local_.current_debug_scope_, | 342 base::NoBarrier_Store(&thread_local_.current_debug_scope_, |
| 343 static_cast<base::AtomicWord>(0)); | 343 static_cast<base::AtomicWord>(0)); |
| 344 thread_local_.restarter_frame_function_pointer_ = NULL; | 344 thread_local_.restarter_frame_function_pointer_ = NULL; |
| 345 } | 345 } |
| 346 | 346 |
| 347 | 347 |
| 348 char* Debug::ArchiveDebug(char* storage) { | 348 char* Debug::ArchiveDebug(char* storage) { |
| 349 char* to = storage; | 349 char* to = storage; |
| 350 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); | 350 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 741 } | 741 } |
| 742 // Remove all debug info. | 742 // Remove all debug info. |
| 743 while (debug_info_list_ != NULL) { | 743 while (debug_info_list_ != NULL) { |
| 744 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info()); | 744 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info()); |
| 745 } | 745 } |
| 746 } | 746 } |
| 747 | 747 |
| 748 | 748 |
| 749 void Debug::FloodWithOneShot(Handle<JSFunction> function, | 749 void Debug::FloodWithOneShot(Handle<JSFunction> function, |
| 750 BreakLocatorType type) { | 750 BreakLocatorType type) { |
| 751 // Debug utility functions are not subject to debugging. |
| 752 if (function->native_context() == *debug_context()) return; |
| 753 |
| 751 if (!function->shared()->IsSubjectToDebugging()) { | 754 if (!function->shared()->IsSubjectToDebugging()) { |
| 752 // Builtin functions are not subject to stepping, but need to be | 755 // Builtin functions are not subject to stepping, but need to be |
| 753 // deoptimized, because optimized code does not check for debug | 756 // deoptimized, because optimized code does not check for debug |
| 754 // step in at call sites. | 757 // step in at call sites. |
| 755 Deoptimizer::DeoptimizeFunction(*function); | 758 Deoptimizer::DeoptimizeFunction(*function); |
| 756 return; | 759 return; |
| 757 } | 760 } |
| 758 // Make sure the function is compiled and has set up the debug info. | 761 // Make sure the function is compiled and has set up the debug info. |
| 759 Handle<SharedFunctionInfo> shared(function->shared()); | 762 Handle<SharedFunctionInfo> shared(function->shared()); |
| 760 if (!EnsureDebugInfo(shared, function)) { | 763 if (!EnsureDebugInfo(shared, function)) { |
| 761 // Return if we failed to retrieve the debug info. | 764 // Return if we failed to retrieve the debug info. |
| 762 return; | 765 return; |
| 763 } | 766 } |
| 764 | 767 |
| 765 // Flood the function with break points. | 768 // Flood the function with break points. |
| 766 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 769 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
| 767 for (BreakLocation::Iterator it(debug_info, type); !it.Done(); it.Next()) { | 770 for (BreakLocation::Iterator it(debug_info, type); !it.Done(); it.Next()) { |
| 768 it.GetBreakLocation().SetOneShot(); | 771 it.GetBreakLocation().SetOneShot(); |
| 769 } | 772 } |
| 770 } | 773 } |
| 771 | 774 |
| 772 | 775 |
| 773 void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) { | |
| 774 Handle<BindingsArray> new_bindings(function->function_bindings()); | |
| 775 Handle<Object> bindee(new_bindings->bound_function(), isolate_); | |
| 776 | |
| 777 if (!bindee.is_null() && bindee->IsJSFunction()) { | |
| 778 Handle<JSFunction> bindee_function(JSFunction::cast(*bindee)); | |
| 779 FloodWithOneShotGeneric(bindee_function); | |
| 780 } | |
| 781 } | |
| 782 | |
| 783 | |
| 784 void Debug::FloodDefaultConstructorWithOneShot(Handle<JSFunction> function) { | |
| 785 DCHECK(function->shared()->is_default_constructor()); | |
| 786 // Instead of stepping into the function we directly step into the super class | |
| 787 // constructor. | |
| 788 Isolate* isolate = function->GetIsolate(); | |
| 789 PrototypeIterator iter(isolate, function); | |
| 790 Handle<Object> proto = PrototypeIterator::GetCurrent(iter); | |
| 791 if (!proto->IsJSFunction()) return; // Object.prototype | |
| 792 Handle<JSFunction> function_proto = Handle<JSFunction>::cast(proto); | |
| 793 FloodWithOneShotGeneric(function_proto); | |
| 794 } | |
| 795 | |
| 796 | |
| 797 void Debug::FloodWithOneShotGeneric(Handle<JSFunction> function, | |
| 798 Handle<Object> holder) { | |
| 799 if (function->shared()->bound()) { | |
| 800 FloodBoundFunctionWithOneShot(function); | |
| 801 } else if (function->shared()->is_default_constructor()) { | |
| 802 FloodDefaultConstructorWithOneShot(function); | |
| 803 } else { | |
| 804 Isolate* isolate = function->GetIsolate(); | |
| 805 // Don't allow step into functions in the native context. | |
| 806 if (function->shared()->code() == | |
| 807 isolate->builtins()->builtin(Builtins::kFunctionApply) || | |
| 808 function->shared()->code() == | |
| 809 isolate->builtins()->builtin(Builtins::kFunctionCall)) { | |
| 810 // Handle function.apply and function.call separately to flood the | |
| 811 // function to be called and not the code for Builtins::FunctionApply or | |
| 812 // Builtins::FunctionCall. The receiver of call/apply is the target | |
| 813 // function. | |
| 814 if (!holder.is_null() && holder->IsJSFunction()) { | |
| 815 Handle<JSFunction> js_function = Handle<JSFunction>::cast(holder); | |
| 816 FloodWithOneShotGeneric(js_function); | |
| 817 } | |
| 818 } else { | |
| 819 FloodWithOneShot(function); | |
| 820 } | |
| 821 } | |
| 822 } | |
| 823 | |
| 824 | |
| 825 void Debug::FloodHandlerWithOneShot() { | 776 void Debug::FloodHandlerWithOneShot() { |
| 826 // Iterate through the JavaScript stack looking for handlers. | 777 // Iterate through the JavaScript stack looking for handlers. |
| 827 StackFrame::Id id = break_frame_id(); | 778 DCHECK_NE(StackFrame::NO_ID, break_frame_id()); |
| 828 if (id == StackFrame::NO_ID) { | 779 for (JavaScriptFrameIterator it(isolate_, break_frame_id()); !it.done(); |
| 829 // If there is no JavaScript stack don't do anything. | 780 it.Advance()) { |
| 830 return; | |
| 831 } | |
| 832 for (JavaScriptFrameIterator it(isolate_, id); !it.done(); it.Advance()) { | |
| 833 JavaScriptFrame* frame = it.frame(); | 781 JavaScriptFrame* frame = it.frame(); |
| 834 int stack_slots = 0; // The computed stack slot count is not used. | 782 int stack_slots = 0; // The computed stack slot count is not used. |
| 835 if (frame->LookupExceptionHandlerInTable(&stack_slots, NULL) > 0) { | 783 if (frame->LookupExceptionHandlerInTable(&stack_slots, NULL) > 0) { |
| 836 // Flood the function with the catch/finally block with break points. | 784 // Flood the function with the catch/finally block with break points. |
| 837 FloodWithOneShot(Handle<JSFunction>(frame->function())); | 785 FloodWithOneShot(Handle<JSFunction>(frame->function())); |
| 838 return; | 786 return; |
| 839 } | 787 } |
| 840 } | 788 } |
| 841 } | 789 } |
| 842 | 790 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 859 } | 807 } |
| 860 | 808 |
| 861 | 809 |
| 862 FrameSummary GetFirstFrameSummary(JavaScriptFrame* frame) { | 810 FrameSummary GetFirstFrameSummary(JavaScriptFrame* frame) { |
| 863 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); | 811 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); |
| 864 frame->Summarize(&frames); | 812 frame->Summarize(&frames); |
| 865 return frames.first(); | 813 return frames.first(); |
| 866 } | 814 } |
| 867 | 815 |
| 868 | 816 |
| 817 void Debug::PrepareStepIn(Handle<JSFunction> function) { |
| 818 if (!is_active()) return; |
| 819 if (!IsStepping()) return; |
| 820 if (last_step_action() < StepIn) return; |
| 821 if (in_debug_scope()) return; |
| 822 if (thread_local_.step_in_enabled_) { |
| 823 ClearStepOut(); |
| 824 FloodWithOneShot(function); |
| 825 } |
| 826 } |
| 827 |
| 828 |
| 869 void Debug::PrepareStep(StepAction step_action, | 829 void Debug::PrepareStep(StepAction step_action, |
| 870 int step_count, | 830 int step_count, |
| 871 StackFrame::Id frame_id) { | 831 StackFrame::Id frame_id) { |
| 872 HandleScope scope(isolate_); | 832 HandleScope scope(isolate_); |
| 873 | 833 |
| 874 DCHECK(in_debug_scope()); | 834 DCHECK(in_debug_scope()); |
| 875 | 835 |
| 876 // Remember this step action and count. | 836 // Remember this step action and count. |
| 877 thread_local_.last_step_action_ = step_action; | 837 thread_local_.last_step_action_ = step_action; |
| 838 STATIC_ASSERT(StepFrame > StepIn); |
| 839 thread_local_.step_in_enabled_ = (step_action >= StepIn); |
| 878 if (step_action == StepOut) { | 840 if (step_action == StepOut) { |
| 879 // For step out target frame will be found on the stack so there is no need | 841 // For step out target frame will be found on the stack so there is no need |
| 880 // to set step counter for it. It's expected to always be 0 for StepOut. | 842 // to set step counter for it. It's expected to always be 0 for StepOut. |
| 881 thread_local_.step_count_ = 0; | 843 thread_local_.step_count_ = 0; |
| 882 } else { | 844 } else { |
| 883 thread_local_.step_count_ = step_count; | 845 thread_local_.step_count_ = step_count; |
| 884 } | 846 } |
| 885 | 847 |
| 886 // Get the frame where the execution has stopped and skip the debug frame if | 848 // Get the frame where the execution has stopped and skip the debug frame if |
| 887 // any. The debug frame will only be present if execution was stopped due to | 849 // any. The debug frame will only be present if execution was stopped due to |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 943 while (step_count-- > 0 && !frames_it.done()) { | 905 while (step_count-- > 0 && !frames_it.done()) { |
| 944 frames_it.Advance(); | 906 frames_it.Advance(); |
| 945 } | 907 } |
| 946 } else { | 908 } else { |
| 947 DCHECK(location.IsReturn()); | 909 DCHECK(location.IsReturn()); |
| 948 frames_it.Advance(); | 910 frames_it.Advance(); |
| 949 } | 911 } |
| 950 // Skip native and extension functions on the stack. | 912 // Skip native and extension functions on the stack. |
| 951 while (!frames_it.done() && | 913 while (!frames_it.done() && |
| 952 !frames_it.frame()->function()->shared()->IsSubjectToDebugging()) { | 914 !frames_it.frame()->function()->shared()->IsSubjectToDebugging()) { |
| 915 if (step_action >= StepIn) { |
| 916 // Builtin functions are not subject to stepping, but need to be |
| 917 // deoptimized, because optimized code does not check for debug |
| 918 // step in at call sites. |
| 919 Deoptimizer::DeoptimizeFunction(frames_it.frame()->function()); |
| 920 } |
| 953 frames_it.Advance(); | 921 frames_it.Advance(); |
| 954 } | 922 } |
| 955 // Step out: If there is a JavaScript caller frame, we need to | 923 // Step out: If there is a JavaScript caller frame, we need to |
| 956 // flood it with breakpoints. | 924 // flood it with breakpoints. |
| 957 if (!frames_it.done()) { | 925 if (!frames_it.done()) { |
| 958 // Fill the function to return to with one-shot break points. | 926 // Fill the function to return to with one-shot break points. |
| 959 JSFunction* function = frames_it.frame()->function(); | 927 JSFunction* function = frames_it.frame()->function(); |
| 960 FloodWithOneShot(Handle<JSFunction>(function)); | 928 FloodWithOneShot(Handle<JSFunction>(function)); |
| 961 // Set target frame pointer. | 929 // Set target frame pointer. |
| 962 ActivateStepOut(frames_it.frame()); | 930 ActivateStepOut(frames_it.frame()); |
| 931 } else { |
| 932 // Stepping out to the embedder. Disable step-in to avoid stepping into |
| 933 // the next (unrelated) call that the embedder makes. |
| 934 thread_local_.step_in_enabled_ = false; |
| 963 } | 935 } |
| 964 return; | 936 return; |
| 965 } | 937 } |
| 966 | 938 |
| 967 if (step_action != StepNext) { | 939 STATIC_ASSERT(StepFrame > StepIn); |
| 940 if (step_action >= StepIn) { |
| 968 // If there's restarter frame on top of the stack, just get the pointer | 941 // If there's restarter frame on top of the stack, just get the pointer |
| 969 // to function which is going to be restarted. | 942 // to function which is going to be restarted. |
| 970 if (thread_local_.restarter_frame_function_pointer_ != NULL) { | 943 if (thread_local_.restarter_frame_function_pointer_ != NULL) { |
| 971 Handle<JSFunction> restarted_function( | 944 Handle<JSFunction> restarted_function( |
| 972 JSFunction::cast(*thread_local_.restarter_frame_function_pointer_)); | 945 JSFunction::cast(*thread_local_.restarter_frame_function_pointer_)); |
| 973 FloodWithOneShot(restarted_function); | 946 FloodWithOneShot(restarted_function); |
| 974 } else if (location.IsStepInLocation()) { | |
| 975 // Find target function on the expression stack. | |
| 976 // Expression stack looks like this (top to bottom): | |
| 977 // argN | |
| 978 // ... | |
| 979 // arg0 | |
| 980 // Receiver (only present for calls, not for construct). | |
| 981 // Function to call | |
| 982 int base = location.IsCall() ? 2 : 1; | |
| 983 int num_expressions_without_args = | |
| 984 frame->ComputeExpressionsCount() - location.CallArgumentsCount(); | |
| 985 DCHECK(num_expressions_without_args >= base); | |
| 986 Object* fun = frame->GetExpression(num_expressions_without_args - base); | |
| 987 | |
| 988 // Flood the actual target of call/apply. | |
| 989 if (location.IsCall() && fun->IsJSFunction()) { | |
| 990 Isolate* isolate = JSFunction::cast(fun)->GetIsolate(); | |
| 991 Code* apply = isolate->builtins()->builtin(Builtins::kFunctionApply); | |
| 992 Code* call = isolate->builtins()->builtin(Builtins::kFunctionCall); | |
| 993 // Find target function on the expression stack for expression like | |
| 994 // Function.call.call...apply(...) | |
| 995 int i = 1; | |
| 996 while (fun->IsJSFunction()) { | |
| 997 Code* code = JSFunction::cast(fun)->shared()->code(); | |
| 998 if (code != apply && code != call) break; | |
| 999 DCHECK(num_expressions_without_args >= i); | |
| 1000 fun = frame->GetExpression(num_expressions_without_args - i); | |
| 1001 i--; | |
| 1002 } | |
| 1003 } | |
| 1004 | |
| 1005 if (fun->IsJSFunction()) { | |
| 1006 Handle<JSFunction> js_function(JSFunction::cast(fun)); | |
| 1007 FloodWithOneShotGeneric(js_function); | |
| 1008 } | |
| 1009 } | 947 } |
| 1010 | |
| 1011 ActivateStepIn(frame); | |
| 1012 } | 948 } |
| 1013 | 949 |
| 1014 // Fill the current function with one-shot break points even for step in on | 950 // Fill the current function with one-shot break points even for step in on |
| 1015 // a call target as the function called might be a native function for | 951 // a call target as the function called might be a native function for |
| 1016 // which step in will not stop. It also prepares for stepping in | 952 // which step in will not stop. It also prepares for stepping in |
| 1017 // getters/setters. | 953 // getters/setters. |
| 1018 // If we are stepping into another frame, only fill calls and returns. | 954 // If we are stepping into another frame, only fill calls and returns. |
| 1019 FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS | 955 FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS |
| 1020 : ALL_BREAK_LOCATIONS); | 956 : ALL_BREAK_LOCATIONS); |
| 1021 | 957 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1104 position = Smi::FromInt(break_point_info->source_position()); | 1040 position = Smi::FromInt(break_point_info->source_position()); |
| 1105 break; | 1041 break; |
| 1106 } | 1042 } |
| 1107 for (int j = 0; j < break_points; ++j) locations->set(count++, position); | 1043 for (int j = 0; j < break_points; ++j) locations->set(count++, position); |
| 1108 } | 1044 } |
| 1109 } | 1045 } |
| 1110 return locations; | 1046 return locations; |
| 1111 } | 1047 } |
| 1112 | 1048 |
| 1113 | 1049 |
| 1114 // Handle stepping into a function. | |
| 1115 void Debug::HandleStepIn(Handle<Object> function_obj) { | |
| 1116 // Flood getter/setter if we either step in or step to another frame. | |
| 1117 bool step_frame = thread_local_.last_step_action_ == StepFrame; | |
| 1118 if (!StepInActive() && !step_frame) return; | |
| 1119 if (!function_obj->IsJSFunction()) return; | |
| 1120 Handle<JSFunction> function = Handle<JSFunction>::cast(function_obj); | |
| 1121 Isolate* isolate = function->GetIsolate(); | |
| 1122 | |
| 1123 StackFrameIterator it(isolate); | |
| 1124 it.Advance(); | |
| 1125 Address fp = it.frame()->fp(); | |
| 1126 | |
| 1127 // Flood the function with one-shot break points if it is called from where | |
| 1128 // step into was requested, or when stepping into a new frame. | |
| 1129 if (fp == thread_local_.step_into_fp_ || step_frame) { | |
| 1130 FloodWithOneShotGeneric(function, Handle<Object>()); | |
| 1131 } | |
| 1132 } | |
| 1133 | |
| 1134 | |
| 1135 void Debug::ClearStepping() { | 1050 void Debug::ClearStepping() { |
| 1136 // Clear the various stepping setup. | 1051 // Clear the various stepping setup. |
| 1137 ClearOneShot(); | 1052 ClearOneShot(); |
| 1138 ClearStepIn(); | |
| 1139 ClearStepOut(); | 1053 ClearStepOut(); |
| 1140 ClearStepNext(); | |
| 1141 | 1054 |
| 1142 // Clear multiple step counter. | |
| 1143 thread_local_.step_count_ = 0; | 1055 thread_local_.step_count_ = 0; |
| 1056 thread_local_.last_step_action_ = StepNone; |
| 1057 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; |
| 1058 thread_local_.last_fp_ = 0; |
| 1144 } | 1059 } |
| 1145 | 1060 |
| 1146 | 1061 |
| 1147 // Clears all the one-shot break points that are currently set. Normally this | 1062 // Clears all the one-shot break points that are currently set. Normally this |
| 1148 // function is called each time a break point is hit as one shot break points | 1063 // function is called each time a break point is hit as one shot break points |
| 1149 // are used to support stepping. | 1064 // are used to support stepping. |
| 1150 void Debug::ClearOneShot() { | 1065 void Debug::ClearOneShot() { |
| 1151 // The current implementation just runs through all the breakpoints. When the | 1066 // The current implementation just runs through all the breakpoints. When the |
| 1152 // last break point for a function is removed that function is automatically | 1067 // last break point for a function is removed that function is automatically |
| 1153 // removed from the list. | 1068 // removed from the list. |
| 1154 for (DebugInfoListNode* node = debug_info_list_; node != NULL; | 1069 for (DebugInfoListNode* node = debug_info_list_; node != NULL; |
| 1155 node = node->next()) { | 1070 node = node->next()) { |
| 1156 for (BreakLocation::Iterator it(node->debug_info(), ALL_BREAK_LOCATIONS); | 1071 for (BreakLocation::Iterator it(node->debug_info(), ALL_BREAK_LOCATIONS); |
| 1157 !it.Done(); it.Next()) { | 1072 !it.Done(); it.Next()) { |
| 1158 it.GetBreakLocation().ClearOneShot(); | 1073 it.GetBreakLocation().ClearOneShot(); |
| 1159 } | 1074 } |
| 1160 } | 1075 } |
| 1161 } | 1076 } |
| 1162 | 1077 |
| 1163 | 1078 |
| 1164 void Debug::ActivateStepIn(StackFrame* frame) { | |
| 1165 DCHECK(!StepOutActive()); | |
| 1166 thread_local_.step_into_fp_ = frame->UnpaddedFP(); | |
| 1167 } | |
| 1168 | |
| 1169 | |
| 1170 void Debug::ClearStepIn() { | |
| 1171 thread_local_.step_into_fp_ = 0; | |
| 1172 } | |
| 1173 | |
| 1174 | |
| 1175 void Debug::ActivateStepOut(StackFrame* frame) { | 1079 void Debug::ActivateStepOut(StackFrame* frame) { |
| 1176 DCHECK(!StepInActive()); | |
| 1177 thread_local_.step_out_fp_ = frame->UnpaddedFP(); | 1080 thread_local_.step_out_fp_ = frame->UnpaddedFP(); |
| 1178 } | 1081 } |
| 1179 | 1082 |
| 1180 | 1083 |
| 1181 void Debug::ClearStepOut() { | 1084 void Debug::EnableStepIn() { |
| 1182 thread_local_.step_out_fp_ = 0; | 1085 STATIC_ASSERT(StepFrame > StepIn); |
| 1086 thread_local_.step_in_enabled_ = (last_step_action() >= StepIn); |
| 1183 } | 1087 } |
| 1184 | 1088 |
| 1185 | 1089 |
| 1186 void Debug::ClearStepNext() { | 1090 void Debug::ClearStepOut() { thread_local_.step_out_fp_ = 0; } |
| 1187 thread_local_.last_step_action_ = StepNone; | |
| 1188 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; | |
| 1189 thread_local_.last_fp_ = 0; | |
| 1190 } | |
| 1191 | 1091 |
| 1192 | 1092 |
| 1193 bool MatchingCodeTargets(Code* target1, Code* target2) { | 1093 bool MatchingCodeTargets(Code* target1, Code* target2) { |
| 1194 if (target1 == target2) return true; | 1094 if (target1 == target2) return true; |
| 1195 if (target1->kind() != target2->kind()) return false; | 1095 if (target1->kind() != target2->kind()) return false; |
| 1196 return target1->is_handler() || target1->is_inline_cache_stub(); | 1096 return target1->is_handler() || target1->is_inline_cache_stub(); |
| 1197 } | 1097 } |
| 1198 | 1098 |
| 1199 | 1099 |
| 1200 // Count the number of calls before the current frame PC to find the | 1100 // Count the number of calls before the current frame PC to find the |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1535 if (shared->HasDebugInfo()) return true; | 1435 if (shared->HasDebugInfo()) return true; |
| 1536 | 1436 |
| 1537 if (function.is_null()) { | 1437 if (function.is_null()) { |
| 1538 DCHECK(shared->HasDebugCode()); | 1438 DCHECK(shared->HasDebugCode()); |
| 1539 } else if (!Compiler::Compile(function, CLEAR_EXCEPTION)) { | 1439 } else if (!Compiler::Compile(function, CLEAR_EXCEPTION)) { |
| 1540 return false; | 1440 return false; |
| 1541 } | 1441 } |
| 1542 | 1442 |
| 1543 if (!PrepareFunctionForBreakPoints(shared)) return false; | 1443 if (!PrepareFunctionForBreakPoints(shared)) return false; |
| 1544 | 1444 |
| 1545 // Make sure IC state is clean. This is so that we correctly flood | |
| 1546 // accessor pairs when stepping in. | |
| 1547 shared->code()->ClearInlineCaches(); | |
| 1548 shared->ClearTypeFeedbackInfo(); | |
| 1549 | |
| 1550 CreateDebugInfo(shared); | 1445 CreateDebugInfo(shared); |
| 1551 | 1446 |
| 1552 return true; | 1447 return true; |
| 1553 } | 1448 } |
| 1554 | 1449 |
| 1555 | 1450 |
| 1556 void Debug::CreateDebugInfo(Handle<SharedFunctionInfo> shared) { | 1451 void Debug::CreateDebugInfo(Handle<SharedFunctionInfo> shared) { |
| 1557 // Create the debug info object. | 1452 // Create the debug info object. |
| 1558 DCHECK(shared->HasDebugCode()); | 1453 DCHECK(shared->HasDebugCode()); |
| 1559 Handle<DebugInfo> debug_info = isolate_->factory()->NewDebugInfo(shared); | 1454 Handle<DebugInfo> debug_info = isolate_->factory()->NewDebugInfo(shared); |
| (...skipping 791 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2351 debug_->SetNextBreakId(); | 2246 debug_->SetNextBreakId(); |
| 2352 | 2247 |
| 2353 debug_->UpdateState(); | 2248 debug_->UpdateState(); |
| 2354 // Make sure that debugger is loaded and enter the debugger context. | 2249 // Make sure that debugger is loaded and enter the debugger context. |
| 2355 // The previous context is kept in save_. | 2250 // The previous context is kept in save_. |
| 2356 failed_ = !debug_->is_loaded(); | 2251 failed_ = !debug_->is_loaded(); |
| 2357 if (!failed_) isolate()->set_context(*debug->debug_context()); | 2252 if (!failed_) isolate()->set_context(*debug->debug_context()); |
| 2358 } | 2253 } |
| 2359 | 2254 |
| 2360 | 2255 |
| 2361 | |
| 2362 DebugScope::~DebugScope() { | 2256 DebugScope::~DebugScope() { |
| 2363 if (!failed_ && prev_ == NULL) { | 2257 if (!failed_ && prev_ == NULL) { |
| 2364 // Clear mirror cache when leaving the debugger. Skip this if there is a | 2258 // Clear mirror cache when leaving the debugger. Skip this if there is a |
| 2365 // pending exception as clearing the mirror cache calls back into | 2259 // pending exception as clearing the mirror cache calls back into |
| 2366 // JavaScript. This can happen if the v8::Debug::Call is used in which | 2260 // JavaScript. This can happen if the v8::Debug::Call is used in which |
| 2367 // case the exception should end up in the calling code. | 2261 // case the exception should end up in the calling code. |
| 2368 if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache(); | 2262 if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache(); |
| 2369 | 2263 |
| 2370 // If there are commands in the queue when leaving the debugger request | 2264 // If there are commands in the queue when leaving the debugger request |
| 2371 // that these commands are processed. | 2265 // that these commands are processed. |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2631 } | 2525 } |
| 2632 | 2526 |
| 2633 | 2527 |
| 2634 void LockingCommandMessageQueue::Clear() { | 2528 void LockingCommandMessageQueue::Clear() { |
| 2635 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2529 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
| 2636 queue_.Clear(); | 2530 queue_.Clear(); |
| 2637 } | 2531 } |
| 2638 | 2532 |
| 2639 } // namespace internal | 2533 } // namespace internal |
| 2640 } // namespace v8 | 2534 } // namespace v8 |
| OLD | NEW |