| Index: runtime/vm/ast_transformer.cc
|
| ===================================================================
|
| --- runtime/vm/ast_transformer.cc (revision 41104)
|
| +++ runtime/vm/ast_transformer.cc (working copy)
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "vm/ast_transformer.h"
|
|
|
| +#include "vm/object_store.h"
|
| #include "vm/parser.h"
|
|
|
| namespace dart {
|
| @@ -43,12 +44,10 @@
|
| #undef DEFINE_UNREACHABLE
|
|
|
| AwaitTransformer::AwaitTransformer(SequenceNode* preamble,
|
| - const Library& library,
|
| ParsedFunction* const parsed_function,
|
| LocalScope* function_top)
|
| : preamble_(preamble),
|
| temp_cnt_(0),
|
| - library_(library),
|
| parsed_function_(parsed_function),
|
| function_top_(function_top),
|
| isolate_(Isolate::Current()) {
|
| @@ -114,13 +113,14 @@
|
| //
|
| // :await_temp_var_X = <expr>;
|
| // :result_param = :await_temp_var_X;
|
| - // if (:result_param is Future) {
|
| - // AwaitMarker(kNewContinuationState);
|
| - // :result_param = :result_param.then(:async_op);
|
| - // _asyncCatchHelper(:result_param.catchError, :async_op);
|
| - // return; // (return_type() == kContinuation)
|
| + // if (:result_param is !Future) {
|
| + // :result_param = Future.value(:result_param);
|
| // }
|
| - // AwaitMarker(kTargetForContinuation); // Join happens here.
|
| + // AwaitMarker(kNewContinuationState);
|
| + // :result_param = :result_param.then(:async_op);
|
| + // _asyncCatchHelper(:result_param.catchError, :async_op);
|
| + // return; // (return_type() == kContinuationTarget)
|
| + //
|
| // :saved_try_ctx_var = :await_saved_try_ctx_var_y;
|
| // :await_temp_var_(X+1) = :result_param;
|
|
|
| @@ -131,30 +131,64 @@
|
| LocalVariable* error_param = GetVariableInScope(
|
| preamble_->scope(), Symbols::AsyncOperationErrorParam());
|
|
|
| - node->expr()->Visit(this);
|
| + AstNode* transformed_expr = Transform(node->expr());
|
| preamble_->Add(new(I) StoreLocalNode(
|
| - Scanner::kNoSourcePos, result_param, result_));
|
| + Scanner::kNoSourcePos, result_param, transformed_expr));
|
| +
|
| LoadLocalNode* load_result_param = new(I) LoadLocalNode(
|
| Scanner::kNoSourcePos, result_param);
|
| - LocalScope* is_future_scope = ChainNewScope(preamble_->scope());
|
| - SequenceNode* is_future_branch = new (I) SequenceNode(
|
| - Scanner::kNoSourcePos, is_future_scope);
|
| - AwaitMarkerNode* await_marker = new (I) AwaitMarkerNode(
|
| - AwaitMarkerNode::kNewContinuationState);
|
| - await_marker->set_scope(is_future_scope);
|
| - GetVariableInScope(is_future_scope, Symbols::AwaitJumpVar());
|
| - GetVariableInScope(is_future_scope, Symbols::AwaitContextVar());
|
| - is_future_branch->Add(await_marker);
|
| +
|
| + const Class& future_cls =
|
| + Class::ZoneHandle(I, I->object_store()->future_class());
|
| + ASSERT(!future_cls.IsNull());
|
| + const AbstractType& future_type =
|
| + AbstractType::ZoneHandle(I, future_cls.RareType());
|
| + ASSERT(!future_type.IsNull());
|
| +
|
| + LocalScope* is_not_future_scope = ChainNewScope(preamble_->scope());
|
| + SequenceNode* is_not_future_branch =
|
| + new (I) SequenceNode(Scanner::kNoSourcePos, is_not_future_scope);
|
| +
|
| + // if (:result_param is !Future) {
|
| + // :result_param = Future.value(:result_param);
|
| + // }
|
| + const Function& value_ctor = Function::ZoneHandle(
|
| + I, future_cls.LookupFunction(Symbols::FutureValue()));
|
| + ASSERT(!value_ctor.IsNull());
|
| + ArgumentListNode* ctor_args = new (I) ArgumentListNode(Scanner::kNoSourcePos);
|
| + ctor_args->Add(new (I) LoadLocalNode(Scanner::kNoSourcePos, result_param));
|
| + ConstructorCallNode* ctor_call =
|
| + new (I) ConstructorCallNode(Scanner::kNoSourcePos,
|
| + TypeArguments::ZoneHandle(I),
|
| + value_ctor,
|
| + ctor_args);
|
| + is_not_future_branch->Add(new (I) StoreLocalNode(
|
| + Scanner::kNoSourcePos, result_param, ctor_call));
|
| + AstNode* is_not_future_test = new (I) ComparisonNode(
|
| + Scanner::kNoSourcePos,
|
| + Token::kISNOT,
|
| + load_result_param,
|
| + new (I) TypeNode(Scanner::kNoSourcePos, future_type));
|
| + preamble_->Add(new(I) IfNode(Scanner::kNoSourcePos,
|
| + is_not_future_test,
|
| + is_not_future_branch,
|
| + NULL));
|
| +
|
| + AwaitMarkerNode* await_marker = new (I) AwaitMarkerNode();
|
| + await_marker->set_scope(preamble_->scope());
|
| + GetVariableInScope(preamble_->scope(), Symbols::AwaitJumpVar());
|
| + GetVariableInScope(preamble_->scope(), Symbols::AwaitContextVar());
|
| + preamble_->Add(await_marker);
|
| ArgumentListNode* args = new(I) ArgumentListNode(Scanner::kNoSourcePos);
|
| +
|
| args->Add(new(I) LoadLocalNode(Scanner::kNoSourcePos, async_op));
|
| - is_future_branch->Add(new (I) StoreLocalNode(
|
| + preamble_->Add(new (I) StoreLocalNode(
|
| Scanner::kNoSourcePos,
|
| result_param,
|
| - new(I) InstanceCallNode(
|
| - Scanner::kNoSourcePos,
|
| - load_result_param,
|
| - Symbols::FutureThen(),
|
| - args)));
|
| + new(I) InstanceCallNode(Scanner::kNoSourcePos,
|
| + load_result_param,
|
| + Symbols::FutureThen(),
|
| + args)));
|
| const Library& core_lib = Library::Handle(Library::CoreLibrary());
|
| const Function& async_catch_helper = Function::ZoneHandle(
|
| I, core_lib.LookupFunctionAllowPrivate(Symbols::AsyncCatchHelper()));
|
| @@ -168,30 +202,14 @@
|
| catch_helper_args->Add(catch_error_getter);
|
| catch_helper_args->Add(new (I) LoadLocalNode(
|
| Scanner::kNoSourcePos, async_op));
|
| - is_future_branch->Add(new (I) StaticCallNode(
|
| + preamble_->Add(new (I) StaticCallNode(
|
| Scanner::kNoSourcePos,
|
| async_catch_helper,
|
| catch_helper_args));
|
| ReturnNode* continuation_return = new(I) ReturnNode(Scanner::kNoSourcePos);
|
| - continuation_return->set_return_type(ReturnNode::kContinuation);
|
| - is_future_branch->Add(continuation_return);
|
| + continuation_return->set_return_type(ReturnNode::kContinuationTarget);
|
| + preamble_->Add(continuation_return);
|
|
|
| - const Class& cls = Class::ZoneHandle(
|
| - I, library_.LookupClass(Symbols::Future()));
|
| - const AbstractType& future_type = AbstractType::ZoneHandle(I, cls.RareType());
|
| - ASSERT(!future_type.IsNull());
|
| - preamble_->Add(new(I) IfNode(
|
| - Scanner::kNoSourcePos,
|
| - new (I) ComparisonNode(
|
| - Scanner::kNoSourcePos,
|
| - Token::kIS,
|
| - load_result_param,
|
| - new (I) TypeNode(Scanner::kNoSourcePos, future_type)),
|
| - is_future_branch,
|
| - NULL));
|
| - preamble_->Add(new (I) AwaitMarkerNode(
|
| - AwaitMarkerNode::kTargetForContinuation));
|
| -
|
| // If this expression is part of a try block, also append the code for
|
| // restoring the saved try context that lives on the stack.
|
| const String& async_saved_try_ctx_name =
|
|
|