Chromium Code Reviews| 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 2555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2566 // 'return' Expression? ';' | 2566 // 'return' Expression? ';' |
| 2567 | 2567 |
| 2568 // Consume the return token. It is necessary to do that before | 2568 // Consume the return token. It is necessary to do that before |
| 2569 // reporting any errors on it, because of the way errors are | 2569 // reporting any errors on it, because of the way errors are |
| 2570 // reported (underlining). | 2570 // reported (underlining). |
| 2571 Expect(Token::RETURN, CHECK_OK); | 2571 Expect(Token::RETURN, CHECK_OK); |
| 2572 Scanner::Location loc = scanner()->location(); | 2572 Scanner::Location loc = scanner()->location(); |
| 2573 function_state_->set_return_location(loc); | 2573 function_state_->set_return_location(loc); |
| 2574 | 2574 |
| 2575 Token::Value tok = peek(); | 2575 Token::Value tok = peek(); |
| 2576 int tail_call_position = -1; | |
| 2577 if (FLAG_harmony_explicit_tailcalls && tok == Token::CONTINUE) { | |
| 2578 Consume(Token::CONTINUE); | |
| 2579 tail_call_position = position(); | |
| 2580 tok = peek(); | |
| 2581 } | |
| 2582 | |
| 2576 Statement* result; | 2583 Statement* result; |
| 2577 Expression* return_value; | 2584 Expression* return_value; |
| 2578 if (scanner()->HasAnyLineTerminatorBeforeNext() || | 2585 if (scanner()->HasAnyLineTerminatorBeforeNext() || |
| 2579 tok == Token::SEMICOLON || | 2586 tok == Token::SEMICOLON || |
| 2580 tok == Token::RBRACE || | 2587 tok == Token::RBRACE || |
| 2581 tok == Token::EOS) { | 2588 tok == Token::EOS) { |
| 2582 if (IsSubclassConstructor(function_state_->kind())) { | 2589 if (IsSubclassConstructor(function_state_->kind())) { |
| 2583 return_value = ThisExpression(scope_, factory(), loc.beg_pos); | 2590 return_value = ThisExpression(scope_, factory(), loc.beg_pos); |
| 2584 } else { | 2591 } else { |
| 2585 return_value = GetLiteralUndefined(position()); | 2592 return_value = GetLiteralUndefined(position()); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2622 Expression* is_undefined = factory()->NewCompareOperation( | 2629 Expression* is_undefined = factory()->NewCompareOperation( |
| 2623 Token::EQ_STRICT, assign, | 2630 Token::EQ_STRICT, assign, |
| 2624 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), pos); | 2631 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), pos); |
| 2625 | 2632 |
| 2626 // is_undefined ? this : is_object_conditional | 2633 // is_undefined ? this : is_object_conditional |
| 2627 return_value = factory()->NewConditional( | 2634 return_value = factory()->NewConditional( |
| 2628 is_undefined, ThisExpression(scope_, factory(), pos), | 2635 is_undefined, ThisExpression(scope_, factory(), pos), |
| 2629 is_object_conditional, pos); | 2636 is_object_conditional, pos); |
| 2630 } | 2637 } |
| 2631 | 2638 |
| 2632 // ES6 14.6.1 Static Semantics: IsInTailPosition | 2639 // TODO(ishell): update chapter number. |
| 2633 if (allow_tailcalls() && !is_sloppy(language_mode())) { | 2640 // ES7 XX.YY.ZZ |
|
rossberg
2016/04/26 14:56:57
It's gonna be ES8. ;)
Igor Sheludko
2016/04/26 16:48:17
Done.
| |
| 2634 function_state_->AddExpressionInTailPosition(return_value); | 2641 if (tail_call_position >= 0) { |
| 2642 if (!function_state_->collect_expressions_in_tail_position()) { | |
| 2643 Scanner::Location loc(tail_call_position, tail_call_position + 1); | |
| 2644 ReportMessageAt(loc, MessageTemplate::kTailCallInTryBlock); | |
| 2645 *ok = false; | |
| 2646 return NULL; | |
| 2647 } | |
| 2648 function_state_->AddExpressionInTailPosition(return_value, | |
| 2649 tail_call_position); | |
| 2650 | |
| 2651 } else if (allow_tailcalls() && !is_sloppy(language_mode())) { | |
| 2652 // ES6 14.6.1 Static Semantics: IsInTailPosition | |
| 2653 function_state_->AddExpressionInTailPosition(return_value, pos); | |
| 2635 } | 2654 } |
| 2636 } | 2655 } |
| 2637 ExpectSemicolon(CHECK_OK); | 2656 ExpectSemicolon(CHECK_OK); |
| 2638 | 2657 |
| 2639 if (is_generator()) { | 2658 if (is_generator()) { |
| 2640 return_value = BuildIteratorResult(return_value, true); | 2659 return_value = BuildIteratorResult(return_value, true); |
| 2641 } | 2660 } |
| 2642 | 2661 |
| 2643 result = factory()->NewReturnStatement(return_value, loc.beg_pos); | 2662 result = factory()->NewReturnStatement(return_value, loc.beg_pos); |
| 2644 | 2663 |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2804 *ok = false; | 2823 *ok = false; |
| 2805 return NULL; | 2824 return NULL; |
| 2806 } | 2825 } |
| 2807 Expression* exception = ParseExpression(true, CHECK_OK); | 2826 Expression* exception = ParseExpression(true, CHECK_OK); |
| 2808 ExpectSemicolon(CHECK_OK); | 2827 ExpectSemicolon(CHECK_OK); |
| 2809 | 2828 |
| 2810 return factory()->NewExpressionStatement( | 2829 return factory()->NewExpressionStatement( |
| 2811 factory()->NewThrow(exception, pos), pos); | 2830 factory()->NewThrow(exception, pos), pos); |
| 2812 } | 2831 } |
| 2813 | 2832 |
| 2814 class Parser::DontCollectExpressionsInTailPositionScope { | |
| 2815 public: | |
| 2816 DontCollectExpressionsInTailPositionScope( | |
| 2817 Parser::FunctionState* function_state) | |
| 2818 : function_state_(function_state), | |
| 2819 old_value_(function_state->collect_expressions_in_tail_position()) { | |
| 2820 function_state->set_collect_expressions_in_tail_position(false); | |
| 2821 } | |
| 2822 ~DontCollectExpressionsInTailPositionScope() { | |
| 2823 function_state_->set_collect_expressions_in_tail_position(old_value_); | |
| 2824 } | |
| 2825 | |
| 2826 private: | |
| 2827 Parser::FunctionState* function_state_; | |
| 2828 bool old_value_; | |
| 2829 }; | |
| 2830 | |
| 2831 // Collects all return expressions at tail call position in this scope | |
| 2832 // to a separate list. | |
| 2833 class Parser::CollectExpressionsInTailPositionToListScope { | |
| 2834 public: | |
| 2835 CollectExpressionsInTailPositionToListScope( | |
| 2836 Parser::FunctionState* function_state, List<Expression*>* list) | |
| 2837 : function_state_(function_state), list_(list) { | |
| 2838 function_state->expressions_in_tail_position().Swap(list_); | |
| 2839 } | |
| 2840 ~CollectExpressionsInTailPositionToListScope() { | |
| 2841 function_state_->expressions_in_tail_position().Swap(list_); | |
| 2842 } | |
| 2843 | |
| 2844 private: | |
| 2845 Parser::FunctionState* function_state_; | |
| 2846 List<Expression*>* list_; | |
| 2847 }; | |
| 2848 | 2833 |
| 2849 TryStatement* Parser::ParseTryStatement(bool* ok) { | 2834 TryStatement* Parser::ParseTryStatement(bool* ok) { |
| 2850 // TryStatement :: | 2835 // TryStatement :: |
| 2851 // 'try' Block Catch | 2836 // 'try' Block Catch |
| 2852 // 'try' Block Finally | 2837 // 'try' Block Finally |
| 2853 // 'try' Block Catch Finally | 2838 // 'try' Block Catch Finally |
| 2854 // | 2839 // |
| 2855 // Catch :: | 2840 // Catch :: |
| 2856 // 'catch' '(' Identifier ')' Block | 2841 // 'catch' '(' Identifier ')' Block |
| 2857 // | 2842 // |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 2870 Token::Value tok = peek(); | 2855 Token::Value tok = peek(); |
| 2871 if (tok != Token::CATCH && tok != Token::FINALLY) { | 2856 if (tok != Token::CATCH && tok != Token::FINALLY) { |
| 2872 ReportMessage(MessageTemplate::kNoCatchOrFinally); | 2857 ReportMessage(MessageTemplate::kNoCatchOrFinally); |
| 2873 *ok = false; | 2858 *ok = false; |
| 2874 return NULL; | 2859 return NULL; |
| 2875 } | 2860 } |
| 2876 | 2861 |
| 2877 Scope* catch_scope = NULL; | 2862 Scope* catch_scope = NULL; |
| 2878 Variable* catch_variable = NULL; | 2863 Variable* catch_variable = NULL; |
| 2879 Block* catch_block = NULL; | 2864 Block* catch_block = NULL; |
| 2880 List<Expression*> expressions_in_tail_position_in_catch_block; | 2865 List<TailCallExpression> expressions_in_tail_position_in_catch_block; |
| 2881 if (tok == Token::CATCH) { | 2866 if (tok == Token::CATCH) { |
| 2882 Consume(Token::CATCH); | 2867 Consume(Token::CATCH); |
| 2883 | 2868 |
| 2884 Expect(Token::LPAREN, CHECK_OK); | 2869 Expect(Token::LPAREN, CHECK_OK); |
| 2885 catch_scope = NewScope(scope_, CATCH_SCOPE); | 2870 catch_scope = NewScope(scope_, CATCH_SCOPE); |
| 2886 catch_scope->set_start_position(scanner()->location().beg_pos); | 2871 catch_scope->set_start_position(scanner()->location().beg_pos); |
| 2887 | 2872 |
| 2888 ExpressionClassifier pattern_classifier(this); | 2873 ExpressionClassifier pattern_classifier(this); |
| 2889 Expression* pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK); | 2874 Expression* pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK); |
| 2890 ValidateBindingPattern(&pattern_classifier, CHECK_OK); | 2875 ValidateBindingPattern(&pattern_classifier, CHECK_OK); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2986 // For a try-catch construct append return expressions from the catch block | 2971 // For a try-catch construct append return expressions from the catch block |
| 2987 // to the list of return expressions. | 2972 // to the list of return expressions. |
| 2988 function_state_->expressions_in_tail_position().AddAll( | 2973 function_state_->expressions_in_tail_position().AddAll( |
| 2989 expressions_in_tail_position_in_catch_block); | 2974 expressions_in_tail_position_in_catch_block); |
| 2990 | 2975 |
| 2991 DCHECK(finally_block == NULL); | 2976 DCHECK(finally_block == NULL); |
| 2992 DCHECK(catch_scope != NULL && catch_variable != NULL); | 2977 DCHECK(catch_scope != NULL && catch_variable != NULL); |
| 2993 result = factory()->NewTryCatchStatement(try_block, catch_scope, | 2978 result = factory()->NewTryCatchStatement(try_block, catch_scope, |
| 2994 catch_variable, catch_block, pos); | 2979 catch_variable, catch_block, pos); |
| 2995 } else { | 2980 } else { |
| 2981 if (FLAG_harmony_explicit_tailcalls && | |
|
rossberg
2016/04/26 14:56:57
How come you only need to do something here for th
Igor Sheludko
2016/04/26 16:48:17
We collect expressions in tail position to the exp
| |
| 2982 expressions_in_tail_position_in_catch_block.length() > 0) { | |
| 2983 // TODO(ishell): update chapter number. | |
| 2984 // ES7 XX.YY.ZZ | |
| 2985 int pos = expressions_in_tail_position_in_catch_block[0].pos; | |
| 2986 ReportMessageAt(Scanner::Location(pos, pos + 1), | |
| 2987 MessageTemplate::kTailCallInCatchBlock); | |
| 2988 *ok = false; | |
| 2989 return NULL; | |
| 2990 } | |
| 2996 DCHECK(finally_block != NULL); | 2991 DCHECK(finally_block != NULL); |
| 2997 result = factory()->NewTryFinallyStatement(try_block, finally_block, pos); | 2992 result = factory()->NewTryFinallyStatement(try_block, finally_block, pos); |
| 2998 } | 2993 } |
| 2999 | 2994 |
| 3000 return result; | 2995 return result; |
| 3001 } | 2996 } |
| 3002 | 2997 |
| 3003 | 2998 |
| 3004 DoWhileStatement* Parser::ParseDoWhileStatement( | 2999 DoWhileStatement* Parser::ParseDoWhileStatement( |
| 3005 ZoneList<const AstRawString*>* labels, bool* ok) { | 3000 ZoneList<const AstRawString*>* labels, bool* ok) { |
| (...skipping 1560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4566 result->Set(kFunctionNameAssignmentIndex, | 4561 result->Set(kFunctionNameAssignmentIndex, |
| 4567 factory()->NewExpressionStatement( | 4562 factory()->NewExpressionStatement( |
| 4568 factory()->NewAssignment(Token::INIT, fproxy, | 4563 factory()->NewAssignment(Token::INIT, fproxy, |
| 4569 factory()->NewThisFunction(pos), | 4564 factory()->NewThisFunction(pos), |
| 4570 RelocInfo::kNoPosition), | 4565 RelocInfo::kNoPosition), |
| 4571 RelocInfo::kNoPosition)); | 4566 RelocInfo::kNoPosition)); |
| 4572 } | 4567 } |
| 4573 | 4568 |
| 4574 // ES6 14.6.1 Static Semantics: IsInTailPosition | 4569 // ES6 14.6.1 Static Semantics: IsInTailPosition |
| 4575 // Mark collected return expressions that are in tail call position. | 4570 // Mark collected return expressions that are in tail call position. |
| 4576 const List<Expression*>& expressions_in_tail_position = | 4571 const List<TailCallExpression>& expressions_in_tail_position = |
| 4577 function_state_->expressions_in_tail_position(); | 4572 function_state_->expressions_in_tail_position(); |
| 4578 for (int i = 0; i < expressions_in_tail_position.length(); ++i) { | 4573 for (int i = 0; i < expressions_in_tail_position.length(); ++i) { |
| 4579 MarkTailPosition(expressions_in_tail_position[i]); | 4574 MarkTailPosition(expressions_in_tail_position[i].expression); |
| 4580 } | 4575 } |
| 4581 return result; | 4576 return result; |
| 4582 } | 4577 } |
| 4583 | 4578 |
| 4584 | 4579 |
| 4585 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( | 4580 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( |
| 4586 SingletonLogger* logger, Scanner::BookmarkScope* bookmark) { | 4581 SingletonLogger* logger, Scanner::BookmarkScope* bookmark) { |
| 4587 // This function may be called on a background thread too; record only the | 4582 // This function may be called on a background thread too; record only the |
| 4588 // main thread preparse times. | 4583 // main thread preparse times. |
| 4589 if (pre_parse_timer_ != NULL) { | 4584 if (pre_parse_timer_ != NULL) { |
| (...skipping 2206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6796 try_block, target); | 6791 try_block, target); |
| 6797 final_loop = target; | 6792 final_loop = target; |
| 6798 } | 6793 } |
| 6799 | 6794 |
| 6800 return final_loop; | 6795 return final_loop; |
| 6801 } | 6796 } |
| 6802 | 6797 |
| 6803 | 6798 |
| 6804 } // namespace internal | 6799 } // namespace internal |
| 6805 } // namespace v8 | 6800 } // namespace v8 |
| OLD | NEW |