@@ -4057,6 +4057,8 @@ LinearScan::InsertSecondChanceCompensation(Lifetime ** branchRegContent, Lifetim
4057
4057
continue ;
4058
4058
}
4059
4059
4060
+ // Allow us to properly insert compensation code for symbols whose lifetimes start after the generator jump table
4061
+ // The GeneratorBailInLabel will have 2 edges in: one from the normal flow, one straight from the generator jump table
4060
4062
if (!branchLifetime && lifetime && lifetime->start > branchInstr->GetNumber () && labelInstr->m_opcode == Js::OpCode::GeneratorBailInLabel)
4061
4063
{
4062
4064
continue ;
@@ -4977,14 +4979,12 @@ void LinearScan::GeneratorBailIn::SpillRegsForBailIn()
4977
4979
}
4978
4980
}
4979
4981
4982
+ // Note: Comments refer to rax/rcx for x64. For x86, we use their equivalence: eax/ecx
4980
4983
// Restores the live stack locations followed by the live registers from
4981
4984
// the interpreter's register slots.
4982
4985
// RecordDefs each live register that is restored.
4983
4986
//
4984
4987
// Generates the following code:
4985
- //
4986
- // PUSH rax ; if needed
4987
- // PUSH rcx ; if needed
4988
4988
//
4989
4989
// MOV rax, param0
4990
4990
// MOV rax, [rax + JavascriptGenerator::GetFrameOffset()]
@@ -4998,8 +4998,6 @@ void LinearScan::GeneratorBailIn::SpillRegsForBailIn()
4998
4998
//
4999
4999
// MOV sym(register), [rax + regslot offset]
5000
5000
//
5001
- // POP rax; if needed
5002
- // POP rcx; if needed
5003
5001
IR::Instr* LinearScan::GeneratorBailIn::GenerateBailIn (IR::Instr* resumeLabelInstr, BailOutInfo* bailOutInfo)
5004
5002
{
5005
5003
Assert (!bailOutInfo->capturedValues || bailOutInfo->capturedValues ->constantValues .Empty ());
@@ -5138,10 +5136,20 @@ bool LinearScan::GeneratorBailIn::NeedsReloadingValueWhenBailIn(StackSym* sym, L
5138
5136
{
5139
5137
if (this ->func ->GetJITFunctionBody ()->RegIsConstant (sym->GetByteCodeRegSlot ()))
5140
5138
{
5139
+ // Resume jump table is inserted after we load symbols in the constant table,
5140
+ // so at bail-in point, we can have two scenarios:
5141
+ // 1) the symbols are still in registers
5142
+ // 2) the symbols have already been "spilled"
5143
+ // Since we don't save/restore constant symbols and simply insert loads of their
5144
+ // values before use, in either case, there is no need to reload the values
5141
5145
return false ;
5142
5146
}
5143
5147
else
5144
5148
{
5149
+ // Again, for all other constant symbols, if they are bytecodeUpwardExposed and they have
5150
+ // already been "spilled", which means that the register allocator will automatically
5151
+ // insert the load of their values later before use, we don't need to restore.
5152
+ // Only restore symbols that are still in registers
5145
5153
return !lifetime->isSpilled ;
5146
5154
}
5147
5155
}
@@ -5159,6 +5167,8 @@ bool LinearScan::GeneratorBailIn::NeedsReloadingValueWhenBailIn(StackSym* sym, L
5159
5167
5160
5168
IR::SymOpnd* LinearScan::GeneratorBailIn::CreateGeneratorObjectOpnd () const
5161
5169
{
5170
+ // First parameter passed to the jit'd frame
5171
+ // See `CallGenerator` method
5162
5172
StackSym* sym = StackSym::NewParamSlotSym (1 , this ->func );
5163
5173
this ->func ->SetArgOffset (sym, LowererMD::GetFormalParamOffset () * MachPtr);
5164
5174
return IR::SymOpnd::New (sym, TyMachPtr, this ->func );
0 commit comments