Chromium Code Reviews| Index: runtime/vm/flow_graph_builder.cc |
| diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc |
| index bf135624fb07337f4a2ea3895866d0e4c4fa2d95..79f66d872e099c88988b9b69955796e993b585f4 100644 |
| --- a/runtime/vm/flow_graph_builder.cc |
| +++ b/runtime/vm/flow_graph_builder.cc |
| @@ -1131,6 +1131,30 @@ void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) { |
| } |
| } |
| + if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) { |
|
rmacnak
2017/01/26 18:05:57
&& FLAG_sane_async_stacks
Cutch
2017/01/31 23:45:31
Done.
|
| + // We are returning from an asynchronous closure. Before we do that, be |
| + // sure to clear the thread's asynchronous stack trace. |
| + const Library& async_lib = Library::Handle(Library::AsyncLibrary()); |
| + ASSERT(!async_lib.IsNull()); |
| + const String& private_name = String::ZoneHandle( |
| + async_lib.PrivateName(Symbols::ClearAsyncThreadStackTrace())); |
| + ASSERT(!private_name.IsNull()); |
| + const Function& async_clear_thread_stack_trace = Function::ZoneHandle( |
| + Z, |
| + Resolver::ResolveStatic(async_lib, String::ZoneHandle(String::null()), |
|
rmacnak
2017/01/26 18:05:57
It might be worth caching the three helper functio
Cutch
2017/01/31 23:45:31
Done.
|
| + private_name, 0, Object::null_array())); |
| + ASSERT(!async_clear_thread_stack_trace.IsNull()); |
| + // Mark that this function is not debuggable. |
| + async_clear_thread_stack_trace.set_is_debuggable(false); |
|
rmacnak
2017/01/26 18:05:57
I thought we can't step into native functions anyw
Cutch
2017/01/31 23:45:30
Acknowledged.
|
| + 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 |
| @@ -3787,6 +3811,44 @@ void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) { |
| } |
| } |
| + if (is_top_level_sequence && |
| + (function.IsAsyncClosure() || function.IsAsyncGenClosure())) { |
|
rmacnak
2017/01/26 18:05:57
&& FLAG_sane_async_stacks
Cutch
2017/01/31 23:45:30
Done.
|
| + 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)); |
| + |
| + // Lookup _asyncSetThreadStackTrace |
| + const Library& async_lib = Library::Handle(Library::AsyncLibrary()); |
| + ASSERT(!async_lib.IsNull()); |
| + const String& private_name = String::ZoneHandle( |
| + async_lib.PrivateName(Symbols::SetAsyncThreadStackTrace())); |
| + ASSERT(!private_name.IsNull()); |
| + const Function& async_set_thread_stack_trace = Function::ZoneHandle( |
| + Z, |
| + Resolver::ResolveStatic(async_lib, String::ZoneHandle(String::null()), |
| + private_name, 1, Object::null_array())); |
|
siva
2017/01/26 19:26:23
Agree with Ryan might be worth caching these funct
Cutch
2017/01/31 23:45:30
Done.
|
| + ASSERT(!async_set_thread_stack_trace.IsNull()); |
| + // Mark that this function is not debuggable. |
| + async_set_thread_stack_trace.set_is_debuggable(false); |
| + // 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 |