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 747 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |