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

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

Issue 2646443005: Track async causal stack traces (Closed)
Patch Set: rebase Created 3 years, 10 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 | « runtime/vm/debugger.h ('k') | runtime/vm/exceptions.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 (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 "platform/address_sanitizer.h" 9 #include "platform/address_sanitizer.h"
10 10
11 #include "vm/code_generator.h" 11 #include "vm/code_generator.h"
12 #include "vm/code_patcher.h" 12 #include "vm/code_patcher.h"
13 #include "vm/compiler.h" 13 #include "vm/compiler.h"
14 #include "vm/dart_entry.h" 14 #include "vm/dart_entry.h"
15 #include "vm/deopt_instructions.h" 15 #include "vm/deopt_instructions.h"
16 #include "vm/flags.h" 16 #include "vm/flags.h"
17 #include "vm/globals.h" 17 #include "vm/globals.h"
18 #include "vm/longjump.h" 18 #include "vm/longjump.h"
19 #include "vm/json_stream.h" 19 #include "vm/json_stream.h"
20 #include "vm/message_handler.h" 20 #include "vm/message_handler.h"
21 #include "vm/object.h" 21 #include "vm/object.h"
22 #include "vm/object_store.h" 22 #include "vm/object_store.h"
23 #include "vm/os.h" 23 #include "vm/os.h"
24 #include "vm/port.h" 24 #include "vm/port.h"
25 #include "vm/service_event.h" 25 #include "vm/service_event.h"
26 #include "vm/service_isolate.h" 26 #include "vm/service_isolate.h"
27 #include "vm/service.h" 27 #include "vm/service.h"
28 #include "vm/stack_frame.h" 28 #include "vm/stack_frame.h"
29 #include "vm/stack_trace.h"
29 #include "vm/stub_code.h" 30 #include "vm/stub_code.h"
30 #include "vm/symbols.h" 31 #include "vm/symbols.h"
31 #include "vm/thread_interrupter.h" 32 #include "vm/thread_interrupter.h"
32 #include "vm/timeline.h" 33 #include "vm/timeline.h"
33 #include "vm/token_position.h" 34 #include "vm/token_position.h"
34 #include "vm/visitor.h" 35 #include "vm/visitor.h"
35 36
36 37
37 namespace dart { 38 namespace dart {
38 39
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 visitor->VisitPointer(reinterpret_cast<RawObject**>(&saved_value_)); 243 visitor->VisitPointer(reinterpret_cast<RawObject**>(&saved_value_));
243 #endif 244 #endif
244 } 245 }
245 246
246 247
247 ActivationFrame::ActivationFrame(uword pc, 248 ActivationFrame::ActivationFrame(uword pc,
248 uword fp, 249 uword fp,
249 uword sp, 250 uword sp,
250 const Code& code, 251 const Code& code,
251 const Array& deopt_frame, 252 const Array& deopt_frame,
252 intptr_t deopt_frame_offset) 253 intptr_t deopt_frame_offset,
254 ActivationFrame::Kind kind)
253 : pc_(pc), 255 : pc_(pc),
254 fp_(fp), 256 fp_(fp),
255 sp_(sp), 257 sp_(sp),
256 ctx_(Context::ZoneHandle()), 258 ctx_(Context::ZoneHandle()),
257 code_(Code::ZoneHandle(code.raw())), 259 code_(Code::ZoneHandle(code.raw())),
258 function_(Function::ZoneHandle(code.function())), 260 function_(Function::ZoneHandle(code.function())),
261 live_frame_(kind == kRegular),
259 token_pos_initialized_(false), 262 token_pos_initialized_(false),
260 token_pos_(TokenPosition::kNoSource), 263 token_pos_(TokenPosition::kNoSource),
261 try_index_(-1), 264 try_index_(-1),
262 line_number_(-1), 265 line_number_(-1),
263 column_number_(-1), 266 column_number_(-1),
264 context_level_(-1), 267 context_level_(-1),
265 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())), 268 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())),
266 deopt_frame_offset_(deopt_frame_offset), 269 deopt_frame_offset_(deopt_frame_offset),
270 kind_(kind),
267 vars_initialized_(false), 271 vars_initialized_(false),
268 var_descriptors_(LocalVarDescriptors::ZoneHandle()), 272 var_descriptors_(LocalVarDescriptors::ZoneHandle()),
269 desc_indices_(8), 273 desc_indices_(8),
270 pc_desc_(PcDescriptors::ZoneHandle()) {} 274 pc_desc_(PcDescriptors::ZoneHandle()) {}
271 275
272 276
277 ActivationFrame::ActivationFrame(Kind kind)
278 : pc_(0),
279 fp_(0),
280 sp_(0),
281 ctx_(Context::ZoneHandle()),
282 code_(Code::ZoneHandle()),
283 function_(Function::ZoneHandle()),
284 live_frame_(kind == kRegular),
285 token_pos_initialized_(false),
286 token_pos_(TokenPosition::kNoSource),
287 try_index_(-1),
288 line_number_(-1),
289 column_number_(-1),
290 context_level_(-1),
291 deopt_frame_(Array::ZoneHandle()),
292 deopt_frame_offset_(0),
293 kind_(kind),
294 vars_initialized_(false),
295 var_descriptors_(LocalVarDescriptors::ZoneHandle()),
296 desc_indices_(8),
297 pc_desc_(PcDescriptors::ZoneHandle()) {}
298
273 bool Debugger::NeedsIsolateEvents() { 299 bool Debugger::NeedsIsolateEvents() {
274 return ((isolate_ != Dart::vm_isolate()) && 300 return ((isolate_ != Dart::vm_isolate()) &&
275 !ServiceIsolate::IsServiceIsolateDescendant(isolate_) && 301 !ServiceIsolate::IsServiceIsolateDescendant(isolate_) &&
276 ((event_handler_ != NULL) || Service::isolate_stream.enabled())); 302 ((event_handler_ != NULL) || Service::isolate_stream.enabled()));
277 } 303 }
278 304
279 305
280 bool Debugger::NeedsDebugEvents() { 306 bool Debugger::NeedsDebugEvents() {
281 ASSERT(isolate_ != Dart::vm_isolate() && 307 ASSERT(isolate_ != Dart::vm_isolate() &&
282 !ServiceIsolate::IsServiceIsolateDescendant(isolate_)); 308 !ServiceIsolate::IsServiceIsolateDescendant(isolate_));
(...skipping 28 matching lines...) Expand all
311 if (ignore_breakpoints_ || IsPaused()) { 337 if (ignore_breakpoints_ || IsPaused()) {
312 // We don't let the isolate get interrupted if we are already 338 // We don't let the isolate get interrupted if we are already
313 // paused or ignoring breakpoints. 339 // paused or ignoring breakpoints.
314 return Error::null(); 340 return Error::null();
315 } 341 }
316 ServiceEvent event(isolate_, kind); 342 ServiceEvent event(isolate_, kind);
317 DebuggerStackTrace* trace = CollectStackTrace(); 343 DebuggerStackTrace* trace = CollectStackTrace();
318 if (trace->Length() > 0) { 344 if (trace->Length() > 0) {
319 event.set_top_frame(trace->FrameAt(0)); 345 event.set_top_frame(trace->FrameAt(0));
320 } 346 }
321 ASSERT(stack_trace_ == NULL); 347 CacheStackTraces(trace, CollectAsyncCausalStackTrace());
322 stack_trace_ = trace;
323 resume_action_ = kContinue; 348 resume_action_ = kContinue;
324 Pause(&event); 349 Pause(&event);
325 HandleSteppingRequest(trace); 350 HandleSteppingRequest(trace);
326 stack_trace_ = NULL; 351 ClearCachedStackTraces();
327 352
328 // If any error occurred while in the debug message loop, return it here. 353 // If any error occurred while in the debug message loop, return it here.
329 const Error& error = Error::Handle(Thread::Current()->sticky_error()); 354 const Error& error = Error::Handle(Thread::Current()->sticky_error());
330 ASSERT(error.IsNull() || error.IsUnwindError()); 355 ASSERT(error.IsNull() || error.IsUnwindError());
331 Thread::Current()->clear_sticky_error(); 356 Thread::Current()->clear_sticky_error();
332 return error.raw(); 357 return error.raw();
333 } 358 }
334 359
335 360
336 void Debugger::SendBreakpointEvent(ServiceEvent::EventKind kind, 361 void Debugger::SendBreakpointEvent(ServiceEvent::EventKind kind,
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after
733 } 758 }
734 759
735 760
736 void ActivationFrame::GetDescIndices() { 761 void ActivationFrame::GetDescIndices() {
737 if (vars_initialized_) { 762 if (vars_initialized_) {
738 return; 763 return;
739 } 764 }
740 GetVarDescriptors(); 765 GetVarDescriptors();
741 766
742 TokenPosition activation_token_pos = TokenPos(); 767 TokenPosition activation_token_pos = TokenPos();
743 if (!activation_token_pos.IsDebugPause()) { 768 if (!activation_token_pos.IsDebugPause() || !live_frame_) {
744 // We don't have a token position for this frame, so can't determine 769 // We don't have a token position for this frame, so can't determine
745 // which variables are visible. 770 // which variables are visible.
746 vars_initialized_ = true; 771 vars_initialized_ = true;
747 return; 772 return;
748 } 773 }
749 774
750 GrowableArray<String*> var_names(8); 775 GrowableArray<String*> var_names(8);
751 intptr_t var_desc_len = var_descriptors_.Length(); 776 intptr_t var_desc_len = var_descriptors_.Length();
752 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { 777 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) {
753 ASSERT(var_names.length() == desc_indices_.length()); 778 ASSERT(var_names.length() == desc_indices_.length());
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
1079 "\tline = %" Pd 1104 "\tline = %" Pd
1080 "\n" 1105 "\n"
1081 "\tcontext = %s\n" 1106 "\tcontext = %s\n"
1082 "\tcontext level = %" Pd " ]\n", 1107 "\tcontext level = %" Pd " ]\n",
1083 pc(), fp(), sp(), func_name, url.ToCString(), line, ctx_.ToCString(), 1108 pc(), fp(), sp(), func_name, url.ToCString(), line, ctx_.ToCString(),
1084 ContextLevel()); 1109 ContextLevel());
1085 } 1110 }
1086 1111
1087 1112
1088 void ActivationFrame::PrintToJSONObject(JSONObject* jsobj, bool full) { 1113 void ActivationFrame::PrintToJSONObject(JSONObject* jsobj, bool full) {
1114 if (kind_ == kRegular) {
1115 PrintToJSONObjectRegular(jsobj, full);
1116 } else if (kind_ == kAsyncCausal) {
1117 PrintToJSONObjectAsyncCausal(jsobj, full);
1118 } else if (kind_ == kAsyncSuspensionMarker) {
1119 PrintToJSONObjectAsyncSuspensionMarker(jsobj, full);
1120 } else {
1121 UNIMPLEMENTED();
1122 }
1123 }
1124
1125
1126 void ActivationFrame::PrintToJSONObjectRegular(JSONObject* jsobj, bool full) {
1089 const Script& script = Script::Handle(SourceScript()); 1127 const Script& script = Script::Handle(SourceScript());
1090 jsobj->AddProperty("type", "Frame"); 1128 jsobj->AddProperty("type", "Frame");
1129 jsobj->AddProperty("kind", KindToCString(kind_));
1091 TokenPosition pos = TokenPos(); 1130 TokenPosition pos = TokenPos();
1092 if (pos.IsSynthetic()) { 1131 if (pos.IsSynthetic()) {
1093 pos = pos.FromSynthetic(); 1132 pos = pos.FromSynthetic();
1094 } 1133 }
1095 jsobj->AddLocation(script, pos); 1134 jsobj->AddLocation(script, pos);
1096 jsobj->AddProperty("function", function(), !full); 1135 jsobj->AddProperty("function", function(), !full);
1097 jsobj->AddProperty("code", code()); 1136 jsobj->AddProperty("code", code());
1098 if (full) { 1137 if (full) {
1099 // TODO(cutch): The old "full" script usage no longer fits 1138 // TODO(cutch): The old "full" script usage no longer fits
1100 // in the world where we pass the script as part of the 1139 // in the world where we pass the script as part of the
(...skipping 21 matching lines...) Expand all
1122 jsvar.AddProperty("declarationTokenPos", declaration_token_pos); 1161 jsvar.AddProperty("declarationTokenPos", declaration_token_pos);
1123 // When the variable becomes visible to the scope. 1162 // When the variable becomes visible to the scope.
1124 jsvar.AddProperty("scopeStartTokenPos", visible_start_token_pos); 1163 jsvar.AddProperty("scopeStartTokenPos", visible_start_token_pos);
1125 // When the variable stops being visible to the scope. 1164 // When the variable stops being visible to the scope.
1126 jsvar.AddProperty("scopeEndTokenPos", visible_end_token_pos); 1165 jsvar.AddProperty("scopeEndTokenPos", visible_end_token_pos);
1127 } 1166 }
1128 } 1167 }
1129 } 1168 }
1130 } 1169 }
1131 1170
1171
1172 void ActivationFrame::PrintToJSONObjectAsyncCausal(JSONObject* jsobj,
1173 bool full) {
1174 jsobj->AddProperty("type", "Frame");
1175 jsobj->AddProperty("kind", KindToCString(kind_));
1176 const Script& script = Script::Handle(SourceScript());
1177 TokenPosition pos = TokenPos();
1178 if (pos.IsSynthetic()) {
1179 pos = pos.FromSynthetic();
1180 }
1181 jsobj->AddLocation(script, pos);
1182 jsobj->AddProperty("function", function(), !full);
1183 jsobj->AddProperty("code", code());
1184 if (full) {
1185 // TODO(cutch): The old "full" script usage no longer fits
1186 // in the world where we pass the script as part of the
1187 // location.
1188 jsobj->AddProperty("script", script, !full);
1189 }
1190 }
1191
1192
1193 void ActivationFrame::PrintToJSONObjectAsyncSuspensionMarker(JSONObject* jsobj,
1194 bool full) {
1195 jsobj->AddProperty("type", "Frame");
1196 jsobj->AddProperty("kind", KindToCString(kind_));
1197 jsobj->AddProperty("marker", "AsynchronousSuspension");
1198 }
1199
1200
1132 static bool IsFunctionVisible(const Function& function) { 1201 static bool IsFunctionVisible(const Function& function) {
1133 return FLAG_show_invisible_frames || function.is_visible(); 1202 return FLAG_show_invisible_frames || function.is_visible();
1134 } 1203 }
1135 1204
1136 1205
1137 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) { 1206 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) {
1138 if (IsFunctionVisible(frame->function())) { 1207 if (IsFunctionVisible(frame->function())) {
1139 trace_.Add(frame); 1208 trace_.Add(frame);
1140 } 1209 }
1141 } 1210 }
1142 1211
1143 1212
1213 void DebuggerStackTrace::AddMarker(ActivationFrame::Kind marker) {
1214 ASSERT((marker >= ActivationFrame::kAsyncSuspensionMarker) &&
1215 (marker <= ActivationFrame::kAsyncSuspensionMarker));
1216 trace_.Add(new ActivationFrame(marker));
1217 }
1218
1219
1220 void DebuggerStackTrace::AddAsyncCausalFrame(uword pc, const Code& code) {
1221 trace_.Add(new ActivationFrame(pc, 0, 0, code, Array::Handle(), 0,
1222 ActivationFrame::kAsyncCausal));
1223 }
1224
1225
1144 const uint8_t kSafepointKind = RawPcDescriptors::kIcCall | 1226 const uint8_t kSafepointKind = RawPcDescriptors::kIcCall |
1145 RawPcDescriptors::kUnoptStaticCall | 1227 RawPcDescriptors::kUnoptStaticCall |
1146 RawPcDescriptors::kRuntimeCall; 1228 RawPcDescriptors::kRuntimeCall;
1147 1229
1148 1230
1149 CodeBreakpoint::CodeBreakpoint(const Code& code, 1231 CodeBreakpoint::CodeBreakpoint(const Code& code,
1150 TokenPosition token_pos, 1232 TokenPosition token_pos,
1151 uword pc, 1233 uword pc,
1152 RawPcDescriptors::Kind kind) 1234 RawPcDescriptors::Kind kind)
1153 : code_(code.raw()), 1235 : code_(code.raw()),
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1261 latent_locations_(NULL), 1343 latent_locations_(NULL),
1262 breakpoint_locations_(NULL), 1344 breakpoint_locations_(NULL),
1263 code_breakpoints_(NULL), 1345 code_breakpoints_(NULL),
1264 resume_action_(kContinue), 1346 resume_action_(kContinue),
1265 resume_frame_index_(-1), 1347 resume_frame_index_(-1),
1266 post_deopt_frame_index_(-1), 1348 post_deopt_frame_index_(-1),
1267 ignore_breakpoints_(false), 1349 ignore_breakpoints_(false),
1268 pause_event_(NULL), 1350 pause_event_(NULL),
1269 obj_cache_(NULL), 1351 obj_cache_(NULL),
1270 stack_trace_(NULL), 1352 stack_trace_(NULL),
1353 async_causal_stack_trace_(NULL),
1271 stepping_fp_(0), 1354 stepping_fp_(0),
1272 skip_next_step_(false), 1355 skip_next_step_(false),
1273 synthetic_async_breakpoint_(NULL), 1356 synthetic_async_breakpoint_(NULL),
1274 exc_pause_info_(kNoPauseOnExceptions) {} 1357 exc_pause_info_(kNoPauseOnExceptions) {}
1275 1358
1276 1359
1277 Debugger::~Debugger() { 1360 Debugger::~Debugger() {
1278 isolate_id_ = ILLEGAL_ISOLATE_ID; 1361 isolate_id_ = ILLEGAL_ISOLATE_ID;
1279 ASSERT(!IsPaused()); 1362 ASSERT(!IsPaused());
1280 ASSERT(latent_locations_ == NULL); 1363 ASSERT(latent_locations_ == NULL);
1281 ASSERT(breakpoint_locations_ == NULL); 1364 ASSERT(breakpoint_locations_ == NULL);
1282 ASSERT(code_breakpoints_ == NULL); 1365 ASSERT(code_breakpoints_ == NULL);
1283 ASSERT(stack_trace_ == NULL); 1366 ASSERT(stack_trace_ == NULL);
1367 ASSERT(async_causal_stack_trace_ == NULL);
1284 ASSERT(obj_cache_ == NULL); 1368 ASSERT(obj_cache_ == NULL);
1285 ASSERT(synthetic_async_breakpoint_ == NULL); 1369 ASSERT(synthetic_async_breakpoint_ == NULL);
1286 } 1370 }
1287 1371
1288 1372
1289 void Debugger::Shutdown() { 1373 void Debugger::Shutdown() {
1290 // TODO(johnmccutchan): Do not create a debugger for isolates that don't need 1374 // TODO(johnmccutchan): Do not create a debugger for isolates that don't need
1291 // them. Then, assert here that isolate_ is not one of those isolates. 1375 // them. Then, assert here that isolate_ is not one of those isolates.
1292 if ((isolate_ == Dart::vm_isolate()) || 1376 if ((isolate_ == Dart::vm_isolate()) ||
1293 ServiceIsolate::IsServiceIsolateDescendant(isolate_)) { 1377 ServiceIsolate::IsServiceIsolateDescendant(isolate_)) {
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
1512 1596
1513 for (StackFrame* frame = iterator.NextFrame(); frame != NULL; 1597 for (StackFrame* frame = iterator.NextFrame(); frame != NULL;
1514 frame = iterator.NextFrame()) { 1598 frame = iterator.NextFrame()) {
1515 ASSERT(frame->IsValid()); 1599 ASSERT(frame->IsValid());
1516 if (FLAG_trace_debugger_stacktrace) { 1600 if (FLAG_trace_debugger_stacktrace) {
1517 OS::PrintErr("CollectStackTrace: visiting frame:\n\t%s\n", 1601 OS::PrintErr("CollectStackTrace: visiting frame:\n\t%s\n",
1518 frame->ToCString()); 1602 frame->ToCString());
1519 } 1603 }
1520 if (frame->IsDartFrame()) { 1604 if (frame->IsDartFrame()) {
1521 code = frame->LookupDartCode(); 1605 code = frame->LookupDartCode();
1522 if (code.is_optimized() && !FLAG_precompiled_runtime) { 1606 AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code,
1523 deopt_frame = DeoptimizeToArray(thread, frame, code); 1607 &inlined_code, &deopt_frame);
1524 for (InlinedFunctionsIterator it(code, frame->pc()); !it.Done();
1525 it.Advance()) {
1526 inlined_code = it.code();
1527 if (FLAG_trace_debugger_stacktrace) {
1528 const Function& function =
1529 Function::Handle(zone, inlined_code.function());
1530 ASSERT(!function.IsNull());
1531 OS::PrintErr("CollectStackTrace: visiting inlined function: %s\n",
1532 function.ToFullyQualifiedCString());
1533 }
1534 intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
1535 stack_trace->AddActivation(CollectDartFrame(isolate, it.pc(), frame,
1536 inlined_code, deopt_frame,
1537 deopt_frame_offset));
1538 }
1539 } else {
1540 stack_trace->AddActivation(CollectDartFrame(
1541 isolate, frame->pc(), frame, code, Object::null_array(), 0));
1542 }
1543 } 1608 }
1544 } 1609 }
1545 return stack_trace; 1610 return stack_trace;
1546 } 1611 }
1547 1612
1613 void Debugger::AppendCodeFrames(Thread* thread,
1614 Isolate* isolate,
1615 Zone* zone,
1616 DebuggerStackTrace* stack_trace,
1617 StackFrame* frame,
1618 Code* code,
1619 Code* inlined_code,
1620 Array* deopt_frame) {
1621 if (code->is_optimized() && !FLAG_precompiled_runtime) {
1622 // TODO(rmacnak): Use CodeSourceMap
1623 *deopt_frame = DeoptimizeToArray(thread, frame, *code);
1624 for (InlinedFunctionsIterator it(*code, frame->pc()); !it.Done();
1625 it.Advance()) {
1626 *inlined_code = it.code();
1627 if (FLAG_trace_debugger_stacktrace) {
1628 const Function& function =
1629 Function::Handle(zone, inlined_code->function());
1630 ASSERT(!function.IsNull());
1631 OS::PrintErr("CollectStackTrace: visiting inlined function: %s\n",
1632 function.ToFullyQualifiedCString());
1633 }
1634 intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
1635 stack_trace->AddActivation(CollectDartFrame(isolate, it.pc(), frame,
1636 *inlined_code, *deopt_frame,
1637 deopt_frame_offset));
1638 }
1639 } else {
1640 stack_trace->AddActivation(CollectDartFrame(
1641 isolate, frame->pc(), frame, *code, Object::null_array(), 0));
1642 }
1643 }
1644
1645
1646 DebuggerStackTrace* Debugger::CollectAsyncCausalStackTrace() {
1647 if (!FLAG_causal_async_stacks) {
1648 return NULL;
1649 }
1650 Thread* thread = Thread::Current();
1651 Zone* zone = thread->zone();
1652 Isolate* isolate = thread->isolate();
1653 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
1654
1655 Code& code = Code::Handle(zone);
1656 Smi& offset = Smi::Handle();
1657 Code& inlined_code = Code::Handle(zone);
1658 Array& deopt_frame = Array::Handle(zone);
1659
1660 Function& async_function = Function::Handle(zone);
1661 class StackTrace& async_stack_trace = StackTrace::Handle(zone);
1662 Array& async_code_array = Array::Handle(zone);
1663 Array& async_pc_offset_array = Array::Handle(zone);
1664 StackTraceUtils::ExtractAsyncStackTraceInfo(
1665 thread, &async_function, &async_stack_trace, &async_code_array,
1666 &async_pc_offset_array);
1667
1668 if (async_function.IsNull()) {
1669 return NULL;
1670 }
1671
1672 intptr_t synchronous_stack_trace_length =
1673 StackTraceUtils::CountFrames(thread, 0, async_function);
1674
1675 // Append the top frames from the synchronous stack trace, up until the active
1676 // asynchronous function. We truncate the remainder of the synchronous
1677 // stack trace because it contains activations that are part of the
1678 // asynchronous dispatch mechanisms.
1679 StackFrameIterator iterator(false);
1680 StackFrame* frame = iterator.NextFrame();
1681 while (synchronous_stack_trace_length >= 0) {
1682 ASSERT(frame != NULL);
1683 if (frame->IsDartFrame()) {
1684 code = frame->LookupDartCode();
1685 AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code,
1686 &inlined_code, &deopt_frame);
1687 synchronous_stack_trace_length--;
1688 }
1689 frame = iterator.NextFrame();
1690 }
1691
1692 // Now we append the asynchronous causal stack trace. These are not active
1693 // frames but a historical record of how this asynchronous function was
1694 // activated.
1695 while (!async_stack_trace.IsNull()) {
1696 for (intptr_t i = 0; i < async_stack_trace.Length(); i++) {
1697 if (async_stack_trace.CodeAtFrame(i) == Code::null()) {
1698 break;
1699 }
1700 if (async_stack_trace.CodeAtFrame(i) ==
1701 StubCode::AsynchronousGapMarker_entry()->code()) {
1702 stack_trace->AddMarker(ActivationFrame::kAsyncSuspensionMarker);
1703 } else {
1704 code = Code::RawCast(async_stack_trace.CodeAtFrame(i));
1705 offset = Smi::RawCast(async_stack_trace.PcOffsetAtFrame(i));
1706 uword pc = code.PayloadStart() + offset.Value();
1707 if (code.is_optimized()) {
1708 for (InlinedFunctionsIterator it(code, pc); !it.Done();
1709 it.Advance()) {
1710 inlined_code = it.code();
1711 stack_trace->AddAsyncCausalFrame(pc, inlined_code);
1712 }
1713 } else {
1714 stack_trace->AddAsyncCausalFrame(pc, code);
1715 }
1716 }
1717 }
1718 // Follow the link.
1719 async_stack_trace = async_stack_trace.async_link();
1720 }
1721
1722 return stack_trace;
1723 }
1548 1724
1549 ActivationFrame* Debugger::TopDartFrame() const { 1725 ActivationFrame* Debugger::TopDartFrame() const {
1550 StackFrameIterator iterator(false); 1726 StackFrameIterator iterator(false);
1551 StackFrame* frame = iterator.NextFrame(); 1727 StackFrame* frame = iterator.NextFrame();
1552 while ((frame != NULL) && !frame->IsDartFrame()) { 1728 while ((frame != NULL) && !frame->IsDartFrame()) {
1553 frame = iterator.NextFrame(); 1729 frame = iterator.NextFrame();
1554 } 1730 }
1555 Code& code = Code::Handle(frame->LookupDartCode()); 1731 Code& code = Code::Handle(frame->LookupDartCode());
1556 ActivationFrame* activation = new ActivationFrame( 1732 ActivationFrame* activation = new ActivationFrame(
1557 frame->pc(), frame->fp(), frame->sp(), code, Object::null_array(), 0); 1733 frame->pc(), frame->fp(), frame->sp(), code, Object::null_array(), 0);
1558 return activation; 1734 return activation;
1559 } 1735 }
1560 1736
1561 1737
1562 DebuggerStackTrace* Debugger::StackTrace() { 1738 DebuggerStackTrace* Debugger::StackTrace() {
1563 return (stack_trace_ != NULL) ? stack_trace_ : CollectStackTrace(); 1739 return (stack_trace_ != NULL) ? stack_trace_ : CollectStackTrace();
1564 } 1740 }
1565 1741
1742
1566 DebuggerStackTrace* Debugger::CurrentStackTrace() { 1743 DebuggerStackTrace* Debugger::CurrentStackTrace() {
1567 return CollectStackTrace(); 1744 return CollectStackTrace();
1568 } 1745 }
1569 1746
1747
1748 DebuggerStackTrace* Debugger::AsyncCausalStackTrace() {
1749 return (async_causal_stack_trace_ != NULL) ? async_causal_stack_trace_
1750 : CollectAsyncCausalStackTrace();
1751 }
1752
1753
1754 DebuggerStackTrace* Debugger::CurrentAsyncCausalStackTrace() {
1755 return CollectAsyncCausalStackTrace();
1756 }
1757
1758
1570 DebuggerStackTrace* Debugger::StackTraceFrom(const class StackTrace& ex_trace) { 1759 DebuggerStackTrace* Debugger::StackTraceFrom(const class StackTrace& ex_trace) {
1571 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8); 1760 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
1572 Function& function = Function::Handle(); 1761 Function& function = Function::Handle();
1573 Code& code = Code::Handle(); 1762 Code& code = Code::Handle();
1574 1763
1575 const uword fp = 0; 1764 const uword fp = 0;
1576 const uword sp = 0; 1765 const uword sp = 0;
1577 const Array& deopt_frame = Array::Handle(); 1766 const Array& deopt_frame = Array::Handle();
1578 const intptr_t deopt_frame_offset = -1; 1767 const intptr_t deopt_frame_offset = -1;
1579 1768
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1660 } 1849 }
1661 DebuggerStackTrace* stack_trace = CollectStackTrace(); 1850 DebuggerStackTrace* stack_trace = CollectStackTrace();
1662 if (!ShouldPauseOnException(stack_trace, exc)) { 1851 if (!ShouldPauseOnException(stack_trace, exc)) {
1663 return; 1852 return;
1664 } 1853 }
1665 ServiceEvent event(isolate_, ServiceEvent::kPauseException); 1854 ServiceEvent event(isolate_, ServiceEvent::kPauseException);
1666 event.set_exception(&exc); 1855 event.set_exception(&exc);
1667 if (stack_trace->Length() > 0) { 1856 if (stack_trace->Length() > 0) {
1668 event.set_top_frame(stack_trace->FrameAt(0)); 1857 event.set_top_frame(stack_trace->FrameAt(0));
1669 } 1858 }
1670 ASSERT(stack_trace_ == NULL); 1859 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace());
1671 stack_trace_ = stack_trace;
1672 Pause(&event); 1860 Pause(&event);
1673 HandleSteppingRequest(stack_trace_); // we may get a rewind request 1861 HandleSteppingRequest(stack_trace_); // we may get a rewind request
1674 stack_trace_ = NULL; 1862 ClearCachedStackTraces();
1675 } 1863 }
1676 1864
1677 1865
1678 static TokenPosition LastTokenOnLine(Zone* zone, 1866 static TokenPosition LastTokenOnLine(Zone* zone,
1679 const TokenStream& tokens, 1867 const TokenStream& tokens,
1680 TokenPosition pos) { 1868 TokenPosition pos) {
1681 TokenStream::Iterator iter(zone, tokens, pos, 1869 TokenStream::Iterator iter(zone, tokens, pos,
1682 TokenStream::Iterator::kAllTokens); 1870 TokenStream::Iterator::kAllTokens);
1683 ASSERT(iter.IsValid()); 1871 ASSERT(iter.IsValid());
1684 TokenPosition last_pos = pos; 1872 TokenPosition last_pos = pos;
(...skipping 976 matching lines...) Expand 10 before | Expand all | Expand 10 after
2661 OS::PrintErr("#%04" Pd " %s\n", num++, frame->ToCString()); 2849 OS::PrintErr("#%04" Pd " %s\n", num++, frame->ToCString());
2662 frame = iterator.NextFrame(); 2850 frame = iterator.NextFrame();
2663 } 2851 }
2664 } 2852 }
2665 RewindToFrame(resume_frame_index_); 2853 RewindToFrame(resume_frame_index_);
2666 UNREACHABLE(); 2854 UNREACHABLE();
2667 } 2855 }
2668 } 2856 }
2669 2857
2670 2858
2859 void Debugger::CacheStackTraces(DebuggerStackTrace* stack_trace,
2860 DebuggerStackTrace* async_causal_stack_trace) {
2861 ASSERT(stack_trace_ == NULL);
2862 stack_trace_ = stack_trace;
2863 ASSERT(async_causal_stack_trace_ == NULL);
2864 async_causal_stack_trace_ = async_causal_stack_trace;
2865 }
2866
2867
2868 void Debugger::ClearCachedStackTraces() {
2869 stack_trace_ = NULL;
2870 async_causal_stack_trace_ = NULL;
2871 }
2872
2873
2671 static intptr_t FindNextRewindFrameIndex(DebuggerStackTrace* stack, 2874 static intptr_t FindNextRewindFrameIndex(DebuggerStackTrace* stack,
2672 intptr_t frame_index) { 2875 intptr_t frame_index) {
2673 for (intptr_t i = frame_index + 1; i < stack->Length(); i++) { 2876 for (intptr_t i = frame_index + 1; i < stack->Length(); i++) {
2674 ActivationFrame* frame = stack->FrameAt(i); 2877 ActivationFrame* frame = stack->FrameAt(i);
2675 if (frame->IsRewindable()) { 2878 if (frame->IsRewindable()) {
2676 return i; 2879 return i;
2677 } 2880 }
2678 } 2881 }
2679 return -1; 2882 return -1;
2680 } 2883 }
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
2789 } 2992 }
2790 } 2993 }
2791 } 2994 }
2792 UNIMPLEMENTED(); 2995 UNIMPLEMENTED();
2793 } 2996 }
2794 2997
2795 2998
2796 void Debugger::RewindToUnoptimizedFrame(StackFrame* frame, const Code& code) { 2999 void Debugger::RewindToUnoptimizedFrame(StackFrame* frame, const Code& code) {
2797 // We will be jumping out of the debugger rather than exiting this 3000 // We will be jumping out of the debugger rather than exiting this
2798 // function, so prepare the debugger state. 3001 // function, so prepare the debugger state.
2799 stack_trace_ = NULL; 3002 ClearCachedStackTraces();
2800 resume_action_ = kContinue; 3003 resume_action_ = kContinue;
2801 resume_frame_index_ = -1; 3004 resume_frame_index_ = -1;
2802 EnterSingleStepMode(); 3005 EnterSingleStepMode();
2803 3006
2804 uword rewind_pc = LookupRewindPc(code, frame->pc()); 3007 uword rewind_pc = LookupRewindPc(code, frame->pc());
2805 if (FLAG_trace_rewind && rewind_pc == 0) { 3008 if (FLAG_trace_rewind && rewind_pc == 0) {
2806 OS::PrintErr("Unable to find rewind pc for pc(%" Px ")\n", frame->pc()); 3009 OS::PrintErr("Unable to find rewind pc for pc(%" Px ")\n", frame->pc());
2807 } 3010 }
2808 ASSERT(rewind_pc != 0); 3011 ASSERT(rewind_pc != 0);
2809 if (FLAG_trace_rewind) { 3012 if (FLAG_trace_rewind) {
(...skipping 11 matching lines...) Expand all
2821 } 3024 }
2822 3025
2823 3026
2824 void Debugger::RewindToOptimizedFrame(StackFrame* frame, 3027 void Debugger::RewindToOptimizedFrame(StackFrame* frame,
2825 const Code& optimized_code, 3028 const Code& optimized_code,
2826 intptr_t sub_index) { 3029 intptr_t sub_index) {
2827 post_deopt_frame_index_ = sub_index; 3030 post_deopt_frame_index_ = sub_index;
2828 3031
2829 // We will be jumping out of the debugger rather than exiting this 3032 // We will be jumping out of the debugger rather than exiting this
2830 // function, so prepare the debugger state. 3033 // function, so prepare the debugger state.
2831 stack_trace_ = NULL; 3034 ClearCachedStackTraces();
2832 resume_action_ = kContinue; 3035 resume_action_ = kContinue;
2833 resume_frame_index_ = -1; 3036 resume_frame_index_ = -1;
2834 EnterSingleStepMode(); 3037 EnterSingleStepMode();
2835 3038
2836 if (FLAG_trace_rewind) { 3039 if (FLAG_trace_rewind) {
2837 OS::PrintErr( 3040 OS::PrintErr(
2838 "===============================\n" 3041 "===============================\n"
2839 "Deoptimizing frame for rewind:\n" 3042 "Deoptimizing frame for rewind:\n"
2840 " deopt_pc(0x%" Px ") sp(0x%" Px ") fp(0x%" Px 3043 " deopt_pc(0x%" Px ") sp(0x%" Px ") fp(0x%" Px
2841 ")\n" 3044 ")\n"
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
2997 ASSERT(!HasActiveBreakpoint(frame->pc())); 3200 ASSERT(!HasActiveBreakpoint(frame->pc()));
2998 3201
2999 if (FLAG_verbose_debug) { 3202 if (FLAG_verbose_debug) {
3000 OS::Print(">>> single step break at %s:%" Pd " (func %s token %s)\n", 3203 OS::Print(">>> single step break at %s:%" Pd " (func %s token %s)\n",
3001 String::Handle(frame->SourceUrl()).ToCString(), 3204 String::Handle(frame->SourceUrl()).ToCString(),
3002 frame->LineNumber(), 3205 frame->LineNumber(),
3003 String::Handle(frame->QualifiedFunctionName()).ToCString(), 3206 String::Handle(frame->QualifiedFunctionName()).ToCString(),
3004 frame->TokenPos().ToCString()); 3207 frame->TokenPos().ToCString());
3005 } 3208 }
3006 3209
3007 ASSERT(stack_trace_ == NULL); 3210
3008 stack_trace_ = CollectStackTrace(); 3211 CacheStackTraces(CollectStackTrace(), CollectAsyncCausalStackTrace());
3009 // If this step callback is part of stepping over an await statement, 3212 // If this step callback is part of stepping over an await statement,
3010 // we saved the synthetic async breakpoint in PauseBreakpoint. We report 3213 // we saved the synthetic async breakpoint in PauseBreakpoint. We report
3011 // that we are paused at that breakpoint and then delete it after continuing. 3214 // that we are paused at that breakpoint and then delete it after continuing.
3012 SignalPausedEvent(frame, synthetic_async_breakpoint_); 3215 SignalPausedEvent(frame, synthetic_async_breakpoint_);
3013 if (synthetic_async_breakpoint_ != NULL) { 3216 if (synthetic_async_breakpoint_ != NULL) {
3014 RemoveBreakpoint(synthetic_async_breakpoint_->id()); 3217 RemoveBreakpoint(synthetic_async_breakpoint_->id());
3015 synthetic_async_breakpoint_ = NULL; 3218 synthetic_async_breakpoint_ = NULL;
3016 } 3219 }
3017 HandleSteppingRequest(stack_trace_); 3220 HandleSteppingRequest(stack_trace_);
3018 stack_trace_ = NULL; 3221 ClearCachedStackTraces();
3019 3222
3020 // If any error occurred while in the debug message loop, return it here. 3223 // If any error occurred while in the debug message loop, return it here.
3021 const Error& error = Error::Handle(Thread::Current()->sticky_error()); 3224 const Error& error = Error::Handle(Thread::Current()->sticky_error());
3022 Thread::Current()->clear_sticky_error(); 3225 Thread::Current()->clear_sticky_error();
3023 return error.raw(); 3226 return error.raw();
3024 } 3227 }
3025 3228
3026 3229
3027 RawError* Debugger::PauseBreakpoint() { 3230 RawError* Debugger::PauseBreakpoint() {
3028 // We ignore this breakpoint when the VM is executing code invoked 3231 // We ignore this breakpoint when the VM is executing code invoked
3029 // by the debugger to evaluate variables values, or when we see a nested 3232 // by the debugger to evaluate variables values, or when we see a nested
3030 // breakpoint or exception event. 3233 // breakpoint or exception event.
3031 if (ignore_breakpoints_ || IsPaused()) { 3234 if (ignore_breakpoints_ || IsPaused()) {
3032 return Error::null(); 3235 return Error::null();
3033 } 3236 }
3034 DebuggerStackTrace* stack_trace = CollectStackTrace(); 3237 DebuggerStackTrace* stack_trace = CollectStackTrace();
3035 ASSERT(stack_trace->Length() > 0); 3238 ASSERT(stack_trace->Length() > 0);
3036 ActivationFrame* top_frame = stack_trace->FrameAt(0); 3239 ActivationFrame* top_frame = stack_trace->FrameAt(0);
3037 ASSERT(top_frame != NULL); 3240 ASSERT(top_frame != NULL);
3038 CodeBreakpoint* cbpt = GetCodeBreakpoint(top_frame->pc()); 3241 CodeBreakpoint* cbpt = GetCodeBreakpoint(top_frame->pc());
3039 ASSERT(cbpt != NULL); 3242 ASSERT(cbpt != NULL);
3040 3243
3041 BreakpointLocation* bpt_location = cbpt->bpt_location_; 3244 Breakpoint* bpt_hit = FindHitBreakpoint(cbpt->bpt_location_, top_frame);
3042 Breakpoint* bpt_hit = NULL;
3043
3044 // There may be more than one applicable breakpoint at this location, but we
3045 // will report only one as reached. If there is a single-shot breakpoint, we
3046 // favor it; then a closure-specific breakpoint ; then an general breakpoint.
3047 if (bpt_location != NULL) {
3048 Breakpoint* bpt = bpt_location->breakpoints();
3049 while (bpt != NULL) {
3050 if (bpt->IsSingleShot()) {
3051 bpt_hit = bpt;
3052 break;
3053 }
3054 bpt = bpt->next();
3055 }
3056
3057 if (bpt_hit == NULL) {
3058 bpt = bpt_location->breakpoints();
3059 while (bpt != NULL) {
3060 if (bpt->IsPerClosure()) {
3061 Object& closure = Object::Handle(top_frame->GetClosure());
3062 ASSERT(closure.IsInstance());
3063 ASSERT(Instance::Cast(closure).IsClosure());
3064 if (closure.raw() == bpt->closure()) {
3065 bpt_hit = bpt;
3066 break;
3067 }
3068 }
3069 bpt = bpt->next();
3070 }
3071 }
3072
3073 if (bpt_hit == NULL) {
3074 bpt = bpt_location->breakpoints();
3075 while (bpt != NULL) {
3076 if (bpt->IsRepeated()) {
3077 bpt_hit = bpt;
3078 break;
3079 }
3080 bpt = bpt->next();
3081 }
3082 }
3083 }
3084
3085 if (bpt_hit == NULL) { 3245 if (bpt_hit == NULL) {
3086 return Error::null(); 3246 return Error::null();
3087 } 3247 }
3088 3248
3089 if (bpt_hit->is_synthetic_async()) { 3249 if (bpt_hit->is_synthetic_async()) {
3090 DebuggerStackTrace* stack_trace = CollectStackTrace(); 3250 DebuggerStackTrace* stack_trace = CollectStackTrace();
3091 ASSERT(stack_trace->Length() > 0); 3251 ASSERT(stack_trace->Length() > 0);
3092 ASSERT(stack_trace_ == NULL); 3252 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace());
3093 stack_trace_ = stack_trace;
3094 3253
3095 // Hit a synthetic async breakpoint. 3254 // Hit a synthetic async breakpoint.
3096 if (FLAG_verbose_debug) { 3255 if (FLAG_verbose_debug) {
3097 OS::Print(">>> hit synthetic breakpoint at %s:%" Pd 3256 OS::Print(">>> hit synthetic breakpoint at %s:%" Pd
3098 " " 3257 " "
3099 "(token %s) (address %#" Px ")\n", 3258 "(token %s) (address %#" Px ")\n",
3100 String::Handle(cbpt->SourceUrl()).ToCString(), 3259 String::Handle(cbpt->SourceUrl()).ToCString(),
3101 cbpt->LineNumber(), cbpt->token_pos().ToCString(), 3260 cbpt->LineNumber(), cbpt->token_pos().ToCString(),
3102 top_frame->pc()); 3261 top_frame->pc());
3103 } 3262 }
3104 3263
3105 ASSERT(synthetic_async_breakpoint_ == NULL); 3264 ASSERT(synthetic_async_breakpoint_ == NULL);
3106 synthetic_async_breakpoint_ = bpt_hit; 3265 synthetic_async_breakpoint_ = bpt_hit;
3107 bpt_hit = NULL; 3266 bpt_hit = NULL;
3108 3267
3109 // We are at the entry of an async function. 3268 // We are at the entry of an async function.
3110 // We issue a step over to resume at the point after the await statement. 3269 // We issue a step over to resume at the point after the await statement.
3111 SetResumeAction(kStepOver); 3270 SetResumeAction(kStepOver);
3112 // When we single step from a user breakpoint, our next stepping 3271 // When we single step from a user breakpoint, our next stepping
3113 // point will be at the exact same pc. Skip it. 3272 // point will be at the exact same pc. Skip it.
3114 HandleSteppingRequest(stack_trace_, true /* skip next step */); 3273 HandleSteppingRequest(stack_trace_, true /* skip next step */);
3115 stack_trace_ = NULL; 3274 ClearCachedStackTraces();
3116 return Error::null(); 3275 return Error::null();
3117 } 3276 }
3118 3277
3119 if (FLAG_verbose_debug) { 3278 if (FLAG_verbose_debug) {
3120 OS::Print(">>> hit %s breakpoint at %s:%" Pd 3279 OS::Print(">>> hit %s breakpoint at %s:%" Pd
3121 " " 3280 " "
3122 "(token %s) (address %#" Px ")\n", 3281 "(token %s) (address %#" Px ")\n",
3123 cbpt->IsInternal() ? "internal" : "user", 3282 cbpt->IsInternal() ? "internal" : "user",
3124 String::Handle(cbpt->SourceUrl()).ToCString(), cbpt->LineNumber(), 3283 String::Handle(cbpt->SourceUrl()).ToCString(), cbpt->LineNumber(),
3125 cbpt->token_pos().ToCString(), top_frame->pc()); 3284 cbpt->token_pos().ToCString(), top_frame->pc());
3126 } 3285 }
3127 3286
3128 ASSERT(stack_trace_ == NULL); 3287 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace());
3129 stack_trace_ = stack_trace;
3130 SignalPausedEvent(top_frame, bpt_hit); 3288 SignalPausedEvent(top_frame, bpt_hit);
3131 // When we single step from a user breakpoint, our next stepping 3289 // When we single step from a user breakpoint, our next stepping
3132 // point will be at the exact same pc. Skip it. 3290 // point will be at the exact same pc. Skip it.
3133 HandleSteppingRequest(stack_trace_, true /* skip next step */); 3291 HandleSteppingRequest(stack_trace_, true /* skip next step */);
3134 stack_trace_ = NULL; 3292 ClearCachedStackTraces();
3135 if (cbpt->IsInternal()) { 3293 if (cbpt->IsInternal()) {
3136 RemoveInternalBreakpoints(); 3294 RemoveInternalBreakpoints();
3137 } 3295 }
3138 3296
3139 // If any error occurred while in the debug message loop, return it here. 3297 // If any error occurred while in the debug message loop, return it here.
3140 const Error& error = Error::Handle(Thread::Current()->sticky_error()); 3298 const Error& error = Error::Handle(Thread::Current()->sticky_error());
3141 Thread::Current()->clear_sticky_error(); 3299 Thread::Current()->clear_sticky_error();
3142 return error.raw(); 3300 return error.raw();
3143 } 3301 }
3144 3302
3145 3303
3304 Breakpoint* Debugger::FindHitBreakpoint(BreakpointLocation* location,
3305 ActivationFrame* top_frame) {
3306 if (location == NULL) {
3307 return NULL;
3308 }
3309 // There may be more than one applicable breakpoint at this location, but we
3310 // will report only one as reached. If there is a single-shot breakpoint, we
3311 // favor it; then a closure-specific breakpoint ; then an general breakpoint.
3312
3313 // First check for a single-shot breakpoint.
3314 Breakpoint* bpt = location->breakpoints();
3315 while (bpt != NULL) {
3316 if (bpt->IsSingleShot()) {
3317 return bpt;
3318 }
3319 bpt = bpt->next();
3320 }
3321
3322 // Now check for a closure-specific breakpoint.
3323 bpt = location->breakpoints();
3324 while (bpt != NULL) {
3325 if (bpt->IsPerClosure()) {
3326 Object& closure = Object::Handle(top_frame->GetClosure());
3327 ASSERT(closure.IsInstance());
3328 ASSERT(Instance::Cast(closure).IsClosure());
3329 if (closure.raw() == bpt->closure()) {
3330 return bpt;
3331 }
3332 }
3333 bpt = bpt->next();
3334 }
3335
3336 // Finally, check for a general breakpoint.
3337 bpt = location->breakpoints();
3338 while (bpt != NULL) {
3339 if (bpt->IsRepeated()) {
3340 return bpt;
3341 }
3342 bpt = bpt->next();
3343 }
3344
3345 return NULL;
3346 }
3347
3348
3146 void Debugger::PauseDeveloper(const String& msg) { 3349 void Debugger::PauseDeveloper(const String& msg) {
3147 // We ignore this breakpoint when the VM is executing code invoked 3350 // We ignore this breakpoint when the VM is executing code invoked
3148 // by the debugger to evaluate variables values, or when we see a nested 3351 // by the debugger to evaluate variables values, or when we see a nested
3149 // breakpoint or exception event. 3352 // breakpoint or exception event.
3150 if (ignore_breakpoints_ || IsPaused()) { 3353 if (ignore_breakpoints_ || IsPaused()) {
3151 return; 3354 return;
3152 } 3355 }
3153 3356
3154 DebuggerStackTrace* stack_trace = CollectStackTrace(); 3357 DebuggerStackTrace* stack_trace = CollectStackTrace();
3155 ASSERT(stack_trace->Length() > 0); 3358 ASSERT(stack_trace->Length() > 0);
3156 ASSERT(stack_trace_ == NULL); 3359 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace());
3157 stack_trace_ = stack_trace;
3158
3159 // TODO(johnmccutchan): Send |msg| to Observatory. 3360 // TODO(johnmccutchan): Send |msg| to Observatory.
3160 3361
3161 // We are in the native call to Developer_debugger. the developer 3362 // We are in the native call to Developer_debugger. the developer
3162 // gets a better experience by not seeing this call. To accomplish 3363 // gets a better experience by not seeing this call. To accomplish
3163 // this, we continue execution until the call exits (step out). 3364 // this, we continue execution until the call exits (step out).
3164 SetResumeAction(kStepOut); 3365 SetResumeAction(kStepOut);
3165 HandleSteppingRequest(stack_trace_); 3366 HandleSteppingRequest(stack_trace_);
3166 3367 ClearCachedStackTraces();
3167 stack_trace_ = NULL;
3168 } 3368 }
3169 3369
3170 3370
3171 void Debugger::Initialize(Isolate* isolate) { 3371 void Debugger::Initialize(Isolate* isolate) {
3172 if (initialized_) { 3372 if (initialized_) {
3173 return; 3373 return;
3174 } 3374 }
3175 isolate_ = isolate; 3375 isolate_ = isolate;
3176 3376
3177 // Use the isolate's control port as the isolate_id for debugging. 3377 // Use the isolate's control port as the isolate_id for debugging.
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after
3607 3807
3608 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { 3808 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
3609 ASSERT(bpt->next() == NULL); 3809 ASSERT(bpt->next() == NULL);
3610 bpt->set_next(code_breakpoints_); 3810 bpt->set_next(code_breakpoints_);
3611 code_breakpoints_ = bpt; 3811 code_breakpoints_ = bpt;
3612 } 3812 }
3613 3813
3614 #endif // !PRODUCT 3814 #endif // !PRODUCT
3615 3815
3616 } // namespace dart 3816 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/exceptions.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698