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 const AstRawString* name, Scanner::Location class_name_location, | 758 const AstRawString* name, Scanner::Location class_name_location, |
759 bool name_is_strict_reserved, int pos, bool* ok) { | 759 bool name_is_strict_reserved, int pos, bool* ok) { |
760 return parser_->ParseClassLiteral(name, class_name_location, | 760 return parser_->ParseClassLiteral(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 1801 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2579 // 'return' Expression? ';' | 2583 // 'return' Expression? ';' |
2580 | 2584 |
2581 // Consume the return token. It is necessary to do that before | 2585 // Consume the return token. It is necessary to do that before |
2582 // reporting any errors on it, because of the way errors are | 2586 // reporting any errors on it, because of the way errors are |
2583 // reported (underlining). | 2587 // reported (underlining). |
2584 Expect(Token::RETURN, CHECK_OK); | 2588 Expect(Token::RETURN, CHECK_OK); |
2585 Scanner::Location loc = scanner()->location(); | 2589 Scanner::Location loc = scanner()->location(); |
2586 function_state_->set_return_location(loc); | 2590 function_state_->set_return_location(loc); |
2587 | 2591 |
2588 Token::Value tok = peek(); | 2592 Token::Value tok = peek(); |
2589 int tail_call_position = -1; | |
2590 if (FLAG_harmony_explicit_tailcalls && tok == Token::CONTINUE) { | |
2591 Consume(Token::CONTINUE); | |
2592 tail_call_position = position(); | |
2593 tok = peek(); | |
2594 } | |
2595 | |
2596 Statement* result; | 2593 Statement* result; |
2597 Expression* return_value; | 2594 Expression* return_value; |
2598 if (scanner()->HasAnyLineTerminatorBeforeNext() || | 2595 if (scanner()->HasAnyLineTerminatorBeforeNext() || |
2599 tok == Token::SEMICOLON || | 2596 tok == Token::SEMICOLON || |
2600 tok == Token::RBRACE || | 2597 tok == Token::RBRACE || |
2601 tok == Token::EOS) { | 2598 tok == Token::EOS) { |
2602 if (IsSubclassConstructor(function_state_->kind())) { | 2599 if (IsSubclassConstructor(function_state_->kind())) { |
2603 return_value = ThisExpression(scope_, factory(), loc.beg_pos); | 2600 return_value = ThisExpression(scope_, factory(), loc.beg_pos); |
2604 } else { | 2601 } else { |
2605 return_value = GetLiteralUndefined(position()); | 2602 return_value = GetLiteralUndefined(position()); |
2606 } | 2603 } |
2607 } else { | 2604 } else { |
2608 int pos = peek_position(); | 2605 int pos = peek_position(); |
2609 return_value = ParseExpression(true, CHECK_OK); | |
2610 | 2606 |
2611 if (IsSubclassConstructor(function_state_->kind())) { | 2607 if (IsSubclassConstructor(function_state_->kind())) { |
| 2608 // Because of the return code rewriting that happens in case of a subclass |
| 2609 // constructor we don't want to accept tail calls, therefore we don't set |
| 2610 // ReturnExprScope to kInsideValidReturnStatement here. |
| 2611 return_value = ParseExpression(true, CHECK_OK); |
| 2612 |
2612 // For subclass constructors we need to return this in case of undefined | 2613 // For subclass constructors we need to return this in case of undefined |
2613 // return a Smi (transformed into an exception in the ConstructStub) | 2614 // return a Smi (transformed into an exception in the ConstructStub) |
2614 // for a non object. | 2615 // for a non object. |
2615 // | 2616 // |
2616 // return expr; | 2617 // return expr; |
2617 // | 2618 // |
2618 // Is rewritten as: | 2619 // Is rewritten as: |
2619 // | 2620 // |
2620 // return (temp = expr) === undefined ? this : | 2621 // return (temp = expr) === undefined ? this : |
2621 // %_IsJSReceiver(temp) ? temp : 1; | 2622 // %_IsJSReceiver(temp) ? temp : 1; |
(...skipping 18 matching lines...) Expand all Loading... |
2640 | 2641 |
2641 // temp === undefined | 2642 // temp === undefined |
2642 Expression* is_undefined = factory()->NewCompareOperation( | 2643 Expression* is_undefined = factory()->NewCompareOperation( |
2643 Token::EQ_STRICT, assign, | 2644 Token::EQ_STRICT, assign, |
2644 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), pos); | 2645 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), pos); |
2645 | 2646 |
2646 // is_undefined ? this : is_object_conditional | 2647 // is_undefined ? this : is_object_conditional |
2647 return_value = factory()->NewConditional( | 2648 return_value = factory()->NewConditional( |
2648 is_undefined, ThisExpression(scope_, factory(), pos), | 2649 is_undefined, ThisExpression(scope_, factory(), pos), |
2649 is_object_conditional, pos); | 2650 is_object_conditional, pos); |
2650 } | 2651 } else { |
| 2652 ReturnExprScope maybe_allow_tail_calls( |
| 2653 function_state_, ReturnExprContext::kInsideValidReturnStatement); |
| 2654 return_value = ParseExpression(true, CHECK_OK); |
2651 | 2655 |
2652 // TODO(ishell): update chapter number. | 2656 if (allow_tailcalls() && !is_sloppy(language_mode())) { |
2653 // ES8 XX.YY.ZZ | 2657 // ES6 14.6.1 Static Semantics: IsInTailPosition |
2654 if (tail_call_position >= 0) { | 2658 Scanner::Location loc(pos, pos + 1); |
2655 ReturnExprContext return_expr_context = | 2659 function_state_->AddExpressionInTailPosition(return_value, loc); |
2656 function_state_->return_expr_context(); | |
2657 if (return_expr_context != ReturnExprContext::kNormal) { | |
2658 ReportIllegalTailCallAt(tail_call_position, return_expr_context); | |
2659 *ok = false; | |
2660 return NULL; | |
2661 } | 2660 } |
2662 function_state_->AddExpressionInTailPosition(return_value, | |
2663 tail_call_position); | |
2664 | |
2665 } else if (allow_tailcalls() && !is_sloppy(language_mode())) { | |
2666 // ES6 14.6.1 Static Semantics: IsInTailPosition | |
2667 function_state_->AddExpressionInTailPosition(return_value, pos); | |
2668 } | 2661 } |
2669 } | 2662 } |
2670 ExpectSemicolon(CHECK_OK); | 2663 ExpectSemicolon(CHECK_OK); |
2671 | 2664 |
2672 if (is_generator()) { | 2665 if (is_generator()) { |
2673 return_value = BuildIteratorResult(return_value, true); | 2666 return_value = BuildIteratorResult(return_value, true); |
2674 } | 2667 } |
2675 | 2668 |
2676 result = factory()->NewReturnStatement(return_value, loc.beg_pos); | 2669 result = factory()->NewReturnStatement(return_value, loc.beg_pos); |
2677 | 2670 |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2870 Token::Value tok = peek(); | 2863 Token::Value tok = peek(); |
2871 if (tok != Token::CATCH && tok != Token::FINALLY) { | 2864 if (tok != Token::CATCH && tok != Token::FINALLY) { |
2872 ReportMessage(MessageTemplate::kNoCatchOrFinally); | 2865 ReportMessage(MessageTemplate::kNoCatchOrFinally); |
2873 *ok = false; | 2866 *ok = false; |
2874 return NULL; | 2867 return NULL; |
2875 } | 2868 } |
2876 | 2869 |
2877 Scope* catch_scope = NULL; | 2870 Scope* catch_scope = NULL; |
2878 Variable* catch_variable = NULL; | 2871 Variable* catch_variable = NULL; |
2879 Block* catch_block = NULL; | 2872 Block* catch_block = NULL; |
2880 List<TailCallExpression> expressions_in_tail_position_in_catch_block; | 2873 TailCallExpressionList tail_call_expressions_in_catch_block(zone()); |
2881 if (tok == Token::CATCH) { | 2874 if (tok == Token::CATCH) { |
2882 Consume(Token::CATCH); | 2875 Consume(Token::CATCH); |
2883 | 2876 |
2884 Expect(Token::LPAREN, CHECK_OK); | 2877 Expect(Token::LPAREN, CHECK_OK); |
2885 catch_scope = NewScope(scope_, CATCH_SCOPE); | 2878 catch_scope = NewScope(scope_, CATCH_SCOPE); |
2886 catch_scope->set_start_position(scanner()->location().beg_pos); | 2879 catch_scope->set_start_position(scanner()->location().beg_pos); |
2887 | 2880 |
2888 ExpressionClassifier pattern_classifier(this); | 2881 ExpressionClassifier pattern_classifier(this); |
2889 Expression* pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK); | 2882 Expression* pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK); |
2890 ValidateBindingPattern(&pattern_classifier, CHECK_OK); | 2883 ValidateBindingPattern(&pattern_classifier, CHECK_OK); |
2891 | 2884 |
2892 const AstRawString* name = ast_value_factory()->dot_catch_string(); | 2885 const AstRawString* name = ast_value_factory()->dot_catch_string(); |
2893 bool is_simple = pattern->IsVariableProxy(); | 2886 bool is_simple = pattern->IsVariableProxy(); |
2894 if (is_simple) { | 2887 if (is_simple) { |
2895 auto proxy = pattern->AsVariableProxy(); | 2888 auto proxy = pattern->AsVariableProxy(); |
2896 scope_->RemoveUnresolved(proxy); | 2889 scope_->RemoveUnresolved(proxy); |
2897 name = proxy->raw_name(); | 2890 name = proxy->raw_name(); |
2898 } | 2891 } |
2899 | 2892 |
2900 catch_variable = catch_scope->DeclareLocal(name, VAR, kCreatedInitialized, | 2893 catch_variable = catch_scope->DeclareLocal(name, VAR, kCreatedInitialized, |
2901 Variable::NORMAL); | 2894 Variable::NORMAL); |
2902 | 2895 |
2903 Expect(Token::RPAREN, CHECK_OK); | 2896 Expect(Token::RPAREN, CHECK_OK); |
2904 | 2897 |
2905 { | 2898 { |
2906 CollectExpressionsInTailPositionToListScope | 2899 CollectExpressionsInTailPositionToListScope |
2907 collect_expressions_in_tail_position_scope( | 2900 collect_tail_call_expressions_scope( |
2908 function_state_, &expressions_in_tail_position_in_catch_block); | 2901 function_state_, &tail_call_expressions_in_catch_block); |
2909 BlockState block_state(&scope_, catch_scope); | 2902 BlockState block_state(&scope_, catch_scope); |
2910 | 2903 |
2911 // TODO(adamk): Make a version of ParseBlock that takes a scope and | 2904 // TODO(adamk): Make a version of ParseBlock that takes a scope and |
2912 // a block. | 2905 // a block. |
2913 catch_block = | 2906 catch_block = |
2914 factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition); | 2907 factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition); |
2915 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); | 2908 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); |
2916 | 2909 |
2917 block_scope->set_start_position(scanner()->location().beg_pos); | 2910 block_scope->set_start_position(scanner()->location().beg_pos); |
2918 { | 2911 { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2978 catch_block, RelocInfo::kNoPosition); | 2971 catch_block, RelocInfo::kNoPosition); |
2979 try_block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); | 2972 try_block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); |
2980 try_block->statements()->Add(statement, zone()); | 2973 try_block->statements()->Add(statement, zone()); |
2981 catch_block = NULL; // Clear to indicate it's been handled. | 2974 catch_block = NULL; // Clear to indicate it's been handled. |
2982 } | 2975 } |
2983 | 2976 |
2984 TryStatement* result = NULL; | 2977 TryStatement* result = NULL; |
2985 if (catch_block != NULL) { | 2978 if (catch_block != NULL) { |
2986 // For a try-catch construct append return expressions from the catch block | 2979 // For a try-catch construct append return expressions from the catch block |
2987 // to the list of return expressions. | 2980 // to the list of return expressions. |
2988 function_state_->expressions_in_tail_position().AddAll( | 2981 function_state_->tail_call_expressions().Append( |
2989 expressions_in_tail_position_in_catch_block); | 2982 tail_call_expressions_in_catch_block); |
2990 | 2983 |
2991 DCHECK(finally_block == NULL); | 2984 DCHECK(finally_block == NULL); |
2992 DCHECK(catch_scope != NULL && catch_variable != NULL); | 2985 DCHECK(catch_scope != NULL && catch_variable != NULL); |
2993 result = factory()->NewTryCatchStatement(try_block, catch_scope, | 2986 result = factory()->NewTryCatchStatement(try_block, catch_scope, |
2994 catch_variable, catch_block, pos); | 2987 catch_variable, catch_block, pos); |
2995 } else { | 2988 } else { |
2996 if (FLAG_harmony_explicit_tailcalls && | 2989 if (FLAG_harmony_explicit_tailcalls && |
2997 expressions_in_tail_position_in_catch_block.length() > 0) { | 2990 !tail_call_expressions_in_catch_block.is_empty()) { |
2998 // TODO(ishell): update chapter number. | 2991 // TODO(ishell): update chapter number. |
2999 // ES8 XX.YY.ZZ | 2992 // ES8 XX.YY.ZZ |
3000 int pos = expressions_in_tail_position_in_catch_block[0].pos; | 2993 ReportMessageAt(tail_call_expressions_in_catch_block.location(), |
3001 ReportMessageAt(Scanner::Location(pos, pos + 1), | 2994 MessageTemplate::kUnexpectedTailCallInCatchBlock); |
3002 MessageTemplate::kTailCallInCatchBlock); | |
3003 *ok = false; | 2995 *ok = false; |
3004 return NULL; | 2996 return NULL; |
3005 } | 2997 } |
3006 DCHECK(finally_block != NULL); | 2998 DCHECK(finally_block != NULL); |
3007 result = factory()->NewTryFinallyStatement(try_block, finally_block, pos); | 2999 result = factory()->NewTryFinallyStatement(try_block, finally_block, pos); |
3008 } | 3000 } |
3009 | 3001 |
3010 return result; | 3002 return result; |
3011 } | 3003 } |
3012 | 3004 |
(...skipping 1563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4576 | 4568 |
4577 VariableProxy* fproxy = factory()->NewVariableProxy(fvar); | 4569 VariableProxy* fproxy = factory()->NewVariableProxy(fvar); |
4578 result->Set(kFunctionNameAssignmentIndex, | 4570 result->Set(kFunctionNameAssignmentIndex, |
4579 factory()->NewExpressionStatement( | 4571 factory()->NewExpressionStatement( |
4580 factory()->NewAssignment(Token::INIT, fproxy, | 4572 factory()->NewAssignment(Token::INIT, fproxy, |
4581 factory()->NewThisFunction(pos), | 4573 factory()->NewThisFunction(pos), |
4582 RelocInfo::kNoPosition), | 4574 RelocInfo::kNoPosition), |
4583 RelocInfo::kNoPosition)); | 4575 RelocInfo::kNoPosition)); |
4584 } | 4576 } |
4585 | 4577 |
4586 // ES6 14.6.1 Static Semantics: IsInTailPosition | 4578 MarkCollectedTailCallExpressions(); |
4587 // Mark collected return expressions that are in tail call position. | |
4588 const List<TailCallExpression>& expressions_in_tail_position = | |
4589 function_state_->expressions_in_tail_position(); | |
4590 for (int i = 0; i < expressions_in_tail_position.length(); ++i) { | |
4591 MarkTailPosition(expressions_in_tail_position[i].expression); | |
4592 } | |
4593 return result; | 4579 return result; |
4594 } | 4580 } |
4595 | 4581 |
4596 | 4582 |
4597 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( | 4583 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( |
4598 SingletonLogger* logger, Scanner::BookmarkScope* bookmark) { | 4584 SingletonLogger* logger, Scanner::BookmarkScope* bookmark) { |
4599 // This function may be called on a background thread too; record only the | 4585 // This function may be called on a background thread too; record only the |
4600 // main thread preparse times. | 4586 // main thread preparse times. |
4601 if (pre_parse_timer_ != NULL) { | 4587 if (pre_parse_timer_ != NULL) { |
4602 pre_parse_timer_->Start(); | 4588 pre_parse_timer_->Start(); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4656 proxy = NewUnresolved(name, CONST); | 4642 proxy = NewUnresolved(name, CONST); |
4657 Declaration* declaration = | 4643 Declaration* declaration = |
4658 factory()->NewVariableDeclaration(proxy, CONST, block_scope, pos); | 4644 factory()->NewVariableDeclaration(proxy, CONST, block_scope, pos); |
4659 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); | 4645 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); |
4660 } | 4646 } |
4661 | 4647 |
4662 Expression* extends = NULL; | 4648 Expression* extends = NULL; |
4663 if (Check(Token::EXTENDS)) { | 4649 if (Check(Token::EXTENDS)) { |
4664 block_scope->set_start_position(scanner()->location().end_pos); | 4650 block_scope->set_start_position(scanner()->location().end_pos); |
4665 ExpressionClassifier classifier(this); | 4651 ExpressionClassifier classifier(this); |
4666 extends = ParseLeftHandSideExpression(&classifier, CHECK_OK); | 4652 extends = |
| 4653 ParseLeftHandSideExpression(kDontAcceptTCE, &classifier, CHECK_OK); |
4667 RewriteNonPattern(&classifier, CHECK_OK); | 4654 RewriteNonPattern(&classifier, CHECK_OK); |
4668 } else { | 4655 } else { |
4669 block_scope->set_start_position(scanner()->location().end_pos); | 4656 block_scope->set_start_position(scanner()->location().end_pos); |
4670 } | 4657 } |
4671 | 4658 |
4672 | 4659 |
4673 ClassLiteralChecker checker(this); | 4660 ClassLiteralChecker checker(this); |
4674 ZoneList<ObjectLiteral::Property*>* properties = NewPropertyList(4, zone()); | 4661 ZoneList<ObjectLiteral::Property*>* properties = NewPropertyList(4, zone()); |
4675 FunctionLiteral* constructor = NULL; | 4662 FunctionLiteral* constructor = NULL; |
4676 bool has_seen_constructor = false; | 4663 bool has_seen_constructor = false; |
(...skipping 618 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5295 ++use_counts_[feature]; | 5282 ++use_counts_[feature]; |
5296 scope->SetLanguageMode(mode); | 5283 scope->SetLanguageMode(mode); |
5297 } | 5284 } |
5298 | 5285 |
5299 | 5286 |
5300 void Parser::RaiseLanguageMode(LanguageMode mode) { | 5287 void Parser::RaiseLanguageMode(LanguageMode mode) { |
5301 LanguageMode old = scope_->language_mode(); | 5288 LanguageMode old = scope_->language_mode(); |
5302 SetLanguageMode(scope_, old > mode ? old : mode); | 5289 SetLanguageMode(scope_, old > mode ? old : mode); |
5303 } | 5290 } |
5304 | 5291 |
| 5292 void Parser::MarkCollectedTailCallExpressions() { |
| 5293 const ZoneList<Expression*>& tail_call_expressions = |
| 5294 function_state_->tail_call_expressions().expressions(); |
| 5295 for (int i = 0; i < tail_call_expressions.length(); ++i) { |
| 5296 Expression* expression = tail_call_expressions[i]; |
| 5297 // If only FLAG_harmony_explicit_tailcalls is enabled then expression |
| 5298 // must be a Call expression. |
| 5299 DCHECK(FLAG_harmony_tailcalls || !FLAG_harmony_explicit_tailcalls || |
| 5300 expression->IsCall()); |
| 5301 MarkTailPosition(expression); |
| 5302 } |
| 5303 } |
5305 | 5304 |
5306 void ParserTraits::RewriteDestructuringAssignments() { | 5305 void ParserTraits::RewriteDestructuringAssignments() { |
5307 parser_->RewriteDestructuringAssignments(); | 5306 parser_->RewriteDestructuringAssignments(); |
5308 } | 5307 } |
5309 | 5308 |
5310 Expression* ParserTraits::RewriteExponentiation(Expression* left, | 5309 Expression* ParserTraits::RewriteExponentiation(Expression* left, |
5311 Expression* right, int pos) { | 5310 Expression* right, int pos) { |
5312 return parser_->RewriteExponentiation(left, right, pos); | 5311 return parser_->RewriteExponentiation(left, right, pos); |
5313 } | 5312 } |
5314 | 5313 |
(...skipping 1493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6808 try_block, target); | 6807 try_block, target); |
6809 final_loop = target; | 6808 final_loop = target; |
6810 } | 6809 } |
6811 | 6810 |
6812 return final_loop; | 6811 return final_loop; |
6813 } | 6812 } |
6814 | 6813 |
6815 | 6814 |
6816 } // namespace internal | 6815 } // namespace internal |
6817 } // namespace v8 | 6816 } // namespace v8 |
OLD | NEW |