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

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

Issue 2375793002: Reland: [modules] Properly initialize declared variables. (Closed)
Patch Set: Update CompilerHints. Created 4 years, 2 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
« no previous file with comments | « src/parsing/parser.h ('k') | test/cctest/interpreter/bytecode_expectations/CallRuntime.golden » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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();
771 if (info->is_eval()) { 772 if (info->is_eval()) {
772 if (!outer->is_script_scope() || is_strict(info->language_mode())) { 773 if (!outer->is_script_scope() || is_strict(info->language_mode())) {
773 parsing_mode = PARSE_EAGERLY; 774 parsing_mode = PARSE_EAGERLY;
774 } 775 }
775 outer = NewEvalScope(outer); 776 outer = NewEvalScope(outer);
776 } else if (info->is_module()) { 777 } else if (parsing_module_) {
777 DCHECK_EQ(outer, info->script_scope()); 778 DCHECK_EQ(outer, info->script_scope());
778 outer = NewModuleScope(info->script_scope()); 779 outer = NewModuleScope(info->script_scope());
779 // Never do lazy parsing in modules. If we want to support this in the 780 // Never do lazy parsing in modules. If we want to support this in the
780 // future, we must force context-allocation for all variables that are 781 // future, we must force context-allocation for all variables that are
781 // declared at the module level but not MODULE-allocated. 782 // declared at the module level but not MODULE-allocated.
782 parsing_mode = PARSE_EAGERLY; 783 parsing_mode = PARSE_EAGERLY;
783 } 784 }
784 785
785 DeclarationScope* scope = outer->AsDeclarationScope(); 786 DeclarationScope* scope = outer->AsDeclarationScope();
786 787
787 scope->set_start_position(0); 788 scope->set_start_position(0);
788 789
789 // Enter 'scope' with the given parsing mode. 790 // Enter 'scope' with the given parsing mode.
790 ParsingModeScope parsing_mode_scope(this, parsing_mode); 791 ParsingModeScope parsing_mode_scope(this, parsing_mode);
791 FunctionState function_state(&function_state_, &scope_state_, scope); 792 FunctionState function_state(&function_state_, &scope_state_, scope);
792 793
793 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); 794 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
794 bool ok = true; 795 bool ok = true;
795 int beg_pos = scanner()->location().beg_pos; 796 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
808 ParseModuleItemList(body, &ok); 815 ParseModuleItemList(body, &ok);
809 ok = ok && 816 ok = ok &&
810 module()->Validate(this->scope()->AsModuleScope(), 817 module()->Validate(this->scope()->AsModuleScope(),
811 &pending_error_handler_, zone()); 818 &pending_error_handler_, zone());
812 } else { 819 } else {
813 // Don't count the mode in the use counters--give the program a chance 820 // Don't count the mode in the use counters--give the program a chance
814 // to enable script-wide strict mode below. 821 // to enable script-wide strict mode below.
815 this->scope()->SetLanguageMode(info->language_mode()); 822 this->scope()->SetLanguageMode(info->language_mode());
816 ParseStatementList(body, Token::EOS, &ok); 823 ParseStatementList(body, Token::EOS, &ok);
817 } 824 }
(...skipping 1704 matching lines...) Expand 10 before | Expand all | Expand 10 after
2522 2529
2523 for (const auto p : parameters.params) { 2530 for (const auto p : parameters.params) {
2524 if (p.pattern != nullptr) reindexer.Reindex(p.pattern); 2531 if (p.pattern != nullptr) reindexer.Reindex(p.pattern);
2525 if (p.initializer != nullptr) reindexer.Reindex(p.initializer); 2532 if (p.initializer != nullptr) reindexer.Reindex(p.initializer);
2526 } 2533 }
2527 2534
2528 DCHECK(reindexer.count() <= function_state_->materialized_literal_count()); 2535 DCHECK(reindexer.count() <= function_state_->materialized_literal_count());
2529 } 2536 }
2530 } 2537 }
2531 2538
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 }
2532 2553
2533 FunctionLiteral* Parser::ParseFunctionLiteral( 2554 FunctionLiteral* Parser::ParseFunctionLiteral(
2534 const AstRawString* function_name, Scanner::Location function_name_location, 2555 const AstRawString* function_name, Scanner::Location function_name_location,
2535 FunctionNameValidity function_name_validity, FunctionKind kind, 2556 FunctionNameValidity function_name_validity, FunctionKind kind,
2536 int function_token_pos, FunctionLiteral::FunctionType function_type, 2557 int function_token_pos, FunctionLiteral::FunctionType function_type,
2537 LanguageMode language_mode, bool* ok) { 2558 LanguageMode language_mode, bool* ok) {
2538 // Function :: 2559 // Function ::
2539 // '(' FormalParameterList? ')' '{' FunctionBody '}' 2560 // '(' FormalParameterList? ')' '{' FunctionBody '}'
2540 // 2561 //
2541 // Getter :: 2562 // Getter ::
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
2643 bool should_be_used_once_hint = false; 2664 bool should_be_used_once_hint = false;
2644 bool has_duplicate_parameters; 2665 bool has_duplicate_parameters;
2645 2666
2646 FunctionState function_state(&function_state_, &scope_state_, scope); 2667 FunctionState function_state(&function_state_, &scope_state_, scope);
2647 #ifdef DEBUG 2668 #ifdef DEBUG
2648 scope->SetScopeName(function_name); 2669 scope->SetScopeName(function_name);
2649 #endif 2670 #endif
2650 2671
2651 ExpressionClassifier formals_classifier(this, &duplicate_finder); 2672 ExpressionClassifier formals_classifier(this, &duplicate_finder);
2652 2673
2653 if (is_generator) { 2674 if (is_generator) PrepareGeneratorVariables(&function_state);
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 }
2667 2675
2668 Expect(Token::LPAREN, CHECK_OK); 2676 Expect(Token::LPAREN, CHECK_OK);
2669 int start_position = scanner()->location().beg_pos; 2677 int start_position = scanner()->location().beg_pos;
2670 this->scope()->set_start_position(start_position); 2678 this->scope()->set_start_position(start_position);
2671 ParserFormalParameters formals(scope); 2679 ParserFormalParameters formals(scope);
2672 ParseFormalParameterList(&formals, CHECK_OK); 2680 ParseFormalParameterList(&formals, CHECK_OK);
2673 arity = formals.Arity(); 2681 arity = formals.Arity();
2674 Expect(Token::RPAREN, CHECK_OK); 2682 Expect(Token::RPAREN, CHECK_OK);
2675 int formals_end_position = scanner()->location().end_pos; 2683 int formals_end_position = scanner()->location().end_pos;
2676 2684
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after
3117 // paths which may be the first to access the Promise temporary. Whichever 3125 // paths which may be the first to access the Promise temporary. Whichever
3118 // comes first should create it and stash it in the FunctionState. 3126 // comes first should create it and stash it in the FunctionState.
3119 Variable* promise = function_state_->promise_variable(); 3127 Variable* promise = function_state_->promise_variable();
3120 if (function_state_->promise_variable() == nullptr) { 3128 if (function_state_->promise_variable() == nullptr) {
3121 promise = scope()->NewTemporary(ast_value_factory()->empty_string()); 3129 promise = scope()->NewTemporary(ast_value_factory()->empty_string());
3122 function_state_->set_promise_variable(promise); 3130 function_state_->set_promise_variable(promise);
3123 } 3131 }
3124 return promise; 3132 return promise;
3125 } 3133 }
3126 3134
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
3127 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( 3150 ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
3128 const AstRawString* function_name, int pos, 3151 const AstRawString* function_name, int pos,
3129 const ParserFormalParameters& parameters, FunctionKind kind, 3152 const ParserFormalParameters& parameters, FunctionKind kind,
3130 FunctionLiteral::FunctionType function_type, bool* ok) { 3153 FunctionLiteral::FunctionType function_type, bool* ok) {
3131 // Everything inside an eagerly parsed function will be parsed eagerly (see 3154 // Everything inside an eagerly parsed function will be parsed eagerly (see
3132 // comment above). Lazy inner functions are handled separately and they won't 3155 // comment above). Lazy inner functions are handled separately and they won't
3133 // require the mode to be PARSE_LAZILY (see ParseFunctionLiteral). 3156 // require the mode to be PARSE_LAZILY (see ParseFunctionLiteral).
3134 // TODO(marja): Refactor parsing modes: remove this. 3157 // TODO(marja): Refactor parsing modes: remove this.
3135 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); 3158 ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
3136 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); 3159 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone());
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3169 // finally { %_GeneratorClose(generator) } 3192 // finally { %_GeneratorClose(generator) }
3170 // 3193 //
3171 // - InitialYield yields the actual generator object. 3194 // - InitialYield yields the actual generator object.
3172 // - Any return statement inside the body will have its argument wrapped 3195 // - Any return statement inside the body will have its argument wrapped
3173 // in a "done" iterator result object. 3196 // in a "done" iterator result object.
3174 // - If the generator terminates for whatever reason, we must close it. 3197 // - If the generator terminates for whatever reason, we must close it.
3175 // Hence the finally clause. 3198 // Hence the finally clause.
3176 3199
3177 Block* try_block = 3200 Block* try_block =
3178 factory()->NewBlock(nullptr, 3, false, kNoSourcePosition); 3201 factory()->NewBlock(nullptr, 3, false, kNoSourcePosition);
3179 3202 Expression* initial_yield = BuildInitialYield(pos, kind);
3180 { 3203 try_block->statements()->Add(
3181 Expression* allocation = BuildCreateJSGeneratorObject(pos, kind); 3204 factory()->NewExpressionStatement(initial_yield, kNoSourcePosition),
3182 VariableProxy* init_proxy = factory()->NewVariableProxy( 3205 zone());
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
3199 ParseStatementList(try_block->statements(), Token::RBRACE, CHECK_OK); 3206 ParseStatementList(try_block->statements(), Token::RBRACE, CHECK_OK);
3200 3207
3201 Statement* final_return = factory()->NewReturnStatement( 3208 Statement* final_return = factory()->NewReturnStatement(
3202 BuildIteratorResult(nullptr, true), kNoSourcePosition); 3209 BuildIteratorResult(nullptr, true), kNoSourcePosition);
3203 try_block->statements()->Add(final_return, zone()); 3210 try_block->statements()->Add(final_return, zone());
3204 3211
3205 Block* finally_block = 3212 Block* finally_block =
3206 factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); 3213 factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
3207 ZoneList<Expression*>* args = 3214 ZoneList<Expression*>* args =
3208 new (zone()) ZoneList<Expression*>(1, zone()); 3215 new (zone()) ZoneList<Expression*>(1, zone());
(...skipping 2247 matching lines...) Expand 10 before | Expand all | Expand 10 after
5456 5463
5457 return final_loop; 5464 return final_loop;
5458 } 5465 }
5459 5466
5460 #undef CHECK_OK 5467 #undef CHECK_OK
5461 #undef CHECK_OK_VOID 5468 #undef CHECK_OK_VOID
5462 #undef CHECK_FAILED 5469 #undef CHECK_FAILED
5463 5470
5464 } // namespace internal 5471 } // namespace internal
5465 } // namespace v8 5472 } // namespace v8
OLDNEW
« no previous file with comments | « src/parsing/parser.h ('k') | test/cctest/interpreter/bytecode_expectations/CallRuntime.golden » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698