Commit b9af74c8 authored by Leszek Swirski's avatar Leszek Swirski Committed by V8 LUCI CQ

[codegen] Use ABI caller saved regs for Pop/PushCallerSaved

The set of registers used for Pop/PushCallerSaved is a superset of the
ABI caller-saved registers. In the past it may have been the case that
these extra registers had to be saved, but at this point
Pop/PushCallerSaved is only used for fast C calls from JS, so we can
rely on the C-compiled functions saving callee-saved registers
correctly, and only save ABI-required registers ourselves.

Change-Id: I2a172bdbb381a1485654e54e3561d695b6672ed0
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3735130
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81467}
parent d1d4c648
......@@ -299,21 +299,11 @@ void TurboAssembler::LoadAddress(Register destination,
mov(destination, Immediate(source));
}
static constexpr Register saved_regs[] = {eax, ecx, edx};
static constexpr int kNumberOfSavedRegs = sizeof(saved_regs) / sizeof(Register);
int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
Register exclusion1,
Register exclusion2,
Register exclusion3) const {
Register exclusion) const {
int bytes = 0;
for (int i = 0; i < kNumberOfSavedRegs; i++) {
Register reg = saved_regs[i];
if (reg != exclusion1 && reg != exclusion2 && reg != exclusion3) {
bytes += kSystemPointerSize;
}
}
RegList saved_regs = kCallerSaved - exclusion;
bytes += kSystemPointerSize * saved_regs.Count();
if (fp_mode == SaveFPRegsMode::kSave) {
// Count all XMM registers except XMM0.
......@@ -323,19 +313,17 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
return bytes;
}
int TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
Register exclusion2, Register exclusion3) {
int TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode,
Register exclusion) {
ASM_CODE_COMMENT(this);
// We don't allow a GC in a write barrier slow path so there is no need to
// store the registers in any particular way, but we do have to store and
// restore them.
int bytes = 0;
for (int i = 0; i < kNumberOfSavedRegs; i++) {
Register reg = saved_regs[i];
if (reg != exclusion1 && reg != exclusion2 && reg != exclusion3) {
push(reg);
bytes += kSystemPointerSize;
}
RegList saved_regs = kCallerSaved - exclusion;
for (Register reg : saved_regs) {
push(reg);
bytes += kSystemPointerSize;
}
if (fp_mode == SaveFPRegsMode::kSave) {
......@@ -356,8 +344,7 @@ int TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
return bytes;
}
int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
Register exclusion2, Register exclusion3) {
int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion) {
ASM_CODE_COMMENT(this);
int bytes = 0;
if (fp_mode == SaveFPRegsMode::kSave) {
......@@ -375,12 +362,10 @@ int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
bytes += delta;
}
for (int i = kNumberOfSavedRegs - 1; i >= 0; i--) {
Register reg = saved_regs[i];
if (reg != exclusion1 && reg != exclusion2 && reg != exclusion3) {
pop(reg);
bytes += kSystemPointerSize;
}
RegList saved_regs = kCallerSaved - exclusion;
for (Register reg : base::Reversed(saved_regs)) {
pop(reg);
bytes += kSystemPointerSize;
}
return bytes;
......
......@@ -375,25 +375,19 @@ class V8_EXPORT_PRIVATE TurboAssembler
// Calculate how much stack space (in bytes) are required to store caller
// registers excluding those specified in the arguments.
int RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
Register exclusion1 = no_reg,
Register exclusion2 = no_reg,
Register exclusion3 = no_reg) const;
Register exclusion = no_reg) const;
// PushCallerSaved and PopCallerSaved do not arrange the registers in any
// particular order so they are not useful for calls that can cause a GC.
// The caller can exclude up to 3 registers that do not need to be saved and
// The caller can exclude a register that does not need to be saved and
// restored.
// Push caller saved registers on the stack, and return the number of bytes
// stack pointer is adjusted.
int PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1 = no_reg,
Register exclusion2 = no_reg,
Register exclusion3 = no_reg);
int PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion = no_reg);
// Restore caller saved registers from the stack, and return the number of
// bytes stack pointer is adjusted.
int PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1 = no_reg,
Register exclusion2 = no_reg,
Register exclusion3 = no_reg);
int PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion = no_reg);
// Compute the start of the generated instruction stream from the current PC.
// This is an alternative to embedding the {CodeObject} handle as a reference.
......
......@@ -22,6 +22,9 @@ constexpr RegList kJSCallerSaved = {
ebx, // used as caller-saved register in JavaScript code
edi}; // callee function
// Caller-saved registers according to the x86 ABI
constexpr RegList kCallerSaved = {eax, ecx, edx};
constexpr int kNumJSCallerSaved = 5;
} // namespace internal
......
......@@ -776,22 +776,11 @@ void MacroAssembler::JumpToExternalReference(const ExternalReference& ext,
Jump(code, RelocInfo::CODE_TARGET);
}
static constexpr Register saved_regs[] = {rax, rcx, rdx, rbx, rbp, rsi,
rdi, r8, r9, r10, r11};
static constexpr int kNumberOfSavedRegs = sizeof(saved_regs) / sizeof(Register);
int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
Register exclusion1,
Register exclusion2,
Register exclusion3) const {
Register exclusion) const {
int bytes = 0;
for (int i = 0; i < kNumberOfSavedRegs; i++) {
Register reg = saved_regs[i];
if (reg != exclusion1 && reg != exclusion2 && reg != exclusion3) {
bytes += kSystemPointerSize;
}
}
RegList saved_regs = kCallerSaved - exclusion;
bytes += kSystemPointerSize * saved_regs.Count();
// R12 to r15 are callee save on all platforms.
if (fp_mode == SaveFPRegsMode::kSave) {
......@@ -801,19 +790,17 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
return bytes;
}
int TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
Register exclusion2, Register exclusion3) {
int TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode,
Register exclusion) {
ASM_CODE_COMMENT(this);
// We don't allow a GC in a write barrier slow path so there is no need to
// store the registers in any particular way, but we do have to store and
// restore them.
int bytes = 0;
for (int i = 0; i < kNumberOfSavedRegs; i++) {
Register reg = saved_regs[i];
if (reg != exclusion1 && reg != exclusion2 && reg != exclusion3) {
pushq(reg);
bytes += kSystemPointerSize;
}
RegList saved_regs = kCallerSaved - exclusion;
for (Register reg : saved_regs) {
pushq(reg);
bytes += kSystemPointerSize;
}
// R12 to r15 are callee save on all platforms.
......@@ -834,8 +821,7 @@ int TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
return bytes;
}
int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
Register exclusion2, Register exclusion3) {
int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion) {
ASM_CODE_COMMENT(this);
int bytes = 0;
if (fp_mode == SaveFPRegsMode::kSave) {
......@@ -852,12 +838,10 @@ int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
bytes += delta;
}
for (int i = kNumberOfSavedRegs - 1; i >= 0; i--) {
Register reg = saved_regs[i];
if (reg != exclusion1 && reg != exclusion2 && reg != exclusion3) {
popq(reg);
bytes += kSystemPointerSize;
}
RegList saved_regs = kCallerSaved - exclusion;
for (Register reg : base::Reversed(saved_regs)) {
popq(reg);
bytes += kSystemPointerSize;
}
return bytes;
......
......@@ -530,25 +530,19 @@ class V8_EXPORT_PRIVATE TurboAssembler
// Calculate how much stack space (in bytes) are required to store caller
// registers excluding those specified in the arguments.
int RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
Register exclusion1 = no_reg,
Register exclusion2 = no_reg,
Register exclusion3 = no_reg) const;
Register exclusion = no_reg) const;
// PushCallerSaved and PopCallerSaved do not arrange the registers in any
// particular order so they are not useful for calls that can cause a GC.
// The caller can exclude up to 3 registers that do not need to be saved and
// The caller can exclude a register that does not need to be saved and
// restored.
// Push caller saved registers on the stack, and return the number of bytes
// stack pointer is adjusted.
int PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1 = no_reg,
Register exclusion2 = no_reg,
Register exclusion3 = no_reg);
int PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion = no_reg);
// Restore caller saved registers from the stack, and return the number of
// bytes stack pointer is adjusted.
int PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1 = no_reg,
Register exclusion2 = no_reg,
Register exclusion3 = no_reg);
int PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion = no_reg);
// Compute the start of the generated instruction stream from the current PC.
// This is an alternative to embedding the {CodeObject} handle as a reference.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment