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

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

Issue 22184003: Fix a bug in compilation of try-finally. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 4 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/language.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/parser.h" 5 #include "vm/parser.h"
6 6
7 #include "lib/invocation_mirror.h" 7 #include "lib/invocation_mirror.h"
8 #include "vm/bigint_operations.h" 8 #include "vm/bigint_operations.h"
9 #include "vm/class_finalizer.h" 9 #include "vm/class_finalizer.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 LocalScope* scope; 197 LocalScope* scope;
198 SequenceNode* statements; 198 SequenceNode* statements;
199 }; 199 };
200 200
201 201
202 // Class which describes an inlined finally block which is used to generate 202 // Class which describes an inlined finally block which is used to generate
203 // inlined code for the finally blocks when there is an exit from a try 203 // inlined code for the finally blocks when there is an exit from a try
204 // block using 'return', 'break' or 'continue'. 204 // block using 'return', 'break' or 'continue'.
205 class Parser::TryBlocks : public ZoneAllocated { 205 class Parser::TryBlocks : public ZoneAllocated {
206 public: 206 public:
207 TryBlocks(Block* try_block, TryBlocks* outer_try_block) 207 TryBlocks(Block* try_block, TryBlocks* outer_try_block, intptr_t try_index)
208 : try_block_(try_block), 208 : try_block_(try_block),
209 inlined_finally_nodes_(), 209 inlined_finally_nodes_(),
210 outer_try_block_(outer_try_block) { } 210 outer_try_block_(outer_try_block),
211 try_index_(try_index) { }
211 212
212 TryBlocks* outer_try_block() const { return outer_try_block_; } 213 TryBlocks* outer_try_block() const { return outer_try_block_; }
213 Block* try_block() const { return try_block_; } 214 Block* try_block() const { return try_block_; }
215 intptr_t try_index() const { return try_index_; }
214 216
215 void AddNodeForFinallyInlining(AstNode* node); 217 void AddNodeForFinallyInlining(AstNode* node);
216 AstNode* GetNodeToInlineFinally(int index) { 218 AstNode* GetNodeToInlineFinally(int index) {
217 if (0 <= index && index < inlined_finally_nodes_.length()) { 219 if (0 <= index && index < inlined_finally_nodes_.length()) {
218 return inlined_finally_nodes_[index]; 220 return inlined_finally_nodes_[index];
219 } 221 }
220 return NULL; 222 return NULL;
221 } 223 }
222 224
223 private: 225 private:
224 Block* try_block_; 226 Block* try_block_;
225 GrowableArray<AstNode*> inlined_finally_nodes_; 227 GrowableArray<AstNode*> inlined_finally_nodes_;
226 TryBlocks* outer_try_block_; 228 TryBlocks* outer_try_block_;
229 const intptr_t try_index_;
227 230
228 DISALLOW_COPY_AND_ASSIGN(TryBlocks); 231 DISALLOW_COPY_AND_ASSIGN(TryBlocks);
229 }; 232 };
230 233
231 234
232 void Parser::TryBlocks::AddNodeForFinallyInlining(AstNode* node) { 235 void Parser::TryBlocks::AddNodeForFinallyInlining(AstNode* node) {
233 inlined_finally_nodes_.Add(node); 236 inlined_finally_nodes_.Add(node);
234 } 237 }
235 238
236 239
237 // For parsing a compilation unit. 240 // For parsing a compilation unit.
238 Parser::Parser(const Script& script, const Library& library, intptr_t token_pos) 241 Parser::Parser(const Script& script, const Library& library, intptr_t token_pos)
239 : isolate_(Isolate::Current()), 242 : isolate_(Isolate::Current()),
240 script_(Script::Handle(isolate_, script.raw())), 243 script_(Script::Handle(isolate_, script.raw())),
241 tokens_iterator_(TokenStream::Handle(isolate_, script.tokens()), 244 tokens_iterator_(TokenStream::Handle(isolate_, script.tokens()),
242 token_pos), 245 token_pos),
243 token_kind_(Token::kILLEGAL), 246 token_kind_(Token::kILLEGAL),
244 current_block_(NULL), 247 current_block_(NULL),
245 is_top_level_(false), 248 is_top_level_(false),
246 current_member_(NULL), 249 current_member_(NULL),
247 allow_function_literals_(true), 250 allow_function_literals_(true),
248 parsed_function_(NULL), 251 parsed_function_(NULL),
249 innermost_function_(Function::Handle(isolate_)), 252 innermost_function_(Function::Handle(isolate_)),
250 literal_token_(LiteralToken::Handle(isolate_)), 253 literal_token_(LiteralToken::Handle(isolate_)),
251 current_class_(Class::Handle(isolate_)), 254 current_class_(Class::Handle(isolate_)),
252 library_(Library::Handle(isolate_, library.raw())), 255 library_(Library::Handle(isolate_, library.raw())),
253 try_blocks_list_(NULL) { 256 try_blocks_list_(NULL),
257 last_used_try_index_(CatchClauseNode::kInvalidTryIndex) {
254 ASSERT(tokens_iterator_.IsValid()); 258 ASSERT(tokens_iterator_.IsValid());
255 ASSERT(!library.IsNull()); 259 ASSERT(!library.IsNull());
256 } 260 }
257 261
258 262
259 // For parsing a function. 263 // For parsing a function.
260 Parser::Parser(const Script& script, 264 Parser::Parser(const Script& script,
261 ParsedFunction* parsed_function, 265 ParsedFunction* parsed_function,
262 intptr_t token_position) 266 intptr_t token_position)
263 : isolate_(Isolate::Current()), 267 : isolate_(Isolate::Current()),
264 script_(Script::Handle(isolate_, script.raw())), 268 script_(Script::Handle(isolate_, script.raw())),
265 tokens_iterator_(TokenStream::Handle(isolate_, script.tokens()), 269 tokens_iterator_(TokenStream::Handle(isolate_, script.tokens()),
266 token_position), 270 token_position),
267 token_kind_(Token::kILLEGAL), 271 token_kind_(Token::kILLEGAL),
268 current_block_(NULL), 272 current_block_(NULL),
269 is_top_level_(false), 273 is_top_level_(false),
270 current_member_(NULL), 274 current_member_(NULL),
271 allow_function_literals_(true), 275 allow_function_literals_(true),
272 parsed_function_(parsed_function), 276 parsed_function_(parsed_function),
273 innermost_function_(Function::Handle(isolate_, 277 innermost_function_(Function::Handle(isolate_,
274 parsed_function->function().raw())), 278 parsed_function->function().raw())),
275 literal_token_(LiteralToken::Handle(isolate_)), 279 literal_token_(LiteralToken::Handle(isolate_)),
276 current_class_(Class::Handle(isolate_, 280 current_class_(Class::Handle(isolate_,
277 parsed_function->function().Owner())), 281 parsed_function->function().Owner())),
278 library_(Library::Handle(Class::Handle( 282 library_(Library::Handle(Class::Handle(
279 isolate_, 283 isolate_,
280 parsed_function->function().origin()).library())), 284 parsed_function->function().origin()).library())),
281 try_blocks_list_(NULL) { 285 try_blocks_list_(NULL),
286 last_used_try_index_(CatchClauseNode::kInvalidTryIndex) {
282 ASSERT(tokens_iterator_.IsValid()); 287 ASSERT(tokens_iterator_.IsValid());
283 ASSERT(!current_function().IsNull()); 288 ASSERT(!current_function().IsNull());
284 if (FLAG_enable_type_checks) { 289 if (FLAG_enable_type_checks) {
285 EnsureExpressionTemp(); 290 EnsureExpressionTemp();
286 } 291 }
287 } 292 }
288 293
289 294
290 void Parser::SetScript(const Script & script, intptr_t token_pos) { 295 void Parser::SetScript(const Script & script, intptr_t token_pos) {
291 script_ = script.raw(); 296 script_ = script.raw();
(...skipping 5999 matching lines...) Expand 10 before | Expand all | Expand 10 after
6291 OpenBlock(); 6296 OpenBlock();
6292 ExpectToken(Token::kLBRACE); 6297 ExpectToken(Token::kLBRACE);
6293 ParseStatementSequence(); 6298 ParseStatementSequence();
6294 ExpectToken(Token::kRBRACE); 6299 ExpectToken(Token::kRBRACE);
6295 SequenceNode* finally_block = CloseBlock(); 6300 SequenceNode* finally_block = CloseBlock();
6296 return finally_block; 6301 return finally_block;
6297 } 6302 }
6298 6303
6299 6304
6300 void Parser::PushTryBlock(Block* try_block) { 6305 void Parser::PushTryBlock(Block* try_block) {
6301 TryBlocks* block = new TryBlocks(try_block, try_blocks_list_); 6306 intptr_t try_index = AllocateTryIndex();
6307 TryBlocks* block = new TryBlocks(try_block, try_blocks_list_, try_index);
6302 try_blocks_list_ = block; 6308 try_blocks_list_ = block;
6303 } 6309 }
6304 6310
6305 6311
6306 Parser::TryBlocks* Parser::PopTryBlock() { 6312 Parser::TryBlocks* Parser::PopTryBlock() {
6307 TryBlocks* innermost_try_block = try_blocks_list_; 6313 TryBlocks* innermost_try_block = try_blocks_list_;
6308 try_blocks_list_ = try_blocks_list_->outer_try_block(); 6314 try_blocks_list_ = try_blocks_list_->outer_try_block();
6309 return innermost_try_block; 6315 return innermost_try_block;
6310 } 6316 }
6311 6317
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
6543 handler_types.SetLength(0); 6549 handler_types.SetLength(0);
6544 handler_types.Add(*exception_param.type); 6550 handler_types.Add(*exception_param.type);
6545 } 6551 }
6546 SequenceNode* catch_clause = CloseBlock(); 6552 SequenceNode* catch_clause = CloseBlock();
6547 6553
6548 // Add this individual catch handler to the catch handlers list. 6554 // Add this individual catch handler to the catch handlers list.
6549 current_block_->statements->Add(catch_clause); 6555 current_block_->statements->Add(catch_clause);
6550 } 6556 }
6551 catch_handler_list = CloseBlock(); 6557 catch_handler_list = CloseBlock();
6552 TryBlocks* inner_try_block = PopTryBlock(); 6558 TryBlocks* inner_try_block = PopTryBlock();
6559 intptr_t try_index = inner_try_block->try_index();
6560 TryBlocks* outer_try_block = try_blocks_list_;
6561 intptr_t outer_try_index = (outer_try_block != NULL)
6562 ? outer_try_block->try_index()
6563 : CatchClauseNode::kInvalidTryIndex;
6553 6564
6554 // Finally parse the 'finally' block. 6565 // Finally parse the 'finally' block.
6555 SequenceNode* finally_block = NULL; 6566 SequenceNode* finally_block = NULL;
6556 if (CurrentToken() == Token::kFINALLY) { 6567 if (CurrentToken() == Token::kFINALLY) {
6557 current_function().set_has_finally(true); 6568 current_function().set_has_finally(true);
6558 ConsumeToken(); // Consume the 'finally'. 6569 ConsumeToken(); // Consume the 'finally'.
6559 const intptr_t finally_pos = TokenPos(); 6570 const intptr_t finally_pos = TokenPos();
6560 // Add the finally block to the exit points recorded so far. 6571 // Add the finally block to the exit points recorded so far.
6561 intptr_t node_index = 0; 6572 intptr_t node_index = 0;
6562 AstNode* node_to_inline = 6573 AstNode* node_to_inline =
6563 inner_try_block->GetNodeToInlineFinally(node_index); 6574 inner_try_block->GetNodeToInlineFinally(node_index);
6564 while (node_to_inline != NULL) { 6575 while (node_to_inline != NULL) {
6565 finally_block = ParseFinallyBlock(); 6576 finally_block = ParseFinallyBlock();
6566 InlinedFinallyNode* node = new InlinedFinallyNode(finally_pos, 6577 InlinedFinallyNode* node = new InlinedFinallyNode(finally_pos,
6567 finally_block, 6578 finally_block,
6568 context_var); 6579 context_var,
6580 outer_try_index);
6569 AddFinallyBlockToNode(node_to_inline, node); 6581 AddFinallyBlockToNode(node_to_inline, node);
6570 node_index += 1; 6582 node_index += 1;
6571 node_to_inline = inner_try_block->GetNodeToInlineFinally(node_index); 6583 node_to_inline = inner_try_block->GetNodeToInlineFinally(node_index);
6572 tokens_iterator_.SetCurrentPosition(finally_pos); 6584 tokens_iterator_.SetCurrentPosition(finally_pos);
6573 } 6585 }
6574 finally_block = ParseFinallyBlock(); 6586 finally_block = ParseFinallyBlock();
6575 } else { 6587 } else {
6576 if (!catch_seen) { 6588 if (!catch_seen) {
6577 ErrorMsg("catch or finally clause expected"); 6589 ErrorMsg("catch or finally clause expected");
6578 } 6590 }
6579 } 6591 }
6580 6592
6581 if (!generic_catch_seen) { 6593 if (!generic_catch_seen) {
6582 // No generic catch handler exists so rethrow the exception so that 6594 // No generic catch handler exists so rethrow the exception so that
6583 // the next catch handler can deal with it. 6595 // the next catch handler can deal with it.
6584 catch_handler_list->Add( 6596 catch_handler_list->Add(
6585 new ThrowNode(handler_pos, 6597 new ThrowNode(handler_pos,
6586 new LoadLocalNode(handler_pos, catch_excp_var), 6598 new LoadLocalNode(handler_pos, catch_excp_var),
6587 new LoadLocalNode(handler_pos, catch_trace_var))); 6599 new LoadLocalNode(handler_pos, catch_trace_var)));
6588 } 6600 }
6589 CatchClauseNode* catch_block = 6601 CatchClauseNode* catch_block =
6590 new CatchClauseNode(handler_pos, 6602 new CatchClauseNode(handler_pos,
6591 catch_handler_list, 6603 catch_handler_list,
6592 Array::ZoneHandle(Array::MakeArray(handler_types)), 6604 Array::ZoneHandle(Array::MakeArray(handler_types)),
6593 context_var, 6605 context_var,
6594 catch_excp_var, 6606 catch_excp_var,
6595 catch_trace_var); 6607 catch_trace_var,
6608 (finally_block != NULL)
6609 ? AllocateTryIndex()
6610 : CatchClauseNode::kInvalidTryIndex);
6596 6611
6597 // Now create the try/catch ast node and return it. If there is a label 6612 // Now create the try/catch ast node and return it. If there is a label
6598 // on the try/catch, close the block that's embedding the try statement 6613 // on the try/catch, close the block that's embedding the try statement
6599 // and attach the label to it. 6614 // and attach the label to it.
6600 AstNode* try_catch_node = 6615 AstNode* try_catch_node =
6601 new TryCatchNode(try_pos, try_block, end_catch_label, 6616 new TryCatchNode(try_pos, try_block, end_catch_label,
6602 context_var, catch_block, finally_block); 6617 context_var, catch_block, finally_block, try_index);
6603 6618
6604 if (try_label != NULL) { 6619 if (try_label != NULL) {
6605 current_block_->statements->Add(try_catch_node); 6620 current_block_->statements->Add(try_catch_node);
6606 SequenceNode* sequence = CloseBlock(); 6621 SequenceNode* sequence = CloseBlock();
6607 sequence->set_label(try_label); 6622 sequence->set_label(try_label);
6608 try_catch_node = sequence; 6623 try_catch_node = sequence;
6609 } 6624 }
6610 return try_catch_node; 6625 return try_catch_node;
6611 } 6626 }
6612 6627
(...skipping 3645 matching lines...) Expand 10 before | Expand all | Expand 10 after
10258 void Parser::SkipQualIdent() { 10273 void Parser::SkipQualIdent() {
10259 ASSERT(IsIdentifier()); 10274 ASSERT(IsIdentifier());
10260 ConsumeToken(); 10275 ConsumeToken();
10261 if (CurrentToken() == Token::kPERIOD) { 10276 if (CurrentToken() == Token::kPERIOD) {
10262 ConsumeToken(); // Consume the kPERIOD token. 10277 ConsumeToken(); // Consume the kPERIOD token.
10263 ExpectIdentifier("identifier expected after '.'"); 10278 ExpectIdentifier("identifier expected after '.'");
10264 } 10279 }
10265 } 10280 }
10266 10281
10267 } // namespace dart 10282 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/language.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698