-
Notifications
You must be signed in to change notification settings - Fork 6.2k
8346657: Improve out of bounds exception messages for MemorySegments #28124
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 6 commits
a106ac8
adc7a06
49c35fa
53f68ba
fb7b28c
b96a015
9a2cc13
df86a85
1095cf6
57b9480
6a89618
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -68,7 +68,7 @@ | |
| * {@link MappedMemorySegmentImpl}. | ||
| */ | ||
| public abstract sealed class AbstractMemorySegmentImpl | ||
| implements MemorySegment, SegmentAllocator, BiFunction<String, List<Number>, RuntimeException> | ||
| implements MemorySegment, SegmentAllocator | ||
| permits HeapMemorySegmentImpl, NativeMemorySegmentImpl { | ||
|
|
||
| static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); | ||
|
|
@@ -100,19 +100,19 @@ public boolean isReadOnly() { | |
|
|
||
| @Override | ||
| public AbstractMemorySegmentImpl asSlice(long offset, long newSize) { | ||
| checkBounds(offset, newSize); | ||
| checkSliceBounds(offset, newSize); | ||
| return asSliceNoCheck(offset, newSize); | ||
| } | ||
|
|
||
| @Override | ||
| public AbstractMemorySegmentImpl asSlice(long offset) { | ||
| checkBounds(offset, 0); | ||
| checkSliceBounds(offset, 0); | ||
| return asSliceNoCheck(offset, length - offset); | ||
| } | ||
|
|
||
| @Override | ||
| public MemorySegment asSlice(long offset, long newSize, long byteAlignment) { | ||
| checkBounds(offset, newSize); | ||
| checkSliceBounds(offset, newSize); | ||
| Utils.checkAlign(byteAlignment); | ||
|
|
||
| if (!isAlignedForElement(offset, byteAlignment)) { | ||
|
|
@@ -354,7 +354,7 @@ public void checkReadOnly(boolean readOnly) { | |
| @ForceInline | ||
| public void checkAccess(long offset, long length, boolean readOnly) { | ||
| checkReadOnly(readOnly); | ||
| checkBounds(offset, length); | ||
| checkAccessBounds(offset, length); | ||
| } | ||
|
|
||
| @ForceInline | ||
|
|
@@ -398,20 +398,13 @@ private int checkArraySize(String typeName, int elemSize) { | |
| } | ||
|
|
||
| @ForceInline | ||
| void checkBounds(long offset, long length) { | ||
| if (length > 0) { | ||
| Preconditions.checkIndex(offset, this.length - length + 1, this); | ||
| } else if (length < 0 || offset < 0 || | ||
| offset > this.length - length) { | ||
| throw outOfBoundException(offset, length); | ||
| } | ||
| void checkSliceBounds(long offset, long length) { | ||
| Preconditions.checkFromIndexSize(offset, length, this.length, this::sliceOutOfBoundException); | ||
| } | ||
|
|
||
| @Override | ||
| public RuntimeException apply(String s, List<Number> numbers) { | ||
| long offset = numbers.get(0).longValue(); | ||
| long length = byteSize() - numbers.get(1).longValue() + 1; | ||
| return outOfBoundException(offset, length); | ||
| @ForceInline | ||
| void checkAccessBounds(long offset, long length) { | ||
| Preconditions.checkFromIndexSize(offset, length, this.length, this::accessOutOfBoundException); | ||
| } | ||
|
|
||
| @Override | ||
|
|
@@ -429,9 +422,28 @@ public final MemorySessionImpl sessionImpl() { | |
| return scope; | ||
| } | ||
|
|
||
| private IndexOutOfBoundsException outOfBoundException(long offset, long length) { | ||
| return new IndexOutOfBoundsException(String.format("Out of bound access on segment %s; new offset = %d; new length = %d", | ||
| this, offset, length)); | ||
| private IndexOutOfBoundsException sliceOutOfBoundException(String s, List<Number> numbers) { | ||
| return outOfBoundException(BoundPolicy.SLICE, numbers); | ||
| } | ||
|
|
||
| private IndexOutOfBoundsException accessOutOfBoundException(String s, List<Number> numbers) { | ||
| return outOfBoundException(BoundPolicy.ACCESS, numbers); | ||
| } | ||
|
|
||
| private IndexOutOfBoundsException outOfBoundException(BoundPolicy policy, List<Number> numbers) { | ||
| long offset = numbers.get(0).longValue(); | ||
| long length = numbers.get(1).longValue(); | ||
| long totalLength = numbers.get(2).longValue(); | ||
|
|
||
| String msg = switch (policy) { | ||
| case BoundPolicy.SLICE -> "attempting to get slice of length"; | ||
| case BoundPolicy.ACCESS -> "attempting to access an element of length"; | ||
| }; | ||
|
|
||
| return new IndexOutOfBoundsException(String.format("Out of bound access on segment %s; " + | ||
|
||
| "%s %d at offset %d " + | ||
| "which is outside the valid range 0 <= offset+length < byteSize (=%d)", | ||
| this, msg, length, offset, totalLength)); | ||
| } | ||
|
|
||
| static class SegmentSplitter implements Spliterator<MemorySegment> { | ||
|
|
@@ -508,6 +520,10 @@ public int characteristics() { | |
| } | ||
| } | ||
|
|
||
| private enum BoundPolicy { | ||
| SLICE, ACCESS | ||
| } | ||
|
|
||
| // Object methods | ||
|
|
||
| @Override | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this performance-wise neutral? This is on a hot path and captures a lambda every time, need to verify compiler can eliminate this, which I doubt.