Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: src/parsing/parser.cc

Issue 1917993004: [es8] Initial set of changes to support syntactic tail calls. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | src/parsing/parser-base.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698