8321786: SegmentAllocator:allocateFrom(ValueLayout, MemorySegment,ValueLayout,long,long) spec mismatch in exception scenario
Reviewed-by: mcimadamore
This commit is contained in:
parent
d75d876edd
commit
7edd10e5fa
src/java.base/share/classes
java/lang/foreign
jdk/internal/foreign
test/jdk/java/foreign
@ -1016,7 +1016,7 @@ public sealed interface MemoryLayout
|
||||
* @throws IllegalArgumentException if {@code elementLayout.byteSize() % elementLayout.byteAlignment() != 0}
|
||||
*/
|
||||
static SequenceLayout sequenceLayout(long elementCount, MemoryLayout elementLayout) {
|
||||
MemoryLayoutUtil.requireNonNegative(elementCount);
|
||||
Utils.checkNonNegativeArgument(elementCount, "elementCount");
|
||||
Objects.requireNonNull(elementLayout);
|
||||
Utils.checkElementAlignment(elementLayout,
|
||||
"Element layout size is not multiple of alignment");
|
||||
|
@ -44,6 +44,7 @@ import java.util.stream.Stream;
|
||||
import jdk.internal.foreign.AbstractMemorySegmentImpl;
|
||||
import jdk.internal.foreign.MemorySessionImpl;
|
||||
import jdk.internal.foreign.SegmentFactories;
|
||||
import jdk.internal.foreign.Utils;
|
||||
import jdk.internal.javac.Restricted;
|
||||
import jdk.internal.reflect.CallerSensitive;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
@ -1591,6 +1592,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
|
||||
* in the provided layout
|
||||
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
|
||||
* or {@code offset < 0}
|
||||
*/
|
||||
byte get(ValueLayout.OfByte layout, long offset);
|
||||
|
||||
@ -1609,6 +1611,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
|
||||
* in the provided layout
|
||||
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
|
||||
* or {@code offset < 0}
|
||||
* @throws IllegalArgumentException if this segment is
|
||||
* {@linkplain #isReadOnly() read-only}
|
||||
*/
|
||||
@ -1629,6 +1632,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
|
||||
* in the provided layout
|
||||
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
|
||||
* or {@code offset < 0}
|
||||
*/
|
||||
boolean get(ValueLayout.OfBoolean layout, long offset);
|
||||
|
||||
@ -1647,6 +1651,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
|
||||
* in the provided layout
|
||||
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
|
||||
* or {@code offset < 0}
|
||||
* @throws IllegalArgumentException if this segment is
|
||||
* {@linkplain #isReadOnly() read-only}
|
||||
*/
|
||||
@ -1667,6 +1672,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
|
||||
* in the provided layout
|
||||
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
|
||||
* or {@code offset < 0}
|
||||
*/
|
||||
char get(ValueLayout.OfChar layout, long offset);
|
||||
|
||||
@ -1685,6 +1691,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
|
||||
* in the provided layout
|
||||
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
|
||||
* or {@code offset < 0}
|
||||
* @throws IllegalArgumentException if this segment is
|
||||
* {@linkplain #isReadOnly() read-only}
|
||||
*/
|
||||
@ -1705,6 +1712,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
|
||||
* in the provided layout
|
||||
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
|
||||
* or {@code offset < 0}
|
||||
*/
|
||||
short get(ValueLayout.OfShort layout, long offset);
|
||||
|
||||
@ -1723,6 +1731,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
|
||||
* in the provided layout
|
||||
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
|
||||
* or {@code offset < 0}
|
||||
* @throws IllegalArgumentException if this segment is
|
||||
* {@linkplain #isReadOnly() read-only}
|
||||
*/
|
||||
@ -1743,6 +1752,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
|
||||
* in the provided layout
|
||||
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
|
||||
* or {@code offset < 0}
|
||||
*/
|
||||
int get(ValueLayout.OfInt layout, long offset);
|
||||
|
||||
@ -1761,6 +1771,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
|
||||
* in the provided layout
|
||||
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
|
||||
* or {@code offset < 0}
|
||||
* @throws IllegalArgumentException if this segment is
|
||||
* {@linkplain #isReadOnly() read-only}
|
||||
*/
|
||||
@ -1781,6 +1792,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
|
||||
* in the provided layout
|
||||
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
|
||||
* or {@code offset < 0}
|
||||
*/
|
||||
float get(ValueLayout.OfFloat layout, long offset);
|
||||
|
||||
@ -1799,6 +1811,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
|
||||
* in the provided layout
|
||||
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
|
||||
* or {@code offset < 0}
|
||||
* @throws IllegalArgumentException if this segment is
|
||||
* {@linkplain #isReadOnly() read-only}
|
||||
*/
|
||||
@ -1819,6 +1832,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
|
||||
* in the provided layout
|
||||
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
|
||||
* or {@code offset < 0}
|
||||
*/
|
||||
long get(ValueLayout.OfLong layout, long offset);
|
||||
|
||||
@ -1837,6 +1851,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
|
||||
* in the provided layout
|
||||
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
|
||||
* or {@code offset < 0}
|
||||
* @throws IllegalArgumentException if this segment is
|
||||
* {@linkplain #isReadOnly() read-only}
|
||||
*/
|
||||
@ -1857,6 +1872,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
|
||||
* in the provided layout
|
||||
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
|
||||
* or {@code offset < 0}
|
||||
*/
|
||||
double get(ValueLayout.OfDouble layout, long offset);
|
||||
|
||||
@ -1875,6 +1891,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
|
||||
* in the provided layout
|
||||
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
|
||||
* or {@code offset < 0}
|
||||
* @throws IllegalArgumentException if this segment is
|
||||
* {@linkplain #isReadOnly() read-only}
|
||||
*/
|
||||
@ -1905,6 +1922,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
|
||||
* in {@code T}
|
||||
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
|
||||
* or {@code offset < 0}
|
||||
*/
|
||||
MemorySegment get(AddressLayout layout, long offset);
|
||||
|
||||
@ -1923,8 +1941,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
|
||||
* in the provided layout
|
||||
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
|
||||
* @throws UnsupportedOperationException if this segment is
|
||||
* {@linkplain #isReadOnly() read-only}
|
||||
* or {@code offset < 0}
|
||||
* @throws IllegalArgumentException if {@code value} is not a
|
||||
* {@linkplain #isNative() native} segment
|
||||
* @throws IllegalArgumentException if this segment is
|
||||
@ -1951,6 +1968,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
|
||||
* or {@code index < 0}
|
||||
*/
|
||||
byte getAtIndex(ValueLayout.OfByte layout, long index);
|
||||
|
||||
@ -1973,6 +1991,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
|
||||
* or {@code index < 0}
|
||||
*/
|
||||
boolean getAtIndex(ValueLayout.OfBoolean layout, long index);
|
||||
|
||||
@ -1995,6 +2014,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
|
||||
* or {@code index < 0}
|
||||
*/
|
||||
char getAtIndex(ValueLayout.OfChar layout, long index);
|
||||
|
||||
@ -2017,7 +2037,8 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
|
||||
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}
|
||||
* or {@code index < 0}
|
||||
* @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
|
||||
*/
|
||||
void setAtIndex(ValueLayout.OfChar layout, long index, char value);
|
||||
|
||||
@ -2040,6 +2061,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
|
||||
* or {@code index < 0}
|
||||
*/
|
||||
short getAtIndex(ValueLayout.OfShort layout, long index);
|
||||
|
||||
@ -2061,6 +2083,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
|
||||
* or {@code index < 0}
|
||||
* @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
|
||||
*/
|
||||
void setAtIndex(ValueLayout.OfByte layout, long index, byte value);
|
||||
@ -2084,6 +2107,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
|
||||
* or {@code index < 0}
|
||||
* @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
|
||||
*/
|
||||
void setAtIndex(ValueLayout.OfBoolean layout, long index, boolean value);
|
||||
@ -2107,6 +2131,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
|
||||
* or {@code index < 0}
|
||||
* @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
|
||||
*/
|
||||
void setAtIndex(ValueLayout.OfShort layout, long index, short value);
|
||||
@ -2130,6 +2155,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
|
||||
* or {@code index < 0}
|
||||
*/
|
||||
int getAtIndex(ValueLayout.OfInt layout, long index);
|
||||
|
||||
@ -2152,6 +2178,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
|
||||
* or {@code index < 0}
|
||||
* @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
|
||||
*/
|
||||
void setAtIndex(ValueLayout.OfInt layout, long index, int value);
|
||||
@ -2175,6 +2202,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
|
||||
* or {@code index < 0}
|
||||
*/
|
||||
float getAtIndex(ValueLayout.OfFloat layout, long index);
|
||||
|
||||
@ -2197,6 +2225,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
|
||||
* or {@code index < 0}
|
||||
* @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
|
||||
*/
|
||||
void setAtIndex(ValueLayout.OfFloat layout, long index, float value);
|
||||
@ -2220,6 +2249,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
|
||||
* or {@code index < 0}
|
||||
*/
|
||||
long getAtIndex(ValueLayout.OfLong layout, long index);
|
||||
|
||||
@ -2242,6 +2272,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
|
||||
* or {@code index < 0}
|
||||
* @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
|
||||
*/
|
||||
void setAtIndex(ValueLayout.OfLong layout, long index, long value);
|
||||
@ -2265,6 +2296,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
|
||||
* or {@code index < 0}
|
||||
*/
|
||||
double getAtIndex(ValueLayout.OfDouble layout, long index);
|
||||
|
||||
@ -2287,6 +2319,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
|
||||
* or {@code index < 0}
|
||||
* @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
|
||||
*/
|
||||
void setAtIndex(ValueLayout.OfDouble layout, long index, double value);
|
||||
@ -2319,6 +2352,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* in {@code T}
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
|
||||
* or {@code index < 0}
|
||||
*/
|
||||
MemorySegment getAtIndex(AddressLayout layout, long index);
|
||||
|
||||
@ -2341,7 +2375,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
||||
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
|
||||
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
|
||||
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}
|
||||
* or {@code index < 0}
|
||||
* @throws IllegalArgumentException if {@code value} is not a {@linkplain #isNative() native} segment
|
||||
* @throws IllegalArgumentException if this segment is
|
||||
* {@linkplain #isReadOnly() read-only}
|
||||
|
@ -33,6 +33,7 @@ import jdk.internal.foreign.AbstractMemorySegmentImpl;
|
||||
import jdk.internal.foreign.ArenaImpl;
|
||||
import jdk.internal.foreign.SlicingAllocator;
|
||||
import jdk.internal.foreign.StringSupport;
|
||||
import jdk.internal.foreign.Utils;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
|
||||
/**
|
||||
@ -390,9 +391,10 @@ public interface SegmentAllocator {
|
||||
* with {@code source} is not {@linkplain MemorySegment.Scope#isAlive() alive}
|
||||
* @throws WrongThreadException if this method is called from a thread {@code T},
|
||||
* such that {@code source.isAccessibleBy(T) == false}
|
||||
* @throws IndexOutOfBoundsException if {@code elementCount * sourceElementLayout.byteSize()} overflows
|
||||
* @throws IllegalArgumentException if {@code elementCount * sourceElementLayout.byteSize()} overflows
|
||||
* @throws IllegalArgumentException if {@code elementCount < 0}
|
||||
* @throws IndexOutOfBoundsException if {@code sourceOffset > source.byteSize() - (elementCount * sourceElementLayout.byteSize())}
|
||||
* @throws IndexOutOfBoundsException if either {@code sourceOffset} or {@code elementCount} are {@code < 0}
|
||||
* @throws IndexOutOfBoundsException if {@code sourceOffset < 0}
|
||||
*/
|
||||
@ForceInline
|
||||
default MemorySegment allocateFrom(ValueLayout elementLayout,
|
||||
|
@ -153,9 +153,7 @@ public abstract sealed class AbstractMemorySegmentImpl
|
||||
|
||||
public MemorySegment reinterpretInternal(Class<?> callerClass, long newSize, Scope scope, Consumer<MemorySegment> cleanup) {
|
||||
Reflection.ensureNativeAccess(callerClass, MemorySegment.class, "reinterpret");
|
||||
if (newSize < 0) {
|
||||
throw new IllegalArgumentException("newSize < 0");
|
||||
}
|
||||
Utils.checkNonNegativeArgument(newSize, "newSize");
|
||||
if (!isNative()) throw new UnsupportedOperationException("Not a native segment");
|
||||
Runnable action = cleanup != null ?
|
||||
() -> cleanup.accept(SegmentFactories.makeNativeSegmentUnchecked(address(), newSize)) :
|
||||
@ -594,6 +592,7 @@ public abstract sealed class AbstractMemorySegmentImpl
|
||||
MemorySegment dstSegment, ValueLayout dstElementLayout, long dstOffset,
|
||||
long elementCount) {
|
||||
|
||||
Utils.checkNonNegativeIndex(elementCount, "elementCount");
|
||||
AbstractMemorySegmentImpl srcImpl = (AbstractMemorySegmentImpl)srcSegment;
|
||||
AbstractMemorySegmentImpl dstImpl = (AbstractMemorySegmentImpl)dstSegment;
|
||||
if (srcElementLayout.byteSize() != dstElementLayout.byteSize()) {
|
||||
@ -625,7 +624,7 @@ public abstract sealed class AbstractMemorySegmentImpl
|
||||
public static void copy(MemorySegment srcSegment, ValueLayout srcLayout, long srcOffset,
|
||||
Object dstArray, int dstIndex,
|
||||
int elementCount) {
|
||||
|
||||
Utils.checkNonNegativeIndex(elementCount, "elementCount");
|
||||
var dstInfo = Utils.BaseAndScale.of(dstArray);
|
||||
if (dstArray.getClass().componentType() != srcLayout.carrier()) {
|
||||
throw new IllegalArgumentException("Incompatible value layout: " + srcLayout);
|
||||
@ -652,7 +651,6 @@ public abstract sealed class AbstractMemorySegmentImpl
|
||||
public static void copy(Object srcArray, int srcIndex,
|
||||
MemorySegment dstSegment, ValueLayout dstLayout, long dstOffset,
|
||||
int elementCount) {
|
||||
|
||||
var srcInfo = Utils.BaseAndScale.of(srcArray);
|
||||
if (srcArray.getClass().componentType() != dstLayout.carrier()) {
|
||||
throw new IllegalArgumentException("Incompatible value layout: " + dstLayout);
|
||||
|
@ -200,11 +200,8 @@ public final class Utils {
|
||||
}
|
||||
|
||||
public static void checkAllocationSizeAndAlign(long byteSize, long byteAlignment) {
|
||||
// size should be >= 0
|
||||
if (byteSize < 0) {
|
||||
throw new IllegalArgumentException("Invalid allocation size : " + byteSize);
|
||||
}
|
||||
|
||||
// byteSize should be >= 0
|
||||
Utils.checkNonNegativeArgument(byteSize, "allocation size");
|
||||
checkAlign(byteAlignment);
|
||||
}
|
||||
|
||||
@ -216,6 +213,20 @@ public final class Utils {
|
||||
}
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
public static void checkNonNegativeArgument(long value, String name) {
|
||||
if (value < 0) {
|
||||
throw new IllegalArgumentException("The provided " + name + " is negative: " + value);
|
||||
}
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
public static void checkNonNegativeIndex(long value, String name) {
|
||||
if (value < 0) {
|
||||
throw new IndexOutOfBoundsException("The provided " + name + " is negative: " + value);
|
||||
}
|
||||
}
|
||||
|
||||
private static long computePadding(long offset, long align) {
|
||||
boolean isAligned = offset == 0 || offset % align == 0;
|
||||
if (isAligned) {
|
||||
|
@ -151,13 +151,8 @@ public abstract sealed class AbstractLayout<L extends AbstractLayout<L> & Memory
|
||||
}
|
||||
|
||||
public long scale(long offset, long index) {
|
||||
if (offset < 0) {
|
||||
throw new IllegalArgumentException("Negative offset: " + offset);
|
||||
}
|
||||
if (index < 0) {
|
||||
throw new IllegalArgumentException("Negative index: " + index);
|
||||
}
|
||||
|
||||
Utils.checkNonNegativeArgument(offset, "offset");
|
||||
Utils.checkNonNegativeArgument(index, "index");
|
||||
return Math.addExact(offset, Math.multiplyExact(byteSize(), index));
|
||||
}
|
||||
|
||||
|
@ -30,13 +30,6 @@ public final class MemoryLayoutUtil {
|
||||
private MemoryLayoutUtil() {
|
||||
}
|
||||
|
||||
public static long requireNonNegative(long value) {
|
||||
if (value < 0) {
|
||||
throw new IllegalArgumentException("The provided value was negative: " + value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public static long requireByteSizeValid(long byteSize, boolean allowZero) {
|
||||
if ((byteSize == 0 && !allowZero) || byteSize < 0) {
|
||||
throw new IllegalArgumentException("Invalid byte size: " + byteSize);
|
||||
|
@ -371,13 +371,13 @@ public class TestLayouts {
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class,
|
||||
expectedExceptionsMessageRegExp=".*Negative offset.*")
|
||||
expectedExceptionsMessageRegExp=".*offset is negative.*")
|
||||
public void testScaleNegativeOffset() {
|
||||
JAVA_INT.scale(-1, 0);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class,
|
||||
expectedExceptionsMessageRegExp=".*Negative index.*")
|
||||
expectedExceptionsMessageRegExp=".*index is negative.*")
|
||||
public void testScaleNegativeIndex() {
|
||||
JAVA_INT.scale(0, -1);
|
||||
}
|
||||
|
@ -164,6 +164,13 @@ public class TestMemoryAccessInstance {
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "segmentAccessors")
|
||||
public <X, L extends ValueLayout> void negativeOffset(String testName, Accessor<X, L> accessor) {
|
||||
MemorySegment segment = MemorySegment.ofArray(new byte[100]);
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> accessor.get(segment, -ValueLayout.JAVA_LONG.byteSize()));
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> accessor.set(segment, -ValueLayout.JAVA_LONG.byteSize(), accessor.value));
|
||||
}
|
||||
|
||||
static final ByteOrder NE = ByteOrder.nativeOrder();
|
||||
|
||||
@DataProvider(name = "segmentAccessors")
|
||||
|
@ -27,6 +27,7 @@
|
||||
*/
|
||||
|
||||
import java.lang.foreign.Arena;
|
||||
import java.lang.foreign.MemoryLayout;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
import java.lang.foreign.ValueLayout;
|
||||
|
||||
@ -135,6 +136,8 @@ public class TestScopedOperations {
|
||||
ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_FLOAT, new float[]{0}), "Arena::allocateFrom/float");
|
||||
ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_LONG, new long[]{0}), "Arena::allocateFrom/long");
|
||||
ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_DOUBLE, new double[]{0}), "Arena::allocateFrom/double");
|
||||
var source = MemorySegment.ofArray(new byte[]{});
|
||||
ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_INT, source, JAVA_BYTE, 0, 1), "Arena::allocateFrom/5arg");
|
||||
};
|
||||
|
||||
@DataProvider(name = "scopedOperations")
|
||||
|
@ -44,6 +44,8 @@ import java.nio.LongBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
@ -189,6 +191,81 @@ public class TestSegmentAllocators {
|
||||
}
|
||||
}
|
||||
|
||||
// Invariant checking tests for the SegmentAllocator method:
|
||||
// MemorySegment allocateFrom(ValueLayout elementLayout,
|
||||
// MemorySegment source,
|
||||
// ValueLayout sourceElementLayout,
|
||||
// long sourceOffset,
|
||||
// long elementCount) {
|
||||
@Test
|
||||
public void testAllocatorAllocateFromArguments() {
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
var sourceElements = 2;
|
||||
var source = arena.allocate(ValueLayout.JAVA_LONG, sourceElements);
|
||||
var elementLayout = ValueLayout.JAVA_INT;
|
||||
var sourceElementLayout = ValueLayout.JAVA_INT;
|
||||
|
||||
// IllegalArgumentException if {@code elementLayout.byteSize() != sourceElementLayout.byteSize()}
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
arena.allocateFrom(elementLayout, source, ValueLayout.JAVA_BYTE, 0, 1)
|
||||
);
|
||||
|
||||
// IllegalArgumentException if source segment/offset
|
||||
// are <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
|
||||
// in the source element layout
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
arena.allocateFrom(elementLayout, source.asSlice(1), sourceElementLayout, 0, 1)
|
||||
);
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
arena.allocateFrom(elementLayout, source, sourceElementLayout, 1, 1)
|
||||
);
|
||||
|
||||
// IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
arena.allocateFrom(elementLayout.withByteAlignment(elementLayout.byteAlignment() * 2), source, sourceElementLayout, 1, 1)
|
||||
);
|
||||
|
||||
// IllegalStateException if the {@linkplain MemorySegment#scope() scope} associated
|
||||
// with {@code source} is not {@linkplain MemorySegment.Scope#isAlive() alive}
|
||||
// This is tested in TestScopedOperations
|
||||
|
||||
// WrongThreadException if this method is called from a thread {@code T},
|
||||
// such that {@code source.isAccessibleBy(T) == false}
|
||||
CompletableFuture<Arena> future = CompletableFuture.supplyAsync(Arena::ofConfined);
|
||||
try {
|
||||
Arena otherThreadArena = future.get();
|
||||
assertThrows(WrongThreadException.class, () ->
|
||||
otherThreadArena.allocateFrom(elementLayout, source, sourceElementLayout, 0, 1)
|
||||
);
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
fail("Unable to create arena", e);
|
||||
}
|
||||
|
||||
// IllegalArgumentException if {@code elementCount * sourceElementLayout.byteSize()} overflows
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
arena.allocateFrom(elementLayout, source, sourceElementLayout, 0, Long.MAX_VALUE)
|
||||
);
|
||||
|
||||
// IndexOutOfBoundsException if {@code sourceOffset > source.byteSize() - (elementCount * sourceElementLayout.byteSize())}
|
||||
assertThrows(IndexOutOfBoundsException.class, () ->
|
||||
arena.allocateFrom(elementLayout, source, sourceElementLayout, source.byteSize() - (1 * sourceElementLayout.byteAlignment()) + elementLayout.byteSize(), 1)
|
||||
);
|
||||
|
||||
// IndexOutOfBoundsException if {@code sourceOffset < 0}
|
||||
assertThrows(IndexOutOfBoundsException.class, () ->
|
||||
arena.allocateFrom(elementLayout, source, sourceElementLayout, -elementLayout.byteSize(), 1)
|
||||
);
|
||||
|
||||
// IllegalArgumentException if {@code elementCount < 0}
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
arena.allocateFrom(elementLayout, source, sourceElementLayout, 0, -1)
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testArrayAllocateDelegation() {
|
||||
AtomicInteger calls = new AtomicInteger();
|
||||
|
@ -145,6 +145,66 @@ public class TestSegmentCopy {
|
||||
MemorySegment.copy(segment, JAVA_BYTE.withByteAlignment(2), 0, segment, 0, 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCopy5ArgWithNegativeValues() {
|
||||
MemorySegment src = MemorySegment.ofArray(new byte[] {1, 2, 3, 4});
|
||||
MemorySegment dst = MemorySegment.ofArray(new byte[] {1, 2, 3, 4});
|
||||
assertThrows(IndexOutOfBoundsException.class, () ->
|
||||
MemorySegment.copy(src, -1, dst, 0, 4)
|
||||
);
|
||||
assertThrows(IndexOutOfBoundsException.class, () ->
|
||||
MemorySegment.copy(src, 0, dst, -1, 4)
|
||||
);
|
||||
assertThrows(IndexOutOfBoundsException.class, () ->
|
||||
MemorySegment.copy(src, 0, dst, 0, -1)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCopy7ArgWithNegativeValues() {
|
||||
MemorySegment src = MemorySegment.ofArray(new byte[] {1, 2, 3, 4});
|
||||
MemorySegment dst = MemorySegment.ofArray(new byte[] {1, 2, 3, 4});
|
||||
assertThrows(IndexOutOfBoundsException.class, () ->
|
||||
MemorySegment.copy(src, JAVA_BYTE, -1, dst, JAVA_BYTE, 0, 4)
|
||||
);
|
||||
assertThrows(IndexOutOfBoundsException.class, () ->
|
||||
MemorySegment.copy(src, JAVA_BYTE, 0, dst, JAVA_BYTE, -1, 4)
|
||||
);
|
||||
assertThrows(IndexOutOfBoundsException.class, () ->
|
||||
MemorySegment.copy(src, JAVA_BYTE, 0, dst, JAVA_BYTE, 0, -1)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCopyFromArrayWithNegativeValues() {
|
||||
MemorySegment src = MemorySegment.ofArray(new byte[] {1, 2, 3, 4});
|
||||
byte[] dst = new byte[] {1, 2, 3, 4};
|
||||
assertThrows(IndexOutOfBoundsException.class, () ->
|
||||
MemorySegment.copy(src, JAVA_BYTE, -1, dst, 0, 4)
|
||||
);
|
||||
assertThrows(IndexOutOfBoundsException.class, () ->
|
||||
MemorySegment.copy(src, JAVA_BYTE, 0, dst, -1, 4)
|
||||
);
|
||||
assertThrows(IndexOutOfBoundsException.class, () ->
|
||||
MemorySegment.copy(src, JAVA_BYTE, 0, dst, 0, -1)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCopyToArrayWithNegativeValues() {
|
||||
byte[] src = new byte[] {1, 2, 3, 4};
|
||||
MemorySegment dst = MemorySegment.ofArray(new byte[] {1, 2, 3, 4});
|
||||
assertThrows(IndexOutOfBoundsException.class, () ->
|
||||
MemorySegment.copy(src, -1, dst, JAVA_BYTE, 0, 4)
|
||||
);
|
||||
assertThrows(IndexOutOfBoundsException.class, () ->
|
||||
MemorySegment.copy(src, 0, dst, JAVA_BYTE, -1, 4)
|
||||
);
|
||||
assertThrows(IndexOutOfBoundsException.class, () ->
|
||||
MemorySegment.copy(src, 0, dst, JAVA_BYTE, 0, -1)
|
||||
);
|
||||
}
|
||||
|
||||
enum Type {
|
||||
// Byte
|
||||
BYTE(byte.class, JAVA_BYTE, i -> (byte)i),
|
||||
|
@ -43,6 +43,7 @@ import java.util.function.IntFunction;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static java.lang.foreign.ValueLayout.JAVA_INT;
|
||||
import static java.lang.foreign.ValueLayout.JAVA_LONG;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class TestSegments {
|
||||
@ -55,14 +56,13 @@ public class TestSegments {
|
||||
@Test
|
||||
public void testZeroLengthNativeSegment() {
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
Arena session = arena;
|
||||
var segment = session.allocate(0, 1);
|
||||
var segment = arena.allocate(0, 1);
|
||||
assertEquals(segment.byteSize(), 0);
|
||||
MemoryLayout seq = MemoryLayout.sequenceLayout(0, JAVA_INT);
|
||||
segment = session.allocate(seq);
|
||||
segment = arena.allocate(seq);
|
||||
assertEquals(segment.byteSize(), 0);
|
||||
assertEquals(segment.address() % seq.byteAlignment(), 0);
|
||||
segment = session.allocate(0, 4);
|
||||
segment = arena.allocate(0, 4);
|
||||
assertEquals(segment.byteSize(), 0);
|
||||
assertEquals(segment.address() % 4, 0);
|
||||
MemorySegment rawAddress = MemorySegment.ofAddress(segment.address());
|
||||
@ -133,8 +133,7 @@ public class TestSegments {
|
||||
@Test
|
||||
public void testEqualsOffHeap() {
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
Arena scope1 = arena;
|
||||
MemorySegment segment = scope1.allocate(100, 1);
|
||||
MemorySegment segment = arena.allocate(100, 1);
|
||||
assertEquals(segment, segment.asReadOnly());
|
||||
assertEquals(segment, segment.asSlice(0, 100));
|
||||
assertNotEquals(segment, segment.asSlice(10, 90));
|
||||
|
Loading…
x
Reference in New Issue
Block a user