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/v8.h" | 5 #include "src/v8.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 18 matching lines...) Expand all Loading... |
29 Debug::Debug(Isolate* isolate) | 29 Debug::Debug(Isolate* isolate) |
30 : debug_context_(Handle<Context>()), | 30 : debug_context_(Handle<Context>()), |
31 event_listener_(Handle<Object>()), | 31 event_listener_(Handle<Object>()), |
32 event_listener_data_(Handle<Object>()), | 32 event_listener_data_(Handle<Object>()), |
33 message_handler_(NULL), | 33 message_handler_(NULL), |
34 command_received_(0), | 34 command_received_(0), |
35 command_queue_(isolate->logger(), kQueueInitialSize), | 35 command_queue_(isolate->logger(), kQueueInitialSize), |
36 is_active_(false), | 36 is_active_(false), |
37 is_suppressed_(false), | 37 is_suppressed_(false), |
38 live_edit_enabled_(true), // TODO(yangguo): set to false by default. | 38 live_edit_enabled_(true), // TODO(yangguo): set to false by default. |
39 has_break_points_(false), | |
40 break_disabled_(false), | 39 break_disabled_(false), |
41 in_debug_event_listener_(false), | 40 in_debug_event_listener_(false), |
42 break_on_exception_(false), | 41 break_on_exception_(false), |
43 break_on_uncaught_exception_(false), | 42 break_on_uncaught_exception_(false), |
44 script_cache_(NULL), | 43 script_cache_(NULL), |
45 debug_info_list_(NULL), | 44 debug_info_list_(NULL), |
46 isolate_(isolate) { | 45 isolate_(isolate) { |
47 ThreadInit(); | 46 ThreadInit(); |
48 } | 47 } |
49 | 48 |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 break; | 138 break; |
140 } | 139 } |
141 break_index_++; | 140 break_index_++; |
142 } | 141 } |
143 | 142 |
144 | 143 |
145 // Find the break point at the supplied address, or the closest one before | 144 // Find the break point at the supplied address, or the closest one before |
146 // the address. | 145 // the address. |
147 BreakLocation BreakLocation::FromAddress(Handle<DebugInfo> debug_info, | 146 BreakLocation BreakLocation::FromAddress(Handle<DebugInfo> debug_info, |
148 BreakLocatorType type, Address pc) { | 147 BreakLocatorType type, Address pc) { |
149 DCHECK(debug_info->code()->has_debug_break_slots()); | |
150 Iterator it(debug_info, type); | 148 Iterator it(debug_info, type); |
151 it.SkipTo(BreakIndexFromAddress(debug_info, type, pc)); | 149 it.SkipTo(BreakIndexFromAddress(debug_info, type, pc)); |
152 return it.GetBreakLocation(); | 150 return it.GetBreakLocation(); |
153 } | 151 } |
154 | 152 |
155 | 153 |
156 // Find the break point at the supplied address, or the closest one before | 154 // Find the break point at the supplied address, or the closest one before |
157 // the address. | 155 // the address. |
158 void BreakLocation::FromAddressSameStatement(Handle<DebugInfo> debug_info, | 156 void BreakLocation::FromAddressSameStatement(Handle<DebugInfo> debug_info, |
159 BreakLocatorType type, Address pc, | 157 BreakLocatorType type, Address pc, |
160 List<BreakLocation>* result_out) { | 158 List<BreakLocation>* result_out) { |
161 DCHECK(debug_info->code()->has_debug_break_slots()); | |
162 int break_index = BreakIndexFromAddress(debug_info, type, pc); | 159 int break_index = BreakIndexFromAddress(debug_info, type, pc); |
163 Iterator it(debug_info, type); | 160 Iterator it(debug_info, type); |
164 it.SkipTo(break_index); | 161 it.SkipTo(break_index); |
165 int statement_position = it.statement_position(); | 162 int statement_position = it.statement_position(); |
166 while (!it.Done() && it.statement_position() == statement_position) { | 163 while (!it.Done() && it.statement_position() == statement_position) { |
167 result_out->Add(it.GetBreakLocation()); | 164 result_out->Add(it.GetBreakLocation()); |
168 it.Next(); | 165 it.Next(); |
169 } | 166 } |
170 } | 167 } |
171 | 168 |
(...skipping 12 matching lines...) Expand all Loading... |
184 if (distance == 0) break; | 181 if (distance == 0) break; |
185 } | 182 } |
186 } | 183 } |
187 return closest_break; | 184 return closest_break; |
188 } | 185 } |
189 | 186 |
190 | 187 |
191 BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info, | 188 BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info, |
192 BreakLocatorType type, int position, | 189 BreakLocatorType type, int position, |
193 BreakPositionAlignment alignment) { | 190 BreakPositionAlignment alignment) { |
194 DCHECK(debug_info->code()->has_debug_break_slots()); | |
195 // Run through all break points to locate the one closest to the source | 191 // Run through all break points to locate the one closest to the source |
196 // position. | 192 // position. |
197 int closest_break = 0; | 193 int closest_break = 0; |
198 int distance = kMaxInt; | 194 int distance = kMaxInt; |
199 | 195 |
200 for (Iterator it(debug_info, type); !it.Done(); it.Next()) { | 196 for (Iterator it(debug_info, type); !it.Done(); it.Next()) { |
201 int next_position; | 197 int next_position; |
202 if (alignment == STATEMENT_ALIGNED) { | 198 if (alignment == STATEMENT_ALIGNED) { |
203 next_position = it.statement_position(); | 199 next_position = it.statement_position(); |
204 } else { | 200 } else { |
(...skipping 10 matching lines...) Expand all Loading... |
215 | 211 |
216 Iterator it(debug_info, type); | 212 Iterator it(debug_info, type); |
217 it.SkipTo(closest_break); | 213 it.SkipTo(closest_break); |
218 return it.GetBreakLocation(); | 214 return it.GetBreakLocation(); |
219 } | 215 } |
220 | 216 |
221 | 217 |
222 void BreakLocation::SetBreakPoint(Handle<Object> break_point_object) { | 218 void BreakLocation::SetBreakPoint(Handle<Object> break_point_object) { |
223 // If there is not already a real break point here patch code with debug | 219 // If there is not already a real break point here patch code with debug |
224 // break. | 220 // break. |
225 DCHECK(code()->has_debug_break_slots()); | |
226 if (!HasBreakPoint()) SetDebugBreak(); | 221 if (!HasBreakPoint()) SetDebugBreak(); |
227 DCHECK(IsDebugBreak() || IsDebuggerStatement()); | 222 DCHECK(IsDebugBreak() || IsDebuggerStatement()); |
228 // Set the break point information. | 223 // Set the break point information. |
229 DebugInfo::SetBreakPoint(debug_info_, pc_offset_, position_, | 224 DebugInfo::SetBreakPoint(debug_info_, pc_offset_, position_, |
230 statement_position_, break_point_object); | 225 statement_position_, break_point_object); |
231 } | 226 } |
232 | 227 |
233 | 228 |
234 void BreakLocation::ClearBreakPoint(Handle<Object> break_point_object) { | 229 void BreakLocation::ClearBreakPoint(Handle<Object> break_point_object) { |
235 // Clear the break point information. | 230 // Clear the break point information. |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
600 // Enter the debugger. | 595 // Enter the debugger. |
601 DebugScope debug_scope(this); | 596 DebugScope debug_scope(this); |
602 if (debug_scope.failed()) return; | 597 if (debug_scope.failed()) return; |
603 | 598 |
604 // Postpone interrupt during breakpoint processing. | 599 // Postpone interrupt during breakpoint processing. |
605 PostponeInterruptsScope postpone(isolate_); | 600 PostponeInterruptsScope postpone(isolate_); |
606 | 601 |
607 // Get the debug info (create it if it does not exist). | 602 // Get the debug info (create it if it does not exist). |
608 Handle<SharedFunctionInfo> shared = | 603 Handle<SharedFunctionInfo> shared = |
609 Handle<SharedFunctionInfo>(frame->function()->shared()); | 604 Handle<SharedFunctionInfo>(frame->function()->shared()); |
610 Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 605 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
611 | 606 |
612 // Find the break point where execution has stopped. | 607 // Find the break point where execution has stopped. |
613 // PC points to the instruction after the current one, possibly a break | 608 // PC points to the instruction after the current one, possibly a break |
614 // location as well. So the "- 1" to exclude it from the search. | 609 // location as well. So the "- 1" to exclude it from the search. |
615 Address call_pc = frame->pc() - 1; | 610 Address call_pc = frame->pc() - 1; |
616 BreakLocation break_location = | 611 BreakLocation break_location = |
617 BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc); | 612 BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc); |
618 | 613 |
619 // Check whether step next reached a new statement. | 614 // Check whether step next reached a new statement. |
620 if (!StepNextContinue(&break_location, frame)) { | 615 if (!StepNextContinue(&break_location, frame)) { |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
773 arraysize(argv), | 768 arraysize(argv), |
774 argv).ToHandle(&result)) { | 769 argv).ToHandle(&result)) { |
775 return false; | 770 return false; |
776 } | 771 } |
777 | 772 |
778 // Return whether the break point is triggered. | 773 // Return whether the break point is triggered. |
779 return result->IsTrue(); | 774 return result->IsTrue(); |
780 } | 775 } |
781 | 776 |
782 | 777 |
783 // Check whether the function has debug information. | |
784 bool Debug::HasDebugInfo(Handle<SharedFunctionInfo> shared) { | |
785 return !shared->debug_info()->IsUndefined(); | |
786 } | |
787 | |
788 | |
789 // Return the debug info for this function. EnsureDebugInfo must be called | |
790 // prior to ensure the debug info has been generated for shared. | |
791 Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) { | |
792 DCHECK(HasDebugInfo(shared)); | |
793 return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info())); | |
794 } | |
795 | |
796 | |
797 bool Debug::SetBreakPoint(Handle<JSFunction> function, | 778 bool Debug::SetBreakPoint(Handle<JSFunction> function, |
798 Handle<Object> break_point_object, | 779 Handle<Object> break_point_object, |
799 int* source_position) { | 780 int* source_position) { |
800 HandleScope scope(isolate_); | 781 HandleScope scope(isolate_); |
801 | 782 |
802 PrepareForBreakPoints(); | |
803 | |
804 // Make sure the function is compiled and has set up the debug info. | 783 // Make sure the function is compiled and has set up the debug info. |
805 Handle<SharedFunctionInfo> shared(function->shared()); | 784 Handle<SharedFunctionInfo> shared(function->shared()); |
806 if (!EnsureDebugInfo(shared, function)) { | 785 if (!EnsureDebugInfo(shared, function)) { |
807 // Return if retrieving debug info failed. | 786 // Return if retrieving debug info failed. |
808 return true; | 787 return true; |
809 } | 788 } |
810 | 789 |
811 Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 790 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
812 // Source positions starts with zero. | 791 // Source positions starts with zero. |
813 DCHECK(*source_position >= 0); | 792 DCHECK(*source_position >= 0); |
814 | 793 |
815 // Find the break point and change it. | 794 // Find the break point and change it. |
816 BreakLocation location = BreakLocation::FromPosition( | 795 BreakLocation location = BreakLocation::FromPosition( |
817 debug_info, ALL_BREAK_LOCATIONS, *source_position, STATEMENT_ALIGNED); | 796 debug_info, ALL_BREAK_LOCATIONS, *source_position, STATEMENT_ALIGNED); |
818 *source_position = location.statement_position(); | 797 *source_position = location.statement_position(); |
819 location.SetBreakPoint(break_point_object); | 798 location.SetBreakPoint(break_point_object); |
820 | 799 |
821 // At least one active break point now. | 800 // At least one active break point now. |
822 return debug_info->GetBreakPointCount() > 0; | 801 return debug_info->GetBreakPointCount() > 0; |
823 } | 802 } |
824 | 803 |
825 | 804 |
826 bool Debug::SetBreakPointForScript(Handle<Script> script, | 805 bool Debug::SetBreakPointForScript(Handle<Script> script, |
827 Handle<Object> break_point_object, | 806 Handle<Object> break_point_object, |
828 int* source_position, | 807 int* source_position, |
829 BreakPositionAlignment alignment) { | 808 BreakPositionAlignment alignment) { |
830 HandleScope scope(isolate_); | 809 HandleScope scope(isolate_); |
831 | 810 |
832 PrepareForBreakPoints(); | |
833 | |
834 // Obtain shared function info for the function. | 811 // Obtain shared function info for the function. |
835 Handle<Object> result = | 812 Handle<Object> result = |
836 FindSharedFunctionInfoInScript(script, *source_position); | 813 FindSharedFunctionInfoInScript(script, *source_position); |
837 if (result->IsUndefined()) return false; | 814 if (result->IsUndefined()) return false; |
838 | 815 |
839 // Make sure the function has set up the debug info. | 816 // Make sure the function has set up the debug info. |
840 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result); | 817 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result); |
841 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) { | 818 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) { |
842 // Return if retrieving debug info failed. | 819 // Return if retrieving debug info failed. |
843 return false; | 820 return false; |
844 } | 821 } |
845 | 822 |
846 // Find position within function. The script position might be before the | 823 // Find position within function. The script position might be before the |
847 // source position of the first function. | 824 // source position of the first function. |
848 int position; | 825 int position; |
849 if (shared->start_position() > *source_position) { | 826 if (shared->start_position() > *source_position) { |
850 position = 0; | 827 position = 0; |
851 } else { | 828 } else { |
852 position = *source_position - shared->start_position(); | 829 position = *source_position - shared->start_position(); |
853 } | 830 } |
854 | 831 |
855 Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 832 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
856 // Source positions starts with zero. | 833 // Source positions starts with zero. |
857 DCHECK(position >= 0); | 834 DCHECK(position >= 0); |
858 | 835 |
859 // Find the break point and change it. | 836 // Find the break point and change it. |
860 BreakLocation location = BreakLocation::FromPosition( | 837 BreakLocation location = BreakLocation::FromPosition( |
861 debug_info, ALL_BREAK_LOCATIONS, position, alignment); | 838 debug_info, ALL_BREAK_LOCATIONS, position, alignment); |
862 location.SetBreakPoint(break_point_object); | 839 location.SetBreakPoint(break_point_object); |
863 | 840 |
864 position = (alignment == STATEMENT_ALIGNED) ? location.statement_position() | 841 position = (alignment == STATEMENT_ALIGNED) ? location.statement_position() |
865 : location.position(); | 842 : location.position(); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
919 } | 896 } |
920 // Remove all debug info. | 897 // Remove all debug info. |
921 while (debug_info_list_ != NULL) { | 898 while (debug_info_list_ != NULL) { |
922 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info()); | 899 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info()); |
923 } | 900 } |
924 } | 901 } |
925 | 902 |
926 | 903 |
927 void Debug::FloodWithOneShot(Handle<JSFunction> function, | 904 void Debug::FloodWithOneShot(Handle<JSFunction> function, |
928 BreakLocatorType type) { | 905 BreakLocatorType type) { |
929 PrepareForBreakPoints(); | |
930 | |
931 // Make sure the function is compiled and has set up the debug info. | 906 // Make sure the function is compiled and has set up the debug info. |
932 Handle<SharedFunctionInfo> shared(function->shared()); | 907 Handle<SharedFunctionInfo> shared(function->shared()); |
933 if (!EnsureDebugInfo(shared, function)) { | 908 if (!EnsureDebugInfo(shared, function)) { |
934 // Return if we failed to retrieve the debug info. | 909 // Return if we failed to retrieve the debug info. |
935 return; | 910 return; |
936 } | 911 } |
937 | 912 |
938 // Flood the function with break points. | 913 // Flood the function with break points. |
939 for (BreakLocation::Iterator it(GetDebugInfo(shared), type); !it.Done(); | 914 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
940 it.Next()) { | 915 for (BreakLocation::Iterator it(debug_info, type); !it.Done(); it.Next()) { |
941 it.GetBreakLocation().SetOneShot(); | 916 it.GetBreakLocation().SetOneShot(); |
942 } | 917 } |
943 } | 918 } |
944 | 919 |
945 | 920 |
946 void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) { | 921 void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) { |
947 Handle<FixedArray> new_bindings(function->function_bindings()); | 922 Handle<FixedArray> new_bindings(function->function_bindings()); |
948 Handle<Object> bindee(new_bindings->get(JSFunction::kBoundFunctionIndex), | 923 Handle<Object> bindee(new_bindings->get(JSFunction::kBoundFunctionIndex), |
949 isolate_); | 924 isolate_); |
950 | 925 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1026 | 1001 |
1027 bool Debug::IsBreakOnException(ExceptionBreakType type) { | 1002 bool Debug::IsBreakOnException(ExceptionBreakType type) { |
1028 if (type == BreakUncaughtException) { | 1003 if (type == BreakUncaughtException) { |
1029 return break_on_uncaught_exception_; | 1004 return break_on_uncaught_exception_; |
1030 } else { | 1005 } else { |
1031 return break_on_exception_; | 1006 return break_on_exception_; |
1032 } | 1007 } |
1033 } | 1008 } |
1034 | 1009 |
1035 | 1010 |
| 1011 FrameSummary GetFirstFrameSummary(JavaScriptFrame* frame) { |
| 1012 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); |
| 1013 frame->Summarize(&frames); |
| 1014 return frames.first(); |
| 1015 } |
| 1016 |
| 1017 |
1036 void Debug::PrepareStep(StepAction step_action, | 1018 void Debug::PrepareStep(StepAction step_action, |
1037 int step_count, | 1019 int step_count, |
1038 StackFrame::Id frame_id) { | 1020 StackFrame::Id frame_id) { |
1039 HandleScope scope(isolate_); | 1021 HandleScope scope(isolate_); |
1040 | 1022 |
1041 PrepareForBreakPoints(); | |
1042 | |
1043 DCHECK(in_debug_scope()); | 1023 DCHECK(in_debug_scope()); |
1044 | 1024 |
1045 // Remember this step action and count. | 1025 // Remember this step action and count. |
1046 thread_local_.last_step_action_ = step_action; | 1026 thread_local_.last_step_action_ = step_action; |
1047 if (step_action == StepOut) { | 1027 if (step_action == StepOut) { |
1048 // For step out target frame will be found on the stack so there is no need | 1028 // For step out target frame will be found on the stack so there is no need |
1049 // to set step counter for it. It's expected to always be 0 for StepOut. | 1029 // to set step counter for it. It's expected to always be 0 for StepOut. |
1050 thread_local_.step_count_ = 0; | 1030 thread_local_.step_count_ = 0; |
1051 } else { | 1031 } else { |
1052 thread_local_.step_count_ = step_count; | 1032 thread_local_.step_count_ = step_count; |
(...skipping 24 matching lines...) Expand all Loading... |
1077 if (!frame->function()->IsJSFunction()) { | 1057 if (!frame->function()->IsJSFunction()) { |
1078 // Step out: Find the calling JavaScript frame and flood it with | 1058 // Step out: Find the calling JavaScript frame and flood it with |
1079 // breakpoints. | 1059 // breakpoints. |
1080 frames_it.Advance(); | 1060 frames_it.Advance(); |
1081 // Fill the function to return to with one-shot break points. | 1061 // Fill the function to return to with one-shot break points. |
1082 JSFunction* function = frames_it.frame()->function(); | 1062 JSFunction* function = frames_it.frame()->function(); |
1083 FloodWithOneShot(Handle<JSFunction>(function)); | 1063 FloodWithOneShot(Handle<JSFunction>(function)); |
1084 return; | 1064 return; |
1085 } | 1065 } |
1086 | 1066 |
1087 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); | |
1088 frames_it.frame()->Summarize(&frames); | |
1089 FrameSummary summary = frames.first(); | |
1090 | |
1091 // Get the debug info (create it if it does not exist). | 1067 // Get the debug info (create it if it does not exist). |
| 1068 FrameSummary summary = GetFirstFrameSummary(frame); |
1092 Handle<JSFunction> function(summary.function()); | 1069 Handle<JSFunction> function(summary.function()); |
1093 Handle<SharedFunctionInfo> shared(function->shared()); | 1070 Handle<SharedFunctionInfo> shared(function->shared()); |
1094 if (!EnsureDebugInfo(shared, function)) { | 1071 if (!EnsureDebugInfo(shared, function)) { |
1095 // Return if ensuring debug info failed. | 1072 // Return if ensuring debug info failed. |
1096 return; | 1073 return; |
1097 } | 1074 } |
1098 Handle<DebugInfo> debug_info = GetDebugInfo(shared); | |
1099 | 1075 |
1100 // Compute whether or not the target is a call target. | 1076 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
1101 bool is_at_restarted_function = false; | 1077 // Refresh frame summary if the code has been recompiled for debugging. |
1102 Handle<Code> call_function_stub; | 1078 if (shared->code() != *summary.code()) summary = GetFirstFrameSummary(frame); |
1103 | 1079 |
1104 // PC points to the instruction after the current one, possibly a break | 1080 // PC points to the instruction after the current one, possibly a break |
1105 // location as well. So the "- 1" to exclude it from the search. | 1081 // location as well. So the "- 1" to exclude it from the search. |
1106 Address call_pc = summary.pc() - 1; | 1082 Address call_pc = summary.pc() - 1; |
1107 BreakLocation location = | 1083 BreakLocation location = |
1108 BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc); | 1084 BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc); |
1109 | 1085 |
1110 if (thread_local_.restarter_frame_function_pointer_ != NULL) { | |
1111 is_at_restarted_function = true; | |
1112 } | |
1113 | |
1114 // If this is the last break code target step out is the only possibility. | 1086 // If this is the last break code target step out is the only possibility. |
1115 if (location.IsReturn() || step_action == StepOut) { | 1087 if (location.IsReturn() || step_action == StepOut) { |
1116 if (step_action == StepOut) { | 1088 if (step_action == StepOut) { |
1117 // Skip step_count frames starting with the current one. | 1089 // Skip step_count frames starting with the current one. |
1118 while (step_count-- > 0 && !frames_it.done()) { | 1090 while (step_count-- > 0 && !frames_it.done()) { |
1119 frames_it.Advance(); | 1091 frames_it.Advance(); |
1120 } | 1092 } |
1121 } else { | 1093 } else { |
1122 DCHECK(location.IsReturn()); | 1094 DCHECK(location.IsReturn()); |
1123 frames_it.Advance(); | 1095 frames_it.Advance(); |
(...skipping 11 matching lines...) Expand all Loading... |
1135 FloodWithOneShot(Handle<JSFunction>(function)); | 1107 FloodWithOneShot(Handle<JSFunction>(function)); |
1136 // Set target frame pointer. | 1108 // Set target frame pointer. |
1137 ActivateStepOut(frames_it.frame()); | 1109 ActivateStepOut(frames_it.frame()); |
1138 } | 1110 } |
1139 return; | 1111 return; |
1140 } | 1112 } |
1141 | 1113 |
1142 if (step_action != StepNext && step_action != StepMin) { | 1114 if (step_action != StepNext && step_action != StepMin) { |
1143 // If there's restarter frame on top of the stack, just get the pointer | 1115 // If there's restarter frame on top of the stack, just get the pointer |
1144 // to function which is going to be restarted. | 1116 // to function which is going to be restarted. |
1145 if (is_at_restarted_function) { | 1117 if (thread_local_.restarter_frame_function_pointer_ != NULL) { |
1146 Handle<JSFunction> restarted_function( | 1118 Handle<JSFunction> restarted_function( |
1147 JSFunction::cast(*thread_local_.restarter_frame_function_pointer_)); | 1119 JSFunction::cast(*thread_local_.restarter_frame_function_pointer_)); |
1148 FloodWithOneShot(restarted_function); | 1120 FloodWithOneShot(restarted_function); |
1149 } else if (location.IsCall()) { | 1121 } else if (location.IsCall()) { |
1150 // Find target function on the expression stack. | 1122 // Find target function on the expression stack. |
1151 // Expression stack looks like this (top to bottom): | 1123 // Expression stack looks like this (top to bottom): |
1152 // argN | 1124 // argN |
1153 // ... | 1125 // ... |
1154 // arg0 | 1126 // arg0 |
1155 // Receiver | 1127 // Receiver |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1246 return code->is_debug_stub(); | 1218 return code->is_debug_stub(); |
1247 } | 1219 } |
1248 | 1220 |
1249 | 1221 |
1250 // Simple function for returning the source positions for active break points. | 1222 // Simple function for returning the source positions for active break points. |
1251 Handle<Object> Debug::GetSourceBreakLocations( | 1223 Handle<Object> Debug::GetSourceBreakLocations( |
1252 Handle<SharedFunctionInfo> shared, | 1224 Handle<SharedFunctionInfo> shared, |
1253 BreakPositionAlignment position_alignment) { | 1225 BreakPositionAlignment position_alignment) { |
1254 Isolate* isolate = shared->GetIsolate(); | 1226 Isolate* isolate = shared->GetIsolate(); |
1255 Heap* heap = isolate->heap(); | 1227 Heap* heap = isolate->heap(); |
1256 if (!HasDebugInfo(shared)) { | 1228 if (!shared->HasDebugInfo()) { |
1257 return Handle<Object>(heap->undefined_value(), isolate); | 1229 return Handle<Object>(heap->undefined_value(), isolate); |
1258 } | 1230 } |
1259 Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 1231 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
1260 if (debug_info->GetBreakPointCount() == 0) { | 1232 if (debug_info->GetBreakPointCount() == 0) { |
1261 return Handle<Object>(heap->undefined_value(), isolate); | 1233 return Handle<Object>(heap->undefined_value(), isolate); |
1262 } | 1234 } |
1263 Handle<FixedArray> locations = | 1235 Handle<FixedArray> locations = |
1264 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount()); | 1236 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount()); |
1265 int count = 0; | 1237 int count = 0; |
1266 for (int i = 0; i < debug_info->break_points()->length(); ++i) { | 1238 for (int i = 0; i < debug_info->break_points()->length(); ++i) { |
1267 if (!debug_info->break_points()->get(i)->IsUndefined()) { | 1239 if (!debug_info->break_points()->get(i)->IsUndefined()) { |
1268 BreakPointInfo* break_point_info = | 1240 BreakPointInfo* break_point_info = |
1269 BreakPointInfo::cast(debug_info->break_points()->get(i)); | 1241 BreakPointInfo::cast(debug_info->break_points()->get(i)); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1362 } | 1334 } |
1363 | 1335 |
1364 | 1336 |
1365 void Debug::ClearStepNext() { | 1337 void Debug::ClearStepNext() { |
1366 thread_local_.last_step_action_ = StepNone; | 1338 thread_local_.last_step_action_ = StepNone; |
1367 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; | 1339 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; |
1368 thread_local_.last_fp_ = 0; | 1340 thread_local_.last_fp_ = 0; |
1369 } | 1341 } |
1370 | 1342 |
1371 | 1343 |
1372 static void CollectActiveFunctionsFromThread( | |
1373 Isolate* isolate, | |
1374 ThreadLocalTop* top, | |
1375 List<Handle<JSFunction> >* active_functions, | |
1376 Object* active_code_marker) { | |
1377 // Find all non-optimized code functions with activation frames | |
1378 // on the stack. This includes functions which have optimized | |
1379 // activations (including inlined functions) on the stack as the | |
1380 // non-optimized code is needed for the lazy deoptimization. | |
1381 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) { | |
1382 JavaScriptFrame* frame = it.frame(); | |
1383 if (frame->is_optimized()) { | |
1384 List<JSFunction*> functions(FLAG_max_inlining_levels + 1); | |
1385 frame->GetFunctions(&functions); | |
1386 for (int i = 0; i < functions.length(); i++) { | |
1387 JSFunction* function = functions[i]; | |
1388 active_functions->Add(Handle<JSFunction>(function)); | |
1389 function->shared()->code()->set_gc_metadata(active_code_marker); | |
1390 } | |
1391 } else if (frame->function()->IsJSFunction()) { | |
1392 JSFunction* function = frame->function(); | |
1393 DCHECK(frame->LookupCode()->kind() == Code::FUNCTION); | |
1394 active_functions->Add(Handle<JSFunction>(function)); | |
1395 function->shared()->code()->set_gc_metadata(active_code_marker); | |
1396 } | |
1397 } | |
1398 } | |
1399 | |
1400 | |
1401 // Count the number of calls before the current frame PC to find the | 1344 // Count the number of calls before the current frame PC to find the |
1402 // corresponding PC in the newly recompiled code. | 1345 // corresponding PC in the newly recompiled code. |
1403 static Address ComputeNewPcForRedirect(Code* new_code, Code* old_code, | 1346 static Address ComputeNewPcForRedirect(Code* new_code, Code* old_code, |
1404 Address old_pc) { | 1347 Address old_pc) { |
1405 DCHECK_EQ(old_code->kind(), Code::FUNCTION); | 1348 DCHECK_EQ(old_code->kind(), Code::FUNCTION); |
1406 DCHECK_EQ(new_code->kind(), Code::FUNCTION); | 1349 DCHECK_EQ(new_code->kind(), Code::FUNCTION); |
1407 DCHECK(!old_code->has_debug_break_slots()); | |
1408 DCHECK(new_code->has_debug_break_slots()); | 1350 DCHECK(new_code->has_debug_break_slots()); |
1409 int mask = RelocInfo::kCodeTargetMask; | 1351 int mask = RelocInfo::kCodeTargetMask; |
1410 int index = 0; | 1352 int index = 0; |
1411 intptr_t delta = 0; | 1353 intptr_t delta = 0; |
1412 for (RelocIterator it(old_code, mask); !it.done(); it.next()) { | 1354 for (RelocIterator it(old_code, mask); !it.done(); it.next()) { |
1413 RelocInfo* rinfo = it.rinfo(); | 1355 RelocInfo* rinfo = it.rinfo(); |
1414 Address current_pc = rinfo->pc(); | 1356 Address current_pc = rinfo->pc(); |
1415 // The frame PC is behind the call instruction by the call instruction size. | 1357 // The frame PC is behind the call instruction by the call instruction size. |
1416 if (current_pc > old_pc) break; | 1358 if (current_pc > old_pc) break; |
1417 index++; | 1359 index++; |
1418 delta = old_pc - current_pc; | 1360 delta = old_pc - current_pc; |
1419 } | 1361 } |
1420 | 1362 |
1421 RelocIterator it(new_code, mask); | 1363 RelocIterator it(new_code, mask); |
1422 for (int i = 1; i < index; i++) it.next(); | 1364 for (int i = 1; i < index; i++) it.next(); |
1423 return it.rinfo()->pc() + delta; | 1365 return it.rinfo()->pc() + delta; |
1424 } | 1366 } |
1425 | 1367 |
1426 | 1368 |
1427 // Count the number of continuations at which the current pc offset is at. | 1369 // Count the number of continuations at which the current pc offset is at. |
1428 static int ComputeContinuationIndexFromPcOffset(Code* code, int pc_offset) { | 1370 static int ComputeContinuationIndexFromPcOffset(Code* code, int pc_offset) { |
1429 DCHECK_EQ(code->kind(), Code::FUNCTION); | 1371 DCHECK_EQ(code->kind(), Code::FUNCTION); |
1430 DCHECK(!code->has_debug_break_slots()); | |
1431 Address pc = code->instruction_start() + pc_offset; | 1372 Address pc = code->instruction_start() + pc_offset; |
1432 int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION); | 1373 int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION); |
1433 int index = 0; | 1374 int index = 0; |
1434 for (RelocIterator it(code, mask); !it.done(); it.next()) { | 1375 for (RelocIterator it(code, mask); !it.done(); it.next()) { |
1435 index++; | 1376 index++; |
1436 RelocInfo* rinfo = it.rinfo(); | 1377 RelocInfo* rinfo = it.rinfo(); |
1437 Address current_pc = rinfo->pc(); | 1378 Address current_pc = rinfo->pc(); |
1438 if (current_pc == pc) break; | 1379 if (current_pc == pc) break; |
1439 DCHECK(current_pc < pc); | 1380 DCHECK(current_pc < pc); |
1440 } | 1381 } |
1441 return index; | 1382 return index; |
1442 } | 1383 } |
1443 | 1384 |
1444 | 1385 |
1445 // Find the pc offset for the given continuation index. | 1386 // Find the pc offset for the given continuation index. |
1446 static int ComputePcOffsetFromContinuationIndex(Code* code, int index) { | 1387 static int ComputePcOffsetFromContinuationIndex(Code* code, int index) { |
1447 DCHECK_EQ(code->kind(), Code::FUNCTION); | 1388 DCHECK_EQ(code->kind(), Code::FUNCTION); |
1448 DCHECK(code->has_debug_break_slots()); | 1389 DCHECK(code->has_debug_break_slots()); |
1449 int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION); | 1390 int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION); |
1450 RelocIterator it(code, mask); | 1391 RelocIterator it(code, mask); |
1451 for (int i = 1; i < index; i++) it.next(); | 1392 for (int i = 1; i < index; i++) it.next(); |
1452 return static_cast<int>(it.rinfo()->pc() - code->instruction_start()); | 1393 return static_cast<int>(it.rinfo()->pc() - code->instruction_start()); |
1453 } | 1394 } |
1454 | 1395 |
1455 | 1396 |
1456 static void RedirectActivationsToRecompiledCodeOnThread( | 1397 class RedirectActiveFunctions : public ThreadVisitor { |
1457 Isolate* isolate, | 1398 public: |
1458 ThreadLocalTop* top) { | 1399 explicit RedirectActiveFunctions(SharedFunctionInfo* shared) |
1459 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) { | 1400 : shared_(shared) { |
1460 JavaScriptFrame* frame = it.frame(); | 1401 DCHECK(shared->HasDebugCode()); |
| 1402 } |
1461 | 1403 |
1462 if (frame->is_optimized() || !frame->function()->IsJSFunction()) continue; | 1404 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { |
| 1405 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) { |
| 1406 JavaScriptFrame* frame = it.frame(); |
| 1407 JSFunction* function = frame->function(); |
| 1408 if (frame->is_optimized()) continue; |
| 1409 if (!function->Inlines(shared_)) continue; |
1463 | 1410 |
1464 JSFunction* function = frame->function(); | 1411 Code* frame_code = frame->LookupCode(); |
| 1412 DCHECK(frame_code->kind() == Code::FUNCTION); |
| 1413 if (frame_code->has_debug_break_slots()) continue; |
1465 | 1414 |
1466 DCHECK(frame->LookupCode()->kind() == Code::FUNCTION); | 1415 Code* new_code = function->shared()->code(); |
| 1416 Address old_pc = frame->pc(); |
| 1417 Address new_pc = ComputeNewPcForRedirect(new_code, frame_code, old_pc); |
1467 | 1418 |
1468 Handle<Code> frame_code(frame->LookupCode()); | 1419 if (FLAG_trace_deopt) { |
1469 if (frame_code->has_debug_break_slots()) continue; | 1420 PrintF("Replacing pc for debugging: %08" V8PRIxPTR " => %08" V8PRIxPTR |
| 1421 "\n", |
| 1422 reinterpret_cast<intptr_t>(old_pc), |
| 1423 reinterpret_cast<intptr_t>(new_pc)); |
| 1424 } |
1470 | 1425 |
1471 Handle<Code> new_code(function->shared()->code()); | 1426 if (FLAG_enable_embedded_constant_pool) { |
1472 if (new_code->kind() != Code::FUNCTION || | 1427 // Update constant pool pointer for new code. |
1473 !new_code->has_debug_break_slots()) { | 1428 frame->set_constant_pool(new_code->constant_pool()); |
1474 continue; | 1429 } |
| 1430 |
| 1431 // Patch the return address to return into the code with |
| 1432 // debug break slots. |
| 1433 frame->set_pc(new_pc); |
1475 } | 1434 } |
| 1435 } |
1476 | 1436 |
1477 Address new_pc = | 1437 private: |
1478 ComputeNewPcForRedirect(*new_code, *frame_code, frame->pc()); | 1438 SharedFunctionInfo* shared_; |
| 1439 DisallowHeapAllocation no_gc_; |
| 1440 }; |
1479 | 1441 |
1480 if (FLAG_trace_deopt) { | 1442 |
1481 PrintF("Replacing code %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) " | 1443 bool Debug::PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared) { |
1482 "with %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) " | 1444 DCHECK(shared->is_compiled()); |
1483 "for debugging, " | 1445 |
1484 "changing pc from %08" V8PRIxPTR " to %08" V8PRIxPTR "\n", | 1446 if (isolate_->concurrent_recompilation_enabled()) { |
1485 reinterpret_cast<intptr_t>( | 1447 isolate_->optimizing_compile_dispatcher()->Flush(); |
1486 frame_code->instruction_start()), | 1448 } |
1487 reinterpret_cast<intptr_t>( | 1449 |
1488 frame_code->instruction_start()) + | 1450 List<Handle<JSFunction> > functions; |
1489 frame_code->instruction_size(), | 1451 List<Handle<JSGeneratorObject> > suspended_generators; |
1490 frame_code->instruction_size(), | 1452 |
1491 reinterpret_cast<intptr_t>(new_code->instruction_start()), | 1453 if (!shared->optimized_code_map()->IsSmi()) { |
1492 reinterpret_cast<intptr_t>(new_code->instruction_start()) + | 1454 shared->ClearOptimizedCodeMap(); |
1493 new_code->instruction_size(), | 1455 } |
1494 new_code->instruction_size(), | 1456 |
1495 reinterpret_cast<intptr_t>(frame->pc()), | 1457 // Make sure we abort incremental marking. |
1496 reinterpret_cast<intptr_t>(new_pc)); | 1458 isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask, |
| 1459 "prepare for break points"); |
| 1460 |
| 1461 { |
| 1462 HeapIterator iterator(isolate_->heap()); |
| 1463 HeapObject* obj; |
| 1464 bool include_generators = shared->is_generator(); |
| 1465 |
| 1466 while ((obj = iterator.next())) { |
| 1467 if (obj->IsJSFunction()) { |
| 1468 JSFunction* function = JSFunction::cast(obj); |
| 1469 if (!function->Inlines(*shared)) continue; |
| 1470 if (function->code()->kind() == Code::OPTIMIZED_FUNCTION) { |
| 1471 Deoptimizer::DeoptimizeFunction(function); |
| 1472 } |
| 1473 functions.Add(handle(function)); |
| 1474 } else if (include_generators && obj->IsJSGeneratorObject()) { |
| 1475 JSGeneratorObject* generator_obj = JSGeneratorObject::cast(obj); |
| 1476 if (!generator_obj->is_suspended()) continue; |
| 1477 JSFunction* function = generator_obj->function(); |
| 1478 if (!function->Inlines(*shared)) continue; |
| 1479 int pc_offset = generator_obj->continuation(); |
| 1480 int index = |
| 1481 ComputeContinuationIndexFromPcOffset(function->code(), pc_offset); |
| 1482 generator_obj->set_continuation(index); |
| 1483 suspended_generators.Add(handle(generator_obj)); |
| 1484 } |
1497 } | 1485 } |
| 1486 } |
1498 | 1487 |
1499 if (FLAG_enable_embedded_constant_pool) { | 1488 if (!shared->HasDebugCode()) { |
1500 // Update constant pool pointer for new code. | 1489 DCHECK(functions.length() > 0); |
1501 frame->set_constant_pool(new_code->constant_pool()); | 1490 if (Compiler::GetDebugCode(functions.first()).is_null()) { |
| 1491 return false; |
1502 } | 1492 } |
| 1493 } |
1503 | 1494 |
1504 // Patch the return address to return into the code with | 1495 for (Handle<JSFunction> const function : functions) { |
1505 // debug break slots. | 1496 function->ReplaceCode(shared->code()); |
1506 frame->set_pc(new_pc); | |
1507 } | 1497 } |
| 1498 |
| 1499 for (Handle<JSGeneratorObject> const generator_obj : suspended_generators) { |
| 1500 int index = generator_obj->continuation(); |
| 1501 int pc_offset = ComputePcOffsetFromContinuationIndex(shared->code(), index); |
| 1502 generator_obj->set_continuation(pc_offset); |
| 1503 } |
| 1504 |
| 1505 // Update PCs on the stack to point to recompiled code. |
| 1506 RedirectActiveFunctions redirect_visitor(*shared); |
| 1507 redirect_visitor.VisitThread(isolate_, isolate_->thread_local_top()); |
| 1508 isolate_->thread_manager()->IterateArchivedThreads(&redirect_visitor); |
| 1509 |
| 1510 return true; |
1508 } | 1511 } |
1509 | 1512 |
1510 | 1513 |
1511 class ActiveFunctionsCollector : public ThreadVisitor { | |
1512 public: | |
1513 explicit ActiveFunctionsCollector(List<Handle<JSFunction> >* active_functions, | |
1514 Object* active_code_marker) | |
1515 : active_functions_(active_functions), | |
1516 active_code_marker_(active_code_marker) { } | |
1517 | |
1518 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { | |
1519 CollectActiveFunctionsFromThread(isolate, | |
1520 top, | |
1521 active_functions_, | |
1522 active_code_marker_); | |
1523 } | |
1524 | |
1525 private: | |
1526 List<Handle<JSFunction> >* active_functions_; | |
1527 Object* active_code_marker_; | |
1528 }; | |
1529 | |
1530 | |
1531 class ActiveFunctionsRedirector : public ThreadVisitor { | |
1532 public: | |
1533 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { | |
1534 RedirectActivationsToRecompiledCodeOnThread(isolate, top); | |
1535 } | |
1536 }; | |
1537 | |
1538 | |
1539 static void EnsureFunctionHasDebugBreakSlots(Handle<JSFunction> function) { | |
1540 if (function->code()->kind() == Code::FUNCTION && | |
1541 function->code()->has_debug_break_slots()) { | |
1542 // Nothing to do. Function code already had debug break slots. | |
1543 return; | |
1544 } | |
1545 // Make sure that the shared full code is compiled with debug | |
1546 // break slots. | |
1547 if (!function->shared()->code()->has_debug_break_slots()) { | |
1548 MaybeHandle<Code> code = Compiler::GetDebugCode(function); | |
1549 // Recompilation can fail. In that case leave the code as it was. | |
1550 if (!code.is_null()) function->ReplaceCode(*code.ToHandleChecked()); | |
1551 } else { | |
1552 // Simply use shared code if it has debug break slots. | |
1553 function->ReplaceCode(function->shared()->code()); | |
1554 } | |
1555 } | |
1556 | |
1557 | |
1558 static void RecompileAndRelocateSuspendedGenerators( | |
1559 const List<Handle<JSGeneratorObject> > &generators) { | |
1560 for (int i = 0; i < generators.length(); i++) { | |
1561 Handle<JSFunction> fun(generators[i]->function()); | |
1562 | |
1563 EnsureFunctionHasDebugBreakSlots(fun); | |
1564 | |
1565 int index = generators[i]->continuation(); | |
1566 int pc_offset = ComputePcOffsetFromContinuationIndex(fun->code(), index); | |
1567 generators[i]->set_continuation(pc_offset); | |
1568 } | |
1569 } | |
1570 | |
1571 | |
1572 static bool SkipSharedFunctionInfo(SharedFunctionInfo* shared, | |
1573 Object* active_code_marker) { | |
1574 if (!shared->allows_lazy_compilation()) return true; | |
1575 Object* script = shared->script(); | |
1576 if (!script->IsScript()) return true; | |
1577 if (Script::cast(script)->type()->value() == Script::TYPE_NATIVE) return true; | |
1578 Code* shared_code = shared->code(); | |
1579 return shared_code->gc_metadata() == active_code_marker; | |
1580 } | |
1581 | |
1582 | |
1583 static inline bool HasDebugBreakSlots(Code* code) { | |
1584 return code->kind() == Code::FUNCTION && code->has_debug_break_slots(); | |
1585 } | |
1586 | |
1587 | |
1588 void Debug::PrepareForBreakPoints() { | |
1589 // If preparing for the first break point make sure to deoptimize all | |
1590 // functions as debugging does not work with optimized code. | |
1591 if (!has_break_points_) { | |
1592 if (isolate_->concurrent_recompilation_enabled()) { | |
1593 isolate_->optimizing_compile_dispatcher()->Flush(); | |
1594 } | |
1595 | |
1596 Deoptimizer::DeoptimizeAll(isolate_); | |
1597 | |
1598 Handle<Code> lazy_compile = isolate_->builtins()->CompileLazy(); | |
1599 | |
1600 // There will be at least one break point when we are done. | |
1601 has_break_points_ = true; | |
1602 | |
1603 // Keep the list of activated functions in a handlified list as it | |
1604 // is used both in GC and non-GC code. | |
1605 List<Handle<JSFunction> > active_functions(100); | |
1606 | |
1607 // A list of all suspended generators. | |
1608 List<Handle<JSGeneratorObject> > suspended_generators; | |
1609 | |
1610 // A list of all generator functions. We need to recompile all functions, | |
1611 // but we don't know until after visiting the whole heap which generator | |
1612 // functions have suspended activations and which do not. As in the case of | |
1613 // functions with activations on the stack, we need to be careful with | |
1614 // generator functions with suspended activations because although they | |
1615 // should be recompiled, recompilation can fail, and we need to avoid | |
1616 // leaving the heap in an inconsistent state. | |
1617 // | |
1618 // We could perhaps avoid this list and instead re-use the GC metadata | |
1619 // links. | |
1620 List<Handle<JSFunction> > generator_functions; | |
1621 | |
1622 { | |
1623 // We are going to iterate heap to find all functions without | |
1624 // debug break slots. | |
1625 Heap* heap = isolate_->heap(); | |
1626 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, | |
1627 "preparing for breakpoints"); | |
1628 HeapIterator iterator(heap); | |
1629 | |
1630 // Ensure no GC in this scope as we are going to use gc_metadata | |
1631 // field in the Code object to mark active functions. | |
1632 DisallowHeapAllocation no_allocation; | |
1633 | |
1634 Object* active_code_marker = heap->the_hole_value(); | |
1635 | |
1636 CollectActiveFunctionsFromThread(isolate_, | |
1637 isolate_->thread_local_top(), | |
1638 &active_functions, | |
1639 active_code_marker); | |
1640 ActiveFunctionsCollector active_functions_collector(&active_functions, | |
1641 active_code_marker); | |
1642 isolate_->thread_manager()->IterateArchivedThreads( | |
1643 &active_functions_collector); | |
1644 | |
1645 // Scan the heap for all non-optimized functions which have no | |
1646 // debug break slots and are not active or inlined into an active | |
1647 // function and mark them for lazy compilation. | |
1648 HeapObject* obj = NULL; | |
1649 while (((obj = iterator.next()) != NULL)) { | |
1650 if (obj->IsJSFunction()) { | |
1651 JSFunction* function = JSFunction::cast(obj); | |
1652 SharedFunctionInfo* shared = function->shared(); | |
1653 if (SkipSharedFunctionInfo(shared, active_code_marker)) continue; | |
1654 if (shared->is_generator()) { | |
1655 generator_functions.Add(Handle<JSFunction>(function, isolate_)); | |
1656 continue; | |
1657 } | |
1658 if (HasDebugBreakSlots(function->code())) continue; | |
1659 Code* fallback = HasDebugBreakSlots(shared->code()) ? shared->code() | |
1660 : *lazy_compile; | |
1661 Code::Kind kind = function->code()->kind(); | |
1662 if (kind == Code::FUNCTION || | |
1663 (kind == Code::BUILTIN && // Abort in-flight compilation. | |
1664 (function->IsInOptimizationQueue() || | |
1665 function->IsMarkedForOptimization() || | |
1666 function->IsMarkedForConcurrentOptimization()))) { | |
1667 function->ReplaceCode(fallback); | |
1668 } | |
1669 if (kind == Code::OPTIMIZED_FUNCTION) { | |
1670 // Optimized code can only get here if DeoptimizeAll did not | |
1671 // deoptimize turbo fan code. | |
1672 DCHECK(!FLAG_turbo_asm_deoptimization); | |
1673 DCHECK(function->shared()->asm_function()); | |
1674 DCHECK(function->code()->is_turbofanned()); | |
1675 function->ReplaceCode(fallback); | |
1676 } | |
1677 } else if (obj->IsJSGeneratorObject()) { | |
1678 JSGeneratorObject* gen = JSGeneratorObject::cast(obj); | |
1679 if (!gen->is_suspended()) continue; | |
1680 | |
1681 JSFunction* fun = gen->function(); | |
1682 DCHECK_EQ(fun->code()->kind(), Code::FUNCTION); | |
1683 if (fun->code()->has_debug_break_slots()) continue; | |
1684 | |
1685 int pc_offset = gen->continuation(); | |
1686 DCHECK_LT(0, pc_offset); | |
1687 | |
1688 int index = | |
1689 ComputeContinuationIndexFromPcOffset(fun->code(), pc_offset); | |
1690 | |
1691 // This will be fixed after we recompile the functions. | |
1692 gen->set_continuation(index); | |
1693 | |
1694 suspended_generators.Add(Handle<JSGeneratorObject>(gen, isolate_)); | |
1695 } else if (obj->IsSharedFunctionInfo()) { | |
1696 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); | |
1697 if (SkipSharedFunctionInfo(shared, active_code_marker)) continue; | |
1698 if (shared->is_generator()) continue; | |
1699 if (HasDebugBreakSlots(shared->code())) continue; | |
1700 shared->ReplaceCode(*lazy_compile); | |
1701 } | |
1702 } | |
1703 | |
1704 // Clear gc_metadata field. | |
1705 for (int i = 0; i < active_functions.length(); i++) { | |
1706 Handle<JSFunction> function = active_functions[i]; | |
1707 function->shared()->code()->set_gc_metadata(Smi::FromInt(0)); | |
1708 } | |
1709 } | |
1710 | |
1711 // Recompile generator functions that have suspended activations, and | |
1712 // relocate those activations. | |
1713 RecompileAndRelocateSuspendedGenerators(suspended_generators); | |
1714 | |
1715 // Mark generator functions that didn't have suspended activations for lazy | |
1716 // recompilation. Note that this set does not include any active functions. | |
1717 for (int i = 0; i < generator_functions.length(); i++) { | |
1718 Handle<JSFunction> &function = generator_functions[i]; | |
1719 if (function->code()->kind() != Code::FUNCTION) continue; | |
1720 if (function->code()->has_debug_break_slots()) continue; | |
1721 function->ReplaceCode(*lazy_compile); | |
1722 function->shared()->ReplaceCode(*lazy_compile); | |
1723 } | |
1724 | |
1725 // Now recompile all functions with activation frames and and | |
1726 // patch the return address to run in the new compiled code. It could be | |
1727 // that some active functions were recompiled already by the suspended | |
1728 // generator recompilation pass above; a generator with suspended | |
1729 // activations could also have active activations. That's fine. | |
1730 for (int i = 0; i < active_functions.length(); i++) { | |
1731 Handle<JSFunction> function = active_functions[i]; | |
1732 Handle<SharedFunctionInfo> shared(function->shared()); | |
1733 if (!shared->allows_lazy_compilation()) { | |
1734 // Ignore functions that cannot be recompiled. Fortunately, those are | |
1735 // only ones that are not subject to debugging in the first place. | |
1736 DCHECK(!function->IsSubjectToDebugging()); | |
1737 continue; | |
1738 } | |
1739 if (shared->code()->kind() == Code::BUILTIN) continue; | |
1740 | |
1741 EnsureFunctionHasDebugBreakSlots(function); | |
1742 } | |
1743 | |
1744 RedirectActivationsToRecompiledCodeOnThread(isolate_, | |
1745 isolate_->thread_local_top()); | |
1746 | |
1747 ActiveFunctionsRedirector active_functions_redirector; | |
1748 isolate_->thread_manager()->IterateArchivedThreads( | |
1749 &active_functions_redirector); | |
1750 } | |
1751 } | |
1752 | |
1753 | |
1754 class SharedFunctionInfoFinder { | 1514 class SharedFunctionInfoFinder { |
1755 public: | 1515 public: |
1756 explicit SharedFunctionInfoFinder(int target_position) | 1516 explicit SharedFunctionInfoFinder(int target_position) |
1757 : current_candidate_(NULL), | 1517 : current_candidate_(NULL), |
1758 current_candidate_closure_(NULL), | 1518 current_candidate_closure_(NULL), |
1759 current_start_position_(RelocInfo::kNoPosition), | 1519 current_start_position_(RelocInfo::kNoPosition), |
1760 target_position_(target_position) {} | 1520 target_position_(target_position) {} |
1761 | 1521 |
1762 void NewCandidate(SharedFunctionInfo* shared, JSFunction* closure = NULL) { | 1522 void NewCandidate(SharedFunctionInfo* shared, JSFunction* closure = NULL) { |
1763 int start_position = shared->function_token_position(); | 1523 int start_position = shared->function_token_position(); |
(...skipping 28 matching lines...) Expand all Loading... |
1792 | 1552 |
1793 private: | 1553 private: |
1794 SharedFunctionInfo* current_candidate_; | 1554 SharedFunctionInfo* current_candidate_; |
1795 JSFunction* current_candidate_closure_; | 1555 JSFunction* current_candidate_closure_; |
1796 int current_start_position_; | 1556 int current_start_position_; |
1797 int target_position_; | 1557 int target_position_; |
1798 DisallowHeapAllocation no_gc_; | 1558 DisallowHeapAllocation no_gc_; |
1799 }; | 1559 }; |
1800 | 1560 |
1801 | 1561 |
1802 template <typename C> | 1562 // We need to find a SFI for a literal that may not yet have been compiled yet, |
1803 bool Debug::CompileToRevealInnerFunctions(C* compilable) { | 1563 // and there may not be a JSFunction referencing it. Find the SFI closest to |
1804 HandleScope scope(isolate_); | 1564 // the given position, compile it to reveal possible inner SFIs and repeat. |
1805 // Force compiling inner functions that require context. | 1565 // While we are at this, also ensure code with debug break slots so that we do |
1806 // TODO(yangguo): remove this hack. | 1566 // not have to compile a SFI without JSFunction, which is paifu for those that |
1807 bool has_break_points = has_break_points_; | 1567 // cannot be compiled without context (need to find outer compilable SFI etc.) |
1808 has_break_points_ = true; | |
1809 Handle<C> compilable_handle(compilable); | |
1810 bool result = !Compiler::GetUnoptimizedCode(compilable_handle).is_null(); | |
1811 has_break_points_ = has_break_points; | |
1812 return result; | |
1813 } | |
1814 | |
1815 | |
1816 Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script, | 1568 Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script, |
1817 int position) { | 1569 int position) { |
1818 while (true) { | 1570 while (true) { |
1819 // Go through all shared function infos associated with this script to | 1571 // Go through all shared function infos associated with this script to |
1820 // find the inner most function containing this position. | 1572 // find the inner most function containing this position. |
1821 if (!script->shared_function_infos()->IsWeakFixedArray()) break; | 1573 if (!script->shared_function_infos()->IsWeakFixedArray()) break; |
1822 WeakFixedArray* array = | 1574 WeakFixedArray* array = |
1823 WeakFixedArray::cast(script->shared_function_infos()); | 1575 WeakFixedArray::cast(script->shared_function_infos()); |
1824 | 1576 |
1825 SharedFunctionInfo* shared; | 1577 SharedFunctionInfo* shared; |
1826 { | 1578 { |
1827 SharedFunctionInfoFinder finder(position); | 1579 SharedFunctionInfoFinder finder(position); |
1828 for (int i = 0; i < array->Length(); i++) { | 1580 for (int i = 0; i < array->Length(); i++) { |
1829 Object* item = array->Get(i); | 1581 Object* item = array->Get(i); |
1830 if (!item->IsSharedFunctionInfo()) continue; | 1582 if (!item->IsSharedFunctionInfo()) continue; |
1831 finder.NewCandidate(SharedFunctionInfo::cast(item)); | 1583 finder.NewCandidate(SharedFunctionInfo::cast(item)); |
1832 } | 1584 } |
1833 shared = finder.Result(); | 1585 shared = finder.Result(); |
1834 if (shared == NULL) break; | 1586 if (shared == NULL) break; |
1835 // We found it if it's already compiled. | 1587 // We found it if it's already compiled and has debug code. |
1836 if (shared->is_compiled()) return handle(shared); | 1588 if (shared->HasDebugCode()) return handle(shared); |
1837 } | 1589 } |
1838 // If not, compile to reveal inner functions, if possible. | 1590 // If not, compile to reveal inner functions, if possible. |
1839 if (shared->allows_lazy_compilation_without_context()) { | 1591 if (shared->allows_lazy_compilation_without_context()) { |
1840 if (!CompileToRevealInnerFunctions(shared)) break; | 1592 HandleScope scope(isolate_); |
| 1593 if (Compiler::GetDebugCode(handle(shared)).is_null()) break; |
1841 continue; | 1594 continue; |
1842 } | 1595 } |
1843 | 1596 |
1844 // If not possible, comb the heap for the best suitable compile target. | 1597 // If not possible, comb the heap for the best suitable compile target. |
1845 JSFunction* closure; | 1598 JSFunction* closure; |
1846 { | 1599 { |
1847 HeapIterator it(isolate_->heap(), HeapIterator::kNoFiltering); | 1600 HeapIterator it(isolate_->heap()); |
1848 SharedFunctionInfoFinder finder(position); | 1601 SharedFunctionInfoFinder finder(position); |
1849 while (HeapObject* object = it.next()) { | 1602 while (HeapObject* object = it.next()) { |
1850 JSFunction* candidate_closure = NULL; | 1603 JSFunction* candidate_closure = NULL; |
1851 SharedFunctionInfo* candidate = NULL; | 1604 SharedFunctionInfo* candidate = NULL; |
1852 if (object->IsJSFunction()) { | 1605 if (object->IsJSFunction()) { |
1853 candidate_closure = JSFunction::cast(object); | 1606 candidate_closure = JSFunction::cast(object); |
1854 candidate = candidate_closure->shared(); | 1607 candidate = candidate_closure->shared(); |
1855 } else if (object->IsSharedFunctionInfo()) { | 1608 } else if (object->IsSharedFunctionInfo()) { |
1856 candidate = SharedFunctionInfo::cast(object); | 1609 candidate = SharedFunctionInfo::cast(object); |
1857 if (!candidate->allows_lazy_compilation_without_context()) continue; | 1610 if (!candidate->allows_lazy_compilation_without_context()) continue; |
1858 } else { | 1611 } else { |
1859 continue; | 1612 continue; |
1860 } | 1613 } |
1861 if (candidate->script() == *script) { | 1614 if (candidate->script() == *script) { |
1862 finder.NewCandidate(candidate, candidate_closure); | 1615 finder.NewCandidate(candidate, candidate_closure); |
1863 } | 1616 } |
1864 } | 1617 } |
1865 closure = finder.ResultClosure(); | 1618 closure = finder.ResultClosure(); |
1866 shared = finder.Result(); | 1619 shared = finder.Result(); |
1867 } | 1620 } |
1868 if (closure == NULL ? !CompileToRevealInnerFunctions(shared) | 1621 HandleScope scope(isolate_); |
1869 : !CompileToRevealInnerFunctions(closure)) { | 1622 if (closure == NULL) { |
1870 break; | 1623 if (Compiler::GetDebugCode(handle(shared)).is_null()) break; |
| 1624 } else { |
| 1625 if (Compiler::GetDebugCode(handle(closure)).is_null()) break; |
1871 } | 1626 } |
1872 } | 1627 } |
1873 return isolate_->factory()->undefined_value(); | 1628 return isolate_->factory()->undefined_value(); |
1874 } | 1629 } |
1875 | 1630 |
1876 | 1631 |
1877 // Ensures the debug information is present for shared. | 1632 // Ensures the debug information is present for shared. |
1878 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared, | 1633 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared, |
1879 Handle<JSFunction> function) { | 1634 Handle<JSFunction> function) { |
1880 if (!shared->IsSubjectToDebugging()) return false; | 1635 if (!shared->IsSubjectToDebugging()) return false; |
1881 | 1636 |
1882 // Return if we already have the debug info for shared. | 1637 // Return if we already have the debug info for shared. |
1883 if (HasDebugInfo(shared)) { | 1638 if (shared->HasDebugInfo()) return true; |
1884 DCHECK(shared->is_compiled()); | |
1885 DCHECK(shared->code()->has_debug_break_slots()); | |
1886 return true; | |
1887 } | |
1888 | |
1889 // There will be at least one break point when we are done. | |
1890 has_break_points_ = true; | |
1891 | 1639 |
1892 if (function.is_null()) { | 1640 if (function.is_null()) { |
1893 DCHECK(shared->is_compiled()); | 1641 DCHECK(shared->HasDebugCode()); |
1894 DCHECK(shared->code()->has_debug_break_slots()); | |
1895 } else if (!Compiler::EnsureCompiled(function, CLEAR_EXCEPTION)) { | 1642 } else if (!Compiler::EnsureCompiled(function, CLEAR_EXCEPTION)) { |
1896 return false; | 1643 return false; |
1897 } | 1644 } |
1898 | 1645 |
| 1646 if (!PrepareFunctionForBreakPoints(shared)) return false; |
| 1647 |
1899 // Make sure IC state is clean. This is so that we correctly flood | 1648 // Make sure IC state is clean. This is so that we correctly flood |
1900 // accessor pairs when stepping in. | 1649 // accessor pairs when stepping in. |
1901 shared->code()->ClearInlineCaches(); | 1650 shared->code()->ClearInlineCaches(); |
1902 shared->feedback_vector()->ClearICSlots(*shared); | 1651 shared->feedback_vector()->ClearICSlots(*shared); |
1903 | 1652 |
1904 // Create the debug info object. | 1653 // Create the debug info object. |
1905 DCHECK(shared->is_compiled()); | 1654 DCHECK(shared->HasDebugCode()); |
1906 DCHECK(shared->code()->has_debug_break_slots()); | |
1907 Handle<DebugInfo> debug_info = isolate_->factory()->NewDebugInfo(shared); | 1655 Handle<DebugInfo> debug_info = isolate_->factory()->NewDebugInfo(shared); |
1908 | 1656 |
1909 // Add debug info to the list. | 1657 // Add debug info to the list. |
1910 DebugInfoListNode* node = new DebugInfoListNode(*debug_info); | 1658 DebugInfoListNode* node = new DebugInfoListNode(*debug_info); |
1911 node->set_next(debug_info_list_); | 1659 node->set_next(debug_info_list_); |
1912 debug_info_list_ = node; | 1660 debug_info_list_ = node; |
1913 | 1661 |
1914 return true; | 1662 return true; |
1915 } | 1663 } |
1916 | 1664 |
1917 | 1665 |
1918 void Debug::RemoveDebugInfo(DebugInfoListNode* prev, DebugInfoListNode* node) { | 1666 void Debug::RemoveDebugInfo(DebugInfoListNode* prev, DebugInfoListNode* node) { |
1919 // Unlink from list. If prev is NULL we are looking at the first element. | 1667 // Unlink from list. If prev is NULL we are looking at the first element. |
1920 if (prev == NULL) { | 1668 if (prev == NULL) { |
1921 debug_info_list_ = node->next(); | 1669 debug_info_list_ = node->next(); |
1922 } else { | 1670 } else { |
1923 prev->set_next(node->next()); | 1671 prev->set_next(node->next()); |
1924 } | 1672 } |
1925 delete node; | 1673 delete node; |
1926 | |
1927 // If there are no more debug info objects there are not more break | |
1928 // points. | |
1929 has_break_points_ = debug_info_list_ != NULL; | |
1930 } | 1674 } |
1931 | 1675 |
1932 | 1676 |
1933 void Debug::RemoveDebugInfo(DebugInfo** debug_info) { | 1677 void Debug::RemoveDebugInfo(DebugInfo** debug_info) { |
1934 DCHECK(debug_info_list_ != NULL); | 1678 DCHECK(debug_info_list_ != NULL); |
1935 // Run through the debug info objects to find this one and remove it. | 1679 // Run through the debug info objects to find this one and remove it. |
1936 DebugInfoListNode* prev = NULL; | 1680 DebugInfoListNode* prev = NULL; |
1937 DebugInfoListNode* current = debug_info_list_; | 1681 DebugInfoListNode* current = debug_info_list_; |
1938 while (current != NULL) { | 1682 while (current != NULL) { |
1939 if (current->debug_info().location() == debug_info) { | 1683 if (current->debug_info().location() == debug_info) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1982 if (LiveEdit::SetAfterBreakTarget(this)) return; // LiveEdit did the job. | 1726 if (LiveEdit::SetAfterBreakTarget(this)) return; // LiveEdit did the job. |
1983 | 1727 |
1984 // Continue just after the slot. | 1728 // Continue just after the slot. |
1985 after_break_target_ = frame->pc(); | 1729 after_break_target_ = frame->pc(); |
1986 } | 1730 } |
1987 | 1731 |
1988 | 1732 |
1989 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { | 1733 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { |
1990 HandleScope scope(isolate_); | 1734 HandleScope scope(isolate_); |
1991 | 1735 |
1992 // If there are no break points this cannot be break at return, as | |
1993 // the debugger statement and stack guard debug break cannot be at | |
1994 // return. | |
1995 if (!has_break_points_) return false; | |
1996 | |
1997 PrepareForBreakPoints(); | |
1998 | |
1999 // Get the executing function in which the debug break occurred. | 1736 // Get the executing function in which the debug break occurred. |
2000 Handle<JSFunction> function(JSFunction::cast(frame->function())); | 1737 Handle<JSFunction> function(JSFunction::cast(frame->function())); |
2001 Handle<SharedFunctionInfo> shared(function->shared()); | 1738 Handle<SharedFunctionInfo> shared(function->shared()); |
2002 if (!EnsureDebugInfo(shared, function)) { | 1739 |
2003 // Return if we failed to retrieve the debug info. | 1740 // With no debug info there are no break points, so we can't be at a return. |
2004 return false; | 1741 if (!shared->HasDebugInfo()) return false; |
2005 } | 1742 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
2006 Handle<DebugInfo> debug_info = GetDebugInfo(shared); | |
2007 Handle<Code> code(debug_info->code()); | 1743 Handle<Code> code(debug_info->code()); |
2008 #ifdef DEBUG | 1744 #ifdef DEBUG |
2009 // Get the code which is actually executing. | 1745 // Get the code which is actually executing. |
2010 Handle<Code> frame_code(frame->LookupCode()); | 1746 Handle<Code> frame_code(frame->LookupCode()); |
2011 DCHECK(frame_code.is_identical_to(code)); | 1747 DCHECK(frame_code.is_identical_to(code)); |
2012 #endif | 1748 #endif |
2013 | 1749 |
2014 // Find the reloc info matching the start of the debug break slot. | 1750 // Find the reloc info matching the start of the debug break slot. |
2015 Address slot_pc = frame->pc() - Assembler::kDebugBreakSlotLength; | 1751 Address slot_pc = frame->pc() - Assembler::kDebugBreakSlotLength; |
2016 int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN); | 1752 int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN); |
2017 for (RelocIterator it(debug_info->code(), mask); !it.done(); it.next()) { | 1753 for (RelocIterator it(*code, mask); !it.done(); it.next()) { |
2018 if (it.rinfo()->pc() == slot_pc) return true; | 1754 if (it.rinfo()->pc() == slot_pc) return true; |
2019 } | 1755 } |
2020 return false; | 1756 return false; |
2021 } | 1757 } |
2022 | 1758 |
2023 | 1759 |
2024 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, | 1760 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, |
2025 LiveEdit::FrameDropMode mode, | 1761 LiveEdit::FrameDropMode mode, |
2026 Object** restarter_frame_function_pointer) { | 1762 Object** restarter_frame_function_pointer) { |
2027 if (mode != LiveEdit::CURRENTLY_SET_MODE) { | 1763 if (mode != LiveEdit::CURRENTLY_SET_MODE) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2061 // Perform GC to get unreferenced scripts evicted from the cache before | 1797 // Perform GC to get unreferenced scripts evicted from the cache before |
2062 // returning the content. | 1798 // returning the content. |
2063 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 1799 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
2064 "Debug::GetLoadedScripts"); | 1800 "Debug::GetLoadedScripts"); |
2065 | 1801 |
2066 // Get the scripts from the cache. | 1802 // Get the scripts from the cache. |
2067 return script_cache_->GetScripts(); | 1803 return script_cache_->GetScripts(); |
2068 } | 1804 } |
2069 | 1805 |
2070 | 1806 |
| 1807 void Debug::GetStepinPositions(JavaScriptFrame* frame, StackFrame::Id frame_id, |
| 1808 List<int>* results_out) { |
| 1809 FrameSummary summary = GetFirstFrameSummary(frame); |
| 1810 |
| 1811 Handle<JSFunction> fun = Handle<JSFunction>(summary.function()); |
| 1812 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>(fun->shared()); |
| 1813 |
| 1814 if (!EnsureDebugInfo(shared, fun)) return; |
| 1815 |
| 1816 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
| 1817 // Refresh frame summary if the code has been recompiled for debugging. |
| 1818 if (shared->code() != *summary.code()) summary = GetFirstFrameSummary(frame); |
| 1819 |
| 1820 // Find range of break points starting from the break point where execution |
| 1821 // has stopped. |
| 1822 Address call_pc = summary.pc() - 1; |
| 1823 List<BreakLocation> locations; |
| 1824 BreakLocation::FromAddressSameStatement(debug_info, ALL_BREAK_LOCATIONS, |
| 1825 call_pc, &locations); |
| 1826 |
| 1827 for (BreakLocation location : locations) { |
| 1828 if (location.pc() <= summary.pc()) { |
| 1829 // The break point is near our pc. Could be a step-in possibility, |
| 1830 // that is currently taken by active debugger call. |
| 1831 if (break_frame_id() == StackFrame::NO_ID) { |
| 1832 continue; // We are not stepping. |
| 1833 } else { |
| 1834 JavaScriptFrameIterator frame_it(isolate_, break_frame_id()); |
| 1835 // If our frame is a top frame and we are stepping, we can do step-in |
| 1836 // at this place. |
| 1837 if (frame_it.frame()->id() != frame_id) continue; |
| 1838 } |
| 1839 } |
| 1840 if (location.IsStepInLocation()) results_out->Add(location.position()); |
| 1841 } |
| 1842 } |
| 1843 |
| 1844 |
2071 void Debug::RecordEvalCaller(Handle<Script> script) { | 1845 void Debug::RecordEvalCaller(Handle<Script> script) { |
2072 script->set_compilation_type(Script::COMPILATION_TYPE_EVAL); | 1846 script->set_compilation_type(Script::COMPILATION_TYPE_EVAL); |
2073 // For eval scripts add information on the function from which eval was | 1847 // For eval scripts add information on the function from which eval was |
2074 // called. | 1848 // called. |
2075 StackTraceFrameIterator it(script->GetIsolate()); | 1849 StackTraceFrameIterator it(script->GetIsolate()); |
2076 if (!it.done()) { | 1850 if (!it.done()) { |
2077 script->set_eval_from_shared(it.frame()->function()->shared()); | 1851 script->set_eval_from_shared(it.frame()->function()->shared()); |
2078 Code* code = it.frame()->LookupCode(); | 1852 Code* code = it.frame()->LookupCode(); |
2079 int offset = static_cast<int>( | 1853 int offset = static_cast<int>( |
2080 it.frame()->pc() - code->instruction_start()); | 1854 it.frame()->pc() - code->instruction_start()); |
(...skipping 979 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3060 } | 2834 } |
3061 | 2835 |
3062 | 2836 |
3063 void LockingCommandMessageQueue::Clear() { | 2837 void LockingCommandMessageQueue::Clear() { |
3064 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2838 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
3065 queue_.Clear(); | 2839 queue_.Clear(); |
3066 } | 2840 } |
3067 | 2841 |
3068 } // namespace internal | 2842 } // namespace internal |
3069 } // namespace v8 | 2843 } // namespace v8 |
OLD | NEW |