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

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

Issue 2767483002: Fix two bugs with async stack traces. (Closed)
Patch Set: Created 3 years, 9 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/flag_list.h » ('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
(...skipping 1886 matching lines...) Expand 10 before | Expand all | Expand 10 after
1897 // the readability of the trace. 1897 // the readability of the trace.
1898 i++; 1898 i++;
1899 } else { 1899 } else {
1900 code = Code::RawCast(async_stack_trace.CodeAtFrame(i)); 1900 code = Code::RawCast(async_stack_trace.CodeAtFrame(i));
1901 offset = Smi::RawCast(async_stack_trace.PcOffsetAtFrame(i)); 1901 offset = Smi::RawCast(async_stack_trace.PcOffsetAtFrame(i));
1902 uword pc = code.PayloadStart() + offset.Value(); 1902 uword pc = code.PayloadStart() + offset.Value();
1903 if (code.is_optimized()) { 1903 if (code.is_optimized()) {
1904 for (InlinedFunctionsIterator it(code, pc); !it.Done(); 1904 for (InlinedFunctionsIterator it(code, pc); !it.Done();
1905 it.Advance()) { 1905 it.Advance()) {
1906 inlined_code = it.code(); 1906 inlined_code = it.code();
1907 stack_trace->AddAsyncCausalFrame(pc, inlined_code); 1907 stack_trace->AddAsyncCausalFrame(it.pc(), inlined_code);
1908 } 1908 }
1909 } else { 1909 } else {
1910 stack_trace->AddAsyncCausalFrame(pc, code); 1910 stack_trace->AddAsyncCausalFrame(pc, code);
1911 } 1911 }
1912 } 1912 }
1913 } 1913 }
1914 // Follow the link. 1914 // Follow the link.
1915 async_stack_trace = async_stack_trace.async_link(); 1915 async_stack_trace = async_stack_trace.async_link();
1916 } 1916 }
1917 1917
1918 return stack_trace; 1918 return stack_trace;
1919 } 1919 }
1920 1920
1921 1921
1922 DebuggerStackTrace* Debugger::CollectAwaiterReturnStackTrace() { 1922 DebuggerStackTrace* Debugger::CollectAwaiterReturnStackTrace() {
1923 if (!FLAG_causal_async_stacks) { 1923 if (!FLAG_causal_async_stacks) {
1924 return NULL; 1924 return NULL;
1925 } 1925 }
1926 // Causal async stacks are not supported in the AOT runtime.
1927 ASSERT(!FLAG_precompiled_runtime);
1928
1926 Thread* thread = Thread::Current(); 1929 Thread* thread = Thread::Current();
1927 Zone* zone = thread->zone(); 1930 Zone* zone = thread->zone();
1928 Isolate* isolate = thread->isolate(); 1931 Isolate* isolate = thread->isolate();
1929 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8); 1932 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
1930 1933
1931 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames); 1934 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames);
1932 1935
1933 Code& code = Code::Handle(zone); 1936 Code& code = Code::Handle(zone);
1934 Function& function = Function::Handle(zone); 1937 Function& function = Function::Handle(zone);
1935 Code& inlined_code = Code::Handle(zone); 1938 Code& inlined_code = Code::Handle(zone);
1936 Closure& async_activation = Closure::Handle(zone); 1939 Closure& async_activation = Closure::Handle(zone);
1937 Array& deopt_frame = Array::Handle(zone); 1940 Array& deopt_frame = Array::Handle(zone);
1938 1941
1939 for (StackFrame* frame = iterator.NextFrame(); frame != NULL; 1942 for (StackFrame* frame = iterator.NextFrame(); frame != NULL;
1940 frame = iterator.NextFrame()) { 1943 frame = iterator.NextFrame()) {
1941 ASSERT(frame->IsValid()); 1944 ASSERT(frame->IsValid());
1945 if (FLAG_trace_debugger_stacktrace) {
1946 OS::PrintErr("CollectStackTrace: visiting frame:\n\t%s\n",
1947 frame->ToCString());
1948 }
1942 if (frame->IsDartFrame()) { 1949 if (frame->IsDartFrame()) {
1943 code = frame->LookupDartCode(); 1950 code = frame->LookupDartCode();
1944 function = code.function(); 1951 if (code.is_optimized()) {
1945 if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) { 1952 deopt_frame = DeoptimizeToArray(thread, frame, code);
1946 ActivationFrame* activation = CollectDartFrame( 1953 bool found_async_awaiter = false;
1947 isolate, frame->pc(), frame, code, Object::null_array(), 0, 1954 for (InlinedFunctionsIterator it(code, frame->pc()); !it.Done();
1948 ActivationFrame::kAsyncActivation); 1955 it.Advance()) {
1949 ASSERT(activation != NULL); 1956 inlined_code = it.code();
1950 stack_trace->AddActivation(activation); 1957 function = inlined_code.function();
1951 // Grab the awaiter. 1958 if (FLAG_trace_debugger_stacktrace) {
1952 async_activation ^= activation->GetAsyncAwaiter(); 1959 ASSERT(!function.IsNull());
1953 break; 1960 OS::PrintErr("CollectStackTrace: visiting inlined function: %s\n",
1961 function.ToFullyQualifiedCString());
1962 }
1963 intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
1964 if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
1965 ActivationFrame* activation = CollectDartFrame(
1966 isolate, it.pc(), frame, inlined_code, deopt_frame,
1967 deopt_frame_offset, ActivationFrame::kAsyncActivation);
1968 ASSERT(activation != NULL);
1969 stack_trace->AddActivation(activation);
1970 // Grab the awaiter.
1971 async_activation ^= activation->GetAsyncAwaiter();
1972 found_async_awaiter = true;
1973 break;
1974 } else {
1975 stack_trace->AddActivation(
1976 CollectDartFrame(isolate, it.pc(), frame, inlined_code,
1977 deopt_frame, deopt_frame_offset));
1978 }
1979 }
1980 // Break out of outer loop.
1981 if (found_async_awaiter) {
1982 break;
1983 }
1954 } else { 1984 } else {
1955 AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code, 1985 function = code.function();
1956 &inlined_code, &deopt_frame); 1986 if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
1987 ActivationFrame* activation = CollectDartFrame(
1988 isolate, frame->pc(), frame, code, Object::null_array(), 0,
1989 ActivationFrame::kAsyncActivation);
1990 ASSERT(activation != NULL);
1991 stack_trace->AddActivation(activation);
1992 // Grab the awaiter.
1993 async_activation ^= activation->GetAsyncAwaiter();
1994 break;
1995 } else {
1996 stack_trace->AddActivation(CollectDartFrame(
1997 isolate, frame->pc(), frame, code, Object::null_array(), 0));
1998 }
1957 } 1999 }
1958 } 2000 }
1959 } 2001 }
1960 2002
1961 // Return NULL to indicate that there is no useful information in this stack 2003 // Return NULL to indicate that there is no useful information in this stack
1962 // trace because we never found an awaiter. 2004 // trace because we never found an awaiter.
1963 if (async_activation.IsNull()) { 2005 if (async_activation.IsNull()) {
1964 return NULL; 2006 return NULL;
1965 } 2007 }
1966 2008
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
2069 (pause_info == kPauseOnAllExceptions)); 2111 (pause_info == kPauseOnAllExceptions));
2070 exc_pause_info_ = pause_info; 2112 exc_pause_info_ = pause_info;
2071 } 2113 }
2072 2114
2073 2115
2074 Dart_ExceptionPauseInfo Debugger::GetExceptionPauseInfo() const { 2116 Dart_ExceptionPauseInfo Debugger::GetExceptionPauseInfo() const {
2075 return exc_pause_info_; 2117 return exc_pause_info_;
2076 } 2118 }
2077 2119
2078 2120
2079 bool Debugger::ShouldPauseOnAsyncException(DebuggerStackTrace* stack_trace,
2080 const Instance& exc) {
2081 if (exc_pause_info_ == kNoPauseOnExceptions) {
2082 return false;
2083 }
2084 if (exc_pause_info_ == kPauseOnAllExceptions) {
2085 return true;
2086 }
2087 ASSERT(exc_pause_info_ == kPauseOnUnhandledExceptions);
2088 for (intptr_t i = 0; i < stack_trace->Length(); i++) {
2089 ActivationFrame* frame = stack_trace->FrameAt(i);
2090 if (frame->HandlesException(exc)) {
2091 if (FLAG_verbose_debug) {
2092 OS::PrintErr("%s is caught by frame %s\n", exc.ToCString(),
2093 frame->ToCString());
2094 }
2095 return false;
2096 }
2097 }
2098 return true;
2099 }
2100
2101
2102 bool Debugger::ShouldPauseOnException(DebuggerStackTrace* stack_trace, 2121 bool Debugger::ShouldPauseOnException(DebuggerStackTrace* stack_trace,
2103 const Instance& exception) { 2122 const Instance& exception) {
2104 if (exc_pause_info_ == kNoPauseOnExceptions) { 2123 if (exc_pause_info_ == kNoPauseOnExceptions) {
2105 return false; 2124 return false;
2106 } 2125 }
2107 if (exc_pause_info_ == kPauseOnAllExceptions) { 2126 if (exc_pause_info_ == kPauseOnAllExceptions) {
2108 return true; 2127 return true;
2109 } 2128 }
2110 ASSERT(exc_pause_info_ == kPauseOnUnhandledExceptions); 2129 ASSERT(exc_pause_info_ == kPauseOnUnhandledExceptions);
2111 ActivationFrame* handler_frame = stack_trace->GetHandlerFrame(exception); 2130 ActivationFrame* handler_frame = stack_trace->GetHandlerFrame(exception);
2112 if (handler_frame == NULL) { 2131 if (handler_frame == NULL) {
2113 // Did not find an exception handler that catches this exception. 2132 // Did not find an exception handler that catches this exception.
2114 // Note that this check is not precise, since we can't check 2133 // Note that this check is not precise, since we can't check
2115 // uninstantiated types, i.e. types containing type parameters. 2134 // uninstantiated types, i.e. types containing type parameters.
2116 // Thus, we may report an exception as unhandled when in fact 2135 // Thus, we may report an exception as unhandled when in fact
2117 // it will be caught once we unwind the stack. 2136 // it will be caught once we unwind the stack.
2118 return true; 2137 return true;
2119 } 2138 }
2120 return false; 2139 return false;
2121 } 2140 }
2122 2141
2123 2142
2124 void Debugger::PauseException(const Instance& exc) { 2143 void Debugger::PauseException(const Instance& exc) {
2144 if (FLAG_stress_async_stacks) {
2145 CollectAwaiterReturnStackTrace();
2146 }
2125 // We ignore this exception event when the VM is executing code invoked 2147 // We ignore this exception event when the VM is executing code invoked
2126 // by the debugger to evaluate variables values, when we see a nested 2148 // by the debugger to evaluate variables values, when we see a nested
2127 // breakpoint or exception event, or if the debugger is not 2149 // breakpoint or exception event, or if the debugger is not
2128 // interested in exception events. 2150 // interested in exception events.
2129 if (ignore_breakpoints_ || IsPaused() || 2151 if (ignore_breakpoints_ || IsPaused() ||
2130 (exc_pause_info_ == kNoPauseOnExceptions)) { 2152 (exc_pause_info_ == kNoPauseOnExceptions)) {
2131 return; 2153 return;
2132 } 2154 }
2133 DebuggerStackTrace* awaiter_stack_trace = CollectAwaiterReturnStackTrace(); 2155 DebuggerStackTrace* awaiter_stack_trace = CollectAwaiterReturnStackTrace();
2134 DebuggerStackTrace* stack_trace = CollectStackTrace(); 2156 DebuggerStackTrace* stack_trace = CollectStackTrace();
2135 if (awaiter_stack_trace != NULL) { 2157 if (awaiter_stack_trace != NULL) {
2136 if (!ShouldPauseOnAsyncException(awaiter_stack_trace, exc)) { 2158 if (!ShouldPauseOnException(awaiter_stack_trace, exc)) {
2137 return; 2159 return;
2138 } 2160 }
2139 } else { 2161 } else {
2140 if (!ShouldPauseOnException(stack_trace, exc)) { 2162 if (!ShouldPauseOnException(stack_trace, exc)) {
2141 return; 2163 return;
2142 } 2164 }
2143 } 2165 }
2144 ServiceEvent event(isolate_, ServiceEvent::kPauseException); 2166 ServiceEvent event(isolate_, ServiceEvent::kPauseException);
2145 event.set_exception(&exc); 2167 event.set_exception(&exc);
2146 if (stack_trace->Length() > 0) { 2168 if (stack_trace->Length() > 0) {
(...skipping 1964 matching lines...) Expand 10 before | Expand all | Expand 10 after
4111 4133
4112 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { 4134 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
4113 ASSERT(bpt->next() == NULL); 4135 ASSERT(bpt->next() == NULL);
4114 bpt->set_next(code_breakpoints_); 4136 bpt->set_next(code_breakpoints_);
4115 code_breakpoints_ = bpt; 4137 code_breakpoints_ = bpt;
4116 } 4138 }
4117 4139
4118 #endif // !PRODUCT 4140 #endif // !PRODUCT
4119 4141
4120 } // namespace dart 4142 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/flag_list.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698