| 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 // Shift remaining entries left and delete last entry. |
| 401 for (int j = i + 1; j < inlined_finally_nodes_.length(); j++) { |
| 402 inlined_finally_nodes_[j - 1] = inlined_finally_nodes_[j]; |
| 403 } |
| 404 inlined_finally_nodes_.RemoveLast(); |
| 405 continue; |
| 406 } |
| 407 } |
| 408 i++; |
| 409 } |
| 410 } |
| 411 |
| 412 |
| 393 // For parsing a compilation unit. | 413 // For parsing a compilation unit. |
| 394 Parser::Parser(const Script& script, | 414 Parser::Parser(const Script& script, |
| 395 const Library& library, | 415 const Library& library, |
| 396 TokenPosition token_pos) | 416 TokenPosition token_pos) |
| 397 : thread_(Thread::Current()), | 417 : thread_(Thread::Current()), |
| 398 isolate_(thread()->isolate()), | 418 isolate_(thread()->isolate()), |
| 399 script_(Script::Handle(zone(), script.raw())), | 419 script_(Script::Handle(zone(), script.raw())), |
| 400 tokens_iterator_(zone(), | 420 tokens_iterator_(zone(), |
| 401 TokenStream::Handle(zone(), script.tokens()), | 421 TokenStream::Handle(zone(), script.tokens()), |
| 402 token_pos), | 422 token_pos), |
| (...skipping 8031 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8434 case_label = current_block_->scope->LocalLookupLabel(*label_name); | 8454 case_label = current_block_->scope->LocalLookupLabel(*label_name); |
| 8435 if (case_label == NULL) { | 8455 if (case_label == NULL) { |
| 8436 // Label does not exist yet. Add it to scope of switch statement. | 8456 // Label does not exist yet. Add it to scope of switch statement. |
| 8437 case_label = new(Z) SourceLabel( | 8457 case_label = new(Z) SourceLabel( |
| 8438 label_pos, *label_name, SourceLabel::kCase); | 8458 label_pos, *label_name, SourceLabel::kCase); |
| 8439 current_block_->scope->AddLabel(case_label); | 8459 current_block_->scope->AddLabel(case_label); |
| 8440 } else if (case_label->kind() == SourceLabel::kForward) { | 8460 } else if (case_label->kind() == SourceLabel::kForward) { |
| 8441 // We have seen a 'continue' with this label name. Resolve | 8461 // We have seen a 'continue' with this label name. Resolve |
| 8442 // the forward reference. | 8462 // the forward reference. |
| 8443 case_label->ResolveForwardReference(); | 8463 case_label->ResolveForwardReference(); |
| 8464 RemoveNodesForFinallyInlining(case_label); |
| 8444 } else { | 8465 } else { |
| 8445 ReportError(label_pos, "label '%s' already exists in scope", | 8466 ReportError(label_pos, "label '%s' already exists in scope", |
| 8446 label_name->ToCString()); | 8467 label_name->ToCString()); |
| 8447 } | 8468 } |
| 8448 ASSERT(case_label->kind() == SourceLabel::kCase); | 8469 ASSERT(case_label->kind() == SourceLabel::kCase); |
| 8449 } | 8470 } |
| 8450 if (CurrentToken() == Token::kCASE || | 8471 if (CurrentToken() == Token::kCASE || |
| 8451 CurrentToken() == Token::kDEFAULT) { | 8472 CurrentToken() == Token::kDEFAULT) { |
| 8452 if (default_seen) { | 8473 if (default_seen) { |
| 8453 ReportError("no case clauses allowed after default clause"); | 8474 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. | 9363 // For continue and break node check if the target label is in scope. |
| 9343 if (node->IsJumpNode()) { | 9364 if (node->IsJumpNode()) { |
| 9344 SourceLabel* label = node->AsJumpNode()->label(); | 9365 SourceLabel* label = node->AsJumpNode()->label(); |
| 9345 ASSERT(label != NULL); | 9366 ASSERT(label != NULL); |
| 9346 LocalScope* try_scope = iterator->try_block()->scope; | 9367 LocalScope* try_scope = iterator->try_block()->scope; |
| 9347 // If the label is defined in a scope which is a child (nested scope) | 9368 // 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 | 9369 // 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 | 9370 // 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 | 9371 // to inline the finally code of this try block and then move on to the |
| 9351 // next outer try block. | 9372 // next outer try block. |
| 9352 if (label->owner()->IsNestedWithin(try_scope)) { | 9373 // For unresolved forward jumps to switch cases, we don't yet know |
| 9374 // to which scope the label will be resolved. Tentatively add the |
| 9375 // jump to all nested try statements and remove the outermost ones |
| 9376 // when we know the exact jump target. (See |
| 9377 // RemoveNodesForFinallyInlining below.) |
| 9378 if (!label->IsUnresolved() && label->owner()->IsNestedWithin(try_scope)) { |
| 9353 break; | 9379 break; |
| 9354 } | 9380 } |
| 9355 } | 9381 } |
| 9356 iterator->AddNodeForFinallyInlining(node); | 9382 iterator->AddNodeForFinallyInlining(node); |
| 9357 iterator = iterator->outer_try(); | 9383 iterator = iterator->outer_try(); |
| 9358 } | 9384 } |
| 9359 } | 9385 } |
| 9360 | 9386 |
| 9361 | 9387 |
| 9388 void Parser::RemoveNodesForFinallyInlining(SourceLabel* label) { |
| 9389 TryStack* iterator = try_stack_; |
| 9390 const intptr_t func_level = FunctionLevel(); |
| 9391 while ((iterator != NULL) && |
| 9392 (iterator->try_block()->scope->function_level() == func_level)) { |
| 9393 iterator->RemoveJumpToLabel(label); |
| 9394 iterator = iterator->outer_try(); |
| 9395 } |
| 9396 } |
| 9397 |
| 9398 |
| 9362 // Add the inlined finally clause to the specified node. | 9399 // Add the inlined finally clause to the specified node. |
| 9363 void Parser::AddFinallyClauseToNode(bool is_async, | 9400 void Parser::AddFinallyClauseToNode(bool is_async, |
| 9364 AstNode* node, | 9401 AstNode* node, |
| 9365 InlinedFinallyNode* finally_clause) { | 9402 InlinedFinallyNode* finally_clause) { |
| 9366 ReturnNode* return_node = node->AsReturnNode(); | 9403 ReturnNode* return_node = node->AsReturnNode(); |
| 9367 if (return_node != NULL) { | 9404 if (return_node != NULL) { |
| 9368 if (FunctionLevel() == 0) { | 9405 if (FunctionLevel() == 0) { |
| 9369 parsed_function()->EnsureFinallyReturnTemp(is_async); | 9406 parsed_function()->EnsureFinallyReturnTemp(is_async); |
| 9370 } | 9407 } |
| 9371 return_node->AddInlinedFinallyNode(finally_clause); | 9408 return_node->AddInlinedFinallyNode(finally_clause); |
| (...skipping 5202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14574 const ArgumentListNode& function_args, | 14611 const ArgumentListNode& function_args, |
| 14575 const LocalVariable* temp_for_last_arg, | 14612 const LocalVariable* temp_for_last_arg, |
| 14576 bool is_super_invocation) { | 14613 bool is_super_invocation) { |
| 14577 UNREACHABLE(); | 14614 UNREACHABLE(); |
| 14578 return NULL; | 14615 return NULL; |
| 14579 } | 14616 } |
| 14580 | 14617 |
| 14581 } // namespace dart | 14618 } // namespace dart |
| 14582 | 14619 |
| 14583 #endif // DART_PRECOMPILED_RUNTIME | 14620 #endif // DART_PRECOMPILED_RUNTIME |
| OLD | NEW |