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 <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/ast/ast-expression-rewriter.h" | 10 #include "src/ast/ast-expression-rewriter.h" |
(...skipping 748 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
759 // via ParseInfo, and also not pass it forward. | 759 // via ParseInfo, and also not pass it forward. |
760 DCHECK_NULL(scope_state_); | 760 DCHECK_NULL(scope_state_); |
761 DCHECK_NULL(target_stack_); | 761 DCHECK_NULL(target_stack_); |
762 | 762 |
763 Mode parsing_mode = allow_lazy() ? PARSE_LAZILY : PARSE_EAGERLY; | 763 Mode parsing_mode = allow_lazy() ? PARSE_LAZILY : PARSE_EAGERLY; |
764 | 764 |
765 FunctionLiteral* result = NULL; | 765 FunctionLiteral* result = NULL; |
766 { | 766 { |
767 Scope* outer = original_scope_; | 767 Scope* outer = original_scope_; |
768 DCHECK_NOT_NULL(outer); | 768 DCHECK_NOT_NULL(outer); |
769 parsing_module_ = info->is_module(); | |
769 if (info->is_eval()) { | 770 if (info->is_eval()) { |
770 if (!outer->is_script_scope() || is_strict(info->language_mode())) { | 771 if (!outer->is_script_scope() || is_strict(info->language_mode())) { |
771 parsing_mode = PARSE_EAGERLY; | 772 parsing_mode = PARSE_EAGERLY; |
772 } | 773 } |
773 outer = NewEvalScope(outer); | 774 outer = NewEvalScope(outer); |
774 } else if (info->is_module()) { | 775 } else if (parsing_module_) { |
775 DCHECK_EQ(outer, info->script_scope()); | 776 DCHECK_EQ(outer, info->script_scope()); |
776 outer = NewModuleScope(info->script_scope()); | 777 outer = NewModuleScope(info->script_scope()); |
777 // Never do lazy parsing in modules. If we want to support this in the | 778 // Never do lazy parsing in modules. If we want to support this in the |
778 // future, we must force context-allocation for all variables that are | 779 // future, we must force context-allocation for all variables that are |
779 // declared at the module level but not MODULE-allocated. | 780 // declared at the module level but not MODULE-allocated. |
780 parsing_mode = PARSE_EAGERLY; | 781 parsing_mode = PARSE_EAGERLY; |
781 } | 782 } |
782 | 783 |
783 DeclarationScope* scope = outer->AsDeclarationScope(); | 784 DeclarationScope* scope = outer->AsDeclarationScope(); |
784 | 785 |
785 scope->set_start_position(0); | 786 scope->set_start_position(0); |
786 | 787 |
787 // Enter 'scope' with the given parsing mode. | 788 // Enter 'scope' with the given parsing mode. |
788 ParsingModeScope parsing_mode_scope(this, parsing_mode); | 789 ParsingModeScope parsing_mode_scope(this, parsing_mode); |
789 FunctionState function_state(&function_state_, &scope_state_, scope); | 790 FunctionState function_state(&function_state_, &scope_state_, scope); |
790 | 791 |
791 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); | 792 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); |
792 bool ok = true; | 793 bool ok = true; |
793 int beg_pos = scanner()->location().beg_pos; | 794 int beg_pos = scanner()->location().beg_pos; |
794 parsing_module_ = info->is_module(); | |
795 if (parsing_module_) { | 795 if (parsing_module_) { |
796 // Declare the special module parameter. | 796 // Declare the special module parameter. |
797 auto name = ast_value_factory()->empty_string(); | 797 auto name = ast_value_factory()->empty_string(); |
798 bool is_duplicate; | 798 bool is_duplicate; |
799 bool is_rest = false; | 799 bool is_rest = false; |
800 bool is_optional = false; | 800 bool is_optional = false; |
801 auto var = scope->DeclareParameter(name, VAR, is_optional, is_rest, | 801 auto var = scope->DeclareParameter(name, VAR, is_optional, is_rest, |
802 &is_duplicate, ast_value_factory()); | 802 &is_duplicate, ast_value_factory()); |
803 DCHECK(!is_duplicate); | 803 DCHECK(!is_duplicate); |
804 var->AllocateTo(VariableLocation::PARAMETER, 0); | 804 var->AllocateTo(VariableLocation::PARAMETER, 0); |
805 | 805 |
806 PrepareGeneratorVariables(&function_state); | |
807 Expression* initial_yield = | |
808 BuildInitialYield(kNoSourcePosition, kGeneratorFunction); | |
809 body->Add( | |
810 factory()->NewExpressionStatement(initial_yield, kNoSourcePosition), | |
811 zone()); | |
812 | |
806 ParseModuleItemList(body, &ok); | 813 ParseModuleItemList(body, &ok); |
807 ok = ok && | 814 ok = ok && |
808 module()->Validate(this->scope()->AsModuleScope(), | 815 module()->Validate(this->scope()->AsModuleScope(), |
809 &pending_error_handler_, zone()); | 816 &pending_error_handler_, zone()); |
810 } else { | 817 } else { |
811 // Don't count the mode in the use counters--give the program a chance | 818 // Don't count the mode in the use counters--give the program a chance |
812 // to enable script-wide strict mode below. | 819 // to enable script-wide strict mode below. |
813 this->scope()->SetLanguageMode(info->language_mode()); | 820 this->scope()->SetLanguageMode(info->language_mode()); |
814 ParseStatementList(body, Token::EOS, &ok); | 821 ParseStatementList(body, Token::EOS, &ok); |
815 } | 822 } |
(...skipping 26 matching lines...) Expand all Loading... | |
842 ReportMessage(MessageTemplate::kSingleFunctionLiteral); | 849 ReportMessage(MessageTemplate::kSingleFunctionLiteral); |
843 ok = false; | 850 ok = false; |
844 } | 851 } |
845 } | 852 } |
846 | 853 |
847 if (ok) { | 854 if (ok) { |
848 RewriteDestructuringAssignments(); | 855 RewriteDestructuringAssignments(); |
849 int parameter_count = parsing_module_ ? 1 : 0; | 856 int parameter_count = parsing_module_ ? 1 : 0; |
850 result = factory()->NewScriptOrEvalFunctionLiteral( | 857 result = factory()->NewScriptOrEvalFunctionLiteral( |
851 scope, body, function_state.materialized_literal_count(), | 858 scope, body, function_state.materialized_literal_count(), |
852 function_state.expected_property_count(), parameter_count); | 859 function_state.expected_property_count(), parameter_count, |
860 function_state.kind()); | |
853 } | 861 } |
854 } | 862 } |
855 | 863 |
856 // Make sure the target stack is empty. | 864 // Make sure the target stack is empty. |
857 DCHECK(target_stack_ == NULL); | 865 DCHECK(target_stack_ == NULL); |
858 | 866 |
859 return result; | 867 return result; |
860 } | 868 } |
861 | 869 |
862 | 870 |
(...skipping 1714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2577 | 2585 |
2578 for (const auto p : parameters.params) { | 2586 for (const auto p : parameters.params) { |
2579 if (p.pattern != nullptr) reindexer.Reindex(p.pattern); | 2587 if (p.pattern != nullptr) reindexer.Reindex(p.pattern); |
2580 if (p.initializer != nullptr) reindexer.Reindex(p.initializer); | 2588 if (p.initializer != nullptr) reindexer.Reindex(p.initializer); |
2581 } | 2589 } |
2582 | 2590 |
2583 DCHECK(reindexer.count() <= function_state_->materialized_literal_count()); | 2591 DCHECK(reindexer.count() <= function_state_->materialized_literal_count()); |
2584 } | 2592 } |
2585 } | 2593 } |
2586 | 2594 |
2595 void Parser::PrepareGeneratorVariables(FunctionState* function_state) { | |
2596 // For generators, allocating variables in contexts is currently a win | |
2597 // because it minimizes the work needed to suspend and resume an | |
2598 // activation. The machine code produced for generators (by full-codegen) | |
2599 // relies on this forced context allocation, but not in an essential way. | |
2600 this->scope()->ForceContextAllocation(); | |
adamk
2016/09/27 23:26:12
Nit: remove "this->"
| |
2601 | |
2602 // Calling a generator returns a generator object. That object is stored | |
2603 // in a temporary variable, a definition that is used by "yield" | |
2604 // expressions. This also marks the FunctionState as a generator. | |
2605 Variable* temp = | |
2606 NewTemporary(ast_value_factory()->dot_generator_object_string()); | |
2607 function_state->set_generator_object_variable(temp); | |
2608 } | |
2587 | 2609 |
2588 FunctionLiteral* Parser::ParseFunctionLiteral( | 2610 FunctionLiteral* Parser::ParseFunctionLiteral( |
2589 const AstRawString* function_name, Scanner::Location function_name_location, | 2611 const AstRawString* function_name, Scanner::Location function_name_location, |
2590 FunctionNameValidity function_name_validity, FunctionKind kind, | 2612 FunctionNameValidity function_name_validity, FunctionKind kind, |
2591 int function_token_pos, FunctionLiteral::FunctionType function_type, | 2613 int function_token_pos, FunctionLiteral::FunctionType function_type, |
2592 LanguageMode language_mode, bool* ok) { | 2614 LanguageMode language_mode, bool* ok) { |
2593 // Function :: | 2615 // Function :: |
2594 // '(' FormalParameterList? ')' '{' FunctionBody '}' | 2616 // '(' FormalParameterList? ')' '{' FunctionBody '}' |
2595 // | 2617 // |
2596 // Getter :: | 2618 // Getter :: |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2721 } else { | 2743 } else { |
2722 DCHECK(main_scope->zone() != scope->zone()); | 2744 DCHECK(main_scope->zone() != scope->zone()); |
2723 } | 2745 } |
2724 | 2746 |
2725 FunctionState function_state(&function_state_, &scope_state_, scope); | 2747 FunctionState function_state(&function_state_, &scope_state_, scope); |
2726 #ifdef DEBUG | 2748 #ifdef DEBUG |
2727 scope->SetScopeName(function_name); | 2749 scope->SetScopeName(function_name); |
2728 #endif | 2750 #endif |
2729 ExpressionClassifier formals_classifier(this, &duplicate_finder); | 2751 ExpressionClassifier formals_classifier(this, &duplicate_finder); |
2730 | 2752 |
2731 if (is_generator) { | 2753 if (is_generator) PrepareGeneratorVariables(&function_state); |
2732 // For generators, allocating variables in contexts is currently a win | |
2733 // because it minimizes the work needed to suspend and resume an | |
2734 // activation. The machine code produced for generators (by full-codegen) | |
2735 // relies on this forced context allocation, but not in an essential way. | |
2736 this->scope()->ForceContextAllocation(); | |
2737 | |
2738 // Calling a generator returns a generator object. That object is stored | |
2739 // in a temporary variable, a definition that is used by "yield" | |
2740 // expressions. This also marks the FunctionState as a generator. | |
2741 Variable* temp = | |
2742 NewTemporary(ast_value_factory()->dot_generator_object_string()); | |
2743 function_state.set_generator_object_variable(temp); | |
2744 } | |
2745 | 2754 |
2746 Expect(Token::LPAREN, CHECK_OK); | 2755 Expect(Token::LPAREN, CHECK_OK); |
2747 int start_position = scanner()->location().beg_pos; | 2756 int start_position = scanner()->location().beg_pos; |
2748 this->scope()->set_start_position(start_position); | 2757 this->scope()->set_start_position(start_position); |
2749 ParserFormalParameters formals(scope); | 2758 ParserFormalParameters formals(scope); |
2750 ParseFormalParameterList(&formals, CHECK_OK); | 2759 ParseFormalParameterList(&formals, CHECK_OK); |
2751 arity = formals.Arity(); | 2760 arity = formals.Arity(); |
2752 Expect(Token::RPAREN, CHECK_OK); | 2761 Expect(Token::RPAREN, CHECK_OK); |
2753 int formals_end_position = scanner()->location().end_pos; | 2762 int formals_end_position = scanner()->location().end_pos; |
2754 | 2763 |
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3181 // paths which may be the first to access the Promise temporary. Whichever | 3190 // paths which may be the first to access the Promise temporary. Whichever |
3182 // comes first should create it and stash it in the FunctionState. | 3191 // comes first should create it and stash it in the FunctionState. |
3183 Variable* promise = function_state_->promise_variable(); | 3192 Variable* promise = function_state_->promise_variable(); |
3184 if (function_state_->promise_variable() == nullptr) { | 3193 if (function_state_->promise_variable() == nullptr) { |
3185 promise = scope()->NewTemporary(ast_value_factory()->empty_string()); | 3194 promise = scope()->NewTemporary(ast_value_factory()->empty_string()); |
3186 function_state_->set_promise_variable(promise); | 3195 function_state_->set_promise_variable(promise); |
3187 } | 3196 } |
3188 return promise; | 3197 return promise; |
3189 } | 3198 } |
3190 | 3199 |
3200 Expression* Parser::BuildInitialYield(int pos, FunctionKind kind) { | |
3201 Expression* allocation = BuildCreateJSGeneratorObject(pos, kind); | |
3202 VariableProxy* init_proxy = | |
3203 factory()->NewVariableProxy(function_state_->generator_object_variable()); | |
3204 Assignment* assignment = factory()->NewAssignment( | |
3205 Token::INIT, init_proxy, allocation, kNoSourcePosition); | |
3206 VariableProxy* get_proxy = | |
3207 factory()->NewVariableProxy(function_state_->generator_object_variable()); | |
3208 // The position of the yield is important for reporting the exception | |
3209 // caused by calling the .throw method on a generator suspended at the | |
3210 // initial yield (i.e. right after generator instantiation). | |
3211 return factory()->NewYield(get_proxy, assignment, scope()->start_position(), | |
3212 Yield::kOnExceptionThrow); | |
3213 } | |
3214 | |
3191 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( | 3215 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( |
3192 const AstRawString* function_name, int pos, | 3216 const AstRawString* function_name, int pos, |
3193 const ParserFormalParameters& parameters, FunctionKind kind, | 3217 const ParserFormalParameters& parameters, FunctionKind kind, |
3194 FunctionLiteral::FunctionType function_type, bool* ok) { | 3218 FunctionLiteral::FunctionType function_type, bool* ok) { |
3195 // Everything inside an eagerly parsed function will be parsed eagerly (see | 3219 // Everything inside an eagerly parsed function will be parsed eagerly (see |
3196 // comment above). Lazy inner functions are handled separately and they won't | 3220 // comment above). Lazy inner functions are handled separately and they won't |
3197 // require the mode to be PARSE_LAZILY (see ParseFunctionLiteral). | 3221 // require the mode to be PARSE_LAZILY (see ParseFunctionLiteral). |
3198 // TODO(marja): Refactor parsing modes: remove this. | 3222 // TODO(marja): Refactor parsing modes: remove this. |
3199 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); | 3223 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); |
3200 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); | 3224 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3233 // finally { %_GeneratorClose(generator) } | 3257 // finally { %_GeneratorClose(generator) } |
3234 // | 3258 // |
3235 // - InitialYield yields the actual generator object. | 3259 // - InitialYield yields the actual generator object. |
3236 // - Any return statement inside the body will have its argument wrapped | 3260 // - Any return statement inside the body will have its argument wrapped |
3237 // in a "done" iterator result object. | 3261 // in a "done" iterator result object. |
3238 // - If the generator terminates for whatever reason, we must close it. | 3262 // - If the generator terminates for whatever reason, we must close it. |
3239 // Hence the finally clause. | 3263 // Hence the finally clause. |
3240 | 3264 |
3241 Block* try_block = | 3265 Block* try_block = |
3242 factory()->NewBlock(nullptr, 3, false, kNoSourcePosition); | 3266 factory()->NewBlock(nullptr, 3, false, kNoSourcePosition); |
3243 | 3267 Expression* initial_yield = BuildInitialYield(pos, kind); |
3244 { | 3268 try_block->statements()->Add( |
3245 Expression* allocation = BuildCreateJSGeneratorObject(pos, kind); | 3269 factory()->NewExpressionStatement(initial_yield, kNoSourcePosition), |
3246 VariableProxy* init_proxy = factory()->NewVariableProxy( | 3270 zone()); |
3247 function_state_->generator_object_variable()); | |
3248 Assignment* assignment = factory()->NewAssignment( | |
3249 Token::INIT, init_proxy, allocation, kNoSourcePosition); | |
3250 VariableProxy* get_proxy = factory()->NewVariableProxy( | |
3251 function_state_->generator_object_variable()); | |
3252 // The position of the yield is important for reporting the exception | |
3253 // caused by calling the .throw method on a generator suspended at the | |
3254 // initial yield (i.e. right after generator instantiation). | |
3255 Yield* yield = factory()->NewYield(get_proxy, assignment, | |
3256 scope()->start_position(), | |
3257 Yield::kOnExceptionThrow); | |
3258 try_block->statements()->Add( | |
3259 factory()->NewExpressionStatement(yield, kNoSourcePosition), | |
3260 zone()); | |
3261 } | |
3262 | |
3263 ParseStatementList(try_block->statements(), Token::RBRACE, CHECK_OK); | 3271 ParseStatementList(try_block->statements(), Token::RBRACE, CHECK_OK); |
3264 | 3272 |
3265 Statement* final_return = factory()->NewReturnStatement( | 3273 Statement* final_return = factory()->NewReturnStatement( |
3266 BuildIteratorResult(nullptr, true), kNoSourcePosition); | 3274 BuildIteratorResult(nullptr, true), kNoSourcePosition); |
3267 try_block->statements()->Add(final_return, zone()); | 3275 try_block->statements()->Add(final_return, zone()); |
3268 | 3276 |
3269 Block* finally_block = | 3277 Block* finally_block = |
3270 factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); | 3278 factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); |
3271 ZoneList<Expression*>* args = | 3279 ZoneList<Expression*>* args = |
3272 new (zone()) ZoneList<Expression*>(1, zone()); | 3280 new (zone()) ZoneList<Expression*>(1, zone()); |
(...skipping 2289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5562 | 5570 |
5563 return final_loop; | 5571 return final_loop; |
5564 } | 5572 } |
5565 | 5573 |
5566 #undef CHECK_OK | 5574 #undef CHECK_OK |
5567 #undef CHECK_OK_VOID | 5575 #undef CHECK_OK_VOID |
5568 #undef CHECK_FAILED | 5576 #undef CHECK_FAILED |
5569 | 5577 |
5570 } // namespace internal | 5578 } // namespace internal |
5571 } // namespace v8 | 5579 } // namespace v8 |
OLD | NEW |