OLD | NEW |
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 |
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 if (ignore_breakpoints_ || IsPaused()) { | 370 if (ignore_breakpoints_ || IsPaused()) { |
371 // We don't let the isolate get interrupted if we are already | 371 // We don't let the isolate get interrupted if we are already |
372 // paused or ignoring breakpoints. | 372 // paused or ignoring breakpoints. |
373 return Error::null(); | 373 return Error::null(); |
374 } | 374 } |
375 ServiceEvent event(isolate_, kind); | 375 ServiceEvent event(isolate_, kind); |
376 DebuggerStackTrace* trace = CollectStackTrace(); | 376 DebuggerStackTrace* trace = CollectStackTrace(); |
377 if (trace->Length() > 0) { | 377 if (trace->Length() > 0) { |
378 event.set_top_frame(trace->FrameAt(0)); | 378 event.set_top_frame(trace->FrameAt(0)); |
379 } | 379 } |
380 CacheStackTraces(trace, CollectAsyncCausalStackTrace()); | 380 CacheStackTraces(trace, CollectAsyncCausalStackTrace(), |
| 381 CollectAwaiterReturnStackTrace()); |
381 resume_action_ = kContinue; | 382 resume_action_ = kContinue; |
382 Pause(&event); | 383 Pause(&event); |
383 HandleSteppingRequest(trace); | 384 HandleSteppingRequest(trace); |
384 ClearCachedStackTraces(); | 385 ClearCachedStackTraces(); |
385 | 386 |
386 // If any error occurred while in the debug message loop, return it here. | 387 // If any error occurred while in the debug message loop, return it here. |
387 const Error& error = Error::Handle(Thread::Current()->sticky_error()); | 388 const Error& error = Error::Handle(Thread::Current()->sticky_error()); |
388 ASSERT(error.IsNull() || error.IsUnwindError()); | 389 ASSERT(error.IsNull() || error.IsUnwindError()); |
389 Thread::Current()->clear_sticky_error(); | 390 Thread::Current()->clear_sticky_error(); |
390 return error.raw(); | 391 return error.raw(); |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
706 } | 707 } |
707 } | 708 } |
708 } | 709 } |
709 ASSERT(context_level_ >= 0); | 710 ASSERT(context_level_ >= 0); |
710 } | 711 } |
711 return context_level_; | 712 return context_level_; |
712 } | 713 } |
713 | 714 |
714 | 715 |
715 RawObject* ActivationFrame::GetAsyncContextVariable(const String& name) { | 716 RawObject* ActivationFrame::GetAsyncContextVariable(const String& name) { |
716 if (!function_.IsAsyncClosure()) { | 717 if (!function_.IsAsyncClosure() && !function_.IsAsyncGenClosure()) { |
717 return Object::null(); | 718 return Object::null(); |
718 } | 719 } |
719 GetVarDescriptors(); | 720 GetVarDescriptors(); |
720 intptr_t var_desc_len = var_descriptors_.Length(); | 721 intptr_t var_desc_len = var_descriptors_.Length(); |
721 for (intptr_t i = 0; i < var_desc_len; i++) { | 722 for (intptr_t i = 0; i < var_desc_len; i++) { |
722 RawLocalVarDescriptors::VarInfo var_info; | 723 RawLocalVarDescriptors::VarInfo var_info; |
723 var_descriptors_.GetInfo(i, &var_info); | 724 var_descriptors_.GetInfo(i, &var_info); |
724 if (var_descriptors_.GetName(i) == name.raw()) { | 725 if (var_descriptors_.GetName(i) == name.raw()) { |
725 const int8_t kind = var_info.kind(); | 726 const int8_t kind = var_info.kind(); |
726 if (!live_frame_) { | 727 if (!live_frame_) { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
792 const Object& async_stream_controller_stream = | 793 const Object& async_stream_controller_stream = |
793 Object::Handle(GetAsyncStreamControllerStream()); | 794 Object::Handle(GetAsyncStreamControllerStream()); |
794 if (!async_stream_controller_stream.IsNull()) { | 795 if (!async_stream_controller_stream.IsNull()) { |
795 return GetAsyncStreamControllerStreamAwaiter( | 796 return GetAsyncStreamControllerStreamAwaiter( |
796 async_stream_controller_stream); | 797 async_stream_controller_stream); |
797 } | 798 } |
798 return Object::null(); | 799 return Object::null(); |
799 } | 800 } |
800 | 801 |
801 | 802 |
| 803 RawObject* ActivationFrame::GetCausalStack() { |
| 804 return GetAsyncContextVariable(Symbols::AsyncStackTraceVar()); |
| 805 } |
| 806 |
| 807 |
802 bool ActivationFrame::HandlesException(const Instance& exc_obj) { | 808 bool ActivationFrame::HandlesException(const Instance& exc_obj) { |
803 intptr_t try_index = TryIndex(); | 809 intptr_t try_index = TryIndex(); |
804 if (try_index < 0) { | 810 if (try_index < 0) { |
805 return false; | 811 return false; |
806 } | 812 } |
807 ExceptionHandlers& handlers = ExceptionHandlers::Handle(); | 813 ExceptionHandlers& handlers = ExceptionHandlers::Handle(); |
808 Array& handled_types = Array::Handle(); | 814 Array& handled_types = Array::Handle(); |
809 AbstractType& type = Type::Handle(); | 815 AbstractType& type = Type::Handle(); |
810 const bool is_async = | 816 const bool is_async = |
811 function().IsAsyncClosure() || function().IsAsyncGenClosure(); | 817 function().IsAsyncClosure() || function().IsAsyncGenClosure(); |
(...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1302 } | 1308 } |
1303 | 1309 |
1304 | 1310 |
1305 void ActivationFrame::PrintToJSONObject(JSONObject* jsobj, bool full) { | 1311 void ActivationFrame::PrintToJSONObject(JSONObject* jsobj, bool full) { |
1306 if (kind_ == kRegular) { | 1312 if (kind_ == kRegular) { |
1307 PrintToJSONObjectRegular(jsobj, full); | 1313 PrintToJSONObjectRegular(jsobj, full); |
1308 } else if (kind_ == kAsyncCausal) { | 1314 } else if (kind_ == kAsyncCausal) { |
1309 PrintToJSONObjectAsyncCausal(jsobj, full); | 1315 PrintToJSONObjectAsyncCausal(jsobj, full); |
1310 } else if (kind_ == kAsyncSuspensionMarker) { | 1316 } else if (kind_ == kAsyncSuspensionMarker) { |
1311 PrintToJSONObjectAsyncSuspensionMarker(jsobj, full); | 1317 PrintToJSONObjectAsyncSuspensionMarker(jsobj, full); |
| 1318 } else if (kind_ == kAsyncActivation) { |
| 1319 PrintToJSONObjectAsyncActivation(jsobj, full); |
1312 } else { | 1320 } else { |
1313 UNIMPLEMENTED(); | 1321 UNIMPLEMENTED(); |
1314 } | 1322 } |
1315 } | 1323 } |
1316 | 1324 |
1317 | 1325 |
1318 void ActivationFrame::PrintToJSONObjectRegular(JSONObject* jsobj, bool full) { | 1326 void ActivationFrame::PrintToJSONObjectRegular(JSONObject* jsobj, bool full) { |
1319 const Script& script = Script::Handle(SourceScript()); | 1327 const Script& script = Script::Handle(SourceScript()); |
1320 jsobj->AddProperty("type", "Frame"); | 1328 jsobj->AddProperty("type", "Frame"); |
1321 jsobj->AddProperty("kind", KindToCString(kind_)); | 1329 jsobj->AddProperty("kind", KindToCString(kind_)); |
(...skipping 14 matching lines...) Expand all Loading... |
1336 String& var_name = String::Handle(); | 1344 String& var_name = String::Handle(); |
1337 Instance& var_value = Instance::Handle(); | 1345 Instance& var_value = Instance::Handle(); |
1338 TokenPosition declaration_token_pos; | 1346 TokenPosition declaration_token_pos; |
1339 TokenPosition visible_start_token_pos; | 1347 TokenPosition visible_start_token_pos; |
1340 TokenPosition visible_end_token_pos; | 1348 TokenPosition visible_end_token_pos; |
1341 VariableAt(v, &var_name, &declaration_token_pos, &visible_start_token_pos, | 1349 VariableAt(v, &var_name, &declaration_token_pos, &visible_start_token_pos, |
1342 &visible_end_token_pos, &var_value); | 1350 &visible_end_token_pos, &var_value); |
1343 if ((var_name.raw() != Symbols::AsyncOperation().raw()) && | 1351 if ((var_name.raw() != Symbols::AsyncOperation().raw()) && |
1344 (var_name.raw() != Symbols::AsyncCompleter().raw()) && | 1352 (var_name.raw() != Symbols::AsyncCompleter().raw()) && |
1345 (var_name.raw() != Symbols::ControllerStream().raw()) && | 1353 (var_name.raw() != Symbols::ControllerStream().raw()) && |
1346 (var_name.raw() != Symbols::AwaitJumpVar().raw())) { | 1354 (var_name.raw() != Symbols::AwaitJumpVar().raw()) && |
| 1355 (var_name.raw() != Symbols::AsyncStackTraceVar().raw())) { |
1347 JSONObject jsvar(&jsvars); | 1356 JSONObject jsvar(&jsvars); |
1348 jsvar.AddProperty("type", "BoundVariable"); | 1357 jsvar.AddProperty("type", "BoundVariable"); |
1349 var_name = String::ScrubName(var_name); | 1358 var_name = String::ScrubName(var_name); |
1350 jsvar.AddProperty("name", var_name.ToCString()); | 1359 jsvar.AddProperty("name", var_name.ToCString()); |
1351 jsvar.AddProperty("value", var_value, !full); | 1360 jsvar.AddProperty("value", var_value, !full); |
1352 // Where was the variable declared? | 1361 // Where was the variable declared? |
1353 jsvar.AddProperty("declarationTokenPos", declaration_token_pos); | 1362 jsvar.AddProperty("declarationTokenPos", declaration_token_pos); |
1354 // When the variable becomes visible to the scope. | 1363 // When the variable becomes visible to the scope. |
1355 jsvar.AddProperty("scopeStartTokenPos", visible_start_token_pos); | 1364 jsvar.AddProperty("scopeStartTokenPos", visible_start_token_pos); |
1356 // When the variable stops being visible to the scope. | 1365 // When the variable stops being visible to the scope. |
(...skipping 23 matching lines...) Expand all Loading... |
1380 | 1389 |
1381 | 1390 |
1382 void ActivationFrame::PrintToJSONObjectAsyncSuspensionMarker(JSONObject* jsobj, | 1391 void ActivationFrame::PrintToJSONObjectAsyncSuspensionMarker(JSONObject* jsobj, |
1383 bool full) { | 1392 bool full) { |
1384 jsobj->AddProperty("type", "Frame"); | 1393 jsobj->AddProperty("type", "Frame"); |
1385 jsobj->AddProperty("kind", KindToCString(kind_)); | 1394 jsobj->AddProperty("kind", KindToCString(kind_)); |
1386 jsobj->AddProperty("marker", "AsynchronousSuspension"); | 1395 jsobj->AddProperty("marker", "AsynchronousSuspension"); |
1387 } | 1396 } |
1388 | 1397 |
1389 | 1398 |
| 1399 void ActivationFrame::PrintToJSONObjectAsyncActivation(JSONObject* jsobj, |
| 1400 bool full) { |
| 1401 jsobj->AddProperty("type", "Frame"); |
| 1402 jsobj->AddProperty("kind", KindToCString(kind_)); |
| 1403 const Script& script = Script::Handle(SourceScript()); |
| 1404 const TokenPosition pos = TokenPos().SourcePosition(); |
| 1405 jsobj->AddLocation(script, pos); |
| 1406 jsobj->AddProperty("function", function(), !full); |
| 1407 jsobj->AddProperty("code", code()); |
| 1408 if (full) { |
| 1409 // TODO(cutch): The old "full" script usage no longer fits |
| 1410 // in the world where we pass the script as part of the |
| 1411 // location. |
| 1412 jsobj->AddProperty("script", script, !full); |
| 1413 } |
| 1414 } |
| 1415 |
| 1416 |
1390 static bool IsFunctionVisible(const Function& function) { | 1417 static bool IsFunctionVisible(const Function& function) { |
1391 return FLAG_show_invisible_frames || function.is_visible(); | 1418 return FLAG_show_invisible_frames || function.is_visible(); |
1392 } | 1419 } |
1393 | 1420 |
1394 | 1421 |
1395 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) { | 1422 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) { |
1396 if (IsFunctionVisible(frame->function())) { | 1423 if (IsFunctionVisible(frame->function())) { |
1397 trace_.Add(frame); | 1424 trace_.Add(frame); |
1398 } | 1425 } |
1399 } | 1426 } |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1533 breakpoint_locations_(NULL), | 1560 breakpoint_locations_(NULL), |
1534 code_breakpoints_(NULL), | 1561 code_breakpoints_(NULL), |
1535 resume_action_(kContinue), | 1562 resume_action_(kContinue), |
1536 resume_frame_index_(-1), | 1563 resume_frame_index_(-1), |
1537 post_deopt_frame_index_(-1), | 1564 post_deopt_frame_index_(-1), |
1538 ignore_breakpoints_(false), | 1565 ignore_breakpoints_(false), |
1539 pause_event_(NULL), | 1566 pause_event_(NULL), |
1540 obj_cache_(NULL), | 1567 obj_cache_(NULL), |
1541 stack_trace_(NULL), | 1568 stack_trace_(NULL), |
1542 async_causal_stack_trace_(NULL), | 1569 async_causal_stack_trace_(NULL), |
| 1570 awaiter_stack_trace_(NULL), |
1543 stepping_fp_(0), | 1571 stepping_fp_(0), |
1544 skip_next_step_(false), | 1572 skip_next_step_(false), |
1545 needs_breakpoint_cleanup_(false), | 1573 needs_breakpoint_cleanup_(false), |
1546 synthetic_async_breakpoint_(NULL), | 1574 synthetic_async_breakpoint_(NULL), |
1547 exc_pause_info_(kNoPauseOnExceptions) {} | 1575 exc_pause_info_(kNoPauseOnExceptions) {} |
1548 | 1576 |
1549 | 1577 |
1550 Debugger::~Debugger() { | 1578 Debugger::~Debugger() { |
1551 isolate_id_ = ILLEGAL_ISOLATE_ID; | 1579 isolate_id_ = ILLEGAL_ISOLATE_ID; |
1552 ASSERT(!IsPaused()); | 1580 ASSERT(!IsPaused()); |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1930 ASSERT(!FLAG_precompiled_runtime); | 1958 ASSERT(!FLAG_precompiled_runtime); |
1931 | 1959 |
1932 Thread* thread = Thread::Current(); | 1960 Thread* thread = Thread::Current(); |
1933 Zone* zone = thread->zone(); | 1961 Zone* zone = thread->zone(); |
1934 Isolate* isolate = thread->isolate(); | 1962 Isolate* isolate = thread->isolate(); |
1935 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8); | 1963 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8); |
1936 | 1964 |
1937 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames); | 1965 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames); |
1938 | 1966 |
1939 Code& code = Code::Handle(zone); | 1967 Code& code = Code::Handle(zone); |
| 1968 Smi& offset = Smi::Handle(zone); |
1940 Function& function = Function::Handle(zone); | 1969 Function& function = Function::Handle(zone); |
1941 Code& inlined_code = Code::Handle(zone); | 1970 Code& inlined_code = Code::Handle(zone); |
1942 Closure& async_activation = Closure::Handle(zone); | 1971 Closure& async_activation = Closure::Handle(zone); |
| 1972 Object& next_async_activation = Object::Handle(zone); |
1943 Array& deopt_frame = Array::Handle(zone); | 1973 Array& deopt_frame = Array::Handle(zone); |
| 1974 class StackTrace& async_stack_trace = StackTrace::Handle(zone); |
1944 | 1975 |
1945 for (StackFrame* frame = iterator.NextFrame(); frame != NULL; | 1976 for (StackFrame* frame = iterator.NextFrame(); frame != NULL; |
1946 frame = iterator.NextFrame()) { | 1977 frame = iterator.NextFrame()) { |
1947 ASSERT(frame->IsValid()); | 1978 ASSERT(frame->IsValid()); |
1948 if (FLAG_trace_debugger_stacktrace) { | 1979 if (FLAG_trace_debugger_stacktrace) { |
1949 OS::PrintErr("CollectStackTrace: visiting frame:\n\t%s\n", | 1980 OS::PrintErr("CollectStackTrace: visiting frame:\n\t%s\n", |
1950 frame->ToCString()); | 1981 frame->ToCString()); |
1951 } | 1982 } |
1952 if (frame->IsDartFrame()) { | 1983 if (frame->IsDartFrame()) { |
1953 code = frame->LookupDartCode(); | 1984 code = frame->LookupDartCode(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2004 } | 2035 } |
2005 | 2036 |
2006 // Return NULL to indicate that there is no useful information in this stack | 2037 // Return NULL to indicate that there is no useful information in this stack |
2007 // trace because we never found an awaiter. | 2038 // trace because we never found an awaiter. |
2008 if (async_activation.IsNull()) { | 2039 if (async_activation.IsNull()) { |
2009 return NULL; | 2040 return NULL; |
2010 } | 2041 } |
2011 | 2042 |
2012 // Append the awaiter return call stack. | 2043 // Append the awaiter return call stack. |
2013 while (!async_activation.IsNull()) { | 2044 while (!async_activation.IsNull()) { |
2014 ActivationFrame* activation = new ActivationFrame(async_activation); | 2045 ActivationFrame* activation = new (zone) ActivationFrame(async_activation); |
2015 async_activation ^= activation->GetAsyncAwaiter(); | |
2016 activation->ExtractTokenPositionFromAsyncClosure(); | 2046 activation->ExtractTokenPositionFromAsyncClosure(); |
2017 stack_trace->AddActivation(activation); | 2047 stack_trace->AddActivation(activation); |
| 2048 next_async_activation = activation->GetAsyncAwaiter(); |
| 2049 if (next_async_activation.IsNull()) { |
| 2050 // No more awaiters. Extract the causal stack trace (if it exists). |
| 2051 async_stack_trace ^= activation->GetCausalStack(); |
| 2052 break; |
| 2053 } |
| 2054 async_activation = Closure::RawCast(next_async_activation.raw()); |
| 2055 } |
| 2056 |
| 2057 // Now we append the asynchronous causal stack trace. These are not active |
| 2058 // frames but a historical record of how this asynchronous function was |
| 2059 // activated. |
| 2060 while (!async_stack_trace.IsNull()) { |
| 2061 for (intptr_t i = 0; i < async_stack_trace.Length(); i++) { |
| 2062 if (async_stack_trace.CodeAtFrame(i) == Code::null()) { |
| 2063 // Incomplete OutOfMemory/StackOverflow trace OR array padding. |
| 2064 break; |
| 2065 } |
| 2066 if (async_stack_trace.CodeAtFrame(i) == |
| 2067 StubCode::AsynchronousGapMarker_entry()->code()) { |
| 2068 stack_trace->AddMarker(ActivationFrame::kAsyncSuspensionMarker); |
| 2069 // The frame immediately below the asynchronous gap marker is the |
| 2070 // identical to the frame above the marker. Skip the frame to enhance |
| 2071 // the readability of the trace. |
| 2072 i++; |
| 2073 } else { |
| 2074 code = Code::RawCast(async_stack_trace.CodeAtFrame(i)); |
| 2075 offset = Smi::RawCast(async_stack_trace.PcOffsetAtFrame(i)); |
| 2076 uword pc = code.PayloadStart() + offset.Value(); |
| 2077 if (code.is_optimized()) { |
| 2078 for (InlinedFunctionsIterator it(code, pc); !it.Done(); |
| 2079 it.Advance()) { |
| 2080 inlined_code = it.code(); |
| 2081 stack_trace->AddAsyncCausalFrame(it.pc(), inlined_code); |
| 2082 } |
| 2083 } else { |
| 2084 stack_trace->AddAsyncCausalFrame(pc, code); |
| 2085 } |
| 2086 } |
| 2087 } |
| 2088 // Follow the link. |
| 2089 async_stack_trace = async_stack_trace.async_link(); |
2018 } | 2090 } |
2019 | 2091 |
2020 return stack_trace; | 2092 return stack_trace; |
2021 } | 2093 } |
2022 | 2094 |
2023 | 2095 |
2024 ActivationFrame* Debugger::TopDartFrame() const { | 2096 ActivationFrame* Debugger::TopDartFrame() const { |
2025 StackFrameIterator iterator(false); | 2097 StackFrameIterator iterator(false); |
2026 StackFrame* frame = iterator.NextFrame(); | 2098 StackFrame* frame = iterator.NextFrame(); |
2027 while ((frame != NULL) && !frame->IsDartFrame()) { | 2099 while ((frame != NULL) && !frame->IsDartFrame()) { |
(...skipping 20 matching lines...) Expand all Loading... |
2048 return (async_causal_stack_trace_ != NULL) ? async_causal_stack_trace_ | 2120 return (async_causal_stack_trace_ != NULL) ? async_causal_stack_trace_ |
2049 : CollectAsyncCausalStackTrace(); | 2121 : CollectAsyncCausalStackTrace(); |
2050 } | 2122 } |
2051 | 2123 |
2052 | 2124 |
2053 DebuggerStackTrace* Debugger::CurrentAsyncCausalStackTrace() { | 2125 DebuggerStackTrace* Debugger::CurrentAsyncCausalStackTrace() { |
2054 return CollectAsyncCausalStackTrace(); | 2126 return CollectAsyncCausalStackTrace(); |
2055 } | 2127 } |
2056 | 2128 |
2057 | 2129 |
| 2130 DebuggerStackTrace* Debugger::AwaiterStackTrace() { |
| 2131 return (awaiter_stack_trace_ != NULL) ? awaiter_stack_trace_ |
| 2132 : CollectAwaiterReturnStackTrace(); |
| 2133 } |
| 2134 |
| 2135 |
| 2136 DebuggerStackTrace* Debugger::CurrentAwaiterStackTrace() { |
| 2137 return CollectAwaiterReturnStackTrace(); |
| 2138 } |
| 2139 |
| 2140 |
2058 DebuggerStackTrace* Debugger::StackTraceFrom(const class StackTrace& ex_trace) { | 2141 DebuggerStackTrace* Debugger::StackTraceFrom(const class StackTrace& ex_trace) { |
2059 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8); | 2142 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8); |
2060 Function& function = Function::Handle(); | 2143 Function& function = Function::Handle(); |
2061 Code& code = Code::Handle(); | 2144 Code& code = Code::Handle(); |
2062 | 2145 |
2063 const uword fp = 0; | 2146 const uword fp = 0; |
2064 const uword sp = 0; | 2147 const uword sp = 0; |
2065 const Array& deopt_frame = Array::Handle(); | 2148 const Array& deopt_frame = Array::Handle(); |
2066 const intptr_t deopt_frame_offset = -1; | 2149 const intptr_t deopt_frame_offset = -1; |
2067 | 2150 |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2164 } else { | 2247 } else { |
2165 if (!ShouldPauseOnException(stack_trace, exc)) { | 2248 if (!ShouldPauseOnException(stack_trace, exc)) { |
2166 return; | 2249 return; |
2167 } | 2250 } |
2168 } | 2251 } |
2169 ServiceEvent event(isolate_, ServiceEvent::kPauseException); | 2252 ServiceEvent event(isolate_, ServiceEvent::kPauseException); |
2170 event.set_exception(&exc); | 2253 event.set_exception(&exc); |
2171 if (stack_trace->Length() > 0) { | 2254 if (stack_trace->Length() > 0) { |
2172 event.set_top_frame(stack_trace->FrameAt(0)); | 2255 event.set_top_frame(stack_trace->FrameAt(0)); |
2173 } | 2256 } |
2174 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace()); | 2257 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace(), |
| 2258 CollectAwaiterReturnStackTrace()); |
2175 Pause(&event); | 2259 Pause(&event); |
2176 HandleSteppingRequest(stack_trace_); // we may get a rewind request | 2260 HandleSteppingRequest(stack_trace_); // we may get a rewind request |
2177 ClearCachedStackTraces(); | 2261 ClearCachedStackTraces(); |
2178 } | 2262 } |
2179 | 2263 |
2180 | 2264 |
2181 static TokenPosition LastTokenOnLine(Zone* zone, | 2265 static TokenPosition LastTokenOnLine(Zone* zone, |
2182 const TokenStream& tokens, | 2266 const TokenStream& tokens, |
2183 TokenPosition pos) { | 2267 TokenPosition pos) { |
2184 TokenStream::Iterator iter(zone, tokens, pos, | 2268 TokenStream::Iterator iter(zone, tokens, pos, |
(...skipping 983 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3168 frame = iterator.NextFrame(); | 3252 frame = iterator.NextFrame(); |
3169 } | 3253 } |
3170 } | 3254 } |
3171 RewindToFrame(resume_frame_index_); | 3255 RewindToFrame(resume_frame_index_); |
3172 UNREACHABLE(); | 3256 UNREACHABLE(); |
3173 } | 3257 } |
3174 } | 3258 } |
3175 | 3259 |
3176 | 3260 |
3177 void Debugger::CacheStackTraces(DebuggerStackTrace* stack_trace, | 3261 void Debugger::CacheStackTraces(DebuggerStackTrace* stack_trace, |
3178 DebuggerStackTrace* async_causal_stack_trace) { | 3262 DebuggerStackTrace* async_causal_stack_trace, |
| 3263 DebuggerStackTrace* awaiter_stack_trace) { |
3179 ASSERT(stack_trace_ == NULL); | 3264 ASSERT(stack_trace_ == NULL); |
3180 stack_trace_ = stack_trace; | 3265 stack_trace_ = stack_trace; |
3181 ASSERT(async_causal_stack_trace_ == NULL); | 3266 ASSERT(async_causal_stack_trace_ == NULL); |
3182 async_causal_stack_trace_ = async_causal_stack_trace; | 3267 async_causal_stack_trace_ = async_causal_stack_trace; |
| 3268 ASSERT(awaiter_stack_trace_ == NULL); |
| 3269 awaiter_stack_trace_ = awaiter_stack_trace; |
3183 } | 3270 } |
3184 | 3271 |
3185 | 3272 |
3186 void Debugger::ClearCachedStackTraces() { | 3273 void Debugger::ClearCachedStackTraces() { |
3187 stack_trace_ = NULL; | 3274 stack_trace_ = NULL; |
3188 async_causal_stack_trace_ = NULL; | 3275 async_causal_stack_trace_ = NULL; |
| 3276 awaiter_stack_trace_ = NULL; |
3189 } | 3277 } |
3190 | 3278 |
3191 | 3279 |
3192 static intptr_t FindNextRewindFrameIndex(DebuggerStackTrace* stack, | 3280 static intptr_t FindNextRewindFrameIndex(DebuggerStackTrace* stack, |
3193 intptr_t frame_index) { | 3281 intptr_t frame_index) { |
3194 for (intptr_t i = frame_index + 1; i < stack->Length(); i++) { | 3282 for (intptr_t i = frame_index + 1; i < stack->Length(); i++) { |
3195 ActivationFrame* frame = stack->FrameAt(i); | 3283 ActivationFrame* frame = stack->FrameAt(i); |
3196 if (frame->IsRewindable()) { | 3284 if (frame->IsRewindable()) { |
3197 return i; | 3285 return i; |
3198 } | 3286 } |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3519 | 3607 |
3520 if (FLAG_verbose_debug) { | 3608 if (FLAG_verbose_debug) { |
3521 OS::Print(">>> single step break at %s:%" Pd " (func %s token %s)\n", | 3609 OS::Print(">>> single step break at %s:%" Pd " (func %s token %s)\n", |
3522 String::Handle(frame->SourceUrl()).ToCString(), | 3610 String::Handle(frame->SourceUrl()).ToCString(), |
3523 frame->LineNumber(), | 3611 frame->LineNumber(), |
3524 String::Handle(frame->QualifiedFunctionName()).ToCString(), | 3612 String::Handle(frame->QualifiedFunctionName()).ToCString(), |
3525 frame->TokenPos().ToCString()); | 3613 frame->TokenPos().ToCString()); |
3526 } | 3614 } |
3527 | 3615 |
3528 | 3616 |
3529 CacheStackTraces(CollectStackTrace(), CollectAsyncCausalStackTrace()); | 3617 CacheStackTraces(CollectStackTrace(), CollectAsyncCausalStackTrace(), |
| 3618 CollectAwaiterReturnStackTrace()); |
3530 // If this step callback is part of stepping over an await statement, | 3619 // If this step callback is part of stepping over an await statement, |
3531 // we saved the synthetic async breakpoint in PauseBreakpoint. We report | 3620 // we saved the synthetic async breakpoint in PauseBreakpoint. We report |
3532 // that we are paused at that breakpoint and then delete it after continuing. | 3621 // that we are paused at that breakpoint and then delete it after continuing. |
3533 SignalPausedEvent(frame, synthetic_async_breakpoint_); | 3622 SignalPausedEvent(frame, synthetic_async_breakpoint_); |
3534 if (synthetic_async_breakpoint_ != NULL) { | 3623 if (synthetic_async_breakpoint_ != NULL) { |
3535 RemoveBreakpoint(synthetic_async_breakpoint_->id()); | 3624 RemoveBreakpoint(synthetic_async_breakpoint_->id()); |
3536 synthetic_async_breakpoint_ = NULL; | 3625 synthetic_async_breakpoint_ = NULL; |
3537 } | 3626 } |
3538 HandleSteppingRequest(stack_trace_); | 3627 HandleSteppingRequest(stack_trace_); |
3539 ClearCachedStackTraces(); | 3628 ClearCachedStackTraces(); |
(...skipping 20 matching lines...) Expand all Loading... |
3560 ASSERT(cbpt != NULL); | 3649 ASSERT(cbpt != NULL); |
3561 | 3650 |
3562 Breakpoint* bpt_hit = FindHitBreakpoint(cbpt->bpt_location_, top_frame); | 3651 Breakpoint* bpt_hit = FindHitBreakpoint(cbpt->bpt_location_, top_frame); |
3563 if (bpt_hit == NULL) { | 3652 if (bpt_hit == NULL) { |
3564 return Error::null(); | 3653 return Error::null(); |
3565 } | 3654 } |
3566 | 3655 |
3567 if (bpt_hit->is_synthetic_async()) { | 3656 if (bpt_hit->is_synthetic_async()) { |
3568 DebuggerStackTrace* stack_trace = CollectStackTrace(); | 3657 DebuggerStackTrace* stack_trace = CollectStackTrace(); |
3569 ASSERT(stack_trace->Length() > 0); | 3658 ASSERT(stack_trace->Length() > 0); |
3570 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace()); | 3659 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace(), |
| 3660 CollectAwaiterReturnStackTrace()); |
3571 | 3661 |
3572 // Hit a synthetic async breakpoint. | 3662 // Hit a synthetic async breakpoint. |
3573 if (FLAG_verbose_debug) { | 3663 if (FLAG_verbose_debug) { |
3574 OS::Print(">>> hit synthetic breakpoint at %s:%" Pd | 3664 OS::Print(">>> hit synthetic breakpoint at %s:%" Pd |
3575 " " | 3665 " " |
3576 "(token %s) (address %#" Px ")\n", | 3666 "(token %s) (address %#" Px ")\n", |
3577 String::Handle(cbpt->SourceUrl()).ToCString(), | 3667 String::Handle(cbpt->SourceUrl()).ToCString(), |
3578 cbpt->LineNumber(), cbpt->token_pos().ToCString(), | 3668 cbpt->LineNumber(), cbpt->token_pos().ToCString(), |
3579 top_frame->pc()); | 3669 top_frame->pc()); |
3580 } | 3670 } |
(...skipping 14 matching lines...) Expand all Loading... |
3595 | 3685 |
3596 if (FLAG_verbose_debug) { | 3686 if (FLAG_verbose_debug) { |
3597 OS::Print(">>> hit breakpoint %" Pd " at %s:%" Pd | 3687 OS::Print(">>> hit breakpoint %" Pd " at %s:%" Pd |
3598 " (token %s) " | 3688 " (token %s) " |
3599 "(address %#" Px ")\n", | 3689 "(address %#" Px ")\n", |
3600 bpt_hit->id(), String::Handle(cbpt->SourceUrl()).ToCString(), | 3690 bpt_hit->id(), String::Handle(cbpt->SourceUrl()).ToCString(), |
3601 cbpt->LineNumber(), cbpt->token_pos().ToCString(), | 3691 cbpt->LineNumber(), cbpt->token_pos().ToCString(), |
3602 top_frame->pc()); | 3692 top_frame->pc()); |
3603 } | 3693 } |
3604 | 3694 |
3605 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace()); | 3695 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace(), |
| 3696 CollectAwaiterReturnStackTrace()); |
3606 SignalPausedEvent(top_frame, bpt_hit); | 3697 SignalPausedEvent(top_frame, bpt_hit); |
3607 // When we single step from a user breakpoint, our next stepping | 3698 // When we single step from a user breakpoint, our next stepping |
3608 // point will be at the exact same pc. Skip it. | 3699 // point will be at the exact same pc. Skip it. |
3609 HandleSteppingRequest(stack_trace_, true /* skip next step */); | 3700 HandleSteppingRequest(stack_trace_, true /* skip next step */); |
3610 ClearCachedStackTraces(); | 3701 ClearCachedStackTraces(); |
3611 | 3702 |
3612 // If any error occurred while in the debug message loop, return it here. | 3703 // If any error occurred while in the debug message loop, return it here. |
3613 const Error& error = Error::Handle(Thread::Current()->sticky_error()); | 3704 const Error& error = Error::Handle(Thread::Current()->sticky_error()); |
3614 Thread::Current()->clear_sticky_error(); | 3705 Thread::Current()->clear_sticky_error(); |
3615 return error.raw(); | 3706 return error.raw(); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3664 void Debugger::PauseDeveloper(const String& msg) { | 3755 void Debugger::PauseDeveloper(const String& msg) { |
3665 // We ignore this breakpoint when the VM is executing code invoked | 3756 // We ignore this breakpoint when the VM is executing code invoked |
3666 // by the debugger to evaluate variables values, or when we see a nested | 3757 // by the debugger to evaluate variables values, or when we see a nested |
3667 // breakpoint or exception event. | 3758 // breakpoint or exception event. |
3668 if (ignore_breakpoints_ || IsPaused()) { | 3759 if (ignore_breakpoints_ || IsPaused()) { |
3669 return; | 3760 return; |
3670 } | 3761 } |
3671 | 3762 |
3672 DebuggerStackTrace* stack_trace = CollectStackTrace(); | 3763 DebuggerStackTrace* stack_trace = CollectStackTrace(); |
3673 ASSERT(stack_trace->Length() > 0); | 3764 ASSERT(stack_trace->Length() > 0); |
3674 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace()); | 3765 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace(), |
| 3766 CollectAwaiterReturnStackTrace()); |
3675 // TODO(johnmccutchan): Send |msg| to Observatory. | 3767 // TODO(johnmccutchan): Send |msg| to Observatory. |
3676 | 3768 |
3677 // We are in the native call to Developer_debugger. the developer | 3769 // We are in the native call to Developer_debugger. the developer |
3678 // gets a better experience by not seeing this call. To accomplish | 3770 // gets a better experience by not seeing this call. To accomplish |
3679 // this, we continue execution until the call exits (step out). | 3771 // this, we continue execution until the call exits (step out). |
3680 SetResumeAction(kStepOut); | 3772 SetResumeAction(kStepOut); |
3681 HandleSteppingRequest(stack_trace_); | 3773 HandleSteppingRequest(stack_trace_); |
3682 ClearCachedStackTraces(); | 3774 ClearCachedStackTraces(); |
3683 } | 3775 } |
3684 | 3776 |
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4153 | 4245 |
4154 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 4246 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
4155 ASSERT(bpt->next() == NULL); | 4247 ASSERT(bpt->next() == NULL); |
4156 bpt->set_next(code_breakpoints_); | 4248 bpt->set_next(code_breakpoints_); |
4157 code_breakpoints_ = bpt; | 4249 code_breakpoints_ = bpt; |
4158 } | 4250 } |
4159 | 4251 |
4160 #endif // !PRODUCT | 4252 #endif // !PRODUCT |
4161 | 4253 |
4162 } // namespace dart | 4254 } // namespace dart |
OLD | NEW |