Skip to content

Commit d13302f

Browse files
committedDec 11, 2023
8321387: SegmentAllocator:allocateFrom(AddressLayout, MemorySegment) does not throw stated UnsupportedOperationException
Reviewed-by: mcimadamore
1 parent ce10844 commit d13302f

File tree

10 files changed

+99
-36
lines changed

10 files changed

+99
-36
lines changed
 

‎src/java.base/share/classes/java/lang/foreign/MemoryLayout.java

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

‎src/java.base/share/classes/java/lang/foreign/MemorySegment.java

+30-22
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,7 @@ MemorySegment reinterpret(long newSize,
869869
* this segment is not {@linkplain Scope#isAlive() alive}
870870
* @throws WrongThreadException if this method is called from a thread {@code T},
871871
* such that {@code isAccessibleBy(T) == false}
872-
* @throws UnsupportedOperationException if this segment is
872+
* @throws IllegalArgumentException if this segment is
873873
* {@linkplain #isReadOnly() read-only}
874874
*/
875875
MemorySegment fill(byte value);
@@ -894,7 +894,7 @@ MemorySegment reinterpret(long newSize,
894894
* {@code src} is not {@linkplain Scope#isAlive() alive}
895895
* @throws WrongThreadException if this method is called from a thread {@code T},
896896
* such that {@code src.isAccessibleBy(T) == false}
897-
* @throws UnsupportedOperationException if this segment is
897+
* @throws IllegalArgumentException if this segment is
898898
* {@linkplain #isReadOnly() read-only}
899899
* @return this segment
900900
*/
@@ -1269,6 +1269,8 @@ MemorySegment reinterpret(long newSize,
12691269
* this segment is not {@linkplain Scope#isAlive() alive}
12701270
* @throws WrongThreadException if this method is called from a thread {@code T},
12711271
* such that {@code isAccessibleBy(T) == false}
1272+
* @throws IllegalArgumentException if this segment is
1273+
* {@linkplain #isReadOnly() read-only}
12721274
*/
12731275
void setString(long offset, String str);
12741276

@@ -1306,6 +1308,8 @@ MemorySegment reinterpret(long newSize,
13061308
* such that {@code isAccessibleBy(T) == false}
13071309
* @throws IllegalArgumentException if {@code charset} is not a
13081310
* {@linkplain StandardCharsets standard charset}
1311+
* @throws IllegalArgumentException if this segment is
1312+
* {@linkplain #isReadOnly() read-only}
13091313
*/
13101314
void setString(long offset, String str, Charset charset);
13111315

@@ -1493,7 +1497,7 @@ static MemorySegment ofAddress(long address) {
14931497
* @throws IndexOutOfBoundsException if {@code dstOffset > dstSegment.byteSize() - bytes}
14941498
* @throws IndexOutOfBoundsException if either {@code srcOffset},
14951499
* {@code dstOffset} or {@code bytes} are {@code < 0}
1496-
* @throws UnsupportedOperationException if {@code dstSegment} is
1500+
* @throws IllegalArgumentException if {@code dstSegment} is
14971501
* {@linkplain #isReadOnly() read-only}
14981502
*/
14991503
@ForceInline
@@ -1552,7 +1556,7 @@ static void copy(MemorySegment srcSegment, long srcOffset,
15521556
* {@code dstSegment} is not {@linkplain Scope#isAlive() alive}
15531557
* @throws WrongThreadException if this method is called from a thread {@code T},
15541558
* such that {@code dstSegment.isAccessibleBy(T) == false}
1555-
* @throws UnsupportedOperationException if {@code dstSegment} is {@linkplain #isReadOnly() read-only}
1559+
* @throws IllegalArgumentException if {@code dstSegment} is {@linkplain #isReadOnly() read-only}
15561560
* @throws IndexOutOfBoundsException if {@code elementCount * srcLayout.byteSize()} overflows
15571561
* @throws IndexOutOfBoundsException if {@code elementCount * dtsLayout.byteSize()} overflows
15581562
* @throws IndexOutOfBoundsException if {@code srcOffset > srcSegment.byteSize() - (elementCount * srcLayout.byteSize())}
@@ -1605,7 +1609,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
16051609
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
16061610
* in the provided layout
16071611
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
1608-
* @throws UnsupportedOperationException if this segment is
1612+
* @throws IllegalArgumentException if this segment is
16091613
* {@linkplain #isReadOnly() read-only}
16101614
*/
16111615
void set(ValueLayout.OfByte layout, long offset, byte value);
@@ -1643,7 +1647,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
16431647
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
16441648
* in the provided layout
16451649
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
1646-
* @throws UnsupportedOperationException if this segment is
1650+
* @throws IllegalArgumentException if this segment is
16471651
* {@linkplain #isReadOnly() read-only}
16481652
*/
16491653
void set(ValueLayout.OfBoolean layout, long offset, boolean value);
@@ -1681,7 +1685,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
16811685
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
16821686
* in the provided layout
16831687
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
1684-
* @throws UnsupportedOperationException if this segment is
1688+
* @throws IllegalArgumentException if this segment is
16851689
* {@linkplain #isReadOnly() read-only}
16861690
*/
16871691
void set(ValueLayout.OfChar layout, long offset, char value);
@@ -1719,7 +1723,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
17191723
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
17201724
* in the provided layout
17211725
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
1722-
* @throws UnsupportedOperationException if this segment is
1726+
* @throws IllegalArgumentException if this segment is
17231727
* {@linkplain #isReadOnly() read-only}
17241728
*/
17251729
void set(ValueLayout.OfShort layout, long offset, short value);
@@ -1757,7 +1761,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
17571761
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
17581762
* in the provided layout
17591763
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
1760-
* @throws UnsupportedOperationException if this segment is
1764+
* @throws IllegalArgumentException if this segment is
17611765
* {@linkplain #isReadOnly() read-only}
17621766
*/
17631767
void set(ValueLayout.OfInt layout, long offset, int value);
@@ -1795,7 +1799,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
17951799
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
17961800
* in the provided layout
17971801
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
1798-
* @throws UnsupportedOperationException if this segment is
1802+
* @throws IllegalArgumentException if this segment is
17991803
* {@linkplain #isReadOnly() read-only}
18001804
*/
18011805
void set(ValueLayout.OfFloat layout, long offset, float value);
@@ -1833,7 +1837,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
18331837
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
18341838
* in the provided layout
18351839
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
1836-
* @throws UnsupportedOperationException if this segment is
1840+
* @throws IllegalArgumentException if this segment is
18371841
* {@linkplain #isReadOnly() read-only}
18381842
*/
18391843
void set(ValueLayout.OfLong layout, long offset, long value);
@@ -1871,7 +1875,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
18711875
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
18721876
* in the provided layout
18731877
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
1874-
* @throws UnsupportedOperationException if this segment is
1878+
* @throws IllegalArgumentException if this segment is
18751879
* {@linkplain #isReadOnly() read-only}
18761880
*/
18771881
void set(ValueLayout.OfDouble layout, long offset, double value);
@@ -1921,8 +1925,10 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
19211925
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
19221926
* @throws UnsupportedOperationException if this segment is
19231927
* {@linkplain #isReadOnly() read-only}
1924-
* @throws UnsupportedOperationException if {@code value} is not a
1928+
* @throws IllegalArgumentException if {@code value} is not a
19251929
* {@linkplain #isNative() native} segment
1930+
* @throws IllegalArgumentException if this segment is
1931+
* {@linkplain #isReadOnly() read-only}
19261932
*/
19271933
void set(AddressLayout layout, long offset, MemorySegment value);
19281934

@@ -2055,7 +2061,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
20552061
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
20562062
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
20572063
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
2058-
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}
2064+
* @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
20592065
*/
20602066
void setAtIndex(ValueLayout.OfByte layout, long index, byte value);
20612067

@@ -2078,7 +2084,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
20782084
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
20792085
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
20802086
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
2081-
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}
2087+
* @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
20822088
*/
20832089
void setAtIndex(ValueLayout.OfBoolean layout, long index, boolean value);
20842090

@@ -2101,7 +2107,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
21012107
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
21022108
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
21032109
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
2104-
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}
2110+
* @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
21052111
*/
21062112
void setAtIndex(ValueLayout.OfShort layout, long index, short value);
21072113

@@ -2146,7 +2152,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
21462152
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
21472153
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
21482154
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
2149-
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}
2155+
* @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
21502156
*/
21512157
void setAtIndex(ValueLayout.OfInt layout, long index, int value);
21522158

@@ -2191,7 +2197,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
21912197
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
21922198
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
21932199
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
2194-
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}
2200+
* @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
21952201
*/
21962202
void setAtIndex(ValueLayout.OfFloat layout, long index, float value);
21972203

@@ -2236,7 +2242,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
22362242
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
22372243
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
22382244
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
2239-
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}
2245+
* @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
22402246
*/
22412247
void setAtIndex(ValueLayout.OfLong layout, long index, long value);
22422248

@@ -2281,7 +2287,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
22812287
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
22822288
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
22832289
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
2284-
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}
2290+
* @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
22852291
*/
22862292
void setAtIndex(ValueLayout.OfDouble layout, long index, double value);
22872293

@@ -2336,7 +2342,9 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
23362342
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
23372343
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
23382344
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}
2339-
* @throws UnsupportedOperationException if {@code value} is not a {@linkplain #isNative() native} segment
2345+
* @throws IllegalArgumentException if {@code value} is not a {@linkplain #isNative() native} segment
2346+
* @throws IllegalArgumentException if this segment is
2347+
* {@linkplain #isReadOnly() read-only}
23402348
*/
23412349
void setAtIndex(AddressLayout layout, long index, MemorySegment value);
23422350

@@ -2460,7 +2468,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcLayout, long srcOffset
24602468
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
24612469
* in the source element layout
24622470
* @throws IllegalArgumentException if {@code dstLayout.byteAlignment() > dstLayout.byteSize()}
2463-
* @throws UnsupportedOperationException if {@code dstSegment} is {@linkplain #isReadOnly() read-only}
2471+
* @throws IllegalArgumentException if {@code dstSegment} is {@linkplain #isReadOnly() read-only}
24642472
* @throws IndexOutOfBoundsException if {@code elementCount * dstLayout.byteSize()} overflows
24652473
* @throws IndexOutOfBoundsException if {@code dstOffset > dstSegment.byteSize() - (elementCount * dstLayout.byteSize())}
24662474
* @throws IndexOutOfBoundsException if {@code srcIndex > srcArray.length - elementCount}

‎src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java

+15-3
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ default MemorySegment allocateFrom(ValueLayout.OfDouble layout, double value) {
350350
*
351351
* @param layout the layout of the block of memory to be allocated
352352
* @param value the value to be set in the newly allocated memory segment
353-
* @throws UnsupportedOperationException if {@code value} is not
353+
* @throws IllegalArgumentException if {@code value} is not
354354
* a {@linkplain MemorySegment#isNative() native} segment
355355
*/
356356
default MemorySegment allocateFrom(AddressLayout layout, MemorySegment value) {
@@ -670,9 +670,11 @@ default MemorySegment allocate(long byteSize) {
670670
*
671671
* @param segment the segment from which the returned allocator should slice from
672672
* @return a new slicing allocator
673+
* @throws IllegalArgumentException if the {@code segment} is
674+
* {@linkplain MemorySegment#isReadOnly() read-only}
673675
*/
674676
static SegmentAllocator slicingAllocator(MemorySegment segment) {
675-
Objects.requireNonNull(segment);
677+
assertWritable(segment);
676678
return new SlicingAllocator(segment);
677679
}
678680

@@ -700,9 +702,19 @@ static SegmentAllocator slicingAllocator(MemorySegment segment) {
700702
* @param segment the memory segment to be recycled by the returned allocator
701703
* @return an allocator that recycles an existing segment upon each new
702704
* allocation request
705+
* @throws IllegalArgumentException if the {@code segment} is
706+
* {@linkplain MemorySegment#isReadOnly() read-only}
703707
*/
704708
static SegmentAllocator prefixAllocator(MemorySegment segment) {
705-
return (AbstractMemorySegmentImpl)Objects.requireNonNull(segment);
709+
assertWritable(segment);
710+
return (AbstractMemorySegmentImpl)segment;
711+
}
712+
713+
private static void assertWritable(MemorySegment segment) {
714+
// Implicit null check
715+
if (segment.isReadOnly()) {
716+
throw new IllegalArgumentException("read-only segment");
717+
}
706718
}
707719

708720
@ForceInline

‎src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ private <Z> Z toArray(Class<Z> arrayClass, ValueLayout elemLayout, IntFunction<Z
361361
@ForceInline
362362
public void checkAccess(long offset, long length, boolean readOnly) {
363363
if (!readOnly && this.readOnly) {
364-
throw new UnsupportedOperationException("Attempt to write a read-only segment");
364+
throw new IllegalArgumentException("Attempt to write a read-only segment");
365365
}
366366
checkBounds(offset, length);
367367
}

‎test/jdk/java/foreign/TestArrayCopy.java

+1-4
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,9 @@
2626
* @run testng TestArrayCopy
2727
*/
2828

29-
import java.lang.foreign.MemoryLayout;
3029
import java.lang.foreign.MemorySegment;
3130
import java.lang.foreign.ValueLayout;
32-
import java.lang.invoke.MethodHandle;
3331
import java.lang.invoke.MethodHandles;
34-
import java.lang.invoke.MethodType;
3532
import java.lang.invoke.VarHandle;
3633
import java.nio.ByteOrder;
3734
import java.util.ArrayList;
@@ -240,7 +237,7 @@ public void testCopyReadOnlyDest(CopyMode mode, CopyHelper<Object, ValueLayout>
240237
try {
241238
helper.copyFromArray(srcArr, 0, SEG_LENGTH_BYTES / bytesPerElement, dstSeg, 0, ByteOrder.nativeOrder());
242239
fail();
243-
} catch (UnsupportedOperationException ex) {
240+
} catch (IllegalArgumentException ex) {
244241
//ok
245242
}
246243
}

0 commit comments

Comments
 (0)
Please sign in to comment.