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

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(const PcDescriptors& pc_descs, intptr_t i) {
srdjan 2013/05/16 00:11:36 Optional: I would either move this into the PcDesc
hausner 2013/05/16 15:23:03 I would like to keep the debugger-specific stuff l
864 PcDescriptors::Kind kind = pc_descs.DescriptorKind(i);
865 return ((kind == PcDescriptors::kIcCall) ||
866 (kind == PcDescriptors::kFuncCall) ||
867 (kind == PcDescriptors::kClosureCall) ||
868 (kind == PcDescriptors::kReturn));
869 }
870
871
863 void Debugger::InstrumentForStepping(const Function& target_function) { 872 void Debugger::InstrumentForStepping(const Function& target_function) {
864 if (!target_function.HasCode()) { 873 if (!target_function.HasCode()) {
865 Compiler::CompileFunction(target_function); 874 Compiler::CompileFunction(target_function);
866 // If there were any errors, ignore them silently and return without 875 // If there were any errors, ignore them silently and return without
867 // adding breakpoints to target. 876 // adding breakpoints to target.
868 if (!target_function.HasCode()) { 877 if (!target_function.HasCode()) {
869 return; 878 return;
870 } 879 }
871 } 880 }
872 DeoptimizeWorld(); 881 DeoptimizeWorld();
873 ASSERT(!target_function.HasOptimizedCode()); 882 ASSERT(!target_function.HasOptimizedCode());
874 Code& code = Code::Handle(target_function.unoptimized_code()); 883 Code& code = Code::Handle(target_function.unoptimized_code());
875 ASSERT(!code.IsNull()); 884 ASSERT(!code.IsNull());
876 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); 885 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
877 for (int i = 0; i < desc.Length(); i++) { 886 for (int i = 0; i < desc.Length(); i++) {
878 CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(i)); 887 CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(i));
879 if (bpt != NULL) { 888 if (bpt != NULL) {
880 // There is already a breakpoint for this address. Make sure 889 // There is already a breakpoint for this address. Make sure
881 // it is enabled. 890 // it is enabled.
882 bpt->Enable(); 891 bpt->Enable();
883 continue; 892 continue;
884 } 893 }
885 PcDescriptors::Kind kind = desc.DescriptorKind(i); 894 if (IsSafePoint(desc, 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); 895 bpt = new CodeBreakpoint(target_function, i);
891 RegisterCodeBreakpoint(bpt); 896 RegisterCodeBreakpoint(bpt);
892 bpt->Enable(); 897 bpt->Enable();
893 } 898 }
894 } 899 }
895 } 900 }
896 901
897 902
898 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { 903 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) {
899 if (event_handler_ != NULL) { 904 if (event_handler_ != NULL) {
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
1021 DebuggerEvent event; 1026 DebuggerEvent event;
1022 event.type = kExceptionThrown; 1027 event.type = kExceptionThrown;
1023 event.exception = &exc; 1028 event.exception = &exc;
1024 ASSERT(event_handler_ != NULL); 1029 ASSERT(event_handler_ != NULL);
1025 (*event_handler_)(&event); 1030 (*event_handler_)(&event);
1026 stack_trace_ = NULL; 1031 stack_trace_ = NULL;
1027 obj_cache_ = NULL; // Remote object cache is zone allocated. 1032 obj_cache_ = NULL; // Remote object cache is zone allocated.
1028 } 1033 }
1029 1034
1030 1035
1031 CodeBreakpoint* Debugger::MakeCodeBreakpoint(const Function& func, 1036 // Given a function and a token position range, return the best fit
1032 intptr_t first_token_pos, 1037 // token position to set a breakpoint.
1033 intptr_t last_token_pos) { 1038 // If multiple possible breakpoint positions are within the given range,
1039 // the one with the lowest machine code address is picked.
1040 // If no possible breakpoint location exists in the given range, the closest
1041 // token position after the range is returned.
1042 intptr_t Debugger::ResolveBreakpointPos(const Function& func,
1043 intptr_t first_token_pos,
1044 intptr_t last_token_pos) {
1034 ASSERT(func.HasCode()); 1045 ASSERT(func.HasCode());
1035 ASSERT(!func.HasOptimizedCode()); 1046 ASSERT(!func.HasOptimizedCode());
1036 Code& code = Code::Handle(func.unoptimized_code()); 1047 Code& code = Code::Handle(func.unoptimized_code());
1037 ASSERT(!code.IsNull()); 1048 ASSERT(!code.IsNull());
1038 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); 1049 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; 1050 intptr_t best_fit_index = -1;
1044 intptr_t best_fit = INT_MAX; 1051 intptr_t best_fit = INT_MAX;
1045 uword lowest_pc = kUwordMax; 1052 uword lowest_pc = kUwordMax;
1046 intptr_t lowest_pc_index = -1; 1053 intptr_t lowest_pc_index = -1;
1047 for (int i = 0; i < desc.Length(); i++) { 1054 for (int i = 0; i < desc.Length(); i++) {
1048 intptr_t desc_token_pos = desc.TokenPos(i); 1055 intptr_t desc_token_pos = desc.TokenPos(i);
1049 ASSERT(desc_token_pos >= 0); 1056 ASSERT(desc_token_pos >= 0);
1050 if (desc_token_pos < first_token_pos) { 1057 if (desc_token_pos < first_token_pos) {
1058 // This descriptor is before the given range.
1051 continue; 1059 continue;
1052 } 1060 }
1053 PcDescriptors::Kind kind = desc.DescriptorKind(i); 1061 if (IsSafePoint(desc, 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) { 1062 if ((desc_token_pos - first_token_pos) < best_fit) {
1063 // So far, this descriptor has the closest token position to the
1064 // beginning of the range.
1059 best_fit = desc_token_pos - first_token_pos; 1065 best_fit = desc_token_pos - first_token_pos;
1060 ASSERT(best_fit >= 0); 1066 ASSERT(best_fit >= 0);
1061 best_fit_index = i; 1067 best_fit_index = i;
1062 } 1068 }
1063 if ((first_token_pos <= desc_token_pos) && 1069 if ((first_token_pos <= desc_token_pos) &&
1064 (desc_token_pos <= last_token_pos) && 1070 (desc_token_pos <= last_token_pos) &&
1065 (desc.PC(i) < lowest_pc)) { 1071 (desc.PC(i) < lowest_pc)) {
1072 // This descriptor is within the token position range and so
1073 // far has the lowest code address.
1066 lowest_pc = desc.PC(i); 1074 lowest_pc = desc.PC(i);
1067 lowest_pc_index = i; 1075 lowest_pc_index = i;
1068 } 1076 }
1069 } 1077 }
1070 } 1078 }
1071 if (lowest_pc_index >= 0) { 1079 if (lowest_pc_index >= 0) {
1072 // We found the the pc descriptor within the given token range that 1080 // We found the the pc descriptor within the given token range that
1073 // has the lowest execution address. This is the first possible 1081 // has the lowest execution address. This is the first possible
1074 // breakpoint on the line. We use this instead of the nearest 1082 // breakpoint on the line. We use this instead of the nearest
1075 // PC descriptor measured in token index distance. 1083 // PC descriptor measured in token index distance.
1076 best_fit_index = lowest_pc_index; 1084 best_fit_index = lowest_pc_index;
1077 } 1085 }
1078 if (best_fit_index >= 0) { 1086 if (best_fit_index >= 0) {
1079 CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(best_fit_index)); 1087 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 } 1088 }
1098 return NULL; 1089 return -1;
1099 } 1090 }
1100 1091
1101 1092
1093 void Debugger::MakeCodeBreakpointsAt(const Function& func,
1094 intptr_t token_pos,
1095 SourceBreakpoint* bpt) {
1096 ASSERT(!func.HasOptimizedCode());
1097 Code& code = Code::Handle(func.unoptimized_code());
1098 ASSERT(!code.IsNull());
1099 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
1100 for (int i = 0; i < desc.Length(); i++) {
1101 intptr_t desc_token_pos = desc.TokenPos(i);
1102 if ((desc_token_pos == token_pos) && IsSafePoint(desc, i)) {
1103 CodeBreakpoint* code_bpt = GetCodeBreakpoint(desc.PC(i));
1104 if (code_bpt == NULL) {
1105 // No code breakpoint for this code exists; create one.
1106 code_bpt = new CodeBreakpoint(func, i);
1107 RegisterCodeBreakpoint(code_bpt);
1108 }
1109 code_bpt->set_src_bpt(bpt);
1110 }
1111 }
1112 }
1113
1114
1102 SourceBreakpoint* Debugger::SetBreakpoint(const Function& target_function, 1115 SourceBreakpoint* Debugger::SetBreakpoint(const Function& target_function,
1103 intptr_t first_token_pos, 1116 intptr_t first_token_pos,
1104 intptr_t last_token_pos) { 1117 intptr_t last_token_pos) {
1105 if ((last_token_pos < target_function.token_pos()) || 1118 if ((last_token_pos < target_function.token_pos()) ||
1106 (target_function.end_token_pos() < first_token_pos)) { 1119 (target_function.end_token_pos() < first_token_pos)) {
1107 // The given token position is not within the target function. 1120 // The given token position is not within the target function.
1108 return NULL; 1121 return NULL;
1109 } 1122 }
1110 DeoptimizeWorld(); 1123 intptr_t breakpoint_pos = -1;
1111 ASSERT(!target_function.HasOptimizedCode()); 1124 Function& closure = Function::Handle(isolate_);
1112 1125 if (target_function.HasImplicitClosureFunction()) {
1113 CodeBreakpoint* cbpt = NULL; 1126 // There is a closurized version of this function.
1114 SourceBreakpoint* source_bpt = NULL; 1127 closure = target_function.ImplicitClosureFunction();
1128 }
1129 // Determine actual breakpoint location if the function or an
1130 // implicit closure of the function has been compiled already.
1115 if (target_function.HasCode()) { 1131 if (target_function.HasCode()) {
1116 cbpt = MakeCodeBreakpoint(target_function, first_token_pos, last_token_pos); 1132 DeoptimizeWorld();
srdjan 2013/05/16 00:11:36 Do you need to deoptimize everything (also below)?
hausner 2013/05/16 15:23:03 See comment at DeoptimizeWorld. Yes, we currently
1117 if (cbpt != NULL) { 1133 ASSERT(!target_function.HasOptimizedCode());
1118 if (cbpt->src_bpt() != NULL) { 1134 breakpoint_pos =
1119 // There is already a source breakpoint for the location. 1135 ResolveBreakpointPos(target_function, first_token_pos, last_token_pos);
1120 ASSERT(cbpt->src_bpt() == 1136 } else if (!closure.IsNull() && closure.HasCode()) {
1121 GetSourceBreakpoint(target_function, cbpt->token_pos())); 1137 DeoptimizeWorld();
1122 return cbpt->src_bpt(); 1138 ASSERT(!closure.HasOptimizedCode());
1139 breakpoint_pos =
1140 ResolveBreakpointPos(closure, first_token_pos, last_token_pos);
1141 } else {
1142 // This function has not been compiled yet. Set a pending
1143 // breakpoint to be resolved later.
1144 SourceBreakpoint* source_bpt =
1145 GetSourceBreakpoint(target_function, first_token_pos);
1146 if (source_bpt != NULL) {
1147 // A pending source breakpoint for this uncompiled location
1148 // already exists.
1149 if (FLAG_verbose_debug && !target_function.HasCode()) {
1150 OS::Print("Pending breakpoint for uncompiled function"
1151 " '%s' at line %"Pd" already exists\n",
1152 target_function.ToFullyQualifiedCString(),
1153 source_bpt->LineNumber());
1123 } 1154 }
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; 1155 return source_bpt;
1136 } 1156 }
1137 } 1157 source_bpt =
1138 source_bpt = new SourceBreakpoint(nextId(), target_function, first_token_pos); 1158 new SourceBreakpoint(nextId(), target_function, first_token_pos);
1139 RegisterSourceBreakpoint(source_bpt); 1159 RegisterSourceBreakpoint(source_bpt);
1140 if (FLAG_verbose_debug && !target_function.HasCode()) { 1160 if (FLAG_verbose_debug && !target_function.HasCode()) {
Ivan Posva 2013/05/16 00:03:52 Check for target_function.HasCode() is confusing a
hausner 2013/05/16 00:10:47 Good catch. Also in line 1149. Done.
1141 OS::Print("Registering breakpoint for " 1161 OS::Print("Registering pending breakpoint for "
1142 "uncompiled function '%s' at line %"Pd"\n", 1162 "uncompiled function '%s' at line %"Pd"\n",
1143 target_function.ToFullyQualifiedCString(), 1163 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) {
1153 OS::Print("Failed to set breakpoint at '%s' line %"Pd"\n",
1154 String::Handle(source_bpt->SourceUrl()).ToCString(),
1155 source_bpt->LineNumber()); 1164 source_bpt->LineNumber());
1156 } 1165 }
1166 source_bpt->Enable();
1167 return source_bpt;
1157 } 1168 }
1158 1169 ASSERT(breakpoint_pos != -1);
1159 if (target_function.HasImplicitClosureFunction()) { 1170 SourceBreakpoint* source_bpt =
1160 // There is a closurized version of this function. If the closure 1171 GetSourceBreakpoint(target_function, breakpoint_pos);
1161 // is already compiled, we need to set a code breakpoint in its 1172 if (source_bpt != NULL) {
1162 // code. 1173 // A source breakpoint for this location already exists.
1163 const Function& closure = 1174 return source_bpt;
1164 Function::Handle(target_function.ImplicitClosureFunction()); 1175 }
1165 if (closure.HasCode()) { 1176 source_bpt = new SourceBreakpoint(nextId(), target_function, breakpoint_pos);
1166 ASSERT(!closure.HasOptimizedCode()); 1177 RegisterSourceBreakpoint(source_bpt);
1167 CodeBreakpoint* closure_bpt = 1178 if (target_function.HasCode()) {
1168 MakeCodeBreakpoint(closure, first_token_pos, last_token_pos); 1179 MakeCodeBreakpointsAt(target_function, breakpoint_pos, source_bpt);
1169 if ((closure_bpt != NULL) && (closure_bpt->src_bpt() == NULL)) { 1180 }
1170 closure_bpt->set_src_bpt(source_bpt); 1181 if (!closure.IsNull() && closure.HasCode()) {
1171 } 1182 MakeCodeBreakpointsAt(closure, breakpoint_pos, source_bpt);
1172 }
1173 } 1183 }
1174 source_bpt->Enable(); 1184 source_bpt->Enable();
1175 return source_bpt; 1185 return source_bpt;
1176 } 1186 }
1177 1187
1178 1188
1179 // Synchronize the enabled/disabled state of all code breakpoints 1189 // Synchronize the enabled/disabled state of all code breakpoints
1180 // associated with the source breakpoint bpt. 1190 // associated with the source breakpoint bpt.
1181 void Debugger::SyncBreakpoint(SourceBreakpoint* bpt) { 1191 void Debugger::SyncBreakpoint(SourceBreakpoint* bpt) {
1182 CodeBreakpoint* cbpt = code_breakpoints_; 1192 CodeBreakpoint* cbpt = code_breakpoints_;
(...skipping 19 matching lines...) Expand all
1202 const Function& target_function) { 1212 const Function& target_function) {
1203 ASSERT(!target_function.IsNull()); 1213 ASSERT(!target_function.IsNull());
1204 return SetBreakpoint(target_function, 1214 return SetBreakpoint(target_function,
1205 target_function.token_pos(), 1215 target_function.token_pos(),
1206 target_function.end_token_pos()); 1216 target_function.end_token_pos());
1207 } 1217 }
1208 1218
1209 1219
1210 SourceBreakpoint* Debugger::SetBreakpointAtLine(const String& script_url, 1220 SourceBreakpoint* Debugger::SetBreakpointAtLine(const String& script_url,
1211 intptr_t line_number) { 1221 intptr_t line_number) {
1212 Library& lib = Library::Handle(); 1222 Library& lib = Library::Handle(isolate_);
1213 Script& script = Script::Handle(); 1223 Script& script = Script::Handle(isolate_);
1214 const GrowableObjectArray& libs = 1224 const GrowableObjectArray& libs =
1215 GrowableObjectArray::Handle(isolate_->object_store()->libraries()); 1225 GrowableObjectArray::Handle(isolate_->object_store()->libraries());
1216 for (int i = 0; i < libs.Length(); i++) { 1226 for (int i = 0; i < libs.Length(); i++) {
1217 lib ^= libs.At(i); 1227 lib ^= libs.At(i);
1218 script = lib.LookupScript(script_url); 1228 script = lib.LookupScript(script_url);
1219 if (!script.IsNull()) { 1229 if (!script.IsNull()) {
1220 break; 1230 break;
1221 } 1231 }
1222 } 1232 }
1223 if (script.IsNull()) { 1233 if (script.IsNull()) {
1224 if (FLAG_verbose_debug) { 1234 if (FLAG_verbose_debug) {
1225 OS::Print("Failed to find script with url '%s'\n", 1235 OS::Print("Failed to find script with url '%s'\n",
1226 script_url.ToCString()); 1236 script_url.ToCString());
1227 } 1237 }
1228 return NULL; 1238 return NULL;
1229 } 1239 }
1230 intptr_t first_token_idx, last_token_idx; 1240 intptr_t first_token_idx, last_token_idx;
1231 script.TokenRangeAtLine(line_number, &first_token_idx, &last_token_idx); 1241 script.TokenRangeAtLine(line_number, &first_token_idx, &last_token_idx);
1232 if (first_token_idx < 0) { 1242 if (first_token_idx < 0) {
1233 // Script does not contain the given line number. 1243 // Script does not contain the given line number.
1234 if (FLAG_verbose_debug) { 1244 if (FLAG_verbose_debug) {
1235 OS::Print("Script '%s' does not contain line number %"Pd"\n", 1245 OS::Print("Script '%s' does not contain line number %"Pd"\n",
1236 script_url.ToCString(), line_number); 1246 script_url.ToCString(), line_number);
1237 } 1247 }
1238 return NULL; 1248 return NULL;
1239 } 1249 }
1240 const Function& func = 1250
1241 Function::Handle(lib.LookupFunctionInScript(script, first_token_idx)); 1251 Function& func = Function::Handle(isolate_);
1252 while (first_token_idx <= last_token_idx) {
1253 func = lib.LookupFunctionInScript(script, first_token_idx);
1254 if (!func.IsNull()) {
1255 break;
1256 }
1257 first_token_idx++;
1258 }
1242 if (func.IsNull()) { 1259 if (func.IsNull()) {
1243 if (FLAG_verbose_debug) { 1260 if (FLAG_verbose_debug) {
1244 OS::Print("No executable code at line %"Pd" in '%s'\n", 1261 OS::Print("No executable code at line %"Pd" in '%s'\n",
1245 line_number, script_url.ToCString()); 1262 line_number, script_url.ToCString());
1246 } 1263 }
1247 return NULL; 1264 return NULL;
1248 } 1265 }
1249 if (last_token_idx < 0) { 1266 if (last_token_idx < 0) {
1250 // The token at first_token_index is past the requested source line. 1267 // The token at first_token_index is past the requested source line.
1251 // Set the breakpoint at the closest position after that line. 1268 // 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) { 1694 if (FLAG_verbose_debug) {
1678 OS::Print("Resetting pending breakpoint to function %s\n", 1695 OS::Print("Resetting pending breakpoint to function %s\n",
1679 closure.ToFullyQualifiedCString()); 1696 closure.ToFullyQualifiedCString());
1680 } 1697 }
1681 bpt->set_function(closure); 1698 bpt->set_function(closure);
1682 } else { 1699 } else {
1683 if (FLAG_verbose_debug) { 1700 if (FLAG_verbose_debug) {
1684 OS::Print("Enable pending breakpoint for function '%s'\n", 1701 OS::Print("Enable pending breakpoint for function '%s'\n",
1685 String::Handle(lookup_function.name()).ToCString()); 1702 String::Handle(lookup_function.name()).ToCString());
1686 } 1703 }
1687 // Set breakpoint in newly compiled code of function func. 1704 intptr_t bp_pos =
1688 CodeBreakpoint* cbpt = 1705 ResolveBreakpointPos(func, bpt->token_pos(), func.end_token_pos());
1689 MakeCodeBreakpoint(func, bpt->token_pos(), func.end_token_pos()); 1706 bpt->set_token_pos(bp_pos);
1690 if (cbpt != NULL) { 1707 MakeCodeBreakpointsAt(func, bp_pos, bpt);
1691 cbpt->set_src_bpt(bpt); 1708 SignalBpResolved(bpt);
1692 SignalBpResolved(bpt);
1693 }
1694 } 1709 }
1695 bpt->Enable(); // Enables the code breakpoint as well. 1710 bpt->Enable(); // Enables the code breakpoint as well.
1696 } 1711 }
1697 bpt = bpt->next(); 1712 bpt = bpt->next();
1698 } 1713 }
1699 } 1714 }
1700 1715
1701 1716
1702 CodeBreakpoint* Debugger::GetCodeBreakpoint(uword breakpoint_address) { 1717 CodeBreakpoint* Debugger::GetCodeBreakpoint(uword breakpoint_address) {
1703 CodeBreakpoint* bpt = code_breakpoints_; 1718 CodeBreakpoint* bpt = code_breakpoints_;
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1811 } 1826 }
1812 1827
1813 1828
1814 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { 1829 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
1815 ASSERT(bpt->next() == NULL); 1830 ASSERT(bpt->next() == NULL);
1816 bpt->set_next(code_breakpoints_); 1831 bpt->set_next(code_breakpoints_);
1817 code_breakpoints_ = bpt; 1832 code_breakpoints_ = bpt;
1818 } 1833 }
1819 1834
1820 } // namespace dart 1835 } // 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