Index: src/interpreter/bytecode-generator.cc |
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc |
index b754897e759335c90ea8c4a94555f3d22d3e6a9f..f2a5d74029bc8f33726b604f218f48c0da6530be 100644 |
--- a/src/interpreter/bytecode-generator.cc |
+++ b/src/interpreter/bytecode-generator.cc |
@@ -776,6 +776,7 @@ BytecodeGenerator::BytecodeGenerator(CompilationInfo* info) |
execution_context_(nullptr), |
execution_result_(nullptr), |
generator_jump_table_(nullptr), |
+ generator_object_(), |
generator_state_(), |
loop_depth_(0) { |
DCHECK_EQ(closure_scope(), closure_scope()->GetClosureScope()); |
@@ -962,6 +963,7 @@ void BytecodeGenerator::VisitIterationHeader(IterationStatement* stmt, |
void BytecodeGenerator::BuildGeneratorPrologue() { |
DCHECK_GT(info()->literal()->suspend_count(), 0); |
+ generator_object_ = register_allocator()->NewRegister(); |
generator_state_ = register_allocator()->NewRegister(); |
generator_jump_table_ = |
builder()->AllocateJumpTable(info()->literal()->suspend_count(), 0); |
@@ -970,19 +972,20 @@ void BytecodeGenerator::BuildGeneratorPrologue() { |
// indicate that this is a resume call and to pass in the generator object. |
// In ordinary calls, new.target is always undefined because generator |
// functions are non-constructable. |
- Register generator_object = Register::new_target(); |
+ builder()->MoveRegister(Register::new_target(), generator_object_); |
+ |
BytecodeLabel regular_call; |
builder() |
- ->LoadAccumulatorWithRegister(generator_object) |
+ ->LoadAccumulatorWithRegister(generator_object_) |
.JumpIfUndefined(®ular_call); |
// This is a resume call. Restore the current context and the registers, |
// then perform state dispatch. |
Register generator_context = register_allocator()->NewRegister(); |
builder() |
- ->CallRuntime(Runtime::kInlineGeneratorGetContext, generator_object) |
+ ->CallRuntime(Runtime::kInlineGeneratorGetContext, generator_object_) |
.PushContext(generator_context) |
- .ResumeGenerator(generator_object) |
+ .RestoreGeneratorState(generator_object_) |
.StoreAccumulatorInRegister(generator_state_) |
.SwitchOnSmiNoFeedback(generator_jump_table_); |
// We fall through when the generator state is not in the jump table. |
@@ -2518,8 +2521,8 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) { |
} |
} |
-void BytecodeGenerator::BuildGeneratorSuspend(Suspend* expr, |
- Register generator) { |
+void BytecodeGenerator::BuildGeneratorSuspend(Suspend* expr, Register generator, |
+ RegisterList registers_to_save) { |
RegisterAllocationScope register_scope(this); |
builder()->SetExpressionPosition(expr); |
@@ -2528,7 +2531,7 @@ void BytecodeGenerator::BuildGeneratorSuspend(Suspend* expr, |
// Save context, registers, and state. Then return. |
builder() |
->LoadLiteral(Smi::FromInt(expr->suspend_id())) |
- .SuspendGenerator(generator, expr->flags()); |
+ .SuspendGenerator(generator, registers_to_save, expr->flags()); |
if (expr->IsNonInitialAsyncGeneratorYield()) { |
// AsyncGenerator yields (with the exception of the initial yield) delegate |
@@ -2549,10 +2552,13 @@ void BytecodeGenerator::BuildGeneratorSuspend(Suspend* expr, |
builder()->Return(); // Hard return (ignore any finally blocks). |
} |
-void BytecodeGenerator::BuildGeneratorResume(Suspend* expr, |
- Register generator) { |
+void BytecodeGenerator::BuildGeneratorResume( |
+ Suspend* expr, Register generator, RegisterList registers_to_restore) { |
RegisterAllocationScope register_scope(this); |
+ // Clobbers all registers. |
+ builder()->RestoreGeneratorRegisters(generator_object_, registers_to_restore); |
+ |
// Update state to indicate that we have finished resuming. Loop headers |
// rely on this. |
builder() |
@@ -2623,10 +2629,11 @@ void BytecodeGenerator::BuildGeneratorResume(Suspend* expr, |
void BytecodeGenerator::VisitSuspend(Suspend* expr) { |
Register generator = VisitForRegisterValue(expr->generator_object()); |
- BuildGeneratorSuspend(expr, generator); |
+ RegisterList registers(0, register_allocator()->next_register_index()); |
+ BuildGeneratorSuspend(expr, generator, registers); |
builder()->Bind(generator_jump_table_, static_cast<int>(expr->suspend_id())); |
// Upon resume, we continue here. |
- BuildGeneratorResume(expr, generator); |
+ BuildGeneratorResume(expr, generator, registers); |
} |
void BytecodeGenerator::VisitThrow(Throw* expr) { |
@@ -3728,7 +3735,8 @@ void BytecodeGenerator::BuildGeneratorObjectVariableInitialization() { |
builder() |
->MoveRegister(Register::function_closure(), args[0]) |
.MoveRegister(builder()->Receiver(), args[1]) |
- .CallRuntime(Runtime::kInlineCreateJSGeneratorObject, args); |
+ .CallRuntime(Runtime::kInlineCreateJSGeneratorObject, args) |
+ .StoreAccumulatorInRegister(generator_object_); |
BuildVariableAssignment(closure_scope()->generator_object_var(), Token::INIT, |
FeedbackSlot::Invalid(), HoleCheckMode::kElided); |
} |