Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 0a67a6646c829465c43ee79154632b039437957d
      
https://github.com/WebKit/WebKit/commit/0a67a6646c829465c43ee79154632b039437957d
  Author: Andrew Gaul <[email protected]>
  Date:   2026-08-26 (Wed, 26 Aug 2026)

  Changed paths:
    M Source/JavaScriptCore/jit/JIT.h
    M Source/JavaScriptCore/jit/JITInlines.h
    M Source/JavaScriptCore/jit/JITOpcodes.cpp
    M Source/JavaScriptCore/jit/JITPropertyAccess.cpp

  Log Message:
  -----------
  [JSC] Baseline: load adjacent metadata pointer fields with a single ldp
https://bugs.webkit.org/show_bug.cgi?id=322566

Reviewed by Keith Miller.

op_new_object and op_put_to_scope each read two adjacent pointer-sized
fields out of the metadata table with two separate loadPtr calls, which on
arm64 is two ldrs against the same base at offsets eight apart:

    ldr x1, [x25, #0x1a8]     ; ObjectAllocationProfile::m_allocator
    ldr x3, [x25, #0x1b0]     ; ObjectAllocationProfile::m_structure

becomes

    ldp x1, x3, [x25, #0x1a8]

Both pairs are laid out adjacently by construction, so this is just a
missed use of loadPairPtr(), which every 64-bit backend implements and
which degrades to the two loads it replaces when the offset is outside
ldp's imm7 range (-512..504) or on a backend without a paired load.

* op_new_object loads ObjectAllocationProfile's m_allocator and m_structure.
  A new loadPairPtrFromMetadata() spells the paired form the way
  loadPtrFromMetadata() spells the single one.

* op_put_to_scope loads OpPutToScope::Metadata's m_watchpointSet and
  m_operand. The ClosureVar case already loads them back to back. The
  GlobalVar case loaded m_operand, ran the TDZ check, then loaded
  m_watchpointSet; hoisting the watchpoint-set load above the TDZ check
  pairs them too. Nothing between the two points clobbers either register,
  and both were already live across emitNotifyWriteWatchpoint().

Both sites get a static_assert on the adjacency the paired load depends on,
so a layout change is a build error rather than a silent pessimization.

Scanning everything the JITs emit while running JetStream 3 (54.7M
instructions) reports 6601 adjacent-load pairs that ldp could fold. 2953 of
them are these two opcodes -- 1502 op_new_object and 1451 op_put_to_scope --
and all 2953 are within ldp's immediate range. The remaining 3648 are DFG
and FTL tail calls, where CallFrameShuffler restores the caller's callee-save
registers from adjacent old-frame slots one ldr at a time; that needs a
change to the shuffler's load loop and is not addressed here.

Re-dumping ARES-6 with this change: every ldp-encodable metadata pair is
gone, and 53 ldps appear where 28 pairs were folded -- the extra 25 are
GlobalLexicalVar sites whose two loads were previously separated by the TDZ
check, so armlint's adjacency matcher never counted them.

Found with armlint.

* Source/JavaScriptCore/jit/JIT.h:
* Source/JavaScriptCore/jit/JITInlines.h:
(JSC::JIT::loadPairPtrFromMetadata):
* Source/JavaScriptCore/jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_new_object):
* Source/JavaScriptCore/jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_put_to_scope):

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



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

Reply via email to