← All issues

[JSC] Add foundation of handling builtin iterators in fast-iteration-protocol

3d1bebd

// Source/JavaScriptCore/runtime/VM.h
+ JSValue fastArrayValuesSentinel()  const { return m_fastArrayValuesSentinel.get(); }
+ JSValue fastArrayKeysSentinel()    const { return m_fastArrayKeysSentinel.get(); }
+ JSValue fastArrayEntriesSentinel() const { return m_fastArrayEntriesSentinel.get(); }

JSC's bytecode includes op_iterator_open and op_iterator_next, which the baseline JIT and DFG can fast-path when a built-in iterator (e.g., Array's @@iterator) is recognized. Previously, the fast path handled only a single 'FastArray' (values) mode and passed an empty JS value as the sentinel between the two opcodes — a slot the DFG used solely to detect that the fast path was active.

This commit introduces JSSentinel — a new VM-level heap object — to carry iterator kind (values/keys/entries) between op_iterator_open and op_iterator_next. The empty-value sentinel is replaced with typed JSSentinel singletons stored on the VM (one per kind), so DFG/FTL can emit specialized inline code for FastArrayKeys and FastArrayEntries in addition to values, yielding 14–37% speedups. TypedArrays share ArrayIteratorPrototype and are intentionally excluded; a future FastTypedArrayXXX extension will handle them.

This is a foundational architectural change: it decouples iterator kind from the iterator object itself, enabling DFG specialization of keys and entries without touching the JS heap object, and paves the way for fully eliminating JS-side ArrayIterator#next, MapIterator#next, and SetIterator#next builtins in favor of C++/DFG implementations.

🔒

Cross-realm guard logic, watchpoint invalidation, and TypedArray exclusion all introduce edge cases in these new fast paths worth auditing.

Subscribe to read more