Skip to content

Commit

Permalink
7903437: Improve translation strategy for function pointers
Browse files Browse the repository at this point in the history
Reviewed-by: jvernee
  • Loading branch information
mcimadamore committed Feb 17, 2023
1 parent 8f41279 commit dfafbbe
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 13 deletions.
27 changes: 23 additions & 4 deletions src/main/java/org/openjdk/jextract/impl/ConstantBuilder.java
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -197,7 +201,7 @@ public Constant emitIfAbsent(String name, Constant.Kind kind, Supplier<Constant>
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);
Expand Down Expand Up @@ -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<String> prefixElementNames) {
String layoutAccess = rootLayoutName != null ?
Expand Down
Expand Up @@ -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");
Expand All @@ -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();
Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -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() &&
Expand Down
Expand Up @@ -71,11 +71,18 @@ final class RuntimeHelper {
orElse(null);
}

static <Z> MemorySegment upcallStub(Class<Z> 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 <Z> 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);
}
Expand Down

0 comments on commit dfafbbe

Please sign in to comment.