mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 14:24:46 +02:00
8336768: Allow captureCallState and critical linker options to be combined
Reviewed-by: mcimadamore
This commit is contained in:
parent
63af2f42b7
commit
8cad0431ff
14 changed files with 178 additions and 86 deletions
|
@ -852,8 +852,6 @@ public sealed interface Linker permits AbstractLinker {
|
|||
* // use errno
|
||||
* }
|
||||
* }
|
||||
* <p>
|
||||
* This linker option can not be combined with {@link #critical}.
|
||||
*
|
||||
* @param capturedState the names of the values to save
|
||||
* @throws IllegalArgumentException if at least one of the provided
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -195,6 +195,10 @@ public class CallingSequence {
|
|||
return !linkerOptions.isCritical();
|
||||
}
|
||||
|
||||
public boolean usingAddressPairs() {
|
||||
return linkerOptions.allowsHeapAccess();
|
||||
}
|
||||
|
||||
public int numLeadingParams() {
|
||||
return 2 + (linkerOptions.hasCapturedCallState() ? 1 : 0); // 2 for addr, allocator
|
||||
}
|
||||
|
|
|
@ -108,9 +108,18 @@ public class CallingSequenceBuilder {
|
|||
MethodType calleeMethodType;
|
||||
if (!forUpcall) {
|
||||
if (linkerOptions.hasCapturedCallState()) {
|
||||
addArgumentBinding(0, MemorySegment.class, ValueLayout.ADDRESS, List.of(
|
||||
Binding.unboxAddress(),
|
||||
Binding.vmStore(abi.capturedStateStorage(), long.class)));
|
||||
if (linkerOptions.allowsHeapAccess()) {
|
||||
addArgumentBinding(0, MemorySegment.class, ValueLayout.ADDRESS, List.of(
|
||||
Binding.dup(),
|
||||
Binding.segmentBase(),
|
||||
Binding.vmStore(abi.capturedStateStorage(), Object.class),
|
||||
Binding.segmentOffsetAllowHeap(),
|
||||
Binding.vmStore(null, long.class)));
|
||||
} else {
|
||||
addArgumentBinding(0, MemorySegment.class, ValueLayout.ADDRESS, List.of(
|
||||
Binding.unboxAddress(),
|
||||
Binding.vmStore(abi.capturedStateStorage(), long.class)));
|
||||
}
|
||||
}
|
||||
addArgumentBinding(0, MemorySegment.class, ValueLayout.ADDRESS, List.of(
|
||||
Binding.unboxAddress(),
|
||||
|
|
|
@ -84,7 +84,8 @@ public class DowncallLinker {
|
|||
leafType,
|
||||
callingSequence.needsReturnBuffer(),
|
||||
callingSequence.capturedStateMask(),
|
||||
callingSequence.needsTransition()
|
||||
callingSequence.needsTransition(),
|
||||
callingSequence.usingAddressPairs()
|
||||
);
|
||||
MethodHandle handle = JLIA.nativeMethodHandle(nep);
|
||||
|
||||
|
|
|
@ -63,11 +63,7 @@ public class LinkerOptions {
|
|||
optionMap.put(option.getClass(), opImpl);
|
||||
}
|
||||
|
||||
LinkerOptions linkerOptions = new LinkerOptions(optionMap);
|
||||
if (linkerOptions.hasCapturedCallState() && linkerOptions.isCritical()) {
|
||||
throw new IllegalArgumentException("Incompatible linker options: captureCallState, critical");
|
||||
}
|
||||
return linkerOptions;
|
||||
return new LinkerOptions(optionMap);
|
||||
}
|
||||
|
||||
public static LinkerOptions empty() {
|
||||
|
|
|
@ -60,11 +60,12 @@ public class NativeEntryPoint {
|
|||
MethodType methodType,
|
||||
boolean needsReturnBuffer,
|
||||
int capturedStateMask,
|
||||
boolean needsTransition) {
|
||||
boolean needsTransition,
|
||||
boolean usingAddressPairs) {
|
||||
if (returnMoves.length > 1 != needsReturnBuffer) {
|
||||
throw new AssertionError("Multiple register return, but needsReturnBuffer was false");
|
||||
}
|
||||
checkType(methodType, needsReturnBuffer, capturedStateMask);
|
||||
checkMethodType(methodType, needsReturnBuffer, capturedStateMask, usingAddressPairs);
|
||||
|
||||
CacheKey key = new CacheKey(methodType, abi, Arrays.asList(argMoves), Arrays.asList(returnMoves),
|
||||
needsReturnBuffer, capturedStateMask, needsTransition);
|
||||
|
@ -80,14 +81,26 @@ public class NativeEntryPoint {
|
|||
});
|
||||
}
|
||||
|
||||
private static void checkType(MethodType methodType, boolean needsReturnBuffer, int savedValueMask) {
|
||||
if (methodType.parameterType(0) != long.class) {
|
||||
throw new AssertionError("Address expected as first param: " + methodType);
|
||||
private static void checkMethodType(MethodType methodType, boolean needsReturnBuffer, int savedValueMask,
|
||||
boolean usingAddressPairs) {
|
||||
int checkIdx = 0;
|
||||
checkParamType(methodType, checkIdx++, long.class, "Function address");
|
||||
if (needsReturnBuffer) {
|
||||
checkParamType(methodType, checkIdx++, long.class, "Return buffer address");
|
||||
}
|
||||
int checkIdx = 1;
|
||||
if ((needsReturnBuffer && methodType.parameterType(checkIdx++) != long.class)
|
||||
|| (savedValueMask != 0 && methodType.parameterType(checkIdx) != long.class)) {
|
||||
throw new AssertionError("return buffer and/or preserved value address expected: " + methodType);
|
||||
if (savedValueMask != 0) { // capturing call state
|
||||
if (usingAddressPairs) {
|
||||
checkParamType(methodType, checkIdx++, Object.class, "Capture state heap base");
|
||||
checkParamType(methodType, checkIdx, long.class, "Capture state offset");
|
||||
} else {
|
||||
checkParamType(methodType, checkIdx, long.class, "Capture state address");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkParamType(MethodType methodType, int checkIdx, Class<?> expectedType, String name) {
|
||||
if (methodType.parameterType(checkIdx) != expectedType) {
|
||||
throw new AssertionError(name + " expected at index " + checkIdx + ": " + methodType);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -163,8 +163,14 @@ public final class FallbackLinker extends AbstractLinker {
|
|||
acquiredSessions.add(targetImpl);
|
||||
|
||||
MemorySegment capturedState = null;
|
||||
Object captureStateHeapBase = null;
|
||||
if (invData.capturedStateMask() != 0) {
|
||||
capturedState = SharedUtils.checkCaptureSegment((MemorySegment) args[argStart++]);
|
||||
if (!invData.allowsHeapAccess) {
|
||||
SharedUtils.checkNative(capturedState);
|
||||
} else {
|
||||
captureStateHeapBase = capturedState.heapBase().orElse(null);
|
||||
}
|
||||
MemorySessionImpl capturedStateImpl = ((AbstractMemorySegmentImpl) capturedState).sessionImpl();
|
||||
capturedStateImpl.acquire0();
|
||||
acquiredSessions.add(capturedStateImpl);
|
||||
|
@ -199,7 +205,8 @@ public final class FallbackLinker extends AbstractLinker {
|
|||
retSeg = (invData.returnLayout() instanceof GroupLayout ? returnAllocator : arena).allocate(invData.returnLayout);
|
||||
}
|
||||
|
||||
LibFallback.doDowncall(invData.cif, target, retSeg, argPtrs, capturedState, invData.capturedStateMask(),
|
||||
LibFallback.doDowncall(invData.cif, target, retSeg, argPtrs,
|
||||
captureStateHeapBase, capturedState, invData.capturedStateMask(),
|
||||
heapBases, args.length);
|
||||
|
||||
Reference.reachabilityFence(invData.cif());
|
||||
|
|
|
@ -90,10 +90,11 @@ final class LibFallback {
|
|||
* @see jdk.internal.foreign.abi.CapturableState
|
||||
*/
|
||||
static void doDowncall(MemorySegment cif, MemorySegment target, MemorySegment retPtr, MemorySegment argPtrs,
|
||||
MemorySegment capturedState, int capturedStateMask,
|
||||
Object captureStateHeapBase, MemorySegment capturedState, int capturedStateMask,
|
||||
Object[] heapBases, int numArgs) {
|
||||
doDowncall(cif.address(), target.address(),
|
||||
retPtr == null ? 0 : retPtr.address(), argPtrs.address(),
|
||||
captureStateHeapBase,
|
||||
capturedState == null ? 0 : capturedState.address(), capturedStateMask,
|
||||
heapBases, numArgs);
|
||||
}
|
||||
|
@ -212,7 +213,7 @@ final class LibFallback {
|
|||
private static native int createClosure(long cif, Object userData, long[] ptrs);
|
||||
private static native void freeClosure(long closureAddress, long globalTarget);
|
||||
private static native void doDowncall(long cif, long fn, long rvalue, long avalues,
|
||||
long capturedState, int capturedStateMask,
|
||||
Object captureStateHeapBase, long capturedState, int capturedStateMask,
|
||||
Object[] heapBases, int numArgs);
|
||||
|
||||
private static native int ffi_prep_cif(long cif, int abi, int nargs, long rtype, long atypes);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue