Chromium Code Reviews| 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); |
| } |