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 #include "vm/flags.h" | 6 #include "vm/flags.h" |
7 | 7 |
8 #ifndef DART_PRECOMPILED_RUNTIME | 8 #ifndef DART_PRECOMPILED_RUNTIME |
9 | 9 |
10 #include "lib/invocation_mirror.h" | 10 #include "lib/invocation_mirror.h" |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
358 TryStack* outer_try() const { return outer_try_; } | 358 TryStack* outer_try() const { return outer_try_; } |
359 Block* try_block() const { return try_block_; } | 359 Block* try_block() const { return try_block_; } |
360 intptr_t try_index() const { return try_index_; } | 360 intptr_t try_index() const { return try_index_; } |
361 bool inside_catch() const { return inside_catch_; } | 361 bool inside_catch() const { return inside_catch_; } |
362 void enter_catch() { inside_catch_ = true; } | 362 void enter_catch() { inside_catch_ = true; } |
363 bool inside_finally() const { return inside_finally_; } | 363 bool inside_finally() const { return inside_finally_; } |
364 void enter_finally() { inside_finally_ = true; } | 364 void enter_finally() { inside_finally_ = true; } |
365 void exit_finally() { inside_finally_ = false; } | 365 void exit_finally() { inside_finally_ = false; } |
366 | 366 |
367 void AddNodeForFinallyInlining(AstNode* node); | 367 void AddNodeForFinallyInlining(AstNode* node); |
368 void RemoveJumpToLabel(SourceLabel *label); | |
368 AstNode* GetNodeToInlineFinally(int index) { | 369 AstNode* GetNodeToInlineFinally(int index) { |
369 if (0 <= index && index < inlined_finally_nodes_.length()) { | 370 if (0 <= index && index < inlined_finally_nodes_.length()) { |
370 return inlined_finally_nodes_[index]; | 371 return inlined_finally_nodes_[index]; |
371 } | 372 } |
372 return NULL; | 373 return NULL; |
373 } | 374 } |
374 | 375 |
375 private: | 376 private: |
376 Block* try_block_; | 377 Block* try_block_; |
377 GrowableArray<AstNode*> inlined_finally_nodes_; | 378 GrowableArray<AstNode*> inlined_finally_nodes_; |
378 TryStack* outer_try_; | 379 TryStack* outer_try_; |
379 const intptr_t try_index_; | 380 const intptr_t try_index_; |
380 bool inside_catch_; // True when parsing a catch clause of this try. | 381 bool inside_catch_; // True when parsing a catch clause of this try. |
381 bool inside_finally_; // True when parsing a finally clause of an inner try | 382 bool inside_finally_; // True when parsing a finally clause of an inner try |
382 // of this try. | 383 // of this try. |
383 | 384 |
384 DISALLOW_COPY_AND_ASSIGN(TryStack); | 385 DISALLOW_COPY_AND_ASSIGN(TryStack); |
385 }; | 386 }; |
386 | 387 |
387 | 388 |
388 void Parser::TryStack::AddNodeForFinallyInlining(AstNode* node) { | 389 void Parser::TryStack::AddNodeForFinallyInlining(AstNode* node) { |
389 inlined_finally_nodes_.Add(node); | 390 inlined_finally_nodes_.Add(node); |
390 } | 391 } |
391 | 392 |
392 | 393 |
394 void Parser::TryStack::RemoveJumpToLabel(SourceLabel *label) { | |
395 int i = 0; | |
396 while (i < inlined_finally_nodes_.length()) { | |
397 if (inlined_finally_nodes_[i]->IsJumpNode()) { | |
398 JumpNode* jump = inlined_finally_nodes_[i]->AsJumpNode(); | |
399 if (jump->label() == label) { | |
400 for (int j = i + 1; j < inlined_finally_nodes_.length(); j++) { | |
401 inlined_finally_nodes_[i] = inlined_finally_nodes_[j]; | |
regis
2016/06/02 01:13:25
Did you mean j-1 instead of i, which is not increm
hausner
2016/06/02 15:38:51
Ahem, yes. Good catch, thank you!
| |
402 } | |
403 inlined_finally_nodes_.RemoveLast(); | |
404 continue; | |
405 } | |
406 } | |
407 i++; | |
408 } | |
409 } | |
410 | |
411 | |
393 // For parsing a compilation unit. | 412 // For parsing a compilation unit. |
394 Parser::Parser(const Script& script, | 413 Parser::Parser(const Script& script, |
395 const Library& library, | 414 const Library& library, |
396 TokenPosition token_pos) | 415 TokenPosition token_pos) |
397 : thread_(Thread::Current()), | 416 : thread_(Thread::Current()), |
398 isolate_(thread()->isolate()), | 417 isolate_(thread()->isolate()), |
399 script_(Script::Handle(zone(), script.raw())), | 418 script_(Script::Handle(zone(), script.raw())), |
400 tokens_iterator_(zone(), | 419 tokens_iterator_(zone(), |
401 TokenStream::Handle(zone(), script.tokens()), | 420 TokenStream::Handle(zone(), script.tokens()), |
402 token_pos), | 421 token_pos), |
(...skipping 8031 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8434 case_label = current_block_->scope->LocalLookupLabel(*label_name); | 8453 case_label = current_block_->scope->LocalLookupLabel(*label_name); |
8435 if (case_label == NULL) { | 8454 if (case_label == NULL) { |
8436 // Label does not exist yet. Add it to scope of switch statement. | 8455 // Label does not exist yet. Add it to scope of switch statement. |
8437 case_label = new(Z) SourceLabel( | 8456 case_label = new(Z) SourceLabel( |
8438 label_pos, *label_name, SourceLabel::kCase); | 8457 label_pos, *label_name, SourceLabel::kCase); |
8439 current_block_->scope->AddLabel(case_label); | 8458 current_block_->scope->AddLabel(case_label); |
8440 } else if (case_label->kind() == SourceLabel::kForward) { | 8459 } else if (case_label->kind() == SourceLabel::kForward) { |
8441 // We have seen a 'continue' with this label name. Resolve | 8460 // We have seen a 'continue' with this label name. Resolve |
8442 // the forward reference. | 8461 // the forward reference. |
8443 case_label->ResolveForwardReference(); | 8462 case_label->ResolveForwardReference(); |
8463 RemoveNodesForFinallyInlining(case_label); | |
8444 } else { | 8464 } else { |
8445 ReportError(label_pos, "label '%s' already exists in scope", | 8465 ReportError(label_pos, "label '%s' already exists in scope", |
8446 label_name->ToCString()); | 8466 label_name->ToCString()); |
8447 } | 8467 } |
8448 ASSERT(case_label->kind() == SourceLabel::kCase); | 8468 ASSERT(case_label->kind() == SourceLabel::kCase); |
8449 } | 8469 } |
8450 if (CurrentToken() == Token::kCASE || | 8470 if (CurrentToken() == Token::kCASE || |
8451 CurrentToken() == Token::kDEFAULT) { | 8471 CurrentToken() == Token::kDEFAULT) { |
8452 if (default_seen) { | 8472 if (default_seen) { |
8453 ReportError("no case clauses allowed after default clause"); | 8473 ReportError("no case clauses allowed after default clause"); |
(...skipping 888 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9342 // For continue and break node check if the target label is in scope. | 9362 // For continue and break node check if the target label is in scope. |
9343 if (node->IsJumpNode()) { | 9363 if (node->IsJumpNode()) { |
9344 SourceLabel* label = node->AsJumpNode()->label(); | 9364 SourceLabel* label = node->AsJumpNode()->label(); |
9345 ASSERT(label != NULL); | 9365 ASSERT(label != NULL); |
9346 LocalScope* try_scope = iterator->try_block()->scope; | 9366 LocalScope* try_scope = iterator->try_block()->scope; |
9347 // If the label is defined in a scope which is a child (nested scope) | 9367 // If the label is defined in a scope which is a child (nested scope) |
9348 // of the try scope then we are not breaking out of this try block | 9368 // of the try scope then we are not breaking out of this try block |
9349 // so we do not need to inline the finally code. Otherwise we need | 9369 // so we do not need to inline the finally code. Otherwise we need |
9350 // to inline the finally code of this try block and then move on to the | 9370 // to inline the finally code of this try block and then move on to the |
9351 // next outer try block. | 9371 // next outer try block. |
9352 if (label->owner()->IsNestedWithin(try_scope)) { | 9372 // For unresolved forward jumps to switch cases, we don't yet know |
9373 // to which scope the label will be resolved. Tentatively add the | |
9374 // jump to all nested try statements and remove the outermost ones | |
9375 // when we know the exact jump target. (See | |
9376 // RemoveNodesForFinallyInlining below.) | |
9377 if (!label->IsUnresolved() && label->owner()->IsNestedWithin(try_scope)) { | |
9353 break; | 9378 break; |
9354 } | 9379 } |
9355 } | 9380 } |
9356 iterator->AddNodeForFinallyInlining(node); | 9381 iterator->AddNodeForFinallyInlining(node); |
9357 iterator = iterator->outer_try(); | 9382 iterator = iterator->outer_try(); |
9358 } | 9383 } |
9359 } | 9384 } |
9360 | 9385 |
9361 | 9386 |
9387 void Parser::RemoveNodesForFinallyInlining(SourceLabel* label) { | |
9388 TryStack* iterator = try_stack_; | |
9389 const intptr_t func_level = FunctionLevel(); | |
9390 while ((iterator != NULL) && | |
9391 (iterator->try_block()->scope->function_level() == func_level)) { | |
9392 iterator->RemoveJumpToLabel(label); | |
9393 iterator = iterator->outer_try(); | |
9394 } | |
9395 } | |
9396 | |
9397 | |
9362 // Add the inlined finally clause to the specified node. | 9398 // Add the inlined finally clause to the specified node. |
9363 void Parser::AddFinallyClauseToNode(bool is_async, | 9399 void Parser::AddFinallyClauseToNode(bool is_async, |
9364 AstNode* node, | 9400 AstNode* node, |
9365 InlinedFinallyNode* finally_clause) { | 9401 InlinedFinallyNode* finally_clause) { |
9366 ReturnNode* return_node = node->AsReturnNode(); | 9402 ReturnNode* return_node = node->AsReturnNode(); |
9367 if (return_node != NULL) { | 9403 if (return_node != NULL) { |
9368 if (FunctionLevel() == 0) { | 9404 if (FunctionLevel() == 0) { |
9369 parsed_function()->EnsureFinallyReturnTemp(is_async); | 9405 parsed_function()->EnsureFinallyReturnTemp(is_async); |
9370 } | 9406 } |
9371 return_node->AddInlinedFinallyNode(finally_clause); | 9407 return_node->AddInlinedFinallyNode(finally_clause); |
(...skipping 5202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
14574 const ArgumentListNode& function_args, | 14610 const ArgumentListNode& function_args, |
14575 const LocalVariable* temp_for_last_arg, | 14611 const LocalVariable* temp_for_last_arg, |
14576 bool is_super_invocation) { | 14612 bool is_super_invocation) { |
14577 UNREACHABLE(); | 14613 UNREACHABLE(); |
14578 return NULL; | 14614 return NULL; |
14579 } | 14615 } |
14580 | 14616 |
14581 } // namespace dart | 14617 } // namespace dart |
14582 | 14618 |
14583 #endif // DART_PRECOMPILED_RUNTIME | 14619 #endif // DART_PRECOMPILED_RUNTIME |
OLD | NEW |