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

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

Issue 958243003: Fix async machinery (issue 22445 and possibly others to be triaged later). (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/parser.h ('k') | runtime/vm/symbols.h » ('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 3018 matching lines...) Expand 10 before | Expand all | Expand 10 after
3029 Array* default_parameter_values) { 3029 Array* default_parameter_values) {
3030 TRACE_PARSER("ParseFunc"); 3030 TRACE_PARSER("ParseFunc");
3031 Function& saved_innermost_function = 3031 Function& saved_innermost_function =
3032 Function::Handle(Z, innermost_function().raw()); 3032 Function::Handle(Z, innermost_function().raw());
3033 innermost_function_ = func.raw(); 3033 innermost_function_ = func.raw();
3034 3034
3035 // Save current try index. Try index starts at zero for each function. 3035 // Save current try index. Try index starts at zero for each function.
3036 intptr_t saved_try_index = last_used_try_index_; 3036 intptr_t saved_try_index = last_used_try_index_;
3037 last_used_try_index_ = 0; 3037 last_used_try_index_ = 0;
3038 3038
3039 // In case of nested async functions we also need to save the currently saved 3039 // In case of nested async functions we also need to save the scope where
3040 // try context, the corresponding stack variable, and the scope where
3041 // temporaries are added. 3040 // temporaries are added.
3042 LocalVariable* saved_saved_try_ctx = parsed_function()->saved_try_ctx();
3043 const String& saved_async_saved_try_ctx_name =
3044 String::Handle(Z, parsed_function()->async_saved_try_ctx_name());
3045 parsed_function()->reset_saved_try_ctx_vars();
3046 LocalScope* saved_async_temp_scope = async_temp_scope_; 3041 LocalScope* saved_async_temp_scope = async_temp_scope_;
3047 3042
3048 if (func.IsGenerativeConstructor()) { 3043 if (func.IsGenerativeConstructor()) {
3049 SequenceNode* statements = ParseConstructor(func, default_parameter_values); 3044 SequenceNode* statements = ParseConstructor(func, default_parameter_values);
3050 innermost_function_ = saved_innermost_function.raw(); 3045 innermost_function_ = saved_innermost_function.raw();
3051 last_used_try_index_ = saved_try_index; 3046 last_used_try_index_ = saved_try_index;
3052 return statements; 3047 return statements;
3053 } 3048 }
3054 3049
3055 ASSERT(!func.IsGenerativeConstructor()); 3050 ASSERT(!func.IsGenerativeConstructor());
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
3258 } else if (func.IsSyncGenerator()) { 3253 } else if (func.IsSyncGenerator()) {
3259 body = CloseSyncGenFunction(generated_body_closure, body); 3254 body = CloseSyncGenFunction(generated_body_closure, body);
3260 generated_body_closure.set_end_token_pos(end_token_pos); 3255 generated_body_closure.set_end_token_pos(end_token_pos);
3261 } else if (func.IsSyncGenClosure()) { 3256 } else if (func.IsSyncGenClosure()) {
3262 body->scope()->RecursivelyCaptureAllVariables(); 3257 body->scope()->RecursivelyCaptureAllVariables();
3263 } 3258 }
3264 current_block_->statements->Add(body); 3259 current_block_->statements->Add(body);
3265 innermost_function_ = saved_innermost_function.raw(); 3260 innermost_function_ = saved_innermost_function.raw();
3266 last_used_try_index_ = saved_try_index; 3261 last_used_try_index_ = saved_try_index;
3267 async_temp_scope_ = saved_async_temp_scope; 3262 async_temp_scope_ = saved_async_temp_scope;
3268 parsed_function()->set_saved_try_ctx(saved_saved_try_ctx);
3269 parsed_function()->set_async_saved_try_ctx_name(
3270 saved_async_saved_try_ctx_name);
3271 return CloseBlock(); 3263 return CloseBlock();
3272 } 3264 }
3273 3265
3274 3266
3275 void Parser::AddEqualityNullCheck() { 3267 void Parser::AddEqualityNullCheck() {
3276 AstNode* argument = 3268 AstNode* argument =
3277 new LoadLocalNode(Scanner::kNoSourcePos, 3269 new LoadLocalNode(Scanner::kNoSourcePos,
3278 current_block_->scope->parent()->VariableAt(1)); 3270 current_block_->scope->parent()->VariableAt(1));
3279 LiteralNode* null_operand = 3271 LiteralNode* null_operand =
3280 new LiteralNode(Scanner::kNoSourcePos, Instance::ZoneHandle(Z)); 3272 new LiteralNode(Scanner::kNoSourcePos, Instance::ZoneHandle(Z));
(...skipping 2711 matching lines...) Expand 10 before | Expand all | Expand 10 after
5992 if (stack_trace_param.var != NULL) { 5984 if (stack_trace_param.var != NULL) {
5993 // A stack trace variable is specified in this block, so generate code 5985 // A stack trace variable is specified in this block, so generate code
5994 // to load the stack trace object (:stack_trace_var) into the stack 5986 // to load the stack trace object (:stack_trace_var) into the stack
5995 // trace variable specified in this block. 5987 // trace variable specified in this block.
5996 current_block_->statements->Add(new(Z) StoreLocalNode( 5988 current_block_->statements->Add(new(Z) StoreLocalNode(
5997 Scanner::kNoSourcePos, 5989 Scanner::kNoSourcePos,
5998 stack_trace_param.var, 5990 stack_trace_param.var,
5999 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var))); 5991 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var)));
6000 } 5992 }
6001 5993
6002 AddSavedExceptionAndStacktraceToScope( 5994 SaveExceptionAndStacktrace(exception_var, stack_trace_var);
6003 exception_var, stack_trace_var, current_block_->scope);
6004 5995
6005 ASSERT(try_blocks_list_ != NULL); 5996 ASSERT(try_blocks_list_ != NULL);
6006 ASSERT(innermost_function().IsAsyncClosure() || 5997 ASSERT(innermost_function().IsAsyncClosure() ||
6007 innermost_function().IsAsyncFunction()); 5998 innermost_function().IsAsyncFunction());
6008 if ((try_blocks_list_->outer_try_block() != NULL) && 5999 if ((try_blocks_list_->outer_try_block() != NULL) &&
6009 (try_blocks_list_->outer_try_block()->try_block() 6000 (try_blocks_list_->outer_try_block()->try_block()
6010 ->scope->function_level() == 6001 ->scope->function_level() ==
6011 current_block_->scope->function_level())) { 6002 current_block_->scope->function_level())) {
6012 // We need to unchain three scope levels: catch clause, catch 6003 // We need to unchain three scope levels: catch clause, catch
6013 // parameters, and the general try block. 6004 // parameters, and the general try block.
6014 RestoreSavedTryContext( 6005 current_block_->statements->Add(
6015 current_block_->scope->parent()->parent()->parent(), 6006 AwaitTransformer::RestoreSavedTryContext(
6016 try_blocks_list_->outer_try_block()->try_index(), 6007 Z,
6017 current_block_->statements); 6008 current_block_->scope->parent()->parent()->parent(),
6018 } else { 6009 try_blocks_list_->outer_try_block()->try_index()));
6019 parsed_function()->reset_saved_try_ctx_vars();
6020 } 6010 }
6021 6011
6022 // Complete the async future with an error. 6012 // Complete the async future with an error.
6023 // Since we control the catch block there is no need to generate a nested 6013 // Since we control the catch block there is no need to generate a nested
6024 // if/then/else. 6014 // if/then/else.
6025 LocalVariable* async_completer = current_block_->scope->LookupVariable( 6015 LocalVariable* async_completer = current_block_->scope->LookupVariable(
6026 Symbols::AsyncCompleter(), false); 6016 Symbols::AsyncCompleter(), false);
6027 ASSERT(async_completer != NULL); 6017 ASSERT(async_completer != NULL);
6028 ArgumentListNode* completer_args = 6018 ArgumentListNode* completer_args =
6029 new (Z) ArgumentListNode(Scanner::kNoSourcePos); 6019 new (Z) ArgumentListNode(Scanner::kNoSourcePos);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
6096 LocalVariable* stack_trace_var = 6086 LocalVariable* stack_trace_var =
6097 current_block_->scope->LocalLookupVariable(Symbols::StackTraceVar()); 6087 current_block_->scope->LocalLookupVariable(Symbols::StackTraceVar());
6098 if (stack_trace_var == NULL) { 6088 if (stack_trace_var == NULL) {
6099 stack_trace_var = new(Z) LocalVariable( 6089 stack_trace_var = new(Z) LocalVariable(
6100 TokenPos(), 6090 TokenPos(),
6101 Symbols::StackTraceVar(), 6091 Symbols::StackTraceVar(),
6102 Type::ZoneHandle(Z, Type::DynamicType())); 6092 Type::ZoneHandle(Z, Type::DynamicType()));
6103 current_block_->scope->AddVariable(stack_trace_var); 6093 current_block_->scope->AddVariable(stack_trace_var);
6104 } 6094 }
6105 6095
6096 SetupSavedExceptionAndStacktrace();
6097
6106 // Open the try block. 6098 // Open the try block.
6107 OpenBlock(); 6099 OpenBlock();
6108 PushTryBlock(current_block_); 6100 PushTryBlock(current_block_);
6109 6101
6110 if (innermost_function().IsAsyncClosure() || 6102 SetupSavedTryContext(context_var);
6111 innermost_function().IsAsyncFunction() ||
6112 innermost_function().IsSyncGenClosure() ||
6113 innermost_function().IsSyncGenerator()) {
6114 SetupSavedTryContext(context_var);
6115 }
6116 } 6103 }
6117 6104
6118 6105
6119 void Parser::AddSyncGenClosureParameters(ParamList* params) { 6106 void Parser::AddSyncGenClosureParameters(ParamList* params) {
6120 // Create the parameter list for the body closure of a sync generator: 6107 // Create the parameter list for the body closure of a sync generator:
6121 // 1) Implicit closure parameter; 6108 // 1) Implicit closure parameter;
6122 // 2) Iterator 6109 // 2) Iterator
6123 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); 6110 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType());
6124 // Add implicit closure parameter if not already present. 6111 // Add implicit closure parameter if not already present.
6125 if (params->parameters->length() == 0) { 6112 if (params->parameters->length() == 0) {
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
6378 // Record the begin and end token index of the scope. 6365 // Record the begin and end token index of the scope.
6379 ASSERT(statements != NULL); 6366 ASSERT(statements != NULL);
6380 current_block_->scope->set_begin_token_pos(statements->token_pos()); 6367 current_block_->scope->set_begin_token_pos(statements->token_pos());
6381 current_block_->scope->set_end_token_pos(TokenPos()); 6368 current_block_->scope->set_end_token_pos(TokenPos());
6382 } 6369 }
6383 current_block_ = current_block_->parent; 6370 current_block_ = current_block_->parent;
6384 return statements; 6371 return statements;
6385 } 6372 }
6386 6373
6387 6374
6388 static inline String& BuildAsyncSavedTryContextName(Zone* zone,
6389 int16_t id) {
6390 const char* async_saved_prefix = ":async_saved_try_ctx_var_";
6391 // Can be a regular handle since we only use it to build an actual symbol.
6392 const String& cnt_str = String::Handle(zone,
6393 String::NewFormatted("%s%d", async_saved_prefix, id));
6394 return String::ZoneHandle(zone, Symbols::New(cnt_str));
6395 }
6396
6397
6398 SequenceNode* Parser::CloseAsyncFunction(const Function& closure, 6375 SequenceNode* Parser::CloseAsyncFunction(const Function& closure,
6399 SequenceNode* closure_body) { 6376 SequenceNode* closure_body) {
6400 TRACE_PARSER("CloseAsyncFunction"); 6377 TRACE_PARSER("CloseAsyncFunction");
6401 ASSERT(!closure.IsNull()); 6378 ASSERT(!closure.IsNull());
6402 ASSERT(closure_body != NULL); 6379 ASSERT(closure_body != NULL);
6403 // The block for the async closure body has already been closed. Close the 6380 // The block for the async closure body has already been closed. Close the
6404 // corresponding function block. 6381 // corresponding function block.
6405 CloseBlock(); 6382 CloseBlock();
6406 6383
6407 closure_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false); 6384 closure_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false);
(...skipping 1362 matching lines...) Expand 10 before | Expand all | Expand 10 after
7770 // it to the loop body. 7747 // it to the loop body.
7771 if (await_preamble != NULL) { 7748 if (await_preamble != NULL) {
7772 dowhile_body->Add(await_preamble); 7749 dowhile_body->Add(await_preamble);
7773 } 7750 }
7774 ExpectToken(Token::kRPAREN); 7751 ExpectToken(Token::kRPAREN);
7775 ExpectSemicolon(); 7752 ExpectSemicolon();
7776 return new(Z) DoWhileNode(do_pos, label, cond_expr, dowhile_body); 7753 return new(Z) DoWhileNode(do_pos, label, cond_expr, dowhile_body);
7777 } 7754 }
7778 7755
7779 7756
7757 // If the await or yield being parsed is in a try block, the continuation code
7758 // needs to restore the corresponding stack-based variable :saved_try_ctx_var,
7759 // and possibly the stack-based variable :saved_try_ctx_var of the outer try
7760 // block.
7761 // The inner :saved_try_ctx_var is used by a finally clause handling an
7762 // exception thrown by the continuation code in a catch clause. If no finally
7763 // clause exists, the catch or finally clause of the outer try block, if any,
7764 // uses the outer :saved_try_ctx_var to handle the exception.
7765 //
7766 // * Try blocks: Set the context variable for this try block.
7767 // * Catch blocks: Set the context variable for this try block and for any outer
7768 // try block (if existent).
7769 // * Finally blocks: Set the context variable for any outer try block (if
7770 // existent). Note that this try block is popped before
7771 // parsing the finally clause, so the outer try block (if
7772 // existent) is at the top of the try block list.
7773 //
7774 // TODO(regis): Could we return the variables instead of their containing
7775 // scopes? Check if they are already setup at this point.
7776 void Parser::CheckAsyncOpInTryBlock(LocalScope** try_scope,
7777 int16_t* try_index,
7778 LocalScope** outer_try_scope,
7779 int16_t* outer_try_index) const {
7780 *try_scope = NULL;
7781 *try_index = CatchClauseNode::kInvalidTryIndex;
7782 *outer_try_scope = NULL;
7783 *outer_try_index = CatchClauseNode::kInvalidTryIndex;
7784 if (try_blocks_list_ != NULL) {
7785 LocalScope* scope = try_blocks_list_->try_block()->scope;
7786 const int current_function_level = current_block_->scope->function_level();
7787 if (scope->function_level() == current_function_level) {
Ivan Posva 2015/02/27 22:15:25 We need to evaluate the need for this check.
7788 // The block declaring :saved_try_ctx_var variable is the parent of the
7789 // pushed try block.
7790 *try_scope = scope->parent();
7791 *try_index = try_blocks_list_->try_index();
7792 if (try_blocks_list_->inside_catch() &&
7793 (try_blocks_list_->outer_try_block() != NULL)) {
7794 scope = try_blocks_list_->outer_try_block()->try_block()->scope;
7795 if (scope->function_level() == current_function_level) {
7796 *outer_try_scope = scope->parent();
7797 *outer_try_index = try_blocks_list_->outer_try_block()->try_index();
7798 }
7799 }
7800 }
7801 }
7802 // An async or async* has an implicitly created try-catch around the
7803 // function body, so the await or yield inside the async closure should always
7804 // be created with a try scope.
7805 ASSERT((*try_scope != NULL) ||
7806 innermost_function().IsAsyncFunction() ||
7807 innermost_function().IsSyncGenClosure() ||
7808 innermost_function().IsSyncGenerator());
7809 }
7810
7811
7780 AstNode* Parser::ParseAwaitForStatement(String* label_name) { 7812 AstNode* Parser::ParseAwaitForStatement(String* label_name) {
7781 TRACE_PARSER("ParseAwaitForStatement"); 7813 TRACE_PARSER("ParseAwaitForStatement");
7782 ASSERT(IsAwaitKeyword()); 7814 ASSERT(IsAwaitKeyword());
7783 const intptr_t await_for_pos = TokenPos(); 7815 const intptr_t await_for_pos = TokenPos();
7784 ConsumeToken(); // await. 7816 ConsumeToken(); // await.
7785 ASSERT(CurrentToken() == Token::kFOR); 7817 ASSERT(CurrentToken() == Token::kFOR);
7786 ConsumeToken(); // for. 7818 ConsumeToken(); // for.
7787 ExpectToken(Token::kLPAREN); 7819 ExpectToken(Token::kLPAREN);
7788 7820
7789 if (!innermost_function().IsAsyncFunction() && 7821 if (!innermost_function().IsAsyncFunction() &&
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
7837 iterator_ctor, 7869 iterator_ctor,
7838 ctor_args); 7870 ctor_args);
7839 const AbstractType& iterator_type = Type::ZoneHandle(Z, Type::DynamicType()); 7871 const AbstractType& iterator_type = Type::ZoneHandle(Z, Type::DynamicType());
7840 LocalVariable* iterator_var = new(Z) LocalVariable( 7872 LocalVariable* iterator_var = new(Z) LocalVariable(
7841 stream_pos, Symbols::ForInIter(), iterator_type); 7873 stream_pos, Symbols::ForInIter(), iterator_type);
7842 current_block_->scope->AddVariable(iterator_var); 7874 current_block_->scope->AddVariable(iterator_var);
7843 AstNode* iterator_init = 7875 AstNode* iterator_init =
7844 new(Z) StoreLocalNode(stream_pos, iterator_var, ctor_call); 7876 new(Z) StoreLocalNode(stream_pos, iterator_var, ctor_call);
7845 current_block_->statements->Add(iterator_init); 7877 current_block_->statements->Add(iterator_init);
7846 7878
7879 LocalScope* try_scope;
7880 int16_t try_index;
7881 LocalScope* outer_try_scope;
7882 int16_t outer_try_index;
7883 CheckAsyncOpInTryBlock(&try_scope, &try_index,
7884 &outer_try_scope, &outer_try_index);
7885
7847 // Build while loop condition. 7886 // Build while loop condition.
7848 // while (await :for-in-iter.moveNext()) 7887 // while (await :for-in-iter.moveNext())
7849 ArgumentListNode* no_args = new(Z) ArgumentListNode(stream_pos); 7888 ArgumentListNode* no_args = new(Z) ArgumentListNode(stream_pos);
7850 AstNode* iterator_moveNext = new(Z) InstanceCallNode( 7889 AstNode* iterator_moveNext = new(Z) InstanceCallNode(
7851 stream_pos, 7890 stream_pos,
7852 new(Z) LoadLocalNode(stream_pos, iterator_var), 7891 new(Z) LoadLocalNode(stream_pos, iterator_var),
7853 Symbols::MoveNext(), 7892 Symbols::MoveNext(),
7854 no_args); 7893 no_args);
7855 AstNode* await_moveNext = new (Z) AwaitNode(stream_pos, iterator_moveNext); 7894 AstNode* await_moveNext = new (Z) AwaitNode(stream_pos,
7895 iterator_moveNext,
7896 try_scope,
7897 try_index,
7898 outer_try_scope,
7899 outer_try_index);
7856 OpenBlock(); 7900 OpenBlock();
7857 AwaitTransformer at(current_block_->statements, 7901 AwaitTransformer at(current_block_->statements, async_temp_scope_);
7858 *parsed_function(),
7859 async_temp_scope_);
7860 AstNode* transformed_await = at.Transform(await_moveNext); 7902 AstNode* transformed_await = at.Transform(await_moveNext);
7861 SequenceNode* await_preamble = CloseBlock(); 7903 SequenceNode* await_preamble = CloseBlock();
7862 7904
7863 // Parse the for loop body. Ideally, we would use ParseNestedStatement() 7905 // Parse the for loop body. Ideally, we would use ParseNestedStatement()
7864 // here, but that does not work well because we have to insert an implicit 7906 // here, but that does not work well because we have to insert an implicit
7865 // variable assignment and potentially a variable declaration in the 7907 // variable assignment and potentially a variable declaration in the
7866 // loop body. 7908 // loop body.
7867 OpenLoopBlock(); 7909 OpenLoopBlock();
7868 SourceLabel* label = 7910 SourceLabel* label =
7869 SourceLabel::New(await_for_pos, label_name, SourceLabel::kFor); 7911 SourceLabel::New(await_for_pos, label_name, SourceLabel::kFor);
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
8211 // The name of the exception param is reused for the stack trace param. 8253 // The name of the exception param is reused for the stack trace param.
8212 ReportError(stack_trace_param->token_pos, 8254 ReportError(stack_trace_param->token_pos,
8213 "name '%s' already exists in scope", 8255 "name '%s' already exists in scope",
8214 stack_trace_param->name->ToCString()); 8256 stack_trace_param->name->ToCString());
8215 } 8257 }
8216 stack_trace_param->var = var; 8258 stack_trace_param->var = var;
8217 } 8259 }
8218 } 8260 }
8219 8261
8220 8262
8221 // Populate local scope of the catch block with the saved exception and saved 8263 // Populate current scope of the try block with the saved exception and saved
8222 // stack trace. 8264 // stack trace.
8223 void Parser::AddSavedExceptionAndStacktraceToScope( 8265 void Parser::SetupSavedExceptionAndStacktrace() {
8224 LocalVariable* exception_var,
8225 LocalVariable* stack_trace_var,
8226 LocalScope* scope) {
8227 ASSERT(innermost_function().IsAsyncClosure() || 8266 ASSERT(innermost_function().IsAsyncClosure() ||
8228 innermost_function().IsAsyncFunction() || 8267 innermost_function().IsAsyncFunction() ||
8229 innermost_function().IsSyncGenClosure() || 8268 innermost_function().IsSyncGenClosure() ||
8230 innermost_function().IsSyncGenerator()); 8269 innermost_function().IsSyncGenerator());
8231 // Add :saved_exception_var and :saved_stack_trace_var to scope. 8270 // Add :saved_exception_var and :saved_stack_trace_var to current scope.
8232 // They will automatically get captured. 8271 // They will automatically get captured.
8233 LocalVariable* saved_exception_var = new (Z) LocalVariable( 8272 // Parallel try statements share the same set of variables.
8234 Scanner::kNoSourcePos, 8273 LocalVariable* saved_exception_var =
8235 Symbols::SavedExceptionVar(), 8274 current_block_->scope->LocalLookupVariable(Symbols::SavedExceptionVar());
8236 Type::ZoneHandle(Z, Type::DynamicType())); 8275 if (saved_exception_var == NULL) {
8237 saved_exception_var->set_is_final(); 8276 saved_exception_var = new (Z) LocalVariable(
8238 scope->AddVariable(saved_exception_var); 8277 Scanner::kNoSourcePos,
8239 LocalVariable* saved_stack_trace_var = new (Z) LocalVariable( 8278 Symbols::SavedExceptionVar(),
8279 Type::ZoneHandle(Z, Type::DynamicType()));
8280 saved_exception_var->set_is_final();
8281 current_block_->scope->AddVariable(saved_exception_var);
8282 }
8283 LocalVariable* saved_stack_trace_var =
8284 current_block_->scope->LocalLookupVariable(Symbols::SavedStackTraceVar());
8285 if (saved_stack_trace_var == NULL) {
8286 saved_stack_trace_var = new (Z) LocalVariable(
8240 Scanner::kNoSourcePos, 8287 Scanner::kNoSourcePos,
8241 Symbols::SavedStackTraceVar(), 8288 Symbols::SavedStackTraceVar(),
8242 Type::ZoneHandle(Z, Type::DynamicType())); 8289 Type::ZoneHandle(Z, Type::DynamicType()));
8243 saved_exception_var->set_is_final(); 8290 saved_exception_var->set_is_final();
8244 scope->AddVariable(saved_stack_trace_var); 8291 current_block_->scope->AddVariable(saved_stack_trace_var);
8292 }
8293 }
8245 8294
8246 // Generate code to load the exception object (:exception_var) into 8295
8247 // the saved exception variable (:saved_exception_var) used to rethrow. 8296 // Generate code to load the exception object (:exception_var) into
8248 saved_exception_var = current_block_->scope->LookupVariable( 8297 // the saved exception variable (:saved_exception_var) used to rethrow.
8298 void Parser::SaveExceptionAndStacktrace(LocalVariable* exception_var,
8299 LocalVariable* stack_trace_var) {
8300 ASSERT(innermost_function().IsAsyncClosure() ||
8301 innermost_function().IsAsyncFunction() ||
8302 innermost_function().IsSyncGenClosure() ||
8303 innermost_function().IsSyncGenerator());
8304 LocalVariable* saved_exception_var = current_block_->scope->LookupVariable(
8249 Symbols::SavedExceptionVar(), false); 8305 Symbols::SavedExceptionVar(), false);
8250 ASSERT(saved_exception_var != NULL); 8306 ASSERT(saved_exception_var != NULL);
8251 ASSERT(exception_var != NULL); 8307 ASSERT(exception_var != NULL);
8252 current_block_->statements->Add(new(Z) StoreLocalNode( 8308 current_block_->statements->Add(new(Z) StoreLocalNode(
8253 Scanner::kNoSourcePos, 8309 Scanner::kNoSourcePos,
8254 saved_exception_var, 8310 saved_exception_var,
8255 new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var))); 8311 new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var)));
8256 8312
8257 // Generate code to load the stack trace object (:stack_trace_var) into 8313 // Generate code to load the stack trace object (:stack_trace_var) into
8258 // the saved stacktrace variable (:saved_stack_trace_var) used to rethrow. 8314 // the saved stacktrace variable (:saved_stack_trace_var) used to rethrow.
8259 saved_stack_trace_var = current_block_->scope->LookupVariable( 8315 LocalVariable* saved_stack_trace_var = current_block_->scope->LookupVariable(
8260 Symbols::SavedStackTraceVar(), false); 8316 Symbols::SavedStackTraceVar(), false);
8261 ASSERT(saved_stack_trace_var != NULL); 8317 ASSERT(saved_stack_trace_var != NULL);
8262 ASSERT(stack_trace_var != NULL); 8318 ASSERT(stack_trace_var != NULL);
8263 current_block_->statements->Add(new(Z) StoreLocalNode( 8319 current_block_->statements->Add(new(Z) StoreLocalNode(
8264 Scanner::kNoSourcePos, 8320 Scanner::kNoSourcePos,
8265 saved_stack_trace_var, 8321 saved_stack_trace_var,
8266 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var))); 8322 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var)));
8267 } 8323 }
8268 8324
8269 8325
8270 SequenceNode* Parser::ParseFinallyBlock() { 8326 SequenceNode* Parser::ParseFinallyBlock() {
8271 TRACE_PARSER("ParseFinallyBlock"); 8327 TRACE_PARSER("ParseFinallyBlock");
8272 OpenBlock(); 8328 OpenBlock();
8273 ExpectToken(Token::kLBRACE); 8329 ExpectToken(Token::kLBRACE);
8274 8330
8275 // In case of async closures we need to restore the saved try index of an 8331 // In case of async closures we need to restore the saved try index of an
8276 // outer try block (if it exists). The current try block has already been 8332 // outer try block (if it exists). The current try block has already been
8277 // removed from the stack of try blocks. 8333 // removed from the stack of try blocks.
8278 if ((innermost_function().IsAsyncClosure() || 8334 if ((innermost_function().IsAsyncClosure() ||
8279 innermost_function().IsAsyncFunction() || 8335 innermost_function().IsAsyncFunction() ||
8280 innermost_function().IsSyncGenClosure() || 8336 innermost_function().IsSyncGenClosure() ||
8281 innermost_function().IsSyncGenerator()) && 8337 innermost_function().IsSyncGenerator()) &&
8282 (try_blocks_list_ != NULL)) { 8338 (try_blocks_list_ != NULL)) {
8283 // We need two unchain two scopes: finally clause, and the try block level. 8339 // We need two unchain two scopes: finally clause, and the try block level.
8284 RestoreSavedTryContext(current_block_->scope->parent()->parent(), 8340 current_block_->statements->Add(
8285 try_blocks_list_->try_index(), 8341 AwaitTransformer::RestoreSavedTryContext(
8286 current_block_->statements); 8342 Z,
8287 } else { 8343 current_block_->scope->parent()->parent(),
8288 parsed_function()->reset_saved_try_ctx_vars(); 8344 try_blocks_list_->try_index()));
8289 } 8345 }
8290 8346
8291 ParseStatementSequence(); 8347 ParseStatementSequence();
8292 ExpectToken(Token::kRBRACE); 8348 ExpectToken(Token::kRBRACE);
8293 SequenceNode* finally_block = CloseBlock(); 8349 SequenceNode* finally_block = CloseBlock();
8294 return finally_block; 8350 return finally_block;
8295 } 8351 }
8296 8352
8297 8353
8298 void Parser::PushTryBlock(Block* try_block) { 8354 void Parser::PushTryBlock(Block* try_block) {
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
8436 if (innermost_function().IsAsyncClosure() || 8492 if (innermost_function().IsAsyncClosure() ||
8437 innermost_function().IsAsyncFunction() || 8493 innermost_function().IsAsyncFunction() ||
8438 innermost_function().IsSyncGenClosure() || 8494 innermost_function().IsSyncGenClosure() ||
8439 innermost_function().IsSyncGenerator()) { 8495 innermost_function().IsSyncGenerator()) {
8440 if ((try_blocks_list_->outer_try_block() != NULL) && 8496 if ((try_blocks_list_->outer_try_block() != NULL) &&
8441 (try_blocks_list_->outer_try_block()->try_block() 8497 (try_blocks_list_->outer_try_block()->try_block()
8442 ->scope->function_level() == 8498 ->scope->function_level() ==
8443 current_block_->scope->function_level())) { 8499 current_block_->scope->function_level())) {
8444 // We need to unchain three scope levels: catch clause, catch 8500 // We need to unchain three scope levels: catch clause, catch
8445 // parameters, and the general try block. 8501 // parameters, and the general try block.
8446 RestoreSavedTryContext( 8502 current_block_->statements->Add(
8447 current_block_->scope->parent()->parent()->parent(), 8503 AwaitTransformer::RestoreSavedTryContext(
8448 try_blocks_list_->outer_try_block()->try_index(), 8504 Z,
8449 current_block_->statements); 8505 current_block_->scope->parent()->parent()->parent(),
8450 } else { 8506 try_blocks_list_->outer_try_block()->try_index()));
8451 parsed_function()->reset_saved_try_ctx_vars();
8452 } 8507 }
8453 AddSavedExceptionAndStacktraceToScope( 8508 SaveExceptionAndStacktrace(exception_var, stack_trace_var);
8454 exception_var, stack_trace_var, current_block_->scope);
8455 } 8509 }
8456 8510
8457 current_block_->statements->Add(ParseNestedStatement(false, NULL)); 8511 current_block_->statements->Add(ParseNestedStatement(false, NULL));
8458 catch_blocks.Add(CloseBlock()); 8512 catch_blocks.Add(CloseBlock());
8459 8513
8460 const bool is_bad_type = 8514 const bool is_bad_type =
8461 exception_param.type->IsMalformed() || 8515 exception_param.type->IsMalformed() ||
8462 exception_param.type->IsMalbounded(); 8516 exception_param.type->IsMalbounded();
8463 if (exception_param.type->IsDynamicType() || is_bad_type) { 8517 if (exception_param.type->IsDynamicType() || is_bad_type) {
8464 // There is no exception type or else it is malformed or malbounded. 8518 // There is no exception type or else it is malformed or malbounded.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
8512 8566
8513 // Build the if/then/else nest from the inside out. Keep the AST simple 8567 // Build the if/then/else nest from the inside out. Keep the AST simple
8514 // for the case of a single generic catch clause. The initial value of 8568 // for the case of a single generic catch clause. The initial value of
8515 // current is the last (innermost) else block if there were any catch 8569 // current is the last (innermost) else block if there were any catch
8516 // clauses. 8570 // clauses.
8517 SequenceNode* current = NULL; 8571 SequenceNode* current = NULL;
8518 if (!generic_catch_seen) { 8572 if (!generic_catch_seen) {
8519 // There isn't a generic catch clause so create a clause body that 8573 // There isn't a generic catch clause so create a clause body that
8520 // rethrows the exception. This includes the case that there were no 8574 // rethrows the exception. This includes the case that there were no
8521 // catch clauses. 8575 // catch clauses.
8576 // An await cannot possibly be executed inbetween the catch entry and here,
8577 // therefore, it is safe to rethrow the stack-based :exception_var instead
8578 // of the captured copy :saved_exception_var.
8522 current = new(Z) SequenceNode(handler_pos, NULL); 8579 current = new(Z) SequenceNode(handler_pos, NULL);
8523 current->Add(new(Z) ThrowNode( 8580 current->Add(new(Z) ThrowNode(
8524 handler_pos, 8581 handler_pos,
8525 new(Z) LoadLocalNode(handler_pos, exception_var), 8582 new(Z) LoadLocalNode(handler_pos, exception_var),
8526 new(Z) LoadLocalNode(handler_pos, stack_trace_var))); 8583 new(Z) LoadLocalNode(handler_pos, stack_trace_var)));
8527 } else if (type_tests.Last()->IsLiteralNode()) { 8584 } else if (type_tests.Last()->IsLiteralNode()) {
8528 ASSERT(type_tests.Last()->AsLiteralNode()->literal().raw() == 8585 ASSERT(type_tests.Last()->AsLiteralNode()->literal().raw() ==
8529 Bool::True().raw()); 8586 Bool::True().raw());
8530 // The last body is entered unconditionally. Start building the 8587 // The last body is entered unconditionally. Start building the
8531 // if/then/else nest with that body as the innermost else block. 8588 // if/then/else nest with that body as the innermost else block.
8532 // Note that it is nested inside an extra block which we opened 8589 // Note that it is nested inside an extra block which we opened
8533 // before we knew the body was entered unconditionally. 8590 // before we knew the body was entered unconditionally.
8534 type_tests.RemoveLast(); 8591 type_tests.RemoveLast();
8535 current_block_->statements->Add(catch_blocks.RemoveLast()); 8592 current_block_->statements->Add(catch_blocks.RemoveLast());
8536 current = CloseBlock(); 8593 current = CloseBlock();
8537 } 8594 }
8538 // If the last body was entered conditionally and there is no need to add 8595 // If the last body was entered conditionally and there is no need to add
8539 // a rethrow, use an empty else body (current = NULL above). 8596 // a rethrow, use an empty else body (current = NULL above).
8540 8597
8541 while (!type_tests.is_empty()) { 8598 while (!type_tests.is_empty()) {
8542 AstNode* type_test = type_tests.RemoveLast(); 8599 AstNode* type_test = type_tests.RemoveLast();
8543 SequenceNode* catch_block = catch_blocks.RemoveLast(); 8600 SequenceNode* catch_block = catch_blocks.RemoveLast();
8544 8601
8602 // TODO(regis): Understand the purpose of the following code restoring
8603 // :saved_try_context_var. This code was added as part of r39926.
8604 // In some cases, this code even crashed the compiler (debug mode assert),
8605 // because the scope unchaining was starting from the wrong block.
8606 // The catch clause(s) emitted below contain the same restoring code.
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
8545 // In case of async closures we need to restore the saved try index of an 8613 // In case of async closures we need to restore the saved try index of an
8546 // outer try block (if it exists). 8614 // outer try block (if it exists).
8547 ASSERT(try_blocks_list_ != NULL); 8615 ASSERT(try_blocks_list_ != NULL);
8548 if (innermost_function().IsAsyncClosure() || 8616 if (innermost_function().IsAsyncClosure() ||
8549 innermost_function().IsAsyncFunction() || 8617 innermost_function().IsAsyncFunction() ||
8550 innermost_function().IsSyncGenClosure() || 8618 innermost_function().IsSyncGenClosure() ||
8551 innermost_function().IsSyncGenerator()) { 8619 innermost_function().IsSyncGenerator()) {
8552 if ((try_blocks_list_->outer_try_block() != NULL) && 8620 if ((try_blocks_list_->outer_try_block() != NULL) &&
8553 (try_blocks_list_->outer_try_block()->try_block() 8621 (try_blocks_list_->outer_try_block()->try_block()
8554 ->scope->function_level() == 8622 ->scope->function_level() ==
8555 current_block_->scope->function_level())) { 8623 current_block_->scope->function_level())) {
8556 // We need to unchain three scope levels: catch clause, catch 8624 // We need to unchain three scope levels (from the catch block and not
8625 // from the current block): catch clause, catch
8557 // parameters, and the general try block. 8626 // parameters, and the general try block.
8558 RestoreSavedTryContext( 8627 current_block_->statements->Add(
8559 current_block_->scope->parent()->parent(), 8628 AwaitTransformer::RestoreSavedTryContext(
8560 try_blocks_list_->outer_try_block()->try_index(), 8629 Z,
8561 current_block_->statements); 8630 catch_block->scope()->parent()->parent()->parent(),
8562 } else { 8631 try_blocks_list_->outer_try_block()->try_index()));
8563 parsed_function()->reset_saved_try_ctx_vars();
8564 } 8632 }
8565 } 8633 }
8566 8634
8567 current_block_->statements->Add(new(Z) IfNode( 8635 current_block_->statements->Add(new(Z) IfNode(
8568 type_test->token_pos(), type_test, catch_block, current)); 8636 type_test->token_pos(), type_test, catch_block, current));
8569 current = CloseBlock(); 8637 current = CloseBlock();
8570 } 8638 }
8571 return current; 8639 return current;
8572 } 8640 }
8573 8641
8574 8642
8575 void Parser::SetupSavedTryContext(LocalVariable* saved_try_context) { 8643 void Parser::SetupSavedTryContext(LocalVariable* saved_try_context) {
8576 const String& async_saved_try_ctx_name = 8644 const String& async_saved_try_ctx_name = String::ZoneHandle(Z,
8577 BuildAsyncSavedTryContextName(Z, last_used_try_index_ - 1); 8645 Symbols::New(String::Handle(Z,
8646 String::NewFormatted("%s%d",
8647 Symbols::AsyncSavedTryCtxVarPrefix().ToCString(),
8648 last_used_try_index_ - 1))));
8578 LocalVariable* async_saved_try_ctx = new (Z) LocalVariable( 8649 LocalVariable* async_saved_try_ctx = new (Z) LocalVariable(
8579 Scanner::kNoSourcePos, 8650 Scanner::kNoSourcePos,
8580 async_saved_try_ctx_name, 8651 async_saved_try_ctx_name,
8581 Type::ZoneHandle(Z, Type::DynamicType())); 8652 Type::ZoneHandle(Z, Type::DynamicType()));
8582 ASSERT(async_temp_scope_ != NULL); 8653 ASSERT(async_temp_scope_ != NULL);
8583 async_temp_scope_->AddVariable(async_saved_try_ctx); 8654 async_temp_scope_->AddVariable(async_saved_try_ctx);
8584 async_saved_try_ctx->set_is_captured(); 8655 async_saved_try_ctx->set_is_captured();
8585 async_saved_try_ctx = current_block_->scope->LookupVariable( 8656 async_saved_try_ctx = current_block_->scope->LookupVariable(
8586 async_saved_try_ctx_name, false); 8657 async_saved_try_ctx_name, false);
8587 ASSERT(async_saved_try_ctx != NULL); 8658 ASSERT(async_saved_try_ctx != NULL);
8588 ASSERT(saved_try_context != NULL); 8659 ASSERT(saved_try_context != NULL);
8589 current_block_->statements->Add(new(Z) StoreLocalNode( 8660 current_block_->statements->Add(new(Z) StoreLocalNode(
8590 Scanner::kNoSourcePos, 8661 Scanner::kNoSourcePos,
8591 async_saved_try_ctx, 8662 async_saved_try_ctx,
8592 new(Z) LoadLocalNode(Scanner::kNoSourcePos, saved_try_context))); 8663 new(Z) LoadLocalNode(Scanner::kNoSourcePos, saved_try_context)));
8593 parsed_function()->set_saved_try_ctx(saved_try_context);
8594 parsed_function()->set_async_saved_try_ctx_name(async_saved_try_ctx_name);
8595 }
8596
8597
8598 // Restore the currently relevant :saved_try_context_var on the stack
8599 // from the captured :async_saved_try_ctx_var_.
8600 // * Try blocks: Set the context variable for this try block.
8601 // * Catch/finally blocks: Set the context variable for any outer try block (if
8602 // existent).
8603 //
8604 // Also save the captured variable and the stack variable to be able to set
8605 // it after a function continues execution (await).
8606 void Parser::RestoreSavedTryContext(LocalScope* saved_try_context_scope,
8607 int16_t try_index,
8608 SequenceNode* target) {
8609 LocalVariable* saved_try_ctx = saved_try_context_scope->LookupVariable(
8610 Symbols::SavedTryContextVar(), false);
8611 ASSERT((saved_try_ctx != NULL) && !saved_try_ctx->is_captured());
8612 const String& async_saved_try_ctx_name =
8613 BuildAsyncSavedTryContextName(Z, try_index);
8614 LocalVariable* async_saved_try_ctx =
8615 target->scope()->LookupVariable(async_saved_try_ctx_name, false);
8616 ASSERT(async_saved_try_ctx != NULL);
8617 ASSERT(async_saved_try_ctx->is_captured());
8618 target->Add(new (Z) StoreLocalNode(
8619 Scanner::kNoSourcePos,
8620 saved_try_ctx,
8621 new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_saved_try_ctx)));
8622
8623 parsed_function()->set_saved_try_ctx(saved_try_ctx);
8624 parsed_function()->set_async_saved_try_ctx_name(async_saved_try_ctx_name);
8625 } 8664 }
8626 8665
8627 8666
8628 AstNode* Parser::ParseTryStatement(String* label_name) { 8667 AstNode* Parser::ParseTryStatement(String* label_name) {
8629 TRACE_PARSER("ParseTryStatement"); 8668 TRACE_PARSER("ParseTryStatement");
8630 8669
8631 // We create three variables for exceptions here: 8670 // We create three variables for exceptions here:
8632 // ':saved_try_context_var' - Used to save the context before the start of 8671 // ':saved_try_context_var' - Used to save the context before the start of
8633 // the try block. The context register is 8672 // the try block. The context register is
8634 // restored from this variable before 8673 // restored from this variable before
8635 // processing the catch block handler. 8674 // processing the catch block handler.
8636 // ':exception_var' - Used to save the current exception object that was 8675 // ':exception_var' - Used to save the current exception object that was
8637 // thrown. 8676 // thrown.
8638 // ':stack_trace_var' - Used to save the current stack trace object which 8677 // ':stack_trace_var' - Used to save the current stack trace object which
8639 // the stack trace was copied into when an exception 8678 // the stack trace was copied into when an exception
8640 // was thrown. 8679 // was thrown.
8641 // :exception_var and :stack_trace_var get set with the exception object 8680 // :exception_var and :stack_trace_var get set with the exception object
8642 // and the stack trace object when an exception is thrown. These three 8681 // and the stack trace object when an exception is thrown. These three
8643 // implicit variables can never be captured. 8682 // implicit variables can never be captured.
8683 // Parallel try statements share the same set of variables.
8644 LocalVariable* context_var = 8684 LocalVariable* context_var =
8645 current_block_->scope->LocalLookupVariable(Symbols::SavedTryContextVar()); 8685 current_block_->scope->LocalLookupVariable(Symbols::SavedTryContextVar());
8646 if (context_var == NULL) { 8686 if (context_var == NULL) {
8647 context_var = new(Z) LocalVariable( 8687 context_var = new(Z) LocalVariable(
8648 TokenPos(), 8688 TokenPos(),
8649 Symbols::SavedTryContextVar(), 8689 Symbols::SavedTryContextVar(),
8650 Type::ZoneHandle(Z, Type::DynamicType())); 8690 Type::ZoneHandle(Z, Type::DynamicType()));
8651 current_block_->scope->AddVariable(context_var); 8691 current_block_->scope->AddVariable(context_var);
8652 } 8692 }
8653 LocalVariable* exception_var = 8693 LocalVariable* exception_var =
8654 current_block_->scope->LocalLookupVariable(Symbols::ExceptionVar()); 8694 current_block_->scope->LocalLookupVariable(Symbols::ExceptionVar());
8655 if (exception_var == NULL) { 8695 if (exception_var == NULL) {
8656 exception_var = new(Z) LocalVariable( 8696 exception_var = new(Z) LocalVariable(
8657 TokenPos(), 8697 TokenPos(),
8658 Symbols::ExceptionVar(), 8698 Symbols::ExceptionVar(),
8659 Type::ZoneHandle(Z, Type::DynamicType())); 8699 Type::ZoneHandle(Z, Type::DynamicType()));
8660 current_block_->scope->AddVariable(exception_var); 8700 current_block_->scope->AddVariable(exception_var);
8661 } 8701 }
8662 LocalVariable* stack_trace_var = 8702 LocalVariable* stack_trace_var =
8663 current_block_->scope->LocalLookupVariable(Symbols::StackTraceVar()); 8703 current_block_->scope->LocalLookupVariable(Symbols::StackTraceVar());
8664 if (stack_trace_var == NULL) { 8704 if (stack_trace_var == NULL) {
8665 stack_trace_var = new(Z) LocalVariable( 8705 stack_trace_var = new(Z) LocalVariable(
8666 TokenPos(), 8706 TokenPos(),
8667 Symbols::StackTraceVar(), 8707 Symbols::StackTraceVar(),
8668 Type::ZoneHandle(Z, Type::DynamicType())); 8708 Type::ZoneHandle(Z, Type::DynamicType()));
8669 current_block_->scope->AddVariable(stack_trace_var); 8709 current_block_->scope->AddVariable(stack_trace_var);
8670 } 8710 }
8671 8711
8712 if (innermost_function().IsAsyncClosure() ||
8713 innermost_function().IsAsyncFunction() ||
8714 innermost_function().IsSyncGenClosure() ||
8715 innermost_function().IsSyncGenerator()) {
8716 SetupSavedExceptionAndStacktrace();
8717 }
8718
8672 const intptr_t try_pos = TokenPos(); 8719 const intptr_t try_pos = TokenPos();
8673 ConsumeToken(); // Consume the 'try'. 8720 ConsumeToken(); // Consume the 'try'.
8674 8721
8675 SourceLabel* try_label = NULL; 8722 SourceLabel* try_label = NULL;
8676 if (label_name != NULL) { 8723 if (label_name != NULL) {
8677 try_label = SourceLabel::New(try_pos, label_name, SourceLabel::kStatement); 8724 try_label = SourceLabel::New(try_pos, label_name, SourceLabel::kStatement);
8678 OpenBlock(); 8725 OpenBlock();
8679 current_block_->scope->AddLabel(try_label); 8726 current_block_->scope->AddLabel(try_label);
8680 } 8727 }
8681 8728
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
8924 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode(); 8971 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode();
8925 await_marker->set_scope(current_block_->scope); 8972 await_marker->set_scope(current_block_->scope);
8926 yield->AddNode(await_marker); 8973 yield->AddNode(await_marker);
8927 // Return true to indicate that a value has been generated. 8974 // Return true to indicate that a value has been generated.
8928 ReturnNode* return_true = new(Z) ReturnNode(statement_pos, 8975 ReturnNode* return_true = new(Z) ReturnNode(statement_pos,
8929 new(Z) LiteralNode(TokenPos(), Bool::True())); 8976 new(Z) LiteralNode(TokenPos(), Bool::True()));
8930 return_true->set_return_type(ReturnNode::kContinuationTarget); 8977 return_true->set_return_type(ReturnNode::kContinuationTarget);
8931 yield->AddNode(return_true); 8978 yield->AddNode(return_true);
8932 8979
8933 // If this expression is part of a try block, also append the code for 8980 // If this expression is part of a try block, also append the code for
8934 // restoring the saved try context that lives on the stack. 8981 // restoring the saved try context that lives on the stack and possibly the
8935 const String& async_saved_try_ctx_name = 8982 // saved try context of the outer try block.
8936 String::Handle(Z, parsed_function()->async_saved_try_ctx_name()); 8983 LocalScope* try_scope;
8937 if (!async_saved_try_ctx_name.IsNull()) { 8984 int16_t try_index;
8938 LocalVariable* async_saved_try_ctx = 8985 LocalScope* outer_try_scope;
8939 current_block_->scope->LookupVariable(async_saved_try_ctx_name, 8986 int16_t outer_try_index;
8940 false); 8987 CheckAsyncOpInTryBlock(&try_scope, &try_index,
8941 ASSERT(async_saved_try_ctx != NULL); 8988 &outer_try_scope, &outer_try_index);
8942 yield->AddNode(new (Z) StoreLocalNode( 8989 if (try_scope != NULL) {
8943 Scanner::kNoSourcePos, 8990 yield->AddNode(
8944 parsed_function()->saved_try_ctx(), 8991 AwaitTransformer::RestoreSavedTryContext(Z,
8945 new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_saved_try_ctx))); 8992 try_scope,
8993 try_index));
8994 if (outer_try_scope != NULL) {
8995 yield->AddNode(
8996 AwaitTransformer::RestoreSavedTryContext(Z,
8997 outer_try_scope,
8998 outer_try_index));
8999 }
9000 } else {
9001 ASSERT(outer_try_scope == NULL);
8946 } 9002 }
8947 9003
8948 statement = yield; 9004 statement = yield;
8949 ExpectSemicolon(); 9005 ExpectSemicolon();
8950 } else if (token == Token::kIF) { 9006 } else if (token == Token::kIF) {
8951 statement = ParseIfStatement(label_name); 9007 statement = ParseIfStatement(label_name);
8952 } else if (token == Token::kASSERT) { 9008 } else if (token == Token::kASSERT) {
8953 statement = ParseAssertStatement(); 9009 statement = ParseAssertStatement();
8954 ExpectSemicolon(); 9010 ExpectSemicolon();
8955 } else if (IsVariableDeclaration()) { 9011 } else if (IsVariableDeclaration()) {
(...skipping 30 matching lines...) Expand all
8986 // Rethrow of current exception. 9042 // Rethrow of current exception.
8987 ConsumeToken(); 9043 ConsumeToken();
8988 ExpectSemicolon(); 9044 ExpectSemicolon();
8989 // Check if it is ok to do a rethrow. 9045 // Check if it is ok to do a rethrow.
8990 if ((try_blocks_list_ == NULL) || !try_blocks_list_->inside_catch()) { 9046 if ((try_blocks_list_ == NULL) || !try_blocks_list_->inside_catch()) {
8991 ReportError(statement_pos, "rethrow of an exception is not valid here"); 9047 ReportError(statement_pos, "rethrow of an exception is not valid here");
8992 } 9048 }
8993 9049
8994 // If in async code, use :saved_exception_var and :saved_stack_trace_var 9050 // If in async code, use :saved_exception_var and :saved_stack_trace_var
8995 // instead of :exception_var and :stack_trace_var. 9051 // instead of :exception_var and :stack_trace_var.
9052 // These variables are bound in the block containing the try.
9053 // Look in the try scope directly.
9054 LocalScope* scope = try_blocks_list_->try_block()->scope->parent();
9055 ASSERT(scope != NULL);
8996 LocalVariable* excp_var; 9056 LocalVariable* excp_var;
8997 LocalVariable* trace_var; 9057 LocalVariable* trace_var;
8998 if (innermost_function().IsAsyncClosure() || 9058 if (innermost_function().IsAsyncClosure() ||
8999 innermost_function().IsAsyncFunction() || 9059 innermost_function().IsAsyncFunction() ||
9000 innermost_function().IsSyncGenClosure() || 9060 innermost_function().IsSyncGenClosure() ||
9001 innermost_function().IsSyncGenerator()) { 9061 innermost_function().IsSyncGenerator()) {
9002 // The saved exception and stack trace variables are bound in the block 9062 excp_var = scope->LocalLookupVariable(Symbols::SavedExceptionVar());
9003 // containing the catch. So start looking in the current scope. 9063 trace_var = scope->LocalLookupVariable(Symbols::SavedStackTraceVar());
9004 LocalScope* scope = current_block_->scope;
9005 excp_var = scope->LookupVariable(Symbols::SavedExceptionVar(), false);
9006 trace_var = scope->LookupVariable(Symbols::SavedStackTraceVar(), false);
9007 } else { 9064 } else {
9008 // The exception and stack trace variables are bound in the block
9009 // containing the try. Look in the try scope directly.
9010 LocalScope* scope = try_blocks_list_->try_block()->scope->parent();
9011 ASSERT(scope != NULL);
9012 excp_var = scope->LocalLookupVariable(Symbols::ExceptionVar()); 9065 excp_var = scope->LocalLookupVariable(Symbols::ExceptionVar());
9013 trace_var = scope->LocalLookupVariable(Symbols::StackTraceVar()); 9066 trace_var = scope->LocalLookupVariable(Symbols::StackTraceVar());
9014 } 9067 }
9015 ASSERT(excp_var != NULL); 9068 ASSERT(excp_var != NULL);
9016 ASSERT(trace_var != NULL); 9069 ASSERT(trace_var != NULL);
9017 9070
9018 statement = new(Z) ThrowNode( 9071 statement = new(Z) ThrowNode(
9019 statement_pos, 9072 statement_pos,
9020 new(Z) LoadLocalNode(statement_pos, excp_var), 9073 new(Z) LoadLocalNode(statement_pos, excp_var),
9021 new(Z) LoadLocalNode(statement_pos, trace_var)); 9074 new(Z) LoadLocalNode(statement_pos, trace_var));
(...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after
9691 SequenceNode** await_preamble) { 9744 SequenceNode** await_preamble) {
9692 TRACE_PARSER("ParseAwaitableExpr"); 9745 TRACE_PARSER("ParseAwaitableExpr");
9693 BoolScope saved_seen_await(&parsed_function()->have_seen_await_expr_, false); 9746 BoolScope saved_seen_await(&parsed_function()->have_seen_await_expr_, false);
9694 AstNode* expr = ParseExpr(require_compiletime_const, consume_cascades); 9747 AstNode* expr = ParseExpr(require_compiletime_const, consume_cascades);
9695 if (parsed_function()->have_seen_await()) { 9748 if (parsed_function()->have_seen_await()) {
9696 // Make sure we do not reuse the scope to avoid creating contexts that we 9749 // Make sure we do not reuse the scope to avoid creating contexts that we
9697 // are unaware of, i.e, creating contexts that have already been covered. 9750 // are unaware of, i.e, creating contexts that have already been covered.
9698 // See FlowGraphBuilder::VisitSequenceNode() for details on when contexts 9751 // See FlowGraphBuilder::VisitSequenceNode() for details on when contexts
9699 // are created. 9752 // are created.
9700 OpenBlock(); 9753 OpenBlock();
9701 AwaitTransformer at(current_block_->statements, 9754 AwaitTransformer at(current_block_->statements, async_temp_scope_);
9702 *parsed_function(),
9703 async_temp_scope_);
9704 AstNode* result = at.Transform(expr); 9755 AstNode* result = at.Transform(expr);
9705 SequenceNode* preamble = CloseBlock(); 9756 SequenceNode* preamble = CloseBlock();
9706 if (await_preamble == NULL) { 9757 if (await_preamble == NULL) {
9707 current_block_->statements->Add(preamble); 9758 current_block_->statements->Add(preamble);
9708 } else { 9759 } else {
9709 *await_preamble = preamble; 9760 *await_preamble = preamble;
9710 } 9761 }
9711 return result; 9762 return result;
9712 } 9763 }
9713 return expr; 9764 return expr;
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
9809 AstNode* expr = NULL; 9860 AstNode* expr = NULL;
9810 const intptr_t op_pos = TokenPos(); 9861 const intptr_t op_pos = TokenPos();
9811 if (IsAwaitKeyword()) { 9862 if (IsAwaitKeyword()) {
9812 TRACE_PARSER("ParseAwaitExpr"); 9863 TRACE_PARSER("ParseAwaitExpr");
9813 if (!innermost_function().IsAsyncFunction() && 9864 if (!innermost_function().IsAsyncFunction() &&
9814 !innermost_function().IsAsyncClosure()) { 9865 !innermost_function().IsAsyncClosure()) {
9815 ReportError("await operator is only allowed in async function"); 9866 ReportError("await operator is only allowed in async function");
9816 } 9867 }
9817 ConsumeToken(); 9868 ConsumeToken();
9818 parsed_function()->record_await(); 9869 parsed_function()->record_await();
9819 expr = new (Z) AwaitNode(op_pos, ParseUnaryExpr()); 9870
9871 LocalScope* try_scope;
9872 int16_t try_index;
9873 LocalScope* outer_try_scope;
9874 int16_t outer_try_index;
9875 CheckAsyncOpInTryBlock(&try_scope, &try_index,
9876 &outer_try_scope, &outer_try_index);
9877
9878 expr = new (Z) AwaitNode(op_pos,
9879 ParseUnaryExpr(),
9880 try_scope,
9881 try_index,
9882 outer_try_scope,
9883 outer_try_index);
9820 } else if (IsPrefixOperator(CurrentToken())) { 9884 } else if (IsPrefixOperator(CurrentToken())) {
9821 Token::Kind unary_op = CurrentToken(); 9885 Token::Kind unary_op = CurrentToken();
9822 if (unary_op == Token::kSUB) { 9886 if (unary_op == Token::kSUB) {
9823 unary_op = Token::kNEGATE; 9887 unary_op = Token::kNEGATE;
9824 } 9888 }
9825 ConsumeToken(); 9889 ConsumeToken();
9826 expr = ParseUnaryExpr(); 9890 expr = ParseUnaryExpr();
9827 if (expr->IsPrimaryNode() && (expr->AsPrimaryNode()->IsSuper())) { 9891 if (expr->IsPrimaryNode() && (expr->AsPrimaryNode()->IsSuper())) {
9828 expr = BuildUnarySuperOperator(unary_op, expr->AsPrimaryNode()); 9892 expr = BuildUnarySuperOperator(unary_op, expr->AsPrimaryNode());
9829 } else { 9893 } else {
(...skipping 1252 matching lines...) Expand 10 before | Expand all | Expand 10 after
11082 // Parses type = [ident "."] ident ["<" type { "," type } ">"], then resolve and 11146 // Parses type = [ident "."] ident ["<" type { "," type } ">"], then resolve and
11083 // finalize it according to the given type finalization mode. 11147 // finalize it according to the given type finalization mode.
11084 RawAbstractType* Parser::ParseType( 11148 RawAbstractType* Parser::ParseType(
11085 ClassFinalizer::FinalizationKind finalization, 11149 ClassFinalizer::FinalizationKind finalization,
11086 bool allow_deferred_type, 11150 bool allow_deferred_type,
11087 bool consume_unresolved_prefix) { 11151 bool consume_unresolved_prefix) {
11088 TRACE_PARSER("ParseType"); 11152 TRACE_PARSER("ParseType");
11089 CheckToken(Token::kIDENT, "type name expected"); 11153 CheckToken(Token::kIDENT, "type name expected");
11090 intptr_t ident_pos = TokenPos(); 11154 intptr_t ident_pos = TokenPos();
11091 LibraryPrefix& prefix = LibraryPrefix::Handle(Z); 11155 LibraryPrefix& prefix = LibraryPrefix::Handle(Z);
11092 String& type_name = String::Handle(Z);; 11156 String& type_name = String::Handle(Z);
11093 11157
11094 if (finalization == ClassFinalizer::kIgnore) { 11158 if (finalization == ClassFinalizer::kIgnore) {
11095 if (!is_top_level_ && (current_block_ != NULL)) { 11159 if (!is_top_level_ && (current_block_ != NULL)) {
11096 // Add the library prefix or type class name to the list of referenced 11160 // Add the library prefix or type class name to the list of referenced
11097 // names of this scope, even if the type is ignored. 11161 // names of this scope, even if the type is ignored.
11098 current_block_->scope->AddReferencedName(TokenPos(), *CurrentLiteral()); 11162 current_block_->scope->AddReferencedName(TokenPos(), *CurrentLiteral());
11099 } 11163 }
11100 SkipQualIdent(); 11164 SkipQualIdent();
11101 } else { 11165 } else {
11102 prefix = ParsePrefix(); 11166 prefix = ParsePrefix();
(...skipping 1539 matching lines...) Expand 10 before | Expand all | Expand 10 after
12642 void Parser::SkipQualIdent() { 12706 void Parser::SkipQualIdent() {
12643 ASSERT(IsIdentifier()); 12707 ASSERT(IsIdentifier());
12644 ConsumeToken(); 12708 ConsumeToken();
12645 if (CurrentToken() == Token::kPERIOD) { 12709 if (CurrentToken() == Token::kPERIOD) {
12646 ConsumeToken(); // Consume the kPERIOD token. 12710 ConsumeToken(); // Consume the kPERIOD token.
12647 ExpectIdentifier("identifier expected after '.'"); 12711 ExpectIdentifier("identifier expected after '.'");
12648 } 12712 }
12649 } 12713 }
12650 12714
12651 } // namespace dart 12715 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/symbols.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698