8318598: FFM stylistic cleanups
Co-authored-by: Per Minborg <pminborg@openjdk.org> Co-authored-by: Maurizio Cimadamore <mcimadamore@openjdk.org> Reviewed-by: mcimadamore
This commit is contained in:
parent
b1228de623
commit
8065233e8b
src/java.base/share/classes/jdk/internal/foreign
AbstractMemorySegmentImpl.javaConfinedSession.javaHeapMemorySegmentImpl.javaLayoutPath.javaMemorySessionImpl.javaSegmentFactories.javaSharedSession.javaStringSupport.javaSystemLookup.javaUtils.java
abi
AbstractLinker.javaBinding.javaCapturableState.javaSharedUtils.javaSoftReferenceCache.java
aarch64
fallback
ppc64
riscv64
s390
x64
layout
@ -49,7 +49,6 @@ import jdk.internal.access.JavaNioAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.access.foreign.UnmapperProxy;
|
||||
import jdk.internal.misc.ScopedMemoryAccess;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import jdk.internal.reflect.CallerSensitive;
|
||||
import jdk.internal.reflect.Reflection;
|
||||
import jdk.internal.util.ArraysSupport;
|
||||
@ -560,23 +559,23 @@ public abstract sealed class AbstractMemorySegmentImpl
|
||||
bufferScope = MemorySessionImpl.createHeap(bufferRef(bb));
|
||||
}
|
||||
if (base != null) {
|
||||
if (base instanceof byte[]) {
|
||||
return new HeapMemorySegmentImpl.OfByte(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
||||
} else if (base instanceof short[]) {
|
||||
return new HeapMemorySegmentImpl.OfShort(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
||||
} else if (base instanceof char[]) {
|
||||
return new HeapMemorySegmentImpl.OfChar(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
||||
} else if (base instanceof int[]) {
|
||||
return new HeapMemorySegmentImpl.OfInt(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
||||
} else if (base instanceof float[]) {
|
||||
return new HeapMemorySegmentImpl.OfFloat(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
||||
} else if (base instanceof long[]) {
|
||||
return new HeapMemorySegmentImpl.OfLong(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
||||
} else if (base instanceof double[]) {
|
||||
return new HeapMemorySegmentImpl.OfDouble(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
||||
} else {
|
||||
throw new AssertionError("Cannot get here");
|
||||
}
|
||||
return switch (base) {
|
||||
case byte[] __ ->
|
||||
new HeapMemorySegmentImpl.OfByte(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
||||
case short[] __ ->
|
||||
new HeapMemorySegmentImpl.OfShort(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
||||
case char[] __ ->
|
||||
new HeapMemorySegmentImpl.OfChar(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
||||
case int[] __ ->
|
||||
new HeapMemorySegmentImpl.OfInt(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
||||
case float[] __ ->
|
||||
new HeapMemorySegmentImpl.OfFloat(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
||||
case long[] __ ->
|
||||
new HeapMemorySegmentImpl.OfLong(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
||||
case double[] __ ->
|
||||
new HeapMemorySegmentImpl.OfDouble(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
||||
default -> throw new AssertionError("Cannot get here");
|
||||
};
|
||||
} else if (unmapper == null) {
|
||||
return new NativeMemorySegmentImpl(bbAddress + (pos << scaleFactor), size << scaleFactor, readOnly, bufferScope);
|
||||
} else {
|
||||
@ -596,26 +595,6 @@ public abstract sealed class AbstractMemorySegmentImpl
|
||||
}
|
||||
}
|
||||
|
||||
private static int getScaleFactor(Buffer buffer) {
|
||||
if (buffer instanceof ByteBuffer) {
|
||||
return 0;
|
||||
} else if (buffer instanceof CharBuffer) {
|
||||
return 1;
|
||||
} else if (buffer instanceof ShortBuffer) {
|
||||
return 1;
|
||||
} else if (buffer instanceof IntBuffer) {
|
||||
return 2;
|
||||
} else if (buffer instanceof FloatBuffer) {
|
||||
return 2;
|
||||
} else if (buffer instanceof LongBuffer) {
|
||||
return 3;
|
||||
} else if (buffer instanceof DoubleBuffer) {
|
||||
return 3;
|
||||
} else {
|
||||
throw new AssertionError("Cannot get here");
|
||||
}
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
public static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long srcOffset,
|
||||
MemorySegment dstSegment, ValueLayout dstElementLayout, long dstOffset,
|
||||
@ -653,27 +632,25 @@ public abstract sealed class AbstractMemorySegmentImpl
|
||||
Object dstArray, int dstIndex,
|
||||
int elementCount) {
|
||||
|
||||
long baseAndScale = getBaseAndScale(dstArray.getClass());
|
||||
var dstInfo = Utils.BaseAndScale.of(dstArray);
|
||||
if (dstArray.getClass().componentType() != srcLayout.carrier()) {
|
||||
throw new IllegalArgumentException("Incompatible value layout: " + srcLayout);
|
||||
}
|
||||
int dstBase = (int)baseAndScale;
|
||||
long dstWidth = (int)(baseAndScale >> 32); // Use long arithmetics below
|
||||
AbstractMemorySegmentImpl srcImpl = (AbstractMemorySegmentImpl)srcSegment;
|
||||
Utils.checkElementAlignment(srcLayout, "Source layout alignment greater than its size");
|
||||
if (!srcImpl.isAlignedForElement(srcOffset, srcLayout)) {
|
||||
throw new IllegalArgumentException("Source segment incompatible with alignment constraints");
|
||||
}
|
||||
srcImpl.checkAccess(srcOffset, elementCount * dstWidth, true);
|
||||
srcImpl.checkAccess(srcOffset, elementCount * dstInfo.scale(), true);
|
||||
Objects.checkFromIndexSize(dstIndex, elementCount, Array.getLength(dstArray));
|
||||
if (dstWidth == 1 || srcLayout.order() == ByteOrder.nativeOrder()) {
|
||||
if (dstInfo.scale() == 1 || srcLayout.order() == ByteOrder.nativeOrder()) {
|
||||
ScopedMemoryAccess.getScopedMemoryAccess().copyMemory(srcImpl.sessionImpl(), null,
|
||||
srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset,
|
||||
dstArray, dstBase + (dstIndex * dstWidth), elementCount * dstWidth);
|
||||
dstArray, dstInfo.base() + (dstIndex * dstInfo.scale()), elementCount * dstInfo.scale());
|
||||
} else {
|
||||
ScopedMemoryAccess.getScopedMemoryAccess().copySwapMemory(srcImpl.sessionImpl(), null,
|
||||
srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset,
|
||||
dstArray, dstBase + (dstIndex * dstWidth), elementCount * dstWidth, dstWidth);
|
||||
dstArray, dstInfo.base() + (dstIndex * dstInfo.scale()), elementCount * dstInfo.scale(), dstInfo.scale());
|
||||
}
|
||||
}
|
||||
|
||||
@ -682,27 +659,25 @@ public abstract sealed class AbstractMemorySegmentImpl
|
||||
MemorySegment dstSegment, ValueLayout dstLayout, long dstOffset,
|
||||
int elementCount) {
|
||||
|
||||
long baseAndScale = getBaseAndScale(srcArray.getClass());
|
||||
var srcInfo = Utils.BaseAndScale.of(srcArray);
|
||||
if (srcArray.getClass().componentType() != dstLayout.carrier()) {
|
||||
throw new IllegalArgumentException("Incompatible value layout: " + dstLayout);
|
||||
}
|
||||
int srcBase = (int)baseAndScale;
|
||||
long srcWidth = (int)(baseAndScale >> 32); // Use long arithmetics below
|
||||
Objects.checkFromIndexSize(srcIndex, elementCount, Array.getLength(srcArray));
|
||||
AbstractMemorySegmentImpl destImpl = (AbstractMemorySegmentImpl)dstSegment;
|
||||
Utils.checkElementAlignment(dstLayout, "Destination layout alignment greater than its size");
|
||||
if (!destImpl.isAlignedForElement(dstOffset, dstLayout)) {
|
||||
throw new IllegalArgumentException("Destination segment incompatible with alignment constraints");
|
||||
}
|
||||
destImpl.checkAccess(dstOffset, elementCount * srcWidth, false);
|
||||
if (srcWidth == 1 || dstLayout.order() == ByteOrder.nativeOrder()) {
|
||||
destImpl.checkAccess(dstOffset, elementCount * srcInfo.scale(), false);
|
||||
if (srcInfo.scale() == 1 || dstLayout.order() == ByteOrder.nativeOrder()) {
|
||||
ScopedMemoryAccess.getScopedMemoryAccess().copyMemory(null, destImpl.sessionImpl(),
|
||||
srcArray, srcBase + (srcIndex * srcWidth),
|
||||
destImpl.unsafeGetBase(), destImpl.unsafeGetOffset() + dstOffset, elementCount * srcWidth);
|
||||
srcArray, srcInfo.base() + (srcIndex * srcInfo.scale()),
|
||||
destImpl.unsafeGetBase(), destImpl.unsafeGetOffset() + dstOffset, elementCount * srcInfo.scale());
|
||||
} else {
|
||||
ScopedMemoryAccess.getScopedMemoryAccess().copySwapMemory(null, destImpl.sessionImpl(),
|
||||
srcArray, srcBase + (srcIndex * srcWidth),
|
||||
destImpl.unsafeGetBase(), destImpl.unsafeGetOffset() + dstOffset, elementCount * srcWidth, srcWidth);
|
||||
srcArray, srcInfo.base() + (srcIndex * srcInfo.scale()),
|
||||
destImpl.unsafeGetBase(), destImpl.unsafeGetOffset() + dstOffset, elementCount * srcInfo.scale(), srcInfo.scale());
|
||||
}
|
||||
}
|
||||
|
||||
@ -744,24 +719,16 @@ public abstract sealed class AbstractMemorySegmentImpl
|
||||
return srcBytes != dstBytes ? bytes : -1;
|
||||
}
|
||||
|
||||
private static long getBaseAndScale(Class<?> arrayType) {
|
||||
if (arrayType.equals(byte[].class)) {
|
||||
return (long) Unsafe.ARRAY_BYTE_BASE_OFFSET | ((long)Unsafe.ARRAY_BYTE_INDEX_SCALE << 32);
|
||||
} else if (arrayType.equals(char[].class)) {
|
||||
return (long) Unsafe.ARRAY_CHAR_BASE_OFFSET | ((long)Unsafe.ARRAY_CHAR_INDEX_SCALE << 32);
|
||||
} else if (arrayType.equals(short[].class)) {
|
||||
return (long)Unsafe.ARRAY_SHORT_BASE_OFFSET | ((long)Unsafe.ARRAY_SHORT_INDEX_SCALE << 32);
|
||||
} else if (arrayType.equals(int[].class)) {
|
||||
return (long)Unsafe.ARRAY_INT_BASE_OFFSET | ((long) Unsafe.ARRAY_INT_INDEX_SCALE << 32);
|
||||
} else if (arrayType.equals(float[].class)) {
|
||||
return (long)Unsafe.ARRAY_FLOAT_BASE_OFFSET | ((long)Unsafe.ARRAY_FLOAT_INDEX_SCALE << 32);
|
||||
} else if (arrayType.equals(long[].class)) {
|
||||
return (long)Unsafe.ARRAY_LONG_BASE_OFFSET | ((long)Unsafe.ARRAY_LONG_INDEX_SCALE << 32);
|
||||
} else if (arrayType.equals(double[].class)) {
|
||||
return (long)Unsafe.ARRAY_DOUBLE_BASE_OFFSET | ((long)Unsafe.ARRAY_DOUBLE_INDEX_SCALE << 32);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Not a supported array class: " + arrayType.getSimpleName());
|
||||
}
|
||||
private static int getScaleFactor(Buffer buffer) {
|
||||
return switch (buffer) {
|
||||
case ByteBuffer __ -> 0;
|
||||
case CharBuffer __ -> 1;
|
||||
case ShortBuffer __ -> 1;
|
||||
case IntBuffer __ -> 2;
|
||||
case FloatBuffer __ -> 2;
|
||||
case LongBuffer __ -> 3;
|
||||
case DoubleBuffer __ -> 3;
|
||||
};
|
||||
}
|
||||
|
||||
// accessors
|
||||
|
@ -27,7 +27,6 @@ package jdk.internal.foreign;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.lang.ref.Cleaner;
|
||||
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
|
||||
|
@ -33,14 +33,13 @@ import java.util.Optional;
|
||||
|
||||
import jdk.internal.access.JavaNioAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
|
||||
/**
|
||||
* Implementation for heap memory segments. A heap memory segment is composed by an offset and
|
||||
* a base object (typically an array). To enhance performances, the access to the base object needs to feature
|
||||
* sharp type information, as well as sharp null-check information. For this reason, many concrete subclasses
|
||||
* of {@link HeapMemorySegmentImpl} are defined (e.g. {@link OfFloat}, so that each subclass can override the
|
||||
* of {@link HeapMemorySegmentImpl} are defined (e.g. {@link OfFloat}), so that each subclass can override the
|
||||
* {@link HeapMemorySegmentImpl#unsafeGetBase()} method so that it returns an array of the correct (sharp) type. Note that
|
||||
* the field type storing the 'base' coordinate is just Object; similarly, all the constructor in the subclasses
|
||||
* accept an Object 'base' parameter instead of a sharper type (e.g. {@code byte[]}). This is deliberate, as
|
||||
@ -49,13 +48,15 @@ import jdk.internal.vm.annotation.ForceInline;
|
||||
*/
|
||||
abstract sealed class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
|
||||
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
|
||||
private static final int BYTE_ARR_BASE = UNSAFE.arrayBaseOffset(byte[].class);
|
||||
// Constants defining the maximum alignment supported by various kinds of heap arrays.
|
||||
// While for most arrays, the maximum alignment is constant (the size, in bytes, of the array elements),
|
||||
// note that the alignment of a long[]/double[] depends on the platform: it's 4-byte on x86, but 8 bytes on x64
|
||||
// (as specified by the JAVA_LONG layout constant).
|
||||
|
||||
private static final long MAX_ALIGN_1 = ValueLayout.JAVA_BYTE.byteAlignment();
|
||||
private static final long MAX_ALIGN_2 = ValueLayout.JAVA_SHORT.byteAlignment();
|
||||
private static final long MAX_ALIGN_4 = ValueLayout.JAVA_INT.byteAlignment();
|
||||
private static final long MAX_ALIGN_8 = ValueLayout.JAVA_LONG.byteAlignment();
|
||||
private static final long MAX_ALIGN_BYTE_ARRAY = ValueLayout.JAVA_BYTE.byteAlignment();
|
||||
private static final long MAX_ALIGN_SHORT_ARRAY = ValueLayout.JAVA_SHORT.byteAlignment();
|
||||
private static final long MAX_ALIGN_INT_ARRAY = ValueLayout.JAVA_INT.byteAlignment();
|
||||
private static final long MAX_ALIGN_LONG_ARRAY = ValueLayout.JAVA_LONG.byteAlignment();
|
||||
|
||||
final long offset;
|
||||
final Object base;
|
||||
@ -88,7 +89,7 @@ abstract sealed class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
throw new UnsupportedOperationException("Not an address to an heap-allocated byte array");
|
||||
}
|
||||
JavaNioAccess nioAccess = SharedSecrets.getJavaNioAccess();
|
||||
return nioAccess.newHeapByteBuffer(baseByte, (int)offset - BYTE_ARR_BASE, (int) byteSize(), null);
|
||||
return nioAccess.newHeapByteBuffer(baseByte, (int)offset - Utils.BaseAndScale.BYTE.base(), (int) byteSize(), null);
|
||||
}
|
||||
|
||||
// factories
|
||||
@ -111,12 +112,12 @@ abstract sealed class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
|
||||
@Override
|
||||
public long maxAlignMask() {
|
||||
return MAX_ALIGN_1;
|
||||
return MAX_ALIGN_BYTE_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long address() {
|
||||
return offset - Unsafe.ARRAY_BYTE_BASE_OFFSET;
|
||||
return offset - Utils.BaseAndScale.BYTE.base();
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,12 +139,12 @@ abstract sealed class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
|
||||
@Override
|
||||
public long maxAlignMask() {
|
||||
return MAX_ALIGN_2;
|
||||
return MAX_ALIGN_SHORT_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long address() {
|
||||
return offset - Unsafe.ARRAY_CHAR_BASE_OFFSET;
|
||||
return offset - Utils.BaseAndScale.CHAR.base();
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,12 +166,12 @@ abstract sealed class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
|
||||
@Override
|
||||
public long maxAlignMask() {
|
||||
return MAX_ALIGN_2;
|
||||
return MAX_ALIGN_SHORT_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long address() {
|
||||
return offset - Unsafe.ARRAY_SHORT_BASE_OFFSET;
|
||||
return offset - Utils.BaseAndScale.SHORT.base();
|
||||
}
|
||||
}
|
||||
|
||||
@ -192,12 +193,12 @@ abstract sealed class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
|
||||
@Override
|
||||
public long maxAlignMask() {
|
||||
return MAX_ALIGN_4;
|
||||
return MAX_ALIGN_INT_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long address() {
|
||||
return offset - Unsafe.ARRAY_INT_BASE_OFFSET;
|
||||
return offset - Utils.BaseAndScale.INT.base();
|
||||
}
|
||||
}
|
||||
|
||||
@ -219,12 +220,12 @@ abstract sealed class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
|
||||
@Override
|
||||
public long maxAlignMask() {
|
||||
return MAX_ALIGN_8;
|
||||
return MAX_ALIGN_LONG_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long address() {
|
||||
return offset - Unsafe.ARRAY_LONG_BASE_OFFSET;
|
||||
return offset - Utils.BaseAndScale.LONG.base();
|
||||
}
|
||||
}
|
||||
|
||||
@ -246,12 +247,12 @@ abstract sealed class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
|
||||
@Override
|
||||
public long maxAlignMask() {
|
||||
return MAX_ALIGN_4;
|
||||
return MAX_ALIGN_INT_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long address() {
|
||||
return offset - Unsafe.ARRAY_FLOAT_BASE_OFFSET;
|
||||
return offset - Utils.BaseAndScale.FLOAT.base();
|
||||
}
|
||||
}
|
||||
|
||||
@ -273,12 +274,12 @@ abstract sealed class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
|
||||
@Override
|
||||
public long maxAlignMask() {
|
||||
return MAX_ALIGN_8;
|
||||
return MAX_ALIGN_LONG_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long address() {
|
||||
return offset - Unsafe.ARRAY_DOUBLE_BASE_OFFSET;
|
||||
return offset - Utils.BaseAndScale.DOUBLE.base();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,8 +26,6 @@
|
||||
package jdk.internal.foreign;
|
||||
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
|
||||
import java.lang.foreign.AddressLayout;
|
||||
import java.lang.foreign.GroupLayout;
|
||||
import java.lang.foreign.MemoryLayout;
|
||||
@ -41,7 +39,6 @@ import java.lang.invoke.MethodType;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.stream.IntStream;
|
||||
@ -50,7 +47,7 @@ import java.util.stream.Stream;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
/**
|
||||
* This class provide support for constructing layout paths; that is, starting from a root path (see {@link #rootPath(MemoryLayout)},
|
||||
* This class provide support for constructing layout paths; that is, starting from a root path (see {@link #rootPath(MemoryLayout)}),
|
||||
* a path can be constructed by selecting layout elements using the selector methods provided by this class
|
||||
* (see {@link #sequenceElement()}, {@link #sequenceElement(long)}, {@link #sequenceElement(long, long)}, {@link #groupElement(String)}).
|
||||
* Once a path has been fully constructed, clients can ask for the offset associated with the layout element selected
|
||||
|
@ -83,7 +83,7 @@ public abstract sealed class MemorySessionImpl
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
public static final MemorySessionImpl toMemorySession(Arena arena) {
|
||||
public static MemorySessionImpl toMemorySession(Arena arena) {
|
||||
return (MemorySessionImpl) arena.scope();
|
||||
}
|
||||
|
||||
@ -99,10 +99,10 @@ public abstract sealed class MemorySessionImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a cleanup action. If a failure occurred (because of a add vs. close race), call the cleanup action.
|
||||
* Add a cleanup action. If a failure occurred (because of an add vs. close race), call the cleanup action.
|
||||
* This semantics is useful when allocating new memory segments, since we first do a malloc/mmap and _then_
|
||||
* we register the cleanup (free/munmap) against the session; so, if registration fails, we still have to
|
||||
* cleanup memory. From the perspective of the client, such a failure would manifest as a factory
|
||||
* clean up memory. From the perspective of the client, such a failure would manifest as a factory
|
||||
* returning a segment that is already "closed" - which is always possible anyway (e.g. if the session
|
||||
* is closed _after_ the cleanup for the segment is registered but _before_ the factory returns the
|
||||
* new segment to the client). For this reason, it's not worth adding extra complexity to the segment
|
||||
@ -201,7 +201,7 @@ public abstract sealed class MemorySessionImpl
|
||||
/**
|
||||
* Checks that this session is still alive (see {@link #isAlive()}).
|
||||
* @throws IllegalStateException if this session is already closed or if this is
|
||||
* a confined session and this method is called outside of the owner thread.
|
||||
* a confined session and this method is called outside the owner thread.
|
||||
*/
|
||||
public void checkValidState() {
|
||||
try {
|
||||
@ -211,7 +211,7 @@ public abstract sealed class MemorySessionImpl
|
||||
}
|
||||
}
|
||||
|
||||
public static final void checkValidState(MemorySegment segment) {
|
||||
public static void checkValidState(MemorySegment segment) {
|
||||
((AbstractMemorySegmentImpl)segment).sessionImpl().checkValidState();
|
||||
}
|
||||
|
||||
@ -227,7 +227,7 @@ public abstract sealed class MemorySessionImpl
|
||||
/**
|
||||
* Closes this session, executing any cleanup action (where provided).
|
||||
* @throws IllegalStateException if this session is already closed or if this is
|
||||
* a confined session and this method is called outside of the owner thread.
|
||||
* a confined session and this method is called outside the owner thread.
|
||||
*/
|
||||
public void close() {
|
||||
justClose();
|
||||
|
@ -83,56 +83,56 @@ public class SegmentFactories {
|
||||
public static MemorySegment fromArray(byte[] arr) {
|
||||
ensureInitialized();
|
||||
Objects.requireNonNull(arr);
|
||||
long byteSize = (long)arr.length * Unsafe.ARRAY_BYTE_INDEX_SCALE;
|
||||
return new OfByte(Unsafe.ARRAY_BYTE_BASE_OFFSET, arr, byteSize, false,
|
||||
long byteSize = (long)arr.length * Utils.BaseAndScale.BYTE.scale();
|
||||
return new OfByte(Utils.BaseAndScale.BYTE.base(), arr, byteSize, false,
|
||||
MemorySessionImpl.createHeap(arr));
|
||||
}
|
||||
|
||||
public static MemorySegment fromArray(short[] arr) {
|
||||
ensureInitialized();
|
||||
Objects.requireNonNull(arr);
|
||||
long byteSize = (long)arr.length * Unsafe.ARRAY_SHORT_INDEX_SCALE;
|
||||
return new OfShort(Unsafe.ARRAY_SHORT_BASE_OFFSET, arr, byteSize, false,
|
||||
long byteSize = (long)arr.length * Utils.BaseAndScale.SHORT.scale();
|
||||
return new OfShort(Utils.BaseAndScale.SHORT.base(), arr, byteSize, false,
|
||||
MemorySessionImpl.createHeap(arr));
|
||||
}
|
||||
|
||||
public static MemorySegment fromArray(int[] arr) {
|
||||
ensureInitialized();
|
||||
Objects.requireNonNull(arr);
|
||||
long byteSize = (long)arr.length * Unsafe.ARRAY_INT_INDEX_SCALE;
|
||||
return new OfInt(Unsafe.ARRAY_INT_BASE_OFFSET, arr, byteSize, false,
|
||||
long byteSize = (long)arr.length * Utils.BaseAndScale.INT.scale();
|
||||
return new OfInt(Utils.BaseAndScale.INT.base(), arr, byteSize, false,
|
||||
MemorySessionImpl.createHeap(arr));
|
||||
}
|
||||
|
||||
public static MemorySegment fromArray(char[] arr) {
|
||||
ensureInitialized();
|
||||
Objects.requireNonNull(arr);
|
||||
long byteSize = (long)arr.length * Unsafe.ARRAY_CHAR_INDEX_SCALE;
|
||||
return new OfChar(Unsafe.ARRAY_CHAR_BASE_OFFSET, arr, byteSize, false,
|
||||
long byteSize = (long)arr.length * Utils.BaseAndScale.CHAR.scale();
|
||||
return new OfChar(Utils.BaseAndScale.CHAR.base(), arr, byteSize, false,
|
||||
MemorySessionImpl.createHeap(arr));
|
||||
}
|
||||
|
||||
public static MemorySegment fromArray(float[] arr) {
|
||||
ensureInitialized();
|
||||
Objects.requireNonNull(arr);
|
||||
long byteSize = (long)arr.length * Unsafe.ARRAY_FLOAT_INDEX_SCALE;
|
||||
return new OfFloat(Unsafe.ARRAY_FLOAT_BASE_OFFSET, arr, byteSize, false,
|
||||
long byteSize = (long)arr.length * Utils.BaseAndScale.FLOAT.scale();
|
||||
return new OfFloat(Utils.BaseAndScale.FLOAT.base(), arr, byteSize, false,
|
||||
MemorySessionImpl.createHeap(arr));
|
||||
}
|
||||
|
||||
public static MemorySegment fromArray(double[] arr) {
|
||||
ensureInitialized();
|
||||
Objects.requireNonNull(arr);
|
||||
long byteSize = (long)arr.length * Unsafe.ARRAY_DOUBLE_INDEX_SCALE;
|
||||
return new OfDouble(Unsafe.ARRAY_DOUBLE_BASE_OFFSET, arr, byteSize, false,
|
||||
long byteSize = (long)arr.length * Utils.BaseAndScale.DOUBLE.scale();
|
||||
return new OfDouble(Utils.BaseAndScale.DOUBLE.base(), arr, byteSize, false,
|
||||
MemorySessionImpl.createHeap(arr));
|
||||
}
|
||||
|
||||
public static MemorySegment fromArray(long[] arr) {
|
||||
ensureInitialized();
|
||||
Objects.requireNonNull(arr);
|
||||
long byteSize = (long)arr.length * Unsafe.ARRAY_LONG_INDEX_SCALE;
|
||||
return new OfLong(Unsafe.ARRAY_LONG_BASE_OFFSET, arr, byteSize, false,
|
||||
long byteSize = (long)arr.length * Utils.BaseAndScale.LONG.scale();
|
||||
return new OfLong(Utils.BaseAndScale.LONG.base(), arr, byteSize, false,
|
||||
MemorySessionImpl.createHeap(arr));
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,6 @@ package jdk.internal.foreign;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.lang.ref.Cleaner;
|
||||
import jdk.internal.misc.ScopedMemoryAccess;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
|
||||
|
@ -39,7 +39,7 @@ import static java.lang.foreign.ValueLayout.*;
|
||||
/**
|
||||
* Miscellaneous functions to read and write strings, in various charsets.
|
||||
*/
|
||||
public class StringSupport {
|
||||
public final class StringSupport {
|
||||
|
||||
static final JavaLangAccess JAVA_LANG_ACCESS = SharedSecrets.getJavaLangAccess();
|
||||
|
||||
|
@ -75,7 +75,7 @@ public final class SystemLookup implements SymbolLookup {
|
||||
|
||||
private static SymbolLookup makeWindowsLookup() {
|
||||
@SuppressWarnings("removal")
|
||||
String systemRoot = AccessController.doPrivileged(new PrivilegedAction<String>() {
|
||||
String systemRoot = AccessController.doPrivileged(new PrivilegedAction<>() {
|
||||
@Override
|
||||
public String run() {
|
||||
return System.getenv("SystemRoot");
|
||||
@ -86,7 +86,7 @@ public final class SystemLookup implements SymbolLookup {
|
||||
Path msvcrt = system32.resolve("msvcrt.dll");
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
boolean useUCRT = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
|
||||
boolean useUCRT = AccessController.doPrivileged(new PrivilegedAction<>() {
|
||||
@Override
|
||||
public Boolean run() {
|
||||
return Files.exists(ucrtbase);
|
||||
|
@ -43,6 +43,7 @@ import java.util.function.Supplier;
|
||||
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.foreign.abi.SharedUtils;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
import sun.invoke.util.Wrapper;
|
||||
|
||||
@ -276,4 +277,36 @@ public final class Utils {
|
||||
return "0x" + Long.toHexString(value);
|
||||
}
|
||||
|
||||
public record BaseAndScale(int base, long scale) {
|
||||
|
||||
public static final BaseAndScale BYTE =
|
||||
new BaseAndScale(Unsafe.ARRAY_BYTE_BASE_OFFSET, Unsafe.ARRAY_BYTE_INDEX_SCALE);
|
||||
public static final BaseAndScale CHAR =
|
||||
new BaseAndScale(Unsafe.ARRAY_CHAR_BASE_OFFSET, Unsafe.ARRAY_CHAR_INDEX_SCALE);
|
||||
public static final BaseAndScale SHORT =
|
||||
new BaseAndScale(Unsafe.ARRAY_SHORT_BASE_OFFSET, Unsafe.ARRAY_SHORT_INDEX_SCALE);
|
||||
public static final BaseAndScale INT =
|
||||
new BaseAndScale(Unsafe.ARRAY_INT_BASE_OFFSET, Unsafe.ARRAY_INT_INDEX_SCALE);
|
||||
public static final BaseAndScale FLOAT =
|
||||
new BaseAndScale(Unsafe.ARRAY_FLOAT_BASE_OFFSET, Unsafe.ARRAY_FLOAT_INDEX_SCALE);
|
||||
public static final BaseAndScale LONG =
|
||||
new BaseAndScale(Unsafe.ARRAY_LONG_BASE_OFFSET, Unsafe.ARRAY_LONG_INDEX_SCALE);
|
||||
public static final BaseAndScale DOUBLE =
|
||||
new BaseAndScale(Unsafe.ARRAY_DOUBLE_BASE_OFFSET, Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
|
||||
|
||||
public static BaseAndScale of(Object array) {
|
||||
return switch (array) {
|
||||
case byte[] __ -> BaseAndScale.BYTE;
|
||||
case char[] __ -> BaseAndScale.CHAR;
|
||||
case short[] __ -> BaseAndScale.SHORT;
|
||||
case int[] __ -> BaseAndScale.INT;
|
||||
case float[] __ -> BaseAndScale.FLOAT;
|
||||
case long[] __ -> BaseAndScale.LONG;
|
||||
case double[] __ -> BaseAndScale.DOUBLE;
|
||||
default -> throw new IllegalArgumentException("Not a supported array class: " + array.getClass().getSimpleName());
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ public abstract sealed class AbstractLinker implements Linker permits LinuxAArch
|
||||
return downcallHandle0(function, options);
|
||||
}
|
||||
|
||||
private final MethodHandle downcallHandle0(FunctionDescriptor function, Option... options) {
|
||||
private MethodHandle downcallHandle0(FunctionDescriptor function, Option... options) {
|
||||
Objects.requireNonNull(function);
|
||||
Objects.requireNonNull(options);
|
||||
checkLayouts(function);
|
||||
|
@ -32,7 +32,6 @@ import java.lang.foreign.*;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Deque;
|
||||
import java.util.List;
|
||||
@ -57,7 +56,7 @@ import static java.lang.foreign.ValueLayout.JAVA_SHORT_UNALIGNED;
|
||||
* the CONVERT_ADDRESS operator 'unboxes' a MemoryAddress to a long, but 'boxes' a long to a MemoryAddress.
|
||||
*
|
||||
* Here are some examples of binding recipes derived from C declarations, and according to the Windows ABI (recipes are
|
||||
* ABI-specific). Note that each argument has it's own recipe, which is indicated by '[number]:' (though, the only
|
||||
* ABI-specific). Note that each argument has its own recipe, which is indicated by '[number]:' (though, the only
|
||||
* example that has multiple arguments is the one using varargs).
|
||||
*
|
||||
* --------------------
|
||||
|
@ -33,7 +33,6 @@ import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.lang.foreign.ValueLayout.JAVA_INT;
|
||||
import static sun.security.action.GetPropertyAction.privilegedGetProperty;
|
||||
|
||||
public enum CapturableState {
|
||||
GET_LAST_ERROR ("GetLastError", JAVA_INT, 1 << 0, Utils.IS_WINDOWS),
|
||||
|
@ -178,7 +178,7 @@ public final class SharedUtils {
|
||||
if (dropReturn) { // no handling for return value, need to drop it
|
||||
target = dropReturn(target);
|
||||
} else {
|
||||
// adjust return type so it matches the inferred type of the effective
|
||||
// adjust return type so that it matches the inferred type of the effective
|
||||
// function descriptor
|
||||
target = target.asType(target.type().changeReturnType(MemorySegment.class));
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
class SoftReferenceCache<K, V> {
|
||||
final class SoftReferenceCache<K, V> {
|
||||
private final Map<K, Node> cache = new ConcurrentHashMap<>();
|
||||
|
||||
public V get(K key, Function<K, V> valueFactory) {
|
||||
@ -41,10 +41,7 @@ class SoftReferenceCache<K, V> {
|
||||
private final class Node {
|
||||
private volatile SoftReference<V> ref;
|
||||
|
||||
public Node() {
|
||||
}
|
||||
|
||||
public V get(K key, Function<K, V> valueFactory) {
|
||||
V get(K key, Function<K, V> valueFactory) {
|
||||
V result;
|
||||
if (ref == null || (result = ref.get()) == null) {
|
||||
synchronized (this) { // don't let threads race on the valueFactory::apply call
|
||||
|
@ -37,7 +37,6 @@ import jdk.internal.foreign.abi.CallingSequence;
|
||||
import jdk.internal.foreign.abi.CallingSequenceBuilder;
|
||||
import jdk.internal.foreign.abi.DowncallLinker;
|
||||
import jdk.internal.foreign.abi.LinkerOptions;
|
||||
import jdk.internal.foreign.abi.UpcallLinker;
|
||||
import jdk.internal.foreign.abi.SharedUtils;
|
||||
import jdk.internal.foreign.abi.VMStorage;
|
||||
import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64CallArranger;
|
||||
@ -246,8 +245,8 @@ public abstract class CallArranger {
|
||||
| enough registers | some registers, but not enough | no registers
|
||||
----------------+------------------+---------------------------------+-------------------------
|
||||
Linux | FW in regs | CW on the stack | CW on the stack
|
||||
MacOs, non-VA | FW in regs | FW on the stack | FW on the stack
|
||||
MacOs, VA | FW in regs | CW on the stack | CW on the stack
|
||||
macOS, non-VA | FW in regs | FW on the stack | FW on the stack
|
||||
macOS, VA | FW in regs | CW on the stack | CW on the stack
|
||||
Windows, non-VF | FW in regs | CW on the stack | CW on the stack
|
||||
Windows, VF | FW in regs | CW split between regs and stack | CW on the stack
|
||||
(where FW = Field-wise copy, CW = Chunk-wise copy, VA is a variadic argument, and VF is a variadic function)
|
||||
@ -257,7 +256,7 @@ public abstract class CallArranger {
|
||||
| enough registers | some registers, but not enough | no registers
|
||||
----------------+------------------+---------------------------------+-------------------------
|
||||
Linux | CW in regs | CW on the stack | CW on the stack
|
||||
MacOs | CW in regs | CW on the stack | CW on the stack
|
||||
macOS | CW in regs | CW on the stack | CW on the stack
|
||||
Windows, non-VF | CW in regs | CW on the stack | CW on the stack
|
||||
Windows, VF | CW in regs | CW split between regs and stack | CW on the stack
|
||||
*/
|
||||
|
@ -39,7 +39,7 @@ import java.nio.ByteOrder;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* ABI implementation for macOS on Apple silicon. Based on AAPCS with
|
||||
* ABI implementation for macOS on Apple Silicon. Based on AAPCS with
|
||||
* changes to va_list and passing arguments on the stack.
|
||||
*/
|
||||
public final class MacOsAArch64Linker extends AbstractLinker {
|
||||
|
2
src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/windows/WindowsAArch64CallArranger.java
2
src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/windows/WindowsAArch64CallArranger.java
@ -52,7 +52,7 @@ public class WindowsAArch64CallArranger extends CallArranger {
|
||||
//
|
||||
// Although the AAPCS64 says r0-7 and v0-7 are all valid return
|
||||
// registers, it's not possible to generate a C function that uses
|
||||
// r2-7 and v4-7 so they are omitted here.
|
||||
// r2-7 and v4-7 so, they are omitted here.
|
||||
private static final ABIDescriptor WindowsAArch64AbiDescriptor = abiFor(
|
||||
new VMStorage[] { r0, r1, r2, r3, r4, r5, r6, r7, INDIRECT_RESULT},
|
||||
new VMStorage[] { v0, v1, v2, v3, v4, v5, v6, v7 },
|
||||
|
@ -47,13 +47,12 @@ public final class WindowsAArch64Linker extends AbstractLinker {
|
||||
|
||||
static final Map<String, MemoryLayout> CANONICAL_LAYOUTS =
|
||||
SharedUtils.canonicalLayouts(ValueLayout.JAVA_INT, ValueLayout.JAVA_LONG, ValueLayout.JAVA_CHAR);
|
||||
private static WindowsAArch64Linker instance;
|
||||
|
||||
public static WindowsAArch64Linker getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new WindowsAArch64Linker();
|
||||
class Holder {
|
||||
private static final WindowsAArch64Linker INSTANCE = new WindowsAArch64Linker();
|
||||
}
|
||||
return instance;
|
||||
return Holder.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -58,6 +58,7 @@ import static java.lang.foreign.ValueLayout.JAVA_SHORT;
|
||||
* } ffi_type;
|
||||
*/
|
||||
class FFIType {
|
||||
|
||||
static final ValueLayout SIZE_T = layoutFor((int)ADDRESS.byteSize());
|
||||
private static final ValueLayout UNSIGNED_SHORT = JAVA_SHORT;
|
||||
private static final StructLayout LAYOUT = Utils.computePaddedStructLayout(
|
||||
|
@ -240,30 +240,25 @@ public final class FallbackLinker extends AbstractLinker {
|
||||
|
||||
private static void writeValue(Object arg, MemoryLayout layout, MemorySegment argSeg,
|
||||
Consumer<MemorySegment> acquireCallback) {
|
||||
if (layout instanceof ValueLayout.OfBoolean bl) {
|
||||
argSeg.set(bl, 0, (Boolean) arg);
|
||||
} else if (layout instanceof ValueLayout.OfByte bl) {
|
||||
argSeg.set(bl, 0, (Byte) arg);
|
||||
} else if (layout instanceof ValueLayout.OfShort sl) {
|
||||
argSeg.set(sl, 0, (Short) arg);
|
||||
} else if (layout instanceof ValueLayout.OfChar cl) {
|
||||
argSeg.set(cl, 0, (Character) arg);
|
||||
} else if (layout instanceof ValueLayout.OfInt il) {
|
||||
argSeg.set(il, 0, (Integer) arg);
|
||||
} else if (layout instanceof ValueLayout.OfLong ll) {
|
||||
argSeg.set(ll, 0, (Long) arg);
|
||||
} else if (layout instanceof ValueLayout.OfFloat fl) {
|
||||
argSeg.set(fl, 0, (Float) arg);
|
||||
} else if (layout instanceof ValueLayout.OfDouble dl) {
|
||||
argSeg.set(dl, 0, (Double) arg);
|
||||
} else if (layout instanceof AddressLayout al) {
|
||||
MemorySegment addrArg = (MemorySegment) arg;
|
||||
acquireCallback.accept(addrArg);
|
||||
argSeg.set(al, 0, addrArg);
|
||||
} else if (layout instanceof GroupLayout) {
|
||||
MemorySegment.copy((MemorySegment) arg, 0, argSeg, 0, argSeg.byteSize()); // by-value struct
|
||||
} else {
|
||||
assert layout == null;
|
||||
switch (layout) {
|
||||
case ValueLayout.OfBoolean bl -> argSeg.set(bl, 0, (Boolean) arg);
|
||||
case ValueLayout.OfByte bl -> argSeg.set(bl, 0, (Byte) arg);
|
||||
case ValueLayout.OfShort sl -> argSeg.set(sl, 0, (Short) arg);
|
||||
case ValueLayout.OfChar cl -> argSeg.set(cl, 0, (Character) arg);
|
||||
case ValueLayout.OfInt il -> argSeg.set(il, 0, (Integer) arg);
|
||||
case ValueLayout.OfLong ll -> argSeg.set(ll, 0, (Long) arg);
|
||||
case ValueLayout.OfFloat fl -> argSeg.set(fl, 0, (Float) arg);
|
||||
case ValueLayout.OfDouble dl -> argSeg.set(dl, 0, (Double) arg);
|
||||
case AddressLayout al -> {
|
||||
MemorySegment addrArg = (MemorySegment) arg;
|
||||
acquireCallback.accept(addrArg);
|
||||
argSeg.set(al, 0, addrArg);
|
||||
}
|
||||
case GroupLayout __ ->
|
||||
MemorySegment.copy((MemorySegment) arg, 0, argSeg, 0, argSeg.byteSize()); // by-value struct
|
||||
case null, default -> {
|
||||
assert layout == null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,13 +52,12 @@ public final class PPC64Architecture implements Architecture {
|
||||
|
||||
@Override
|
||||
public int typeSize(int cls) {
|
||||
switch (cls) {
|
||||
case StorageType.INTEGER: return INTEGER_REG_SIZE;
|
||||
case StorageType.FLOAT: return FLOAT_REG_SIZE;
|
||||
return switch (cls) {
|
||||
case StorageType.INTEGER -> INTEGER_REG_SIZE;
|
||||
case StorageType.FLOAT -> FLOAT_REG_SIZE;
|
||||
// STACK is deliberately omitted
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Invalid Storage Class: " + cls);
|
||||
default -> throw new IllegalArgumentException("Invalid Storage Class: " + cls);
|
||||
};
|
||||
}
|
||||
|
||||
public interface StorageType {
|
||||
|
@ -32,7 +32,6 @@ import jdk.internal.foreign.abi.ABIDescriptor;
|
||||
import jdk.internal.foreign.abi.Architecture;
|
||||
import jdk.internal.foreign.abi.StubLocations;
|
||||
import jdk.internal.foreign.abi.VMStorage;
|
||||
import jdk.internal.foreign.abi.riscv64.linux.TypeClass;
|
||||
|
||||
public final class RISCV64Architecture implements Architecture {
|
||||
public static final Architecture INSTANCE = new RISCV64Architecture();
|
||||
|
@ -40,12 +40,10 @@ import jdk.internal.foreign.abi.CallingSequence;
|
||||
import jdk.internal.foreign.abi.CallingSequenceBuilder;
|
||||
import jdk.internal.foreign.abi.DowncallLinker;
|
||||
import jdk.internal.foreign.abi.LinkerOptions;
|
||||
import jdk.internal.foreign.abi.UpcallLinker;
|
||||
import jdk.internal.foreign.abi.SharedUtils;
|
||||
import jdk.internal.foreign.abi.VMStorage;
|
||||
import jdk.internal.foreign.Utils;
|
||||
|
||||
import java.lang.foreign.ValueLayout;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.List;
|
||||
@ -150,7 +148,7 @@ public class LinuxRISCV64CallArranger {
|
||||
this.forArguments = forArguments;
|
||||
}
|
||||
|
||||
// Aggregates or scalars passed on the stack are aligned to the greater of
|
||||
// Aggregates or scalars passed on the stack are aligned to the greatest of
|
||||
// the type alignment and XLEN bits, but never more than the stack alignment.
|
||||
void alignStack(long alignment) {
|
||||
alignment = Utils.alignUp(Math.clamp(alignment, STACK_SLOT_SIZE, 16), STACK_SLOT_SIZE);
|
||||
@ -253,8 +251,8 @@ public class LinuxRISCV64CallArranger {
|
||||
Map.entry(STRUCT_REGISTER_XF, STRUCT_REGISTER_X));
|
||||
}
|
||||
|
||||
static class UnboxBindingCalculator extends BindingCalculator {
|
||||
boolean forArguments;
|
||||
static final class UnboxBindingCalculator extends BindingCalculator {
|
||||
final boolean forArguments;
|
||||
|
||||
UnboxBindingCalculator(boolean forArguments) {
|
||||
super(forArguments);
|
||||
|
@ -78,7 +78,7 @@ public enum TypeClass {
|
||||
* Struct will be flattened while classifying. That is, struct{struct{int, double}} will be treated
|
||||
* same as struct{int, double} and struct{int[2]} will be treated same as struct{int, int}.
|
||||
* */
|
||||
private static record FieldCounter(long integerCnt, long floatCnt, long pointerCnt) {
|
||||
private record FieldCounter(long integerCnt, long floatCnt, long pointerCnt) {
|
||||
static final FieldCounter EMPTY = new FieldCounter(0, 0, 0);
|
||||
static final FieldCounter SINGLE_INTEGER = new FieldCounter(1, 0, 0);
|
||||
static final FieldCounter SINGLE_FLOAT = new FieldCounter(0, 1, 0);
|
||||
@ -128,39 +128,40 @@ public enum TypeClass {
|
||||
}
|
||||
}
|
||||
|
||||
public static record FlattenedFieldDesc(TypeClass typeClass, long offset, ValueLayout layout) {
|
||||
|
||||
}
|
||||
public record FlattenedFieldDesc(TypeClass typeClass, long offset, ValueLayout layout) { }
|
||||
|
||||
private static List<FlattenedFieldDesc> getFlattenedFieldsInner(long offset, MemoryLayout layout) {
|
||||
if (layout instanceof ValueLayout valueLayout) {
|
||||
TypeClass typeClass = classifyValueType(valueLayout);
|
||||
return List.of(switch (typeClass) {
|
||||
case INTEGER, FLOAT -> new FlattenedFieldDesc(typeClass, offset, valueLayout);
|
||||
default -> throw new IllegalStateException("Should not reach here.");
|
||||
});
|
||||
} else if (layout instanceof GroupLayout groupLayout) {
|
||||
List<FlattenedFieldDesc> fields = new ArrayList<>();
|
||||
for (MemoryLayout memberLayout : groupLayout.memberLayouts()) {
|
||||
if (memberLayout instanceof PaddingLayout) {
|
||||
return switch (layout) {
|
||||
case ValueLayout valueLayout -> {
|
||||
TypeClass typeClass = classifyValueType(valueLayout);
|
||||
yield List.of(switch (typeClass) {
|
||||
case INTEGER, FLOAT -> new FlattenedFieldDesc(typeClass, offset, valueLayout);
|
||||
default -> throw new IllegalStateException("Should not reach here.");
|
||||
});
|
||||
}
|
||||
case GroupLayout groupLayout -> {
|
||||
List<FlattenedFieldDesc> fields = new ArrayList<>();
|
||||
for (MemoryLayout memberLayout : groupLayout.memberLayouts()) {
|
||||
if (memberLayout instanceof PaddingLayout) {
|
||||
offset += memberLayout.byteSize();
|
||||
continue;
|
||||
}
|
||||
fields.addAll(getFlattenedFieldsInner(offset, memberLayout));
|
||||
offset += memberLayout.byteSize();
|
||||
continue;
|
||||
}
|
||||
fields.addAll(getFlattenedFieldsInner(offset, memberLayout));
|
||||
offset += memberLayout.byteSize();
|
||||
yield fields;
|
||||
}
|
||||
return fields;
|
||||
} else if (layout instanceof SequenceLayout sequenceLayout) {
|
||||
List<FlattenedFieldDesc> fields = new ArrayList<>();
|
||||
MemoryLayout elementLayout = sequenceLayout.elementLayout();
|
||||
for (long i = 0; i < sequenceLayout.elementCount(); i++) {
|
||||
fields.addAll(getFlattenedFieldsInner(offset, elementLayout));
|
||||
offset += elementLayout.byteSize();
|
||||
case SequenceLayout sequenceLayout -> {
|
||||
List<FlattenedFieldDesc> fields = new ArrayList<>();
|
||||
MemoryLayout elementLayout = sequenceLayout.elementLayout();
|
||||
for (long i = 0; i < sequenceLayout.elementCount(); i++) {
|
||||
fields.addAll(getFlattenedFieldsInner(offset, elementLayout));
|
||||
offset += elementLayout.byteSize();
|
||||
}
|
||||
yield fields;
|
||||
}
|
||||
return fields;
|
||||
} else {
|
||||
throw new IllegalStateException("Cannot get here: " + layout);
|
||||
}
|
||||
case null, default -> throw new IllegalStateException("Cannot get here: " + layout);
|
||||
};
|
||||
}
|
||||
|
||||
public static List<FlattenedFieldDesc> getFlattenedFields(GroupLayout layout) {
|
||||
|
@ -52,15 +52,12 @@ public final class S390Architecture implements Architecture {
|
||||
|
||||
@Override
|
||||
public int typeSize(int cls) {
|
||||
switch (cls) {
|
||||
case StorageType.INTEGER:
|
||||
return INTEGER_REG_SIZE;
|
||||
case StorageType.FLOAT:
|
||||
return FLOAT_REG_SIZE;
|
||||
return switch (cls) {
|
||||
case StorageType.INTEGER -> INTEGER_REG_SIZE;
|
||||
case StorageType.FLOAT -> FLOAT_REG_SIZE;
|
||||
// STACK is deliberately omitted
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Invalid Storage Class: " + cls);
|
||||
default -> throw new IllegalArgumentException("Invalid Storage Class: " + cls);
|
||||
};
|
||||
}
|
||||
|
||||
public interface StorageType {
|
||||
|
@ -37,19 +37,15 @@ import jdk.internal.foreign.abi.CallingSequence;
|
||||
import jdk.internal.foreign.abi.CallingSequenceBuilder;
|
||||
import jdk.internal.foreign.abi.DowncallLinker;
|
||||
import jdk.internal.foreign.abi.LinkerOptions;
|
||||
import jdk.internal.foreign.abi.UpcallLinker;
|
||||
import jdk.internal.foreign.abi.SharedUtils;
|
||||
import jdk.internal.foreign.abi.VMStorage;
|
||||
import jdk.internal.foreign.Utils;
|
||||
|
||||
import java.lang.foreign.ValueLayout;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static jdk.internal.foreign.abi.s390.linux.TypeClass.*;
|
||||
import static jdk.internal.foreign.abi.s390.S390Architecture.*;
|
||||
import static jdk.internal.foreign.abi.s390.S390Architecture.Regs.*;
|
||||
|
||||
|
@ -96,10 +96,7 @@ public enum TypeClass {
|
||||
return false;
|
||||
|
||||
TypeClass baseArgClass = classifyValueType((ValueLayout) baseType);
|
||||
if (baseArgClass != FLOAT)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return baseArgClass == FLOAT;
|
||||
}
|
||||
|
||||
private static TypeClass classifyStructType(MemoryLayout layout) {
|
||||
|
@ -34,7 +34,6 @@ import jdk.internal.foreign.abi.CallingSequenceBuilder;
|
||||
import jdk.internal.foreign.abi.DowncallLinker;
|
||||
import jdk.internal.foreign.abi.LinkerOptions;
|
||||
import jdk.internal.foreign.abi.SharedUtils;
|
||||
import jdk.internal.foreign.abi.UpcallLinker;
|
||||
import jdk.internal.foreign.abi.VMStorage;
|
||||
import jdk.internal.foreign.abi.x64.X86_64Architecture;
|
||||
|
||||
@ -208,7 +207,7 @@ public class CallArranger {
|
||||
return typeClass.classes.stream().map(c -> stackAlloc()).toArray(VMStorage[]::new);
|
||||
}
|
||||
|
||||
//ok, let's pass pass on registers
|
||||
//ok, let's pass on registers
|
||||
VMStorage[] storage = new VMStorage[(int)(nIntegerReg + nVectorReg)];
|
||||
for (int i = 0 ; i < typeClass.classes.size() ; i++) {
|
||||
boolean sse = typeClass.classes.get(i) == ArgumentClassImpl.SSE;
|
||||
|
@ -208,35 +208,40 @@ class TypeClass {
|
||||
return groups;
|
||||
}
|
||||
|
||||
private static void groupByEightBytes(MemoryLayout l, long offset, List<ArgumentClassImpl>[] groups) {
|
||||
if (l instanceof GroupLayout group) {
|
||||
for (MemoryLayout m : group.memberLayouts()) {
|
||||
groupByEightBytes(m, offset, groups);
|
||||
if (group instanceof StructLayout) {
|
||||
offset += m.byteSize();
|
||||
private static void groupByEightBytes(MemoryLayout layout,
|
||||
long offset,
|
||||
List<ArgumentClassImpl>[] groups) {
|
||||
switch (layout) {
|
||||
case GroupLayout group -> {
|
||||
for (MemoryLayout m : group.memberLayouts()) {
|
||||
groupByEightBytes(m, offset, groups);
|
||||
if (group instanceof StructLayout) {
|
||||
offset += m.byteSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (l instanceof PaddingLayout) {
|
||||
return;
|
||||
} else if (l instanceof SequenceLayout seq) {
|
||||
MemoryLayout elem = seq.elementLayout();
|
||||
for (long i = 0 ; i < seq.elementCount() ; i++) {
|
||||
groupByEightBytes(elem, offset, groups);
|
||||
offset += elem.byteSize();
|
||||
case PaddingLayout __ -> {
|
||||
}
|
||||
} else if (l instanceof ValueLayout vl) {
|
||||
List<ArgumentClassImpl> layouts = groups[(int)offset / 8];
|
||||
if (layouts == null) {
|
||||
layouts = new ArrayList<>();
|
||||
groups[(int)offset / 8] = layouts;
|
||||
case SequenceLayout seq -> {
|
||||
MemoryLayout elem = seq.elementLayout();
|
||||
for (long i = 0; i < seq.elementCount(); i++) {
|
||||
groupByEightBytes(elem, offset, groups);
|
||||
offset += elem.byteSize();
|
||||
}
|
||||
}
|
||||
// if the aggregate contains unaligned fields, it has class MEMORY
|
||||
ArgumentClassImpl argumentClass = (offset % vl.byteAlignment()) == 0 ?
|
||||
argumentClassFor(vl) :
|
||||
ArgumentClassImpl.MEMORY;
|
||||
layouts.add(argumentClass);
|
||||
} else {
|
||||
throw new IllegalStateException("Unexpected layout: " + l);
|
||||
case ValueLayout vl -> {
|
||||
List<ArgumentClassImpl> layouts = groups[(int) offset / 8];
|
||||
if (layouts == null) {
|
||||
layouts = new ArrayList<>();
|
||||
groups[(int) offset / 8] = layouts;
|
||||
}
|
||||
// if the aggregate contains unaligned fields, it has class MEMORY
|
||||
ArgumentClassImpl argumentClass = (offset % vl.byteAlignment()) == 0 ?
|
||||
argumentClassFor(vl) :
|
||||
ArgumentClassImpl.MEMORY;
|
||||
layouts.add(argumentClass);
|
||||
}
|
||||
case null, default -> throw new IllegalStateException("Unexpected layout: " + layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,6 @@ import jdk.internal.foreign.abi.CallingSequenceBuilder;
|
||||
import jdk.internal.foreign.abi.DowncallLinker;
|
||||
import jdk.internal.foreign.abi.LinkerOptions;
|
||||
import jdk.internal.foreign.abi.SharedUtils;
|
||||
import jdk.internal.foreign.abi.UpcallLinker;
|
||||
import jdk.internal.foreign.abi.VMStorage;
|
||||
import jdk.internal.foreign.abi.x64.X86_64Architecture;
|
||||
|
||||
@ -42,7 +41,6 @@ import java.lang.foreign.FunctionDescriptor;
|
||||
import java.lang.foreign.GroupLayout;
|
||||
import java.lang.foreign.MemoryLayout;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
import java.lang.foreign.ValueLayout;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.List;
|
||||
|
@ -38,7 +38,7 @@ enum TypeClass {
|
||||
VARARG_FLOAT;
|
||||
|
||||
private static TypeClass classifyValueType(ValueLayout type, boolean isVararg) {
|
||||
// No 128-bit integers in the Windows C ABI. There are __m128(i|d) intrinsic types but they act just
|
||||
// No 128-bit integers in the Windows C ABI. There are __m128(i|d) intrinsic types but, they act just
|
||||
// like a struct when passing as an argument (passed by pointer).
|
||||
// https://docs.microsoft.com/en-us/cpp/cpp/m128?view=vs-2019
|
||||
|
||||
|
@ -40,7 +40,7 @@ import java.util.stream.Collectors;
|
||||
* @implSpec
|
||||
* This class is immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
|
||||
*/
|
||||
public sealed abstract class AbstractGroupLayout<L extends AbstractGroupLayout<L> & MemoryLayout>
|
||||
abstract sealed class AbstractGroupLayout<L extends AbstractGroupLayout<L> & MemoryLayout>
|
||||
extends AbstractLayout<L>
|
||||
permits StructLayoutImpl, UnionLayoutImpl {
|
||||
|
||||
|
@ -59,7 +59,7 @@ public final class ValueLayouts {
|
||||
// Suppresses default constructor, ensuring non-instantiability.
|
||||
private ValueLayouts() {}
|
||||
|
||||
abstract sealed static class AbstractValueLayout<V extends AbstractValueLayout<V> & ValueLayout> extends AbstractLayout<V> {
|
||||
abstract static sealed class AbstractValueLayout<V extends AbstractValueLayout<V> & ValueLayout> extends AbstractLayout<V> {
|
||||
|
||||
static final int ADDRESS_SIZE_BYTES = Unsafe.ADDRESS_SIZE;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user