| Index: runtime/vm/flow_graph_builder.cc
|
| diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
|
| index e13672d724ec4c4afb8d791c3cf0fc724b1db5f4..a6547d17415947ede1c55dc2df63c0765d8b60ae 100644
|
| --- a/runtime/vm/flow_graph_builder.cc
|
| +++ b/runtime/vm/flow_graph_builder.cc
|
| @@ -1131,6 +1131,21 @@ void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) {
|
| }
|
| }
|
|
|
| + if (FLAG_causal_async_stacks &&
|
| + (function.IsAsyncClosure() || function.IsAsyncGenClosure())) {
|
| + // We are returning from an asynchronous closure. Before we do that, be
|
| + // sure to clear the thread's asynchronous stack trace.
|
| + const Function& async_clear_thread_stack_trace = Function::ZoneHandle(
|
| + Z, isolate()->object_store()->async_clear_thread_stack_trace());
|
| + ZoneGrowableArray<PushArgumentInstr*>* no_arguments =
|
| + new (Z) ZoneGrowableArray<PushArgumentInstr*>(0);
|
| + StaticCallInstr* call_async_clear_thread_stack_trace = new (Z)
|
| + StaticCallInstr(node->token_pos().ToSynthetic(),
|
| + async_clear_thread_stack_trace, Object::null_array(),
|
| + no_arguments, owner()->ic_data_array());
|
| + Do(call_async_clear_thread_stack_trace);
|
| + }
|
| +
|
| // Async functions contain two types of return statements:
|
| // 1) Returns that should complete the completer once all finally blocks have
|
| // been inlined (call: :async_completer.complete(return_value)). These
|
| @@ -3792,6 +3807,34 @@ void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) {
|
| }
|
| }
|
|
|
| + if (FLAG_causal_async_stacks && is_top_level_sequence &&
|
| + (function.IsAsyncClosure() || function.IsAsyncGenClosure())) {
|
| + LocalScope* top_scope = node->scope();
|
| + // Fetch the :async_stack_trace variable and store it into the thread.
|
| + LocalVariable* async_stack_trace_var =
|
| + top_scope->LookupVariable(Symbols::AsyncStackTraceVar(), false);
|
| + ASSERT((async_stack_trace_var != NULL) &&
|
| + async_stack_trace_var->is_captured());
|
| + // Load :async_stack_trace
|
| + Value* async_stack_trace_value = Bind(BuildLoadLocal(
|
| + *async_stack_trace_var, node->token_pos().ToSynthetic()));
|
| + // Setup arguments for _asyncSetThreadStackTrace.
|
| + ZoneGrowableArray<PushArgumentInstr*>* arguments =
|
| + new (Z) ZoneGrowableArray<PushArgumentInstr*>(1);
|
| + arguments->Add(PushArgument(async_stack_trace_value));
|
| +
|
| + const Function& async_set_thread_stack_trace = Function::ZoneHandle(
|
| + Z, isolate()->object_store()->async_set_thread_stack_trace());
|
| + ASSERT(!async_set_thread_stack_trace.IsNull());
|
| + // Call _asyncSetThreadStackTrace
|
| + StaticCallInstr* call_async_set_thread_stack_trace = new (Z)
|
| + StaticCallInstr(node->token_pos().ToSynthetic(),
|
| + async_set_thread_stack_trace, Object::null_array(),
|
| + arguments, owner()->ic_data_array());
|
| + Do(call_async_set_thread_stack_trace);
|
| + }
|
| +
|
| +
|
| if (FLAG_support_debugger && is_top_level_sequence &&
|
| function.is_debuggable()) {
|
| // Place a debug check at method entry to ensure breaking on a method always
|
|
|