Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 80fc868e7373b04d6c0456a974af2c8ea89ace5f
https://github.com/WebKit/WebKit/commit/80fc868e7373b04d6c0456a974af2c8ea89ace5f
Author: Andrew Gaul <[email protected]>
Date: 2026-08-26 (Wed, 26 Aug 2026)
Changed paths:
M Source/JavaScriptCore/assembler/MacroAssemblerARM64.h
M Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h
M Source/JavaScriptCore/assembler/testmasm.cpp
Log Message:
-----------
[JSC] add/sub of a zero immediate should be a mov
https://bugs.webkit.org/show_bug.cgi?id=322504
Reviewed by Keith Miller.
The immediate forms of add32/add64/sub32/sub64 wrote a register-to-register
copy the expensive way when the immediate was zero: add xD, xS, #0 or
sub wD, wS, #0 on arm64, and leaq 0(%src), %dest or a dead addq $0, %reg on
x86_64, where the TrustedImm64 pair also burned a movabsq and the scratch
register. A mov is eliminated at rename where add-with-zero and lea are not,
and the 64-bit forms drop the instruction entirely when source and destination
coincide. The 32-bit forms go through zeroExtend32ToWord() instead, since they
must still zero the destination's upper half.
None of these entry points promise flags -- arm64 already uses the
non-flag-setting add and sub, and flag-consuming callers use
branchAdd64/branchSub64 -- so dropping x86_64's flag write is invisible.
x86_64 needed more entry points than arm64: only the add32/sub32 three-operand
forms had the check, and its two-operand forms emit their own instruction
rather than forwarding to the three-operand ones. Its 32-bit two-operand forms
are left alone, where the substitution would be movl %eax, %eax: a byte shorter
than addl $0, %eax but the same single uop.
The dominant source is JIT::emit_op_new_array(), which passes the address of
the literal's first element with
addPtr(TrustedImm32(valuesStart.offset() * sizeof(Register)),
callFrameRegister, argumentGPR2);
and that offset is zero for an empty [] literal.
Scanning everything the JITs emit while running JetStream 3, armlint reports
4563 sites on arm64, 3081 of them exactly add x2, x29, #0 (3335 Baseline, 1068
DFG) and the remaining 699 sub wD, wS, #0. The same scan on x86_64 -- 111654
code blobs and 240 MB captured through LinkBuffer's perf JITDump -- has x86lint
reporting 3989 sites:
3091 lea rD, [rS] zero displacement, 3090 Baseline and 1 DFG
680 add/sub rD, 0 64-bit, 676 DFG, 3 Baseline, 1 WasmBBQ
216 add/sub eD, 0 32-bit, deliberately unchanged
2 lea rD, [rS+rI] two-register, unrelated to this change
All 3091 zero-displacement LEAs are exactly leaq 0(%rbp), %rdx, which is
callFrameRegister into argumentGPR2. After this change an empty array literal
compiles to mov x2, fp or movq %rbp, %rdx; no zero-immediate add or sub is left
on arm64, and on x86_64 both targeted rows are empty, 3771 sites in total. The
32-bit row's drift to 219 is JIT nondeterminism between runs.
testmasm covered none of these entry points on x86_64: the six sub tests sat in
the #if CPU(ARM64) block and there were no add tests at all. Move them to
#if CPU(X86_64) || CPU(ARM64) and add testAdd32Imm, testAdd32ArgImm,
testAdd64Imm32, testAdd64ArgImm32, testAdd64Imm64 and testAdd64ArgImm64, one
per immediate form. int32Operands() and int64Operands() both start at 0, so all
of them exercise the zero-immediate path. testmasm goes from 382 to 394 tests
on x86_64, all passing.
Found with armlint and x86lint.
* Source/JavaScriptCore/assembler/MacroAssemblerARM64.h:
(JSC::MacroAssemblerARM64::add32):
(JSC::MacroAssemblerARM64::add64):
(JSC::MacroAssemblerARM64::sub32):
(JSC::MacroAssemblerARM64::sub64):
* Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h:
(JSC::MacroAssemblerX86_64::add64):
(JSC::MacroAssemblerX86_64::sub64):
* Source/JavaScriptCore/assembler/testmasm.cpp:
(JSC::testAdd32Imm):
(JSC::testAdd32ArgImm):
(JSC::testAdd64Imm32):
(JSC::testAdd64ArgImm32):
(JSC::testAdd64Imm64):
(JSC::testAdd64ArgImm64):
(JSC::run):
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Canonical link: https://commits.webkit.org/319908@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications