diff --git a/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java b/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java index bf8b1e79819..361a10cf49b 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java @@ -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 diff --git a/src/java.base/share/classes/jdk/internal/foreign/ConfinedSession.java b/src/java.base/share/classes/jdk/internal/foreign/ConfinedSession.java index 4961cecde5e..4ff0df787c5 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/ConfinedSession.java +++ b/src/java.base/share/classes/jdk/internal/foreign/ConfinedSession.java @@ -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; diff --git a/src/java.base/share/classes/jdk/internal/foreign/HeapMemorySegmentImpl.java b/src/java.base/share/classes/jdk/internal/foreign/HeapMemorySegmentImpl.java index dd6a6e49edd..e1ea65ff308 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/HeapMemorySegmentImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/HeapMemorySegmentImpl.java @@ -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(); } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java b/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java index f87bbf306c3..53d306e4bc6 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java +++ b/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java @@ -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 diff --git a/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java b/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java index 33bac79999f..b74ccf33936 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java @@ -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(); diff --git a/src/java.base/share/classes/jdk/internal/foreign/SegmentFactories.java b/src/java.base/share/classes/jdk/internal/foreign/SegmentFactories.java index 9e9d60ecf89..17f141b4e8c 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/SegmentFactories.java +++ b/src/java.base/share/classes/jdk/internal/foreign/SegmentFactories.java @@ -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)); } diff --git a/src/java.base/share/classes/jdk/internal/foreign/SharedSession.java b/src/java.base/share/classes/jdk/internal/foreign/SharedSession.java index 984d9d99921..8d54a1e2d8a 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/SharedSession.java +++ b/src/java.base/share/classes/jdk/internal/foreign/SharedSession.java @@ -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; diff --git a/src/java.base/share/classes/jdk/internal/foreign/StringSupport.java b/src/java.base/share/classes/jdk/internal/foreign/StringSupport.java index eaa028cae39..8527d374fb2 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/StringSupport.java +++ b/src/java.base/share/classes/jdk/internal/foreign/StringSupport.java @@ -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(); diff --git a/src/java.base/share/classes/jdk/internal/foreign/SystemLookup.java b/src/java.base/share/classes/jdk/internal/foreign/SystemLookup.java index 4d87b01d002..74fe8492f82 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/SystemLookup.java +++ b/src/java.base/share/classes/jdk/internal/foreign/SystemLookup.java @@ -75,7 +75,7 @@ public final class SystemLookup implements SymbolLookup { private static SymbolLookup makeWindowsLookup() { @SuppressWarnings("removal") - String systemRoot = AccessController.doPrivileged(new PrivilegedAction() { + 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 useUCRT = AccessController.doPrivileged(new PrivilegedAction<>() { @Override public Boolean run() { return Files.exists(ucrtbase); diff --git a/src/java.base/share/classes/jdk/internal/foreign/Utils.java b/src/java.base/share/classes/jdk/internal/foreign/Utils.java index 3809aedba80..00ab90e9612 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/Utils.java +++ b/src/java.base/share/classes/jdk/internal/foreign/Utils.java @@ -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()); + }; + } + + } + } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java index ae41d4f1756..2bb95e58155 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java @@ -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); diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/Binding.java b/src/java.base/share/classes/jdk/internal/foreign/abi/Binding.java index 5ff8508adf4..875b5d998e3 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/Binding.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/Binding.java @@ -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). * * -------------------- diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/CapturableState.java b/src/java.base/share/classes/jdk/internal/foreign/abi/CapturableState.java index c2a480ce54d..8689751a3c8 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/CapturableState.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/CapturableState.java @@ -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), diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java b/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java index 90c3efbfe67..b08202e5e35 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java @@ -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)); } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/SoftReferenceCache.java b/src/java.base/share/classes/jdk/internal/foreign/abi/SoftReferenceCache.java index 3e801600cb6..04565c66c86 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/SoftReferenceCache.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/SoftReferenceCache.java @@ -29,7 +29,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; -class SoftReferenceCache { +final class SoftReferenceCache { private final Map cache = new ConcurrentHashMap<>(); public V get(K key, Function valueFactory) { @@ -41,10 +41,7 @@ class SoftReferenceCache { private final class Node { private volatile SoftReference ref; - public Node() { - } - - public V get(K key, Function valueFactory) { + V get(K key, Function valueFactory) { V result; if (ref == null || (result = ref.get()) == null) { synchronized (this) { // don't let threads race on the valueFactory::apply call diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java index ed3a0d6121e..efd5090e8d9 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java @@ -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 */ diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java index 3f380a04db8..0772c09fdb5 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java @@ -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 { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/windows/WindowsAArch64CallArranger.java b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/windows/WindowsAArch64CallArranger.java index a1caf3da65c..18df7387075 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/windows/WindowsAArch64CallArranger.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/windows/WindowsAArch64CallArranger.java @@ -52,7 +52,7 @@ public class WindowsAArch64CallArranger extends CallArranger { // // Although the AAPCS64 says r0-7 and v0-7 are all valid return // registers, it's not possible to generate a C function that uses - // r2-7 and v4-7 so they are omitted here. + // r2-7 and v4-7 so, they are omitted here. private static final ABIDescriptor WindowsAArch64AbiDescriptor = abiFor( new VMStorage[] { r0, r1, r2, r3, r4, r5, r6, r7, INDIRECT_RESULT}, new VMStorage[] { v0, v1, v2, v3, v4, v5, v6, v7 }, diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/windows/WindowsAArch64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/windows/WindowsAArch64Linker.java index 71d18d7b182..eac1d49c1dd 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/windows/WindowsAArch64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/windows/WindowsAArch64Linker.java @@ -47,13 +47,12 @@ public final class WindowsAArch64Linker extends AbstractLinker { static final Map 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 diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/fallback/FFIType.java b/src/java.base/share/classes/jdk/internal/foreign/abi/fallback/FFIType.java index f5e3c29fc81..c8fa729711a 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/fallback/FFIType.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/fallback/FFIType.java @@ -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( diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/fallback/FallbackLinker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/fallback/FallbackLinker.java index 8e688c06eac..40ebe3b99ca 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/fallback/FallbackLinker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/fallback/FallbackLinker.java @@ -240,30 +240,25 @@ public final class FallbackLinker extends AbstractLinker { private static void writeValue(Object arg, MemoryLayout layout, MemorySegment argSeg, Consumer 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; + } } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/ppc64/PPC64Architecture.java b/src/java.base/share/classes/jdk/internal/foreign/abi/ppc64/PPC64Architecture.java index 3a6eb89c9ec..d9391e4064a 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/ppc64/PPC64Architecture.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/ppc64/PPC64Architecture.java @@ -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 { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/RISCV64Architecture.java b/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/RISCV64Architecture.java index 9c3d64be7ad..409b685baed 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/RISCV64Architecture.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/RISCV64Architecture.java @@ -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(); diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/linux/LinuxRISCV64CallArranger.java b/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/linux/LinuxRISCV64CallArranger.java index 8da7a124abc..60959cf7544 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/linux/LinuxRISCV64CallArranger.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/linux/LinuxRISCV64CallArranger.java @@ -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); diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/linux/TypeClass.java b/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/linux/TypeClass.java index 380f0a83109..e00771d2e59 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/linux/TypeClass.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/linux/TypeClass.java @@ -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 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 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 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 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 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 getFlattenedFields(GroupLayout layout) { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/s390/S390Architecture.java b/src/java.base/share/classes/jdk/internal/foreign/abi/s390/S390Architecture.java index bbafef2f3dc..146536f0bc4 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/s390/S390Architecture.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/s390/S390Architecture.java @@ -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 { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/s390/linux/LinuxS390CallArranger.java b/src/java.base/share/classes/jdk/internal/foreign/abi/s390/linux/LinuxS390CallArranger.java index 84392e45089..009cfb6227f 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/s390/linux/LinuxS390CallArranger.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/s390/linux/LinuxS390CallArranger.java @@ -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.*; diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/s390/linux/TypeClass.java b/src/java.base/share/classes/jdk/internal/foreign/abi/s390/linux/TypeClass.java index 095cb2c08a8..1f96fa4bf79 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/s390/linux/TypeClass.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/s390/linux/TypeClass.java @@ -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) { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java index 59224022e74..75e8d0926a1 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java @@ -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; diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/TypeClass.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/TypeClass.java index d970a543a23..7a6be52ba2f 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/TypeClass.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/TypeClass.java @@ -208,35 +208,40 @@ class TypeClass { return groups; } - private static void groupByEightBytes(MemoryLayout l, long offset, List[] 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[] 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 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 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); } } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java index f905dae0fe5..4d4ad65b1c6 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java @@ -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; diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/TypeClass.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/TypeClass.java index 892e4c49318..04839b740dc 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/TypeClass.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/TypeClass.java @@ -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 diff --git a/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractGroupLayout.java b/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractGroupLayout.java index 6c5fba7ea6b..a2e6ff36591 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractGroupLayout.java +++ b/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractGroupLayout.java @@ -40,7 +40,7 @@ import java.util.stream.Collectors; * @implSpec * This class is immutable, thread-safe and value-based. */ -public sealed abstract class AbstractGroupLayout & MemoryLayout> +abstract sealed class AbstractGroupLayout & MemoryLayout> extends AbstractLayout permits StructLayoutImpl, UnionLayoutImpl { diff --git a/src/java.base/share/classes/jdk/internal/foreign/layout/ValueLayouts.java b/src/java.base/share/classes/jdk/internal/foreign/layout/ValueLayouts.java index 2567227abf6..cc61ed41a98 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/layout/ValueLayouts.java +++ b/src/java.base/share/classes/jdk/internal/foreign/layout/ValueLayouts.java @@ -59,7 +59,7 @@ public final class ValueLayouts { // Suppresses default constructor, ensuring non-instantiability. private ValueLayouts() {} - abstract sealed static class AbstractValueLayout & ValueLayout> extends AbstractLayout { + abstract static sealed class AbstractValueLayout & ValueLayout> extends AbstractLayout { static final int ADDRESS_SIZE_BYTES = Unsafe.ADDRESS_SIZE;