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

Unified Diff: src/parser.cc

Issue 13542002: Calling a generator function returns a generator object (Closed) Base URL: git://github.com/v8/v8.git@master
Patch Set: Rebased to apply to bleeding_edge Created 7 years, 8 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 side-by-side diff with in-line comments
Download patch
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index b80e701577c6ee1e1272e1c4ba40c0986499bd4c..f8349b0448878c6371aeed230340800dec40f691 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -486,17 +486,16 @@ 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()),
parser_(parser),
outer_function_state_(parser->current_function_state_),
outer_scope_(parser->top_scope_),
+ generator_object_variable_(NULL),
saved_ast_node_id_(isolate->ast_node_id()),
factory_(isolate, parser->zone()) {
parser->top_scope_ = 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());
@@ -1033,6 +1030,26 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
// SourceElements ::
// (ModuleElement)* <end_token>
+ // For generators, allocate and yield an iterator on function entry.
Michael Starzinger 2013/04/11 19:17:39 Can we move this down into "ParseFunctionLiteral"
wingo 2013/04/12 10:50:17 Done.
+ if (is_generator()) {
+ ZoneList<Expression*>* arguments =
+ new(zone()) ZoneList<Expression*>(1, zone());
+ arguments->Add(factory()->NewThisFunction(), 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);
+ processor->Add(factory()->NewExpressionStatement(yield), zone());
+ }
+
// Allocate a target stack to use for this set of source
// elements. This way, all scripts and functions get their own
// target stack thus avoiding illegal breaks and continues across
@@ -3103,8 +3120,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 +4409,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)*[','] ')'

Powered by Google App Engine
This is Rietveld 408576698