Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |