Currently, in x64 the list of caller-saved registers to be potentially spilled in ZGC barrier stubs is hard-coded in the body of ZSaveLiveRegisters::initialize(ZBarrierStubC2* stub):
RegMask caller_saved;
caller_saved.Insert(OptoReg::as_OptoReg(rax->as_VMReg()));
caller_saved.Insert(OptoReg::as_OptoReg(rcx->as_VMReg()));
caller_saved.Insert(OptoReg::as_OptoReg(rdx->as_VMReg()));
caller_saved.Insert(OptoReg::as_OptoReg(rsi->as_VMReg()));
caller_saved.Insert(OptoReg::as_OptoReg(rdi->as_VMReg()));
caller_saved.Insert(OptoReg::as_OptoReg(r8->as_VMReg()));
caller_saved.Insert(OptoReg::as_OptoReg(r9->as_VMReg()));
caller_saved.Insert(OptoReg::as_OptoReg(r10->as_VMReg()));
caller_saved.Insert(OptoReg::as_OptoReg(r11->as_VMReg()));
A more maintainable solution would be to compute these using the corresponding register mask and calls to 'c_reg_save_policy', using something like this:
#include "opto/ad.hpp"
(...)
RegMaskIterator int_regs(ALL_INT_REG_mask());
while (int_regs.has_next()) {
OptoReg::Name reg = int_regs.next();
if (c_reg_save_policy[reg] == 'C') {
caller_saved.Insert(reg);
}
}
A similar solution could be used for other platforms (e.g. aarch64), where the list of callee-saved registers to *not* be spilled is hard-coded instead.
An additional benefit of this solution for x64 is that it would avoid spilling RSI and RDI on Windows.
RegMask caller_saved;
caller_saved.Insert(OptoReg::as_OptoReg(rax->as_VMReg()));
caller_saved.Insert(OptoReg::as_OptoReg(rcx->as_VMReg()));
caller_saved.Insert(OptoReg::as_OptoReg(rdx->as_VMReg()));
caller_saved.Insert(OptoReg::as_OptoReg(rsi->as_VMReg()));
caller_saved.Insert(OptoReg::as_OptoReg(rdi->as_VMReg()));
caller_saved.Insert(OptoReg::as_OptoReg(r8->as_VMReg()));
caller_saved.Insert(OptoReg::as_OptoReg(r9->as_VMReg()));
caller_saved.Insert(OptoReg::as_OptoReg(r10->as_VMReg()));
caller_saved.Insert(OptoReg::as_OptoReg(r11->as_VMReg()));
A more maintainable solution would be to compute these using the corresponding register mask and calls to 'c_reg_save_policy', using something like this:
#include "opto/ad.hpp"
(...)
RegMaskIterator int_regs(ALL_INT_REG_mask());
while (int_regs.has_next()) {
OptoReg::Name reg = int_regs.next();
if (c_reg_save_policy[reg] == 'C') {
caller_saved.Insert(reg);
}
}
A similar solution could be used for other platforms (e.g. aarch64), where the list of callee-saved registers to *not* be spilled is hard-coded instead.
An additional benefit of this solution for x64 is that it would avoid spilling RSI and RDI on Windows.