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
@ -49,7 +49,6 @@ import jdk.internal.access.JavaNioAccess;
|
|||||||
import jdk.internal.access.SharedSecrets;
|
import jdk.internal.access.SharedSecrets;
|
||||||
import jdk.internal.access.foreign.UnmapperProxy;
|
import jdk.internal.access.foreign.UnmapperProxy;
|
||||||
import jdk.internal.misc.ScopedMemoryAccess;
|
import jdk.internal.misc.ScopedMemoryAccess;
|
||||||
import jdk.internal.misc.Unsafe;
|
|
||||||
import jdk.internal.reflect.CallerSensitive;
|
import jdk.internal.reflect.CallerSensitive;
|
||||||
import jdk.internal.reflect.Reflection;
|
import jdk.internal.reflect.Reflection;
|
||||||
import jdk.internal.util.ArraysSupport;
|
import jdk.internal.util.ArraysSupport;
|
||||||
@ -560,23 +559,23 @@ public abstract sealed class AbstractMemorySegmentImpl
|
|||||||
bufferScope = MemorySessionImpl.createHeap(bufferRef(bb));
|
bufferScope = MemorySessionImpl.createHeap(bufferRef(bb));
|
||||||
}
|
}
|
||||||
if (base != null) {
|
if (base != null) {
|
||||||
if (base instanceof byte[]) {
|
return switch (base) {
|
||||||
return new HeapMemorySegmentImpl.OfByte(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
case byte[] __ ->
|
||||||
} else if (base instanceof short[]) {
|
new HeapMemorySegmentImpl.OfByte(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
||||||
return new HeapMemorySegmentImpl.OfShort(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
case short[] __ ->
|
||||||
} else if (base instanceof char[]) {
|
new HeapMemorySegmentImpl.OfShort(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
||||||
return new HeapMemorySegmentImpl.OfChar(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
case char[] __ ->
|
||||||
} else if (base instanceof int[]) {
|
new HeapMemorySegmentImpl.OfChar(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
||||||
return new HeapMemorySegmentImpl.OfInt(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
case int[] __ ->
|
||||||
} else if (base instanceof float[]) {
|
new HeapMemorySegmentImpl.OfInt(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
||||||
return new HeapMemorySegmentImpl.OfFloat(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
case float[] __ ->
|
||||||
} else if (base instanceof long[]) {
|
new HeapMemorySegmentImpl.OfFloat(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
||||||
return new HeapMemorySegmentImpl.OfLong(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
case long[] __ ->
|
||||||
} else if (base instanceof double[]) {
|
new HeapMemorySegmentImpl.OfLong(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
||||||
return new HeapMemorySegmentImpl.OfDouble(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
case double[] __ ->
|
||||||
} else {
|
new HeapMemorySegmentImpl.OfDouble(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly, bufferScope);
|
||||||
throw new AssertionError("Cannot get here");
|
default -> throw new AssertionError("Cannot get here");
|
||||||
}
|
};
|
||||||
} else if (unmapper == null) {
|
} else if (unmapper == null) {
|
||||||
return new NativeMemorySegmentImpl(bbAddress + (pos << scaleFactor), size << scaleFactor, readOnly, bufferScope);
|
return new NativeMemorySegmentImpl(bbAddress + (pos << scaleFactor), size << scaleFactor, readOnly, bufferScope);
|
||||||
} else {
|
} 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
|
@ForceInline
|
||||||
public static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long srcOffset,
|
public static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long srcOffset,
|
||||||
MemorySegment dstSegment, ValueLayout dstElementLayout, long dstOffset,
|
MemorySegment dstSegment, ValueLayout dstElementLayout, long dstOffset,
|
||||||
@ -653,27 +632,25 @@ public abstract sealed class AbstractMemorySegmentImpl
|
|||||||
Object dstArray, int dstIndex,
|
Object dstArray, int dstIndex,
|
||||||
int elementCount) {
|
int elementCount) {
|
||||||
|
|
||||||
long baseAndScale = getBaseAndScale(dstArray.getClass());
|
var dstInfo = Utils.BaseAndScale.of(dstArray);
|
||||||
if (dstArray.getClass().componentType() != srcLayout.carrier()) {
|
if (dstArray.getClass().componentType() != srcLayout.carrier()) {
|
||||||
throw new IllegalArgumentException("Incompatible value layout: " + srcLayout);
|
throw new IllegalArgumentException("Incompatible value layout: " + srcLayout);
|
||||||
}
|
}
|
||||||
int dstBase = (int)baseAndScale;
|
|
||||||
long dstWidth = (int)(baseAndScale >> 32); // Use long arithmetics below
|
|
||||||
AbstractMemorySegmentImpl srcImpl = (AbstractMemorySegmentImpl)srcSegment;
|
AbstractMemorySegmentImpl srcImpl = (AbstractMemorySegmentImpl)srcSegment;
|
||||||
Utils.checkElementAlignment(srcLayout, "Source layout alignment greater than its size");
|
Utils.checkElementAlignment(srcLayout, "Source layout alignment greater than its size");
|
||||||
if (!srcImpl.isAlignedForElement(srcOffset, srcLayout)) {
|
if (!srcImpl.isAlignedForElement(srcOffset, srcLayout)) {
|
||||||
throw new IllegalArgumentException("Source segment incompatible with alignment constraints");
|
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));
|
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,
|
ScopedMemoryAccess.getScopedMemoryAccess().copyMemory(srcImpl.sessionImpl(), null,
|
||||||
srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset,
|
srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset,
|
||||||
dstArray, dstBase + (dstIndex * dstWidth), elementCount * dstWidth);
|
dstArray, dstInfo.base() + (dstIndex * dstInfo.scale()), elementCount * dstInfo.scale());
|
||||||
} else {
|
} else {
|
||||||
ScopedMemoryAccess.getScopedMemoryAccess().copySwapMemory(srcImpl.sessionImpl(), null,
|
ScopedMemoryAccess.getScopedMemoryAccess().copySwapMemory(srcImpl.sessionImpl(), null,
|
||||||
srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset,
|
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,
|
MemorySegment dstSegment, ValueLayout dstLayout, long dstOffset,
|
||||||
int elementCount) {
|
int elementCount) {
|
||||||
|
|
||||||
long baseAndScale = getBaseAndScale(srcArray.getClass());
|
var srcInfo = Utils.BaseAndScale.of(srcArray);
|
||||||
if (srcArray.getClass().componentType() != dstLayout.carrier()) {
|
if (srcArray.getClass().componentType() != dstLayout.carrier()) {
|
||||||
throw new IllegalArgumentException("Incompatible value layout: " + dstLayout);
|
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));
|
Objects.checkFromIndexSize(srcIndex, elementCount, Array.getLength(srcArray));
|
||||||
AbstractMemorySegmentImpl destImpl = (AbstractMemorySegmentImpl)dstSegment;
|
AbstractMemorySegmentImpl destImpl = (AbstractMemorySegmentImpl)dstSegment;
|
||||||
Utils.checkElementAlignment(dstLayout, "Destination layout alignment greater than its size");
|
Utils.checkElementAlignment(dstLayout, "Destination layout alignment greater than its size");
|
||||||
if (!destImpl.isAlignedForElement(dstOffset, dstLayout)) {
|
if (!destImpl.isAlignedForElement(dstOffset, dstLayout)) {
|
||||||
throw new IllegalArgumentException("Destination segment incompatible with alignment constraints");
|
throw new IllegalArgumentException("Destination segment incompatible with alignment constraints");
|
||||||
}
|
}
|
||||||
destImpl.checkAccess(dstOffset, elementCount * srcWidth, false);
|
destImpl.checkAccess(dstOffset, elementCount * srcInfo.scale(), false);
|
||||||
if (srcWidth == 1 || dstLayout.order() == ByteOrder.nativeOrder()) {
|
if (srcInfo.scale() == 1 || dstLayout.order() == ByteOrder.nativeOrder()) {
|
||||||
ScopedMemoryAccess.getScopedMemoryAccess().copyMemory(null, destImpl.sessionImpl(),
|
ScopedMemoryAccess.getScopedMemoryAccess().copyMemory(null, destImpl.sessionImpl(),
|
||||||
srcArray, srcBase + (srcIndex * srcWidth),
|
srcArray, srcInfo.base() + (srcIndex * srcInfo.scale()),
|
||||||
destImpl.unsafeGetBase(), destImpl.unsafeGetOffset() + dstOffset, elementCount * srcWidth);
|
destImpl.unsafeGetBase(), destImpl.unsafeGetOffset() + dstOffset, elementCount * srcInfo.scale());
|
||||||
} else {
|
} else {
|
||||||
ScopedMemoryAccess.getScopedMemoryAccess().copySwapMemory(null, destImpl.sessionImpl(),
|
ScopedMemoryAccess.getScopedMemoryAccess().copySwapMemory(null, destImpl.sessionImpl(),
|
||||||
srcArray, srcBase + (srcIndex * srcWidth),
|
srcArray, srcInfo.base() + (srcIndex * srcInfo.scale()),
|
||||||
destImpl.unsafeGetBase(), destImpl.unsafeGetOffset() + dstOffset, elementCount * srcWidth, srcWidth);
|
destImpl.unsafeGetBase(), destImpl.unsafeGetOffset() + dstOffset, elementCount * srcInfo.scale(), srcInfo.scale());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -744,24 +719,16 @@ public abstract sealed class AbstractMemorySegmentImpl
|
|||||||
return srcBytes != dstBytes ? bytes : -1;
|
return srcBytes != dstBytes ? bytes : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long getBaseAndScale(Class<?> arrayType) {
|
private static int getScaleFactor(Buffer buffer) {
|
||||||
if (arrayType.equals(byte[].class)) {
|
return switch (buffer) {
|
||||||
return (long) Unsafe.ARRAY_BYTE_BASE_OFFSET | ((long)Unsafe.ARRAY_BYTE_INDEX_SCALE << 32);
|
case ByteBuffer __ -> 0;
|
||||||
} else if (arrayType.equals(char[].class)) {
|
case CharBuffer __ -> 1;
|
||||||
return (long) Unsafe.ARRAY_CHAR_BASE_OFFSET | ((long)Unsafe.ARRAY_CHAR_INDEX_SCALE << 32);
|
case ShortBuffer __ -> 1;
|
||||||
} else if (arrayType.equals(short[].class)) {
|
case IntBuffer __ -> 2;
|
||||||
return (long)Unsafe.ARRAY_SHORT_BASE_OFFSET | ((long)Unsafe.ARRAY_SHORT_INDEX_SCALE << 32);
|
case FloatBuffer __ -> 2;
|
||||||
} else if (arrayType.equals(int[].class)) {
|
case LongBuffer __ -> 3;
|
||||||
return (long)Unsafe.ARRAY_INT_BASE_OFFSET | ((long) Unsafe.ARRAY_INT_INDEX_SCALE << 32);
|
case DoubleBuffer __ -> 3;
|
||||||
} 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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// accessors
|
// accessors
|
||||||
|
@ -27,7 +27,6 @@ package jdk.internal.foreign;
|
|||||||
|
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
import java.lang.invoke.VarHandle;
|
import java.lang.invoke.VarHandle;
|
||||||
import java.lang.ref.Cleaner;
|
|
||||||
|
|
||||||
import jdk.internal.vm.annotation.ForceInline;
|
import jdk.internal.vm.annotation.ForceInline;
|
||||||
|
|
||||||
|
@ -33,14 +33,13 @@ import java.util.Optional;
|
|||||||
|
|
||||||
import jdk.internal.access.JavaNioAccess;
|
import jdk.internal.access.JavaNioAccess;
|
||||||
import jdk.internal.access.SharedSecrets;
|
import jdk.internal.access.SharedSecrets;
|
||||||
import jdk.internal.misc.Unsafe;
|
|
||||||
import jdk.internal.vm.annotation.ForceInline;
|
import jdk.internal.vm.annotation.ForceInline;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation for heap memory segments. A heap memory segment is composed by an offset and
|
* 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
|
* 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
|
* 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
|
* {@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
|
* 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
|
* 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 {
|
abstract sealed class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||||
|
|
||||||
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
|
// Constants defining the maximum alignment supported by various kinds of heap arrays.
|
||||||
private static final int BYTE_ARR_BASE = UNSAFE.arrayBaseOffset(byte[].class);
|
// 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_BYTE_ARRAY = ValueLayout.JAVA_BYTE.byteAlignment();
|
||||||
private static final long MAX_ALIGN_2 = ValueLayout.JAVA_SHORT.byteAlignment();
|
private static final long MAX_ALIGN_SHORT_ARRAY = ValueLayout.JAVA_SHORT.byteAlignment();
|
||||||
private static final long MAX_ALIGN_4 = ValueLayout.JAVA_INT.byteAlignment();
|
private static final long MAX_ALIGN_INT_ARRAY = ValueLayout.JAVA_INT.byteAlignment();
|
||||||
private static final long MAX_ALIGN_8 = ValueLayout.JAVA_LONG.byteAlignment();
|
private static final long MAX_ALIGN_LONG_ARRAY = ValueLayout.JAVA_LONG.byteAlignment();
|
||||||
|
|
||||||
final long offset;
|
final long offset;
|
||||||
final Object base;
|
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");
|
throw new UnsupportedOperationException("Not an address to an heap-allocated byte array");
|
||||||
}
|
}
|
||||||
JavaNioAccess nioAccess = SharedSecrets.getJavaNioAccess();
|
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
|
// factories
|
||||||
@ -111,12 +112,12 @@ abstract sealed class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long maxAlignMask() {
|
public long maxAlignMask() {
|
||||||
return MAX_ALIGN_1;
|
return MAX_ALIGN_BYTE_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long address() {
|
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
|
@Override
|
||||||
public long maxAlignMask() {
|
public long maxAlignMask() {
|
||||||
return MAX_ALIGN_2;
|
return MAX_ALIGN_SHORT_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long address() {
|
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
|
@Override
|
||||||
public long maxAlignMask() {
|
public long maxAlignMask() {
|
||||||
return MAX_ALIGN_2;
|
return MAX_ALIGN_SHORT_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long address() {
|
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
|
@Override
|
||||||
public long maxAlignMask() {
|
public long maxAlignMask() {
|
||||||
return MAX_ALIGN_4;
|
return MAX_ALIGN_INT_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long address() {
|
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
|
@Override
|
||||||
public long maxAlignMask() {
|
public long maxAlignMask() {
|
||||||
return MAX_ALIGN_8;
|
return MAX_ALIGN_LONG_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long address() {
|
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
|
@Override
|
||||||
public long maxAlignMask() {
|
public long maxAlignMask() {
|
||||||
return MAX_ALIGN_4;
|
return MAX_ALIGN_INT_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long address() {
|
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
|
@Override
|
||||||
public long maxAlignMask() {
|
public long maxAlignMask() {
|
||||||
return MAX_ALIGN_8;
|
return MAX_ALIGN_LONG_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long address() {
|
public long address() {
|
||||||
return offset - Unsafe.ARRAY_DOUBLE_BASE_OFFSET;
|
return offset - Utils.BaseAndScale.DOUBLE.base();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,8 +26,6 @@
|
|||||||
package jdk.internal.foreign;
|
package jdk.internal.foreign;
|
||||||
|
|
||||||
import jdk.internal.vm.annotation.ForceInline;
|
import jdk.internal.vm.annotation.ForceInline;
|
||||||
import jdk.internal.vm.annotation.Stable;
|
|
||||||
|
|
||||||
import java.lang.foreign.AddressLayout;
|
import java.lang.foreign.AddressLayout;
|
||||||
import java.lang.foreign.GroupLayout;
|
import java.lang.foreign.GroupLayout;
|
||||||
import java.lang.foreign.MemoryLayout;
|
import java.lang.foreign.MemoryLayout;
|
||||||
@ -41,7 +39,6 @@ import java.lang.invoke.MethodType;
|
|||||||
import java.lang.invoke.VarHandle;
|
import java.lang.invoke.VarHandle;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.UnaryOperator;
|
import java.util.function.UnaryOperator;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
@ -50,7 +47,7 @@ import java.util.stream.Stream;
|
|||||||
import static java.util.stream.Collectors.joining;
|
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
|
* 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)}).
|
* (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
|
* 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
|
@ForceInline
|
||||||
public static final MemorySessionImpl toMemorySession(Arena arena) {
|
public static MemorySessionImpl toMemorySession(Arena arena) {
|
||||||
return (MemorySessionImpl) arena.scope();
|
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_
|
* 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
|
* 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
|
* 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
|
* 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
|
* 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()}).
|
* Checks that this session is still alive (see {@link #isAlive()}).
|
||||||
* @throws IllegalStateException if this session is already closed or if this is
|
* @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() {
|
public void checkValidState() {
|
||||||
try {
|
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();
|
((AbstractMemorySegmentImpl)segment).sessionImpl().checkValidState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,7 +227,7 @@ public abstract sealed class MemorySessionImpl
|
|||||||
/**
|
/**
|
||||||
* Closes this session, executing any cleanup action (where provided).
|
* Closes this session, executing any cleanup action (where provided).
|
||||||
* @throws IllegalStateException if this session is already closed or if this is
|
* @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() {
|
public void close() {
|
||||||
justClose();
|
justClose();
|
||||||
|
@ -83,56 +83,56 @@ public class SegmentFactories {
|
|||||||
public static MemorySegment fromArray(byte[] arr) {
|
public static MemorySegment fromArray(byte[] arr) {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
Objects.requireNonNull(arr);
|
Objects.requireNonNull(arr);
|
||||||
long byteSize = (long)arr.length * Unsafe.ARRAY_BYTE_INDEX_SCALE;
|
long byteSize = (long)arr.length * Utils.BaseAndScale.BYTE.scale();
|
||||||
return new OfByte(Unsafe.ARRAY_BYTE_BASE_OFFSET, arr, byteSize, false,
|
return new OfByte(Utils.BaseAndScale.BYTE.base(), arr, byteSize, false,
|
||||||
MemorySessionImpl.createHeap(arr));
|
MemorySessionImpl.createHeap(arr));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MemorySegment fromArray(short[] arr) {
|
public static MemorySegment fromArray(short[] arr) {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
Objects.requireNonNull(arr);
|
Objects.requireNonNull(arr);
|
||||||
long byteSize = (long)arr.length * Unsafe.ARRAY_SHORT_INDEX_SCALE;
|
long byteSize = (long)arr.length * Utils.BaseAndScale.SHORT.scale();
|
||||||
return new OfShort(Unsafe.ARRAY_SHORT_BASE_OFFSET, arr, byteSize, false,
|
return new OfShort(Utils.BaseAndScale.SHORT.base(), arr, byteSize, false,
|
||||||
MemorySessionImpl.createHeap(arr));
|
MemorySessionImpl.createHeap(arr));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MemorySegment fromArray(int[] arr) {
|
public static MemorySegment fromArray(int[] arr) {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
Objects.requireNonNull(arr);
|
Objects.requireNonNull(arr);
|
||||||
long byteSize = (long)arr.length * Unsafe.ARRAY_INT_INDEX_SCALE;
|
long byteSize = (long)arr.length * Utils.BaseAndScale.INT.scale();
|
||||||
return new OfInt(Unsafe.ARRAY_INT_BASE_OFFSET, arr, byteSize, false,
|
return new OfInt(Utils.BaseAndScale.INT.base(), arr, byteSize, false,
|
||||||
MemorySessionImpl.createHeap(arr));
|
MemorySessionImpl.createHeap(arr));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MemorySegment fromArray(char[] arr) {
|
public static MemorySegment fromArray(char[] arr) {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
Objects.requireNonNull(arr);
|
Objects.requireNonNull(arr);
|
||||||
long byteSize = (long)arr.length * Unsafe.ARRAY_CHAR_INDEX_SCALE;
|
long byteSize = (long)arr.length * Utils.BaseAndScale.CHAR.scale();
|
||||||
return new OfChar(Unsafe.ARRAY_CHAR_BASE_OFFSET, arr, byteSize, false,
|
return new OfChar(Utils.BaseAndScale.CHAR.base(), arr, byteSize, false,
|
||||||
MemorySessionImpl.createHeap(arr));
|
MemorySessionImpl.createHeap(arr));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MemorySegment fromArray(float[] arr) {
|
public static MemorySegment fromArray(float[] arr) {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
Objects.requireNonNull(arr);
|
Objects.requireNonNull(arr);
|
||||||
long byteSize = (long)arr.length * Unsafe.ARRAY_FLOAT_INDEX_SCALE;
|
long byteSize = (long)arr.length * Utils.BaseAndScale.FLOAT.scale();
|
||||||
return new OfFloat(Unsafe.ARRAY_FLOAT_BASE_OFFSET, arr, byteSize, false,
|
return new OfFloat(Utils.BaseAndScale.FLOAT.base(), arr, byteSize, false,
|
||||||
MemorySessionImpl.createHeap(arr));
|
MemorySessionImpl.createHeap(arr));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MemorySegment fromArray(double[] arr) {
|
public static MemorySegment fromArray(double[] arr) {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
Objects.requireNonNull(arr);
|
Objects.requireNonNull(arr);
|
||||||
long byteSize = (long)arr.length * Unsafe.ARRAY_DOUBLE_INDEX_SCALE;
|
long byteSize = (long)arr.length * Utils.BaseAndScale.DOUBLE.scale();
|
||||||
return new OfDouble(Unsafe.ARRAY_DOUBLE_BASE_OFFSET, arr, byteSize, false,
|
return new OfDouble(Utils.BaseAndScale.DOUBLE.base(), arr, byteSize, false,
|
||||||
MemorySessionImpl.createHeap(arr));
|
MemorySessionImpl.createHeap(arr));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MemorySegment fromArray(long[] arr) {
|
public static MemorySegment fromArray(long[] arr) {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
Objects.requireNonNull(arr);
|
Objects.requireNonNull(arr);
|
||||||
long byteSize = (long)arr.length * Unsafe.ARRAY_LONG_INDEX_SCALE;
|
long byteSize = (long)arr.length * Utils.BaseAndScale.LONG.scale();
|
||||||
return new OfLong(Unsafe.ARRAY_LONG_BASE_OFFSET, arr, byteSize, false,
|
return new OfLong(Utils.BaseAndScale.LONG.base(), arr, byteSize, false,
|
||||||
MemorySessionImpl.createHeap(arr));
|
MemorySessionImpl.createHeap(arr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@ package jdk.internal.foreign;
|
|||||||
|
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
import java.lang.invoke.VarHandle;
|
import java.lang.invoke.VarHandle;
|
||||||
import java.lang.ref.Cleaner;
|
|
||||||
import jdk.internal.misc.ScopedMemoryAccess;
|
import jdk.internal.misc.ScopedMemoryAccess;
|
||||||
import jdk.internal.vm.annotation.ForceInline;
|
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.
|
* 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();
|
static final JavaLangAccess JAVA_LANG_ACCESS = SharedSecrets.getJavaLangAccess();
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ public final class SystemLookup implements SymbolLookup {
|
|||||||
|
|
||||||
private static SymbolLookup makeWindowsLookup() {
|
private static SymbolLookup makeWindowsLookup() {
|
||||||
@SuppressWarnings("removal")
|
@SuppressWarnings("removal")
|
||||||
String systemRoot = AccessController.doPrivileged(new PrivilegedAction<String>() {
|
String systemRoot = AccessController.doPrivileged(new PrivilegedAction<>() {
|
||||||
@Override
|
@Override
|
||||||
public String run() {
|
public String run() {
|
||||||
return System.getenv("SystemRoot");
|
return System.getenv("SystemRoot");
|
||||||
@ -86,7 +86,7 @@ public final class SystemLookup implements SymbolLookup {
|
|||||||
Path msvcrt = system32.resolve("msvcrt.dll");
|
Path msvcrt = system32.resolve("msvcrt.dll");
|
||||||
|
|
||||||
@SuppressWarnings("removal")
|
@SuppressWarnings("removal")
|
||||||
boolean useUCRT = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
|
boolean useUCRT = AccessController.doPrivileged(new PrivilegedAction<>() {
|
||||||
@Override
|
@Override
|
||||||
public Boolean run() {
|
public Boolean run() {
|
||||||
return Files.exists(ucrtbase);
|
return Files.exists(ucrtbase);
|
||||||
|
@ -43,6 +43,7 @@ import java.util.function.Supplier;
|
|||||||
|
|
||||||
import jdk.internal.access.SharedSecrets;
|
import jdk.internal.access.SharedSecrets;
|
||||||
import jdk.internal.foreign.abi.SharedUtils;
|
import jdk.internal.foreign.abi.SharedUtils;
|
||||||
|
import jdk.internal.misc.Unsafe;
|
||||||
import jdk.internal.vm.annotation.ForceInline;
|
import jdk.internal.vm.annotation.ForceInline;
|
||||||
import sun.invoke.util.Wrapper;
|
import sun.invoke.util.Wrapper;
|
||||||
|
|
||||||
@ -276,4 +277,36 @@ public final class Utils {
|
|||||||
return "0x" + Long.toHexString(value);
|
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);
|
return downcallHandle0(function, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final MethodHandle downcallHandle0(FunctionDescriptor function, Option... options) {
|
private MethodHandle downcallHandle0(FunctionDescriptor function, Option... options) {
|
||||||
Objects.requireNonNull(function);
|
Objects.requireNonNull(function);
|
||||||
Objects.requireNonNull(options);
|
Objects.requireNonNull(options);
|
||||||
checkLayouts(function);
|
checkLayouts(function);
|
||||||
|
@ -32,7 +32,6 @@ import java.lang.foreign.*;
|
|||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
import java.lang.invoke.MethodType;
|
import java.lang.invoke.MethodType;
|
||||||
import java.nio.ByteOrder;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
import java.util.List;
|
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.
|
* 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
|
* 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).
|
* 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 java.util.stream.Stream;
|
||||||
|
|
||||||
import static java.lang.foreign.ValueLayout.JAVA_INT;
|
import static java.lang.foreign.ValueLayout.JAVA_INT;
|
||||||
import static sun.security.action.GetPropertyAction.privilegedGetProperty;
|
|
||||||
|
|
||||||
public enum CapturableState {
|
public enum CapturableState {
|
||||||
GET_LAST_ERROR ("GetLastError", JAVA_INT, 1 << 0, Utils.IS_WINDOWS),
|
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
|
if (dropReturn) { // no handling for return value, need to drop it
|
||||||
target = dropReturn(target);
|
target = dropReturn(target);
|
||||||
} else {
|
} 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
|
// function descriptor
|
||||||
target = target.asType(target.type().changeReturnType(MemorySegment.class));
|
target = target.asType(target.type().changeReturnType(MemorySegment.class));
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ import java.util.Map;
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
class SoftReferenceCache<K, V> {
|
final class SoftReferenceCache<K, V> {
|
||||||
private final Map<K, Node> cache = new ConcurrentHashMap<>();
|
private final Map<K, Node> cache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public V get(K key, Function<K, V> valueFactory) {
|
public V get(K key, Function<K, V> valueFactory) {
|
||||||
@ -41,10 +41,7 @@ class SoftReferenceCache<K, V> {
|
|||||||
private final class Node {
|
private final class Node {
|
||||||
private volatile SoftReference<V> ref;
|
private volatile SoftReference<V> ref;
|
||||||
|
|
||||||
public Node() {
|
V get(K key, Function<K, V> valueFactory) {
|
||||||
}
|
|
||||||
|
|
||||||
public V get(K key, Function<K, V> valueFactory) {
|
|
||||||
V result;
|
V result;
|
||||||
if (ref == null || (result = ref.get()) == null) {
|
if (ref == null || (result = ref.get()) == null) {
|
||||||
synchronized (this) { // don't let threads race on the valueFactory::apply call
|
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.CallingSequenceBuilder;
|
||||||
import jdk.internal.foreign.abi.DowncallLinker;
|
import jdk.internal.foreign.abi.DowncallLinker;
|
||||||
import jdk.internal.foreign.abi.LinkerOptions;
|
import jdk.internal.foreign.abi.LinkerOptions;
|
||||||
import jdk.internal.foreign.abi.UpcallLinker;
|
|
||||||
import jdk.internal.foreign.abi.SharedUtils;
|
import jdk.internal.foreign.abi.SharedUtils;
|
||||||
import jdk.internal.foreign.abi.VMStorage;
|
import jdk.internal.foreign.abi.VMStorage;
|
||||||
import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64CallArranger;
|
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
|
| enough registers | some registers, but not enough | no registers
|
||||||
----------------+------------------+---------------------------------+-------------------------
|
----------------+------------------+---------------------------------+-------------------------
|
||||||
Linux | FW in regs | CW on the stack | CW on the stack
|
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, 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, 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, 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
|
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)
|
(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
|
| enough registers | some registers, but not enough | no registers
|
||||||
----------------+------------------+---------------------------------+-------------------------
|
----------------+------------------+---------------------------------+-------------------------
|
||||||
Linux | CW in regs | CW on the stack | CW on the stack
|
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, 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
|
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;
|
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.
|
* changes to va_list and passing arguments on the stack.
|
||||||
*/
|
*/
|
||||||
public final class MacOsAArch64Linker extends AbstractLinker {
|
public final class MacOsAArch64Linker extends AbstractLinker {
|
||||||
|
@ -52,7 +52,7 @@ public class WindowsAArch64CallArranger extends CallArranger {
|
|||||||
//
|
//
|
||||||
// Although the AAPCS64 says r0-7 and v0-7 are all valid return
|
// 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
|
// 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(
|
private static final ABIDescriptor WindowsAArch64AbiDescriptor = abiFor(
|
||||||
new VMStorage[] { r0, r1, r2, r3, r4, r5, r6, r7, INDIRECT_RESULT},
|
new VMStorage[] { r0, r1, r2, r3, r4, r5, r6, r7, INDIRECT_RESULT},
|
||||||
new VMStorage[] { v0, v1, v2, v3, v4, v5, v6, v7 },
|
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 =
|
static final Map<String, MemoryLayout> CANONICAL_LAYOUTS =
|
||||||
SharedUtils.canonicalLayouts(ValueLayout.JAVA_INT, ValueLayout.JAVA_LONG, ValueLayout.JAVA_CHAR);
|
SharedUtils.canonicalLayouts(ValueLayout.JAVA_INT, ValueLayout.JAVA_LONG, ValueLayout.JAVA_CHAR);
|
||||||
private static WindowsAArch64Linker instance;
|
|
||||||
|
|
||||||
public static WindowsAArch64Linker getInstance() {
|
public static WindowsAArch64Linker getInstance() {
|
||||||
if (instance == null) {
|
class Holder {
|
||||||
instance = new WindowsAArch64Linker();
|
private static final WindowsAArch64Linker INSTANCE = new WindowsAArch64Linker();
|
||||||
}
|
}
|
||||||
return instance;
|
return Holder.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -58,6 +58,7 @@ import static java.lang.foreign.ValueLayout.JAVA_SHORT;
|
|||||||
* } ffi_type;
|
* } ffi_type;
|
||||||
*/
|
*/
|
||||||
class FFIType {
|
class FFIType {
|
||||||
|
|
||||||
static final ValueLayout SIZE_T = layoutFor((int)ADDRESS.byteSize());
|
static final ValueLayout SIZE_T = layoutFor((int)ADDRESS.byteSize());
|
||||||
private static final ValueLayout UNSIGNED_SHORT = JAVA_SHORT;
|
private static final ValueLayout UNSIGNED_SHORT = JAVA_SHORT;
|
||||||
private static final StructLayout LAYOUT = Utils.computePaddedStructLayout(
|
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,
|
private static void writeValue(Object arg, MemoryLayout layout, MemorySegment argSeg,
|
||||||
Consumer<MemorySegment> acquireCallback) {
|
Consumer<MemorySegment> acquireCallback) {
|
||||||
if (layout instanceof ValueLayout.OfBoolean bl) {
|
switch (layout) {
|
||||||
argSeg.set(bl, 0, (Boolean) arg);
|
case ValueLayout.OfBoolean bl -> argSeg.set(bl, 0, (Boolean) arg);
|
||||||
} else if (layout instanceof ValueLayout.OfByte bl) {
|
case ValueLayout.OfByte bl -> argSeg.set(bl, 0, (Byte) arg);
|
||||||
argSeg.set(bl, 0, (Byte) arg);
|
case ValueLayout.OfShort sl -> argSeg.set(sl, 0, (Short) arg);
|
||||||
} else if (layout instanceof ValueLayout.OfShort sl) {
|
case ValueLayout.OfChar cl -> argSeg.set(cl, 0, (Character) arg);
|
||||||
argSeg.set(sl, 0, (Short) arg);
|
case ValueLayout.OfInt il -> argSeg.set(il, 0, (Integer) arg);
|
||||||
} else if (layout instanceof ValueLayout.OfChar cl) {
|
case ValueLayout.OfLong ll -> argSeg.set(ll, 0, (Long) arg);
|
||||||
argSeg.set(cl, 0, (Character) arg);
|
case ValueLayout.OfFloat fl -> argSeg.set(fl, 0, (Float) arg);
|
||||||
} else if (layout instanceof ValueLayout.OfInt il) {
|
case ValueLayout.OfDouble dl -> argSeg.set(dl, 0, (Double) arg);
|
||||||
argSeg.set(il, 0, (Integer) arg);
|
case AddressLayout al -> {
|
||||||
} else if (layout instanceof ValueLayout.OfLong ll) {
|
MemorySegment addrArg = (MemorySegment) arg;
|
||||||
argSeg.set(ll, 0, (Long) arg);
|
acquireCallback.accept(addrArg);
|
||||||
} else if (layout instanceof ValueLayout.OfFloat fl) {
|
argSeg.set(al, 0, addrArg);
|
||||||
argSeg.set(fl, 0, (Float) arg);
|
}
|
||||||
} else if (layout instanceof ValueLayout.OfDouble dl) {
|
case GroupLayout __ ->
|
||||||
argSeg.set(dl, 0, (Double) arg);
|
MemorySegment.copy((MemorySegment) arg, 0, argSeg, 0, argSeg.byteSize()); // by-value struct
|
||||||
} else if (layout instanceof AddressLayout al) {
|
case null, default -> {
|
||||||
MemorySegment addrArg = (MemorySegment) arg;
|
assert layout == null;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,13 +52,12 @@ public final class PPC64Architecture implements Architecture {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int typeSize(int cls) {
|
public int typeSize(int cls) {
|
||||||
switch (cls) {
|
return switch (cls) {
|
||||||
case StorageType.INTEGER: return INTEGER_REG_SIZE;
|
case StorageType.INTEGER -> INTEGER_REG_SIZE;
|
||||||
case StorageType.FLOAT: return FLOAT_REG_SIZE;
|
case StorageType.FLOAT -> FLOAT_REG_SIZE;
|
||||||
// STACK is deliberately omitted
|
// STACK is deliberately omitted
|
||||||
}
|
default -> throw new IllegalArgumentException("Invalid Storage Class: " + cls);
|
||||||
|
};
|
||||||
throw new IllegalArgumentException("Invalid Storage Class: " + cls);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface StorageType {
|
public interface StorageType {
|
||||||
|
@ -32,7 +32,6 @@ import jdk.internal.foreign.abi.ABIDescriptor;
|
|||||||
import jdk.internal.foreign.abi.Architecture;
|
import jdk.internal.foreign.abi.Architecture;
|
||||||
import jdk.internal.foreign.abi.StubLocations;
|
import jdk.internal.foreign.abi.StubLocations;
|
||||||
import jdk.internal.foreign.abi.VMStorage;
|
import jdk.internal.foreign.abi.VMStorage;
|
||||||
import jdk.internal.foreign.abi.riscv64.linux.TypeClass;
|
|
||||||
|
|
||||||
public final class RISCV64Architecture implements Architecture {
|
public final class RISCV64Architecture implements Architecture {
|
||||||
public static final Architecture INSTANCE = new RISCV64Architecture();
|
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.CallingSequenceBuilder;
|
||||||
import jdk.internal.foreign.abi.DowncallLinker;
|
import jdk.internal.foreign.abi.DowncallLinker;
|
||||||
import jdk.internal.foreign.abi.LinkerOptions;
|
import jdk.internal.foreign.abi.LinkerOptions;
|
||||||
import jdk.internal.foreign.abi.UpcallLinker;
|
|
||||||
import jdk.internal.foreign.abi.SharedUtils;
|
import jdk.internal.foreign.abi.SharedUtils;
|
||||||
import jdk.internal.foreign.abi.VMStorage;
|
import jdk.internal.foreign.abi.VMStorage;
|
||||||
import jdk.internal.foreign.Utils;
|
import jdk.internal.foreign.Utils;
|
||||||
|
|
||||||
import java.lang.foreign.ValueLayout;
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodType;
|
import java.lang.invoke.MethodType;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -150,7 +148,7 @@ public class LinuxRISCV64CallArranger {
|
|||||||
this.forArguments = forArguments;
|
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.
|
// the type alignment and XLEN bits, but never more than the stack alignment.
|
||||||
void alignStack(long alignment) {
|
void alignStack(long alignment) {
|
||||||
alignment = Utils.alignUp(Math.clamp(alignment, STACK_SLOT_SIZE, 16), STACK_SLOT_SIZE);
|
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));
|
Map.entry(STRUCT_REGISTER_XF, STRUCT_REGISTER_X));
|
||||||
}
|
}
|
||||||
|
|
||||||
static class UnboxBindingCalculator extends BindingCalculator {
|
static final class UnboxBindingCalculator extends BindingCalculator {
|
||||||
boolean forArguments;
|
final boolean forArguments;
|
||||||
|
|
||||||
UnboxBindingCalculator(boolean forArguments) {
|
UnboxBindingCalculator(boolean forArguments) {
|
||||||
super(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
|
* 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}.
|
* 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 EMPTY = new FieldCounter(0, 0, 0);
|
||||||
static final FieldCounter SINGLE_INTEGER = new FieldCounter(1, 0, 0);
|
static final FieldCounter SINGLE_INTEGER = new FieldCounter(1, 0, 0);
|
||||||
static final FieldCounter SINGLE_FLOAT = new FieldCounter(0, 1, 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) {
|
private static List<FlattenedFieldDesc> getFlattenedFieldsInner(long offset, MemoryLayout layout) {
|
||||||
if (layout instanceof ValueLayout valueLayout) {
|
return switch (layout) {
|
||||||
TypeClass typeClass = classifyValueType(valueLayout);
|
case ValueLayout valueLayout -> {
|
||||||
return List.of(switch (typeClass) {
|
TypeClass typeClass = classifyValueType(valueLayout);
|
||||||
case INTEGER, FLOAT -> new FlattenedFieldDesc(typeClass, offset, valueLayout);
|
yield List.of(switch (typeClass) {
|
||||||
default -> throw new IllegalStateException("Should not reach here.");
|
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()) {
|
case GroupLayout groupLayout -> {
|
||||||
if (memberLayout instanceof PaddingLayout) {
|
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();
|
offset += memberLayout.byteSize();
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
fields.addAll(getFlattenedFieldsInner(offset, memberLayout));
|
yield fields;
|
||||||
offset += memberLayout.byteSize();
|
|
||||||
}
|
}
|
||||||
return fields;
|
case SequenceLayout sequenceLayout -> {
|
||||||
} else if (layout instanceof SequenceLayout sequenceLayout) {
|
List<FlattenedFieldDesc> fields = new ArrayList<>();
|
||||||
List<FlattenedFieldDesc> fields = new ArrayList<>();
|
MemoryLayout elementLayout = sequenceLayout.elementLayout();
|
||||||
MemoryLayout elementLayout = sequenceLayout.elementLayout();
|
for (long i = 0; i < sequenceLayout.elementCount(); i++) {
|
||||||
for (long i = 0; i < sequenceLayout.elementCount(); i++) {
|
fields.addAll(getFlattenedFieldsInner(offset, elementLayout));
|
||||||
fields.addAll(getFlattenedFieldsInner(offset, elementLayout));
|
offset += elementLayout.byteSize();
|
||||||
offset += elementLayout.byteSize();
|
}
|
||||||
|
yield fields;
|
||||||
}
|
}
|
||||||
return fields;
|
case null, default -> throw new IllegalStateException("Cannot get here: " + layout);
|
||||||
} else {
|
};
|
||||||
throw new IllegalStateException("Cannot get here: " + layout);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<FlattenedFieldDesc> getFlattenedFields(GroupLayout layout) {
|
public static List<FlattenedFieldDesc> getFlattenedFields(GroupLayout layout) {
|
||||||
|
@ -52,15 +52,12 @@ public final class S390Architecture implements Architecture {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int typeSize(int cls) {
|
public int typeSize(int cls) {
|
||||||
switch (cls) {
|
return switch (cls) {
|
||||||
case StorageType.INTEGER:
|
case StorageType.INTEGER -> INTEGER_REG_SIZE;
|
||||||
return INTEGER_REG_SIZE;
|
case StorageType.FLOAT -> FLOAT_REG_SIZE;
|
||||||
case StorageType.FLOAT:
|
|
||||||
return FLOAT_REG_SIZE;
|
|
||||||
// STACK is deliberately omitted
|
// STACK is deliberately omitted
|
||||||
}
|
default -> throw new IllegalArgumentException("Invalid Storage Class: " + cls);
|
||||||
|
};
|
||||||
throw new IllegalArgumentException("Invalid Storage Class: " + cls);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface StorageType {
|
public interface StorageType {
|
||||||
|
@ -37,19 +37,15 @@ import jdk.internal.foreign.abi.CallingSequence;
|
|||||||
import jdk.internal.foreign.abi.CallingSequenceBuilder;
|
import jdk.internal.foreign.abi.CallingSequenceBuilder;
|
||||||
import jdk.internal.foreign.abi.DowncallLinker;
|
import jdk.internal.foreign.abi.DowncallLinker;
|
||||||
import jdk.internal.foreign.abi.LinkerOptions;
|
import jdk.internal.foreign.abi.LinkerOptions;
|
||||||
import jdk.internal.foreign.abi.UpcallLinker;
|
|
||||||
import jdk.internal.foreign.abi.SharedUtils;
|
import jdk.internal.foreign.abi.SharedUtils;
|
||||||
import jdk.internal.foreign.abi.VMStorage;
|
import jdk.internal.foreign.abi.VMStorage;
|
||||||
import jdk.internal.foreign.Utils;
|
import jdk.internal.foreign.Utils;
|
||||||
|
|
||||||
import java.lang.foreign.ValueLayout;
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodType;
|
import java.lang.invoke.MethodType;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
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.*;
|
||||||
import static jdk.internal.foreign.abi.s390.S390Architecture.Regs.*;
|
import static jdk.internal.foreign.abi.s390.S390Architecture.Regs.*;
|
||||||
|
|
||||||
|
@ -96,10 +96,7 @@ public enum TypeClass {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
TypeClass baseArgClass = classifyValueType((ValueLayout) baseType);
|
TypeClass baseArgClass = classifyValueType((ValueLayout) baseType);
|
||||||
if (baseArgClass != FLOAT)
|
return baseArgClass == FLOAT;
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TypeClass classifyStructType(MemoryLayout layout) {
|
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.DowncallLinker;
|
||||||
import jdk.internal.foreign.abi.LinkerOptions;
|
import jdk.internal.foreign.abi.LinkerOptions;
|
||||||
import jdk.internal.foreign.abi.SharedUtils;
|
import jdk.internal.foreign.abi.SharedUtils;
|
||||||
import jdk.internal.foreign.abi.UpcallLinker;
|
|
||||||
import jdk.internal.foreign.abi.VMStorage;
|
import jdk.internal.foreign.abi.VMStorage;
|
||||||
import jdk.internal.foreign.abi.x64.X86_64Architecture;
|
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);
|
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)];
|
VMStorage[] storage = new VMStorage[(int)(nIntegerReg + nVectorReg)];
|
||||||
for (int i = 0 ; i < typeClass.classes.size() ; i++) {
|
for (int i = 0 ; i < typeClass.classes.size() ; i++) {
|
||||||
boolean sse = typeClass.classes.get(i) == ArgumentClassImpl.SSE;
|
boolean sse = typeClass.classes.get(i) == ArgumentClassImpl.SSE;
|
||||||
|
@ -208,35 +208,40 @@ class TypeClass {
|
|||||||
return groups;
|
return groups;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void groupByEightBytes(MemoryLayout l, long offset, List<ArgumentClassImpl>[] groups) {
|
private static void groupByEightBytes(MemoryLayout layout,
|
||||||
if (l instanceof GroupLayout group) {
|
long offset,
|
||||||
for (MemoryLayout m : group.memberLayouts()) {
|
List<ArgumentClassImpl>[] groups) {
|
||||||
groupByEightBytes(m, offset, groups);
|
switch (layout) {
|
||||||
if (group instanceof StructLayout) {
|
case GroupLayout group -> {
|
||||||
offset += m.byteSize();
|
for (MemoryLayout m : group.memberLayouts()) {
|
||||||
|
groupByEightBytes(m, offset, groups);
|
||||||
|
if (group instanceof StructLayout) {
|
||||||
|
offset += m.byteSize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (l instanceof PaddingLayout) {
|
case 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();
|
|
||||||
}
|
}
|
||||||
} else if (l instanceof ValueLayout vl) {
|
case SequenceLayout seq -> {
|
||||||
List<ArgumentClassImpl> layouts = groups[(int)offset / 8];
|
MemoryLayout elem = seq.elementLayout();
|
||||||
if (layouts == null) {
|
for (long i = 0; i < seq.elementCount(); i++) {
|
||||||
layouts = new ArrayList<>();
|
groupByEightBytes(elem, offset, groups);
|
||||||
groups[(int)offset / 8] = layouts;
|
offset += elem.byteSize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// if the aggregate contains unaligned fields, it has class MEMORY
|
case ValueLayout vl -> {
|
||||||
ArgumentClassImpl argumentClass = (offset % vl.byteAlignment()) == 0 ?
|
List<ArgumentClassImpl> layouts = groups[(int) offset / 8];
|
||||||
argumentClassFor(vl) :
|
if (layouts == null) {
|
||||||
ArgumentClassImpl.MEMORY;
|
layouts = new ArrayList<>();
|
||||||
layouts.add(argumentClass);
|
groups[(int) offset / 8] = layouts;
|
||||||
} else {
|
}
|
||||||
throw new IllegalStateException("Unexpected layout: " + l);
|
// 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.DowncallLinker;
|
||||||
import jdk.internal.foreign.abi.LinkerOptions;
|
import jdk.internal.foreign.abi.LinkerOptions;
|
||||||
import jdk.internal.foreign.abi.SharedUtils;
|
import jdk.internal.foreign.abi.SharedUtils;
|
||||||
import jdk.internal.foreign.abi.UpcallLinker;
|
|
||||||
import jdk.internal.foreign.abi.VMStorage;
|
import jdk.internal.foreign.abi.VMStorage;
|
||||||
import jdk.internal.foreign.abi.x64.X86_64Architecture;
|
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.GroupLayout;
|
||||||
import java.lang.foreign.MemoryLayout;
|
import java.lang.foreign.MemoryLayout;
|
||||||
import java.lang.foreign.MemorySegment;
|
import java.lang.foreign.MemorySegment;
|
||||||
import java.lang.foreign.ValueLayout;
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodType;
|
import java.lang.invoke.MethodType;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -38,7 +38,7 @@ enum TypeClass {
|
|||||||
VARARG_FLOAT;
|
VARARG_FLOAT;
|
||||||
|
|
||||||
private static TypeClass classifyValueType(ValueLayout type, boolean isVararg) {
|
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).
|
// like a struct when passing as an argument (passed by pointer).
|
||||||
// https://docs.microsoft.com/en-us/cpp/cpp/m128?view=vs-2019
|
// https://docs.microsoft.com/en-us/cpp/cpp/m128?view=vs-2019
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ import java.util.stream.Collectors;
|
|||||||
* @implSpec
|
* @implSpec
|
||||||
* This class is immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
|
* 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>
|
extends AbstractLayout<L>
|
||||||
permits StructLayoutImpl, UnionLayoutImpl {
|
permits StructLayoutImpl, UnionLayoutImpl {
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ public final class ValueLayouts {
|
|||||||
// Suppresses default constructor, ensuring non-instantiability.
|
// Suppresses default constructor, ensuring non-instantiability.
|
||||||
private ValueLayouts() {}
|
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;
|
static final int ADDRESS_SIZE_BYTES = Unsafe.ADDRESS_SIZE;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user