| 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 750 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 761 // via ParseInfo, and also not pass it forward. | 761 // via ParseInfo, and also not pass it forward. |
| 762 DCHECK_NULL(scope_state_); | 762 DCHECK_NULL(scope_state_); |
| 763 DCHECK_NULL(target_stack_); | 763 DCHECK_NULL(target_stack_); |
| 764 | 764 |
| 765 Mode parsing_mode = allow_lazy() ? PARSE_LAZILY : PARSE_EAGERLY; | 765 Mode parsing_mode = allow_lazy() ? PARSE_LAZILY : PARSE_EAGERLY; |
| 766 | 766 |
| 767 FunctionLiteral* result = NULL; | 767 FunctionLiteral* result = NULL; |
| 768 { | 768 { |
| 769 Scope* outer = original_scope_; | 769 Scope* outer = original_scope_; |
| 770 DCHECK_NOT_NULL(outer); | 770 DCHECK_NOT_NULL(outer); |
| 771 parsing_module_ = info->is_module(); | |
| 772 if (info->is_eval()) { | 771 if (info->is_eval()) { |
| 773 if (!outer->is_script_scope() || is_strict(info->language_mode())) { | 772 if (!outer->is_script_scope() || is_strict(info->language_mode())) { |
| 774 parsing_mode = PARSE_EAGERLY; | 773 parsing_mode = PARSE_EAGERLY; |
| 775 } | 774 } |
| 776 outer = NewEvalScope(outer); | 775 outer = NewEvalScope(outer); |
| 777 } else if (parsing_module_) { | 776 } else if (info->is_module()) { |
| 778 DCHECK_EQ(outer, info->script_scope()); | 777 DCHECK_EQ(outer, info->script_scope()); |
| 779 outer = NewModuleScope(info->script_scope()); | 778 outer = NewModuleScope(info->script_scope()); |
| 780 // Never do lazy parsing in modules. If we want to support this in the | 779 // Never do lazy parsing in modules. If we want to support this in the |
| 781 // future, we must force context-allocation for all variables that are | 780 // future, we must force context-allocation for all variables that are |
| 782 // declared at the module level but not MODULE-allocated. | 781 // declared at the module level but not MODULE-allocated. |
| 783 parsing_mode = PARSE_EAGERLY; | 782 parsing_mode = PARSE_EAGERLY; |
| 784 } | 783 } |
| 785 | 784 |
| 786 DeclarationScope* scope = outer->AsDeclarationScope(); | 785 DeclarationScope* scope = outer->AsDeclarationScope(); |
| 787 | 786 |
| 788 scope->set_start_position(0); | 787 scope->set_start_position(0); |
| 789 | 788 |
| 790 // Enter 'scope' with the given parsing mode. | 789 // Enter 'scope' with the given parsing mode. |
| 791 ParsingModeScope parsing_mode_scope(this, parsing_mode); | 790 ParsingModeScope parsing_mode_scope(this, parsing_mode); |
| 792 FunctionState function_state(&function_state_, &scope_state_, scope); | 791 FunctionState function_state(&function_state_, &scope_state_, scope); |
| 793 | 792 |
| 794 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); | 793 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); |
| 795 bool ok = true; | 794 bool ok = true; |
| 796 int beg_pos = scanner()->location().beg_pos; | 795 int beg_pos = scanner()->location().beg_pos; |
| 796 parsing_module_ = info->is_module(); |
| 797 if (parsing_module_) { | 797 if (parsing_module_) { |
| 798 // Declare the special module parameter. | 798 // Declare the special module parameter. |
| 799 auto name = ast_value_factory()->empty_string(); | 799 auto name = ast_value_factory()->empty_string(); |
| 800 bool is_duplicate; | 800 bool is_duplicate; |
| 801 bool is_rest = false; | 801 bool is_rest = false; |
| 802 bool is_optional = false; | 802 bool is_optional = false; |
| 803 auto var = scope->DeclareParameter(name, VAR, is_optional, is_rest, | 803 auto var = scope->DeclareParameter(name, VAR, is_optional, is_rest, |
| 804 &is_duplicate, ast_value_factory()); | 804 &is_duplicate, ast_value_factory()); |
| 805 DCHECK(!is_duplicate); | 805 DCHECK(!is_duplicate); |
| 806 var->AllocateTo(VariableLocation::PARAMETER, 0); | 806 var->AllocateTo(VariableLocation::PARAMETER, 0); |
| 807 | 807 |
| 808 PrepareGeneratorVariables(&function_state); | |
| 809 Expression* initial_yield = | |
| 810 BuildInitialYield(kNoSourcePosition, kGeneratorFunction); | |
| 811 body->Add( | |
| 812 factory()->NewExpressionStatement(initial_yield, kNoSourcePosition), | |
| 813 zone()); | |
| 814 | |
| 815 ParseModuleItemList(body, &ok); | 808 ParseModuleItemList(body, &ok); |
| 816 ok = ok && | 809 ok = ok && |
| 817 module()->Validate(this->scope()->AsModuleScope(), | 810 module()->Validate(this->scope()->AsModuleScope(), |
| 818 &pending_error_handler_, zone()); | 811 &pending_error_handler_, zone()); |
| 819 } else { | 812 } else { |
| 820 // Don't count the mode in the use counters--give the program a chance | 813 // Don't count the mode in the use counters--give the program a chance |
| 821 // to enable script-wide strict mode below. | 814 // to enable script-wide strict mode below. |
| 822 this->scope()->SetLanguageMode(info->language_mode()); | 815 this->scope()->SetLanguageMode(info->language_mode()); |
| 823 ParseStatementList(body, Token::EOS, &ok); | 816 ParseStatementList(body, Token::EOS, &ok); |
| 824 } | 817 } |
| (...skipping 1704 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2529 | 2522 |
| 2530 for (const auto p : parameters.params) { | 2523 for (const auto p : parameters.params) { |
| 2531 if (p.pattern != nullptr) reindexer.Reindex(p.pattern); | 2524 if (p.pattern != nullptr) reindexer.Reindex(p.pattern); |
| 2532 if (p.initializer != nullptr) reindexer.Reindex(p.initializer); | 2525 if (p.initializer != nullptr) reindexer.Reindex(p.initializer); |
| 2533 } | 2526 } |
| 2534 | 2527 |
| 2535 DCHECK(reindexer.count() <= function_state_->materialized_literal_count()); | 2528 DCHECK(reindexer.count() <= function_state_->materialized_literal_count()); |
| 2536 } | 2529 } |
| 2537 } | 2530 } |
| 2538 | 2531 |
| 2539 void Parser::PrepareGeneratorVariables(FunctionState* function_state) { | |
| 2540 // For generators, allocating variables in contexts is currently a win | |
| 2541 // because it minimizes the work needed to suspend and resume an | |
| 2542 // activation. The machine code produced for generators (by full-codegen) | |
| 2543 // relies on this forced context allocation, but not in an essential way. | |
| 2544 scope()->ForceContextAllocation(); | |
| 2545 | |
| 2546 // Calling a generator returns a generator object. That object is stored | |
| 2547 // in a temporary variable, a definition that is used by "yield" | |
| 2548 // expressions. | |
| 2549 Variable* temp = | |
| 2550 NewTemporary(ast_value_factory()->dot_generator_object_string()); | |
| 2551 function_state->set_generator_object_variable(temp); | |
| 2552 } | |
| 2553 | 2532 |
| 2554 FunctionLiteral* Parser::ParseFunctionLiteral( | 2533 FunctionLiteral* Parser::ParseFunctionLiteral( |
| 2555 const AstRawString* function_name, Scanner::Location function_name_location, | 2534 const AstRawString* function_name, Scanner::Location function_name_location, |
| 2556 FunctionNameValidity function_name_validity, FunctionKind kind, | 2535 FunctionNameValidity function_name_validity, FunctionKind kind, |
| 2557 int function_token_pos, FunctionLiteral::FunctionType function_type, | 2536 int function_token_pos, FunctionLiteral::FunctionType function_type, |
| 2558 LanguageMode language_mode, bool* ok) { | 2537 LanguageMode language_mode, bool* ok) { |
| 2559 // Function :: | 2538 // Function :: |
| 2560 // '(' FormalParameterList? ')' '{' FunctionBody '}' | 2539 // '(' FormalParameterList? ')' '{' FunctionBody '}' |
| 2561 // | 2540 // |
| 2562 // Getter :: | 2541 // Getter :: |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2664 bool should_be_used_once_hint = false; | 2643 bool should_be_used_once_hint = false; |
| 2665 bool has_duplicate_parameters; | 2644 bool has_duplicate_parameters; |
| 2666 | 2645 |
| 2667 FunctionState function_state(&function_state_, &scope_state_, scope); | 2646 FunctionState function_state(&function_state_, &scope_state_, scope); |
| 2668 #ifdef DEBUG | 2647 #ifdef DEBUG |
| 2669 scope->SetScopeName(function_name); | 2648 scope->SetScopeName(function_name); |
| 2670 #endif | 2649 #endif |
| 2671 | 2650 |
| 2672 ExpressionClassifier formals_classifier(this, &duplicate_finder); | 2651 ExpressionClassifier formals_classifier(this, &duplicate_finder); |
| 2673 | 2652 |
| 2674 if (is_generator) PrepareGeneratorVariables(&function_state); | 2653 if (is_generator) { |
| 2654 // For generators, allocating variables in contexts is currently a win |
| 2655 // because it minimizes the work needed to suspend and resume an |
| 2656 // activation. The machine code produced for generators (by full-codegen) |
| 2657 // relies on this forced context allocation, but not in an essential way. |
| 2658 this->scope()->ForceContextAllocation(); |
| 2659 |
| 2660 // Calling a generator returns a generator object. That object is stored |
| 2661 // in a temporary variable, a definition that is used by "yield" |
| 2662 // expressions. This also marks the FunctionState as a generator. |
| 2663 Variable* temp = |
| 2664 NewTemporary(ast_value_factory()->dot_generator_object_string()); |
| 2665 function_state.set_generator_object_variable(temp); |
| 2666 } |
| 2675 | 2667 |
| 2676 Expect(Token::LPAREN, CHECK_OK); | 2668 Expect(Token::LPAREN, CHECK_OK); |
| 2677 int start_position = scanner()->location().beg_pos; | 2669 int start_position = scanner()->location().beg_pos; |
| 2678 this->scope()->set_start_position(start_position); | 2670 this->scope()->set_start_position(start_position); |
| 2679 ParserFormalParameters formals(scope); | 2671 ParserFormalParameters formals(scope); |
| 2680 ParseFormalParameterList(&formals, CHECK_OK); | 2672 ParseFormalParameterList(&formals, CHECK_OK); |
| 2681 arity = formals.Arity(); | 2673 arity = formals.Arity(); |
| 2682 Expect(Token::RPAREN, CHECK_OK); | 2674 Expect(Token::RPAREN, CHECK_OK); |
| 2683 int formals_end_position = scanner()->location().end_pos; | 2675 int formals_end_position = scanner()->location().end_pos; |
| 2684 | 2676 |
| (...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3125 // paths which may be the first to access the Promise temporary. Whichever | 3117 // paths which may be the first to access the Promise temporary. Whichever |
| 3126 // comes first should create it and stash it in the FunctionState. | 3118 // comes first should create it and stash it in the FunctionState. |
| 3127 Variable* promise = function_state_->promise_variable(); | 3119 Variable* promise = function_state_->promise_variable(); |
| 3128 if (function_state_->promise_variable() == nullptr) { | 3120 if (function_state_->promise_variable() == nullptr) { |
| 3129 promise = scope()->NewTemporary(ast_value_factory()->empty_string()); | 3121 promise = scope()->NewTemporary(ast_value_factory()->empty_string()); |
| 3130 function_state_->set_promise_variable(promise); | 3122 function_state_->set_promise_variable(promise); |
| 3131 } | 3123 } |
| 3132 return promise; | 3124 return promise; |
| 3133 } | 3125 } |
| 3134 | 3126 |
| 3135 Expression* Parser::BuildInitialYield(int pos, FunctionKind kind) { | |
| 3136 Expression* allocation = BuildCreateJSGeneratorObject(pos, kind); | |
| 3137 VariableProxy* init_proxy = | |
| 3138 factory()->NewVariableProxy(function_state_->generator_object_variable()); | |
| 3139 Assignment* assignment = factory()->NewAssignment( | |
| 3140 Token::INIT, init_proxy, allocation, kNoSourcePosition); | |
| 3141 VariableProxy* get_proxy = | |
| 3142 factory()->NewVariableProxy(function_state_->generator_object_variable()); | |
| 3143 // The position of the yield is important for reporting the exception | |
| 3144 // caused by calling the .throw method on a generator suspended at the | |
| 3145 // initial yield (i.e. right after generator instantiation). | |
| 3146 return factory()->NewYield(get_proxy, assignment, scope()->start_position(), | |
| 3147 Yield::kOnExceptionThrow); | |
| 3148 } | |
| 3149 | |
| 3150 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( | 3127 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( |
| 3151 const AstRawString* function_name, int pos, | 3128 const AstRawString* function_name, int pos, |
| 3152 const ParserFormalParameters& parameters, FunctionKind kind, | 3129 const ParserFormalParameters& parameters, FunctionKind kind, |
| 3153 FunctionLiteral::FunctionType function_type, bool* ok) { | 3130 FunctionLiteral::FunctionType function_type, bool* ok) { |
| 3154 // Everything inside an eagerly parsed function will be parsed eagerly (see | 3131 // Everything inside an eagerly parsed function will be parsed eagerly (see |
| 3155 // comment above). Lazy inner functions are handled separately and they won't | 3132 // comment above). Lazy inner functions are handled separately and they won't |
| 3156 // require the mode to be PARSE_LAZILY (see ParseFunctionLiteral). | 3133 // require the mode to be PARSE_LAZILY (see ParseFunctionLiteral). |
| 3157 // TODO(marja): Refactor parsing modes: remove this. | 3134 // TODO(marja): Refactor parsing modes: remove this. |
| 3158 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); | 3135 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); |
| 3159 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); | 3136 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3192 // finally { %_GeneratorClose(generator) } | 3169 // finally { %_GeneratorClose(generator) } |
| 3193 // | 3170 // |
| 3194 // - InitialYield yields the actual generator object. | 3171 // - InitialYield yields the actual generator object. |
| 3195 // - Any return statement inside the body will have its argument wrapped | 3172 // - Any return statement inside the body will have its argument wrapped |
| 3196 // in a "done" iterator result object. | 3173 // in a "done" iterator result object. |
| 3197 // - If the generator terminates for whatever reason, we must close it. | 3174 // - If the generator terminates for whatever reason, we must close it. |
| 3198 // Hence the finally clause. | 3175 // Hence the finally clause. |
| 3199 | 3176 |
| 3200 Block* try_block = | 3177 Block* try_block = |
| 3201 factory()->NewBlock(nullptr, 3, false, kNoSourcePosition); | 3178 factory()->NewBlock(nullptr, 3, false, kNoSourcePosition); |
| 3202 Expression* initial_yield = BuildInitialYield(pos, kind); | 3179 |
| 3203 try_block->statements()->Add( | 3180 { |
| 3204 factory()->NewExpressionStatement(initial_yield, kNoSourcePosition), | 3181 Expression* allocation = BuildCreateJSGeneratorObject(pos, kind); |
| 3205 zone()); | 3182 VariableProxy* init_proxy = factory()->NewVariableProxy( |
| 3183 function_state_->generator_object_variable()); |
| 3184 Assignment* assignment = factory()->NewAssignment( |
| 3185 Token::INIT, init_proxy, allocation, kNoSourcePosition); |
| 3186 VariableProxy* get_proxy = factory()->NewVariableProxy( |
| 3187 function_state_->generator_object_variable()); |
| 3188 // The position of the yield is important for reporting the exception |
| 3189 // caused by calling the .throw method on a generator suspended at the |
| 3190 // initial yield (i.e. right after generator instantiation). |
| 3191 Yield* yield = factory()->NewYield(get_proxy, assignment, |
| 3192 scope()->start_position(), |
| 3193 Yield::kOnExceptionThrow); |
| 3194 try_block->statements()->Add( |
| 3195 factory()->NewExpressionStatement(yield, kNoSourcePosition), |
| 3196 zone()); |
| 3197 } |
| 3198 |
| 3206 ParseStatementList(try_block->statements(), Token::RBRACE, CHECK_OK); | 3199 ParseStatementList(try_block->statements(), Token::RBRACE, CHECK_OK); |
| 3207 | 3200 |
| 3208 Statement* final_return = factory()->NewReturnStatement( | 3201 Statement* final_return = factory()->NewReturnStatement( |
| 3209 BuildIteratorResult(nullptr, true), kNoSourcePosition); | 3202 BuildIteratorResult(nullptr, true), kNoSourcePosition); |
| 3210 try_block->statements()->Add(final_return, zone()); | 3203 try_block->statements()->Add(final_return, zone()); |
| 3211 | 3204 |
| 3212 Block* finally_block = | 3205 Block* finally_block = |
| 3213 factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); | 3206 factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); |
| 3214 ZoneList<Expression*>* args = | 3207 ZoneList<Expression*>* args = |
| 3215 new (zone()) ZoneList<Expression*>(1, zone()); | 3208 new (zone()) ZoneList<Expression*>(1, zone()); |
| (...skipping 2247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5463 | 5456 |
| 5464 return final_loop; | 5457 return final_loop; |
| 5465 } | 5458 } |
| 5466 | 5459 |
| 5467 #undef CHECK_OK | 5460 #undef CHECK_OK |
| 5468 #undef CHECK_OK_VOID | 5461 #undef CHECK_OK_VOID |
| 5469 #undef CHECK_FAILED | 5462 #undef CHECK_FAILED |
| 5470 | 5463 |
| 5471 } // namespace internal | 5464 } // namespace internal |
| 5472 } // namespace v8 | 5465 } // namespace v8 |
| OLD | NEW |