Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Varargs support via FFI functions #121

Merged
merged 7 commits into from Jan 6, 2022
Merged

Conversation

headius
Copy link
Member

@headius headius commented Jan 5, 2022

This PR modifies variadic function call logic to use the ffi_prep_cif_var function provided by libffi for passing varargs. This primarily improves support on Apple Silicon, which (at least under Darwin) structures the call stack for varargs differently than other platforms (a mix of registers and stack).

This is the first part of fixes to better support Apple Silicon. Additional fixes are required in the upstream libraries like jnr-ffi and jnr-posix.

Note that at the time I submit this initial PR it still requires the native library to be rebuilt for each platform. Given the challenges of doing so right now, I hope to find a way to make the Java changes work with the older builds of the C library. We will address build and versioning issues in the future.

In order to call varargs functions using ffi_prep_cif_var we need
to know the fixed argument count for the target method. This
change adds such a field to CallContext allowing it to select the
appropriate function.
@headius headius added this to the 1.4.0 milestone Jan 5, 2022
@headius
Copy link
Member Author

headius commented Jan 5, 2022

As expected, the pre-built linux binaries failed. Will mark this as non-draft once I know they work with the changes, and we can incrementally get the non-Darwin binaries rebuilt.

In order to avoid changing the JNI stub or requiring that
currently-working platforms rebuild that stub, this patch moves
the fixed param count into the high word of the existing `flags`
parameter passed into newCallContext. Older builds will ignore
this value — since they only mask off low word bits — and
continue to use the non-variadic FFI logic that already works on
those platforms. Once rebuilt, they will start to see the fixed
count and use it for the variadic FFI logic.
@headius
Copy link
Member Author

headius commented Jan 5, 2022

Most recent commit moves the fixed param count into the high word of the flags parameter passed into the native side of Foreign.newCallContext. These high bits are ignored by the older builds, which only mask off low-word bits for JFFI behavioral flags. I believe this is safe to release with only the Darwin binary rebuilt.

I fully acknowledge the slight hackiness of passing the fixed count in the flags field but any other solution would require changing the C stub and introducing fallbacks on platforms where it has not been rebuilt. That feels hackier to me. We will need to address the versioning of the native stub better (see #93).

@headius headius marked this pull request as ready for review January 5, 2022 14:13
JRuby FFI duplicates some logic, notably logic from
VariadicInvoker, due to private or package-private utilities
in jnr-ffi. In this case, it needs to be able to set up the
CallContext for the function using the fixed param count, but
there's no constructor to do this and no utility function to
create the CallContext manually.

This duplication will need to be cleaned up but that is out of
scope for this change. I add this constructor so that the duped
code in JRuby can make the proper call.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Varargs support on Apple Silicon
1 participant