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

Unified Diff: runtime/vm/flow_graph_builder.cc

Issue 460763002: Fix returning from async functions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: add scope via sequencenode add method Created 6 years, 4 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 side-by-side diff with in-line comments
Download patch
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..278329adfc1160a6de74d6f546e19bb5f8e3bd15 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 scope() has been set or not.
hausner 2014/08/12 20:51:26 Is it possible to have a return without a sequence
Michael Lippautz (Google) 2014/08/12 21:13:57 True. I added a flag for this that is always true
+ //
+ if (function.is_async_closure() && node->scope() != NULL) {
+ // Temporary store the computed return value.
+ Do(BuildStoreExprTemp(return_value));
+
+ LocalVariable* rcv_var = node->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);
}

Powered by Google App Engine
This is Rietveld 408576698