← All issues

[JSC] GreedyRegAlloc: add loop-aware live range splitting (disabled by default)

7a38dc3

Source/JavaScriptCore/b3/air/AirAllocateRegistersByGreedy.cpp

+ template<Bank bank>
+ bool trySplitAroundLoop(Tmp tmp, TmpData& tmpData)
+ {
+ if (!Options::airGreedyRegAllocSplitAroundLoops())
+ return false;
+ if (tmpData.splitAroundClobbersMetadataIndex)
+ return false;
+ auto [loop, nonLoopRange] = chooseLoopForSplit(tmpData.liveRange);
+ if (!loop) return false;
+ ...
+ Tmp loopTmp = addSplitTmp(tmp, UseDefCost(0), { });
+ }

Air is JSC's lowest-level B3 IR, sitting just above machine-code emission. The greedy register allocator assigns physical registers to virtual tmps based on spill costs and interference. Live range splitting cuts a tmp's range so its halves can receive independent assignments. This commit adds loop-aware splitting: a tmp whose range crosses a loop boundary can be split into loop-body and outer halves. A new CFG normalization pass ensureDedicatedLoopEntryExitBlocks guarantees safe insertion points for Shuffle (Air's parallel-move primitive, handling arbitrary register permutations including cycles) at split boundaries. Currently disabled behind airGreedyRegAllocSplitAroundLoops.

A complex new JIT pass that's currently under-tested (off by default) — enabling it via --airGreedyRegAllocSplitAroundLoops=true in a fuzzer opens a largely untested code region in the JIT compiler pipeline.

🔒

New JIT splitting path with CFG surgery and parallel-move fixups — several edge cases in loop selection and split interactions are worth security investigation.

Subscribe to read more