OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/parsing/parser.h" | 5 #include "src/parsing/parser.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/ast/ast.h" | 8 #include "src/ast/ast.h" |
9 #include "src/ast/ast-expression-rewriter.h" | 9 #include "src/ast/ast-expression-rewriter.h" |
10 #include "src/ast/ast-expression-visitor.h" | 10 #include "src/ast/ast-expression-visitor.h" |
(...skipping 2989 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3000 } | 3000 } |
3001 | 3001 |
3002 // Simplify the AST nodes by converting: | 3002 // Simplify the AST nodes by converting: |
3003 // 'try B0 catch B1 finally B2' | 3003 // 'try B0 catch B1 finally B2' |
3004 // to: | 3004 // to: |
3005 // 'try { try B0 catch B1 } finally B2' | 3005 // 'try { try B0 catch B1 } finally B2' |
3006 | 3006 |
3007 if (catch_block != NULL && finally_block != NULL) { | 3007 if (catch_block != NULL && finally_block != NULL) { |
3008 // If we have both, create an inner try/catch. | 3008 // If we have both, create an inner try/catch. |
3009 DCHECK(catch_scope != NULL && catch_variable != NULL); | 3009 DCHECK(catch_scope != NULL && catch_variable != NULL); |
3010 TryCatchStatement* statement = | 3010 TryCatchStatement* statement = factory()->NewTryCatchStatement( |
3011 factory()->NewTryCatchStatement(try_block, catch_scope, catch_variable, | 3011 try_block, catch_scope, catch_variable, catch_block, true, |
3012 catch_block, RelocInfo::kNoPosition); | 3012 RelocInfo::kNoPosition); |
3013 try_block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); | 3013 try_block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); |
3014 try_block->statements()->Add(statement, zone()); | 3014 try_block->statements()->Add(statement, zone()); |
3015 catch_block = NULL; // Clear to indicate it's been handled. | 3015 catch_block = NULL; // Clear to indicate it's been handled. |
3016 } | 3016 } |
3017 | 3017 |
3018 TryStatement* result = NULL; | 3018 TryStatement* result = NULL; |
3019 if (catch_block != NULL) { | 3019 if (catch_block != NULL) { |
3020 // For a try-catch construct append return expressions from the catch block | 3020 // For a try-catch construct append return expressions from the catch block |
3021 // to the list of return expressions. | 3021 // to the list of return expressions. |
3022 function_state_->expressions_in_tail_position().AddAll( | 3022 function_state_->expressions_in_tail_position().AddAll( |
3023 expressions_in_tail_position_in_catch_block); | 3023 expressions_in_tail_position_in_catch_block); |
3024 | 3024 |
3025 DCHECK(finally_block == NULL); | 3025 DCHECK(finally_block == NULL); |
3026 DCHECK(catch_scope != NULL && catch_variable != NULL); | 3026 DCHECK(catch_scope != NULL && catch_variable != NULL); |
3027 result = factory()->NewTryCatchStatement(try_block, catch_scope, | 3027 result = factory()->NewTryCatchStatement( |
3028 catch_variable, catch_block, pos); | 3028 try_block, catch_scope, catch_variable, catch_block, true, pos); |
3029 } else { | 3029 } else { |
3030 DCHECK(finally_block != NULL); | 3030 DCHECK(finally_block != NULL); |
3031 result = factory()->NewTryFinallyStatement(try_block, finally_block, pos); | 3031 result = factory()->NewTryFinallyStatement(try_block, finally_block, pos); |
3032 } | 3032 } |
3033 | 3033 |
3034 return result; | 3034 return result; |
3035 } | 3035 } |
3036 | 3036 |
3037 | 3037 |
3038 DoWhileStatement* Parser::ParseDoWhileStatement( | 3038 DoWhileStatement* Parser::ParseDoWhileStatement( |
(...skipping 3012 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6051 Block* catch_block = factory->NewBlock(nullptr, 1, false, nopos); | 6051 Block* catch_block = factory->NewBlock(nullptr, 1, false, nopos); |
6052 catch_block->statements()->Add(set_mode_throw, zone); | 6052 catch_block->statements()->Add(set_mode_throw, zone); |
6053 | 6053 |
6054 Scope* catch_scope = NewScope(scope, CATCH_SCOPE); | 6054 Scope* catch_scope = NewScope(scope, CATCH_SCOPE); |
6055 const AstRawString* name = avfactory->dot_catch_string(); | 6055 const AstRawString* name = avfactory->dot_catch_string(); |
6056 Variable* catch_variable = | 6056 Variable* catch_variable = |
6057 catch_scope->DeclareLocal(name, VAR, kCreatedInitialized, | 6057 catch_scope->DeclareLocal(name, VAR, kCreatedInitialized, |
6058 Variable::NORMAL); | 6058 Variable::NORMAL); |
6059 | 6059 |
6060 try_catch = factory->NewTryCatchStatement( | 6060 try_catch = factory->NewTryCatchStatement( |
6061 try_block, catch_scope, catch_variable, catch_block, nopos); | 6061 try_block, catch_scope, catch_variable, catch_block, true, nopos); |
6062 } | 6062 } |
6063 | 6063 |
6064 | 6064 |
6065 // try { ... } finally { ... } | 6065 // try { ... } finally { ... } |
6066 Statement* try_finally; | 6066 Statement* try_finally; |
6067 { | 6067 { |
6068 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos); | 6068 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos); |
6069 try_block->statements()->Add(try_catch, zone); | 6069 try_block->statements()->Add(try_catch, zone); |
6070 | 6070 |
6071 Block* finally = factory->NewBlock(nullptr, 2, false, nopos); | 6071 Block* finally = factory->NewBlock(nullptr, 2, false, nopos); |
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6457 // | 6457 // |
6458 // This function adds two statements to [target], corresponding to the | 6458 // This function adds two statements to [target], corresponding to the |
6459 // following code: | 6459 // following code: |
6460 // | 6460 // |
6461 // completion = kNormalCompletion; | 6461 // completion = kNormalCompletion; |
6462 // try { | 6462 // try { |
6463 // try { | 6463 // try { |
6464 // iterator_use | 6464 // iterator_use |
6465 // } catch(e) { | 6465 // } catch(e) { |
6466 // if (completion === kAbruptCompletion) completion = kThrowCompletion; | 6466 // if (completion === kAbruptCompletion) completion = kThrowCompletion; |
6467 // throw e; | 6467 // %ReThrow(e); |
6468 // } | 6468 // } |
6469 // } finally { | 6469 // } finally { |
6470 // if (condition) { | 6470 // if (condition) { |
6471 // #BuildIteratorCloseForCompletion(iter, completion) | 6471 // #BuildIteratorCloseForCompletion(iter, completion) |
6472 // } | 6472 // } |
6473 // } | 6473 // } |
6474 // | 6474 // |
6475 | 6475 |
6476 const int nopos = RelocInfo::kNoPosition; | 6476 const int nopos = RelocInfo::kNoPosition; |
6477 auto factory = parser_->factory(); | 6477 auto factory = parser_->factory(); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6518 maybe_close = factory->NewBlock(nullptr, 1, true, nopos); | 6518 maybe_close = factory->NewBlock(nullptr, 1, true, nopos); |
6519 maybe_close->statements()->Add( | 6519 maybe_close->statements()->Add( |
6520 factory->NewIfStatement(condition, block, | 6520 factory->NewIfStatement(condition, block, |
6521 factory->NewEmptyStatement(nopos), nopos), | 6521 factory->NewEmptyStatement(nopos), nopos), |
6522 zone); | 6522 zone); |
6523 } | 6523 } |
6524 | 6524 |
6525 // try { #try_block } | 6525 // try { #try_block } |
6526 // catch(e) { | 6526 // catch(e) { |
6527 // #set_completion_throw; | 6527 // #set_completion_throw; |
6528 // throw e; | 6528 // %ReThrow(e); |
6529 // } | 6529 // } |
6530 Statement* try_catch; | 6530 Statement* try_catch; |
6531 { | 6531 { |
6532 Scope* catch_scope = parser_->NewScope(scope, CATCH_SCOPE); | 6532 Scope* catch_scope = parser_->NewScope(scope, CATCH_SCOPE); |
6533 Variable* catch_variable = | 6533 Variable* catch_variable = |
6534 catch_scope->DeclareLocal(avfactory->dot_catch_string(), VAR, | 6534 catch_scope->DeclareLocal(avfactory->dot_catch_string(), VAR, |
6535 kCreatedInitialized, Variable::NORMAL); | 6535 kCreatedInitialized, Variable::NORMAL); |
6536 | 6536 |
6537 Statement* rethrow; | 6537 Statement* rethrow; |
| 6538 // We use %ReThrow rather than the ordinary throw because we want to |
| 6539 // keep the original exception message. This is also why we create the |
| 6540 // TryCatchStatement below with clear_pending_message set to false. |
6538 { | 6541 { |
6539 Expression* proxy = factory->NewVariableProxy(catch_variable); | 6542 auto args = new (zone) ZoneList<Expression*>(1, zone); |
6540 rethrow = factory->NewExpressionStatement(factory->NewThrow(proxy, nopos), | 6543 args->Add(factory->NewVariableProxy(catch_variable), zone); |
6541 nopos); | 6544 rethrow = factory->NewExpressionStatement( |
| 6545 factory->NewCallRuntime(Runtime::kReThrow, args, nopos), nopos); |
6542 } | 6546 } |
6543 | 6547 |
6544 Block* catch_block = factory->NewBlock(nullptr, 2, false, nopos); | 6548 Block* catch_block = factory->NewBlock(nullptr, 2, false, nopos); |
6545 catch_block->statements()->Add(set_completion_throw, zone); | 6549 catch_block->statements()->Add(set_completion_throw, zone); |
6546 catch_block->statements()->Add(rethrow, zone); | 6550 catch_block->statements()->Add(rethrow, zone); |
6547 | 6551 |
6548 try_catch = factory->NewTryCatchStatement( | 6552 try_catch = factory->NewTryCatchStatement( |
6549 iterator_use, catch_scope, catch_variable, catch_block, nopos); | 6553 iterator_use, catch_scope, catch_variable, catch_block, false, nopos); |
6550 } | 6554 } |
6551 | 6555 |
6552 // try { #try_catch } finally { #maybe_close } | 6556 // try { #try_catch } finally { #maybe_close } |
6553 Statement* try_finally; | 6557 Statement* try_finally; |
6554 { | 6558 { |
6555 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos); | 6559 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos); |
6556 try_block->statements()->Add(try_catch, zone); | 6560 try_block->statements()->Add(try_catch, zone); |
6557 | 6561 |
6558 try_finally = | 6562 try_finally = |
6559 factory->NewTryFinallyStatement(try_block, maybe_close, nopos); | 6563 factory->NewTryFinallyStatement(try_block, maybe_close, nopos); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6634 zone); | 6638 zone); |
6635 | 6639 |
6636 Block* catch_block = factory->NewBlock(nullptr, 0, false, nopos); | 6640 Block* catch_block = factory->NewBlock(nullptr, 0, false, nopos); |
6637 | 6641 |
6638 Scope* catch_scope = NewScope(scope, CATCH_SCOPE); | 6642 Scope* catch_scope = NewScope(scope, CATCH_SCOPE); |
6639 Variable* catch_variable = catch_scope->DeclareLocal( | 6643 Variable* catch_variable = catch_scope->DeclareLocal( |
6640 avfactory->dot_catch_string(), VAR, kCreatedInitialized, | 6644 avfactory->dot_catch_string(), VAR, kCreatedInitialized, |
6641 Variable::NORMAL); | 6645 Variable::NORMAL); |
6642 | 6646 |
6643 try_call_return = factory->NewTryCatchStatement( | 6647 try_call_return = factory->NewTryCatchStatement( |
6644 try_block, catch_scope, catch_variable, catch_block, nopos); | 6648 try_block, catch_scope, catch_variable, catch_block, true, nopos); |
6645 } | 6649 } |
6646 | 6650 |
6647 // let output = %_Call(iteratorReturn, iterator); | 6651 // let output = %_Call(iteratorReturn, iterator); |
6648 // if (!IS_RECEIVER(output)) { | 6652 // if (!IS_RECEIVER(output)) { |
6649 // %ThrowIteratorResultNotAnObject(output); | 6653 // %ThrowIteratorResultNotAnObject(output); |
6650 // } | 6654 // } |
6651 Block* validate_return; | 6655 Block* validate_return; |
6652 { | 6656 { |
6653 Variable* var_output = scope->NewTemporary(avfactory->empty_string()); | 6657 Variable* var_output = scope->NewTemporary(avfactory->empty_string()); |
6654 Statement* call_return; | 6658 Statement* call_return; |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6734 // | 6738 // |
6735 // This function replaces the loop with the following wrapping: | 6739 // This function replaces the loop with the following wrapping: |
6736 // | 6740 // |
6737 // let each; | 6741 // let each; |
6738 // let completion = kNormalCompletion; | 6742 // let completion = kNormalCompletion; |
6739 // try { | 6743 // try { |
6740 // try { | 6744 // try { |
6741 // #loop; | 6745 // #loop; |
6742 // } catch(e) { | 6746 // } catch(e) { |
6743 // if (completion === kAbruptCompletion) completion = kThrowCompletion; | 6747 // if (completion === kAbruptCompletion) completion = kThrowCompletion; |
6744 // throw e; | 6748 // %ReThrow(e); |
6745 // } | 6749 // } |
6746 // } finally { | 6750 // } finally { |
6747 // if (!(completion === kNormalCompletion || IS_UNDEFINED(#iterator))) { | 6751 // if (!(completion === kNormalCompletion || IS_UNDEFINED(#iterator))) { |
6748 // #BuildIteratorCloseForCompletion(#iterator, completion) | 6752 // #BuildIteratorCloseForCompletion(#iterator, completion) |
6749 // } | 6753 // } |
6750 // } | 6754 // } |
6751 // | 6755 // |
6752 // where the loop's body is wrapped as follows: | 6756 // where the loop's body is wrapped as follows: |
6753 // | 6757 // |
6754 // { | 6758 // { |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6859 try_block, target); | 6863 try_block, target); |
6860 final_loop = target; | 6864 final_loop = target; |
6861 } | 6865 } |
6862 | 6866 |
6863 return final_loop; | 6867 return final_loop; |
6864 } | 6868 } |
6865 | 6869 |
6866 | 6870 |
6867 } // namespace internal | 6871 } // namespace internal |
6868 } // namespace v8 | 6872 } // namespace v8 |
OLD | NEW |