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:
Jorn Vernee 2023-10-20 15:40:39 +00:00
parent b1228de623
commit 8065233e8b
34 changed files with 230 additions and 256 deletions

@ -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 {

@ -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;