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