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

Reply via email to