Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 1330d5747e024bad42fc5d0d95234bd5db399781
      
https://github.com/WebKit/WebKit/commit/1330d5747e024bad42fc5d0d95234bd5db399781
  Author: Andrew Gaul <[email protected]>
  Date:   2026-08-25 (Tue, 25 Aug 2026)

  Changed paths:
    M Source/JavaScriptCore/assembler/MacroAssemblerARM64.h
    M Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h

  Log Message:
  -----------
  [JSC] Fold unsigned compares against zero into cbz/cbnz and test
https://bugs.webkit.org/show_bug.cgi?id=322370

Reviewed by Yusuke Suzuki.

MacroAssemblerARM64::branch32/branch64 route a zero immediate through
commuteCompareToZeroIntoTest(), which rewrites a relational condition into
the equivalent test condition so the branch becomes a single cbz/cbnz
instead of a cmp plus b.cond. The switch covered Equal, NotEqual, LessThan
and GreaterThanOrEqual but not the unsigned pair, although unsigned x > 0
is exactly x != 0 and unsigned x <= 0 is exactly x == 0.

That gap costs an instruction in every unfenced write barrier. blackThreshold
is 0, so AssemblyHelpers::barrierBranchWithoutFence() asks for
branch8(Above, cellState, TrustedImm32(blackThreshold)) and gets

    ldurb w17, [x1, #7]
    cmp   w17, #0
    b.hi  skipBarrier

where cbnz w17 does the same work. Scanning everything the JITs emit while
running JetStream 3 (54.7M instructions) reports 65764 sites, 99.4% of them
this barrier: 27158 in DFG OSR exit stubs, where osrWriteBarrier() emits the
sequence once per exit, 26303 in DFG code, 7580 in FTL OSR exits and 4723 in
wasm BBQ. The whole class is gone from a re-scan after this change, removing
roughly 263 KB of dead compares from that run.

MacroAssemblerX86_64 carries the same switch and the same gap, so extend it
there too. test reg, reg clears CF, so Above (CF == 0 && ZF == 0) is exactly
NonZero and BelowOrEqual (CF == 1 || ZF == 1) is exactly Zero, and the
resulting test is also shorter to encode than the cmp against an immediate.

The fenced barrierBranch(vm, ...) form compares against
vm.heap.barrierThreshold, a runtime value that the collector raises to a
tautological threshold, and correctly keeps its compare.

Found with armlint.

* Source/JavaScriptCore/assembler/MacroAssemblerARM64.h:
(JSC::MacroAssemblerARM64::commuteCompareToZeroIntoTest):
* Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h:
(JSC::MacroAssemblerX86_64::commuteCompareToZeroIntoTest):

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Canonical link: https://commits.webkit.org/319777@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to