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 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 272 } | 272 } |
| 273 Block* parent; // Enclosing block, or NULL if outermost. | 273 Block* parent; // Enclosing block, or NULL if outermost. |
| 274 LocalScope* scope; | 274 LocalScope* scope; |
| 275 SequenceNode* statements; | 275 SequenceNode* statements; |
| 276 }; | 276 }; |
| 277 | 277 |
| 278 | 278 |
| 279 // Class which describes an inlined finally block which is used to generate | 279 // Class which describes an inlined finally block which is used to generate |
| 280 // inlined code for the finally blocks when there is an exit from a try | 280 // inlined code for the finally blocks when there is an exit from a try |
| 281 // block using 'return', 'break' or 'continue'. | 281 // block using 'return', 'break' or 'continue'. |
| 282 class Parser::TryBlocks : public ZoneAllocated { | 282 class Parser::TryStack : public ZoneAllocated { |
| 283 public: | 283 public: |
| 284 TryBlocks(Block* try_block, TryBlocks* outer_try_block, intptr_t try_index) | 284 TryStack(Block* try_block, TryStack* outer_try, intptr_t try_index) |
| 285 : try_block_(try_block), | 285 : try_block_(try_block), |
| 286 inlined_finally_nodes_(), | 286 inlined_finally_nodes_(), |
| 287 outer_try_block_(outer_try_block), | 287 outer_try_(outer_try), |
| 288 try_index_(try_index), | 288 try_index_(try_index), |
| 289 inside_catch_(false) { } | 289 inside_catch_(false) { } |
| 290 | 290 |
| 291 TryBlocks* outer_try_block() const { return outer_try_block_; } | 291 TryStack* outer_try() const { return outer_try_; } |
| 292 Block* try_block() const { return try_block_; } | 292 Block* try_block() const { return try_block_; } |
| 293 intptr_t try_index() const { return try_index_; } | 293 intptr_t try_index() const { return try_index_; } |
| 294 bool inside_catch() const { return inside_catch_; } | 294 bool inside_catch() const { return inside_catch_; } |
| 295 void enter_catch() { inside_catch_ = true; } | 295 void enter_catch() { inside_catch_ = true; } |
| 296 | 296 |
| 297 void AddNodeForFinallyInlining(AstNode* node); | 297 void AddNodeForFinallyInlining(AstNode* node); |
| 298 AstNode* GetNodeToInlineFinally(int index) { | 298 AstNode* GetNodeToInlineFinally(int index) { |
| 299 if (0 <= index && index < inlined_finally_nodes_.length()) { | 299 if (0 <= index && index < inlined_finally_nodes_.length()) { |
| 300 return inlined_finally_nodes_[index]; | 300 return inlined_finally_nodes_[index]; |
| 301 } | 301 } |
| 302 return NULL; | 302 return NULL; |
| 303 } | 303 } |
| 304 | 304 |
| 305 private: | 305 private: |
| 306 Block* try_block_; | 306 Block* try_block_; |
| 307 GrowableArray<AstNode*> inlined_finally_nodes_; | 307 GrowableArray<AstNode*> inlined_finally_nodes_; |
| 308 TryBlocks* outer_try_block_; | 308 TryStack* outer_try_; |
| 309 const intptr_t try_index_; | 309 const intptr_t try_index_; |
| 310 bool inside_catch_; | 310 bool inside_catch_; |
| 311 | 311 |
| 312 DISALLOW_COPY_AND_ASSIGN(TryBlocks); | 312 DISALLOW_COPY_AND_ASSIGN(TryStack); |
| 313 }; | 313 }; |
| 314 | 314 |
| 315 | 315 |
| 316 void Parser::TryBlocks::AddNodeForFinallyInlining(AstNode* node) { | 316 void Parser::TryStack::AddNodeForFinallyInlining(AstNode* node) { |
| 317 inlined_finally_nodes_.Add(node); | 317 inlined_finally_nodes_.Add(node); |
| 318 } | 318 } |
| 319 | 319 |
| 320 | 320 |
| 321 // For parsing a compilation unit. | 321 // For parsing a compilation unit. |
| 322 Parser::Parser(const Script& script, const Library& library, intptr_t token_pos) | 322 Parser::Parser(const Script& script, const Library& library, intptr_t token_pos) |
| 323 : thread_(Thread::Current()), | 323 : thread_(Thread::Current()), |
| 324 script_(Script::Handle(zone(), script.raw())), | 324 script_(Script::Handle(zone(), script.raw())), |
| 325 tokens_iterator_(TokenStream::Handle(zone(), script.tokens()), | 325 tokens_iterator_(TokenStream::Handle(zone(), script.tokens()), |
| 326 token_pos), | 326 token_pos), |
| 327 token_kind_(Token::kILLEGAL), | 327 token_kind_(Token::kILLEGAL), |
| 328 current_block_(NULL), | 328 current_block_(NULL), |
| 329 is_top_level_(false), | 329 is_top_level_(false), |
| 330 await_is_keyword_(false), | 330 await_is_keyword_(false), |
| 331 current_member_(NULL), | 331 current_member_(NULL), |
| 332 allow_function_literals_(true), | 332 allow_function_literals_(true), |
| 333 parsed_function_(NULL), | 333 parsed_function_(NULL), |
| 334 innermost_function_(Function::Handle(zone())), | 334 innermost_function_(Function::Handle(zone())), |
| 335 literal_token_(LiteralToken::Handle(zone())), | 335 literal_token_(LiteralToken::Handle(zone())), |
| 336 current_class_(Class::Handle(zone())), | 336 current_class_(Class::Handle(zone())), |
| 337 library_(Library::Handle(zone(), library.raw())), | 337 library_(Library::Handle(zone(), library.raw())), |
| 338 try_blocks_list_(NULL), | 338 try_stack_(NULL), |
| 339 last_used_try_index_(0), | 339 last_used_try_index_(0), |
| 340 unregister_pending_function_(false), | 340 unregister_pending_function_(false), |
| 341 async_temp_scope_(NULL), | 341 async_temp_scope_(NULL), |
| 342 trace_indent_(0) { | 342 trace_indent_(0) { |
| 343 ASSERT(tokens_iterator_.IsValid()); | 343 ASSERT(tokens_iterator_.IsValid()); |
| 344 ASSERT(!library.IsNull()); | 344 ASSERT(!library.IsNull()); |
| 345 } | 345 } |
| 346 | 346 |
| 347 | 347 |
| 348 // For parsing a function. | 348 // For parsing a function. |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 361 allow_function_literals_(true), | 361 allow_function_literals_(true), |
| 362 parsed_function_(parsed_function), | 362 parsed_function_(parsed_function), |
| 363 innermost_function_(Function::Handle(zone(), | 363 innermost_function_(Function::Handle(zone(), |
| 364 parsed_function->function().raw())), | 364 parsed_function->function().raw())), |
| 365 literal_token_(LiteralToken::Handle(zone())), | 365 literal_token_(LiteralToken::Handle(zone())), |
| 366 current_class_(Class::Handle(zone(), | 366 current_class_(Class::Handle(zone(), |
| 367 parsed_function->function().Owner())), | 367 parsed_function->function().Owner())), |
| 368 library_(Library::Handle(zone(), Class::Handle( | 368 library_(Library::Handle(zone(), Class::Handle( |
| 369 zone(), | 369 zone(), |
| 370 parsed_function->function().origin()).library())), | 370 parsed_function->function().origin()).library())), |
| 371 try_blocks_list_(NULL), | 371 try_stack_(NULL), |
| 372 last_used_try_index_(0), | 372 last_used_try_index_(0), |
| 373 unregister_pending_function_(false), | 373 unregister_pending_function_(false), |
| 374 async_temp_scope_(NULL), | 374 async_temp_scope_(NULL), |
| 375 trace_indent_(0) { | 375 trace_indent_(0) { |
| 376 ASSERT(tokens_iterator_.IsValid()); | 376 ASSERT(tokens_iterator_.IsValid()); |
| 377 ASSERT(!current_function().IsNull()); | 377 ASSERT(!current_function().IsNull()); |
| 378 EnsureExpressionTemp(); | 378 EnsureExpressionTemp(); |
| 379 } | 379 } |
| 380 | 380 |
| 381 | 381 |
| (...skipping 5593 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5975 async_temp_scope_ = current_block_->scope; | 5975 async_temp_scope_ = current_block_->scope; |
| 5976 | 5976 |
| 5977 OpenAsyncTryBlock(); | 5977 OpenAsyncTryBlock(); |
| 5978 } | 5978 } |
| 5979 | 5979 |
| 5980 | 5980 |
| 5981 SequenceNode* Parser::CloseAsyncGeneratorTryBlock(SequenceNode *body) { | 5981 SequenceNode* Parser::CloseAsyncGeneratorTryBlock(SequenceNode *body) { |
| 5982 TRACE_PARSER("CloseAsyncGeneratorTryBlock"); | 5982 TRACE_PARSER("CloseAsyncGeneratorTryBlock"); |
| 5983 // The generated try-catch-finally that wraps the async generator function | 5983 // The generated try-catch-finally that wraps the async generator function |
| 5984 // body is the outermost try statement. | 5984 // body is the outermost try statement. |
| 5985 ASSERT(try_blocks_list_ != NULL); | 5985 ASSERT(try_stack_ != NULL); |
| 5986 ASSERT(try_blocks_list_->outer_try_block() == NULL); | 5986 ASSERT(try_stack_->outer_try() == NULL); |
| 5987 // We only get here when parsing an async generator body. | 5987 // We only get here when parsing an async generator body. |
| 5988 ASSERT(innermost_function().IsAsyncGenClosure()); | 5988 ASSERT(innermost_function().IsAsyncGenClosure()); |
| 5989 | 5989 |
| 5990 const intptr_t try_end_pos = innermost_function().end_token_pos(); | 5990 const intptr_t try_end_pos = innermost_function().end_token_pos(); |
| 5991 | 5991 |
| 5992 // The try-block (closure body code) has been parsed. We are now | 5992 // The try-block (closure body code) has been parsed. We are now |
| 5993 // generating the code for the catch block. | 5993 // generating the code for the catch block. |
| 5994 LocalScope* try_scope = current_block_->scope; | 5994 LocalScope* try_scope = current_block_->scope; |
| 5995 try_blocks_list_->enter_catch(); | 5995 try_stack_->enter_catch(); |
| 5996 OpenBlock(); // Catch handler list. | 5996 OpenBlock(); // Catch handler list. |
| 5997 OpenBlock(); // Catch block. | 5997 OpenBlock(); // Catch block. |
| 5998 | 5998 |
| 5999 // Add the exception and stack trace parameters to the scope. | 5999 // Add the exception and stack trace parameters to the scope. |
| 6000 const AbstractType& dynamic_type = | 6000 const AbstractType& dynamic_type = |
| 6001 AbstractType::ZoneHandle(Z, Type::DynamicType()); | 6001 AbstractType::ZoneHandle(Z, Type::DynamicType()); |
| 6002 CatchParamDesc exception_param; | 6002 CatchParamDesc exception_param; |
| 6003 CatchParamDesc stack_trace_param; | 6003 CatchParamDesc stack_trace_param; |
| 6004 exception_param.token_pos = Scanner::kNoSourcePos; | 6004 exception_param.token_pos = Scanner::kNoSourcePos; |
| 6005 exception_param.type = &dynamic_type; | 6005 exception_param.type = &dynamic_type; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6066 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller), | 6066 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller), |
| 6067 Symbols::AddError(), | 6067 Symbols::AddError(), |
| 6068 args)); | 6068 args)); |
| 6069 ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos); | 6069 ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos); |
| 6070 AddNodeForFinallyInlining(return_node); | 6070 AddNodeForFinallyInlining(return_node); |
| 6071 current_block_->statements->Add(return_node); | 6071 current_block_->statements->Add(return_node); |
| 6072 AstNode* catch_block = CloseBlock(); | 6072 AstNode* catch_block = CloseBlock(); |
| 6073 current_block_->statements->Add(catch_block); | 6073 current_block_->statements->Add(catch_block); |
| 6074 SequenceNode* catch_handler_list = CloseBlock(); | 6074 SequenceNode* catch_handler_list = CloseBlock(); |
| 6075 | 6075 |
| 6076 TryBlocks* try_block = PopTryBlock(); | 6076 TryStack* outer_try = PopTry(); |
|
hausner
2015/03/05 00:23:01
I always get confused with this name. Try statemen
regis
2015/03/05 00:41:51
Done. Renamed to "try_statement" here and below.
| |
| 6077 ASSERT(try_blocks_list_ == NULL); // We popped the outermost try block. | 6077 ASSERT(try_stack_ == NULL); // We popped the outermost try block. |
| 6078 | 6078 |
| 6079 // Finally block: closing the stream and returning. (Note: the return | 6079 // Finally block: closing the stream and returning. (Note: the return |
| 6080 // is necessary otherwise the back-end will append a rethrow of the | 6080 // is necessary otherwise the back-end will append a rethrow of the |
| 6081 // current exception.) | 6081 // current exception.) |
| 6082 // :controller.close(); | 6082 // :controller.close(); |
| 6083 // return; | 6083 // return; |
| 6084 // We need to inline this code in all recorded exit points. | 6084 // We need to inline this code in all recorded exit points. |
| 6085 intptr_t node_index = 0; | 6085 intptr_t node_index = 0; |
| 6086 SequenceNode* finally_clause = NULL; | 6086 SequenceNode* finally_clause = NULL; |
| 6087 do { | 6087 do { |
| 6088 OpenBlock(); | 6088 OpenBlock(); |
| 6089 ArgumentListNode* no_args = | 6089 ArgumentListNode* no_args = |
| 6090 new(Z) ArgumentListNode(Scanner::kNoSourcePos); | 6090 new(Z) ArgumentListNode(Scanner::kNoSourcePos); |
| 6091 current_block_->statements->Add( | 6091 current_block_->statements->Add( |
| 6092 new(Z) InstanceCallNode(try_end_pos, | 6092 new(Z) InstanceCallNode(try_end_pos, |
| 6093 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller), | 6093 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller), |
| 6094 Symbols::Close(), | 6094 Symbols::Close(), |
| 6095 no_args)); | 6095 no_args)); |
| 6096 | 6096 |
| 6097 ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos); | 6097 ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos); |
| 6098 current_block_->statements->Add(return_node); | 6098 current_block_->statements->Add(return_node); |
| 6099 | 6099 |
| 6100 finally_clause = CloseBlock(); | 6100 finally_clause = CloseBlock(); |
| 6101 AstNode* node_to_inline = try_block->GetNodeToInlineFinally(node_index); | 6101 AstNode* node_to_inline = outer_try->GetNodeToInlineFinally(node_index); |
| 6102 if (node_to_inline != NULL) { | 6102 if (node_to_inline != NULL) { |
| 6103 InlinedFinallyNode* node = | 6103 InlinedFinallyNode* node = |
| 6104 new(Z) InlinedFinallyNode(try_end_pos, | 6104 new(Z) InlinedFinallyNode(try_end_pos, |
| 6105 finally_clause, | 6105 finally_clause, |
| 6106 context_var, | 6106 context_var, |
| 6107 // No outer try statement | 6107 // No outer try statement |
| 6108 CatchClauseNode::kInvalidTryIndex); | 6108 CatchClauseNode::kInvalidTryIndex); |
| 6109 finally_clause = NULL; | 6109 finally_clause = NULL; |
| 6110 AddFinallyBlockToNode(true, node_to_inline, node); | 6110 AddFinallyBlockToNode(true, node_to_inline, node); |
| 6111 node_index++; | 6111 node_index++; |
| 6112 } | 6112 } |
| 6113 } while (finally_clause == NULL); | 6113 } while (finally_clause == NULL); |
| 6114 | 6114 |
| 6115 const GrowableObjectArray& handler_types = | 6115 const GrowableObjectArray& handler_types = |
| 6116 GrowableObjectArray::Handle(Z, GrowableObjectArray::New()); | 6116 GrowableObjectArray::Handle(Z, GrowableObjectArray::New()); |
| 6117 handler_types.Add(dynamic_type); // Catch block handles all exceptions. | 6117 handler_types.Add(dynamic_type); // Catch block handles all exceptions. |
| 6118 | 6118 |
| 6119 CatchClauseNode* catch_clause = new(Z) CatchClauseNode( | 6119 CatchClauseNode* catch_clause = new(Z) CatchClauseNode( |
| 6120 Scanner::kNoSourcePos, | 6120 Scanner::kNoSourcePos, |
| 6121 catch_handler_list, | 6121 catch_handler_list, |
| 6122 Array::ZoneHandle(Z, Array::MakeArray(handler_types)), | 6122 Array::ZoneHandle(Z, Array::MakeArray(handler_types)), |
| 6123 context_var, | 6123 context_var, |
| 6124 exception_var, | 6124 exception_var, |
| 6125 stack_trace_var, | 6125 stack_trace_var, |
| 6126 saved_exception_var, | 6126 saved_exception_var, |
| 6127 saved_stack_trace_var, | 6127 saved_stack_trace_var, |
| 6128 AllocateTryIndex(), | 6128 AllocateTryIndex(), |
| 6129 true); | 6129 true); |
| 6130 | 6130 |
| 6131 const intptr_t try_index = try_block->try_index(); | 6131 const intptr_t try_index = outer_try->try_index(); |
| 6132 | 6132 |
| 6133 AstNode* try_catch_node = | 6133 AstNode* try_catch_node = |
| 6134 new(Z) TryCatchNode(Scanner::kNoSourcePos, | 6134 new(Z) TryCatchNode(Scanner::kNoSourcePos, |
| 6135 body, | 6135 body, |
| 6136 context_var, | 6136 context_var, |
| 6137 catch_clause, | 6137 catch_clause, |
| 6138 finally_clause, | 6138 finally_clause, |
| 6139 try_index); | 6139 try_index); |
| 6140 current_block_->statements->Add(try_catch_node); | 6140 current_block_->statements->Add(try_catch_node); |
| 6141 return CloseBlock(); | 6141 return CloseBlock(); |
| 6142 } | 6142 } |
| 6143 | 6143 |
| 6144 | 6144 |
| 6145 SequenceNode* Parser::CloseAsyncTryBlock(SequenceNode* try_block) { | 6145 SequenceNode* Parser::CloseAsyncTryBlock(SequenceNode* try_block) { |
| 6146 // This is the outermost try-catch of the function. | 6146 // This is the outermost try-catch of the function. |
| 6147 ASSERT(try_blocks_list_ != NULL); | 6147 ASSERT(try_stack_ != NULL); |
| 6148 ASSERT(try_blocks_list_->outer_try_block() == NULL); | 6148 ASSERT(try_stack_->outer_try() == NULL); |
| 6149 ASSERT(innermost_function().IsAsyncClosure()); | 6149 ASSERT(innermost_function().IsAsyncClosure()); |
| 6150 LocalScope* try_scope = current_block_->scope; | 6150 LocalScope* try_scope = current_block_->scope; |
| 6151 | 6151 |
| 6152 try_blocks_list_->enter_catch(); | 6152 try_stack_->enter_catch(); |
| 6153 | 6153 |
| 6154 OpenBlock(); // Catch handler list. | 6154 OpenBlock(); // Catch handler list. |
| 6155 OpenBlock(); // Catch block. | 6155 OpenBlock(); // Catch block. |
| 6156 const AbstractType& dynamic_type = | 6156 const AbstractType& dynamic_type = |
| 6157 AbstractType::ZoneHandle(Z, Type::DynamicType()); | 6157 AbstractType::ZoneHandle(Z, Type::DynamicType()); |
| 6158 CatchParamDesc exception_param; | 6158 CatchParamDesc exception_param; |
| 6159 CatchParamDesc stack_trace_param; | 6159 CatchParamDesc stack_trace_param; |
| 6160 exception_param.token_pos = Scanner::kNoSourcePos; | 6160 exception_param.token_pos = Scanner::kNoSourcePos; |
| 6161 exception_param.type = &dynamic_type; | 6161 exception_param.type = &dynamic_type; |
| 6162 exception_param.name = &Symbols::ExceptionParameter(); | 6162 exception_param.name = &Symbols::ExceptionParameter(); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6227 current_block_->statements->Add(return_node); | 6227 current_block_->statements->Add(return_node); |
| 6228 AstNode* catch_block = CloseBlock(); | 6228 AstNode* catch_block = CloseBlock(); |
| 6229 current_block_->statements->Add(catch_block); | 6229 current_block_->statements->Add(catch_block); |
| 6230 SequenceNode* catch_handler_list = CloseBlock(); | 6230 SequenceNode* catch_handler_list = CloseBlock(); |
| 6231 | 6231 |
| 6232 const GrowableObjectArray& handler_types = | 6232 const GrowableObjectArray& handler_types = |
| 6233 GrowableObjectArray::Handle(Z, GrowableObjectArray::New()); | 6233 GrowableObjectArray::Handle(Z, GrowableObjectArray::New()); |
| 6234 handler_types.SetLength(0); | 6234 handler_types.SetLength(0); |
| 6235 handler_types.Add(*exception_param.type); | 6235 handler_types.Add(*exception_param.type); |
| 6236 | 6236 |
| 6237 TryBlocks* inner_try_block = PopTryBlock(); | 6237 TryStack* inner_try = PopTry(); |
| 6238 const intptr_t try_index = inner_try_block->try_index(); | 6238 const intptr_t try_index = inner_try->try_index(); |
| 6239 | 6239 |
| 6240 CatchClauseNode* catch_clause = new (Z) CatchClauseNode( | 6240 CatchClauseNode* catch_clause = new (Z) CatchClauseNode( |
| 6241 Scanner::kNoSourcePos, | 6241 Scanner::kNoSourcePos, |
| 6242 catch_handler_list, | 6242 catch_handler_list, |
| 6243 Array::ZoneHandle(Z, Array::MakeArray(handler_types)), | 6243 Array::ZoneHandle(Z, Array::MakeArray(handler_types)), |
| 6244 context_var, | 6244 context_var, |
| 6245 exception_var, | 6245 exception_var, |
| 6246 stack_trace_var, | 6246 stack_trace_var, |
| 6247 saved_exception_var, | 6247 saved_exception_var, |
| 6248 saved_stack_trace_var, | 6248 saved_stack_trace_var, |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 6273 true, | 6273 true, |
| 6274 &context_var, | 6274 &context_var, |
| 6275 &exception_var, | 6275 &exception_var, |
| 6276 &stack_trace_var, | 6276 &stack_trace_var, |
| 6277 &saved_exception_var, | 6277 &saved_exception_var, |
| 6278 &saved_stack_trace_var); | 6278 &saved_stack_trace_var); |
| 6279 | 6279 |
| 6280 // Open the try block. | 6280 // Open the try block. |
| 6281 OpenBlock(); | 6281 OpenBlock(); |
| 6282 // This is the outermost try-catch in the function. | 6282 // This is the outermost try-catch in the function. |
| 6283 ASSERT(try_blocks_list_ == NULL); | 6283 ASSERT(try_stack_ == NULL); |
| 6284 PushTryBlock(current_block_); | 6284 PushTry(current_block_); |
| 6285 | 6285 |
| 6286 SetupSavedTryContext(context_var); | 6286 SetupSavedTryContext(context_var); |
| 6287 } | 6287 } |
| 6288 | 6288 |
| 6289 | 6289 |
| 6290 void Parser::AddSyncGenClosureParameters(ParamList* params) { | 6290 void Parser::AddSyncGenClosureParameters(ParamList* params) { |
| 6291 // Create the parameter list for the body closure of a sync generator: | 6291 // Create the parameter list for the body closure of a sync generator: |
| 6292 // 1) Implicit closure parameter; | 6292 // 1) Implicit closure parameter; |
| 6293 // 2) Iterator | 6293 // 2) Iterator |
| 6294 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); | 6294 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); |
| (...skipping 1851 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8146 dowhile_body->Add(await_preamble); | 8146 dowhile_body->Add(await_preamble); |
| 8147 } | 8147 } |
| 8148 ExpectToken(Token::kRPAREN); | 8148 ExpectToken(Token::kRPAREN); |
| 8149 ExpectSemicolon(); | 8149 ExpectSemicolon(); |
| 8150 return new(Z) DoWhileNode(do_pos, label, cond_expr, dowhile_body); | 8150 return new(Z) DoWhileNode(do_pos, label, cond_expr, dowhile_body); |
| 8151 } | 8151 } |
| 8152 | 8152 |
| 8153 | 8153 |
| 8154 // If the await or yield being parsed is in a try block, the continuation code | 8154 // If the await or yield being parsed is in a try block, the continuation code |
| 8155 // needs to restore the corresponding stack-based variable :saved_try_ctx_var, | 8155 // needs to restore the corresponding stack-based variable :saved_try_ctx_var, |
| 8156 // and possibly the stack-based variable :saved_try_ctx_var of the outer try | 8156 // and the stack-based variable :saved_try_ctx_var of the outer try block. |
| 8157 // block. | |
| 8158 // The inner :saved_try_ctx_var is used by a finally clause handling an | 8157 // The inner :saved_try_ctx_var is used by a finally clause handling an |
| 8159 // exception thrown by the continuation code in a catch clause. If no finally | 8158 // exception thrown by the continuation code in a try block or catch block. |
| 8160 // clause exists, the catch or finally clause of the outer try block, if any, | 8159 // If no finally clause exists, the catch or finally clause of the outer try |
| 8161 // uses the outer :saved_try_ctx_var to handle the exception. | 8160 // block, if any, uses the outer :saved_try_ctx_var to handle the exception. |
| 8162 // | 8161 // |
| 8163 // * Try blocks: Set the context variable for this try block. | 8162 // * Try blocks and catch blocks: |
| 8164 // * Catch blocks: Set the context variable for this try block and for any outer | 8163 // Set the context variable for this try block and for the outer try block. |
| 8165 // try block (if existent). | 8164 // * Finally blocks: |
| 8166 // * Finally blocks: Set the context variable for any outer try block (if | 8165 // Set the context variable for the outer try block. Note that the try |
| 8167 // existent). Note that this try block is popped before | 8166 // declaring the finally is popped before parsing the finally clause, so the |
| 8168 // parsing the finally clause, so the outer try block (if | 8167 // outer try block is at the top of the try block list. |
| 8169 // existent) is at the top of the try block list. | |
| 8170 // | 8168 // |
| 8171 // TODO(regis): Could we return the variables instead of their containing | 8169 // TODO(regis): Could we return the variables instead of their containing |
| 8172 // scopes? Check if they are already setup at this point. | 8170 // scopes? Check if they are already setup at this point. |
| 8173 void Parser::CheckAsyncOpInTryBlock(LocalScope** try_scope, | 8171 void Parser::CheckAsyncOpInTryBlock(LocalScope** try_scope, |
| 8174 int16_t* try_index, | 8172 int16_t* try_index, |
| 8175 LocalScope** outer_try_scope, | 8173 LocalScope** outer_try_scope, |
| 8176 int16_t* outer_try_index) const { | 8174 int16_t* outer_try_index) const { |
| 8177 *try_scope = NULL; | 8175 *try_scope = NULL; |
| 8178 *try_index = CatchClauseNode::kInvalidTryIndex; | 8176 *try_index = CatchClauseNode::kInvalidTryIndex; |
| 8179 *outer_try_scope = NULL; | 8177 *outer_try_scope = NULL; |
| 8180 *outer_try_index = CatchClauseNode::kInvalidTryIndex; | 8178 *outer_try_index = CatchClauseNode::kInvalidTryIndex; |
| 8181 if (try_blocks_list_ != NULL) { | 8179 if (try_stack_ != NULL) { |
| 8182 LocalScope* scope = try_blocks_list_->try_block()->scope; | 8180 LocalScope* scope = try_stack_->try_block()->scope; |
| 8183 const int current_function_level = current_block_->scope->function_level(); | 8181 const int current_function_level = current_block_->scope->function_level(); |
| 8184 if (scope->function_level() == current_function_level) { | 8182 if (scope->function_level() == current_function_level) { |
| 8185 // The block declaring :saved_try_ctx_var variable is the parent of the | 8183 // The block declaring :saved_try_ctx_var variable is the parent of the |
| 8186 // pushed try block. | 8184 // pushed try block. |
| 8187 *try_scope = scope->parent(); | 8185 *try_scope = scope->parent(); |
| 8188 *try_index = try_blocks_list_->try_index(); | 8186 *try_index = try_stack_->try_index(); |
| 8189 if (try_blocks_list_->inside_catch() && | 8187 if (try_stack_->outer_try() != NULL) { |
| 8190 (try_blocks_list_->outer_try_block() != NULL)) { | 8188 // TODO(regis): Collecting the outer try scope is not necessary if we |
| 8191 scope = try_blocks_list_->outer_try_block()->try_block()->scope; | 8189 // are in a finally block. Add support for try_stack_->inside_finally(). |
| 8190 scope = try_stack_->outer_try()->try_block()->scope; | |
| 8192 if (scope->function_level() == current_function_level) { | 8191 if (scope->function_level() == current_function_level) { |
| 8193 *outer_try_scope = scope->parent(); | 8192 *outer_try_scope = scope->parent(); |
| 8194 *outer_try_index = try_blocks_list_->outer_try_block()->try_index(); | 8193 *outer_try_index = try_stack_->outer_try()->try_index(); |
| 8195 } | 8194 } |
| 8196 } | 8195 } |
| 8197 } | 8196 } |
| 8198 } | 8197 } |
| 8199 // An async or async* has an implicitly created try-catch around the | 8198 // An async or async* has an implicitly created try-catch around the |
| 8200 // function body, so the await or yield inside the async closure should always | 8199 // function body, so the await or yield inside the async closure should always |
| 8201 // be created with a try scope. | 8200 // be created with a try scope. |
| 8202 ASSERT((*try_scope != NULL) || | 8201 ASSERT((*try_scope != NULL) || |
| 8203 innermost_function().IsAsyncFunction() || | 8202 innermost_function().IsAsyncFunction() || |
| 8204 innermost_function().IsAsyncGenerator() || | 8203 innermost_function().IsAsyncGenerator() || |
| (...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8699 LocalVariable* rethrow_exception_var, | 8698 LocalVariable* rethrow_exception_var, |
| 8700 LocalVariable* rethrow_stack_trace_var) { | 8699 LocalVariable* rethrow_stack_trace_var) { |
| 8701 TRACE_PARSER("ParseFinallyBlock"); | 8700 TRACE_PARSER("ParseFinallyBlock"); |
| 8702 OpenBlock(); | 8701 OpenBlock(); |
| 8703 ExpectToken(Token::kLBRACE); | 8702 ExpectToken(Token::kLBRACE); |
| 8704 | 8703 |
| 8705 // In case of async closures we need to restore the saved try index of an | 8704 // In case of async closures we need to restore the saved try index of an |
| 8706 // outer try block (if it exists). The current try block has already been | 8705 // outer try block (if it exists). The current try block has already been |
| 8707 // removed from the stack of try blocks. | 8706 // removed from the stack of try blocks. |
| 8708 if (is_async) { | 8707 if (is_async) { |
| 8709 if (try_blocks_list_ != NULL) { | 8708 if (try_stack_ != NULL) { |
| 8710 LocalScope* scope = try_blocks_list_->try_block()->scope; | 8709 LocalScope* scope = try_stack_->try_block()->scope; |
| 8711 if (scope->function_level() == current_block_->scope->function_level()) { | 8710 if (scope->function_level() == current_block_->scope->function_level()) { |
| 8712 current_block_->statements->Add( | 8711 current_block_->statements->Add( |
| 8713 AwaitTransformer::RestoreSavedTryContext( | 8712 AwaitTransformer::RestoreSavedTryContext( |
| 8714 Z, scope->parent(), try_blocks_list_->try_index())); | 8713 Z, scope->parent(), try_stack_->try_index())); |
| 8715 } | 8714 } |
| 8716 } | 8715 } |
| 8717 // We need to save the exception variables as in catch clauses, whether | 8716 // We need to save the exception variables as in catch clauses, whether |
| 8718 // there is an outer try or not. Note that this is only necessary if the | 8717 // there is an outer try or not. Note that this is only necessary if the |
| 8719 // finally clause contains an await or yield. | 8718 // finally clause contains an await or yield. |
| 8720 // TODO(hausner): Optimize. | 8719 // TODO(hausner): Optimize. |
| 8721 SaveExceptionAndStacktrace(current_block_->statements, | 8720 SaveExceptionAndStacktrace(current_block_->statements, |
| 8722 exception_var, | 8721 exception_var, |
| 8723 stack_trace_var, | 8722 stack_trace_var, |
| 8724 rethrow_exception_var, | 8723 rethrow_exception_var, |
| 8725 rethrow_stack_trace_var); | 8724 rethrow_stack_trace_var); |
| 8726 } | 8725 } |
| 8727 | 8726 |
| 8728 ParseStatementSequence(); | 8727 ParseStatementSequence(); |
| 8729 ExpectToken(Token::kRBRACE); | 8728 ExpectToken(Token::kRBRACE); |
| 8730 SequenceNode* finally_block = CloseBlock(); | 8729 SequenceNode* finally_block = CloseBlock(); |
| 8731 return finally_block; | 8730 return finally_block; |
| 8732 } | 8731 } |
| 8733 | 8732 |
| 8734 | 8733 |
| 8735 void Parser::PushTryBlock(Block* try_block) { | 8734 void Parser::PushTry(Block* try_block) { |
| 8736 intptr_t try_index = AllocateTryIndex(); | 8735 intptr_t try_index = AllocateTryIndex(); |
| 8737 TryBlocks* block = new(Z) TryBlocks( | 8736 try_stack_ = new(Z) TryStack(try_block, try_stack_, try_index); |
| 8738 try_block, try_blocks_list_, try_index); | |
| 8739 try_blocks_list_ = block; | |
| 8740 } | 8737 } |
| 8741 | 8738 |
| 8742 | 8739 |
| 8743 Parser::TryBlocks* Parser::PopTryBlock() { | 8740 Parser::TryStack* Parser::PopTry() { |
| 8744 TryBlocks* innermost_try_block = try_blocks_list_; | 8741 TryStack* innermost_try = try_stack_; |
| 8745 try_blocks_list_ = try_blocks_list_->outer_try_block(); | 8742 try_stack_ = try_stack_->outer_try(); |
| 8746 return innermost_try_block; | 8743 return innermost_try; |
| 8747 } | 8744 } |
| 8748 | 8745 |
| 8749 | 8746 |
| 8750 void Parser::AddNodeForFinallyInlining(AstNode* node) { | 8747 void Parser::AddNodeForFinallyInlining(AstNode* node) { |
| 8751 if (node == NULL) { | 8748 if (node == NULL) { |
| 8752 return; | 8749 return; |
| 8753 } | 8750 } |
| 8754 ASSERT(node->IsReturnNode() || node->IsJumpNode()); | 8751 ASSERT(node->IsReturnNode() || node->IsJumpNode()); |
| 8755 TryBlocks* iterator = try_blocks_list_; | 8752 TryStack* iterator = try_stack_; |
| 8756 while (iterator != NULL) { | 8753 while (iterator != NULL) { |
| 8757 // For continue and break node check if the target label is in scope. | 8754 // For continue and break node check if the target label is in scope. |
| 8758 if (node->IsJumpNode()) { | 8755 if (node->IsJumpNode()) { |
| 8759 SourceLabel* label = node->AsJumpNode()->label(); | 8756 SourceLabel* label = node->AsJumpNode()->label(); |
| 8760 ASSERT(label != NULL); | 8757 ASSERT(label != NULL); |
| 8761 LocalScope* try_scope = iterator->try_block()->scope; | 8758 LocalScope* try_scope = iterator->try_block()->scope; |
| 8762 // If the label is defined in a scope which is a child (nested scope) | 8759 // If the label is defined in a scope which is a child (nested scope) |
| 8763 // of the try scope then we are not breaking out of this try block | 8760 // of the try scope then we are not breaking out of this try block |
| 8764 // so we do not need to inline the finally code. Otherwise we need | 8761 // so we do not need to inline the finally code. Otherwise we need |
| 8765 // to inline the finally code of this try block and then move on to the | 8762 // to inline the finally code of this try block and then move on to the |
| 8766 // next outer try block. | 8763 // next outer try block. |
| 8767 if (label->owner()->IsNestedWithin(try_scope)) { | 8764 if (label->owner()->IsNestedWithin(try_scope)) { |
| 8768 break; | 8765 break; |
| 8769 } | 8766 } |
| 8770 } | 8767 } |
| 8771 iterator->AddNodeForFinallyInlining(node); | 8768 iterator->AddNodeForFinallyInlining(node); |
| 8772 iterator = iterator->outer_try_block(); | 8769 iterator = iterator->outer_try(); |
| 8773 } | 8770 } |
| 8774 } | 8771 } |
| 8775 | 8772 |
| 8776 | 8773 |
| 8777 // Add the inlined finally block to the specified node. | 8774 // Add the inlined finally block to the specified node. |
| 8778 void Parser::AddFinallyBlockToNode(bool is_async, | 8775 void Parser::AddFinallyBlockToNode(bool is_async, |
| 8779 AstNode* node, | 8776 AstNode* node, |
| 8780 InlinedFinallyNode* finally_node) { | 8777 InlinedFinallyNode* finally_node) { |
| 8781 ReturnNode* return_node = node->AsReturnNode(); | 8778 ReturnNode* return_node = node->AsReturnNode(); |
| 8782 if (return_node != NULL) { | 8779 if (return_node != NULL) { |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8959 while (!type_tests.is_empty()) { | 8956 while (!type_tests.is_empty()) { |
| 8960 AstNode* type_test = type_tests.RemoveLast(); | 8957 AstNode* type_test = type_tests.RemoveLast(); |
| 8961 SequenceNode* catch_block = catch_blocks.RemoveLast(); | 8958 SequenceNode* catch_block = catch_blocks.RemoveLast(); |
| 8962 current_block_->statements->Add(new(Z) IfNode( | 8959 current_block_->statements->Add(new(Z) IfNode( |
| 8963 type_test->token_pos(), type_test, catch_block, current)); | 8960 type_test->token_pos(), type_test, catch_block, current)); |
| 8964 current = CloseBlock(); | 8961 current = CloseBlock(); |
| 8965 } | 8962 } |
| 8966 // In case of async closures, restore :saved_try_context_var before executing | 8963 // In case of async closures, restore :saved_try_context_var before executing |
| 8967 // the catch clauses. | 8964 // the catch clauses. |
| 8968 if (is_async && (current != NULL)) { | 8965 if (is_async && (current != NULL)) { |
| 8969 ASSERT(try_blocks_list_ != NULL); | 8966 ASSERT(try_stack_ != NULL); |
| 8970 SequenceNode* async_code = new(Z) SequenceNode(handler_pos, NULL); | 8967 SequenceNode* async_code = new(Z) SequenceNode(handler_pos, NULL); |
| 8971 const TryBlocks* try_block = try_blocks_list_->outer_try_block(); | 8968 const TryStack* try_block = try_stack_->outer_try(); |
| 8972 if (try_block != NULL) { | 8969 if (try_block != NULL) { |
| 8973 LocalScope* scope = try_block->try_block()->scope; | 8970 LocalScope* scope = try_block->try_block()->scope; |
| 8974 if (scope->function_level() == | 8971 if (scope->function_level() == |
| 8975 current_block_->scope->function_level()) { | 8972 current_block_->scope->function_level()) { |
| 8976 async_code->Add( | 8973 async_code->Add( |
| 8977 AwaitTransformer::RestoreSavedTryContext( | 8974 AwaitTransformer::RestoreSavedTryContext( |
| 8978 Z, scope->parent(), try_block->try_index())); | 8975 Z, scope->parent(), try_block->try_index())); |
| 8979 } | 8976 } |
| 8980 } | 8977 } |
| 8981 SaveExceptionAndStacktrace(async_code, | 8978 SaveExceptionAndStacktrace(async_code, |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9119 &context_var, | 9116 &context_var, |
| 9120 &exception_var, | 9117 &exception_var, |
| 9121 &stack_trace_var, | 9118 &stack_trace_var, |
| 9122 &saved_exception_var, | 9119 &saved_exception_var, |
| 9123 &saved_stack_trace_var); | 9120 &saved_stack_trace_var); |
| 9124 | 9121 |
| 9125 ConsumeToken(); // Consume the 'try'. | 9122 ConsumeToken(); // Consume the 'try'. |
| 9126 | 9123 |
| 9127 // Now parse the 'try' block. | 9124 // Now parse the 'try' block. |
| 9128 OpenBlock(); | 9125 OpenBlock(); |
| 9129 PushTryBlock(current_block_); | 9126 PushTry(current_block_); |
| 9130 ExpectToken(Token::kLBRACE); | 9127 ExpectToken(Token::kLBRACE); |
| 9131 | 9128 |
| 9132 if (is_async) { | 9129 if (is_async) { |
| 9133 SetupSavedTryContext(context_var); | 9130 SetupSavedTryContext(context_var); |
| 9134 } | 9131 } |
| 9135 | 9132 |
| 9136 ParseStatementSequence(); | 9133 ParseStatementSequence(); |
| 9137 ExpectToken(Token::kRBRACE); | 9134 ExpectToken(Token::kRBRACE); |
| 9138 SequenceNode* try_block = CloseBlock(); | 9135 SequenceNode* try_block = CloseBlock(); |
| 9139 | 9136 |
| 9140 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") && | 9137 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") && |
| 9141 (CurrentToken() != Token::kFINALLY)) { | 9138 (CurrentToken() != Token::kFINALLY)) { |
| 9142 ReportError("catch or finally clause expected"); | 9139 ReportError("catch or finally clause expected"); |
| 9143 } | 9140 } |
| 9144 | 9141 |
| 9145 // Now parse the 'catch' blocks if any. | 9142 // Now parse the 'catch' blocks if any. |
| 9146 try_blocks_list_->enter_catch(); | 9143 try_stack_->enter_catch(); |
| 9147 const intptr_t handler_pos = TokenPos(); | 9144 const intptr_t handler_pos = TokenPos(); |
| 9148 const GrowableObjectArray& handler_types = | 9145 const GrowableObjectArray& handler_types = |
| 9149 GrowableObjectArray::Handle(Z, GrowableObjectArray::New()); | 9146 GrowableObjectArray::Handle(Z, GrowableObjectArray::New()); |
| 9150 bool needs_stack_trace = false; | 9147 bool needs_stack_trace = false; |
| 9151 SequenceNode* catch_handler_list = | 9148 SequenceNode* catch_handler_list = |
| 9152 ParseCatchClauses(handler_pos, | 9149 ParseCatchClauses(handler_pos, |
| 9153 is_async, | 9150 is_async, |
| 9154 exception_var, | 9151 exception_var, |
| 9155 stack_trace_var, | 9152 stack_trace_var, |
| 9156 is_async ? saved_exception_var : exception_var, | 9153 is_async ? saved_exception_var : exception_var, |
| 9157 is_async ? saved_stack_trace_var : stack_trace_var, | 9154 is_async ? saved_stack_trace_var : stack_trace_var, |
| 9158 handler_types, | 9155 handler_types, |
| 9159 &needs_stack_trace); | 9156 &needs_stack_trace); |
| 9160 | 9157 |
| 9161 TryBlocks* inner_try_block = PopTryBlock(); | 9158 TryStack* inner_try = PopTry(); |
| 9162 const intptr_t try_index = inner_try_block->try_index(); | 9159 const intptr_t try_index = inner_try->try_index(); |
| 9163 TryBlocks* outer_try_block = try_blocks_list_; | 9160 TryStack* outer_try = try_stack_; |
| 9164 const intptr_t outer_try_index = (outer_try_block != NULL) | 9161 const intptr_t outer_try_index = (outer_try != NULL) ? |
| 9165 ? outer_try_block->try_index() | 9162 outer_try->try_index() : CatchClauseNode::kInvalidTryIndex; |
| 9166 : CatchClauseNode::kInvalidTryIndex; | |
| 9167 | 9163 |
| 9168 // Finally parse the 'finally' block. | 9164 // Finally parse the 'finally' block. |
| 9169 SequenceNode* finally_block = NULL; | 9165 SequenceNode* finally_block = NULL; |
| 9170 if (CurrentToken() == Token::kFINALLY) { | 9166 if (CurrentToken() == Token::kFINALLY) { |
| 9171 ConsumeToken(); // Consume the 'finally'. | 9167 ConsumeToken(); // Consume the 'finally'. |
| 9172 const intptr_t finally_pos = TokenPos(); | 9168 const intptr_t finally_pos = TokenPos(); |
| 9173 // Add the finally block to the exit points recorded so far. | 9169 // Add the finally block to the exit points recorded so far. |
| 9174 intptr_t node_index = 0; | 9170 intptr_t node_index = 0; |
| 9175 AstNode* node_to_inline = | 9171 AstNode* node_to_inline = inner_try->GetNodeToInlineFinally(node_index); |
| 9176 inner_try_block->GetNodeToInlineFinally(node_index); | |
| 9177 while (node_to_inline != NULL) { | 9172 while (node_to_inline != NULL) { |
| 9178 finally_block = ParseFinallyBlock( | 9173 finally_block = ParseFinallyBlock( |
| 9179 is_async, | 9174 is_async, |
| 9180 exception_var, | 9175 exception_var, |
| 9181 stack_trace_var, | 9176 stack_trace_var, |
| 9182 is_async ? saved_exception_var : exception_var, | 9177 is_async ? saved_exception_var : exception_var, |
| 9183 is_async ? saved_stack_trace_var : stack_trace_var); | 9178 is_async ? saved_stack_trace_var : stack_trace_var); |
| 9184 InlinedFinallyNode* node = new(Z) InlinedFinallyNode(finally_pos, | 9179 InlinedFinallyNode* node = new(Z) InlinedFinallyNode(finally_pos, |
| 9185 finally_block, | 9180 finally_block, |
| 9186 context_var, | 9181 context_var, |
| 9187 outer_try_index); | 9182 outer_try_index); |
| 9188 AddFinallyBlockToNode(is_async, node_to_inline, node); | 9183 AddFinallyBlockToNode(is_async, node_to_inline, node); |
| 9189 node_index += 1; | 9184 node_index += 1; |
| 9190 node_to_inline = inner_try_block->GetNodeToInlineFinally(node_index); | 9185 node_to_inline = inner_try->GetNodeToInlineFinally(node_index); |
| 9191 tokens_iterator_.SetCurrentPosition(finally_pos); | 9186 tokens_iterator_.SetCurrentPosition(finally_pos); |
| 9192 } | 9187 } |
| 9193 finally_block = ParseFinallyBlock( | 9188 finally_block = ParseFinallyBlock( |
| 9194 is_async, | 9189 is_async, |
| 9195 exception_var, | 9190 exception_var, |
| 9196 stack_trace_var, | 9191 stack_trace_var, |
| 9197 is_async ? saved_exception_var : exception_var, | 9192 is_async ? saved_exception_var : exception_var, |
| 9198 is_async ? saved_stack_trace_var : stack_trace_var); | 9193 is_async ? saved_stack_trace_var : stack_trace_var); |
| 9199 } | 9194 } |
| 9200 | 9195 |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9526 AddNodeForFinallyInlining(statement); | 9521 AddNodeForFinallyInlining(statement); |
| 9527 ExpectSemicolon(); | 9522 ExpectSemicolon(); |
| 9528 } else if (token == Token::kSEMICOLON) { | 9523 } else if (token == Token::kSEMICOLON) { |
| 9529 // Empty statement, nothing to do. | 9524 // Empty statement, nothing to do. |
| 9530 ConsumeToken(); | 9525 ConsumeToken(); |
| 9531 } else if (token == Token::kRETHROW) { | 9526 } else if (token == Token::kRETHROW) { |
| 9532 // Rethrow of current exception. | 9527 // Rethrow of current exception. |
| 9533 ConsumeToken(); | 9528 ConsumeToken(); |
| 9534 ExpectSemicolon(); | 9529 ExpectSemicolon(); |
| 9535 // Check if it is ok to do a rethrow. | 9530 // Check if it is ok to do a rethrow. |
| 9536 if ((try_blocks_list_ == NULL) || !try_blocks_list_->inside_catch()) { | 9531 if ((try_stack_ == NULL) || !try_stack_->inside_catch()) { |
| 9537 ReportError(statement_pos, "rethrow of an exception is not valid here"); | 9532 ReportError(statement_pos, "rethrow of an exception is not valid here"); |
| 9538 } | 9533 } |
| 9539 | 9534 |
| 9540 // If in async code, use :saved_exception_var and :saved_stack_trace_var | 9535 // If in async code, use :saved_exception_var and :saved_stack_trace_var |
| 9541 // instead of :exception_var and :stack_trace_var. | 9536 // instead of :exception_var and :stack_trace_var. |
| 9542 // These variables are bound in the block containing the try. | 9537 // These variables are bound in the block containing the try. |
| 9543 // Look in the try scope directly. | 9538 // Look in the try scope directly. |
| 9544 LocalScope* scope = try_blocks_list_->try_block()->scope->parent(); | 9539 LocalScope* scope = try_stack_->try_block()->scope->parent(); |
| 9545 ASSERT(scope != NULL); | 9540 ASSERT(scope != NULL); |
| 9546 LocalVariable* excp_var; | 9541 LocalVariable* excp_var; |
| 9547 LocalVariable* trace_var; | 9542 LocalVariable* trace_var; |
| 9548 if (innermost_function().IsAsyncClosure() || | 9543 if (innermost_function().IsAsyncClosure() || |
| 9549 innermost_function().IsAsyncFunction() || | 9544 innermost_function().IsAsyncFunction() || |
| 9550 innermost_function().IsSyncGenClosure() || | 9545 innermost_function().IsSyncGenClosure() || |
| 9551 innermost_function().IsSyncGenerator() || | 9546 innermost_function().IsSyncGenerator() || |
| 9552 innermost_function().IsAsyncGenClosure() || | 9547 innermost_function().IsAsyncGenClosure() || |
| 9553 innermost_function().IsAsyncGenerator()) { | 9548 innermost_function().IsAsyncGenerator()) { |
| 9554 excp_var = scope->LocalLookupVariable(Symbols::SavedExceptionVar()); | 9549 excp_var = scope->LocalLookupVariable(Symbols::SavedExceptionVar()); |
| (...skipping 3645 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 13200 void Parser::SkipQualIdent() { | 13195 void Parser::SkipQualIdent() { |
| 13201 ASSERT(IsIdentifier()); | 13196 ASSERT(IsIdentifier()); |
| 13202 ConsumeToken(); | 13197 ConsumeToken(); |
| 13203 if (CurrentToken() == Token::kPERIOD) { | 13198 if (CurrentToken() == Token::kPERIOD) { |
| 13204 ConsumeToken(); // Consume the kPERIOD token. | 13199 ConsumeToken(); // Consume the kPERIOD token. |
| 13205 ExpectIdentifier("identifier expected after '.'"); | 13200 ExpectIdentifier("identifier expected after '.'"); |
| 13206 } | 13201 } |
| 13207 } | 13202 } |
| 13208 | 13203 |
| 13209 } // namespace dart | 13204 } // namespace dart |
| OLD | NEW |