Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: ce878e190fef3abba29f10243a8454fde765f573
https://github.com/WebKit/WebKit/commit/ce878e190fef3abba29f10243a8454fde765f573
Author: Sosuke Suzuki <[email protected]>
Date: 2026-08-19 (Wed, 19 Aug 2026)
Changed paths:
A JSTests/microbenchmarks/map-for-each-deleted-entries.js
A JSTests/microbenchmarks/map-for-each-key-value.js
A JSTests/microbenchmarks/set-for-each-value.js
A JSTests/stress/map-for-each-mutation-during-iteration.js
A JSTests/stress/set-for-each-mutation-during-iteration.js
M Source/JavaScriptCore/dfg/DFGOperations.cpp
M Source/JavaScriptCore/dfg/DFGOperations.h
M Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
M Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
M Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
Log Message:
-----------
[JSC] Inline `Map#forEach` / `Set#forEach` iteration in DFG and FTL
https://bugs.webkit.org/show_bug.cgi?id=322069
Reviewed by Yusuke Suzuki.
Map.prototype.forEach and Set.prototype.forEach are JS builtins that walk the
storage with @mapIterationNext, @mapIterationEntry, @mapIterationEntryKey and
@mapIterationEntryValue. The corresponding DFG nodes were lowered to C++ calls
in both DFG and FTL, so every element paid four operation calls whose bodies
are two or three butterfly loads. The for-of siblings (MapIteratorNext,
MapIteratorKey, MapIteratorValue) already walk the same table inline.
Lower the four nodes the same way. MapIterationNext checks for the sentinel,
falls back to the operation only when the table is obsolete, and otherwise
scans the data table for the next non-deleted key and stores its entry index
into the IterationEntry slot. MapIterationEntry is a single load of that
slot, and MapIterationEntryKey/Value compute the data index from it through
loadMapEntryData, which MapIteratorKey/Value now share as well; the for-of
lowering is unchanged.
The Entry/EntryKey/EntryValue operations are no longer reachable from JIT code
and are removed. The remaining IterationNext operations are only called for
obsolete tables, so they no longer handle the sentinel.
Baseline Patched
map-for-each 2.2298+-0.0516 ^ 1.7644+-0.0487
^ definitely 1.2638x faster
map-for-each-key-value 80.3508+-1.3258 ^ 48.7157+-1.0237
^ definitely 1.6494x faster
set-for-each-value 68.4946+-1.5632 ^ 46.6082+-1.1317
^ definitely 1.4696x faster
set-for-each 2.0780+-0.0679 ^ 1.6924+-0.0448
^ definitely 1.2278x faster
Tests: JSTests/microbenchmarks/map-for-each-deleted-entries.js
JSTests/microbenchmarks/map-for-each-key-value.js
JSTests/microbenchmarks/set-for-each-value.js
JSTests/stress/map-for-each-mutation-during-iteration.js
JSTests/stress/set-for-each-mutation-during-iteration.js
* JSTests/microbenchmarks/map-for-each-deleted-entries.js: Added.
(sumEntries):
* JSTests/microbenchmarks/map-for-each-key-value.js: Added.
(sumEntries):
* JSTests/microbenchmarks/set-for-each-value.js: Added.
(sumValues.set forEach):
* JSTests/stress/map-for-each-mutation-during-iteration.js: Added.
(shouldBe):
(makeMap):
(keys):
(deleteAhead):
(deleteAllAhead):
(addDuring):
(clearDuring):
(clearAndReadd):
* JSTests/stress/set-for-each-mutation-during-iteration.js: Added.
(shouldBe):
(set values.set forEach):
(deleteAhead.set forEach):
(deleteAllAhead.set forEach):
(addDuring.set forEach):
(clearDuring.set forEach):
(clearAndReadd.set forEach):
* Source/JavaScriptCore/dfg/DFGOperations.cpp:
(JSC::DFG::JSC_DEFINE_NOEXCEPT_JIT_OPERATION):
* Source/JavaScriptCore/dfg/DFGOperations.h:
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::loadMapEntryData):
(JSC::DFG::SpeculativeJIT::compileMapIteratorKey):
(JSC::DFG::SpeculativeJIT::compileMapIteratorValue):
(JSC::DFG::SpeculativeJIT::compileMapIterationNext):
(JSC::DFG::SpeculativeJIT::compileMapIterationEntry):
(JSC::DFG::SpeculativeJIT::compileMapIterationEntryData):
(JSC::DFG::SpeculativeJIT::compileMapIterationEntryKey):
(JSC::DFG::SpeculativeJIT::compileMapIterationEntryValue):
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h:
* Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
Canonical link: https://commits.webkit.org/319440@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications