diff options
| author | Jeff Zhang <jeff@39bytes.dev> | 2026-01-20 18:31:26 -0500 |
|---|---|---|
| committer | Alan Wu <XrXr@users.noreply.github.com> | 2026-01-20 19:42:25 -0500 |
| commit | f7e73ba3bf9ced61ac9cca5cf042fd0efe398f69 (patch) | |
| tree | c2aa093c35376c849ac01ad1c4e80f1751633bcb /zjit/src/codegen.rs | |
| parent | e24b52885feaa87cdb5796c2a08e5995274e83cb (diff) | |
ZJIT: A64: Avoid gaps in the stack when preserving registers for calls
Previously, we used a `str x, [sp, #-0x10]!` for each value, which
left an 8-byte gap. Use STP to store a pair at a time instead.
Diffstat (limited to 'zjit/src/codegen.rs')
| -rw-r--r-- | zjit/src/codegen.rs | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs index 0ae85c24a2..4dae41bf02 100644 --- a/zjit/src/codegen.rs +++ b/zjit/src/codegen.rs @@ -2638,8 +2638,17 @@ pub fn gen_function_stub_hit_trampoline(cb: &mut CodeBlock) -> Result<CodePtr, C asm.frame_setup(&[]); asm_comment!(asm, "preserve argument registers"); - for ® in ALLOC_REGS.iter() { - asm.cpush(Opnd::Reg(reg)); + + for pair in ALLOC_REGS.chunks(2) { + match *pair { + [reg0, reg1] => { + asm.cpush_pair(Opnd::Reg(reg0), Opnd::Reg(reg1)); + } + [reg] => { + asm.cpush(Opnd::Reg(reg)); + } + _ => unreachable!("chunks(2)") + } } if cfg!(target_arch = "x86_64") && ALLOC_REGS.len() % 2 == 1 { asm.cpush(Opnd::Reg(ALLOC_REGS[0])); // maintain alignment for x86_64 @@ -2653,8 +2662,17 @@ pub fn gen_function_stub_hit_trampoline(cb: &mut CodeBlock) -> Result<CodePtr, C if cfg!(target_arch = "x86_64") && ALLOC_REGS.len() % 2 == 1 { asm.cpop_into(Opnd::Reg(ALLOC_REGS[0])); } - for ® in ALLOC_REGS.iter().rev() { - asm.cpop_into(Opnd::Reg(reg)); + + for pair in ALLOC_REGS.chunks(2).rev() { + match *pair { + [reg] => { + asm.cpop_into(Opnd::Reg(reg)); + } + [reg0, reg1] => { + asm.cpop_pair_into(Opnd::Reg(reg1), Opnd::Reg(reg0)); + } + _ => unreachable!("chunks(2)") + } } // Discard the current frame since the JIT function will set it up again |
