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

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

Issue 1928203002: [es8] More spec compliant syntactic tail calls implementation. (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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 <cmath> 5 #include <cmath>
6 6
7 #include "src/allocation.h" 7 #include "src/allocation.h"
8 #include "src/base/logging.h" 8 #include "src/base/logging.h"
9 #include "src/conversions-inl.h" 9 #include "src/conversions-inl.h"
10 #include "src/conversions.h" 10 #include "src/conversions.h"
(...skipping 683 matching lines...) Expand 10 before | Expand all | Expand 10 after
694 // reported (underlining). 694 // reported (underlining).
695 Expect(Token::RETURN, CHECK_OK); 695 Expect(Token::RETURN, CHECK_OK);
696 function_state_->set_return_location(scanner()->location()); 696 function_state_->set_return_location(scanner()->location());
697 697
698 // An ECMAScript program is considered syntactically incorrect if it 698 // An ECMAScript program is considered syntactically incorrect if it
699 // contains a return statement that is not within the body of a 699 // contains a return statement that is not within the body of a
700 // function. See ECMA-262, section 12.9, page 67. 700 // function. See ECMA-262, section 12.9, page 67.
701 // This is not handled during preparsing. 701 // This is not handled during preparsing.
702 702
703 Token::Value tok = peek(); 703 Token::Value tok = peek();
704 int tail_call_position = -1;
705 if (FLAG_harmony_explicit_tailcalls && tok == Token::CONTINUE) {
706 Consume(Token::CONTINUE);
707 tail_call_position = position();
708 tok = peek();
709 }
710 if (!scanner()->HasAnyLineTerminatorBeforeNext() && 704 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
711 tok != Token::SEMICOLON && 705 tok != Token::SEMICOLON &&
712 tok != Token::RBRACE && 706 tok != Token::RBRACE &&
713 tok != Token::EOS) { 707 tok != Token::EOS) {
708 // Because of the return code rewriting that happens in case of a subclass
709 // constructor we don't want to accept tail calls, therefore we don't set
710 // ReturnExprScope to kInsideValidReturnStatement here.
711 ReturnExprContext return_expr_context =
712 IsSubclassConstructor(function_state_->kind())
713 ? function_state_->return_expr_context()
714 : ReturnExprContext::kInsideValidReturnStatement;
715
716 ReturnExprScope maybe_allow_tail_calls(function_state_,
717 return_expr_context);
714 ParseExpression(true, CHECK_OK); 718 ParseExpression(true, CHECK_OK);
715 if (tail_call_position >= 0) {
716 ReturnExprContext return_expr_context =
717 function_state_->return_expr_context();
718 if (return_expr_context != ReturnExprContext::kNormal) {
719 ReportIllegalTailCallAt(tail_call_position, return_expr_context);
720 *ok = false;
721 return Statement::Default();
722 }
723 function_state_->AddExpressionInTailPosition(
724 PreParserExpression::Default(), tail_call_position);
725 }
726 } 719 }
727 ExpectSemicolon(CHECK_OK); 720 ExpectSemicolon(CHECK_OK);
728 return Statement::Jump(); 721 return Statement::Jump();
729 } 722 }
730 723
731 724
732 PreParser::Statement PreParser::ParseWithStatement(bool* ok) { 725 PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
733 // WithStatement :: 726 // WithStatement ::
734 // 'with' '(' Expression ')' Statement 727 // 'with' '(' Expression ')' Statement
735 Expect(Token::WITH, CHECK_OK); 728 Expect(Token::WITH, CHECK_OK);
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
982 ReturnExprContext::kInsideTryBlock); 975 ReturnExprContext::kInsideTryBlock);
983 ParseBlock(CHECK_OK); 976 ParseBlock(CHECK_OK);
984 } 977 }
985 978
986 Token::Value tok = peek(); 979 Token::Value tok = peek();
987 if (tok != Token::CATCH && tok != Token::FINALLY) { 980 if (tok != Token::CATCH && tok != Token::FINALLY) {
988 ReportMessageAt(scanner()->location(), MessageTemplate::kNoCatchOrFinally); 981 ReportMessageAt(scanner()->location(), MessageTemplate::kNoCatchOrFinally);
989 *ok = false; 982 *ok = false;
990 return Statement::Default(); 983 return Statement::Default();
991 } 984 }
992 List<TailCallExpression> expressions_in_tail_position_in_catch_block; 985 TailCallExpressionList tail_call_expressions_in_catch_block(zone());
993 bool catch_block_exists = false; 986 bool catch_block_exists = false;
994 if (tok == Token::CATCH) { 987 if (tok == Token::CATCH) {
995 Consume(Token::CATCH); 988 Consume(Token::CATCH);
996 Expect(Token::LPAREN, CHECK_OK); 989 Expect(Token::LPAREN, CHECK_OK);
997 Scope* catch_scope = NewScope(scope_, CATCH_SCOPE); 990 Scope* catch_scope = NewScope(scope_, CATCH_SCOPE);
998 ExpressionClassifier pattern_classifier(this); 991 ExpressionClassifier pattern_classifier(this);
999 ParsePrimaryExpression(&pattern_classifier, CHECK_OK); 992 ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
1000 ValidateBindingPattern(&pattern_classifier, CHECK_OK); 993 ValidateBindingPattern(&pattern_classifier, CHECK_OK);
1001 Expect(Token::RPAREN, CHECK_OK); 994 Expect(Token::RPAREN, CHECK_OK);
1002 { 995 {
1003 CollectExpressionsInTailPositionToListScope 996 CollectExpressionsInTailPositionToListScope
1004 collect_expressions_in_tail_position_scope( 997 collect_tail_call_expressions_scope(
1005 function_state_, &expressions_in_tail_position_in_catch_block); 998 function_state_, &tail_call_expressions_in_catch_block);
1006 BlockState block_state(&scope_, catch_scope); 999 BlockState block_state(&scope_, catch_scope);
1007 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); 1000 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
1008 { 1001 {
1009 BlockState block_state(&scope_, block_scope); 1002 BlockState block_state(&scope_, block_scope);
1010 ParseBlock(CHECK_OK); 1003 ParseBlock(CHECK_OK);
1011 } 1004 }
1012 } 1005 }
1013 catch_block_exists = true; 1006 catch_block_exists = true;
1014 tok = peek(); 1007 tok = peek();
1015 } 1008 }
1016 if (tok == Token::FINALLY) { 1009 if (tok == Token::FINALLY) {
1017 Consume(Token::FINALLY); 1010 Consume(Token::FINALLY);
1018 ParseBlock(CHECK_OK); 1011 ParseBlock(CHECK_OK);
1019 if (FLAG_harmony_explicit_tailcalls && catch_block_exists && 1012 if (FLAG_harmony_explicit_tailcalls && catch_block_exists &&
1020 expressions_in_tail_position_in_catch_block.length() > 0) { 1013 !tail_call_expressions_in_catch_block.is_empty()) {
1021 // TODO(ishell): update chapter number. 1014 // TODO(ishell): update chapter number.
1022 // ES8 XX.YY.ZZ 1015 // ES8 XX.YY.ZZ
1023 int pos = expressions_in_tail_position_in_catch_block[0].pos; 1016 ReportMessageAt(tail_call_expressions_in_catch_block.location(),
1024 ReportMessageAt(Scanner::Location(pos, pos + 1), 1017 MessageTemplate::kUnexpectedTailCallInCatchBlock);
1025 MessageTemplate::kTailCallInCatchBlock);
1026 *ok = false; 1018 *ok = false;
1027 return Statement::Default(); 1019 return Statement::Default();
1028 } 1020 }
1029 } 1021 }
1030 return Statement::Default(); 1022 return Statement::Default();
1031 } 1023 }
1032 1024
1033 1025
1034 PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) { 1026 PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
1035 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser 1027 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
1152 Scope* scope = NewScope(scope_, BLOCK_SCOPE); 1144 Scope* scope = NewScope(scope_, BLOCK_SCOPE);
1153 BlockState block_state(&scope_, scope); 1145 BlockState block_state(&scope_, scope);
1154 scope_->SetLanguageMode( 1146 scope_->SetLanguageMode(
1155 static_cast<LanguageMode>(class_language_mode | STRICT)); 1147 static_cast<LanguageMode>(class_language_mode | STRICT));
1156 // TODO(marja): Make PreParser use scope names too. 1148 // TODO(marja): Make PreParser use scope names too.
1157 // scope_->SetScopeName(name); 1149 // scope_->SetScopeName(name);
1158 1150
1159 bool has_extends = Check(Token::EXTENDS); 1151 bool has_extends = Check(Token::EXTENDS);
1160 if (has_extends) { 1152 if (has_extends) {
1161 ExpressionClassifier classifier(this); 1153 ExpressionClassifier classifier(this);
1162 ParseLeftHandSideExpression(&classifier, CHECK_OK); 1154 ParseLeftHandSideExpression(kDontAcceptTCE, &classifier, CHECK_OK);
1163 ValidateExpression(&classifier, CHECK_OK); 1155 ValidateExpression(&classifier, CHECK_OK);
1164 } 1156 }
1165 1157
1166 ClassLiteralChecker checker(this); 1158 ClassLiteralChecker checker(this);
1167 bool has_seen_constructor = false; 1159 bool has_seen_constructor = false;
1168 1160
1169 Expect(Token::LBRACE, CHECK_OK); 1161 Expect(Token::LBRACE, CHECK_OK);
1170 while (peek() != Token::RBRACE) { 1162 while (peek() != Token::RBRACE) {
1171 if (Check(Token::SEMICOLON)) continue; 1163 if (Check(Token::SEMICOLON)) continue;
1172 const bool in_class = true; 1164 const bool in_class = true;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1218 } 1210 }
1219 Expect(Token::RBRACE, CHECK_OK); 1211 Expect(Token::RBRACE, CHECK_OK);
1220 return PreParserExpression::Default(); 1212 return PreParserExpression::Default();
1221 } 1213 }
1222 1214
1223 #undef CHECK_OK 1215 #undef CHECK_OK
1224 1216
1225 1217
1226 } // namespace internal 1218 } // namespace internal
1227 } // namespace v8 1219 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698