diff --git a/src/main/java/org/openjdk/jextract/impl/ConstantBuilder.java b/src/main/java/org/openjdk/jextract/impl/ConstantBuilder.java index e43281b7..2e8e5ddb 100644 --- a/src/main/java/org/openjdk/jextract/impl/ConstantBuilder.java +++ b/src/main/java/org/openjdk/jextract/impl/ConstantBuilder.java @@ -29,7 +29,6 @@ import java.lang.foreign.GroupLayout; import java.lang.foreign.MemorySegment; import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; import java.lang.foreign.SequenceLayout; import java.lang.foreign.StructLayout; import java.lang.foreign.ValueLayout; @@ -81,9 +80,14 @@ private Constant addVarHandle(String javaName, String nativeName, ValueLayout va () -> emitVarHandleField(javaName, nativeName, valueLayout, rootLayoutName, prefixElementNames)); } - public Constant addMethodHandle(String javaName, String nativeName, FunctionDescriptor descriptor, boolean isVarargs, boolean virtual) { + public Constant addDowncallMethodHandle(String javaName, String nativeName, FunctionDescriptor descriptor, boolean isVarargs, boolean virtual) { + return emitIfAbsent(javaName, Constant.Kind.METHOD_HANDLE, + () -> emitDowncallMethodHandleField(javaName, nativeName, descriptor, isVarargs, virtual)); + } + + public Constant addLookupMethodHandle(String javaName, String className, String name, FunctionDescriptor descriptor) { return emitIfAbsent(javaName, Constant.Kind.METHOD_HANDLE, - () -> emitMethodHandleField(javaName, nativeName, descriptor, isVarargs, virtual)); + () -> emitUpcallMethodHandleField(javaName, className, name, descriptor)); } public Constant addSegment(String javaName, String nativeName, MemoryLayout layout) { @@ -197,7 +201,7 @@ public Constant emitIfAbsent(String name, Constant.Kind kind, Supplier return constant; } - private Constant emitMethodHandleField(String javaName, String nativeName, FunctionDescriptor descriptor, boolean isVarargs, boolean virtual) { + private Constant emitDowncallMethodHandleField(String javaName, String nativeName, FunctionDescriptor descriptor, boolean isVarargs, boolean virtual) { Constant functionDesc = addFunctionDesc(javaName, descriptor); incrAlign(); String fieldName = Constant.Kind.METHOD_HANDLE.fieldName(javaName); @@ -226,6 +230,21 @@ private Constant emitMethodHandleField(String javaName, String nativeName, Funct return new Constant(className(), javaName, Constant.Kind.METHOD_HANDLE); } + private Constant emitUpcallMethodHandleField(String javaName, String className, String methodName, FunctionDescriptor descriptor) { + Constant functionDesc = addFunctionDesc(javaName, descriptor); + incrAlign(); + String fieldName = Constant.Kind.METHOD_HANDLE.fieldName(javaName); + indent(); + append(memberMods() + "MethodHandle "); + append(fieldName + " = RuntimeHelper.upcallHandle("); + append(className + ".class, "); + append("\"" + methodName + "\", "); + append(functionDesc.accessExpression()); + append(");\n"); + decrAlign(); + return new Constant(className(), javaName, Constant.Kind.METHOD_HANDLE); + } + private Constant emitVarHandleField(String javaName, String nativeName, ValueLayout valueLayout, String rootLayoutName, List prefixElementNames) { String layoutAccess = rootLayoutName != null ? diff --git a/src/main/java/org/openjdk/jextract/impl/FunctionalInterfaceBuilder.java b/src/main/java/org/openjdk/jextract/impl/FunctionalInterfaceBuilder.java index 98ed83b4..9b900bd0 100644 --- a/src/main/java/org/openjdk/jextract/impl/FunctionalInterfaceBuilder.java +++ b/src/main/java/org/openjdk/jextract/impl/FunctionalInterfaceBuilder.java @@ -97,13 +97,14 @@ private void emitFunctionalInterfaceMethod() { private void emitFunctionalFactories() { emitWithConstantClass(constantBuilder -> { Constant functionDesc = constantBuilder.addFunctionDesc(className(), fiDesc); + Constant upcallHandle = constantBuilder.addLookupMethodHandle(className() + "_UP", className(), "apply", fiDesc); incrAlign(); indent(); append(MEMBER_MODS + " MemorySegment allocate(" + className() + " fi, Arena scope) {\n"); incrAlign(); indent(); - append("return RuntimeHelper.upcallStub(" + className() + ".class, fi, " + - functionDesc.accessExpression() + ", scope);\n"); + append("return RuntimeHelper.upcallStub(" + + upcallHandle.accessExpression() + ", fi, " + functionDesc.accessExpression() + ", scope);\n"); decrAlign(); indent(); append("}\n"); @@ -113,7 +114,7 @@ private void emitFunctionalFactories() { private void emitFunctionalFactoryForPointer() { emitWithConstantClass(constantBuilder -> { - Constant mhConstant = constantBuilder.addMethodHandle(className(), className(), + Constant mhConstant = constantBuilder.addDowncallMethodHandle(className() + "_DOWN", className(), fiDesc, false, true); incrAlign(); indent(); diff --git a/src/main/java/org/openjdk/jextract/impl/HeaderFileBuilder.java b/src/main/java/org/openjdk/jextract/impl/HeaderFileBuilder.java index ab814a45..cbff73e1 100644 --- a/src/main/java/org/openjdk/jextract/impl/HeaderFileBuilder.java +++ b/src/main/java/org/openjdk/jextract/impl/HeaderFileBuilder.java @@ -24,7 +24,6 @@ */ package org.openjdk.jextract.impl; -import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.GroupLayout; import java.lang.foreign.MemorySegment; @@ -109,7 +108,7 @@ public void addFunction(Declaration.Function funcTree, FunctionDescriptor descri boolean isVarargs = funcTree.type().varargs(); emitWithConstantClass(constantBuilder -> { - Constant mhConstant = constantBuilder.addMethodHandle(javaName, nativeName, descriptor, isVarargs, false) + Constant mhConstant = constantBuilder.addDowncallMethodHandle(javaName, nativeName, descriptor, isVarargs, false) .emitGetter(this, MEMBER_MODS, Constant.QUALIFIED_NAME, nativeName); MethodType downcallType = descriptor.toMethodType(); boolean needsAllocator = descriptor.returnLayout().isPresent() && diff --git a/src/main/resources/org/openjdk/jextract/impl/resources/RuntimeHelper.java.template b/src/main/resources/org/openjdk/jextract/impl/resources/RuntimeHelper.java.template index e91182fb..51a2c5fa 100644 --- a/src/main/resources/org/openjdk/jextract/impl/resources/RuntimeHelper.java.template +++ b/src/main/resources/org/openjdk/jextract/impl/resources/RuntimeHelper.java.template @@ -71,11 +71,18 @@ final class RuntimeHelper { orElse(null); } - static MemorySegment upcallStub(Class fi, Z z, FunctionDescriptor fdesc, Arena scope) { + static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { try { - MethodHandle handle = MH_LOOKUP.findVirtual(fi, "apply", fdesc.toMethodType()); - handle = handle.bindTo(z); - return LINKER.upcallStub(handle, fdesc, scope); + return MH_LOOKUP.findVirtual(fi, name, fdesc.toMethodType()); + } catch (Throwable ex) { + throw new AssertionError(ex); + } + } + + static MemorySegment upcallStub(MethodHandle fiHandle, Z z, FunctionDescriptor fdesc, Arena scope) { + try { + fiHandle = fiHandle.bindTo(z); + return LINKER.upcallStub(fiHandle, fdesc, scope); } catch (Throwable ex) { throw new AssertionError(ex); }