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

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

Issue 1928203002: [es8] More spec compliant syntactic tail calls implementation. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Some STC tests ported for PTC 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
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 747 matching lines...) Expand 10 before | Expand all | Expand 10 after
758 Scanner::Location class_name_location, bool name_is_strict_reserved, 758 Scanner::Location class_name_location, bool name_is_strict_reserved,
759 int pos, bool* ok) { 759 int pos, bool* ok) {
760 return parser_->ParseClassLiteral(classifier, name, class_name_location, 760 return parser_->ParseClassLiteral(classifier, name, class_name_location,
761 name_is_strict_reserved, pos, ok); 761 name_is_strict_reserved, pos, ok);
762 } 762 }
763 763
764 void ParserTraits::MarkTailPosition(Expression* expression) { 764 void ParserTraits::MarkTailPosition(Expression* expression) {
765 expression->MarkTail(); 765 expression->MarkTail();
766 } 766 }
767 767
768 void ParserTraits::MarkCollectedTailCallExpressions() {
769 parser_->MarkCollectedTailCallExpressions();
770 }
771
768 Parser::Parser(ParseInfo* info) 772 Parser::Parser(ParseInfo* info)
769 : ParserBase<ParserTraits>(info->zone(), &scanner_, info->stack_limit(), 773 : ParserBase<ParserTraits>(info->zone(), &scanner_, info->stack_limit(),
770 info->extension(), info->ast_value_factory(), 774 info->extension(), info->ast_value_factory(),
771 NULL, this), 775 NULL, this),
772 scanner_(info->unicode_cache()), 776 scanner_(info->unicode_cache()),
773 reusable_preparser_(NULL), 777 reusable_preparser_(NULL),
774 original_scope_(NULL), 778 original_scope_(NULL),
775 target_stack_(NULL), 779 target_stack_(NULL),
776 compile_options_(info->compile_options()), 780 compile_options_(info->compile_options()),
777 cached_parse_data_(NULL), 781 cached_parse_data_(NULL),
(...skipping 1803 matching lines...) Expand 10 before | Expand all | Expand 10 after
2581 // 'return' Expression? ';' 2585 // 'return' Expression? ';'
2582 2586
2583 // Consume the return token. It is necessary to do that before 2587 // Consume the return token. It is necessary to do that before
2584 // reporting any errors on it, because of the way errors are 2588 // reporting any errors on it, because of the way errors are
2585 // reported (underlining). 2589 // reported (underlining).
2586 Expect(Token::RETURN, CHECK_OK); 2590 Expect(Token::RETURN, CHECK_OK);
2587 Scanner::Location loc = scanner()->location(); 2591 Scanner::Location loc = scanner()->location();
2588 function_state_->set_return_location(loc); 2592 function_state_->set_return_location(loc);
2589 2593
2590 Token::Value tok = peek(); 2594 Token::Value tok = peek();
2591 int tail_call_position = -1;
2592 if (FLAG_harmony_explicit_tailcalls && tok == Token::CONTINUE) {
2593 Consume(Token::CONTINUE);
2594 tail_call_position = position();
2595 tok = peek();
2596 }
2597
2598 Statement* result; 2595 Statement* result;
2599 Expression* return_value; 2596 Expression* return_value;
2600 if (scanner()->HasAnyLineTerminatorBeforeNext() || 2597 if (scanner()->HasAnyLineTerminatorBeforeNext() ||
2601 tok == Token::SEMICOLON || 2598 tok == Token::SEMICOLON ||
2602 tok == Token::RBRACE || 2599 tok == Token::RBRACE ||
2603 tok == Token::EOS) { 2600 tok == Token::EOS) {
2604 if (IsSubclassConstructor(function_state_->kind())) { 2601 if (IsSubclassConstructor(function_state_->kind())) {
2605 return_value = ThisExpression(scope_, factory(), loc.beg_pos); 2602 return_value = ThisExpression(scope_, factory(), loc.beg_pos);
2606 } else { 2603 } else {
2607 return_value = GetLiteralUndefined(position()); 2604 return_value = GetLiteralUndefined(position());
2608 } 2605 }
2609 } else { 2606 } else {
2610 int pos = peek_position(); 2607 int pos = peek_position();
2611 return_value = ParseExpression(true, CHECK_OK);
2612 2608
2613 if (IsSubclassConstructor(function_state_->kind())) { 2609 if (IsSubclassConstructor(function_state_->kind())) {
2610 // Because of the return code rewriting that happens in case of a subclass
2611 // constructor we don't want to accept tail calls, therefore we don't set
2612 // ReturnExprScope to kInsideValidReturnStatement here.
2613 return_value = ParseExpression(true, CHECK_OK);
2614
2614 // For subclass constructors we need to return this in case of undefined 2615 // For subclass constructors we need to return this in case of undefined
2615 // return a Smi (transformed into an exception in the ConstructStub) 2616 // return a Smi (transformed into an exception in the ConstructStub)
2616 // for a non object. 2617 // for a non object.
2617 // 2618 //
2618 // return expr; 2619 // return expr;
2619 // 2620 //
2620 // Is rewritten as: 2621 // Is rewritten as:
2621 // 2622 //
2622 // return (temp = expr) === undefined ? this : 2623 // return (temp = expr) === undefined ? this :
2623 // %_IsJSReceiver(temp) ? temp : 1; 2624 // %_IsJSReceiver(temp) ? temp : 1;
(...skipping 18 matching lines...) Expand all
2642 2643
2643 // temp === undefined 2644 // temp === undefined
2644 Expression* is_undefined = factory()->NewCompareOperation( 2645 Expression* is_undefined = factory()->NewCompareOperation(
2645 Token::EQ_STRICT, assign, 2646 Token::EQ_STRICT, assign,
2646 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), pos); 2647 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), pos);
2647 2648
2648 // is_undefined ? this : is_object_conditional 2649 // is_undefined ? this : is_object_conditional
2649 return_value = factory()->NewConditional( 2650 return_value = factory()->NewConditional(
2650 is_undefined, ThisExpression(scope_, factory(), pos), 2651 is_undefined, ThisExpression(scope_, factory(), pos),
2651 is_object_conditional, pos); 2652 is_object_conditional, pos);
2652 } 2653 } else {
2654 ReturnExprScope maybe_allow_tail_calls(
2655 function_state_, ReturnExprContext::kInsideValidReturnStatement);
2656 return_value = ParseExpression(true, CHECK_OK);
2653 2657
2654 // TODO(ishell): update chapter number. 2658 if (allow_tailcalls() && !is_sloppy(language_mode())) {
2655 // ES8 XX.YY.ZZ 2659 // ES6 14.6.1 Static Semantics: IsInTailPosition
2656 if (tail_call_position >= 0) { 2660 Scanner::Location loc(pos, pos + 1);
2657 ReturnExprContext return_expr_context = 2661 function_state_->AddExpressionInTailPosition(return_value, loc);
2658 function_state_->return_expr_context();
2659 if (return_expr_context != ReturnExprContext::kNormal) {
2660 ReportIllegalTailCallAt(tail_call_position, return_expr_context);
2661 *ok = false;
2662 return NULL;
2663 } 2662 }
2664 function_state_->AddExpressionInTailPosition(return_value,
2665 tail_call_position);
2666
2667 } else if (allow_tailcalls() && !is_sloppy(language_mode())) {
2668 // ES6 14.6.1 Static Semantics: IsInTailPosition
2669 function_state_->AddExpressionInTailPosition(return_value, pos);
2670 } 2663 }
2671 } 2664 }
2672 ExpectSemicolon(CHECK_OK); 2665 ExpectSemicolon(CHECK_OK);
2673 2666
2674 if (is_generator()) { 2667 if (is_generator()) {
2675 return_value = BuildIteratorResult(return_value, true); 2668 return_value = BuildIteratorResult(return_value, true);
2676 } 2669 }
2677 2670
2678 result = factory()->NewReturnStatement(return_value, loc.beg_pos); 2671 result = factory()->NewReturnStatement(return_value, loc.beg_pos);
2679 2672
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
2872 Token::Value tok = peek(); 2865 Token::Value tok = peek();
2873 if (tok != Token::CATCH && tok != Token::FINALLY) { 2866 if (tok != Token::CATCH && tok != Token::FINALLY) {
2874 ReportMessage(MessageTemplate::kNoCatchOrFinally); 2867 ReportMessage(MessageTemplate::kNoCatchOrFinally);
2875 *ok = false; 2868 *ok = false;
2876 return NULL; 2869 return NULL;
2877 } 2870 }
2878 2871
2879 Scope* catch_scope = NULL; 2872 Scope* catch_scope = NULL;
2880 Variable* catch_variable = NULL; 2873 Variable* catch_variable = NULL;
2881 Block* catch_block = NULL; 2874 Block* catch_block = NULL;
2882 List<TailCallExpression> expressions_in_tail_position_in_catch_block; 2875 TailCallExpressionList tail_call_expressions_in_catch_block(zone());
2883 if (tok == Token::CATCH) { 2876 if (tok == Token::CATCH) {
2884 Consume(Token::CATCH); 2877 Consume(Token::CATCH);
2885 2878
2886 Expect(Token::LPAREN, CHECK_OK); 2879 Expect(Token::LPAREN, CHECK_OK);
2887 catch_scope = NewScope(scope_, CATCH_SCOPE); 2880 catch_scope = NewScope(scope_, CATCH_SCOPE);
2888 catch_scope->set_start_position(scanner()->location().beg_pos); 2881 catch_scope->set_start_position(scanner()->location().beg_pos);
2889 2882
2890 ExpressionClassifier pattern_classifier(this); 2883 ExpressionClassifier pattern_classifier(this);
2891 Expression* pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK); 2884 Expression* pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
2892 ValidateBindingPattern(&pattern_classifier, CHECK_OK); 2885 ValidateBindingPattern(&pattern_classifier, CHECK_OK);
2893 2886
2894 const AstRawString* name = ast_value_factory()->dot_catch_string(); 2887 const AstRawString* name = ast_value_factory()->dot_catch_string();
2895 bool is_simple = pattern->IsVariableProxy(); 2888 bool is_simple = pattern->IsVariableProxy();
2896 if (is_simple) { 2889 if (is_simple) {
2897 auto proxy = pattern->AsVariableProxy(); 2890 auto proxy = pattern->AsVariableProxy();
2898 scope_->RemoveUnresolved(proxy); 2891 scope_->RemoveUnresolved(proxy);
2899 name = proxy->raw_name(); 2892 name = proxy->raw_name();
2900 } 2893 }
2901 2894
2902 catch_variable = catch_scope->DeclareLocal(name, VAR, kCreatedInitialized, 2895 catch_variable = catch_scope->DeclareLocal(name, VAR, kCreatedInitialized,
2903 Variable::NORMAL); 2896 Variable::NORMAL);
2904 2897
2905 Expect(Token::RPAREN, CHECK_OK); 2898 Expect(Token::RPAREN, CHECK_OK);
2906 2899
2907 { 2900 {
2908 CollectExpressionsInTailPositionToListScope 2901 CollectExpressionsInTailPositionToListScope
2909 collect_expressions_in_tail_position_scope( 2902 collect_tail_call_expressions_scope(
2910 function_state_, &expressions_in_tail_position_in_catch_block); 2903 function_state_, &tail_call_expressions_in_catch_block);
2911 BlockState block_state(&scope_, catch_scope); 2904 BlockState block_state(&scope_, catch_scope);
2912 2905
2913 // TODO(adamk): Make a version of ParseBlock that takes a scope and 2906 // TODO(adamk): Make a version of ParseBlock that takes a scope and
2914 // a block. 2907 // a block.
2915 catch_block = 2908 catch_block =
2916 factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition); 2909 factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition);
2917 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); 2910 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
2918 2911
2919 block_scope->set_start_position(scanner()->location().beg_pos); 2912 block_scope->set_start_position(scanner()->location().beg_pos);
2920 { 2913 {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2980 catch_block, RelocInfo::kNoPosition); 2973 catch_block, RelocInfo::kNoPosition);
2981 try_block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); 2974 try_block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
2982 try_block->statements()->Add(statement, zone()); 2975 try_block->statements()->Add(statement, zone());
2983 catch_block = NULL; // Clear to indicate it's been handled. 2976 catch_block = NULL; // Clear to indicate it's been handled.
2984 } 2977 }
2985 2978
2986 TryStatement* result = NULL; 2979 TryStatement* result = NULL;
2987 if (catch_block != NULL) { 2980 if (catch_block != NULL) {
2988 // For a try-catch construct append return expressions from the catch block 2981 // For a try-catch construct append return expressions from the catch block
2989 // to the list of return expressions. 2982 // to the list of return expressions.
2990 function_state_->expressions_in_tail_position().AddAll( 2983 function_state_->tail_call_expressions().Append(
2991 expressions_in_tail_position_in_catch_block); 2984 tail_call_expressions_in_catch_block);
2992 2985
2993 DCHECK(finally_block == NULL); 2986 DCHECK(finally_block == NULL);
2994 DCHECK(catch_scope != NULL && catch_variable != NULL); 2987 DCHECK(catch_scope != NULL && catch_variable != NULL);
2995 result = factory()->NewTryCatchStatement(try_block, catch_scope, 2988 result = factory()->NewTryCatchStatement(try_block, catch_scope,
2996 catch_variable, catch_block, pos); 2989 catch_variable, catch_block, pos);
2997 } else { 2990 } else {
2998 if (FLAG_harmony_explicit_tailcalls && 2991 if (FLAG_harmony_explicit_tailcalls &&
2999 expressions_in_tail_position_in_catch_block.length() > 0) { 2992 !tail_call_expressions_in_catch_block.is_empty()) {
3000 // TODO(ishell): update chapter number. 2993 // TODO(ishell): update chapter number.
3001 // ES8 XX.YY.ZZ 2994 // ES8 XX.YY.ZZ
3002 int pos = expressions_in_tail_position_in_catch_block[0].pos; 2995 ReportMessageAt(tail_call_expressions_in_catch_block.location(),
3003 ReportMessageAt(Scanner::Location(pos, pos + 1), 2996 MessageTemplate::kUnexpectedTailCallInCatchBlock);
3004 MessageTemplate::kTailCallInCatchBlock);
3005 *ok = false; 2997 *ok = false;
3006 return NULL; 2998 return NULL;
3007 } 2999 }
3008 DCHECK(finally_block != NULL); 3000 DCHECK(finally_block != NULL);
3009 result = factory()->NewTryFinallyStatement(try_block, finally_block, pos); 3001 result = factory()->NewTryFinallyStatement(try_block, finally_block, pos);
3010 } 3002 }
3011 3003
3012 return result; 3004 return result;
3013 } 3005 }
3014 3006
(...skipping 1563 matching lines...) Expand 10 before | Expand all | Expand 10 after
4578 4570
4579 VariableProxy* fproxy = factory()->NewVariableProxy(fvar); 4571 VariableProxy* fproxy = factory()->NewVariableProxy(fvar);
4580 result->Set(kFunctionNameAssignmentIndex, 4572 result->Set(kFunctionNameAssignmentIndex,
4581 factory()->NewExpressionStatement( 4573 factory()->NewExpressionStatement(
4582 factory()->NewAssignment(Token::INIT, fproxy, 4574 factory()->NewAssignment(Token::INIT, fproxy,
4583 factory()->NewThisFunction(pos), 4575 factory()->NewThisFunction(pos),
4584 RelocInfo::kNoPosition), 4576 RelocInfo::kNoPosition),
4585 RelocInfo::kNoPosition)); 4577 RelocInfo::kNoPosition));
4586 } 4578 }
4587 4579
4588 // ES6 14.6.1 Static Semantics: IsInTailPosition 4580 MarkCollectedTailCallExpressions();
4589 // Mark collected return expressions that are in tail call position.
4590 const List<TailCallExpression>& expressions_in_tail_position =
4591 function_state_->expressions_in_tail_position();
4592 for (int i = 0; i < expressions_in_tail_position.length(); ++i) {
4593 MarkTailPosition(expressions_in_tail_position[i].expression);
4594 }
4595 return result; 4581 return result;
4596 } 4582 }
4597 4583
4598 4584
4599 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( 4585 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
4600 SingletonLogger* logger, Scanner::BookmarkScope* bookmark) { 4586 SingletonLogger* logger, Scanner::BookmarkScope* bookmark) {
4601 // This function may be called on a background thread too; record only the 4587 // This function may be called on a background thread too; record only the
4602 // main thread preparse times. 4588 // main thread preparse times.
4603 if (pre_parse_timer_ != NULL) { 4589 if (pre_parse_timer_ != NULL) {
4604 pre_parse_timer_->Start(); 4590 pre_parse_timer_->Start();
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
4659 Declaration* declaration = 4645 Declaration* declaration =
4660 factory()->NewVariableDeclaration(proxy, CONST, block_scope, pos); 4646 factory()->NewVariableDeclaration(proxy, CONST, block_scope, pos);
4661 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); 4647 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
4662 } 4648 }
4663 4649
4664 Expression* extends = NULL; 4650 Expression* extends = NULL;
4665 if (Check(Token::EXTENDS)) { 4651 if (Check(Token::EXTENDS)) {
4666 block_scope->set_start_position(scanner()->location().end_pos); 4652 block_scope->set_start_position(scanner()->location().end_pos);
4667 ExpressionClassifier extends_classifier(this); 4653 ExpressionClassifier extends_classifier(this);
4668 extends = ParseLeftHandSideExpression(&extends_classifier, CHECK_OK); 4654 extends = ParseLeftHandSideExpression(&extends_classifier, CHECK_OK);
4655 CheckNoTailCallExpressions(&extends_classifier, CHECK_OK);
4669 RewriteNonPattern(&extends_classifier, CHECK_OK); 4656 RewriteNonPattern(&extends_classifier, CHECK_OK);
4670 if (classifier != nullptr) { 4657 if (classifier != nullptr) {
4671 classifier->Accumulate(&extends_classifier, 4658 classifier->Accumulate(&extends_classifier,
4672 ExpressionClassifier::ExpressionProductions); 4659 ExpressionClassifier::ExpressionProductions);
4673 } 4660 }
4674 } else { 4661 } else {
4675 block_scope->set_start_position(scanner()->location().end_pos); 4662 block_scope->set_start_position(scanner()->location().end_pos);
4676 } 4663 }
4677 4664
4678 4665
(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after
5301 ++use_counts_[feature]; 5288 ++use_counts_[feature];
5302 scope->SetLanguageMode(mode); 5289 scope->SetLanguageMode(mode);
5303 } 5290 }
5304 5291
5305 5292
5306 void Parser::RaiseLanguageMode(LanguageMode mode) { 5293 void Parser::RaiseLanguageMode(LanguageMode mode) {
5307 LanguageMode old = scope_->language_mode(); 5294 LanguageMode old = scope_->language_mode();
5308 SetLanguageMode(scope_, old > mode ? old : mode); 5295 SetLanguageMode(scope_, old > mode ? old : mode);
5309 } 5296 }
5310 5297
5298 void Parser::MarkCollectedTailCallExpressions() {
5299 const ZoneList<Expression*>& tail_call_expressions =
5300 function_state_->tail_call_expressions().expressions();
5301 for (int i = 0; i < tail_call_expressions.length(); ++i) {
5302 Expression* expression = tail_call_expressions[i];
5303 // If only FLAG_harmony_explicit_tailcalls is enabled then expression
5304 // must be a Call expression.
5305 DCHECK(FLAG_harmony_tailcalls || !FLAG_harmony_explicit_tailcalls ||
5306 expression->IsCall());
5307 MarkTailPosition(expression);
5308 }
5309 }
5311 5310
5312 void ParserTraits::RewriteDestructuringAssignments() { 5311 void ParserTraits::RewriteDestructuringAssignments() {
5313 parser_->RewriteDestructuringAssignments(); 5312 parser_->RewriteDestructuringAssignments();
5314 } 5313 }
5315 5314
5316 Expression* ParserTraits::RewriteExponentiation(Expression* left, 5315 Expression* ParserTraits::RewriteExponentiation(Expression* left,
5317 Expression* right, int pos) { 5316 Expression* right, int pos) {
5318 return parser_->RewriteExponentiation(left, right, pos); 5317 return parser_->RewriteExponentiation(left, right, pos);
5319 } 5318 }
5320 5319
(...skipping 1493 matching lines...) Expand 10 before | Expand all | Expand 10 after
6814 try_block, target); 6813 try_block, target);
6815 final_loop = target; 6814 final_loop = target;
6816 } 6815 }
6817 6816
6818 return final_loop; 6817 return final_loop;
6819 } 6818 }
6820 6819
6821 6820
6822 } // namespace internal 6821 } // namespace internal
6823 } // namespace v8 6822 } // namespace v8
OLDNEW
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698