Skip to content

Commit af0609c

Browse files
committed
Add more comments
1 parent 1d7964d commit af0609c

File tree

2 files changed

+55
-9
lines changed

2 files changed

+55
-9
lines changed

lib/Backend/LinearScan.cpp

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4944,7 +4944,10 @@ LinearScan::GeneratorBailIn::GeneratorBailIn(Func* func, LinearScan* linearScan)
49444944
// so no need to restore.
49454945
this->initializedRegs.Set(this->jitFnBody->GetYieldReg());
49464946

4947-
// The environment is loaded before the resume jump table, no need to restore either.
4947+
// The environment is loaded before the resume jump table. At bail-in point, it can either
4948+
// still be in register or already spilled. If it's in register we're good. If it's been spilled,
4949+
// the register allocator should have inserted compensation code before the bail-in block, so we
4950+
// are still fine there.
49484951
this->initializedRegs.Set(this->jitFnBody->GetEnvReg());
49494952

49504953
this->bailInSymbols = JitAnew(this->func->m_alloc, SListBase<BailInSymbol>);
@@ -5061,13 +5064,24 @@ void LinearScan::GeneratorBailIn::BuildBailInSymbolList(
50615064
{
50625065
this->bailInSymbols->Clear(this->func->m_alloc);
50635066

5064-
// Assume all symbols cannot be restored
5067+
// Make sure that all symbols in `upwardExposedUses` can be restored.
5068+
// The idea is to first assume that we cannot restore any of the symbols.
5069+
// Then we use the information in `byteCodeUpwardExposedUses` and `capturedValues`
5070+
// which contains information about symbols in the bytecode, copy-prop'd symbols, and
5071+
// symbols with constant values. As we go through these lists, we clear the
5072+
// bits in `unrestorableSymbols` to indicate that they can be restored. At the
5073+
// end, the bitvector has to be empty.
5074+
5075+
// Assume all symbols cannot be restored.
50655076
BVSparse<JitArenaAllocator> unrestorableSymbols(this->func->m_alloc);
50665077
unrestorableSymbols.Or(&upwardExposedUses);
50675078

50685079
unrestorableSymbols.Minus(&this->initializedRegs);
50695080

5070-
// Symbols in byteCodeUpwardExposedUses are restorable
5081+
// Symbols in byteCodeUpwardExposedUses are restorable.
5082+
// If a symbol is in byteCodeUpwardExposedUses, which means that it is not
5083+
// a constant nor a copy-prop candidate. In such cases, we can simply map
5084+
// the bytecode register directly to its backend id.
50715085
FOREACH_BITSET_IN_SPARSEBV(symId, &byteCodeUpwardExposedUses)
50725086
{
50735087
StackSym* stackSym = this->func->m_symTable->FindStackSym(symId);
@@ -5081,14 +5095,32 @@ void LinearScan::GeneratorBailIn::BuildBailInSymbolList(
50815095
}
50825096
NEXT_BITSET_IN_SPARSEBV;
50835097

5084-
// Symbols that were copy-prop'd
5098+
// Symbols that were copy-prop'd.
5099+
// Example:
5100+
// `copyPropSyms` having an entry { s_key : s_value } means that we can use `s_key`
5101+
// in place of `s_value`.
5102+
//
5103+
// 1) if we find `s_value` at this point (after clearing all symbols in
5104+
// `bytecodeUpwardExposedUses`), it means that `s_value` is a backend-only
5105+
// symbol, and that the only way to restore this symbol is through `s_key`.
5106+
// Since in `FillBailOutRecord`, we make sure to restore all symbols that are
5107+
// keys in in `usedCapturedValues`, we can simply use `s_key` to restore the value
5108+
// for `s_value`.
5109+
// 2) if we find `s_key`, then we can just map directly the value due to the above reason.
50855110
FOREACH_SLISTBASE_ENTRY(CopyPropSyms, copyPropSym, &capturedValues.copyPropSyms)
50865111
{
50875112
Sym* key = copyPropSym.Key();
50885113
Sym* value = copyPropSym.Value();
5089-
if (unrestorableSymbols.TestAndClear(value->m_id))
5114+
5115+
#if DBG
5116+
if (unrestorableSymbols.Test(value->m_id) || unrestorableSymbols.Test(key->m_id))
50905117
{
50915118
Assert(key->IsStackSym() && (key->AsStackSym()->HasByteCodeRegSlot() || key->AsStackSym()->IsFromByteCodeConstantTable()));
5119+
}
5120+
#endif
5121+
5122+
if (unrestorableSymbols.TestAndClear(value->m_id))
5123+
{
50925124
if (this->NeedsReloadingSymWhenBailingIn(copyPropSym.Key()))
50935125
{
50945126
BailInSymbol bailInSym(key->m_id /* fromByteCodeRegSlot */, value->m_id /* toBackendId */);
@@ -5097,7 +5129,6 @@ void LinearScan::GeneratorBailIn::BuildBailInSymbolList(
50975129
}
50985130
else if (unrestorableSymbols.TestAndClear(key->m_id))
50995131
{
5100-
Assert(key->IsStackSym() && (key->AsStackSym()->HasByteCodeRegSlot() || key->AsStackSym()->IsFromByteCodeConstantTable()));
51015132
if (this->NeedsReloadingSymWhenBailingIn(copyPropSym.Key()))
51025133
{
51035134
BailInSymbol bailInSym(key->m_id /* fromByteCodeRegSlot */, key->m_id /* toBackendId */);
@@ -5107,7 +5138,8 @@ void LinearScan::GeneratorBailIn::BuildBailInSymbolList(
51075138
}
51085139
NEXT_SLISTBASE_ENTRY;
51095140

5110-
// Used constant values
5141+
// Used constant values.
5142+
// These symbols are can be mapped directly.
51115143
FOREACH_SLISTBASE_ENTRY(ConstantStackSymValue, entry, &capturedValues.constantValues)
51125144
{
51135145
SymID symId = entry.Key()->m_id;
@@ -5132,6 +5164,7 @@ void LinearScan::GeneratorBailIn::BuildBailInSymbolList(
51325164
}
51335165
NEXT_SLISTBASE_ENTRY;
51345166

5167+
// Clear all symbols that don't need to be restored.
51355168
FOREACH_BITSET_IN_SPARSEBV_EDITING(symId, &unrestorableSymbols)
51365169
{
51375170
StackSym* stackSym = this->func->m_symTable->FindStackSym(symId);
@@ -5253,8 +5286,8 @@ void LinearScan::GeneratorBailIn::InsertRestoreSymbols(
52535286

52545287
bool LinearScan::GeneratorBailIn::NeedsReloadingBackendSymWhenBailingIn(StackSym* sym) const
52555288
{
5256-
// If we have for-in in the generator, don't need to reload the symbol again as it is done
5257-
// during the resume jump table
5289+
// for-in enumerator in generator is loaded as part of the resume jump table.
5290+
// By the same reasoning as `initializedRegs`'s, we don't have to restore this whether or not it's been spilled.
52585291
if (this->func->GetForInEnumeratorSymForGeneratorSym() && this->func->GetForInEnumeratorSymForGeneratorSym()->m_id == sym->m_id)
52595292
{
52605293
return false;

lib/Backend/LinearScan.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,13 @@ class LinearScan
256256
IR::Instr* instrInsertRegSym;
257257
};
258258

259+
// Represents a symbol that needs to be restored when bailing in.
260+
// In normal cases, for a given symbol, whatever bytecode registers that the
261+
// symbol has will map directly to the backend symbol with the same id.
262+
// However, due to copy-prop, sometimes we would use a different symbol for a given value.
263+
// This struct keep track of that fact and generate the restore instruction accordingly.
264+
// Additionally, for symbols that are constant but not in the bytecode constant table, we have
265+
// to reload the symbol's value directly.
259266
struct BailInSymbol
260267
{
261268
const SymID fromByteCodeRegSlot;
@@ -275,6 +282,9 @@ class LinearScan
275282
BVSparse<JitArenaAllocator> initializedRegs;
276283
SListBase<BailInSymbol>* bailInSymbols;
277284

285+
// Registers needed in the bail-in code.
286+
// The register allocator will have to spill these
287+
// so that we are free to use them.
278288
static constexpr int regNum = 2;
279289
const RegNum regs[regNum];
280290
IR::RegOpnd* const interpreterFrameRegOpnd;
@@ -285,13 +295,15 @@ class LinearScan
285295
uint32 GetOffsetFromInterpreterStackFrame(Js::RegSlot regSlot) const;
286296
IR::SymOpnd* CreateGeneratorObjectOpnd() const;
287297

298+
// Insert instructions to restore symbols in the `bailInSymbols` list
288299
void InsertRestoreSymbols(
289300
const BVSparse<JitArenaAllocator>& bytecodeUpwardExposedUses,
290301
const BVSparse<JitArenaAllocator>& upwardExposedUses,
291302
const CapturedValues& capturedValues,
292303
BailInInsertionPoint& insertionPoint
293304
);
294305

306+
// Fill `bailInSymbols` list with all of the symbols that need to be restored
295307
void BuildBailInSymbolList(
296308
const BVSparse<JitArenaAllocator>& byteCodeUpwardExposedUses,
297309
const BVSparse<JitArenaAllocator>& upwardExposedUses,
@@ -305,6 +317,7 @@ class LinearScan
305317
GeneratorBailIn(Func* func, LinearScan* linearScan);
306318
~GeneratorBailIn();
307319
IR::Instr* GenerateBailIn(IR::GeneratorBailInInstr* bailInInstr);
320+
// Spill all registers that we need in order to generate the bail-in code
308321
void SpillRegsForBailIn();
309322
};
310323

0 commit comments

Comments
 (0)