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 |