8321387: SegmentAllocator:allocateFrom(AddressLayout, MemorySegment) does not throw stated UnsupportedOperationException

Reviewed-by: mcimadamore
This commit is contained in:
Per Minborg 2023-12-11 07:52:31 +00:00
parent ce108446ca
commit d13302f8b0
10 changed files with 99 additions and 36 deletions

View File

@ -631,6 +631,9 @@ public sealed interface MemoryLayout
* <li>The accessed memory segment must be * <li>The accessed memory segment must be
* {@link MemorySegment#isAccessibleBy(Thread) accessible} from the thread * {@link MemorySegment#isAccessibleBy(Thread) accessible} from the thread
* performing the access operation, or a {@link WrongThreadException} is thrown.</li> * performing the access operation, or a {@link WrongThreadException} is thrown.</li>
* <li>For write operations, the accessed memory segment must not be
* {@link MemorySegment#isReadOnly() read only}, or an
* {@link IllegalArgumentException} is thrown.</li>
* <li>The {@linkplain MemorySegment#scope() scope} associated with the accessed * <li>The {@linkplain MemorySegment#scope() scope} associated with the accessed
* segment must be {@linkplain MemorySegment.Scope#isAlive() alive}, or an * segment must be {@linkplain MemorySegment.Scope#isAlive() alive}, or an
* {@link IllegalStateException} is thrown.</li> * {@link IllegalStateException} is thrown.</li>

View File

@ -869,7 +869,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* this segment is not {@linkplain Scope#isAlive() alive} * this segment is not {@linkplain Scope#isAlive() alive}
* @throws WrongThreadException if this method is called from a thread {@code T}, * @throws WrongThreadException if this method is called from a thread {@code T},
* such that {@code isAccessibleBy(T) == false} * such that {@code isAccessibleBy(T) == false}
* @throws UnsupportedOperationException if this segment is * @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only} * {@linkplain #isReadOnly() read-only}
*/ */
MemorySegment fill(byte value); MemorySegment fill(byte value);
@ -894,7 +894,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* {@code src} is not {@linkplain Scope#isAlive() alive} * {@code src} is not {@linkplain Scope#isAlive() alive}
* @throws WrongThreadException if this method is called from a thread {@code T}, * @throws WrongThreadException if this method is called from a thread {@code T},
* such that {@code src.isAccessibleBy(T) == false} * such that {@code src.isAccessibleBy(T) == false}
* @throws UnsupportedOperationException if this segment is * @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only} * {@linkplain #isReadOnly() read-only}
* @return this segment * @return this segment
*/ */
@ -1269,6 +1269,8 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* this segment is not {@linkplain Scope#isAlive() alive} * this segment is not {@linkplain Scope#isAlive() alive}
* @throws WrongThreadException if this method is called from a thread {@code T}, * @throws WrongThreadException if this method is called from a thread {@code T},
* such that {@code isAccessibleBy(T) == false} * such that {@code isAccessibleBy(T) == false}
* @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only}
*/ */
void setString(long offset, String str); void setString(long offset, String str);
@ -1306,6 +1308,8 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* such that {@code isAccessibleBy(T) == false} * such that {@code isAccessibleBy(T) == false}
* @throws IllegalArgumentException if {@code charset} is not a * @throws IllegalArgumentException if {@code charset} is not a
* {@linkplain StandardCharsets standard charset} * {@linkplain StandardCharsets standard charset}
* @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only}
*/ */
void setString(long offset, String str, Charset charset); void setString(long offset, String str, Charset charset);
@ -1493,7 +1497,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* @throws IndexOutOfBoundsException if {@code dstOffset > dstSegment.byteSize() - bytes} * @throws IndexOutOfBoundsException if {@code dstOffset > dstSegment.byteSize() - bytes}
* @throws IndexOutOfBoundsException if either {@code srcOffset}, * @throws IndexOutOfBoundsException if either {@code srcOffset},
* {@code dstOffset} or {@code bytes} are {@code < 0} * {@code dstOffset} or {@code bytes} are {@code < 0}
* @throws UnsupportedOperationException if {@code dstSegment} is * @throws IllegalArgumentException if {@code dstSegment} is
* {@linkplain #isReadOnly() read-only} * {@linkplain #isReadOnly() read-only}
*/ */
@ForceInline @ForceInline
@ -1552,7 +1556,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* {@code dstSegment} is not {@linkplain Scope#isAlive() alive} * {@code dstSegment} is not {@linkplain Scope#isAlive() alive}
* @throws WrongThreadException if this method is called from a thread {@code T}, * @throws WrongThreadException if this method is called from a thread {@code T},
* such that {@code dstSegment.isAccessibleBy(T) == false} * such that {@code dstSegment.isAccessibleBy(T) == false}
* @throws UnsupportedOperationException if {@code dstSegment} is {@linkplain #isReadOnly() read-only} * @throws IllegalArgumentException if {@code dstSegment} is {@linkplain #isReadOnly() read-only}
* @throws IndexOutOfBoundsException if {@code elementCount * srcLayout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code elementCount * srcLayout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code elementCount * dtsLayout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code elementCount * dtsLayout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code srcOffset > srcSegment.byteSize() - (elementCount * srcLayout.byteSize())} * @throws IndexOutOfBoundsException if {@code srcOffset > srcSegment.byteSize() - (elementCount * srcLayout.byteSize())}
@ -1605,7 +1609,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a> * <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
* in the provided layout * in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
* @throws UnsupportedOperationException if this segment is * @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only} * {@linkplain #isReadOnly() read-only}
*/ */
void set(ValueLayout.OfByte layout, long offset, byte value); void set(ValueLayout.OfByte layout, long offset, byte value);
@ -1643,7 +1647,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a> * <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
* in the provided layout * in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
* @throws UnsupportedOperationException if this segment is * @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only} * {@linkplain #isReadOnly() read-only}
*/ */
void set(ValueLayout.OfBoolean layout, long offset, boolean value); void set(ValueLayout.OfBoolean layout, long offset, boolean value);
@ -1681,7 +1685,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a> * <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
* in the provided layout * in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
* @throws UnsupportedOperationException if this segment is * @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only} * {@linkplain #isReadOnly() read-only}
*/ */
void set(ValueLayout.OfChar layout, long offset, char value); void set(ValueLayout.OfChar layout, long offset, char value);
@ -1719,7 +1723,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a> * <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
* in the provided layout * in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
* @throws UnsupportedOperationException if this segment is * @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only} * {@linkplain #isReadOnly() read-only}
*/ */
void set(ValueLayout.OfShort layout, long offset, short value); void set(ValueLayout.OfShort layout, long offset, short value);
@ -1757,7 +1761,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a> * <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
* in the provided layout * in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
* @throws UnsupportedOperationException if this segment is * @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only} * {@linkplain #isReadOnly() read-only}
*/ */
void set(ValueLayout.OfInt layout, long offset, int value); void set(ValueLayout.OfInt layout, long offset, int value);
@ -1795,7 +1799,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a> * <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
* in the provided layout * in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
* @throws UnsupportedOperationException if this segment is * @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only} * {@linkplain #isReadOnly() read-only}
*/ */
void set(ValueLayout.OfFloat layout, long offset, float value); void set(ValueLayout.OfFloat layout, long offset, float value);
@ -1833,7 +1837,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a> * <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
* in the provided layout * in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
* @throws UnsupportedOperationException if this segment is * @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only} * {@linkplain #isReadOnly() read-only}
*/ */
void set(ValueLayout.OfLong layout, long offset, long value); void set(ValueLayout.OfLong layout, long offset, long value);
@ -1871,7 +1875,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a> * <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
* in the provided layout * in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
* @throws UnsupportedOperationException if this segment is * @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only} * {@linkplain #isReadOnly() read-only}
*/ */
void set(ValueLayout.OfDouble layout, long offset, double value); void set(ValueLayout.OfDouble layout, long offset, double value);
@ -1921,8 +1925,10 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
* @throws UnsupportedOperationException if this segment is * @throws UnsupportedOperationException if this segment is
* {@linkplain #isReadOnly() read-only} * {@linkplain #isReadOnly() read-only}
* @throws UnsupportedOperationException if {@code value} is not a * @throws IllegalArgumentException if {@code value} is not a
* {@linkplain #isNative() native} segment * {@linkplain #isNative() native} segment
* @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only}
*/ */
void set(AddressLayout layout, long offset, MemorySegment value); void set(AddressLayout layout, long offset, MemorySegment value);
@ -2055,7 +2061,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only} * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
*/ */
void setAtIndex(ValueLayout.OfByte layout, long index, byte value); void setAtIndex(ValueLayout.OfByte layout, long index, byte value);
@ -2078,7 +2084,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only} * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
*/ */
void setAtIndex(ValueLayout.OfBoolean layout, long index, boolean value); void setAtIndex(ValueLayout.OfBoolean layout, long index, boolean value);
@ -2101,7 +2107,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only} * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
*/ */
void setAtIndex(ValueLayout.OfShort layout, long index, short value); void setAtIndex(ValueLayout.OfShort layout, long index, short value);
@ -2146,7 +2152,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only} * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
*/ */
void setAtIndex(ValueLayout.OfInt layout, long index, int value); void setAtIndex(ValueLayout.OfInt layout, long index, int value);
@ -2191,7 +2197,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only} * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
*/ */
void setAtIndex(ValueLayout.OfFloat layout, long index, float value); void setAtIndex(ValueLayout.OfFloat layout, long index, float value);
@ -2236,7 +2242,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only} * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
*/ */
void setAtIndex(ValueLayout.OfLong layout, long index, long value); void setAtIndex(ValueLayout.OfLong layout, long index, long value);
@ -2281,7 +2287,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only} * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
*/ */
void setAtIndex(ValueLayout.OfDouble layout, long index, double value); void setAtIndex(ValueLayout.OfDouble layout, long index, double value);
@ -2336,7 +2342,9 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only} * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}
* @throws UnsupportedOperationException if {@code value} is not a {@linkplain #isNative() native} segment * @throws IllegalArgumentException if {@code value} is not a {@linkplain #isNative() native} segment
* @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only}
*/ */
void setAtIndex(AddressLayout layout, long index, MemorySegment value); void setAtIndex(AddressLayout layout, long index, MemorySegment value);
@ -2460,7 +2468,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a> * <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
* in the source element layout * in the source element layout
* @throws IllegalArgumentException if {@code dstLayout.byteAlignment() > dstLayout.byteSize()} * @throws IllegalArgumentException if {@code dstLayout.byteAlignment() > dstLayout.byteSize()}
* @throws UnsupportedOperationException if {@code dstSegment} is {@linkplain #isReadOnly() read-only} * @throws IllegalArgumentException if {@code dstSegment} is {@linkplain #isReadOnly() read-only}
* @throws IndexOutOfBoundsException if {@code elementCount * dstLayout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code elementCount * dstLayout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code dstOffset > dstSegment.byteSize() - (elementCount * dstLayout.byteSize())} * @throws IndexOutOfBoundsException if {@code dstOffset > dstSegment.byteSize() - (elementCount * dstLayout.byteSize())}
* @throws IndexOutOfBoundsException if {@code srcIndex > srcArray.length - elementCount} * @throws IndexOutOfBoundsException if {@code srcIndex > srcArray.length - elementCount}

View File

@ -350,7 +350,7 @@ public interface SegmentAllocator {
* *
* @param layout the layout of the block of memory to be allocated * @param layout the layout of the block of memory to be allocated
* @param value the value to be set in the newly allocated memory segment * @param value the value to be set in the newly allocated memory segment
* @throws UnsupportedOperationException if {@code value} is not * @throws IllegalArgumentException if {@code value} is not
* a {@linkplain MemorySegment#isNative() native} segment * a {@linkplain MemorySegment#isNative() native} segment
*/ */
default MemorySegment allocateFrom(AddressLayout layout, MemorySegment value) { default MemorySegment allocateFrom(AddressLayout layout, MemorySegment value) {
@ -670,9 +670,11 @@ public interface SegmentAllocator {
* *
* @param segment the segment from which the returned allocator should slice from * @param segment the segment from which the returned allocator should slice from
* @return a new slicing allocator * @return a new slicing allocator
* @throws IllegalArgumentException if the {@code segment} is
* {@linkplain MemorySegment#isReadOnly() read-only}
*/ */
static SegmentAllocator slicingAllocator(MemorySegment segment) { static SegmentAllocator slicingAllocator(MemorySegment segment) {
Objects.requireNonNull(segment); assertWritable(segment);
return new SlicingAllocator(segment); return new SlicingAllocator(segment);
} }
@ -700,9 +702,19 @@ public interface SegmentAllocator {
* @param segment the memory segment to be recycled by the returned allocator * @param segment the memory segment to be recycled by the returned allocator
* @return an allocator that recycles an existing segment upon each new * @return an allocator that recycles an existing segment upon each new
* allocation request * allocation request
* @throws IllegalArgumentException if the {@code segment} is
* {@linkplain MemorySegment#isReadOnly() read-only}
*/ */
static SegmentAllocator prefixAllocator(MemorySegment segment) { static SegmentAllocator prefixAllocator(MemorySegment segment) {
return (AbstractMemorySegmentImpl)Objects.requireNonNull(segment); assertWritable(segment);
return (AbstractMemorySegmentImpl)segment;
}
private static void assertWritable(MemorySegment segment) {
// Implicit null check
if (segment.isReadOnly()) {
throw new IllegalArgumentException("read-only segment");
}
} }
@ForceInline @ForceInline

View File

@ -361,7 +361,7 @@ public abstract sealed class AbstractMemorySegmentImpl
@ForceInline @ForceInline
public void checkAccess(long offset, long length, boolean readOnly) { public void checkAccess(long offset, long length, boolean readOnly) {
if (!readOnly && this.readOnly) { if (!readOnly && this.readOnly) {
throw new UnsupportedOperationException("Attempt to write a read-only segment"); throw new IllegalArgumentException("Attempt to write a read-only segment");
} }
checkBounds(offset, length); checkBounds(offset, length);
} }

View File

@ -26,12 +26,9 @@
* @run testng TestArrayCopy * @run testng TestArrayCopy
*/ */
import java.lang.foreign.MemoryLayout;
import java.lang.foreign.MemorySegment; import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout; import java.lang.foreign.ValueLayout;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.invoke.VarHandle; import java.lang.invoke.VarHandle;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.util.ArrayList; import java.util.ArrayList;
@ -240,7 +237,7 @@ public class TestArrayCopy {
try { try {
helper.copyFromArray(srcArr, 0, SEG_LENGTH_BYTES / bytesPerElement, dstSeg, 0, ByteOrder.nativeOrder()); helper.copyFromArray(srcArr, 0, SEG_LENGTH_BYTES / bytesPerElement, dstSeg, 0, ByteOrder.nativeOrder());
fail(); fail();
} catch (UnsupportedOperationException ex) { } catch (IllegalArgumentException ex) {
//ok //ok
} }
} }

View File

@ -87,7 +87,7 @@ public class TestMemoryAccess {
if (isRO) { if (isRO) {
throw new AssertionError(); //not ok, memory should be immutable throw new AssertionError(); //not ok, memory should be immutable
} }
} catch (UnsupportedOperationException ex) { } catch (IllegalArgumentException ex) {
if (!isRO) { if (!isRO) {
throw new AssertionError(); //we should not have failed! throw new AssertionError(); //we should not have failed!
} }
@ -121,7 +121,7 @@ public class TestMemoryAccess {
if (isRO) { if (isRO) {
throw new AssertionError(); //not ok, memory should be immutable throw new AssertionError(); //not ok, memory should be immutable
} }
} catch (UnsupportedOperationException ex) { } catch (IllegalArgumentException ex) {
if (!isRO) { if (!isRO) {
throw new AssertionError(); //we should not have failed! throw new AssertionError(); //we should not have failed!
} }
@ -185,7 +185,7 @@ public class TestMemoryAccess {
if (isRO) { if (isRO) {
throw new AssertionError(); //not ok, memory should be immutable throw new AssertionError(); //not ok, memory should be immutable
} }
} catch (UnsupportedOperationException ex) { } catch (IllegalArgumentException ex) {
if (!isRO) { if (!isRO) {
throw new AssertionError(); //we should not have failed! throw new AssertionError(); //we should not have failed!
} }

View File

@ -27,7 +27,6 @@
* @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_SEGMENT_FORCE_EXACT=true --enable-native-access=ALL-UNNAMED TestMemoryAccessInstance * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_SEGMENT_FORCE_EXACT=true --enable-native-access=ALL-UNNAMED TestMemoryAccessInstance
*/ */
import java.lang.foreign.MemoryLayout;
import java.lang.foreign.MemorySegment; import java.lang.foreign.MemorySegment;
import java.lang.foreign.Arena; import java.lang.foreign.Arena;
import java.lang.foreign.ValueLayout; import java.lang.foreign.ValueLayout;

View File

@ -100,6 +100,16 @@ public class TestSegmentAllocators {
static final int SIZE_256M = 1024 * 1024 * 256; static final int SIZE_256M = 1024 * 1024 * 256;
@Test(expectedExceptions = IllegalArgumentException.class)
public void testReadOnlySlicingAllocator() {
SegmentAllocator.slicingAllocator(MemorySegment.ofArray(new int[0]).asReadOnly());
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testReadOnlyPrefixAllocator() {
SegmentAllocator.prefixAllocator(MemorySegment.ofArray(new int[0]).asReadOnly());
}
@Test @Test
public void testBigAllocationInUnboundedSession() { public void testBigAllocationInUnboundedSession() {
try (Arena arena = Arena.ofConfined()) { try (Arena arena = Arena.ofConfined()) {
@ -160,6 +170,25 @@ public class TestSegmentAllocators {
} }
} }
@Test(expectedExceptions = IllegalArgumentException.class,
expectedExceptionsMessageRegExp = ".*Heap segment not allowed.*")
public void testArenaAllocateFromHeapSegment() {
try (Arena arena = Arena.ofConfined()) {
var heapSegment = MemorySegment.ofArray(new int[]{1});
arena.allocateFrom(ValueLayout.ADDRESS, heapSegment);
}
}
@Test(expectedExceptions = IllegalArgumentException.class,
expectedExceptionsMessageRegExp = ".*Heap segment not allowed.*")
public void testAllocatorAllocateFromHeapSegment() {
try (Arena arena = Arena.ofConfined()) {
SegmentAllocator allocator = SegmentAllocator.prefixAllocator(arena.allocate(16));
var heapSegment = MemorySegment.ofArray(new int[]{1});
allocator.allocateFrom(ValueLayout.ADDRESS, heapSegment);
}
}
@Test @Test
public void testArrayAllocateDelegation() { public void testArrayAllocateDelegation() {
AtomicInteger calls = new AtomicInteger(); AtomicInteger calls = new AtomicInteger();

View File

@ -76,7 +76,7 @@ public class TestSegmentCopy {
} }
} }
@Test(expectedExceptions = UnsupportedOperationException.class, dataProvider = "segmentKinds") @Test(expectedExceptions = IllegalArgumentException.class, dataProvider = "segmentKinds")
public void testReadOnlyCopy(SegmentKind kind1, SegmentKind kind2) { public void testReadOnlyCopy(SegmentKind kind1, SegmentKind kind2) {
MemorySegment s1 = kind1.makeSegment(TEST_BYTE_SIZE); MemorySegment s1 = kind1.makeSegment(TEST_BYTE_SIZE);
MemorySegment s2 = kind2.makeSegment(TEST_BYTE_SIZE); MemorySegment s2 = kind2.makeSegment(TEST_BYTE_SIZE);
@ -84,6 +84,15 @@ public class TestSegmentCopy {
MemorySegment.copy(s1, Type.BYTE.layout, 0, s2.asReadOnly(), Type.BYTE.layout, 0, 0); MemorySegment.copy(s1, Type.BYTE.layout, 0, s2.asReadOnly(), Type.BYTE.layout, 0, 0);
} }
@Test(expectedExceptions = IllegalArgumentException.class,
expectedExceptionsMessageRegExp = ".*Attempt to write a read-only segment.*")
public void badCopy6Arg() {
try (Arena scope = Arena.ofConfined()) {
MemorySegment dest = scope.allocate(ValueLayout.JAVA_INT).asReadOnly();
MemorySegment.copy(new int[1],0, dest, ValueLayout.JAVA_INT, 0 ,1); // should throw
}
}
@Test(expectedExceptions = IndexOutOfBoundsException.class, dataProvider = "types") @Test(expectedExceptions = IndexOutOfBoundsException.class, dataProvider = "types")
public void testBadOverflow(Type type) { public void testBadOverflow(Type type) {
if (type.layout.byteSize() > 1) { if (type.layout.byteSize() > 1) {

View File

@ -325,12 +325,18 @@ public class TestSegments {
assertEquals(segment.scope(), arena.scope()); assertEquals(segment.scope(), arena.scope());
} }
@Test(dataProvider = "segmentFactories", expectedExceptions = UnsupportedOperationException.class) @Test(dataProvider = "segmentFactories", expectedExceptions = IllegalArgumentException.class)
public void testFillIllegalAccessMode(Supplier<MemorySegment> segmentSupplier) { public void testFillIllegalAccessMode(Supplier<MemorySegment> segmentSupplier) {
MemorySegment segment = segmentSupplier.get(); MemorySegment segment = segmentSupplier.get();
segment.asReadOnly().fill((byte) 0xFF); segment.asReadOnly().fill((byte) 0xFF);
} }
@Test(dataProvider = "segmentFactories", expectedExceptions = IllegalArgumentException.class)
public void testFromStringIllegalAccessMode(Supplier<MemorySegment> segmentSupplier) {
MemorySegment segment = segmentSupplier.get();
segment.asReadOnly().setString(0, "a");
}
@Test(dataProvider = "segmentFactories") @Test(dataProvider = "segmentFactories")
public void testFillThread(Supplier<MemorySegment> segmentSupplier) throws Exception { public void testFillThread(Supplier<MemorySegment> segmentSupplier) throws Exception {
MemorySegment segment = segmentSupplier.get(); MemorySegment segment = segmentSupplier.get();