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 |