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

Side by Side Diff: runtime/vm/debugger.cc

Issue 15000005: Allow breakpoints on one-liner functions (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/debugger.h ('k') | tests/standalone/debugger/basic_debugger_test.dart » ('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 (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/debugger.h" 5 #include "vm/debugger.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 8
9 #include "vm/code_generator.h" 9 #include "vm/code_generator.h"
10 #include "vm/code_patcher.h" 10 #include "vm/code_patcher.h"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 const Function& func, 51 const Function& func,
52 intptr_t token_pos) 52 intptr_t token_pos)
53 : id_(id), 53 : id_(id),
54 function_(func.raw()), 54 function_(func.raw()),
55 token_pos_(token_pos), 55 token_pos_(token_pos),
56 line_number_(-1), 56 line_number_(-1),
57 is_enabled_(false), 57 is_enabled_(false),
58 next_(NULL) { 58 next_(NULL) {
59 ASSERT(!func.IsNull()); 59 ASSERT(!func.IsNull());
60 ASSERT((func.token_pos() <= token_pos_) && 60 ASSERT((func.token_pos() <= token_pos_) &&
61 (token_pos_ < func.end_token_pos())); 61 (token_pos_ <= func.end_token_pos()));
62 } 62 }
63 63
64 64
65 void SourceBreakpoint::Enable() { 65 void SourceBreakpoint::Enable() {
66 is_enabled_ = true; 66 is_enabled_ = true;
67 Isolate::Current()->debugger()->SyncBreakpoint(this); 67 Isolate::Current()->debugger()->SyncBreakpoint(this);
68 } 68 }
69 69
70 70
71 void SourceBreakpoint::Disable() { 71 void SourceBreakpoint::Disable() {
(...skipping 781 matching lines...) Expand 10 before | Expand all | Expand 10 after
853 ASSERT(!function.IsNull()); 853 ASSERT(!function.IsNull());
854 if (function.HasOptimizedCode()) { 854 if (function.HasOptimizedCode()) {
855 function.SwitchToUnoptimizedCode(); 855 function.SwitchToUnoptimizedCode();
856 } 856 }
857 } 857 }
858 } 858 }
859 } 859 }
860 } 860 }
861 861
862 862
863 static bool IsSafePoint(PcDescriptors::Kind kind) {
864 return ((kind == PcDescriptors::kIcCall) ||
865 (kind == PcDescriptors::kFuncCall) ||
866 (kind == PcDescriptors::kClosureCall) ||
867 (kind == PcDescriptors::kReturn));
868 }
869
870
863 void Debugger::InstrumentForStepping(const Function& target_function) { 871 void Debugger::InstrumentForStepping(const Function& target_function) {
864 if (!target_function.HasCode()) { 872 if (!target_function.HasCode()) {
865 Compiler::CompileFunction(target_function); 873 Compiler::CompileFunction(target_function);
866 // If there were any errors, ignore them silently and return without 874 // If there were any errors, ignore them silently and return without
867 // adding breakpoints to target. 875 // adding breakpoints to target.
868 if (!target_function.HasCode()) { 876 if (!target_function.HasCode()) {
869 return; 877 return;
870 } 878 }
871 } 879 }
872 DeoptimizeWorld(); 880 DeoptimizeWorld();
873 ASSERT(!target_function.HasOptimizedCode()); 881 ASSERT(!target_function.HasOptimizedCode());
874 Code& code = Code::Handle(target_function.unoptimized_code()); 882 Code& code = Code::Handle(target_function.unoptimized_code());
875 ASSERT(!code.IsNull()); 883 ASSERT(!code.IsNull());
876 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); 884 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
877 for (int i = 0; i < desc.Length(); i++) { 885 for (int i = 0; i < desc.Length(); i++) {
878 CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(i)); 886 CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(i));
879 if (bpt != NULL) { 887 if (bpt != NULL) {
880 // There is already a breakpoint for this address. Make sure 888 // There is already a breakpoint for this address. Make sure
881 // it is enabled. 889 // it is enabled.
882 bpt->Enable(); 890 bpt->Enable();
883 continue; 891 continue;
884 } 892 }
885 PcDescriptors::Kind kind = desc.DescriptorKind(i); 893 if (IsSafePoint(desc.DescriptorKind(i))) {
886 if ((kind == PcDescriptors::kIcCall) ||
887 (kind == PcDescriptors::kFuncCall) ||
888 (kind == PcDescriptors::kClosureCall) ||
889 (kind == PcDescriptors::kReturn)) {
890 bpt = new CodeBreakpoint(target_function, i); 894 bpt = new CodeBreakpoint(target_function, i);
891 RegisterCodeBreakpoint(bpt); 895 RegisterCodeBreakpoint(bpt);
892 bpt->Enable(); 896 bpt->Enable();
893 } 897 }
894 } 898 }
895 } 899 }
896 900
897 901
898 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { 902 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) {
899 if (event_handler_ != NULL) { 903 if (event_handler_ != NULL) {
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
1021 DebuggerEvent event; 1025 DebuggerEvent event;
1022 event.type = kExceptionThrown; 1026 event.type = kExceptionThrown;
1023 event.exception = &exc; 1027 event.exception = &exc;
1024 ASSERT(event_handler_ != NULL); 1028 ASSERT(event_handler_ != NULL);
1025 (*event_handler_)(&event); 1029 (*event_handler_)(&event);
1026 stack_trace_ = NULL; 1030 stack_trace_ = NULL;
1027 obj_cache_ = NULL; // Remote object cache is zone allocated. 1031 obj_cache_ = NULL; // Remote object cache is zone allocated.
1028 } 1032 }
1029 1033
1030 1034
1031 CodeBreakpoint* Debugger::MakeCodeBreakpoint(const Function& func, 1035 // Given a function and a token position range, return the best fit
1032 intptr_t first_token_pos, 1036 // token position to set a breakpoint.
1033 intptr_t last_token_pos) { 1037 // If multiple possible breakpoint positions are within the given range,
1038 // the one with the lowest machine code address is picked.
1039 // If no possible breakpoint location exists in the given range, the closest
1040 // token position after the range is returned.
1041 intptr_t Debugger::ResolveBreakpointPos(const Function& func,
1042 intptr_t first_token_pos,
1043 intptr_t last_token_pos) {
1034 ASSERT(func.HasCode()); 1044 ASSERT(func.HasCode());
1035 ASSERT(!func.HasOptimizedCode()); 1045 ASSERT(!func.HasOptimizedCode());
1036 Code& code = Code::Handle(func.unoptimized_code()); 1046 Code& code = Code::Handle(func.unoptimized_code());
1037 ASSERT(!code.IsNull()); 1047 ASSERT(!code.IsNull());
1038 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); 1048 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
1039 // We attempt to find the PC descriptor that is closest to the
1040 // beginning of the token range, in terms of native code address. If we
1041 // don't find a PC descriptor within the given range, we pick the
1042 // nearest one to the beginning of the range, in terms of token position.
1043 intptr_t best_fit_index = -1; 1049 intptr_t best_fit_index = -1;
1044 intptr_t best_fit = INT_MAX; 1050 intptr_t best_fit = INT_MAX;
1045 uword lowest_pc = kUwordMax; 1051 uword lowest_pc = kUwordMax;
1046 intptr_t lowest_pc_index = -1; 1052 intptr_t lowest_pc_index = -1;
1047 for (int i = 0; i < desc.Length(); i++) { 1053 for (int i = 0; i < desc.Length(); i++) {
1048 intptr_t desc_token_pos = desc.TokenPos(i); 1054 intptr_t desc_token_pos = desc.TokenPos(i);
1049 ASSERT(desc_token_pos >= 0); 1055 ASSERT(desc_token_pos >= 0);
1050 if (desc_token_pos < first_token_pos) { 1056 if (desc_token_pos < first_token_pos) {
1057 // This descriptor is before the given range.
1051 continue; 1058 continue;
1052 } 1059 }
1053 PcDescriptors::Kind kind = desc.DescriptorKind(i); 1060 if (IsSafePoint(desc.DescriptorKind(i))) {
1054 if ((kind == PcDescriptors::kIcCall) ||
1055 (kind == PcDescriptors::kFuncCall) ||
1056 (kind == PcDescriptors::kClosureCall) ||
1057 (kind == PcDescriptors::kReturn)) {
1058 if ((desc_token_pos - first_token_pos) < best_fit) { 1061 if ((desc_token_pos - first_token_pos) < best_fit) {
1062 // So far, this descriptor has the closest token position to the
1063 // beginning of the range.
1059 best_fit = desc_token_pos - first_token_pos; 1064 best_fit = desc_token_pos - first_token_pos;
1060 ASSERT(best_fit >= 0); 1065 ASSERT(best_fit >= 0);
1061 best_fit_index = i; 1066 best_fit_index = i;
1062 } 1067 }
1063 if ((first_token_pos <= desc_token_pos) && 1068 if ((first_token_pos <= desc_token_pos) &&
1064 (desc_token_pos <= last_token_pos) && 1069 (desc_token_pos <= last_token_pos) &&
1065 (desc.PC(i) < lowest_pc)) { 1070 (desc.PC(i) < lowest_pc)) {
1071 // This descriptor is within the token position range and so
1072 // far has the lowest code address.
1066 lowest_pc = desc.PC(i); 1073 lowest_pc = desc.PC(i);
1067 lowest_pc_index = i; 1074 lowest_pc_index = i;
1068 } 1075 }
1069 } 1076 }
1070 } 1077 }
1071 if (lowest_pc_index >= 0) { 1078 if (lowest_pc_index >= 0) {
1072 // We found the the pc descriptor within the given token range that 1079 // We found the the pc descriptor within the given token range that
1073 // has the lowest execution address. This is the first possible 1080 // has the lowest execution address. This is the first possible
1074 // breakpoint on the line. We use this instead of the nearest 1081 // breakpoint on the line. We use this instead of the nearest
1075 // PC descriptor measured in token index distance. 1082 // PC descriptor measured in token index distance.
1076 best_fit_index = lowest_pc_index; 1083 best_fit_index = lowest_pc_index;
1077 } 1084 }
1078 if (best_fit_index >= 0) { 1085 if (best_fit_index >= 0) {
1079 CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(best_fit_index)); 1086 return desc.TokenPos(best_fit_index);
1080 // We should only ever have one code breakpoint at the same address.
1081 if (bpt != NULL) {
1082 return bpt;
1083 }
1084
1085 bpt = new CodeBreakpoint(func, best_fit_index);
1086 if (FLAG_verbose_debug) {
1087 OS::Print("Setting breakpoint in function '%s' "
1088 "(%s:%"Pd") (Token %"Pd") (PC %#"Px")\n",
1089 String::Handle(func.name()).ToCString(),
1090 String::Handle(bpt->SourceUrl()).ToCString(),
1091 bpt->LineNumber(),
1092 bpt->token_pos(),
1093 bpt->pc());
1094 }
1095 RegisterCodeBreakpoint(bpt);
1096 return bpt;
1097 } 1087 }
1098 return NULL; 1088 return -1;
1099 } 1089 }
1100 1090
1101 1091
1092 void Debugger::MakeCodeBreakpointsAt(const Function& func,
1093 intptr_t token_pos,
1094 SourceBreakpoint* bpt) {
1095 ASSERT(!func.HasOptimizedCode());
1096 Code& code = Code::Handle(func.unoptimized_code());
1097 ASSERT(!code.IsNull());
1098 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
1099 for (int i = 0; i < desc.Length(); i++) {
1100 intptr_t desc_token_pos = desc.TokenPos(i);
1101 if ((desc_token_pos == token_pos) && IsSafePoint(desc.DescriptorKind(i))) {
1102 CodeBreakpoint* code_bpt = GetCodeBreakpoint(desc.PC(i));
1103 if (code_bpt == NULL) {
1104 // No code breakpoint for this code exists; create one.
1105 code_bpt = new CodeBreakpoint(func, i);
1106 RegisterCodeBreakpoint(code_bpt);
1107 }
1108 code_bpt->set_src_bpt(bpt);
1109 }
1110 }
1111 }
1112
1113
1102 SourceBreakpoint* Debugger::SetBreakpoint(const Function& target_function, 1114 SourceBreakpoint* Debugger::SetBreakpoint(const Function& target_function,
1103 intptr_t first_token_pos, 1115 intptr_t first_token_pos,
1104 intptr_t last_token_pos) { 1116 intptr_t last_token_pos) {
1105 if ((last_token_pos < target_function.token_pos()) || 1117 if ((last_token_pos < target_function.token_pos()) ||
1106 (target_function.end_token_pos() < first_token_pos)) { 1118 (target_function.end_token_pos() < first_token_pos)) {
1107 // The given token position is not within the target function. 1119 // The given token position is not within the target function.
1108 return NULL; 1120 return NULL;
1109 } 1121 }
1110 DeoptimizeWorld(); 1122 intptr_t breakpoint_pos = -1;
1111 ASSERT(!target_function.HasOptimizedCode()); 1123 Function& closure = Function::Handle(isolate_);
1112 1124 if (target_function.HasImplicitClosureFunction()) {
1113 CodeBreakpoint* cbpt = NULL; 1125 // There is a closurized version of this function.
1114 SourceBreakpoint* source_bpt = NULL; 1126 closure = target_function.ImplicitClosureFunction();
1127 }
1128 // Determine actual breakpoint location if the function or an
1129 // implicit closure of the function has been compiled already.
1115 if (target_function.HasCode()) { 1130 if (target_function.HasCode()) {
1116 cbpt = MakeCodeBreakpoint(target_function, first_token_pos, last_token_pos); 1131 DeoptimizeWorld();
1117 if (cbpt != NULL) { 1132 ASSERT(!target_function.HasOptimizedCode());
1118 if (cbpt->src_bpt() != NULL) { 1133 breakpoint_pos =
1119 // There is already a source breakpoint for the location. 1134 ResolveBreakpointPos(target_function, first_token_pos, last_token_pos);
1120 ASSERT(cbpt->src_bpt() == 1135 } else if (!closure.IsNull() && closure.HasCode()) {
1121 GetSourceBreakpoint(target_function, cbpt->token_pos())); 1136 DeoptimizeWorld();
1122 return cbpt->src_bpt(); 1137 ASSERT(!closure.HasOptimizedCode());
1138 breakpoint_pos =
1139 ResolveBreakpointPos(closure, first_token_pos, last_token_pos);
1140 } else {
1141 // This function has not been compiled yet. Set a pending
1142 // breakpoint to be resolved later.
1143 SourceBreakpoint* source_bpt =
1144 GetSourceBreakpoint(target_function, first_token_pos);
1145 if (source_bpt != NULL) {
1146 // A pending source breakpoint for this uncompiled location
1147 // already exists.
1148 if (FLAG_verbose_debug) {
1149 OS::Print("Pending breakpoint for uncompiled function"
1150 " '%s' at line %"Pd" already exists\n",
1151 target_function.ToFullyQualifiedCString(),
1152 source_bpt->LineNumber());
1123 } 1153 }
1124 // No source breakpoint exists yet that is associated with the code
1125 // breakpoint we found. (This is an internal breakpoint.) Adjust
1126 // the breakpoint location to the actual position where breakpoint
1127 // got set.
1128 first_token_pos = cbpt->token_pos();
1129 }
1130 } else {
1131 source_bpt = GetSourceBreakpoint(target_function, first_token_pos);
1132 if (source_bpt != NULL) {
1133 // A source breakpoint for this uncompiled location already
1134 // exists.
1135 return source_bpt; 1154 return source_bpt;
1136 } 1155 }
1137 } 1156 source_bpt =
1138 source_bpt = new SourceBreakpoint(nextId(), target_function, first_token_pos); 1157 new SourceBreakpoint(nextId(), target_function, first_token_pos);
1139 RegisterSourceBreakpoint(source_bpt); 1158 RegisterSourceBreakpoint(source_bpt);
1140 if (FLAG_verbose_debug && !target_function.HasCode()) {
1141 OS::Print("Registering breakpoint for "
1142 "uncompiled function '%s' at line %"Pd"\n",
1143 target_function.ToFullyQualifiedCString(),
1144 source_bpt->LineNumber());
1145 }
1146
1147 if (cbpt != NULL) {
1148 ASSERT(cbpt->src_bpt() == NULL);
1149 cbpt->set_src_bpt(source_bpt);
1150 SignalBpResolved(source_bpt);
1151 } else {
1152 if (FLAG_verbose_debug) { 1159 if (FLAG_verbose_debug) {
1153 OS::Print("Failed to set breakpoint at '%s' line %"Pd"\n", 1160 OS::Print("Registering pending breakpoint for "
1154 String::Handle(source_bpt->SourceUrl()).ToCString(), 1161 "uncompiled function '%s' at line %"Pd"\n",
1162 target_function.ToFullyQualifiedCString(),
1155 source_bpt->LineNumber()); 1163 source_bpt->LineNumber());
1156 } 1164 }
1165 source_bpt->Enable();
1166 return source_bpt;
1157 } 1167 }
1158 1168 ASSERT(breakpoint_pos != -1);
1159 if (target_function.HasImplicitClosureFunction()) { 1169 SourceBreakpoint* source_bpt =
1160 // There is a closurized version of this function. If the closure 1170 GetSourceBreakpoint(target_function, breakpoint_pos);
1161 // is already compiled, we need to set a code breakpoint in its 1171 if (source_bpt != NULL) {
1162 // code. 1172 // A source breakpoint for this location already exists.
1163 const Function& closure = 1173 return source_bpt;
1164 Function::Handle(target_function.ImplicitClosureFunction()); 1174 }
1165 if (closure.HasCode()) { 1175 source_bpt = new SourceBreakpoint(nextId(), target_function, breakpoint_pos);
1166 ASSERT(!closure.HasOptimizedCode()); 1176 RegisterSourceBreakpoint(source_bpt);
1167 CodeBreakpoint* closure_bpt = 1177 if (target_function.HasCode()) {
1168 MakeCodeBreakpoint(closure, first_token_pos, last_token_pos); 1178 MakeCodeBreakpointsAt(target_function, breakpoint_pos, source_bpt);
1169 if ((closure_bpt != NULL) && (closure_bpt->src_bpt() == NULL)) { 1179 }
1170 closure_bpt->set_src_bpt(source_bpt); 1180 if (!closure.IsNull() && closure.HasCode()) {
1171 } 1181 MakeCodeBreakpointsAt(closure, breakpoint_pos, source_bpt);
1172 }
1173 } 1182 }
1174 source_bpt->Enable(); 1183 source_bpt->Enable();
1175 return source_bpt; 1184 return source_bpt;
1176 } 1185 }
1177 1186
1178 1187
1179 // Synchronize the enabled/disabled state of all code breakpoints 1188 // Synchronize the enabled/disabled state of all code breakpoints
1180 // associated with the source breakpoint bpt. 1189 // associated with the source breakpoint bpt.
1181 void Debugger::SyncBreakpoint(SourceBreakpoint* bpt) { 1190 void Debugger::SyncBreakpoint(SourceBreakpoint* bpt) {
1182 CodeBreakpoint* cbpt = code_breakpoints_; 1191 CodeBreakpoint* cbpt = code_breakpoints_;
(...skipping 19 matching lines...) Expand all
1202 const Function& target_function) { 1211 const Function& target_function) {
1203 ASSERT(!target_function.IsNull()); 1212 ASSERT(!target_function.IsNull());
1204 return SetBreakpoint(target_function, 1213 return SetBreakpoint(target_function,
1205 target_function.token_pos(), 1214 target_function.token_pos(),
1206 target_function.end_token_pos()); 1215 target_function.end_token_pos());
1207 } 1216 }
1208 1217
1209 1218
1210 SourceBreakpoint* Debugger::SetBreakpointAtLine(const String& script_url, 1219 SourceBreakpoint* Debugger::SetBreakpointAtLine(const String& script_url,
1211 intptr_t line_number) { 1220 intptr_t line_number) {
1212 Library& lib = Library::Handle(); 1221 Library& lib = Library::Handle(isolate_);
1213 Script& script = Script::Handle(); 1222 Script& script = Script::Handle(isolate_);
1214 const GrowableObjectArray& libs = 1223 const GrowableObjectArray& libs =
1215 GrowableObjectArray::Handle(isolate_->object_store()->libraries()); 1224 GrowableObjectArray::Handle(isolate_->object_store()->libraries());
1216 for (int i = 0; i < libs.Length(); i++) { 1225 for (int i = 0; i < libs.Length(); i++) {
1217 lib ^= libs.At(i); 1226 lib ^= libs.At(i);
1218 script = lib.LookupScript(script_url); 1227 script = lib.LookupScript(script_url);
1219 if (!script.IsNull()) { 1228 if (!script.IsNull()) {
1220 break; 1229 break;
1221 } 1230 }
1222 } 1231 }
1223 if (script.IsNull()) { 1232 if (script.IsNull()) {
1224 if (FLAG_verbose_debug) { 1233 if (FLAG_verbose_debug) {
1225 OS::Print("Failed to find script with url '%s'\n", 1234 OS::Print("Failed to find script with url '%s'\n",
1226 script_url.ToCString()); 1235 script_url.ToCString());
1227 } 1236 }
1228 return NULL; 1237 return NULL;
1229 } 1238 }
1230 intptr_t first_token_idx, last_token_idx; 1239 intptr_t first_token_idx, last_token_idx;
1231 script.TokenRangeAtLine(line_number, &first_token_idx, &last_token_idx); 1240 script.TokenRangeAtLine(line_number, &first_token_idx, &last_token_idx);
1232 if (first_token_idx < 0) { 1241 if (first_token_idx < 0) {
1233 // Script does not contain the given line number. 1242 // Script does not contain the given line number.
1234 if (FLAG_verbose_debug) { 1243 if (FLAG_verbose_debug) {
1235 OS::Print("Script '%s' does not contain line number %"Pd"\n", 1244 OS::Print("Script '%s' does not contain line number %"Pd"\n",
1236 script_url.ToCString(), line_number); 1245 script_url.ToCString(), line_number);
1237 } 1246 }
1238 return NULL; 1247 return NULL;
1239 } 1248 }
1240 const Function& func = 1249
1241 Function::Handle(lib.LookupFunctionInScript(script, first_token_idx)); 1250 Function& func = Function::Handle(isolate_);
1251 while (first_token_idx <= last_token_idx) {
1252 func = lib.LookupFunctionInScript(script, first_token_idx);
1253 if (!func.IsNull()) {
1254 break;
1255 }
1256 first_token_idx++;
1257 }
1242 if (func.IsNull()) { 1258 if (func.IsNull()) {
1243 if (FLAG_verbose_debug) { 1259 if (FLAG_verbose_debug) {
1244 OS::Print("No executable code at line %"Pd" in '%s'\n", 1260 OS::Print("No executable code at line %"Pd" in '%s'\n",
1245 line_number, script_url.ToCString()); 1261 line_number, script_url.ToCString());
1246 } 1262 }
1247 return NULL; 1263 return NULL;
1248 } 1264 }
1249 if (last_token_idx < 0) { 1265 if (last_token_idx < 0) {
1250 // The token at first_token_index is past the requested source line. 1266 // The token at first_token_index is past the requested source line.
1251 // Set the breakpoint at the closest position after that line. 1267 // Set the breakpoint at the closest position after that line.
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after
1677 if (FLAG_verbose_debug) { 1693 if (FLAG_verbose_debug) {
1678 OS::Print("Resetting pending breakpoint to function %s\n", 1694 OS::Print("Resetting pending breakpoint to function %s\n",
1679 closure.ToFullyQualifiedCString()); 1695 closure.ToFullyQualifiedCString());
1680 } 1696 }
1681 bpt->set_function(closure); 1697 bpt->set_function(closure);
1682 } else { 1698 } else {
1683 if (FLAG_verbose_debug) { 1699 if (FLAG_verbose_debug) {
1684 OS::Print("Enable pending breakpoint for function '%s'\n", 1700 OS::Print("Enable pending breakpoint for function '%s'\n",
1685 String::Handle(lookup_function.name()).ToCString()); 1701 String::Handle(lookup_function.name()).ToCString());
1686 } 1702 }
1687 // Set breakpoint in newly compiled code of function func. 1703 intptr_t bp_pos =
1688 CodeBreakpoint* cbpt = 1704 ResolveBreakpointPos(func, bpt->token_pos(), func.end_token_pos());
1689 MakeCodeBreakpoint(func, bpt->token_pos(), func.end_token_pos()); 1705 bpt->set_token_pos(bp_pos);
1690 if (cbpt != NULL) { 1706 MakeCodeBreakpointsAt(func, bp_pos, bpt);
1691 cbpt->set_src_bpt(bpt); 1707 SignalBpResolved(bpt);
1692 SignalBpResolved(bpt);
1693 }
1694 } 1708 }
1695 bpt->Enable(); // Enables the code breakpoint as well. 1709 bpt->Enable(); // Enables the code breakpoint as well.
1696 } 1710 }
1697 bpt = bpt->next(); 1711 bpt = bpt->next();
1698 } 1712 }
1699 } 1713 }
1700 1714
1701 1715
1702 CodeBreakpoint* Debugger::GetCodeBreakpoint(uword breakpoint_address) { 1716 CodeBreakpoint* Debugger::GetCodeBreakpoint(uword breakpoint_address) {
1703 CodeBreakpoint* bpt = code_breakpoints_; 1717 CodeBreakpoint* bpt = code_breakpoints_;
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1811 } 1825 }
1812 1826
1813 1827
1814 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { 1828 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
1815 ASSERT(bpt->next() == NULL); 1829 ASSERT(bpt->next() == NULL);
1816 bpt->set_next(code_breakpoints_); 1830 bpt->set_next(code_breakpoints_);
1817 code_breakpoints_ = bpt; 1831 code_breakpoints_ = bpt;
1818 } 1832 }
1819 1833
1820 } // namespace dart 1834 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/debugger.h ('k') | tests/standalone/debugger/basic_debugger_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698