oracle / graal

GraalVM compiles Java applications into native executables that start instantly, scale fast, and use fewer compute resources 🚀
https://www.graalvm.org
Other
20.29k stars 1.63k forks source link

[GR-18218] Full support for the Foreign Function & Memory API in Native Image #8113

Open fniephaus opened 9 months ago

fniephaus commented 9 months ago

TL;DR

Add full support for the Foreign Function & Memory API (JEP 454) to Native Image.

Goals

The Foreign Function & Memory (FFM) API becomes GA in JDK 22, a new API "by which Java programs can interoperate with code and data outside of the Java runtime."

We plan to add full support for the FFM API to Native Image, although not in time for the JDK 22 release. Note that GraalVM for JDK 22 will support the API on HotSpot (e.g. when Graal is used as a JIT compiler).

As part of #7152 and #7238, we already added preliminary support for foreign downcalls and an infrastructure to support upcalls in the future. Documentation on what parts of the FFM API are working in Native Image and how they can be used can be found here.

Non-Goals

Related PRs

msgilligan commented 6 months ago

Is there an issue where we can track support for (downcalls) on ARM64 (aka aarch64)?

fniephaus commented 6 months ago

Is there an issue where we can track support for (downcalls) on ARM64 (aka aarch64)?

@msgilligan I would consider this to be in the scope of this roadmap item: JEP 454 includes aarch64, so full support in Native Image means that it works on all supported platforms including aarch64 on Linux/macOS.

jerboaa commented 6 months ago

One example of an upcall not working (yet) is described in #8616 AFAIUI.

jerboaa commented 6 months ago

@fniephaus Going by https://github.com/oracle/graal/discussions/8677 there should be better support for JEP 454 in latest master (commit https://github.com/oracle/graal/commit/7b51429d1c19595c1e9ddd8e3002159cd345dcae). Is that supposed to fix the test case from https://github.com/oracle/graal/issues/8616? It doesn't for me, fwiw. Just checking.

peter-hofer commented 6 months ago

@jerboaa despite the dynamic nature of the JEP 454 foreign call API, GraalVM Native Image needs to generate stub code for such calls ahead of time, which requires configuration or registration (like JNI calls do). Have a look at the org.graalvm.nativeimage.hosted.RuntimeForeignAccess class for use from a Feature. Also, any downcall method handles or upcall stubs must be created at runtime (with a Linker). It is not supported to create them during the image build and carry them over to runtime using the image heap. As a consequence of this and of dealing only with signatures, the calls use a generic method handle dispatch with little margin for optimization and also, upcall target methods further need to be registered for reflective access so that they can be called by method handle.

jerboaa commented 6 months ago

@jerboaa despite the dynamic nature of the JEP 454 foreign call API, GraalVM Native Image needs to generate stub code for such calls ahead of time, which requires configuration or registration (like JNI calls do).

I take it the native image agent won't help with that kind of registration config generation?

Have a look at the org.graalvm.nativeimage.hosted.RuntimeForeignAccess class for use from a Feature. Also, any downcall method handles or upcall stubs must be created at runtime (with a Linker). It is not supported to create them during the image build and carry them over to runtime using the image heap. As a consequence of this and of dealing only with signatures, the calls use a generic method handle dispatch with little margin for optimization and also, upcall target methods further need to be registered for reflective access so that they can be called by method handle.

OK thanks! Is there some documentation describing how this is supposed to get used going forward? Or maybe there are some examples I could look at? It sounds like #8616 won't work verbatim...

peter-hofer commented 6 months ago

The agent does not generate a foreign API configuration, but I believe it would catch the target methods for upcalls that are needed in the reflection configuration. We have this documentation page: https://www.graalvm.org/jdk23/reference-manual/native-image/native-code-interoperability/foreign-interface/ I believe that for #8616, registering the FunctionDescriptor objects for foreign calls and FFM.compare for method handle calls should suffice.

jerboaa commented 6 months ago

Thanks, I'll give that a go.

Arcane561 commented 3 weeks ago

@peter-hofer Good afternoon! I would like to ask if there are plans to add dynamic call of native method without mandatory registration at the build stage?

peter-hofer commented 3 weeks ago

@Arcane561 we are working on a mechanism that picks up the method handles that jextract generates without mandatory registration, but it expect it to be a while longer. @fangerer

chrisvest commented 3 weeks ago

Only jextract generated ones, or any handles following some supported patterns?