Skip to content

Commit 886615d

Browse files
Clement Skaucommit-bot@chromium.org
Clement Skau
authored andcommitted
[SDK] Switch to is_sync to identify sync/async running.
This should address the regression introduced by https://dart-review.googlesource.com/c/sdk/+/124988 Bug: #39525 Change-Id: Id163b649bdd0363297c186559fa84ff87f908e4b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/129062 Reviewed-by: Clement Skau <[email protected]> Reviewed-by: Martin Kustermann <[email protected]> Commit-Queue: Clement Skau <[email protected]>
1 parent 4774141 commit 886615d

File tree

6 files changed

+415
-439
lines changed

6 files changed

+415
-439
lines changed

runtime/vm/debugger.cc

Lines changed: 117 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -2313,10 +2313,10 @@ DebuggerStackTrace* Debugger::CollectAwaiterReturnStackTrace() {
23132313
#if defined(DART_PRECOMPILED_RUNTIME)
23142314
// Causal async stacks are not supported in the AOT runtime.
23152315
ASSERT(!FLAG_async_debugger);
2316-
return NULL;
2316+
return nullptr;
23172317
#else
23182318
if (!FLAG_async_debugger) {
2319-
return NULL;
2319+
return nullptr;
23202320
}
23212321

23222322
Thread* thread = Thread::Current();
@@ -2337,163 +2337,148 @@ DebuggerStackTrace* Debugger::CollectAwaiterReturnStackTrace() {
23372337
Closure& async_activation = Closure::Handle(zone);
23382338
Object& next_async_activation = Object::Handle(zone);
23392339
Array& deopt_frame = Array::Handle(zone);
2340+
// Note: 'class' since Debugger declares a method by the same name.
23402341
class StackTrace& async_stack_trace = StackTrace::Handle(zone);
23412342
bool stack_has_async_function = false;
2343+
Closure& closure = Closure::Handle(zone);
2344+
CallerClosureFinder caller_closure_finder(zone);
23422345

2343-
// Number of frames we are trying to skip that form "sync async" entry.
2344-
int skip_sync_async_frames_count = -1;
2345-
String& function_name = String::Handle(zone);
2346-
for (StackFrame* frame = iterator.NextFrame(); frame != NULL;
2346+
for (StackFrame* frame = iterator.NextFrame(); frame != nullptr;
23472347
frame = iterator.NextFrame()) {
23482348
ASSERT(frame->IsValid());
23492349
if (FLAG_trace_debugger_stacktrace) {
23502350
OS::PrintErr("CollectAwaiterReturnStackTrace: visiting frame:\n\t%s\n",
23512351
frame->ToCString());
23522352
}
2353-
if (frame->IsDartFrame()) {
2354-
if (frame->is_interpreted()) {
2355-
bytecode = frame->LookupDartBytecode();
2356-
function = bytecode.function();
2357-
if (function.IsNull()) {
2358-
continue; // Skip bytecode stub frame.
2359-
}
2353+
if (!frame->IsDartFrame()) {
2354+
continue;
2355+
}
23602356

2361-
if (skip_sync_async_frames_count > 0) {
2362-
function_name = function.QualifiedScrubbedName();
2363-
if (!StackTraceUtils::CheckAndSkipAsync(&skip_sync_async_frames_count,
2364-
function_name)) {
2365-
// Unexpected function in synchronous call of async function.
2366-
break;
2367-
}
2368-
}
2357+
if (frame->is_interpreted()) {
2358+
bytecode = frame->LookupDartBytecode();
2359+
function = bytecode.function();
2360+
if (function.IsNull()) {
2361+
continue; // Skip bytecode stub frame.
2362+
}
23692363

2370-
if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
2371-
ActivationFrame* activation =
2372-
CollectDartFrame(isolate, frame->pc(), frame, bytecode,
2373-
ActivationFrame::kAsyncActivation);
2374-
ASSERT(activation != NULL);
2375-
stack_trace->AddActivation(activation);
2376-
stack_has_async_function = true;
2377-
// Grab the awaiter.
2378-
async_activation ^= activation->GetAsyncAwaiter();
2379-
async_stack_trace ^= activation->GetCausalStack();
2380-
// Interpreted bytecode does not invoke _ClosureCall().
2381-
// Skip _AsyncAwaitCompleterStart() only.
2382-
skip_sync_async_frames_count = 1;
2383-
} else {
2384-
stack_trace->AddActivation(
2385-
CollectDartFrame(isolate, frame->pc(), frame, bytecode));
2364+
if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
2365+
ActivationFrame* activation =
2366+
CollectDartFrame(isolate, frame->pc(), frame, bytecode,
2367+
ActivationFrame::kAsyncActivation);
2368+
ASSERT(activation != nullptr);
2369+
stack_trace->AddActivation(activation);
2370+
stack_has_async_function = true;
2371+
// Grab the awaiter.
2372+
async_activation ^= activation->GetAsyncAwaiter();
2373+
async_stack_trace ^= activation->GetCausalStack();
2374+
2375+
// Bail if we've reach the end of the sync execution stack.
2376+
RawObject** last_caller_obj =
2377+
reinterpret_cast<RawObject**>(frame->GetCallerSp());
2378+
closure = StackTraceUtils::FindClosureInFrame(last_caller_obj, function,
2379+
frame->is_interpreted());
2380+
if (caller_closure_finder.IsRunningAsync(closure)) {
2381+
// We've reached the end of the stack of the sync execution.
2382+
break;
23862383
}
23872384
} else {
2388-
code = frame->LookupDartCode();
2389-
if (code.is_optimized()) {
2390-
if (code.is_force_optimized()) {
2391-
if (FLAG_trace_debugger_stacktrace) {
2392-
function = code.function();
2393-
ASSERT(!function.IsNull());
2394-
OS::PrintErr(
2395-
"CollectAwaiterReturnStackTrace: "
2396-
"skipping force-optimized function: %s\n",
2397-
function.ToFullyQualifiedCString());
2398-
}
2399-
// Skip frame of force-optimized (and non-debuggable) function.
2400-
continue;
2401-
}
2402-
deopt_frame = DeoptimizeToArray(thread, frame, code);
2403-
bool found_async_awaiter = false;
2404-
bool abort_attempt_to_navigate_through_sync_async = false;
2405-
for (InlinedFunctionsIterator it(code, frame->pc()); !it.Done();
2406-
it.Advance()) {
2407-
inlined_code = it.code();
2408-
function = it.function();
2409-
2410-
if (skip_sync_async_frames_count > 0) {
2411-
function_name ^= function.QualifiedScrubbedName();
2412-
if (!StackTraceUtils::CheckAndSkipAsync(
2413-
&skip_sync_async_frames_count, function_name)) {
2414-
// Unexpected function in sync async call
2415-
skip_sync_async_frames_count = -1;
2416-
abort_attempt_to_navigate_through_sync_async = true;
2417-
break;
2418-
}
2419-
}
2420-
2421-
if (FLAG_trace_debugger_stacktrace) {
2422-
ASSERT(!function.IsNull());
2423-
OS::PrintErr(
2424-
"CollectAwaiterReturnStackTrace: "
2425-
"visiting inlined function: %s\n ",
2426-
function.ToFullyQualifiedCString());
2427-
}
2428-
intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
2429-
if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
2430-
ActivationFrame* activation = CollectDartFrame(
2431-
isolate, it.pc(), frame, inlined_code, deopt_frame,
2432-
deopt_frame_offset, ActivationFrame::kAsyncActivation);
2433-
ASSERT(activation != NULL);
2434-
stack_trace->AddActivation(activation);
2435-
stack_has_async_function = true;
2436-
// Grab the awaiter.
2437-
async_activation ^= activation->GetAsyncAwaiter();
2438-
found_async_awaiter = true;
2439-
// async function might have been called synchronously, in which
2440-
// case we need to keep going down the stack.
2441-
// To determine how we are called we peek few more frames further
2442-
// expecting to see Closure_call followed by
2443-
// AsyncAwaitCompleter_start.
2444-
// If we are able to see those functions we continue going down
2445-
// thestack, if we are not, we break out of the loop as we are
2446-
// not interested in exploring rest of the stack - there is only
2447-
// dart-internal code left.
2448-
skip_sync_async_frames_count = 2;
2449-
} else {
2450-
stack_trace->AddActivation(
2451-
CollectDartFrame(isolate, it.pc(), frame, inlined_code,
2452-
deopt_frame, deopt_frame_offset));
2453-
}
2454-
}
2455-
// Break out of outer loop.
2456-
if (found_async_awaiter ||
2457-
abort_attempt_to_navigate_through_sync_async) {
2458-
break;
2385+
stack_trace->AddActivation(
2386+
CollectDartFrame(isolate, frame->pc(), frame, bytecode));
2387+
}
2388+
} else {
2389+
code = frame->LookupDartCode();
2390+
if (code.is_optimized()) {
2391+
if (code.is_force_optimized()) {
2392+
if (FLAG_trace_debugger_stacktrace) {
2393+
function = code.function();
2394+
ASSERT(!function.IsNull());
2395+
OS::PrintErr(
2396+
"CollectAwaiterReturnStackTrace: "
2397+
"skipping force-optimized function: %s\n",
2398+
function.ToFullyQualifiedCString());
24592399
}
2460-
} else {
2461-
function = code.function();
2400+
// Skip frame of force-optimized (and non-debuggable) function.
2401+
continue;
2402+
}
2403+
deopt_frame = DeoptimizeToArray(thread, frame, code);
2404+
bool found_async_awaiter = false;
2405+
bool abort_attempt_to_navigate_through_sync_async = false;
2406+
for (InlinedFunctionsIterator it(code, frame->pc()); !it.Done();
2407+
it.Advance()) {
2408+
inlined_code = it.code();
2409+
function = it.function();
24622410

2463-
if (skip_sync_async_frames_count > 0) {
2464-
function_name ^= function.QualifiedScrubbedName();
2465-
if (!StackTraceUtils::CheckAndSkipAsync(
2466-
&skip_sync_async_frames_count, function_name)) {
2467-
// Unexpected function in synchronous call of async function.
2468-
break;
2469-
}
2411+
if (FLAG_trace_debugger_stacktrace) {
2412+
ASSERT(!function.IsNull());
2413+
OS::PrintErr(
2414+
"CollectAwaiterReturnStackTrace: "
2415+
"visiting inlined function: %s\n ",
2416+
function.ToFullyQualifiedCString());
24702417
}
2471-
2418+
intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
24722419
if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
24732420
ActivationFrame* activation = CollectDartFrame(
2474-
isolate, frame->pc(), frame, code, Object::null_array(), 0,
2475-
ActivationFrame::kAsyncActivation);
2476-
ASSERT(activation != NULL);
2421+
isolate, it.pc(), frame, inlined_code, deopt_frame,
2422+
deopt_frame_offset, ActivationFrame::kAsyncActivation);
24772423
stack_trace->AddActivation(activation);
24782424
stack_has_async_function = true;
24792425
// Grab the awaiter.
24802426
async_activation ^= activation->GetAsyncAwaiter();
2481-
async_stack_trace ^= activation->GetCausalStack();
2482-
// see comment regarding skipping frames of async functions called
2483-
// synchronously above.
2484-
skip_sync_async_frames_count = 2;
2427+
found_async_awaiter = true;
2428+
2429+
// Bail if we've reach the end of the sync execution stack.
2430+
RawObject** last_caller_obj =
2431+
reinterpret_cast<RawObject**>(frame->GetCallerSp());
2432+
closure = StackTraceUtils::FindClosureInFrame(
2433+
last_caller_obj, function, frame->is_interpreted());
2434+
if (caller_closure_finder.IsRunningAsync(closure)) {
2435+
abort_attempt_to_navigate_through_sync_async = true;
2436+
break;
2437+
}
24852438
} else {
2486-
stack_trace->AddActivation(CollectDartFrame(
2487-
isolate, frame->pc(), frame, code, Object::null_array(), 0));
2439+
stack_trace->AddActivation(
2440+
CollectDartFrame(isolate, it.pc(), frame, inlined_code,
2441+
deopt_frame, deopt_frame_offset));
24882442
}
2443+
} // for (InlinedFunctionsIterator)
2444+
// Break out of outer loop.
2445+
if (found_async_awaiter ||
2446+
abort_attempt_to_navigate_through_sync_async) {
2447+
break;
2448+
}
2449+
} else { // code.is_optimized()
2450+
function = code.function();
2451+
2452+
if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
2453+
ActivationFrame* activation = CollectDartFrame(
2454+
isolate, frame->pc(), frame, code, Object::null_array(), 0,
2455+
ActivationFrame::kAsyncActivation);
2456+
ASSERT(activation != nullptr);
2457+
stack_trace->AddActivation(activation);
2458+
stack_has_async_function = true;
2459+
// Grab the awaiter.
2460+
async_activation ^= activation->GetAsyncAwaiter();
2461+
async_stack_trace ^= activation->GetCausalStack();
2462+
2463+
// Bail if we've reach the end of sync execution stack.
2464+
RawObject** last_caller_obj =
2465+
reinterpret_cast<RawObject**>(frame->GetCallerSp());
2466+
closure = StackTraceUtils::FindClosureInFrame(
2467+
last_caller_obj, function, frame->is_interpreted());
2468+
if (caller_closure_finder.IsRunningAsync(closure)) {
2469+
break;
2470+
}
2471+
} else {
2472+
stack_trace->AddActivation(CollectDartFrame(
2473+
isolate, frame->pc(), frame, code, Object::null_array(), 0));
24892474
}
24902475
}
24912476
}
2492-
}
2477+
} // for (frame in iterator)
24932478

2494-
// If the stack doesn't have any async functions on it, return NULL.
2479+
// If the stack doesn't have any async functions on it, return nullptr.
24952480
if (!stack_has_async_function) {
2496-
return NULL;
2481+
return nullptr;
24972482
}
24982483

24992484
// Append the awaiter return call stack.
@@ -2514,7 +2499,7 @@ DebuggerStackTrace* Debugger::CollectAwaiterReturnStackTrace() {
25142499
break;
25152500
}
25162501
async_activation = Closure::RawCast(next_async_activation.raw());
2517-
}
2502+
} // while (!async_activation.IsNull())
25182503

25192504
// Now we append the asynchronous causal stack trace. These are not active
25202505
// frames but a historical record of how this asynchronous function was
@@ -2569,7 +2554,7 @@ DebuggerStackTrace* Debugger::CollectAwaiterReturnStackTrace() {
25692554
}
25702555
// Follow the link.
25712556
async_stack_trace = async_stack_trace.async_link();
2572-
}
2557+
} // while (!async_stack_trace.IsNull())
25732558

25742559
return stack_trace;
25752560
#endif // defined(DART_PRECOMPILED_RUNTIME)

runtime/vm/stack_frame.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,12 @@ class StackFrame : public ValueObject {
132132

133133
static void DumpCurrentTrace();
134134

135+
uword GetCallerSp() const {
136+
return fp() +
137+
((is_interpreted() ? kKBCCallerSpSlotFromFp : kCallerSpSlotFromFp) *
138+
kWordSize);
139+
}
140+
135141
protected:
136142
explicit StackFrame(Thread* thread)
137143
: fp_(0), sp_(0), pc_(0), thread_(thread), is_interpreted_(false) {}
@@ -151,12 +157,6 @@ class StackFrame : public ValueObject {
151157
RawCode* GetCodeObject() const;
152158
RawBytecode* GetBytecodeObject() const;
153159

154-
uword GetCallerSp() const {
155-
return fp() +
156-
((is_interpreted() ? kKBCCallerSpSlotFromFp : kCallerSpSlotFromFp) *
157-
kWordSize);
158-
}
159-
160160
uword GetCallerFp() const {
161161
return *(reinterpret_cast<uword*>(
162162
fp() + ((is_interpreted() ? kKBCSavedCallerFpSlotFromFp

0 commit comments

Comments
 (0)