ZJIT: Fix SP alignment on JIT-to-JIT calls for x86_64 #13900
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR fixes the alignment of the native stack pointer on JIT-to-JIT calls for x86_64. It fixes the crash on the 30k_ifelse benchmark.
What was happening
When making a call on x86_64, SP should be 16-byte aligned. But the call instruction itself bumps it by 8 bytes, so when you're at the beginning of the function, it's misaligned.
gen_entry_prologue()
was pushing 32 bytes, so the JIT trampoline carried the misaligned state to the call into the JIT function.When the call instruction makes another 8-byte bump to enter the JIT function, it's aligned, so
aligned_stack_bytes()
andalloc_regs()
pushing 16-byte-aligned bytes made sense. However, when it makes a JIT-to-JIT call, the call instruction makes it misaligned on the callee JIT function, so C functions called in it had misaligned SP.Moreover, when a JIT-to-JIT side-exits, the caller frame did not restore the frame size bumped for spilled basic block arguments. So leaving JIT-to-JIT calls with many basic block arguments could lead to wrong/misaligned SP as well.
What happens now
This PR changes
gen_entry_prologue()
to push 24 bytes instead. Combined with the 8 byte pushed by the call instruction, the JIT function is called with SP aligned properly. The JIT function then needs to fix the SP misaligned by the call instruction, soaligned_stack_bytes()
now pushes an odd number of slots.This PR also changes JIT-to-JIT calls to use a small side exit that only restores SP when the call returns Qundef.