Pass unions by value with the C ABI's register classes - #9693
aminmansuri wants to merge 8 commits into
Conversation
union_spec.rb and UnionTest.c match the ffi gem's March 2026 versions without its JRuby skips; union_by_value_spec.rb adds mixed-class, nested, oversize and callback shapes.
Pick the libffi filler from the union's leaves: the float type for a homogeneous floating aggregate, per-eightbyte SSE/INTEGER cells on SysV x86_64, an integer of the union's alignment otherwise.
|
Still a work in progress. I'm going to run a few checks still. |
A 4-aligned union whose cells differ in class, nested at offset 4, takes the enclosing struct's eightbytes: (INTEGER, SSE) on SysV x86_64. Argument, return and callback forms.
libffi merges the cells into eightbytes at the union's offset inside an enclosing struct; a per-cell class is exact there and unchanged for a union passed on its own.
No behaviour change: the one-argument newUnion hands the host platform to the overload, which tests can call with any CPU and OS.
A union of one floating type is a floating-point aggregate on AArch64, ARM, PPC64 ELFv2 and x86_64; riscv64, loongarch64 and s390x pass every union in integer registers, so the integer filler must stay there.
riscv64, loongarch64 and s390x pass unions in integer registers while libffi would put a struct of doubles into FP registers; keep the integer filler there and the float one on AArch64, ARM, PPC64 ELFv2 and x86_64.
JRuby's FFI rejects :long_double layout members, so no union has a long double leaf or an alignment of 16; the integer filler list is now what its name says.
|
Ok.. added some improvements I think this'll do the trick. |
headius
left a comment
There was a problem hiding this comment.
This appears to make sense but I want it to bake in jruby-head for a while. Please rebase to master and we can merge after the 10.1.2.0 release. Once it has been in the wild for a bit we can merge a backport to 10.0.
|
ok.. i worked on this because it was on the list for 10.0.7.0 and I wanted that to come out asap. But no problem. |
|
@aminmansuri I appreciate you looking at the targeted issues! This one just turned out to be a bigger issue than I expected. In the future I will be marking most issues for the "10.0.x" and "10.1.x" milestones so they're not blockers for release. This is meant to indicate "this should be fixed along the 10.0 or 10.1 release line" and not a hard target until we really want to hard target. |
|
I created the PR for master now. |
|
For future reference, it's possible to rebase within the same PR, by rebasing locally and force pushing and then editing the PR to target the other branch (same edit button as for changing the title of the PR). Since you already created the other one, we'll go ahead and close this one. |
|
Yeah.. I don't like to force push in any circumstance. I'm a coward. |
Fixes #9329.
Makes JRuby pass C unions by value the way a C compiler does.
Before, every 8-byte union went in an integer register, so a union of floats came back as garbage and a callback receiving one crashed the JVM.
Now the union's members decide the register class, on x86_64 and ARM64.