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

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

Issue 2375793002: Reland: [modules] Properly initialize declared variables. (Closed)
Patch Set: 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 748 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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