← All issues

[JSC] Add Map / Set fast iteration

4337048

Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

+ // MapIteratorNext changes the iterator, so after that, we cannot
+ // do OSR exit except for throwing an error, otherwise, OSR exit will
+ // advance the iterator again. We carefully emit DFG nodes which never
+ // does normal OSR exits, so this is fine.
+ auto mapIteratorNextNode = addToGraph(MapIteratorNext, OpInfo(0), OpInfo(prediction), iteratorNode);
+ auto isDoneNode = addToGraph(MapIteratorNextDone, mapIteratorNextNode);
+ addToGraph(Branch, OpInfo(branchData), isDoneNode);

Source/JavaScriptCore/bytecode/IterationModeMetadata.h

enum class IterationMode : uint8_t {
Generic,
Fast,
+ FastMap,
+ FastSet,
};

JSC's tiered JIT inlines for-of loops at the bytecode-parser level via iterator_open/iterator_next bytecodes, skipping the generic iterator protocol when the collection type is recognised. Until now this fast path covered arrays only. This commit extends it to JSMap and JSSet across LLInt, Baseline, DFG, and FTL, adding two new IterationMode variants (FastMap, FastSet) and the MapIteratorNext/SetIteratorNext intrinsics that directly advance internal hash-table cursors.

The critical new invariant: after MapIteratorNext executes (and mutates iterator state), the DFG must not emit any node that can trigger a normal OSR exit. A normal exit restores interpreter state and re-runs the bytecode, which would call MapIteratorNext again, double-advancing the iterator. Only exception-path exits are permitted post-advance. constructArrayPair is also forced to Contiguous storage to avoid DFG speculation failures during inlining.

For-of loops over Map and Set are 1.3-2x faster in hot code, and the change adds substantial new JIT-compiled fast paths for security-sensitive collection iteration with strict OSR-exit constraints.

🔒

New JIT fast paths with explicit OSR exit restrictions and cross-tier iterator state assumptions — several audit directions exist.

Subscribe to read more