RFR: 7903437: Improve translation strategy for function pointers
Jorn Vernee
jvernee at openjdk.org
Fri Feb 17 22:01:48 UTC 2023
On Fri, 17 Feb 2023 15:32:53 GMT, Maurizio Cimadamore <mcimadamore at openjdk.org> wrote:
> The current translation stragegy for function pointers is not very efficient. Every time a lambda expression is turned into an upcall stub, a new method handle lookup is performed, which is quite a slow operation.
>
> This patch improves the translation strategy so that the lookup is only performed once. For instance, considering the following `typedef`:
>
>
> typedef void (*cb)(int, int);
>
>
> jextract will generate the following functional interface:
>
>
> import static java.lang.foreign.ValueLayout.*;
> /**
> * {@snippet :
> * void (*cb)(int,int);
> * }
> */
> public interface cb {
>
> void apply(int _x0, int _x1);
> static MemorySegment allocate(cb fi, Arena scope) {
> return RuntimeHelper.upcallStub(constants$0.cb_UP$MH, fi, constants$0.cb$FUNC, scope);
> }
> static cb ofAddress(MemorySegment addr, Arena arena) {
> MemorySegment symbol = addr.reinterpret(arena.scope(), null);
> return (int __x0, int __x1) -> {
> try {
> constants$0.cb_DOWN$MH.invokeExact(symbol, __x0, __x1);
> } catch (Throwable ex$) {
> throw new AssertionError("should not reach here", ex$);
> }
> };
> }
> }
>
>
> Where the constants are defined as follows:
>
>
> static final FunctionDescriptor cb$FUNC = FunctionDescriptor.ofVoid(
> Constants$root.C_INT$LAYOUT,
> Constants$root.C_INT$LAYOUT
> );
>
> static final FunctionDescriptor cb_UP$FUNC = FunctionDescriptor.ofVoid(
> Constants$root.C_INT$LAYOUT,
> Constants$root.C_INT$LAYOUT
> );
>
> static final MethodHandle cb_UP$MH = RuntimeHelper.upcallHandle(cb.class, "apply", constants$0.cb_UP$FUNC);
>
> static final FunctionDescriptor cb_DOWN$FUNC = FunctionDescriptor.ofVoid(
> Constants$root.C_INT$LAYOUT,
> Constants$root.C_INT$LAYOUT
> );
>
> static final MethodHandle cb_DOWN$MH = RuntimeHelper.downcallHandle(
> constants$0.cb_DOWN$FUNC
> );
>
>
> And, where `RuntimeHelper::upcallHandler` is defined as follows:
>
>
> static MethodHandle upcallHandle(Class<?> fi, String name, FunctionDescriptor fdesc) {
> try {
> return MH_LOOKUP.findVirtual(fi, name, fdesc.toMethodType());
> } catch (Throwable ex) {
> throw new AssertionError(ex);
> }
> }
>
>
> This allows to perform the method handle lookup only once. This means that when creating an upcall stub, we only have to `bind` the functional interface instance to the method handle, and then create an upcall stub with the resulting handle. Both operations should be fast after the first time, because of caching.
> > Should we generate the clang bindings with this new translation strategy as well?
>
> Yes, but I think it would be better to do that separately, as that adds some noise (also because of other changes caused by the API update).
Good point.
-------------
Marked as reviewed by jvernee (no project role).
PR: https://git.openjdk.org/jextract/pull/109
More information about the jextract-dev
mailing list