Commit 68f0a47b authored by Adam Klein's avatar Adam Klein Committed by Commit Bot

[ignition] Move generator object creation to BytecodeGenerator

This lets us avoid allocating the "this" variable for every
generator, since the BytecodeGenerator can directly read
the receiver via BytecodeArrayBuilder::Receive() when passing
it into %_CreateJSGeneratorObject.

Bug: v8:6351
Change-Id: Ib5e1f3303b6b5d5fc051ce76ea62129fd6afac65
Reviewed-on: https://chromium-review.googlesource.com/500507
Commit-Queue: Adam Klein <adamk@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Reviewed-by: 's avatarCaitlin Potter <caitp@igalia.com>
Cr-Commit-Position: refs/heads/master@{#45281}
parent fc5765ce
......@@ -774,6 +774,12 @@ void BytecodeGenerator::GenerateBytecodeBody() {
// Build assignment to {new.target} variable if it is used.
VisitNewTargetVariable(closure_scope()->new_target_var());
// Create a generator object if necessary and initialize the
// {.generator_object} variable.
if (IsResumableFunction(info()->literal()->kind())) {
BuildGeneratorObjectVariableInitialization();
}
// Emit tracing call if requested to do so.
if (FLAG_trace) builder()->CallRuntime(Runtime::kTraceEnter);
......@@ -3526,6 +3532,20 @@ void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) {
builder()->Bind(&flush_state_label);
}
void BytecodeGenerator::BuildGeneratorObjectVariableInitialization() {
DCHECK(IsResumableFunction(info()->literal()->kind()));
DCHECK_NOT_NULL(closure_scope()->generator_object_var());
RegisterAllocationScope register_scope(this);
RegisterList args = register_allocator()->NewRegisterList(2);
builder()
->MoveRegister(Register::function_closure(), args[0])
.MoveRegister(builder()->Receiver(), args[1])
.CallRuntime(Runtime::kInlineCreateJSGeneratorObject, args);
BuildVariableAssignment(closure_scope()->generator_object_var(), Token::INIT,
FeedbackSlot::Invalid(), HoleCheckMode::kElided);
}
void BytecodeGenerator::VisitFunctionClosureForContext() {
ValueResultScope value_execution_result(this);
if (closure_scope()->is_script_scope()) {
......
......@@ -144,6 +144,7 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
void BuildClassLiteral(ClassLiteral* expr);
void VisitThisFunctionVariable(Variable* variable);
void VisitNewTargetVariable(Variable* variable);
void BuildGeneratorObjectVariableInitialization();
void VisitBlockDeclarationsAndStatements(Block* stmt);
void VisitFunctionClosureForContext();
void VisitSetHomeObject(Register value, Register home_object,
......
......@@ -3132,22 +3132,6 @@ Block* Parser::BuildRejectPromiseOnException(Block* inner_block) {
return result;
}
Assignment* Parser::BuildCreateJSGeneratorObject(int pos, FunctionKind kind) {
// .generator = %_CreateJSGeneratorObject(...);
DCHECK_NOT_NULL(function_state_->generator_object_variable());
ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
args->Add(factory()->NewThisFunction(pos), zone());
args->Add(IsArrowFunction(kind) ? GetLiteralUndefined(pos)
: ThisExpression(kNoSourcePosition),
zone());
Expression* allocation = factory()->NewCallRuntime(
Runtime::kInlineCreateJSGeneratorObject, args, pos);
VariableProxy* proxy =
factory()->NewVariableProxy(function_state_->generator_object_variable());
return factory()->NewAssignment(Token::INIT, proxy, allocation,
kNoSourcePosition);
}
Expression* Parser::BuildResolvePromise(Expression* value, int pos) {
// %ResolvePromise(.promise, value), .promise
ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
......@@ -3197,13 +3181,17 @@ Variable* Parser::AsyncGeneratorAwaitVariable() {
}
Expression* Parser::BuildInitialYield(int pos, FunctionKind kind) {
Assignment* assignment = BuildCreateJSGeneratorObject(pos, kind);
VariableProxy* generator =
// We access the generator object twice: once for the {generator}
// member of the Suspend AST node, and once for the result of
// the initial yield.
Expression* yield_result =
factory()->NewVariableProxy(function_state_->generator_object_variable());
Expression* generator_object =
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 BuildSuspend(generator, assignment, scope()->start_position(),
return BuildSuspend(generator_object, yield_result, scope()->start_position(),
Suspend::kOnExceptionThrow, SuspendFlags::kYield);
}
......@@ -3867,9 +3855,6 @@ void Parser::PrepareAsyncFunctionBody(ZoneList<Statement*>* body,
if (function_state_->generator_object_variable() == nullptr) {
PrepareGeneratorVariables();
}
body->Add(factory()->NewExpressionStatement(
BuildCreateJSGeneratorObject(pos, kind), kNoSourcePosition),
zone());
}
// This method completes the desugaring of the body of async_function.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment