| Index: runtime/vm/ast_transformer.cc
|
| diff --git a/runtime/vm/ast_transformer.cc b/runtime/vm/ast_transformer.cc
|
| index ac3f9f1b9132178de3c66fbec754f6bed1718397..11cb61cabb661db8f66a1726ff8b1e2bf130c74a 100644
|
| --- a/runtime/vm/ast_transformer.cc
|
| +++ b/runtime/vm/ast_transformer.cc
|
| @@ -112,13 +112,9 @@ void AwaitTransformer::VisitAwaitNode(AwaitNode* node) {
|
| // Await transformation:
|
| //
|
| // :await_temp_var_X = <expr>;
|
| - // :result_param = :await_temp_var_X;
|
| - // if (:result_param is !Future) {
|
| - // :result_param = Future.value(:result_param);
|
| - // }
|
| // AwaitMarker(kNewContinuationState);
|
| - // :result_param = :result_param.then(:async_op);
|
| - // _asyncCatchHelper(:result_param.catchError, :async_op);
|
| + // :result_param = _awaitHelper(
|
| + // :await_temp_var_X, :async_then_callback, :async_catch_error_callback);
|
| // return; // (return_type() == kContinuationTarget)
|
| //
|
| // :saved_try_ctx_var = :await_saved_try_ctx_var_y;
|
| @@ -126,6 +122,10 @@ void AwaitTransformer::VisitAwaitNode(AwaitNode* node) {
|
|
|
| LocalVariable* async_op = GetVariableInScope(
|
| preamble_->scope(), Symbols::AsyncOperation());
|
| + LocalVariable* async_then_callback = GetVariableInScope(
|
| + preamble_->scope(), Symbols::AsyncThenCallback());
|
| + LocalVariable* async_catch_error_callback = GetVariableInScope(
|
| + preamble_->scope(), Symbols::AsyncCatchErrorCallback());
|
| LocalVariable* result_param = GetVariableInScope(
|
| preamble_->scope(), Symbols::AsyncOperationParam());
|
| LocalVariable* error_param = GetVariableInScope(
|
| @@ -134,78 +134,34 @@ void AwaitTransformer::VisitAwaitNode(AwaitNode* node) {
|
| preamble_->scope(), Symbols::AsyncOperationStackTraceParam());
|
|
|
| AstNode* transformed_expr = Transform(node->expr());
|
| - preamble_->Add(new(Z) StoreLocalNode(
|
| - Scanner::kNoSourcePos, result_param, transformed_expr));
|
| -
|
| - LoadLocalNode* load_result_param = new(Z) LoadLocalNode(
|
| - Scanner::kNoSourcePos, result_param);
|
| -
|
| - const Class& future_cls =
|
| - Class::ZoneHandle(Z, thread()->isolate()->object_store()->future_class());
|
| - ASSERT(!future_cls.IsNull());
|
| - const AbstractType& future_type =
|
| - AbstractType::ZoneHandle(Z, future_cls.RareType());
|
| - ASSERT(!future_type.IsNull());
|
| -
|
| - LocalScope* is_not_future_scope = ChainNewScope(preamble_->scope());
|
| - SequenceNode* is_not_future_branch =
|
| - new (Z) SequenceNode(Scanner::kNoSourcePos, is_not_future_scope);
|
| -
|
| - // if (:result_param is !Future) {
|
| - // :result_param = Future.value(:result_param);
|
| - // }
|
| - const Function& value_ctor = Function::ZoneHandle(
|
| - Z, future_cls.LookupFunction(Symbols::FutureValue()));
|
| - ASSERT(!value_ctor.IsNull());
|
| - ArgumentListNode* ctor_args = new (Z) ArgumentListNode(Scanner::kNoSourcePos);
|
| - ctor_args->Add(new (Z) LoadLocalNode(Scanner::kNoSourcePos, result_param));
|
| - ConstructorCallNode* ctor_call =
|
| - new (Z) ConstructorCallNode(Scanner::kNoSourcePos,
|
| - TypeArguments::ZoneHandle(Z),
|
| - value_ctor,
|
| - ctor_args);
|
| - is_not_future_branch->Add(new (Z) StoreLocalNode(
|
| - Scanner::kNoSourcePos, result_param, ctor_call));
|
| - AstNode* is_not_future_test = new (Z) ComparisonNode(
|
| - Scanner::kNoSourcePos,
|
| - Token::kISNOT,
|
| - load_result_param,
|
| - new (Z) TypeNode(Scanner::kNoSourcePos, future_type));
|
| - preamble_->Add(new(Z) IfNode(Scanner::kNoSourcePos,
|
| - is_not_future_test,
|
| - is_not_future_branch,
|
| - NULL));
|
| + LocalVariable* await_temp = AddToPreambleNewTempVar(transformed_expr);
|
|
|
| AwaitMarkerNode* await_marker = new (Z) AwaitMarkerNode();
|
| await_marker->set_scope(preamble_->scope());
|
| preamble_->Add(await_marker);
|
| - ArgumentListNode* args = new(Z) ArgumentListNode(Scanner::kNoSourcePos);
|
|
|
| - args->Add(new(Z) LoadLocalNode(Scanner::kNoSourcePos, async_op));
|
| - preamble_->Add(new (Z) StoreLocalNode(
|
| - Scanner::kNoSourcePos,
|
| - result_param,
|
| - new(Z) InstanceCallNode(node->token_pos(),
|
| - load_result_param,
|
| - Symbols::FutureThen(),
|
| - args)));
|
| - const Library& core_lib = Library::Handle(Library::CoreLibrary());
|
| - const Function& async_catch_helper = Function::ZoneHandle(
|
| - Z, core_lib.LookupFunctionAllowPrivate(Symbols::AsyncCatchHelper()));
|
| - ASSERT(!async_catch_helper.IsNull());
|
| - ArgumentListNode* catch_helper_args = new (Z) ArgumentListNode(
|
| + // :result_param = _awaitHelper(
|
| + // :await_temp, :async_then_callback, :async_catch_error_callback)
|
| + const Library& async_lib = Library::Handle(Library::AsyncLibrary());
|
| + const Function& async_await_helper = Function::ZoneHandle(
|
| + Z, async_lib.LookupFunctionAllowPrivate(Symbols::AsyncAwaitHelper()));
|
| + ASSERT(!async_await_helper.IsNull());
|
| + ArgumentListNode* async_await_helper_args = new (Z) ArgumentListNode(
|
| Scanner::kNoSourcePos);
|
| - InstanceGetterNode* catch_error_getter = new (Z) InstanceGetterNode(
|
| - Scanner::kNoSourcePos,
|
| - load_result_param,
|
| - Symbols::FutureCatchError());
|
| - catch_helper_args->Add(catch_error_getter);
|
| - catch_helper_args->Add(new (Z) LoadLocalNode(
|
| - Scanner::kNoSourcePos, async_op));
|
| - preamble_->Add(new (Z) StaticCallNode(
|
| - Scanner::kNoSourcePos,
|
| - async_catch_helper,
|
| - catch_helper_args));
|
| + async_await_helper_args->Add(
|
| + new(Z) LoadLocalNode(Scanner::kNoSourcePos, await_temp));
|
| + async_await_helper_args->Add(
|
| + new(Z) LoadLocalNode(Scanner::kNoSourcePos, async_then_callback));
|
| + async_await_helper_args->Add(
|
| + new(Z) LoadLocalNode(Scanner::kNoSourcePos, async_catch_error_callback));
|
| + StaticCallNode* await_helper_call = new (Z) StaticCallNode(
|
| + node->token_pos(),
|
| + async_await_helper,
|
| + async_await_helper_args);
|
| +
|
| + preamble_->Add(new(Z) StoreLocalNode(
|
| + Scanner::kNoSourcePos, result_param, await_helper_call));
|
| +
|
| ReturnNode* continuation_return = new(Z) ReturnNode(Scanner::kNoSourcePos);
|
| continuation_return->set_return_type(ReturnNode::kContinuationTarget);
|
| preamble_->Add(continuation_return);
|
| @@ -230,6 +186,12 @@ void AwaitTransformer::VisitAwaitNode(AwaitNode* node) {
|
| ASSERT(node->outer_saved_try_ctx() == NULL);
|
| }
|
|
|
| + // Load the async_op variable. It is unused, but the observatory uses it
|
| + // to determine if a breakpoint is inside an asynchronous function.
|
| + LoadLocalNode* load_async_op = new (Z) LoadLocalNode(
|
| + Scanner::kNoSourcePos, async_op);
|
| + preamble_->Add(load_async_op);
|
| +
|
| LoadLocalNode* load_error_param = new (Z) LoadLocalNode(
|
| Scanner::kNoSourcePos, error_param);
|
| LoadLocalNode* load_stack_trace_param = new (Z) LoadLocalNode(
|
|
|