Skip to content

Commit

Permalink
[GR-47831] Preparations for JEP 424 ("Panama") foreign upcalls in Nat…
Browse files Browse the repository at this point in the history
…ive Image.

PullRequest: graal/15203
  • Loading branch information
Ef55 authored and peter-hofer committed Aug 19, 2023
2 parents 7007979 + 7134c3d commit 0e19198
Show file tree
Hide file tree
Showing 19 changed files with 728 additions and 478 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ public static boolean differentRegisters(Object... values) {
Register r1 = registers.get(i);
for (int j = 0; j < i; j++) {
Register r2 = registers.get(j);
assert !r1.equals(r2) : r1 + " appears more than once";
assert !r1.equals(r2) : r1 + " appears more than once: " + j + " and " + i;
}
}
return true;
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ public static ConstantPool getConstantPool(MetaAccessProvider metaAccess) {
*/
@Platforms(Platform.HOSTED_ONLY.class)
public static String stubName(NativeEntryPointInfo nep) {
StringBuilder builder = new StringBuilder("downcall_(");
for (var param : nep.nativeMethodType().parameterArray()) {
StringBuilder builder = new StringBuilder("downcall_");
for (var param : nep.methodType().parameterArray()) {
builder.append(JavaKind.fromJavaClass(param).getTypeChar());
}
builder.append(")");
builder.append(JavaKind.fromJavaClass(nep.nativeMethodType().returnType()).getTypeChar());
builder.append("_");
builder.append(JavaKind.fromJavaClass(nep.methodType().returnType()).getTypeChar());

if (nep.returnsAssignment() != null) {
if (nep.needsReturnBuffer()) {
builder.append("_r");
}
if (nep.capturesCallState()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.c.function.CFunctionPointer;
import org.graalvm.nativeimage.c.function.CodePointer;
import org.graalvm.nativeimage.c.type.CIntPointer;
import org.graalvm.word.LocationIdentity;

Expand All @@ -51,15 +50,15 @@ public static ForeignFunctionsRuntime singleton() {
return ImageSingletons.lookup(ForeignFunctionsRuntime.class);
}

private final EconomicMap<NativeEntryPointInfo, FunctionPointerHolder> stubs = EconomicMap.create();
private final EconomicMap<NativeEntryPointInfo, FunctionPointerHolder> downcallStubs = EconomicMap.create();

public ForeignFunctionsRuntime() {
}

@Platforms(Platform.HOSTED_ONLY.class)
public void addStubPointer(NativeEntryPointInfo nepi, CFunctionPointer ptr) {
VMError.guarantee(!stubs.containsKey(nepi), "Multiple stubs generated for " + nepi);
stubs.put(nepi, new FunctionPointerHolder(ptr));
public void addDowncallStubPointer(NativeEntryPointInfo nep, CFunctionPointer ptr) {
VMError.guarantee(!downcallStubs.containsKey(nep), "Seems like multiple stubs were generated for " + nep);
VMError.guarantee(downcallStubs.put(nep, new FunctionPointerHolder(ptr)) == null);
}

/**
Expand All @@ -68,26 +67,24 @@ public void addStubPointer(NativeEntryPointInfo nepi, CFunctionPointer ptr) {
* {@link jdk.internal.foreign.abi.DowncallLinker#getBoundMethodHandle} and add information
* about the descriptor there.
*/
public CodePointer getStubPointer(NativeEntryPointInfo nep) {
FunctionPointerHolder pointer = stubs.get(nep);
public CFunctionPointer getDowncallStubPointer(NativeEntryPointInfo nep) {
FunctionPointerHolder pointer = downcallStubs.get(nep);
if (pointer == null) {
throw new UnregisteredDowncallStubException(nep);
throw new UnregisteredForeignStubException(nep);
} else {
return pointer.functionPointer;
}
}

@SuppressWarnings("serial")
public static class UnregisteredDowncallStubException extends RuntimeException {
private final NativeEntryPointInfo nep;
public static class UnregisteredForeignStubException extends RuntimeException {

UnregisteredDowncallStubException(NativeEntryPointInfo nep) {
UnregisteredForeignStubException(NativeEntryPointInfo nep) {
super(generateMessage(nep));
this.nep = nep;
}

private static String generateMessage(NativeEntryPointInfo nep) {
return "Cannot perform downcall with leaf type " + nep.nativeMethodType() + " as it was not registered at compilation time.";
return "Cannot perform downcall with leaf type " + nep.methodType() + " as it was not registered at compilation time.";
}
}

Expand Down Expand Up @@ -138,6 +135,7 @@ public static void captureCallState(int statesToCapture, CIntPointer captureBuff
++i;
}

@Platforms(Platform.HOSTED_ONLY.class)//
public static final SnippetRuntime.SubstrateForeignCallDescriptor CAPTURE_CALL_STATE = SnippetRuntime.findForeignCall(ForeignFunctionsRuntime.class,
"captureCallState", false, LocationIdentity.any());
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,15 @@
import java.util.Arrays;
import java.util.Objects;

import com.oracle.svm.core.graal.code.AssignedLocation;

import jdk.internal.foreign.abi.ABIDescriptor;
import jdk.internal.foreign.abi.VMStorage;

/**
* Carries information about an entrypoint for foreign function calls.
* {@link ForeignFunctionsRuntime#getStubPointer} allows getting the associated function pointer at
* runtime (if it exists).
* {@link ForeignFunctionsRuntime#getDowncallStubPointer} allows getting the associated function
* pointer at runtime (if it exists).
* <p>
* {@link NativeEntryPointInfo#linkMethodType} is of the form (<>: argument; []: optional argument)
* {@link NativeEntryPointInfo#methodType} is of the form (<>: argument; []: optional argument)
*
* <pre>
* {@code
Expand All @@ -50,15 +48,19 @@
*/
public final class NativeEntryPointInfo {
private final MethodType methodType;
private final AssignedLocation[] parameterAssignments;
private final AssignedLocation[] returnBuffering;
private final VMStorage[] parameterAssignments;
private final VMStorage[] returnBuffering;
private final boolean needsReturnBuffer;
private final boolean capturesState;
private final boolean needsTransition;

private NativeEntryPointInfo(MethodType methodType, AssignedLocation[] cc, AssignedLocation[] returnBuffering, boolean capturesState, boolean needsTransition) {
private NativeEntryPointInfo(MethodType methodType, VMStorage[] cc, VMStorage[] returnBuffering, boolean needsReturnBuffer, boolean capturesState, boolean needsTransition) {
assert methodType.parameterCount() == cc.length;
assert needsReturnBuffer == (returnBuffering.length > 1);
this.methodType = methodType;
this.parameterAssignments = cc;
this.returnBuffering = returnBuffering;
this.needsReturnBuffer = needsReturnBuffer;
this.capturesState = capturesState;
this.needsTransition = needsTransition;
}
Expand All @@ -69,13 +71,10 @@ public static NativeEntryPointInfo make(
boolean needsReturnBuffer,
int capturedStateMask,
boolean needsTransition) {
if (returnMoves.length > 1 != needsReturnBuffer) {
if ((returnMoves.length > 1) != needsReturnBuffer) {
throw new AssertionError("Multiple register return, but needsReturnBuffer was false");
}

AssignedLocation[] parametersAssignment = AbiUtils.singleton().toMemoryAssignment(argMoves, false);
AssignedLocation[] returnBuffering = needsReturnBuffer ? AbiUtils.singleton().toMemoryAssignment(returnMoves, true) : null;
return new NativeEntryPointInfo(methodType, parametersAssignment, returnBuffering, capturedStateMask != 0, needsTransition);
return new NativeEntryPointInfo(methodType, argMoves, returnMoves, needsReturnBuffer, capturedStateMask != 0, needsTransition);
}

public static Target_jdk_internal_foreign_abi_NativeEntryPoint makeEntryPoint(
Expand All @@ -86,8 +85,8 @@ public static Target_jdk_internal_foreign_abi_NativeEntryPoint makeEntryPoint(
int capturedStateMask,
boolean needsTransition) {
var info = make(argMoves, returnMoves, methodType, needsReturnBuffer, capturedStateMask, needsTransition);
long addr = ForeignFunctionsRuntime.singleton().getStubPointer(info).rawValue();
return new Target_jdk_internal_foreign_abi_NativeEntryPoint(info.linkMethodType(), addr, capturedStateMask);
long addr = ForeignFunctionsRuntime.singleton().getDowncallStubPointer(info).rawValue();
return new Target_jdk_internal_foreign_abi_NativeEntryPoint(info.methodType(), addr, capturedStateMask);
}

public int callAddressIndex() {
Expand All @@ -101,38 +100,23 @@ public int captureAddressIndex() {
return callAddressIndex() + 1;
}

/**
* Method type without any of the special arguments.
*/
public MethodType nativeMethodType() {
if (capturesCallState()) {
return this.methodType.dropParameterTypes(0, captureAddressIndex() + 1);
} else {
return this.methodType.dropParameterTypes(0, callAddressIndex() + 1);
}
}

/**
* Method type with all special arguments.
*/
public MethodType linkMethodType() {
public MethodType methodType() {
return this.methodType;
}

public boolean needsReturnBuffer() {
return this.returnBuffering != null;
return needsReturnBuffer;
}

public boolean capturesCallState() {
return capturesState;
}

public AssignedLocation[] parametersAssignment() {
assert parameterAssignments.length == this.nativeMethodType().parameterCount() : Arrays.toString(parameterAssignments) + " ; " + nativeMethodType();
public VMStorage[] parametersAssignment() {
return parameterAssignments;
}

public AssignedLocation[] returnsAssignment() {
public VMStorage[] returnsAssignment() {
return returnBuffering;
}

Expand All @@ -149,12 +133,12 @@ public boolean equals(Object o) {
return false;
}
NativeEntryPointInfo that = (NativeEntryPointInfo) o;
return capturesState == that.capturesState && needsTransition == that.needsTransition && Objects.equals(methodType, that.methodType) &&
return capturesState == that.capturesState && needsTransition == that.needsTransition && needsReturnBuffer == that.needsReturnBuffer && Objects.equals(methodType, that.methodType) &&
Arrays.equals(parameterAssignments, that.parameterAssignments) && Arrays.equals(returnBuffering, that.returnBuffering);
}

@Override
public int hashCode() {
return Objects.hash(methodType, capturesState, needsTransition, Arrays.hashCode(parameterAssignments), Arrays.hashCode(returnBuffering));
return Objects.hash(methodType, needsReturnBuffer, capturesState, needsTransition, Arrays.hashCode(parameterAssignments), Arrays.hashCode(returnBuffering));
}
}
Loading

0 comments on commit 0e19198

Please sign in to comment.