< prev index next > src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java
Print this page
import java.lang.foreign.StructLayout;
import java.lang.foreign.UnionLayout;
import java.lang.foreign.ValueLayout;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
+ import java.util.HashSet;
import java.util.List;
import java.nio.ByteOrder;
import java.util.Objects;
import java.util.Set;
}
private record LinkRequest(FunctionDescriptor descriptor, LinkerOptions options) {}
private final SoftReferenceCache<LinkRequest, MethodHandle> DOWNCALL_CACHE = new SoftReferenceCache<>();
private final SoftReferenceCache<LinkRequest, UpcallStubFactory> UPCALL_CACHE = new SoftReferenceCache<>();
+ private final Set<MemoryLayout> CANONICAL_LAYOUTS_CACHE = new HashSet<>(canonicalLayouts().values());
@Override
@CallerSensitive
public final MethodHandle downcallHandle(MemorySegment symbol, FunctionDescriptor function, Option... options) {
Reflection.ensureNativeAccess(Reflection.getCallerClass(), Linker.class, "downcallHandle");
public final MethodHandle downcallHandle(FunctionDescriptor function, Option... options) {
Reflection.ensureNativeAccess(Reflection.getCallerClass(), Linker.class, "downcallHandle");
return downcallHandle0(function, options);
}
! private final MethodHandle downcallHandle0(FunctionDescriptor function, Option... options) {
Objects.requireNonNull(function);
Objects.requireNonNull(options);
checkLayouts(function);
function = stripNames(function);
LinkerOptions optionSet = LinkerOptions.forDowncall(function, options);
public final MethodHandle downcallHandle(FunctionDescriptor function, Option... options) {
Reflection.ensureNativeAccess(Reflection.getCallerClass(), Linker.class, "downcallHandle");
return downcallHandle0(function, options);
}
! private MethodHandle downcallHandle0(FunctionDescriptor function, Option... options) {
Objects.requireNonNull(function);
Objects.requireNonNull(options);
checkLayouts(function);
function = stripNames(function);
LinkerOptions optionSet = LinkerOptions.forDowncall(function, options);
checkLayoutRecursive(sl.elementLayout());
}
}
// check for trailing padding
! private static void checkGroupSize(GroupLayout gl, long maxUnpaddedOffset) {
long expectedSize = Utils.alignUp(maxUnpaddedOffset, gl.byteAlignment());
if (gl.byteSize() != expectedSize) {
throw new IllegalArgumentException("Layout '" + gl + "' has unexpected size: "
+ gl.byteSize() + " != " + expectedSize);
}
}
// checks both that there is no excess padding between 'memberLayout' and
// the previous layout
! private static void checkMemberOffset(StructLayout parent, MemoryLayout memberLayout,
long lastUnpaddedOffset, long offset) {
long expectedOffset = Utils.alignUp(lastUnpaddedOffset, memberLayout.byteAlignment());
if (expectedOffset != offset) {
throw new IllegalArgumentException("Member layout '" + memberLayout + "', of '" + parent + "'" +
" found at unexpected offset: " + offset + " != " + expectedOffset);
}
}
! private static void checkSupported(ValueLayout valueLayout) {
valueLayout = valueLayout.withoutName();
if (valueLayout instanceof AddressLayout addressLayout) {
valueLayout = addressLayout.withoutTargetLayout();
}
! if (!SUPPORTED_LAYOUTS.contains(valueLayout.withoutName())) {
throw new IllegalArgumentException("Unsupported layout: " + valueLayout);
}
}
! private static void checkHasNaturalAlignment(MemoryLayout layout) {
if (!((AbstractLayout<?>) layout).hasNaturalAlignment()) {
throw new IllegalArgumentException("Layout alignment must be natural alignment: " + layout);
}
}
checkLayoutRecursive(sl.elementLayout());
}
}
// check for trailing padding
! private void checkGroupSize(GroupLayout gl, long maxUnpaddedOffset) {
long expectedSize = Utils.alignUp(maxUnpaddedOffset, gl.byteAlignment());
if (gl.byteSize() != expectedSize) {
throw new IllegalArgumentException("Layout '" + gl + "' has unexpected size: "
+ gl.byteSize() + " != " + expectedSize);
}
}
// checks both that there is no excess padding between 'memberLayout' and
// the previous layout
! private void checkMemberOffset(StructLayout parent, MemoryLayout memberLayout,
long lastUnpaddedOffset, long offset) {
long expectedOffset = Utils.alignUp(lastUnpaddedOffset, memberLayout.byteAlignment());
if (expectedOffset != offset) {
throw new IllegalArgumentException("Member layout '" + memberLayout + "', of '" + parent + "'" +
" found at unexpected offset: " + offset + " != " + expectedOffset);
}
}
! private void checkSupported(ValueLayout valueLayout) {
valueLayout = valueLayout.withoutName();
if (valueLayout instanceof AddressLayout addressLayout) {
valueLayout = addressLayout.withoutTargetLayout();
}
! if (!CANONICAL_LAYOUTS_CACHE.contains(valueLayout.withoutName())) {
throw new IllegalArgumentException("Unsupported layout: " + valueLayout);
}
}
! private void checkHasNaturalAlignment(MemoryLayout layout) {
if (!((AbstractLayout<?>) layout).hasNaturalAlignment()) {
throw new IllegalArgumentException("Layout alignment must be natural alignment: " + layout);
}
}
private static FunctionDescriptor stripNames(FunctionDescriptor function) {
return function.returnLayout()
.map(rl -> FunctionDescriptor.of(stripNames(rl), stripNames(function.argumentLayouts())))
.orElseGet(() -> FunctionDescriptor.ofVoid(stripNames(function.argumentLayouts())));
}
-
- private static final Set<MemoryLayout> SUPPORTED_LAYOUTS = Set.of(
- ValueLayout.JAVA_BOOLEAN,
- ValueLayout.JAVA_BYTE,
- ValueLayout.JAVA_CHAR,
- ValueLayout.JAVA_SHORT,
- ValueLayout.JAVA_INT,
- ValueLayout.JAVA_FLOAT,
- ValueLayout.JAVA_LONG,
- ValueLayout.JAVA_DOUBLE,
- ValueLayout.ADDRESS
- );
}
< prev index next >