[JSC] ArrayShift DFG node
Component: JSC DFG and FTL JIT | dfe5dc6
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/dfg/DFGOperations.cpp
Where ArrayPop already gets intrinsic treatment — inlined machine code guided by abstract-interpreter rules describing the node's effects and clobberize rules describing which memory it touches — Array.prototype.shift() did not. This commit gives it a dedicated ArrayShift node, but with a narrower inline fast path: only arrays of length 0 or 1 are handled inline (loading the value, storing empty, updating publicLength), because shifting elements down for longer arrays is expensive and demands careful handling of holes, which in JavaScript can inherit through the prototype chain. Everything else falls back to operationArrayShift.
Significance
A very common array operation gains direct JIT codegen, and with it a new speculative fast path that must maintain array length and storage invariants across both DFG and FTL. The node is 64-bit only — the 32-bit backend hits a DFG_CRASH stub and the parser bails early.
Audit directions
Narrow: review the DFGSpeculativeJIT64.cpp codegen and FTLLowerDFGToB3.cpp's compileArrayShift for correct separation of the length-1 fast path from hole/empty-value detection before falling back, and confirm clobberize and safeToExecute rules prevent unsafe reordering against concurrent array mutation via a getter or a Proxy-backed array. Wider: the portable hunt is across every array-mutating JIT intrinsic that writes publicLength — ArrayPop, ArrayPush, and now ArrayShift — asking in each case whether the length store and the element store can be observed out of order by anything, and whether the empty-value check is applied on every path that reaches the store. Match tell: a store32(..., Butterfly::offsetOfPublicLength()) that is not immediately adjacent to the element write it is meant to pair with.