| Index: runtime/vm/flow_graph_builder.cc
|
| diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
|
| index cacb2fbcd6e4f3219a4957661a06779bae7b6256..b87633016fce9a1d36cfb9075ac2fd070fd3a136 100644
|
| --- a/runtime/vm/flow_graph_builder.cc
|
| +++ b/runtime/vm/flow_graph_builder.cc
|
| @@ -1046,6 +1046,41 @@ void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) {
|
| UnchainContexts(current_context_level);
|
| }
|
|
|
| + // 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
|
| + // returns end up returning null in the end.
|
| + // 2) "Continuation" returns that should not complete the completer.
|
| + //
|
| + // We distinguish those types by whether a return_scope() has been set or not.
|
| + //
|
| + if (function.is_async_closure() && node->return_scope() != NULL) {
|
| + // Temporary store the computed return value.
|
| + Do(BuildStoreExprTemp(return_value));
|
| +
|
| + LocalVariable* rcv_var = node->return_scope()->LookupVariable(
|
| + Symbols::AsyncCompleter(), false);
|
| + ASSERT(rcv_var != NULL && rcv_var->is_captured());
|
| + Value* rcv_value = Bind(BuildLoadLocal(*rcv_var));
|
| + Value* returned_value = Bind(BuildLoadExprTemp());
|
| + ZoneGrowableArray<PushArgumentInstr*>* arguments =
|
| + new(I) ZoneGrowableArray<PushArgumentInstr*>(2);
|
| + arguments->Add(PushArgument(rcv_value));
|
| + arguments->Add(PushArgument(returned_value));
|
| + InstanceCallInstr* call = new(I) InstanceCallInstr(
|
| + Scanner::kNoSourcePos,
|
| + Symbols::CompleterComplete(),
|
| + Token::kILLEGAL,
|
| + arguments,
|
| + Object::null_array(),
|
| + 1,
|
| + owner()->ic_data_array());
|
| + Do(call);
|
| +
|
| + // Rebind the return value for the actual return call to be null.
|
| + return_value = BuildNullValue();
|
| + }
|
| +
|
| AddReturnExit(node->token_pos(), return_value);
|
| }
|
|
|
|
|