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

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

Issue 977243002: Fix more async machinery (issue 22579 and possibly more to be triaged). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/regress_22579_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/parser.h" 5 #include "vm/parser.h"
6 6
7 #include "lib/invocation_mirror.h" 7 #include "lib/invocation_mirror.h"
8 #include "platform/utils.h" 8 #include "platform/utils.h"
9 #include "vm/ast_transformer.h" 9 #include "vm/ast_transformer.h"
10 #include "vm/bootstrap.h" 10 #include "vm/bootstrap.h"
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/regress_22579_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698