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

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

Issue 1079233002: Simplify restoring of saved try contexts in async code by passing around the (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 8 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
« no previous file with comments | « runtime/vm/parser.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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/parser.h" 5 #include "vm/parser.h"
6 6
7 #include "lib/invocation_mirror.h" 7 #include "lib/invocation_mirror.h"
8 #include "platform/utils.h" 8 #include "platform/utils.h"
9 #include "vm/ast_transformer.h" 9 #include "vm/ast_transformer.h"
10 #include "vm/bootstrap.h" 10 #include "vm/bootstrap.h"
(...skipping 8237 matching lines...) Expand 10 before | Expand all | Expand 10 after
8248 await_cond->AddNode(await_preamble); 8248 await_cond->AddNode(await_preamble);
8249 await_cond->AddNode(cond_expr); 8249 await_cond->AddNode(cond_expr);
8250 cond_expr = await_cond; 8250 cond_expr = await_cond;
8251 } 8251 }
8252 ExpectToken(Token::kRPAREN); 8252 ExpectToken(Token::kRPAREN);
8253 ExpectSemicolon(); 8253 ExpectSemicolon();
8254 return new(Z) DoWhileNode(do_pos, label, cond_expr, dowhile_body); 8254 return new(Z) DoWhileNode(do_pos, label, cond_expr, dowhile_body);
8255 } 8255 }
8256 8256
8257 8257
8258 static LocalVariable* LookupSavedTryContextVar(LocalScope* scope) {
8259 LocalVariable* var =
8260 scope->LocalLookupVariable(Symbols::SavedTryContextVar());
8261 ASSERT((var != NULL) && !var->is_captured());
8262 return var;
8263 }
8264
8265
8266 static LocalVariable* LookupAsyncSavedTryContextVar(LocalScope* scope,
8267 uint16_t try_index) {
8268 const String& async_saved_try_ctx_name =
8269 String::ZoneHandle(Symbols::New(String::Handle(
8270 String::NewFormatted(
8271 "%s%d",
8272 Symbols::AsyncSavedTryCtxVarPrefix().ToCString(),
8273 try_index))));
8274 LocalVariable* var = scope->LocalLookupVariable(async_saved_try_ctx_name);
8275 ASSERT((var != NULL) && var->is_captured());\
8276 return var;
8277 }
8278
8279
8258 // If the await or yield being parsed is in a try block, the continuation code 8280 // If the await or yield being parsed is in a try block, the continuation code
8259 // needs to restore the corresponding stack-based variable :saved_try_ctx_var, 8281 // needs to restore the corresponding stack-based variable :saved_try_ctx_var,
8260 // and the stack-based variable :saved_try_ctx_var of the outer try block. 8282 // and the stack-based variable :saved_try_ctx_var of the outer try block.
8261 // The inner :saved_try_ctx_var is used by a finally clause handling an 8283 // The inner :saved_try_ctx_var is used by a finally clause handling an
8262 // exception thrown by the continuation code in a try block or catch block. 8284 // exception thrown by the continuation code in a try block or catch block.
8263 // If no finally clause exists, the catch or finally clause of the outer try 8285 // If no finally clause exists, the catch or finally clause of the outer try
8264 // block, if any, uses the outer :saved_try_ctx_var to handle the exception. 8286 // block, if any, uses the outer :saved_try_ctx_var to handle the exception.
8265 // 8287 //
8266 // * Try blocks and catch blocks: 8288 // * Try blocks and catch blocks:
8267 // Set the context variable for this try block and for the outer try block. 8289 // Set the context variable for this try block and for the outer try block.
8268 // * Finally blocks: 8290 // * Finally blocks:
8269 // Set the context variable for the outer try block. Note that the try 8291 // Set the context variable for the outer try block. Note that the try
8270 // declaring the finally is popped before parsing the finally clause, so the 8292 // declaring the finally is popped before parsing the finally clause, so the
8271 // outer try block is at the top of the try block list. 8293 // outer try block is at the top of the try block list.
8272 // 8294 void Parser::CheckAsyncOpInTryBlock(
8273 // TODO(regis): Could we return the variables instead of their containing 8295 LocalVariable** saved_try_ctx,
8274 // scopes? Check if they are already setup at this point. 8296 LocalVariable** async_saved_try_ctx,
8275 void Parser::CheckAsyncOpInTryBlock(LocalScope** try_scope, 8297 LocalVariable** outer_saved_try_ctx,
8276 int16_t* try_index, 8298 LocalVariable** outer_async_saved_try_ctx) const {
8277 LocalScope** outer_try_scope, 8299 *saved_try_ctx = NULL;
8278 int16_t* outer_try_index) const { 8300 *async_saved_try_ctx = NULL;
8279 *try_scope = NULL; 8301 *outer_saved_try_ctx = NULL;
8280 *try_index = CatchClauseNode::kInvalidTryIndex; 8302 *outer_async_saved_try_ctx = NULL;
8281 *outer_try_scope = NULL;
8282 *outer_try_index = CatchClauseNode::kInvalidTryIndex;
8283 if (try_stack_ != NULL) { 8303 if (try_stack_ != NULL) {
8284 LocalScope* scope = try_stack_->try_block()->scope; 8304 LocalScope* scope = try_stack_->try_block()->scope;
8305 uint16_t try_index = try_stack_->try_index();
8285 const int current_function_level = current_block_->scope->function_level(); 8306 const int current_function_level = current_block_->scope->function_level();
8286 if (scope->function_level() == current_function_level) { 8307 if (scope->function_level() == current_function_level) {
8287 // The block declaring :saved_try_ctx_var variable is the parent of the 8308 // The block declaring :saved_try_ctx_var variable is the parent of the
8288 // pushed try block. 8309 // pushed try block.
8289 *try_scope = scope->parent(); 8310 *saved_try_ctx = LookupSavedTryContextVar(scope->parent());
8290 *try_index = try_stack_->try_index(); 8311 *async_saved_try_ctx = LookupAsyncSavedTryContextVar(scope, try_index);
8291 if (try_stack_->outer_try() != NULL) { 8312 if (try_stack_->outer_try() != NULL) {
8292 // TODO(regis): Collecting the outer try scope is not necessary if we 8313 // TODO(regis): Collecting the outer try scope is not necessary if we
8293 // are in a finally block. Add support for try_stack_->inside_finally(). 8314 // are in a finally block. Add support for try_stack_->inside_finally().
8294 scope = try_stack_->outer_try()->try_block()->scope; 8315 scope = try_stack_->outer_try()->try_block()->scope;
8316 try_index = try_stack_->outer_try()->try_index();
8295 if (scope->function_level() == current_function_level) { 8317 if (scope->function_level() == current_function_level) {
8296 *outer_try_scope = scope->parent(); 8318 *outer_saved_try_ctx = LookupSavedTryContextVar(scope->parent());
8297 *outer_try_index = try_stack_->outer_try()->try_index(); 8319 *outer_async_saved_try_ctx =
8320 LookupAsyncSavedTryContextVar(scope, try_index);
8298 } 8321 }
8299 } 8322 }
8300 } 8323 }
8301 } 8324 }
8302 // An async or async* has an implicitly created try-catch around the 8325 // An async or async* has an implicitly created try-catch around the
8303 // function body, so the await or yield inside the async closure should always 8326 // function body, so the await or yield inside the async closure should always
8304 // be created with a try scope. 8327 // be created with a try scope.
8305 ASSERT((*try_scope != NULL) || 8328 ASSERT((*saved_try_ctx != NULL) ||
8306 innermost_function().IsAsyncFunction() || 8329 innermost_function().IsAsyncFunction() ||
8307 innermost_function().IsAsyncGenerator() || 8330 innermost_function().IsAsyncGenerator() ||
8308 innermost_function().IsSyncGenClosure() || 8331 innermost_function().IsSyncGenClosure() ||
8309 innermost_function().IsSyncGenerator()); 8332 innermost_function().IsSyncGenerator());
8310 } 8333 }
8311 8334
8312 8335
8313 // Build an AST node for static call to Dart function print(str). 8336 // Build an AST node for static call to Dart function print(str).
8314 // Used during debugging to insert print in generated dart code. 8337 // Used during debugging to insert print in generated dart code.
8315 AstNode* Parser::DartPrint(const char* str) { 8338 AstNode* Parser::DartPrint(const char* str) {
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
8419 &exception_var, 8442 &exception_var,
8420 &stack_trace_var, 8443 &stack_trace_var,
8421 &saved_exception_var, 8444 &saved_exception_var,
8422 &saved_stack_trace_var); 8445 &saved_stack_trace_var);
8423 OpenBlock(); // try block. 8446 OpenBlock(); // try block.
8424 PushTry(current_block_); 8447 PushTry(current_block_);
8425 SetupSavedTryContext(context_var); 8448 SetupSavedTryContext(context_var);
8426 8449
8427 // Build while loop condition. 8450 // Build while loop condition.
8428 // while (await :for-in-iter.moveNext()) 8451 // while (await :for-in-iter.moveNext())
8429 LocalScope* try_scope; 8452 LocalVariable* saved_try_ctx;
8430 int16_t try_index; 8453 LocalVariable* async_saved_try_ctx;
8431 LocalScope* outer_try_scope; 8454 LocalVariable* outer_saved_try_ctx;
8432 int16_t outer_try_index; 8455 LocalVariable* outer_async_saved_try_ctx;
8433 CheckAsyncOpInTryBlock(&try_scope, &try_index, 8456 CheckAsyncOpInTryBlock(&saved_try_ctx,
8434 &outer_try_scope, &outer_try_index); 8457 &async_saved_try_ctx,
8435 8458 &outer_saved_try_ctx,
8459 &outer_async_saved_try_ctx);
8436 ArgumentListNode* no_args = new(Z) ArgumentListNode(stream_pos); 8460 ArgumentListNode* no_args = new(Z) ArgumentListNode(stream_pos);
8437 AstNode* iterator_moveNext = new(Z) InstanceCallNode( 8461 AstNode* iterator_moveNext = new(Z) InstanceCallNode(
8438 stream_pos, 8462 stream_pos,
8439 new(Z) LoadLocalNode(stream_pos, iterator_var), 8463 new(Z) LoadLocalNode(stream_pos, iterator_var),
8440 Symbols::MoveNext(), 8464 Symbols::MoveNext(),
8441 no_args); 8465 no_args);
8442 AstNode* await_moveNext = 8466 AstNode* await_moveNext =
8443 new(Z) AwaitNode(stream_pos, 8467 new(Z) AwaitNode(stream_pos,
8444 iterator_moveNext, 8468 iterator_moveNext,
8445 try_scope, 8469 saved_try_ctx,
8446 try_index, 8470 async_saved_try_ctx,
8447 outer_try_scope, 8471 outer_saved_try_ctx,
8448 outer_try_index); 8472 outer_async_saved_try_ctx);
8449 OpenBlock(); 8473 OpenBlock();
8450 AwaitTransformer at(current_block_->statements, async_temp_scope_); 8474 AwaitTransformer at(current_block_->statements, async_temp_scope_);
8451 await_moveNext = at.Transform(await_moveNext); 8475 await_moveNext = at.Transform(await_moveNext);
8452 SequenceNode* await_preamble = CloseBlock(); 8476 SequenceNode* await_preamble = CloseBlock();
8453 8477
8454 // Parse the for loop body. Ideally, we would use ParseNestedStatement() 8478 // Parse the for loop body. Ideally, we would use ParseNestedStatement()
8455 // here, but that does not work well because we have to insert an implicit 8479 // here, but that does not work well because we have to insert an implicit
8456 // variable assignment and potentially a variable declaration in the 8480 // variable assignment and potentially a variable declaration in the
8457 // loop body. 8481 // loop body.
8458 OpenLoopBlock(); 8482 OpenLoopBlock();
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
8516 for_loop_block); 8540 for_loop_block);
8517 // Add the while loop to the try block. 8541 // Add the while loop to the try block.
8518 current_block_->statements->Add(while_node); 8542 current_block_->statements->Add(while_node);
8519 SequenceNode* try_block = CloseBlock(); 8543 SequenceNode* try_block = CloseBlock();
8520 8544
8521 // Create an empty "catch all" block that rethrows the current 8545 // Create an empty "catch all" block that rethrows the current
8522 // exception and stacktrace. 8546 // exception and stacktrace.
8523 try_stack_->enter_catch(); 8547 try_stack_->enter_catch();
8524 SequenceNode* catch_block = new(Z) SequenceNode(await_for_pos, NULL); 8548 SequenceNode* catch_block = new(Z) SequenceNode(await_for_pos, NULL);
8525 8549
8526 if (outer_try_scope != NULL) { 8550 if (outer_saved_try_ctx != NULL) {
8527 catch_block->Add(AwaitTransformer::RestoreSavedTryContext( 8551 catch_block->Add(new (Z) StoreLocalNode(
8528 Z, outer_try_scope, outer_try_index)); 8552 Scanner::kNoSourcePos,
8553 outer_saved_try_ctx,
8554 new (Z) LoadLocalNode(Scanner::kNoSourcePos,
8555 outer_async_saved_try_ctx)));
8529 } 8556 }
8530 8557
8531 // We don't need to copy the current exception and stack trace variables 8558 // We don't need to copy the current exception and stack trace variables
8532 // into :saved_exception_var and :saved_stack_trace_var here because there 8559 // into :saved_exception_var and :saved_stack_trace_var here because there
8533 // is no code in the catch clause that could suspend the function. 8560 // is no code in the catch clause that could suspend the function.
8534 8561
8535 // Rethrow the exception. 8562 // Rethrow the exception.
8536 catch_block->Add(new(Z) ThrowNode( 8563 catch_block->Add(new(Z) ThrowNode(
8537 await_for_pos, 8564 await_for_pos,
8538 new(Z) LoadLocalNode(await_for_pos, exception_var), 8565 new(Z) LoadLocalNode(await_for_pos, exception_var),
8539 new(Z) LoadLocalNode(await_for_pos, stack_trace_var))); 8566 new(Z) LoadLocalNode(await_for_pos, stack_trace_var)));
8540 8567
8541 TryStack* try_statement = PopTry(); 8568 TryStack* try_statement = PopTry();
8542 ASSERT(try_index == try_statement->try_index()); 8569 const intptr_t try_index = try_statement->try_index();
8570 TryStack* outer_try = try_stack_;
8571 const intptr_t outer_try_index = (outer_try != NULL) ?
8572 outer_try->try_index() : CatchClauseNode::kInvalidTryIndex;
8543 8573
8544 // The finally block contains a call to cancel the stream. 8574 // The finally block contains a call to cancel the stream.
8545 // :for-in-iter.cancel() 8575 // :for-in-iter.cancel()
8546 8576
8547 // Inline the finally block to the exit points in the try block. 8577 // Inline the finally block to the exit points in the try block.
8548 intptr_t node_index = 0; 8578 intptr_t node_index = 0;
8549 SequenceNode* finally_clause = NULL; 8579 SequenceNode* finally_clause = NULL;
8550 do { 8580 do {
8551 OpenBlock(); 8581 OpenBlock();
8552 ArgumentListNode* no_args = 8582 ArgumentListNode* no_args =
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
8935 OpenBlock(); 8965 OpenBlock();
8936 ExpectToken(Token::kLBRACE); 8966 ExpectToken(Token::kLBRACE);
8937 8967
8938 // In case of async closures we need to restore the saved try index of an 8968 // In case of async closures we need to restore the saved try index of an
8939 // outer try block (if it exists). The current try block has already been 8969 // outer try block (if it exists). The current try block has already been
8940 // removed from the stack of try blocks. 8970 // removed from the stack of try blocks.
8941 if (is_async) { 8971 if (is_async) {
8942 if (try_stack_ != NULL) { 8972 if (try_stack_ != NULL) {
8943 LocalScope* scope = try_stack_->try_block()->scope; 8973 LocalScope* scope = try_stack_->try_block()->scope;
8944 if (scope->function_level() == current_block_->scope->function_level()) { 8974 if (scope->function_level() == current_block_->scope->function_level()) {
8975 LocalVariable* saved_try_ctx =
8976 LookupSavedTryContextVar(scope->parent());
8977 LocalVariable* async_saved_try_ctx =
8978 LookupAsyncSavedTryContextVar(scope->parent(),
8979 try_stack_->try_index());
8945 current_block_->statements->Add( 8980 current_block_->statements->Add(
8946 AwaitTransformer::RestoreSavedTryContext( 8981 new (Z) StoreLocalNode(
8947 Z, scope->parent(), try_stack_->try_index())); 8982 Scanner::kNoSourcePos,
8983 saved_try_ctx,
8984 new (Z) LoadLocalNode(Scanner::kNoSourcePos,
8985 async_saved_try_ctx)));
8948 } 8986 }
8949 } 8987 }
8950 // We need to save the exception variables as in catch clauses, whether 8988 // We need to save the exception variables as in catch clauses, whether
8951 // there is an outer try or not. Note that this is only necessary if the 8989 // there is an outer try or not. Note that this is only necessary if the
8952 // finally clause contains an await or yield. 8990 // finally clause contains an await or yield.
8953 // TODO(hausner): Optimize. 8991 // TODO(hausner): Optimize.
8954 SaveExceptionAndStacktrace(current_block_->statements, 8992 SaveExceptionAndStacktrace(current_block_->statements,
8955 exception_var, 8993 exception_var,
8956 stack_trace_var, 8994 stack_trace_var,
8957 rethrow_exception_var, 8995 rethrow_exception_var,
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
9195 current = CloseBlock(); 9233 current = CloseBlock();
9196 } 9234 }
9197 // In case of async closures, restore :saved_try_context_var before executing 9235 // In case of async closures, restore :saved_try_context_var before executing
9198 // the catch clauses. 9236 // the catch clauses.
9199 if (is_async && (current != NULL)) { 9237 if (is_async && (current != NULL)) {
9200 ASSERT(try_stack_ != NULL); 9238 ASSERT(try_stack_ != NULL);
9201 SequenceNode* async_code = new(Z) SequenceNode(handler_pos, NULL); 9239 SequenceNode* async_code = new(Z) SequenceNode(handler_pos, NULL);
9202 const TryStack* try_block = try_stack_->outer_try(); 9240 const TryStack* try_block = try_stack_->outer_try();
9203 if (try_block != NULL) { 9241 if (try_block != NULL) {
9204 LocalScope* scope = try_block->try_block()->scope; 9242 LocalScope* scope = try_block->try_block()->scope;
9205 if (scope->function_level() == 9243 if (scope->function_level() == current_block_->scope->function_level()) {
9206 current_block_->scope->function_level()) { 9244 LocalVariable* saved_try_ctx =
9207 async_code->Add( 9245 LookupSavedTryContextVar(scope->parent());
9208 AwaitTransformer::RestoreSavedTryContext( 9246 LocalVariable* async_saved_try_ctx =
9209 Z, scope->parent(), try_block->try_index())); 9247 LookupAsyncSavedTryContextVar(scope->parent(),
9248 try_block->try_index());
9249 current_block_->statements->Add(
9250 new (Z) StoreLocalNode(
9251 Scanner::kNoSourcePos,
9252 saved_try_ctx,
9253 new (Z) LoadLocalNode(Scanner::kNoSourcePos,
9254 async_saved_try_ctx)));
9210 } 9255 }
9211 } 9256 }
9212 SaveExceptionAndStacktrace(async_code, 9257 SaveExceptionAndStacktrace(async_code,
9213 exception_var, 9258 exception_var,
9214 stack_trace_var, 9259 stack_trace_var,
9215 rethrow_exception_var, 9260 rethrow_exception_var,
9216 rethrow_stack_trace_var); 9261 rethrow_stack_trace_var);
9217 // The async_code node sequence contains code to restore the context (if 9262 // The async_code node sequence contains code to restore the context (if
9218 // an outer try block is present) and code to save the exception and 9263 // an outer try block is present) and code to save the exception and
9219 // stack trace variables. 9264 // stack trace variables.
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
9565 yield->AddNode(await_marker); 9610 yield->AddNode(await_marker);
9566 // Return true to indicate that a value has been generated. 9611 // Return true to indicate that a value has been generated.
9567 ReturnNode* return_true = new(Z) ReturnNode(yield_pos, 9612 ReturnNode* return_true = new(Z) ReturnNode(yield_pos,
9568 new(Z) LiteralNode(TokenPos(), Bool::True())); 9613 new(Z) LiteralNode(TokenPos(), Bool::True()));
9569 return_true->set_return_type(ReturnNode::kContinuationTarget); 9614 return_true->set_return_type(ReturnNode::kContinuationTarget);
9570 yield->AddNode(return_true); 9615 yield->AddNode(return_true);
9571 9616
9572 // If this expression is part of a try block, also append the code for 9617 // If this expression is part of a try block, also append the code for
9573 // restoring the saved try context that lives on the stack and possibly the 9618 // restoring the saved try context that lives on the stack and possibly the
9574 // saved try context of the outer try block. 9619 // saved try context of the outer try block.
9575 LocalScope* try_scope; 9620 LocalVariable* saved_try_ctx;
9576 int16_t try_index; 9621 LocalVariable* async_saved_try_ctx;
9577 LocalScope* outer_try_scope; 9622 LocalVariable* outer_saved_try_ctx;
9578 int16_t outer_try_index; 9623 LocalVariable* outer_async_saved_try_ctx;
9579 CheckAsyncOpInTryBlock(&try_scope, &try_index, 9624 CheckAsyncOpInTryBlock(&saved_try_ctx,
9580 &outer_try_scope, &outer_try_index); 9625 &async_saved_try_ctx,
9581 if (try_scope != NULL) { 9626 &outer_saved_try_ctx,
9582 yield->AddNode( 9627 &outer_async_saved_try_ctx);
9583 AwaitTransformer::RestoreSavedTryContext(Z, 9628 if (saved_try_ctx != NULL) {
9584 try_scope, 9629 yield->AddNode(new (Z) StoreLocalNode(
9585 try_index)); 9630 Scanner::kNoSourcePos,
9586 if (outer_try_scope != NULL) { 9631 saved_try_ctx,
9587 yield->AddNode( 9632 new (Z) LoadLocalNode(Scanner::kNoSourcePos,
9588 AwaitTransformer::RestoreSavedTryContext(Z, 9633 async_saved_try_ctx)));
9589 outer_try_scope, 9634 if (outer_saved_try_ctx != NULL) {
9590 outer_try_index)); 9635 yield->AddNode(new (Z) StoreLocalNode(
9636 Scanner::kNoSourcePos,
9637 outer_saved_try_ctx,
9638 new (Z) LoadLocalNode(Scanner::kNoSourcePos,
9639 outer_async_saved_try_ctx)));
9591 } 9640 }
9592 } else { 9641 } else {
9593 ASSERT(outer_try_scope == NULL); 9642 ASSERT(outer_saved_try_ctx == NULL);
9594 } 9643 }
9595 } else { 9644 } else {
9596 // yield statement in async* function. 9645 // yield statement in async* function.
9597 ASSERT(innermost_function().IsAsyncGenerator() || 9646 ASSERT(innermost_function().IsAsyncGenerator() ||
9598 innermost_function().IsAsyncGenClosure()); 9647 innermost_function().IsAsyncGenClosure());
9599 9648
9600 LocalVariable* controller_var = LookupLocalScope(Symbols::Controller()); 9649 LocalVariable* controller_var = LookupLocalScope(Symbols::Controller());
9601 ASSERT(controller_var != NULL); 9650 ASSERT(controller_var != NULL);
9602 // :controller.add[Stream](expr); 9651 // :controller.add[Stream](expr);
9603 ArgumentListNode* add_args = new(Z) ArgumentListNode(yield_pos); 9652 ArgumentListNode* add_args = new(Z) ArgumentListNode(yield_pos);
9604 add_args->Add(expr); 9653 add_args->Add(expr);
9605 AstNode* add_call = 9654 AstNode* add_call =
9606 new(Z) InstanceCallNode(yield_pos, 9655 new(Z) InstanceCallNode(yield_pos,
9607 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller_var), 9656 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller_var),
9608 is_yield_each ? Symbols::AddStream() : Symbols::add(), 9657 is_yield_each ? Symbols::AddStream() : Symbols::add(),
9609 add_args); 9658 add_args);
9610 9659
9611
9612 // if (:controller.add[Stream](expr)) { 9660 // if (:controller.add[Stream](expr)) {
9613 // return; 9661 // return;
9614 // } 9662 // }
9615 // await_marker; 9663 // await_marker;
9616 // continuation_return; 9664 // continuation_return;
9617 // restore saved_try_context 9665 // restore saved_try_context
9618 9666
9619 SequenceNode* true_branch = 9667 SequenceNode* true_branch =
9620 new(Z) SequenceNode(Scanner::kNoSourcePos, NULL); 9668 new(Z) SequenceNode(Scanner::kNoSourcePos, NULL);
9621 AstNode* return_from_generator = new(Z) ReturnNode(yield_pos); 9669 AstNode* return_from_generator = new(Z) ReturnNode(yield_pos);
9622 true_branch->Add(return_from_generator); 9670 true_branch->Add(return_from_generator);
9623 AddNodeForFinallyInlining(return_from_generator); 9671 AddNodeForFinallyInlining(return_from_generator);
9624 AstNode* if_is_cancelled = 9672 AstNode* if_is_cancelled =
9625 new(Z) IfNode(Scanner::kNoSourcePos, add_call, true_branch, NULL); 9673 new(Z) IfNode(Scanner::kNoSourcePos, add_call, true_branch, NULL);
9626 yield->AddNode(if_is_cancelled); 9674 yield->AddNode(if_is_cancelled);
9627 9675
9628 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode(); 9676 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode();
9629 await_marker->set_scope(current_block_->scope); 9677 await_marker->set_scope(current_block_->scope);
9630 yield->AddNode(await_marker); 9678 yield->AddNode(await_marker);
9631 ReturnNode* continuation_return = new(Z) ReturnNode(yield_pos); 9679 ReturnNode* continuation_return = new(Z) ReturnNode(yield_pos);
9632 continuation_return->set_return_type(ReturnNode::kContinuationTarget); 9680 continuation_return->set_return_type(ReturnNode::kContinuationTarget);
9633 yield->AddNode(continuation_return); 9681 yield->AddNode(continuation_return);
9634 9682
9635 // If this expression is part of a try block, also append the code for 9683 // If this expression is part of a try block, also append the code for
9636 // restoring the saved try context that lives on the stack and possibly the 9684 // restoring the saved try context that lives on the stack and possibly the
9637 // saved try context of the outer try block. 9685 // saved try context of the outer try block.
9638 LocalScope* try_scope; 9686 LocalVariable* saved_try_ctx;
9639 int16_t try_index; 9687 LocalVariable* async_saved_try_ctx;
9640 LocalScope* outer_try_scope; 9688 LocalVariable* outer_saved_try_ctx;
9641 int16_t outer_try_index; 9689 LocalVariable* outer_async_saved_try_ctx;
9642 CheckAsyncOpInTryBlock(&try_scope, &try_index, 9690 CheckAsyncOpInTryBlock(&saved_try_ctx,
9643 &outer_try_scope, &outer_try_index); 9691 &async_saved_try_ctx,
9644 if (try_scope != NULL) { 9692 &outer_saved_try_ctx,
9645 yield->AddNode( 9693 &outer_async_saved_try_ctx);
9646 AwaitTransformer::RestoreSavedTryContext(Z, 9694 if (saved_try_ctx != NULL) {
9647 try_scope, 9695 yield->AddNode(new (Z) StoreLocalNode(
9648 try_index)); 9696 Scanner::kNoSourcePos,
9649 if (outer_try_scope != NULL) { 9697 saved_try_ctx,
9650 yield->AddNode( 9698 new (Z) LoadLocalNode(Scanner::kNoSourcePos,
9651 AwaitTransformer::RestoreSavedTryContext(Z, 9699 async_saved_try_ctx)));
9652 outer_try_scope, 9700 if (outer_saved_try_ctx != NULL) {
9653 outer_try_index)); 9701 yield->AddNode(new (Z) StoreLocalNode(
9702 Scanner::kNoSourcePos,
9703 outer_saved_try_ctx,
9704 new (Z) LoadLocalNode(Scanner::kNoSourcePos,
9705 outer_async_saved_try_ctx)));
9654 } 9706 }
9655 } else { 9707 } else {
9656 ASSERT(outer_try_scope == NULL); 9708 ASSERT(outer_saved_try_ctx == NULL);
9657 } 9709 }
9658 } 9710 }
9659 return yield; 9711 return yield;
9660 } 9712 }
9661 9713
9662 9714
9663 AstNode* Parser::ParseStatement() { 9715 AstNode* Parser::ParseStatement() {
9664 TRACE_PARSER("ParseStatement"); 9716 TRACE_PARSER("ParseStatement");
9665 AstNode* statement = NULL; 9717 AstNode* statement = NULL;
9666 intptr_t label_pos = 0; 9718 intptr_t label_pos = 0;
(...skipping 913 matching lines...) Expand 10 before | Expand all | Expand 10 after
10580 TRACE_PARSER("ParseAwaitExpr"); 10632 TRACE_PARSER("ParseAwaitExpr");
10581 if (!innermost_function().IsAsyncFunction() && 10633 if (!innermost_function().IsAsyncFunction() &&
10582 !innermost_function().IsAsyncClosure() && 10634 !innermost_function().IsAsyncClosure() &&
10583 !innermost_function().IsAsyncGenerator() && 10635 !innermost_function().IsAsyncGenerator() &&
10584 !innermost_function().IsAsyncGenClosure()) { 10636 !innermost_function().IsAsyncGenClosure()) {
10585 ReportError("await operator is only allowed in an asynchronous function"); 10637 ReportError("await operator is only allowed in an asynchronous function");
10586 } 10638 }
10587 ConsumeToken(); 10639 ConsumeToken();
10588 parsed_function()->record_await(); 10640 parsed_function()->record_await();
10589 10641
10590 LocalScope* try_scope; 10642 LocalVariable* saved_try_ctx;
10591 int16_t try_index; 10643 LocalVariable* async_saved_try_ctx;
10592 LocalScope* outer_try_scope; 10644 LocalVariable* outer_saved_try_ctx;
10593 int16_t outer_try_index; 10645 LocalVariable* outer_async_saved_try_ctx;
10594 CheckAsyncOpInTryBlock(&try_scope, &try_index, 10646 CheckAsyncOpInTryBlock(&saved_try_ctx,
10595 &outer_try_scope, &outer_try_index); 10647 &async_saved_try_ctx,
10596 10648 &outer_saved_try_ctx,
10649 &outer_async_saved_try_ctx);
10597 expr = new (Z) AwaitNode(op_pos, 10650 expr = new (Z) AwaitNode(op_pos,
10598 ParseUnaryExpr(), 10651 ParseUnaryExpr(),
10599 try_scope, 10652 saved_try_ctx,
10600 try_index, 10653 async_saved_try_ctx,
10601 outer_try_scope, 10654 outer_saved_try_ctx,
10602 outer_try_index); 10655 outer_async_saved_try_ctx);
10603 } else if (IsPrefixOperator(CurrentToken())) { 10656 } else if (IsPrefixOperator(CurrentToken())) {
10604 Token::Kind unary_op = CurrentToken(); 10657 Token::Kind unary_op = CurrentToken();
10605 if (unary_op == Token::kSUB) { 10658 if (unary_op == Token::kSUB) {
10606 unary_op = Token::kNEGATE; 10659 unary_op = Token::kNEGATE;
10607 } 10660 }
10608 ConsumeToken(); 10661 ConsumeToken();
10609 expr = ParseUnaryExpr(); 10662 expr = ParseUnaryExpr();
10610 if (expr->IsPrimaryNode() && (expr->AsPrimaryNode()->IsSuper())) { 10663 if (expr->IsPrimaryNode() && (expr->AsPrimaryNode()->IsSuper())) {
10611 expr = BuildUnarySuperOperator(unary_op, expr->AsPrimaryNode()); 10664 expr = BuildUnarySuperOperator(unary_op, expr->AsPrimaryNode());
10612 } else { 10665 } else {
(...skipping 2827 matching lines...) Expand 10 before | Expand all | Expand 10 after
13440 void Parser::SkipQualIdent() { 13493 void Parser::SkipQualIdent() {
13441 ASSERT(IsIdentifier()); 13494 ASSERT(IsIdentifier());
13442 ConsumeToken(); 13495 ConsumeToken();
13443 if (CurrentToken() == Token::kPERIOD) { 13496 if (CurrentToken() == Token::kPERIOD) {
13444 ConsumeToken(); // Consume the kPERIOD token. 13497 ConsumeToken(); // Consume the kPERIOD token.
13445 ExpectIdentifier("identifier expected after '.'"); 13498 ExpectIdentifier("identifier expected after '.'");
13446 } 13499 }
13447 } 13500 }
13448 13501
13449 } // namespace dart 13502 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698