Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/debug.cc

Issue 1233073005: Debugger: prepare code for debugging on a per-function basis. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: addressed comments. Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/debug.h ('k') | src/heap/mark-compact.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/debug.h ('k') | src/heap/mark-compact.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698