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

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

Issue 969903002: More fixes in async machinery (issue 22438 and maybe more). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 9 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/ast_transformer.cc ('k') | tests/language/language_analyzer.status » ('j') | 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 5978 matching lines...) Expand 10 before | Expand all | Expand 10 after
5989 Scanner::kNoSourcePos, 5989 Scanner::kNoSourcePos,
5990 stack_trace_param.var, 5990 stack_trace_param.var,
5991 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var))); 5991 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var)));
5992 } 5992 }
5993 5993
5994 SaveExceptionAndStacktrace(exception_var, stack_trace_var); 5994 SaveExceptionAndStacktrace(exception_var, stack_trace_var);
5995 5995
5996 ASSERT(try_blocks_list_ != NULL); 5996 ASSERT(try_blocks_list_ != NULL);
5997 ASSERT(innermost_function().IsAsyncClosure() || 5997 ASSERT(innermost_function().IsAsyncClosure() ||
5998 innermost_function().IsAsyncFunction()); 5998 innermost_function().IsAsyncFunction());
5999 if ((try_blocks_list_->outer_try_block() != NULL) && 5999 const TryBlocks* outer_try_block = try_blocks_list_->outer_try_block();
6000 (try_blocks_list_->outer_try_block()->try_block() 6000 if (outer_try_block != NULL) {
6001 ->scope->function_level() == 6001 LocalScope* scope = outer_try_block->try_block()->scope;
6002 current_block_->scope->function_level())) { 6002 if (scope->function_level() == current_block_->scope->function_level()) {
6003 // We need to unchain three scope levels: catch clause, catch 6003 current_block_->statements->Add(
6004 // parameters, and the general try block. 6004 AwaitTransformer::RestoreSavedTryContext(
6005 current_block_->statements->Add( 6005 Z, scope->parent(), outer_try_block->try_index()));
6006 AwaitTransformer::RestoreSavedTryContext( 6006 }
6007 Z,
6008 current_block_->scope->parent()->parent()->parent(),
6009 try_blocks_list_->outer_try_block()->try_index()));
6010 } 6007 }
6011 6008
6012 // Complete the async future with an error. 6009 // Complete the async future with an error.
6013 // Since we control the catch block there is no need to generate a nested 6010 // Since we control the catch block there is no need to generate a nested
6014 // if/then/else. 6011 // if/then/else.
6015 LocalVariable* async_completer = current_block_->scope->LookupVariable( 6012 LocalVariable* async_completer = current_block_->scope->LookupVariable(
6016 Symbols::AsyncCompleter(), false); 6013 Symbols::AsyncCompleter(), false);
6017 ASSERT(async_completer != NULL); 6014 ASSERT(async_completer != NULL);
6018 ArgumentListNode* completer_args = 6015 ArgumentListNode* completer_args =
6019 new (Z) ArgumentListNode(Scanner::kNoSourcePos); 6016 new (Z) ArgumentListNode(Scanner::kNoSourcePos);
(...skipping 2309 matching lines...) Expand 10 before | Expand all | Expand 10 after
8329 ExpectToken(Token::kLBRACE); 8326 ExpectToken(Token::kLBRACE);
8330 8327
8331 // In case of async closures we need to restore the saved try index of an 8328 // In case of async closures we need to restore the saved try index of an
8332 // outer try block (if it exists). The current try block has already been 8329 // outer try block (if it exists). The current try block has already been
8333 // removed from the stack of try blocks. 8330 // removed from the stack of try blocks.
8334 if ((innermost_function().IsAsyncClosure() || 8331 if ((innermost_function().IsAsyncClosure() ||
8335 innermost_function().IsAsyncFunction() || 8332 innermost_function().IsAsyncFunction() ||
8336 innermost_function().IsSyncGenClosure() || 8333 innermost_function().IsSyncGenClosure() ||
8337 innermost_function().IsSyncGenerator()) && 8334 innermost_function().IsSyncGenerator()) &&
8338 (try_blocks_list_ != NULL)) { 8335 (try_blocks_list_ != NULL)) {
8339 // We need two unchain two scopes: finally clause, and the try block level. 8336 LocalScope* scope = try_blocks_list_->try_block()->scope;
8340 current_block_->statements->Add( 8337 if (scope->function_level() == current_block_->scope->function_level()) {
8341 AwaitTransformer::RestoreSavedTryContext( 8338 current_block_->statements->Add(
8342 Z, 8339 AwaitTransformer::RestoreSavedTryContext(
8343 current_block_->scope->parent()->parent(), 8340 Z, scope->parent(), try_blocks_list_->try_index()));
8344 try_blocks_list_->try_index())); 8341 }
8345 } 8342 }
8346 8343
8347 ParseStatementSequence(); 8344 ParseStatementSequence();
8348 ExpectToken(Token::kRBRACE); 8345 ExpectToken(Token::kRBRACE);
8349 SequenceNode* finally_block = CloseBlock(); 8346 SequenceNode* finally_block = CloseBlock();
8350 return finally_block; 8347 return finally_block;
8351 } 8348 }
8352 8349
8353 8350
8354 void Parser::PushTryBlock(Block* try_block) { 8351 void Parser::PushTryBlock(Block* try_block) {
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
8486 // declarations in the body to shadow the catch parameters. 8483 // declarations in the body to shadow the catch parameters.
8487 CheckToken(Token::kLBRACE); 8484 CheckToken(Token::kLBRACE);
8488 8485
8489 // In case of async closures we need to restore the saved try index of an 8486 // In case of async closures we need to restore the saved try index of an
8490 // outer try block (if it exists). 8487 // outer try block (if it exists).
8491 ASSERT(try_blocks_list_ != NULL); 8488 ASSERT(try_blocks_list_ != NULL);
8492 if (innermost_function().IsAsyncClosure() || 8489 if (innermost_function().IsAsyncClosure() ||
8493 innermost_function().IsAsyncFunction() || 8490 innermost_function().IsAsyncFunction() ||
8494 innermost_function().IsSyncGenClosure() || 8491 innermost_function().IsSyncGenClosure() ||
8495 innermost_function().IsSyncGenerator()) { 8492 innermost_function().IsSyncGenerator()) {
8496 if ((try_blocks_list_->outer_try_block() != NULL) && 8493 const TryBlocks* try_block = try_blocks_list_->outer_try_block();
8497 (try_blocks_list_->outer_try_block()->try_block() 8494 if (try_block != NULL) {
8498 ->scope->function_level() == 8495 LocalScope* scope = try_block->try_block()->scope;
8499 current_block_->scope->function_level())) { 8496 if (scope->function_level() ==
8500 // We need to unchain three scope levels: catch clause, catch 8497 current_block_->scope->function_level()) {
8501 // parameters, and the general try block. 8498 current_block_->statements->Add(
8502 current_block_->statements->Add( 8499 AwaitTransformer::RestoreSavedTryContext(
8503 AwaitTransformer::RestoreSavedTryContext( 8500 Z, scope->parent(), try_block->try_index()));
8504 Z, 8501 }
8505 current_block_->scope->parent()->parent()->parent(),
8506 try_blocks_list_->outer_try_block()->try_index()));
8507 } 8502 }
8508 SaveExceptionAndStacktrace(exception_var, stack_trace_var); 8503 SaveExceptionAndStacktrace(exception_var, stack_trace_var);
8509 } 8504 }
8510 8505
8511 current_block_->statements->Add(ParseNestedStatement(false, NULL)); 8506 current_block_->statements->Add(ParseNestedStatement(false, NULL));
8512 catch_blocks.Add(CloseBlock()); 8507 catch_blocks.Add(CloseBlock());
8513 8508
8514 const bool is_bad_type = 8509 const bool is_bad_type =
8515 exception_param.type->IsMalformed() || 8510 exception_param.type->IsMalformed() ||
8516 exception_param.type->IsMalbounded(); 8511 exception_param.type->IsMalbounded();
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
8587 // The last body is entered unconditionally. Start building the 8582 // The last body is entered unconditionally. Start building the
8588 // if/then/else nest with that body as the innermost else block. 8583 // if/then/else nest with that body as the innermost else block.
8589 // Note that it is nested inside an extra block which we opened 8584 // Note that it is nested inside an extra block which we opened
8590 // before we knew the body was entered unconditionally. 8585 // before we knew the body was entered unconditionally.
8591 type_tests.RemoveLast(); 8586 type_tests.RemoveLast();
8592 current_block_->statements->Add(catch_blocks.RemoveLast()); 8587 current_block_->statements->Add(catch_blocks.RemoveLast());
8593 current = CloseBlock(); 8588 current = CloseBlock();
8594 } 8589 }
8595 // If the last body was entered conditionally and there is no need to add 8590 // If the last body was entered conditionally and there is no need to add
8596 // a rethrow, use an empty else body (current = NULL above). 8591 // a rethrow, use an empty else body (current = NULL above).
8597
8598 while (!type_tests.is_empty()) { 8592 while (!type_tests.is_empty()) {
8599 AstNode* type_test = type_tests.RemoveLast(); 8593 AstNode* type_test = type_tests.RemoveLast();
8600 SequenceNode* catch_block = catch_blocks.RemoveLast(); 8594 SequenceNode* catch_block = catch_blocks.RemoveLast();
8601 8595 current_block_->statements->Add(new(Z) IfNode(
8602 // TODO(regis): Understand the purpose of the following code restoring 8596 type_test->token_pos(), type_test, catch_block, current));
8603 // :saved_try_context_var. This code was added as part of r39926. 8597 current = CloseBlock();
8604 // In some cases, this code even crashed the compiler (debug mode assert), 8598 }
8605 // because the scope unchaining was starting from the wrong block. 8599 // Restore :saved_try_context_var before executing the catch clauses.
8606 // The catch clause(s) emitted below contain the same restoring code. 8600 if (current != NULL) {
8607 // So why is it necessary? Could it be an attempt to handle the case where
8608 // the catch clause is replaced by a throw because of a bad type? It is not
8609 // necessary in this case either, because no await could have been executed
8610 // between the setup of :saved_try_context_var in the try clause and here
8611 // (it is the execution of an await that clears all stack-based variables).
8612
8613 // In case of async closures we need to restore the saved try index of an
8614 // outer try block (if it exists).
8615 ASSERT(try_blocks_list_ != NULL); 8601 ASSERT(try_blocks_list_ != NULL);
8616 if (innermost_function().IsAsyncClosure() || 8602 if (innermost_function().IsAsyncClosure() ||
8617 innermost_function().IsAsyncFunction() || 8603 innermost_function().IsAsyncFunction() ||
8618 innermost_function().IsSyncGenClosure() || 8604 innermost_function().IsSyncGenClosure() ||
8619 innermost_function().IsSyncGenerator()) { 8605 innermost_function().IsSyncGenerator()) {
8620 if ((try_blocks_list_->outer_try_block() != NULL) && 8606 const TryBlocks* try_block = try_blocks_list_->outer_try_block();
8621 (try_blocks_list_->outer_try_block()->try_block() 8607 if (try_block != NULL) {
8622 ->scope->function_level() == 8608 LocalScope* scope = try_block->try_block()->scope;
8623 current_block_->scope->function_level())) { 8609 if (scope->function_level() ==
8624 // We need to unchain three scope levels (from the catch block and not 8610 current_block_->scope->function_level()) {
8625 // from the current block): catch clause, catch 8611 SequenceNode* restore_code = new(Z) SequenceNode(handler_pos, NULL);
8626 // parameters, and the general try block. 8612 restore_code->Add(
8627 current_block_->statements->Add( 8613 AwaitTransformer::RestoreSavedTryContext(
8628 AwaitTransformer::RestoreSavedTryContext( 8614 Z, scope->parent(), try_block->try_index()));
8629 Z, 8615 restore_code->Add(current);
8630 catch_block->scope()->parent()->parent()->parent(), 8616 current = restore_code;
8631 try_blocks_list_->outer_try_block()->try_index())); 8617 }
8632 } 8618 }
8633 } 8619 }
8634
8635 current_block_->statements->Add(new(Z) IfNode(
8636 type_test->token_pos(), type_test, catch_block, current));
8637 current = CloseBlock();
8638 } 8620 }
8639 return current; 8621 return current;
8640 } 8622 }
8641 8623
8642 8624
8643 void Parser::SetupSavedTryContext(LocalVariable* saved_try_context) { 8625 void Parser::SetupSavedTryContext(LocalVariable* saved_try_context) {
8644 const String& async_saved_try_ctx_name = String::ZoneHandle(Z, 8626 const String& async_saved_try_ctx_name = String::ZoneHandle(Z,
8645 Symbols::New(String::Handle(Z, 8627 Symbols::New(String::Handle(Z,
8646 String::NewFormatted("%s%d", 8628 String::NewFormatted("%s%d",
8647 Symbols::AsyncSavedTryCtxVarPrefix().ToCString(), 8629 Symbols::AsyncSavedTryCtxVarPrefix().ToCString(),
(...skipping 4058 matching lines...) Expand 10 before | Expand all | Expand 10 after
12706 void Parser::SkipQualIdent() { 12688 void Parser::SkipQualIdent() {
12707 ASSERT(IsIdentifier()); 12689 ASSERT(IsIdentifier());
12708 ConsumeToken(); 12690 ConsumeToken();
12709 if (CurrentToken() == Token::kPERIOD) { 12691 if (CurrentToken() == Token::kPERIOD) {
12710 ConsumeToken(); // Consume the kPERIOD token. 12692 ConsumeToken(); // Consume the kPERIOD token.
12711 ExpectIdentifier("identifier expected after '.'"); 12693 ExpectIdentifier("identifier expected after '.'");
12712 } 12694 }
12713 } 12695 }
12714 12696
12715 } // namespace dart 12697 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/ast_transformer.cc ('k') | tests/language/language_analyzer.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698