| Index: runtime/vm/debugger.cc
|
| diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
|
| index 44b156bd432875d1d93dde3305755bd1c3a948a8..509abb68252285a59f7b4aca4ec791686b041791 100644
|
| --- a/runtime/vm/debugger.cc
|
| +++ b/runtime/vm/debugger.cc
|
| @@ -1904,7 +1904,7 @@ DebuggerStackTrace* Debugger::CollectAsyncCausalStackTrace() {
|
| for (InlinedFunctionsIterator it(code, pc); !it.Done();
|
| it.Advance()) {
|
| inlined_code = it.code();
|
| - stack_trace->AddAsyncCausalFrame(pc, inlined_code);
|
| + stack_trace->AddAsyncCausalFrame(it.pc(), inlined_code);
|
| }
|
| } else {
|
| stack_trace->AddAsyncCausalFrame(pc, code);
|
| @@ -1923,6 +1923,9 @@ DebuggerStackTrace* Debugger::CollectAwaiterReturnStackTrace() {
|
| if (!FLAG_causal_async_stacks) {
|
| return NULL;
|
| }
|
| + // Causal async stacks are not supported in the AOT runtime.
|
| + ASSERT(!FLAG_precompiled_runtime);
|
| +
|
| Thread* thread = Thread::Current();
|
| Zone* zone = thread->zone();
|
| Isolate* isolate = thread->isolate();
|
| @@ -1939,21 +1942,60 @@ DebuggerStackTrace* Debugger::CollectAwaiterReturnStackTrace() {
|
| for (StackFrame* frame = iterator.NextFrame(); frame != NULL;
|
| frame = iterator.NextFrame()) {
|
| ASSERT(frame->IsValid());
|
| + if (FLAG_trace_debugger_stacktrace) {
|
| + OS::PrintErr("CollectStackTrace: visiting frame:\n\t%s\n",
|
| + frame->ToCString());
|
| + }
|
| if (frame->IsDartFrame()) {
|
| code = frame->LookupDartCode();
|
| - function = code.function();
|
| - if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
|
| - ActivationFrame* activation = CollectDartFrame(
|
| - isolate, frame->pc(), frame, code, Object::null_array(), 0,
|
| - ActivationFrame::kAsyncActivation);
|
| - ASSERT(activation != NULL);
|
| - stack_trace->AddActivation(activation);
|
| - // Grab the awaiter.
|
| - async_activation ^= activation->GetAsyncAwaiter();
|
| - break;
|
| + if (code.is_optimized()) {
|
| + deopt_frame = DeoptimizeToArray(thread, frame, code);
|
| + bool found_async_awaiter = false;
|
| + for (InlinedFunctionsIterator it(code, frame->pc()); !it.Done();
|
| + it.Advance()) {
|
| + inlined_code = it.code();
|
| + function = inlined_code.function();
|
| + if (FLAG_trace_debugger_stacktrace) {
|
| + ASSERT(!function.IsNull());
|
| + OS::PrintErr("CollectStackTrace: visiting inlined function: %s\n",
|
| + function.ToFullyQualifiedCString());
|
| + }
|
| + intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
|
| + if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
|
| + ActivationFrame* activation = CollectDartFrame(
|
| + isolate, it.pc(), frame, inlined_code, deopt_frame,
|
| + deopt_frame_offset, ActivationFrame::kAsyncActivation);
|
| + ASSERT(activation != NULL);
|
| + stack_trace->AddActivation(activation);
|
| + // Grab the awaiter.
|
| + async_activation ^= activation->GetAsyncAwaiter();
|
| + found_async_awaiter = true;
|
| + break;
|
| + } else {
|
| + stack_trace->AddActivation(
|
| + CollectDartFrame(isolate, it.pc(), frame, inlined_code,
|
| + deopt_frame, deopt_frame_offset));
|
| + }
|
| + }
|
| + // Break out of outer loop.
|
| + if (found_async_awaiter) {
|
| + break;
|
| + }
|
| } else {
|
| - AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code,
|
| - &inlined_code, &deopt_frame);
|
| + function = code.function();
|
| + if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
|
| + ActivationFrame* activation = CollectDartFrame(
|
| + isolate, frame->pc(), frame, code, Object::null_array(), 0,
|
| + ActivationFrame::kAsyncActivation);
|
| + ASSERT(activation != NULL);
|
| + stack_trace->AddActivation(activation);
|
| + // Grab the awaiter.
|
| + async_activation ^= activation->GetAsyncAwaiter();
|
| + break;
|
| + } else {
|
| + stack_trace->AddActivation(CollectDartFrame(
|
| + isolate, frame->pc(), frame, code, Object::null_array(), 0));
|
| + }
|
| }
|
| }
|
| }
|
| @@ -2076,29 +2118,6 @@ Dart_ExceptionPauseInfo Debugger::GetExceptionPauseInfo() const {
|
| }
|
|
|
|
|
| -bool Debugger::ShouldPauseOnAsyncException(DebuggerStackTrace* stack_trace,
|
| - const Instance& exc) {
|
| - if (exc_pause_info_ == kNoPauseOnExceptions) {
|
| - return false;
|
| - }
|
| - if (exc_pause_info_ == kPauseOnAllExceptions) {
|
| - return true;
|
| - }
|
| - ASSERT(exc_pause_info_ == kPauseOnUnhandledExceptions);
|
| - for (intptr_t i = 0; i < stack_trace->Length(); i++) {
|
| - ActivationFrame* frame = stack_trace->FrameAt(i);
|
| - if (frame->HandlesException(exc)) {
|
| - if (FLAG_verbose_debug) {
|
| - OS::PrintErr("%s is caught by frame %s\n", exc.ToCString(),
|
| - frame->ToCString());
|
| - }
|
| - return false;
|
| - }
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -
|
| bool Debugger::ShouldPauseOnException(DebuggerStackTrace* stack_trace,
|
| const Instance& exception) {
|
| if (exc_pause_info_ == kNoPauseOnExceptions) {
|
| @@ -2122,6 +2141,9 @@ bool Debugger::ShouldPauseOnException(DebuggerStackTrace* stack_trace,
|
|
|
|
|
| void Debugger::PauseException(const Instance& exc) {
|
| + if (FLAG_stress_async_stacks) {
|
| + CollectAwaiterReturnStackTrace();
|
| + }
|
| // We ignore this exception event when the VM is executing code invoked
|
| // by the debugger to evaluate variables values, when we see a nested
|
| // breakpoint or exception event, or if the debugger is not
|
| @@ -2133,7 +2155,7 @@ void Debugger::PauseException(const Instance& exc) {
|
| DebuggerStackTrace* awaiter_stack_trace = CollectAwaiterReturnStackTrace();
|
| DebuggerStackTrace* stack_trace = CollectStackTrace();
|
| if (awaiter_stack_trace != NULL) {
|
| - if (!ShouldPauseOnAsyncException(awaiter_stack_trace, exc)) {
|
| + if (!ShouldPauseOnException(awaiter_stack_trace, exc)) {
|
| return;
|
| }
|
| } else {
|
|
|