Skip to content

Commit d101e8e

Browse files
committed
Move BailOutForElidedYield to ResumeJumpTable
This is to prevent us from accidentally inserting it in the middle of other instructions
1 parent 44eccb5 commit d101e8e

File tree

3 files changed

+66
-54
lines changed

3 files changed

+66
-54
lines changed

lib/Backend/IRBuilder.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7746,17 +7746,23 @@ IRBuilder::GeneratorJumpTable::BuildJumpTable()
77467746
);
77477747
this->m_irBuilder->AddInstr(instr, this->m_irBuilder->m_functionStartOffset);
77487748

7749+
IR::LabelInstr* functionBegin = IR::LabelInstr::New(Js::OpCode::Label, this->m_func);
7750+
LABELNAMESET(functionBegin, "GeneratorFunctionBegin");
7751+
77497752
IR::LabelInstr* initCode = IR::LabelInstr::New(Js::OpCode::Label, this->m_func);
77507753
LABELNAMESET(initCode, "GeneratorInitializationAndJumpTable");
77517754

77527755
// BrNotAddr_A s2 nullptr $initializationCode
7753-
IR::BranchInstr* branchInstr = IR::BranchInstr::New(Js::OpCode::BrNotAddr_A, initCode, genFrameOpnd, IR::AddrOpnd::NewNull(this->m_func), this->m_func);
7754-
this->m_irBuilder->AddInstr(branchInstr, this->m_irBuilder->m_functionStartOffset);
7756+
IR::BranchInstr* skipCreateInterpreterFrame = IR::BranchInstr::New(Js::OpCode::BrNotAddr_A, initCode, genFrameOpnd, IR::AddrOpnd::NewNull(this->m_func), this->m_func);
7757+
this->m_irBuilder->AddInstr(skipCreateInterpreterFrame, this->m_irBuilder->m_functionStartOffset);
77557758

77567759
// Create interpreter stack frame
77577760
IR::Instr* createInterpreterFrame = IR::Instr::New(Js::OpCode::GeneratorCreateInterpreterStackFrame, genFrameOpnd /* dst */, genRegOpnd /* src */, this->m_func);
77587761
this->m_irBuilder->AddInstr(createInterpreterFrame, this->m_irBuilder->m_functionStartOffset);
77597762

7763+
IR::BranchInstr* skipJumpTable = IR::BranchInstr::New(Js::OpCode::Br, functionBegin, this->m_func);
7764+
this->m_irBuilder->AddInstr(skipJumpTable, this->m_irBuilder->m_functionStartOffset);
7765+
77607766
// Label to insert any initialization code
77617767
// $initializationCode:
77627768
this->m_irBuilder->AddInstr(initCode, this->m_irBuilder->m_functionStartOffset);
@@ -7791,6 +7797,10 @@ IRBuilder::GeneratorJumpTable::BuildJumpTable()
77917797
instr->SetSrc1(curOffsetOpnd);
77927798
this->m_irBuilder->AddInstr(instr, this->m_irBuilder->m_functionStartOffset);
77937799

7800+
this->m_func->m_bailOutForElidedYieldInsertionPoint = instr;
7801+
7802+
this->m_irBuilder->AddInstr(functionBegin, this->m_irBuilder->m_functionStartOffset);
7803+
77947804
// Save these values for later use
77957805
this->m_initLabel = initCode;
77967806
this->m_generatorFrameOpnd = genFrameOpnd;

lib/Backend/Lower.cpp

Lines changed: 53 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3010,7 +3010,6 @@ Lowerer::LowerRange(IR::Instr *instrStart, IR::Instr *instrEnd, bool defaultDoFa
30103010

30113011
case Js::OpCode::GeneratorResumeJumpTable:
30123012
{
3013-
this->m_lowerGeneratorHelper.InsertBailOutForElidedYield();
30143013
this->m_lowerGeneratorHelper.LowerGeneratorResumeJumpTable(instr);
30153014
break;
30163015
}
@@ -29079,49 +29078,6 @@ void Lowerer::LowerGeneratorHelper::InsertNullOutGeneratorFrameInEpilogue(IR::La
2907929078
InsertMove(indirOpnd, addrOpnd, insertionPoint);
2908029079
}
2908129080

29082-
void
29083-
Lowerer::LowerGeneratorHelper::InsertBailOutForElidedYield()
29084-
{
29085-
IR::LabelInstr* bailOutNoSaveLabel = nullptr;
29086-
29087-
this->func->MapUntilYieldOffsetResumeLabels([this, &bailOutNoSaveLabel](int, const YieldOffsetResumeLabel& yorl)
29088-
{
29089-
if (yorl.Second() == nullptr)
29090-
{
29091-
if (bailOutNoSaveLabel == nullptr)
29092-
{
29093-
bailOutNoSaveLabel = IR::LabelInstr::New(Js::OpCode::Label, this->func);
29094-
}
29095-
29096-
return true;
29097-
}
29098-
29099-
return false;
29100-
});
29101-
29102-
// Insert the bailoutnosave label somewhere along with a call to BailOutNoSave helper
29103-
if (bailOutNoSaveLabel != nullptr)
29104-
{
29105-
bailOutNoSaveLabel->m_hasNonBranchRef = true;
29106-
bailOutNoSaveLabel->isOpHelper = true;
29107-
29108-
IR::Instr* exitPrevInstr = this->GetEpilogueForReturnStatements()->m_prev;
29109-
IR::Instr* bailOutCall = IR::Instr::New(Js::OpCode::Call, this->func);
29110-
IR::Instr* branchToEpilogue = IR::BranchInstr::New(LowererMD::MDUncondBranchOpcode, this->GetEpilogueForBailOut(), this->func);
29111-
29112-
exitPrevInstr->InsertBefore(bailOutNoSaveLabel);
29113-
exitPrevInstr->InsertBefore(bailOutCall);
29114-
exitPrevInstr->InsertBefore(branchToEpilogue);
29115-
29116-
IR::RegOpnd* frameRegOpnd = IR::RegOpnd::New(nullptr, LowererMD::GetRegFramePointer(), TyMachPtr, this->func);
29117-
this->lowererMD.LoadHelperArgument(bailOutCall, frameRegOpnd);
29118-
this->lowererMD.ChangeToHelperCall(bailOutCall, IR::HelperNoSaveRegistersBailOutForElidedYield);
29119-
29120-
this->func->m_bailOutNoSaveLabel = bailOutNoSaveLabel;
29121-
LABELNAMESET(bailOutNoSaveLabel, "GeneratorBailOutForElidedYield");
29122-
}
29123-
}
29124-
2912529081
void
2912629082
Lowerer::LowerGeneratorHelper::EnsureEpilogueLabels()
2912729083
{
@@ -29165,30 +29121,76 @@ Lowerer::LowerGeneratorHelper::LowerGeneratorResumeJumpTable(IR::Instr* jumpTabl
2916529121
Assert(this->func->GetJITFunctionBody()->IsCoroutine());
2916629122
Assert(jumpTableInstr->m_opcode == Js::OpCode::GeneratorResumeJumpTable);
2916729123

29124+
IR::LabelInstr* bailOutForElidedYield = this->InsertBailOutForElidedYield();
29125+
2916829126
IR::Opnd* srcOpnd = jumpTableInstr->UnlinkSrc1();
2916929127

29170-
this->func->MapYieldOffsetResumeLabels([this, &srcOpnd, &jumpTableInstr](int i, const YieldOffsetResumeLabel& yorl)
29128+
this->func->MapYieldOffsetResumeLabels([this, &srcOpnd, &jumpTableInstr, &bailOutForElidedYield](int i, const YieldOffsetResumeLabel& yorl)
2917129129
{
2917229130
uint32 offset = yorl.First();
29173-
IR::LabelInstr* label = yorl.Second();
29131+
IR::LabelInstr* resumeLabel = yorl.Second();
2917429132

29175-
if (label != nullptr && label->m_hasNonBranchRef)
29133+
if (resumeLabel != nullptr)
2917629134
{
29135+
Assert(resumeLabel->IsGeneratorBailInInstr());
2917729136
// Also fix up the bailout at the label with the jump to epilog that was not emitted in GenerateBailOut()
29178-
this->lowerer->GenerateJumpToEpilogForBailOut(label->m_prev->GetBailOutInfo(), label->m_prev, this->GetEpilogueForBailOut());
29137+
this->lowerer->GenerateJumpToEpilogForBailOut(resumeLabel->m_prev->GetBailOutInfo(), resumeLabel->m_prev, this->GetEpilogueForBailOut());
2917929138
}
29180-
else if (label == nullptr)
29139+
else if (resumeLabel == nullptr)
2918129140
{
29182-
label = this->func->m_bailOutNoSaveLabel;
29141+
resumeLabel = bailOutForElidedYield;
2918329142
}
2918429143

2918529144
// For each offset label pair, insert a compare of the offset and branch if equal to the label
29186-
this->lowerer->InsertCompareBranch(srcOpnd, IR::IntConstOpnd::New(offset, TyUint32, this->func), Js::OpCode::BrSrEq_A, label, jumpTableInstr);
29145+
this->lowerer->InsertCompareBranch(srcOpnd, IR::IntConstOpnd::New(offset, TyUint32, this->func), Js::OpCode::BrSrEq_A, resumeLabel, jumpTableInstr);
2918729146
});
2918829147

2918929148
jumpTableInstr->Remove();
2919029149
}
2919129150

29151+
IR::LabelInstr*
29152+
Lowerer::LowerGeneratorHelper::InsertBailOutForElidedYield()
29153+
{
29154+
IR::LabelInstr* bailOutNoSaveLabel = nullptr;
29155+
29156+
this->func->MapUntilYieldOffsetResumeLabels([this, &bailOutNoSaveLabel](int, const YieldOffsetResumeLabel& yorl)
29157+
{
29158+
if (yorl.Second() == nullptr)
29159+
{
29160+
if (bailOutNoSaveLabel == nullptr)
29161+
{
29162+
bailOutNoSaveLabel = IR::LabelInstr::New(Js::OpCode::Label, this->func);
29163+
}
29164+
29165+
return true;
29166+
}
29167+
29168+
return false;
29169+
});
29170+
29171+
// Insert the bailoutnosave label somewhere along with a call to BailOutNoSave helper
29172+
if (bailOutNoSaveLabel != nullptr)
29173+
{
29174+
bailOutNoSaveLabel->m_hasNonBranchRef = true;
29175+
29176+
IR::Instr* insertionPoint = this->func->m_bailOutForElidedYieldInsertionPoint->m_next;
29177+
IR::Instr* bailOutCall = IR::Instr::New(Js::OpCode::Call, this->func);
29178+
IR::Instr* branchToEpilogue = IR::BranchInstr::New(LowererMD::MDUncondBranchOpcode, this->GetEpilogueForBailOut(), this->func);
29179+
29180+
insertionPoint->InsertBefore(bailOutNoSaveLabel);
29181+
insertionPoint->InsertBefore(bailOutCall);
29182+
insertionPoint->InsertBefore(branchToEpilogue);
29183+
29184+
IR::RegOpnd* frameRegOpnd = IR::RegOpnd::New(nullptr, LowererMD::GetRegFramePointer(), TyMachPtr, this->func);
29185+
this->lowererMD.LoadHelperArgument(bailOutCall, frameRegOpnd);
29186+
this->lowererMD.ChangeToHelperCall(bailOutCall, IR::HelperNoSaveRegistersBailOutForElidedYield);
29187+
29188+
LABELNAMESET(bailOutNoSaveLabel, "GeneratorBailOutForElidedYield");
29189+
}
29190+
29191+
return bailOutNoSaveLabel;
29192+
}
29193+
2919229194
void
2919329195
Lowerer::LowerGeneratorHelper::LowerCreateInterpreterStackFrameForGenerator(IR::Instr* instr)
2919429196
{

lib/Backend/Lower.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -885,7 +885,7 @@ class Lowerer
885885
// They could still be hit if an active generator object had been paused at such a yield point when
886886
// the function body was JITed. So safe guard such a case by having the native code simply jump back
887887
// to the interpreter for such yield points.
888-
void InsertBailOutForElidedYield();
888+
IR::LabelInstr* InsertBailOutForElidedYield();
889889

890890
void LowerGeneratorResumeJumpTable(IR::Instr* jumpTableInstr);
891891
void LowerCreateInterpreterStackFrameForGenerator(IR::Instr* instr);

0 commit comments

Comments
 (0)