Chromium Code Reviews| Index: src/parsing/parser.cc |
| diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc |
| index 0fcc9ead7287f675cd5d19931fe8dcfddf032d0c..ccc7f849fcd16581914189b44914c58102ce8bb6 100644 |
| --- a/src/parsing/parser.cc |
| +++ b/src/parsing/parser.cc |
| @@ -766,12 +766,13 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { |
| { |
| Scope* outer = original_scope_; |
| DCHECK_NOT_NULL(outer); |
| + parsing_module_ = info->is_module(); |
| if (info->is_eval()) { |
| if (!outer->is_script_scope() || is_strict(info->language_mode())) { |
| parsing_mode = PARSE_EAGERLY; |
| } |
| outer = NewEvalScope(outer); |
| - } else if (info->is_module()) { |
| + } else if (parsing_module_) { |
| DCHECK_EQ(outer, info->script_scope()); |
| outer = NewModuleScope(info->script_scope()); |
| // Never do lazy parsing in modules. If we want to support this in the |
| @@ -791,7 +792,6 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { |
| ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); |
| bool ok = true; |
| int beg_pos = scanner()->location().beg_pos; |
| - parsing_module_ = info->is_module(); |
| if (parsing_module_) { |
| // Declare the special module parameter. |
| auto name = ast_value_factory()->empty_string(); |
| @@ -803,6 +803,13 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { |
| DCHECK(!is_duplicate); |
| var->AllocateTo(VariableLocation::PARAMETER, 0); |
| + PrepareGeneratorVariables(&function_state); |
| + Expression* initial_yield = |
| + BuildInitialYield(kNoSourcePosition, kGeneratorFunction); |
| + body->Add( |
| + factory()->NewExpressionStatement(initial_yield, kNoSourcePosition), |
| + zone()); |
| + |
| ParseModuleItemList(body, &ok); |
| ok = ok && |
| module()->Validate(this->scope()->AsModuleScope(), |
| @@ -849,7 +856,8 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { |
| int parameter_count = parsing_module_ ? 1 : 0; |
| result = factory()->NewScriptOrEvalFunctionLiteral( |
| scope, body, function_state.materialized_literal_count(), |
| - function_state.expected_property_count(), parameter_count); |
| + function_state.expected_property_count(), parameter_count, |
| + function_state.kind()); |
| } |
| } |
| @@ -2584,6 +2592,20 @@ void Parser::ReindexLiterals(const ParserFormalParameters& parameters) { |
| } |
| } |
| +void Parser::PrepareGeneratorVariables(FunctionState* function_state) { |
| + // For generators, allocating variables in contexts is currently a win |
| + // because it minimizes the work needed to suspend and resume an |
| + // activation. The machine code produced for generators (by full-codegen) |
| + // relies on this forced context allocation, but not in an essential way. |
| + this->scope()->ForceContextAllocation(); |
|
adamk
2016/09/27 23:26:12
Nit: remove "this->"
|
| + |
| + // Calling a generator returns a generator object. That object is stored |
| + // in a temporary variable, a definition that is used by "yield" |
| + // expressions. This also marks the FunctionState as a generator. |
| + Variable* temp = |
| + NewTemporary(ast_value_factory()->dot_generator_object_string()); |
| + function_state->set_generator_object_variable(temp); |
| +} |
| FunctionLiteral* Parser::ParseFunctionLiteral( |
| const AstRawString* function_name, Scanner::Location function_name_location, |
| @@ -2728,20 +2750,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( |
| #endif |
| ExpressionClassifier formals_classifier(this, &duplicate_finder); |
| - if (is_generator) { |
| - // For generators, allocating variables in contexts is currently a win |
| - // because it minimizes the work needed to suspend and resume an |
| - // activation. The machine code produced for generators (by full-codegen) |
| - // relies on this forced context allocation, but not in an essential way. |
| - this->scope()->ForceContextAllocation(); |
| - |
| - // Calling a generator returns a generator object. That object is stored |
| - // in a temporary variable, a definition that is used by "yield" |
| - // expressions. This also marks the FunctionState as a generator. |
| - Variable* temp = |
| - NewTemporary(ast_value_factory()->dot_generator_object_string()); |
| - function_state.set_generator_object_variable(temp); |
| - } |
| + if (is_generator) PrepareGeneratorVariables(&function_state); |
| Expect(Token::LPAREN, CHECK_OK); |
| int start_position = scanner()->location().beg_pos; |
| @@ -3188,6 +3197,21 @@ Variable* Parser::PromiseVariable() { |
| return promise; |
| } |
| +Expression* Parser::BuildInitialYield(int pos, FunctionKind kind) { |
| + Expression* allocation = BuildCreateJSGeneratorObject(pos, kind); |
| + VariableProxy* init_proxy = |
| + factory()->NewVariableProxy(function_state_->generator_object_variable()); |
| + Assignment* assignment = factory()->NewAssignment( |
| + Token::INIT, init_proxy, allocation, kNoSourcePosition); |
| + VariableProxy* get_proxy = |
| + factory()->NewVariableProxy(function_state_->generator_object_variable()); |
| + // The position of the yield is important for reporting the exception |
| + // caused by calling the .throw method on a generator suspended at the |
| + // initial yield (i.e. right after generator instantiation). |
| + return factory()->NewYield(get_proxy, assignment, scope()->start_position(), |
| + Yield::kOnExceptionThrow); |
| +} |
| + |
| ZoneList<Statement*>* Parser::ParseEagerFunctionBody( |
| const AstRawString* function_name, int pos, |
| const ParserFormalParameters& parameters, FunctionKind kind, |
| @@ -3240,26 +3264,10 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody( |
| Block* try_block = |
| factory()->NewBlock(nullptr, 3, false, kNoSourcePosition); |
| - |
| - { |
| - Expression* allocation = BuildCreateJSGeneratorObject(pos, kind); |
| - VariableProxy* init_proxy = factory()->NewVariableProxy( |
| - function_state_->generator_object_variable()); |
| - Assignment* assignment = factory()->NewAssignment( |
| - Token::INIT, init_proxy, allocation, kNoSourcePosition); |
| - VariableProxy* get_proxy = factory()->NewVariableProxy( |
| - function_state_->generator_object_variable()); |
| - // The position of the yield is important for reporting the exception |
| - // caused by calling the .throw method on a generator suspended at the |
| - // initial yield (i.e. right after generator instantiation). |
| - Yield* yield = factory()->NewYield(get_proxy, assignment, |
| - scope()->start_position(), |
| - Yield::kOnExceptionThrow); |
| - try_block->statements()->Add( |
| - factory()->NewExpressionStatement(yield, kNoSourcePosition), |
| - zone()); |
| - } |
| - |
| + Expression* initial_yield = BuildInitialYield(pos, kind); |
| + try_block->statements()->Add( |
| + factory()->NewExpressionStatement(initial_yield, kNoSourcePosition), |
| + zone()); |
| ParseStatementList(try_block->statements(), Token::RBRACE, CHECK_OK); |
| Statement* final_return = factory()->NewReturnStatement( |