| Index: src/parser.cc
|
| diff --git a/src/parser.cc b/src/parser.cc
|
| index b80e701577c6ee1e1272e1c4ba40c0986499bd4c..b4ab623829b9657382ab58bcbe347ce4b31d3dff 100644
|
| --- a/src/parser.cc
|
| +++ b/src/parser.cc
|
| @@ -486,14 +486,13 @@ class Parser::BlockState BASE_EMBEDDED {
|
|
|
| Parser::FunctionState::FunctionState(Parser* parser,
|
| Scope* scope,
|
| - bool is_generator,
|
| Isolate* isolate)
|
| : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
|
| next_handler_index_(0),
|
| expected_property_count_(0),
|
| - is_generator_(is_generator),
|
| only_simple_this_property_assignments_(false),
|
| this_property_assignments_(isolate->factory()->empty_fixed_array()),
|
| + generator_object_variable_(NULL),
|
| parser_(parser),
|
| outer_function_state_(parser->current_function_state_),
|
| outer_scope_(parser->top_scope_),
|
| @@ -642,9 +641,8 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
|
| }
|
| ParsingModeScope parsing_mode(this, mode);
|
|
|
| - bool is_generator = false;
|
| // Enters 'scope'.
|
| - FunctionState function_state(this, scope, is_generator, isolate());
|
| + FunctionState function_state(this, scope, isolate());
|
|
|
| top_scope_->SetLanguageMode(info->language_mode());
|
| ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
|
| @@ -758,8 +756,7 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source,
|
| scope = Scope::DeserializeScopeChain(info()->closure()->context(), scope,
|
| zone());
|
| }
|
| - bool is_generator = false; // Top scope is not a generator.
|
| - FunctionState function_state(this, scope, is_generator, isolate());
|
| + FunctionState function_state(this, scope, isolate());
|
| ASSERT(scope->language_mode() != STRICT_MODE || !info()->is_classic_mode());
|
| ASSERT(scope->language_mode() != EXTENDED_MODE ||
|
| info()->is_extended_mode());
|
| @@ -3103,8 +3100,11 @@ Expression* Parser::ParseYieldExpression(bool* ok) {
|
| int position = scanner().peek_location().beg_pos;
|
| Expect(Token::YIELD, CHECK_OK);
|
| bool is_yield_star = Check(Token::MUL);
|
| + Expression* generator_object = factory()->NewVariableProxy(
|
| + current_function_state_->generator_object_variable());
|
| Expression* expression = ParseAssignmentExpression(false, CHECK_OK);
|
| - return factory()->NewYield(expression, is_yield_star, position);
|
| + return factory()->NewYield(generator_object, expression, is_yield_star,
|
| + position);
|
| }
|
|
|
|
|
| @@ -4389,11 +4389,24 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
|
| : FunctionLiteral::kNotGenerator;
|
| AstProperties ast_properties;
|
| // Parse function body.
|
| - { FunctionState function_state(this, scope, is_generator, isolate());
|
| + { FunctionState function_state(this, scope, isolate());
|
| top_scope_->SetScopeName(function_name);
|
| - // For generators, allocating variables in contexts is currently a win
|
| - // because it minimizes the work needed to suspend and resume an activation.
|
| - if (is_generator) top_scope_->ForceContextAllocation();
|
| +
|
| + 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.
|
| + top_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. Presence of a variable for the generator object in the
|
| + // FunctionState indicates that this function is a generator.
|
| + Handle<String> tempname = isolate()->factory()->InternalizeOneByteString(
|
| + STATIC_ASCII_VECTOR(".generator_object"));
|
| + Variable* temp = top_scope_->DeclarationScope()->NewTemporary(tempname);
|
| + function_state.set_generator_object_variable(temp);
|
| + }
|
|
|
| // FormalParameterList ::
|
| // '(' (Identifier)*[','] ')'
|
| @@ -4551,6 +4564,26 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
|
| RelocInfo::kNoPosition)),
|
| zone());
|
| }
|
| +
|
| + // For generators, allocate and yield an iterator on function entry.
|
| + if (is_generator) {
|
| + ZoneList<Expression*>* arguments =
|
| + new(zone()) ZoneList<Expression*>(0, zone());
|
| + CallRuntime* allocation = factory()->NewCallRuntime(
|
| + isolate()->factory()->empty_string(),
|
| + Runtime::FunctionForId(Runtime::kCreateJSGeneratorObject),
|
| + arguments);
|
| + VariableProxy* init_proxy = factory()->NewVariableProxy(
|
| + current_function_state_->generator_object_variable());
|
| + Assignment* assignment = factory()->NewAssignment(
|
| + Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition);
|
| + VariableProxy* get_proxy = factory()->NewVariableProxy(
|
| + current_function_state_->generator_object_variable());
|
| + Yield* yield = factory()->NewYield(
|
| + get_proxy, assignment, false, RelocInfo::kNoPosition);
|
| + body->Add(factory()->NewExpressionStatement(yield), zone());
|
| + }
|
| +
|
| ParseSourceElements(body, Token::RBRACE, false, false, CHECK_OK);
|
|
|
| materialized_literal_count = function_state.materialized_literal_count();
|
|
|