commit 67f6bf8eac641ac03c46b0caf25f95a05a1aea70
parent 30e7d973d80ca6ee2ac9d9fd2ff415865c76683e
Author: Ryan Hunt <rhunt@eqrion.net>
Date: Thu, 18 Dec 2025 16:45:29 +0000
Bug 2002625 - Add documentation for ABI special registers. r=yury
This has needed better documentation for a long time.
Driveby fix for ARM64 to ArgRegMask to remove x8. Doesn't appear
to be used anywhere and so it should not be a functional change.
Differential Revision: https://phabricator.services.mozilla.com/D275545
Diffstat:
9 files changed, 149 insertions(+), 82 deletions(-)
diff --git a/js/src/jit/arm/Assembler-arm.h b/js/src/jit/arm/Assembler-arm.h
@@ -89,7 +89,6 @@ static constexpr Register IntArgReg0 = r0;
static constexpr Register IntArgReg1 = r1;
static constexpr Register IntArgReg2 = r2;
static constexpr Register IntArgReg3 = r3;
-static constexpr Register HeapReg = r10;
static constexpr Register CallTempNonArgRegs[] = {r5, r6, r7, r8};
static const uint32_t NumCallTempNonArgRegs = std::size(CallTempNonArgRegs);
@@ -166,32 +165,29 @@ class ABIArgGenerator : public ABIArgGeneratorShared {
bool IsUnaligned(const wasm::MemoryAccessDesc& access);
-// These registers may be volatile or nonvolatile.
+// See "ABI special registers" in Assembler-shared.h for more information.
static constexpr Register ABINonArgReg0 = r4;
static constexpr Register ABINonArgReg1 = r5;
static constexpr Register ABINonArgReg2 = r6;
static constexpr Register ABINonArgReg3 = r7;
-// This register may be volatile or nonvolatile. Avoid d15 which is the
-// ScratchDoubleReg_.
+// See "ABI special registers" in Assembler-shared.h for more information.
+// Avoid d15 which is the ScratchDoubleReg_.
static constexpr FloatRegister ABINonArgDoubleReg{FloatRegisters::d8,
VFPRegister::Double};
-// These registers may be volatile or nonvolatile.
-// Note: these three registers are all guaranteed to be different
+// See "ABI special registers" in Assembler-shared.h for more information.
static constexpr Register ABINonArgReturnReg0 = r4;
static constexpr Register ABINonArgReturnReg1 = r5;
static constexpr Register ABINonVolatileReg = r6;
-// This register is guaranteed to be clobberable during the prologue and
-// epilogue of an ABI call which must preserve both ABI argument, return
-// and non-volatile registers.
+// See "ABI special registers" in Assembler-shared.h for more information.
static constexpr Register ABINonArgReturnVolatileReg = lr;
-// Instance pointer argument register for WebAssembly functions. This must not
-// alias any other register used for passing function arguments or return
-// values. Preserved by WebAssembly functions.
+// See "ABI special registers" in Assembler-shared.h, and "The WASM ABIs" in
+// WasmFrame.h for more information.
static constexpr Register InstanceReg = r9;
+static constexpr Register HeapReg = r10;
// Registers used for wasm table calls. These registers must be disjoint
// from the ABI argument registers, InstanceReg and each other.
diff --git a/js/src/jit/arm64/Architecture-arm64.h b/js/src/jit/arm64/Architecture-arm64.h
@@ -180,7 +180,7 @@ class Registers {
static const SetType ArgRegMask =
(1 << Registers::x0) | (1 << Registers::x1) | (1 << Registers::x2) |
(1 << Registers::x3) | (1 << Registers::x4) | (1 << Registers::x5) |
- (1 << Registers::x6) | (1 << Registers::x7) | (1 << Registers::x8);
+ (1 << Registers::x6) | (1 << Registers::x7);
static const SetType VolatileMask =
(1 << Registers::x0) | (1 << Registers::x1) | (1 << Registers::x2) |
diff --git a/js/src/jit/arm64/Assembler-arm64.h b/js/src/jit/arm64/Assembler-arm64.h
@@ -358,7 +358,6 @@ static constexpr Register IntArgReg4{Registers::x4};
static constexpr Register IntArgReg5{Registers::x5};
static constexpr Register IntArgReg6{Registers::x6};
static constexpr Register IntArgReg7{Registers::x7};
-static constexpr Register HeapReg{Registers::x21};
// Define unsized Registers.
#define DEFINE_UNSIZED_REGISTERS(N) \
@@ -680,32 +679,29 @@ class ABIArgGenerator : public ABIArgGeneratorShared {
ABIArg current_;
};
-// These registers may be volatile or nonvolatile.
+// See "ABI special registers" in Assembler-shared.h for more information.
static constexpr Register ABINonArgReg0 = r8;
static constexpr Register ABINonArgReg1 = r9;
static constexpr Register ABINonArgReg2 = r10;
static constexpr Register ABINonArgReg3 = r11;
-// This register may be volatile or nonvolatile. Avoid d31 which is the
-// ScratchDoubleReg_.
+// See "ABI special registers" in Assembler-shared.h for more information.
+// Avoid d31 which is the ScratchDoubleReg_.
static constexpr FloatRegister ABINonArgDoubleReg = {FloatRegisters::s16,
FloatRegisters::Single};
-// These registers may be volatile or nonvolatile.
-// Note: these three registers are all guaranteed to be different
+// See "ABI special registers" in Assembler-shared.h for more information.
static constexpr Register ABINonArgReturnReg0 = r8;
static constexpr Register ABINonArgReturnReg1 = r9;
static constexpr Register ABINonVolatileReg{Registers::x19};
-// This register is guaranteed to be clobberable during the prologue and
-// epilogue of an ABI call which must preserve both ABI argument, return
-// and non-volatile registers.
-static constexpr Register ABINonArgReturnVolatileReg = lr;
+// See "ABI special registers" in Assembler-shared.h for more information.
+static constexpr Register ABINonArgReturnVolatileReg = r8;
-// Instance pointer argument register for WebAssembly functions. This must not
-// alias any other register used for passing function arguments or return
-// values. Preserved by WebAssembly functions. Must be nonvolatile.
+// See "ABI special registers" in Assembler-shared.h, and "The WASM ABIs" in
+// WasmFrame.h for more information.
static constexpr Register InstanceReg{Registers::x23};
+static constexpr Register HeapReg{Registers::x21};
// Registers used for wasm table calls. These registers must be disjoint
// from the ABI argument registers, InstanceReg and each other.
diff --git a/js/src/jit/loong64/Assembler-loong64.h b/js/src/jit/loong64/Assembler-loong64.h
@@ -162,7 +162,6 @@ static constexpr Register IntArgReg4 = a4;
static constexpr Register IntArgReg5 = a5;
static constexpr Register IntArgReg6 = a6;
static constexpr Register IntArgReg7 = a7;
-static constexpr Register HeapReg = s7;
// Registers used by RegExpMatcher and RegExpExecMatch stubs (do not use
// JSReturnOperand).
@@ -184,32 +183,29 @@ static constexpr Register JSReturnReg_Data = a2;
static constexpr Register JSReturnReg = a2;
static constexpr ValueOperand JSReturnOperand = ValueOperand(JSReturnReg);
-// These registers may be volatile or nonvolatile.
+// See "ABI special registers" in Assembler-shared.h for more information.
static constexpr Register ABINonArgReg0 = t0;
static constexpr Register ABINonArgReg1 = t1;
static constexpr Register ABINonArgReg2 = t2;
static constexpr Register ABINonArgReg3 = t3;
-// These registers may be volatile or nonvolatile.
-// Note: these three registers are all guaranteed to be different
+// See "ABI special registers" in Assembler-shared.h for more information.
static constexpr Register ABINonArgReturnReg0 = t0;
static constexpr Register ABINonArgReturnReg1 = t1;
static constexpr Register ABINonVolatileReg = s0;
-// This register is guaranteed to be clobberable during the prologue and
-// epilogue of an ABI call which must preserve both ABI argument, return
-// and non-volatile registers.
+// See "ABI special registers" in Assembler-shared.h for more information.
static constexpr Register ABINonArgReturnVolatileReg = ra;
-// This register may be volatile or nonvolatile.
+// See "ABI special registers" in Assembler-shared.h for more information.
// Avoid f23 which is the scratch register.
static constexpr FloatRegister ABINonArgDoubleReg{FloatRegisters::f21,
FloatRegisters::Double};
-// Instance pointer argument register for WebAssembly functions. This must not
-// alias any other register used for passing function arguments or return
-// values. Preserved by WebAssembly functions. Must be nonvolatile.
+// See "ABI special registers" in Assembler-shared.h, and "The WASM ABIs" in
+// WasmFrame.h for more information.
static constexpr Register InstanceReg = s4;
+static constexpr Register HeapReg = s7;
// Registers used for wasm table calls. These registers must be disjoint
// from the ABI argument registers, InstanceReg and each other.
diff --git a/js/src/jit/mips64/Assembler-mips64.h b/js/src/jit/mips64/Assembler-mips64.h
@@ -32,31 +32,27 @@ class ABIArgGenerator : public ABIArgGeneratorShared {
ABIArg& current() { return current_; }
};
-// These registers may be volatile or nonvolatile.
+// See "ABI special registers" in Assembler-shared.h for more information.
static constexpr Register ABINonArgReg0 = t4;
static constexpr Register ABINonArgReg1 = t5;
static constexpr Register ABINonArgReg2 = t6;
static constexpr Register ABINonArgReg3 = t7;
-// This register may be volatile or nonvolatile. Avoid f23 which is the
-// ScratchDoubleReg.
+// See "ABI special registers" in Assembler-shared.h for more information.
+// Avoid f23 which is the ScratchDoubleReg.
static constexpr FloatRegister ABINonArgDoubleReg{FloatRegisters::f21,
FloatRegisters::Double};
-// These registers may be volatile or nonvolatile.
-// Note: these three registers are all guaranteed to be different
+// See "ABI special registers" in Assembler-shared.h for more information.
static constexpr Register ABINonArgReturnReg0 = t4;
static constexpr Register ABINonArgReturnReg1 = t5;
static constexpr Register ABINonVolatileReg = s0;
-// This register is guaranteed to be clobberable during the prologue and
-// epilogue of an ABI call which must preserve both ABI argument, return
-// and non-volatile registers.
+// See "ABI special registers" in Assembler-shared.h for more information.
static constexpr Register ABINonArgReturnVolatileReg = t4;
-// TLS pointer argument register for WebAssembly functions. This must not alias
-// any other register used for passing function arguments or return values.
-// Preserved by WebAssembly functions.
+// See "ABI special registers" in Assembler-shared.h, and "The WASM ABIs" in
+// WasmFrame.h for more information.
static constexpr Register InstanceReg = s5;
// Registers used for wasm table calls. These registers must be disjoint
diff --git a/js/src/jit/riscv64/Register-riscv64.h b/js/src/jit/riscv64/Register-riscv64.h
@@ -127,7 +127,6 @@ static constexpr Register IntArgReg4{Registers::a4};
static constexpr Register IntArgReg5{Registers::a5};
static constexpr Register IntArgReg6{Registers::a6};
static constexpr Register IntArgReg7{Registers::a7};
-static constexpr Register HeapReg{Registers::s7};
// Registers used by RegExpMatcher and RegExpExecMatch stubs (do not use
// JSReturnOperand).
@@ -149,24 +148,21 @@ static constexpr Register JSReturnReg_Data{Registers::s2};
static constexpr Register JSReturnReg{Registers::a2};
static constexpr ValueOperand JSReturnOperand = ValueOperand(JSReturnReg);
-// These registers may be volatile or nonvolatile.
+// See "ABI special registers" in Assembler-shared.h for more information.
static constexpr Register ABINonArgReg0{Registers::t0};
static constexpr Register ABINonArgReg1{Registers::t1};
static constexpr Register ABINonArgReg2{Registers::t2};
static constexpr Register ABINonArgReg3{Registers::t3};
-// These registers may be volatile or nonvolatile.
-// Note: these three registers are all guaranteed to be different
+// See "ABI special registers" in Assembler-shared.h for more information.
static constexpr Register ABINonArgReturnReg0{Registers::t0};
static constexpr Register ABINonArgReturnReg1{Registers::t1};
static constexpr Register ABINonVolatileReg{Registers::s1};
-// This register is guaranteed to be clobberable during the prologue and
-// epilogue of an ABI call which must preserve both ABI argument, return
-// and non-volatile registers.
+// See "ABI special registers" in Assembler-shared.h for more information.
static constexpr Register ABINonArgReturnVolatileReg{Registers::t0};
-// This register may be volatile or nonvolatile.
+// See "ABI special registers" in Assembler-shared.h for more information.
// Avoid ft11 which is the scratch register.
static constexpr FloatRegister ABINonArgDoubleReg{FloatRegisters::ft11};
@@ -175,10 +171,10 @@ static constexpr Register WasmTableCallScratchReg1{ABINonArgReg1};
static constexpr Register WasmTableCallSigReg{ABINonArgReg2};
static constexpr Register WasmTableCallIndexReg{ABINonArgReg3};
-// Instance pointer argument register for WebAssembly functions. This must not
-// alias any other register used for passing function arguments or return
-// values. Preserved by WebAssembly functions. Must be nonvolatile.
+// See "ABI special registers" in Assembler-shared.h, and "The WASM ABIs" in
+// WasmFrame.h for more information.
static constexpr Register InstanceReg{Registers::s4};
+static constexpr Register HeapReg{Registers::s7};
static constexpr Register WasmJitEntryReturnScratch{Registers::t1};
diff --git a/js/src/jit/shared/Assembler-shared.h b/js/src/jit/shared/Assembler-shared.h
@@ -797,6 +797,101 @@ class ABIArgGeneratorShared {
uint32_t stackBytesConsumedSoFar() const { return stackOffset_; }
};
+// [SMDOC] ABI special registers
+//
+// There are a number of special registers that can be used for different
+// purposes during "ABI calls". These are defined per-architecture in their
+// Assembler-XYZ.h header. The documentation for them is centralized here to
+// keep them all in-sync.
+//
+// The WebAssembly and System ABI's are similar but distinct, and so some of
+// these can be used in both contexts and others only in one. This is
+// unfortunate and should be formalized better. See "The WASM ABIs" in
+// WasmFrame.h for documentation on the Wasm ABI.
+//
+// The relevant similarities/differences for ABI registers are that:
+// 1. Wasm functions have special InstanceReg/HeapReg registers.
+// 2. Wasm functions do not have non-volatile registers.
+// 3. Wasm and System ABI have the same integer argument and return registers.
+// 4. Wasm and System ABI may have different FP argument and return registers.
+// (notably ARM32 softfp and x87 FP are different).
+//
+// TODO: understand and describe the relationship with the various
+// MacroAssembler scratch registers. It looks like all of these must be
+// distinct from the MacroAssembler scratch registers.
+//
+// # InstanceReg
+//
+// Instance pointer argument register for WebAssembly functions in the
+// WebAssembly ABI.
+//
+// This must not alias any other register used for passing function arguments
+// or return values. Preserved by WebAssembly functions.
+//
+// The register must be non-volatile in the system ABI, as some code relies on
+// this to avoid reloading the register.
+//
+// See "The WASM ABIs" in WasmFrame.h for more information.
+//
+// # HeapReg
+//
+// Pointer to the base of (memory 0) for WebAssembly functions in the
+// WebAssembly ABI.
+//
+// This must not alias any other register used for passing function arguments
+// or return values. Preserved by WebAssembly functions.
+//
+// The register must be non-volatile in the system ABI, as some code relies on
+// this to avoid reloading the register.
+//
+// This register is not available on all architectures. It is notably absent
+// from x86.
+//
+// See "The WASM ABIs" in WasmFrame.h for more information.
+//
+// # ABINonArgReg (4 available)
+//
+// A register that can be clobbered in the prologue of a function.
+//
+// They are each distinct and have the following guarantees:
+// - Will not be a System/Wasm ABI argument register.
+// - Will not be the InstanceReg or HeapReg.
+// - Could be a System/Wasm ABI result register.
+// - Could be a System ABI non-volatile register.
+//
+// # ABINonArgDoubleReg (1 available)
+//
+// A floating-point register that can be clobbered in the prologue of a
+// function. May be volatile or non-volatile.
+//
+// # ABINonArgReturnReg (2 available)
+//
+// A register that can be clobbered in the prologue or epilogue of a function.
+//
+// They are each distinct and have the following guarantees:
+// - All the guarantees of ABINonArgReg.
+// - Will not be a System/Wasm ABI return register.
+// - Will be distinct from ABINonVolatileReg (see below).
+//
+// There are only two of these, and the constraint is x86.
+//
+// # ABINonVolatileReg (1 available)
+//
+// A register that is:
+// - Non-volatile in the System ABI
+// - (implied by above) Not an argument or return register.
+// - Distinct from the ABINonArgReturnReg.
+//
+// # ABINonArgReturnVolatileReg (1 available)
+//
+// A register that can be clobbered in the prologue or epilogue of a system ABI
+// function.
+//
+// They are each distinct and have the following guarantees:
+// - All the guarantees of ABINonArgReturnReg.
+// - Will be a volatile register in the System ABI.
+//
+
} // namespace jit
} // namespace js
diff --git a/js/src/jit/x64/Assembler-x64.h b/js/src/jit/x64/Assembler-x64.h
@@ -97,7 +97,6 @@ struct ScratchRegisterScope : public AutoRegisterScope {
};
static constexpr Register ReturnReg = rax;
-static constexpr Register HeapReg = r15;
static constexpr Register64 ReturnReg64(rax);
static constexpr FloatRegister ReturnFloat32Reg =
FloatRegister(X86Encoding::xmm0, FloatRegisters::Single);
@@ -196,33 +195,30 @@ class ABIArgGenerator : public ABIArgGeneratorShared {
ABIArg& current() { return current_; }
};
-// These registers may be volatile or nonvolatile.
+// See "ABI special registers" in Assembler-shared.h for more information.
// Avoid r11, which is the MacroAssembler's ScratchReg.
static constexpr Register ABINonArgReg0 = rax;
static constexpr Register ABINonArgReg1 = rbx;
static constexpr Register ABINonArgReg2 = r10;
static constexpr Register ABINonArgReg3 = r12;
-// This register may be volatile or nonvolatile. Avoid xmm15 which is the
-// ScratchDoubleReg.
+// See "ABI special registers" in Assembler-shared.h for more information.
+// Avoid xmm15 which is the ScratchDoubleReg.
static constexpr FloatRegister ABINonArgDoubleReg =
FloatRegister(X86Encoding::xmm8, FloatRegisters::Double);
-// These registers may be volatile or nonvolatile.
-// Note: these three registers are all guaranteed to be different
+// See "ABI special registers" in Assembler-shared.h for more information.
static constexpr Register ABINonArgReturnReg0 = r10;
static constexpr Register ABINonArgReturnReg1 = r12;
static constexpr Register ABINonVolatileReg = r13;
-// This register is guaranteed to be clobberable during the prologue and
-// epilogue of an ABI call which must preserve both ABI argument, return
-// and non-volatile registers.
+// See "ABI special registers" in Assembler-shared.h for more information.
static constexpr Register ABINonArgReturnVolatileReg = r10;
-// Instance pointer argument register for WebAssembly functions. This must not
-// alias any other register used for passing function arguments or return
-// values. Preserved by WebAssembly functions.
+// See "ABI special registers" in Assembler-shared.h, and "The WASM ABIs" in
+// WasmFrame.h for more information.
static constexpr Register InstanceReg = r14;
+static constexpr Register HeapReg = r15;
// Registers used for asm.js/wasm table calls. These registers must be disjoint
// from the ABI argument registers, InstanceReg and each other.
diff --git a/js/src/jit/x86/Assembler-x86.h b/js/src/jit/x86/Assembler-x86.h
@@ -100,31 +100,27 @@ class ABIArgGenerator : public ABIArgGeneratorShared {
ABIArg& current() { return current_; }
};
-// These registers may be volatile or nonvolatile.
+// See "ABI special registers" in Assembler-shared.h for more information.
static constexpr Register ABINonArgReg0 = eax;
static constexpr Register ABINonArgReg1 = ebx;
static constexpr Register ABINonArgReg2 = ecx;
static constexpr Register ABINonArgReg3 = edx;
-// This register may be volatile or nonvolatile. Avoid xmm7 which is the
-// ScratchDoubleReg_.
+// See "ABI special registers" in Assembler-shared.h for more information.
+// Avoid xmm7 which is the ScratchDoubleReg_.
static constexpr FloatRegister ABINonArgDoubleReg =
FloatRegister(X86Encoding::xmm0, FloatRegisters::Double);
-// These registers may be volatile or nonvolatile.
-// Note: these three registers are all guaranteed to be different
+// See "ABI special registers" in Assembler-shared.h for more information.
static constexpr Register ABINonArgReturnReg0 = ecx;
static constexpr Register ABINonArgReturnReg1 = edi;
static constexpr Register ABINonVolatileReg = ebx;
-// This register is guaranteed to be clobberable during the prologue and
-// epilogue of an ABI call which must preserve both ABI argument, return
-// and non-volatile registers.
+// See "ABI special registers" in Assembler-shared.h for more information.
static constexpr Register ABINonArgReturnVolatileReg = ecx;
-// Instance pointer argument register for WebAssembly functions. This must not
-// alias any other register used for passing function arguments or return
-// values. Preserved by WebAssembly functions.
+// See "ABI special registers" in Assembler-shared.h, and "The WASM ABIs" in
+// WasmFrame.h for more information.
static constexpr Register InstanceReg = esi;
// Registers used for asm.js/wasm table calls. These registers must be disjoint