Index: src/interpreter/bytecode-generator.cc |
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc |
index b754897e759335c90ea8c4a94555f3d22d3e6a9f..da219c79df0678cf3a6ff198c8e7ab956ca17e82 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) |
+ .ResumeGenerator(generator_object_) |
rmcilroy
2017/06/01 10:44:44
How about we merge GeneratorGetContext into the Re
Jarin
2017/06/01 12:48:22
They both need to return value. Is it common to us
rmcilroy
2017/06/01 13:20:23
It's not common, but it's possible (e.g, use a Reg
|
.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()); |
rmcilroy
2017/06/01 10:44:44
Let's rename this SaveGeneratorRegisters now to ma
Jarin
2017/06/01 12:48:22
It actually does more work than just saving regist
rmcilroy
2017/06/01 13:20:23
It's quite different from RestoreGenerator now tho
|
if (expr->IsNonInitialAsyncGeneratorYield()) { |
// AsyncGenerator yields (with the exception of the initial yield) delegate |
@@ -2549,10 +2552,15 @@ 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) |
+ .StoreAccumulatorInRegister(generator_object_); |
rmcilroy
2017/06/01 10:44:44
Any reason to pass generator_object_ back in accum
Jarin
2017/06/01 12:48:22
Done.
|
+ |
// Update state to indicate that we have finished resuming. Loop headers |
// rely on this. |
builder() |
@@ -2623,10 +2631,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 +3737,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); |
} |