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

Side by Side Diff: runtime/vm/ast_transformer.cc

Issue 634603002: Await always waits (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 2 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/ast_transformer.h" 5 #include "vm/ast_transformer.h"
6 6
7 #include "vm/object_store.h"
7 #include "vm/parser.h" 8 #include "vm/parser.h"
8 9
9 namespace dart { 10 namespace dart {
10 11
11 // Quick access to the locally defined isolate() method. 12 // Quick access to the locally defined isolate() method.
12 #define I (isolate()) 13 #define I (isolate())
13 14
14 // Nodes that are unreachable from already parsed expressions. 15 // Nodes that are unreachable from already parsed expressions.
15 #define FOR_EACH_UNREACHABLE_NODE(V) \ 16 #define FOR_EACH_UNREACHABLE_NODE(V) \
16 V(AwaitMarker) \ 17 V(AwaitMarker) \
(...skipping 19 matching lines...) Expand all
36 37
37 #define DEFINE_UNREACHABLE(BaseName) \ 38 #define DEFINE_UNREACHABLE(BaseName) \
38 void AwaitTransformer::Visit##BaseName##Node(BaseName##Node* node) { \ 39 void AwaitTransformer::Visit##BaseName##Node(BaseName##Node* node) { \
39 UNREACHABLE(); \ 40 UNREACHABLE(); \
40 } 41 }
41 42
42 FOR_EACH_UNREACHABLE_NODE(DEFINE_UNREACHABLE) 43 FOR_EACH_UNREACHABLE_NODE(DEFINE_UNREACHABLE)
43 #undef DEFINE_UNREACHABLE 44 #undef DEFINE_UNREACHABLE
44 45
45 AwaitTransformer::AwaitTransformer(SequenceNode* preamble, 46 AwaitTransformer::AwaitTransformer(SequenceNode* preamble,
46 const Library& library,
47 ParsedFunction* const parsed_function, 47 ParsedFunction* const parsed_function,
48 LocalScope* function_top) 48 LocalScope* function_top)
49 : preamble_(preamble), 49 : preamble_(preamble),
50 temp_cnt_(0), 50 temp_cnt_(0),
51 library_(library),
52 parsed_function_(parsed_function), 51 parsed_function_(parsed_function),
53 function_top_(function_top), 52 function_top_(function_top),
54 isolate_(Isolate::Current()) { 53 isolate_(Isolate::Current()) {
55 ASSERT(function_top_ != NULL); 54 ASSERT(function_top_ != NULL);
56 } 55 }
57 56
58 57
59 AstNode* AwaitTransformer::Transform(AstNode* expr) { 58 AstNode* AwaitTransformer::Transform(AstNode* expr) {
60 expr->Visit(this); 59 expr->Visit(this);
61 return result_; 60 return result_;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 void AwaitTransformer::VisitTypeNode(TypeNode* node) { 106 void AwaitTransformer::VisitTypeNode(TypeNode* node) {
108 result_ = new(I) TypeNode(node->token_pos(), node->type()); 107 result_ = new(I) TypeNode(node->token_pos(), node->type());
109 } 108 }
110 109
111 110
112 void AwaitTransformer::VisitAwaitNode(AwaitNode* node) { 111 void AwaitTransformer::VisitAwaitNode(AwaitNode* node) {
113 // Await transformation: 112 // Await transformation:
114 // 113 //
115 // :await_temp_var_X = <expr>; 114 // :await_temp_var_X = <expr>;
116 // :result_param = :await_temp_var_X; 115 // :result_param = :await_temp_var_X;
117 // if (:result_param is Future) { 116 // if (:result_param is !Future) {
118 // AwaitMarker(kNewContinuationState); 117 // :result_param = Future.value(:result_param);
119 // :result_param = :result_param.then(:async_op);
120 // _asyncCatchHelper(:result_param.catchError, :async_op);
121 // return; // (return_type() == kContinuation)
122 // } 118 // }
123 // AwaitMarker(kTargetForContinuation); // Join happens here. 119 // AwaitMarker(kNewContinuationState);
120 // :result_param = :result_param.then(:async_op);
121 // _asyncCatchHelper(:result_param.catchError, :async_op);
122 // return; // (return_type() == kContinuationTarget)
123 //
124 // :saved_try_ctx_var = :await_saved_try_ctx_var_y; 124 // :saved_try_ctx_var = :await_saved_try_ctx_var_y;
125 // :await_temp_var_(X+1) = :result_param; 125 // :await_temp_var_(X+1) = :result_param;
126 126
127 LocalVariable* async_op = GetVariableInScope( 127 LocalVariable* async_op = GetVariableInScope(
128 preamble_->scope(), Symbols::AsyncOperation()); 128 preamble_->scope(), Symbols::AsyncOperation());
129 LocalVariable* result_param = GetVariableInScope( 129 LocalVariable* result_param = GetVariableInScope(
130 preamble_->scope(), Symbols::AsyncOperationParam()); 130 preamble_->scope(), Symbols::AsyncOperationParam());
131 LocalVariable* error_param = GetVariableInScope( 131 LocalVariable* error_param = GetVariableInScope(
132 preamble_->scope(), Symbols::AsyncOperationErrorParam()); 132 preamble_->scope(), Symbols::AsyncOperationErrorParam());
133 133
134 node->expr()->Visit(this); 134 AstNode* transformed_expr = Transform(node->expr());
135 preamble_->Add(new(I) StoreLocalNode( 135 preamble_->Add(new(I) StoreLocalNode(
136 Scanner::kNoSourcePos, result_param, result_)); 136 Scanner::kNoSourcePos, result_param, transformed_expr));
137
137 LoadLocalNode* load_result_param = new(I) LoadLocalNode( 138 LoadLocalNode* load_result_param = new(I) LoadLocalNode(
138 Scanner::kNoSourcePos, result_param); 139 Scanner::kNoSourcePos, result_param);
139 LocalScope* is_future_scope = ChainNewScope(preamble_->scope()); 140
140 SequenceNode* is_future_branch = new (I) SequenceNode( 141 const Class& future_cls =
141 Scanner::kNoSourcePos, is_future_scope); 142 Class::ZoneHandle(I, I->object_store()->future_class());
142 AwaitMarkerNode* await_marker = new (I) AwaitMarkerNode( 143 ASSERT(!future_cls.IsNull());
143 AwaitMarkerNode::kNewContinuationState); 144 const AbstractType& future_type =
144 await_marker->set_scope(is_future_scope); 145 AbstractType::ZoneHandle(I, future_cls.RareType());
145 GetVariableInScope(is_future_scope, Symbols::AwaitJumpVar()); 146 ASSERT(!future_type.IsNull());
146 GetVariableInScope(is_future_scope, Symbols::AwaitContextVar()); 147
147 is_future_branch->Add(await_marker); 148 LocalScope* is_not_future_scope = ChainNewScope(preamble_->scope());
149 SequenceNode* is_not_future_branch =
150 new (I) SequenceNode(Scanner::kNoSourcePos, is_not_future_scope);
151
152 // if (:result_param is !Future) {
153 // :result_param = Future.value(:result_param);
154 // }
155 const Function& value_ctor = Function::ZoneHandle(
156 I, future_cls.LookupFunction(Symbols::FutureValue()));
157 ASSERT(!value_ctor.IsNull());
158 ArgumentListNode* ctor_args = new (I) ArgumentListNode(Scanner::kNoSourcePos);
159 ctor_args->Add(new (I) LoadLocalNode(Scanner::kNoSourcePos, result_param));
160 ConstructorCallNode* ctor_call =
161 new (I) ConstructorCallNode(Scanner::kNoSourcePos,
162 TypeArguments::ZoneHandle(I),
163 value_ctor,
164 ctor_args);
165 is_not_future_branch->Add(new (I) StoreLocalNode(
166 Scanner::kNoSourcePos, result_param, ctor_call));
167 AstNode* is_not_future_test = new (I) ComparisonNode(
168 Scanner::kNoSourcePos,
169 Token::kISNOT,
170 load_result_param,
171 new (I) TypeNode(Scanner::kNoSourcePos, future_type));
172 preamble_->Add(new(I) IfNode(Scanner::kNoSourcePos,
173 is_not_future_test,
174 is_not_future_branch,
175 NULL));
176
177 AwaitMarkerNode* await_marker = new (I) AwaitMarkerNode();
178 await_marker->set_scope(preamble_->scope());
179 GetVariableInScope(preamble_->scope(), Symbols::AwaitJumpVar());
Florian Schneider 2014/10/14 11:47:30 It looks a little strange that the result of this
Florian Schneider 2014/10/14 15:04:37 I tried fixing this in my CL (https://codereview.c
hausner 2014/10/14 19:56:39 Let's move these with your change list, as a separ
180 GetVariableInScope(preamble_->scope(), Symbols::AwaitContextVar());
Florian Schneider 2014/10/14 11:47:30 Same question for this variable.
181 preamble_->Add(await_marker);
148 ArgumentListNode* args = new(I) ArgumentListNode(Scanner::kNoSourcePos); 182 ArgumentListNode* args = new(I) ArgumentListNode(Scanner::kNoSourcePos);
183
149 args->Add(new(I) LoadLocalNode(Scanner::kNoSourcePos, async_op)); 184 args->Add(new(I) LoadLocalNode(Scanner::kNoSourcePos, async_op));
150 is_future_branch->Add(new (I) StoreLocalNode( 185 preamble_->Add(new (I) StoreLocalNode(
151 Scanner::kNoSourcePos, 186 Scanner::kNoSourcePos,
152 result_param, 187 result_param,
153 new(I) InstanceCallNode( 188 new(I) InstanceCallNode(Scanner::kNoSourcePos,
154 Scanner::kNoSourcePos, 189 load_result_param,
155 load_result_param, 190 Symbols::FutureThen(),
156 Symbols::FutureThen(), 191 args)));
157 args)));
158 const Library& core_lib = Library::Handle(Library::CoreLibrary()); 192 const Library& core_lib = Library::Handle(Library::CoreLibrary());
159 const Function& async_catch_helper = Function::ZoneHandle( 193 const Function& async_catch_helper = Function::ZoneHandle(
160 I, core_lib.LookupFunctionAllowPrivate(Symbols::AsyncCatchHelper())); 194 I, core_lib.LookupFunctionAllowPrivate(Symbols::AsyncCatchHelper()));
161 ASSERT(!async_catch_helper.IsNull()); 195 ASSERT(!async_catch_helper.IsNull());
162 ArgumentListNode* catch_helper_args = new (I) ArgumentListNode( 196 ArgumentListNode* catch_helper_args = new (I) ArgumentListNode(
163 Scanner::kNoSourcePos); 197 Scanner::kNoSourcePos);
164 InstanceGetterNode* catch_error_getter = new (I) InstanceGetterNode( 198 InstanceGetterNode* catch_error_getter = new (I) InstanceGetterNode(
165 Scanner::kNoSourcePos, 199 Scanner::kNoSourcePos,
166 load_result_param, 200 load_result_param,
167 Symbols::FutureCatchError()); 201 Symbols::FutureCatchError());
168 catch_helper_args->Add(catch_error_getter); 202 catch_helper_args->Add(catch_error_getter);
169 catch_helper_args->Add(new (I) LoadLocalNode( 203 catch_helper_args->Add(new (I) LoadLocalNode(
170 Scanner::kNoSourcePos, async_op)); 204 Scanner::kNoSourcePos, async_op));
171 is_future_branch->Add(new (I) StaticCallNode( 205 preamble_->Add(new (I) StaticCallNode(
172 Scanner::kNoSourcePos, 206 Scanner::kNoSourcePos,
173 async_catch_helper, 207 async_catch_helper,
174 catch_helper_args)); 208 catch_helper_args));
175 ReturnNode* continuation_return = new(I) ReturnNode(Scanner::kNoSourcePos); 209 ReturnNode* continuation_return = new(I) ReturnNode(Scanner::kNoSourcePos);
176 continuation_return->set_return_type(ReturnNode::kContinuation); 210 continuation_return->set_return_type(ReturnNode::kContinuationTarget);
177 is_future_branch->Add(continuation_return); 211 preamble_->Add(continuation_return);
178
179 const Class& cls = Class::ZoneHandle(
180 I, library_.LookupClass(Symbols::Future()));
181 const AbstractType& future_type = AbstractType::ZoneHandle(I, cls.RareType());
182 ASSERT(!future_type.IsNull());
183 preamble_->Add(new(I) IfNode(
184 Scanner::kNoSourcePos,
185 new (I) ComparisonNode(
186 Scanner::kNoSourcePos,
187 Token::kIS,
188 load_result_param,
189 new (I) TypeNode(Scanner::kNoSourcePos, future_type)),
190 is_future_branch,
191 NULL));
192 preamble_->Add(new (I) AwaitMarkerNode(
193 AwaitMarkerNode::kTargetForContinuation));
194 212
195 // If this expression is part of a try block, also append the code for 213 // If this expression is part of a try block, also append the code for
196 // restoring the saved try context that lives on the stack. 214 // restoring the saved try context that lives on the stack.
197 const String& async_saved_try_ctx_name = 215 const String& async_saved_try_ctx_name =
198 String::Handle(I, parsed_function_->async_saved_try_ctx_name()); 216 String::Handle(I, parsed_function_->async_saved_try_ctx_name());
199 if (!async_saved_try_ctx_name.IsNull()) { 217 if (!async_saved_try_ctx_name.IsNull()) {
200 LocalVariable* async_saved_try_ctx = 218 LocalVariable* async_saved_try_ctx =
201 GetVariableInScope(preamble_->scope(), async_saved_try_ctx_name); 219 GetVariableInScope(preamble_->scope(), async_saved_try_ctx_name);
202 preamble_->Add(new (I) StoreLocalNode( 220 preamble_->Add(new (I) StoreLocalNode(
203 Scanner::kNoSourcePos, 221 Scanner::kNoSourcePos,
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after
584 void AwaitTransformer::VisitThrowNode(ThrowNode* node) { 602 void AwaitTransformer::VisitThrowNode(ThrowNode* node) {
585 // TODO(mlippautz): Check if relevant. 603 // TODO(mlippautz): Check if relevant.
586 AstNode* new_exception = Transform(node->exception()); 604 AstNode* new_exception = Transform(node->exception());
587 AstNode* new_stacktrace = Transform(node->stacktrace()); 605 AstNode* new_stacktrace = Transform(node->stacktrace());
588 result_ = new(I) ThrowNode(node->token_pos(), 606 result_ = new(I) ThrowNode(node->token_pos(),
589 new_exception, 607 new_exception,
590 new_stacktrace); 608 new_stacktrace);
591 } 609 }
592 610
593 } // namespace dart 611 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698