-
Notifications
You must be signed in to change notification settings - Fork 6.2k
8321786: SegmentAllocator:allocateFrom(ValueLayout, MemorySegment,ValueLayout,long,long) spec mismatch in exception scenario #17079
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
Conversation
|
👋 Welcome back pminborg! A progress list of the required criteria for merging this PR into |
|
/csr |
|
@minborg has indicated that a compatibility and specification (CSR) request is needed for this pull request. @minborg please create a CSR request for issue JDK-8321786 with the correct fix version. This pull request cannot be integrated until the CSR request is approved. |
Webrevs
|
src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java
Outdated
Show resolved
Hide resolved
src/java.base/share/classes/jdk/internal/foreign/layout/AbstractLayout.java
Outdated
Show resolved
Hide resolved
| * @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 offset < 0} |
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.
All these should say index not offset
| * @throws IndexOutOfBoundsException if {@code elementCount * sourceElementLayout.byteSize()} overflows | ||
| * @throws IllegalArgumentException if {@code elementCount * sourceElementLayout.byteSize()} overflows | ||
| * @throws IndexOutOfBoundsException if {@code sourceOffset > source.byteSize() - (elementCount * sourceElementLayout.byteSize())} | ||
| * @throws IndexOutOfBoundsException if either {@code sourceOffset} or {@code elementCount} are {@code < 0} |
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.
I think that if elementCount < 0, we should throw IAE, not IOOBE. Note that we explain this method as:
MemorySegment dest = this.allocate(elementLayout, elementCount);
MemorySegment.copy(source, sourceElementLayout, sourceOffset, dest, elementLayout, 0, elementCount);
So, the set of exceptions thrown by these two methods should be preserved. This means that allocate(MemoryLayout, long) gets a first pass at checking - this means IAE for overflows and also for negative element count.
After that, the exceptions we can have are those specified in MemorySegment.copy.
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.
(as we did in other patches, I think it's important here to remain true to the semantics of the "desugared" code, because that will guarantee that developers can refactor their code w/o worrying about exceptions changing from under them)
| Objects.requireNonNull(source); | ||
| Objects.requireNonNull(sourceElementLayout); | ||
| Objects.requireNonNull(elementLayout); | ||
| Utils.checkNonNegativeIndex(elementCount, "elementCount"); |
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.
I think this check should be omitted (see comment above)
| MemorySegment dstSegment, ValueLayout dstElementLayout, long dstOffset, | ||
| long elementCount) { | ||
|
|
||
| Utils.checkNonNegativeIndex(srcOffset, "srcOffset"); |
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.
These new checks don't change the behavior, right? E.g. they will end up issuing an IIOBE, as before? So, why the changes? (note that these change might lead to double checks)
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.
It seems like this is about generating better exception (while leaving the exception type unchanged). If so, I support the change, as I agree that this patch does improve some of the messages.
| } | ||
| } | ||
|
|
||
| public static void checkNonNegativeArgument(long value, String name) { |
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.
Add @ForceInline to these
|
|
||
| // IllegalStateException if the {@linkplain MemorySegment#scope() scope} associated | ||
| // with {@code source} is not {@linkplain MemorySegment.Scope#isAlive() alive} | ||
| Arena closedArena = Arena.ofConfined(); |
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.
the scope/thread assertions are already checked in TestScopedOperations - I don't think we need this, but you might want to make sure a test case for this new allocator method is added there
| fail("Unable to create arena", e); | ||
| } | ||
|
|
||
| // ArithmeticException if {@code elementCount * sourceElementLayout.byteSize()} overflows |
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.
comment is wrong
| } | ||
|
|
||
| @Test(expectedExceptions = IndexOutOfBoundsException.class) | ||
| public void testNegativeGetOffset() { |
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.
We have a test specifically for instance segment accessors (TestMemoryAccessInstance) which covers all accessors - maybe better to move these new tests there?
| * @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 |
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.
if elementCount < 0 -> IAE, as per allocate(layout, size)
| * @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} | ||
| * @throws IllegalArgumentException if {@code elementCount < 0} |
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.
Please move this closer to the other IAE
| 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) |
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.
| MemorySegment.copy(src, JAVA_BYTE, -1, dst,0, 4) | |
| MemorySegment.copy(src, JAVA_BYTE, -1, dst, 0, 4) |
| MemorySegment.copy(src, JAVA_BYTE, -1, dst,0, 4) | ||
| ); | ||
| assertThrows(IndexOutOfBoundsException.class, () -> | ||
| MemorySegment.copy(src, JAVA_BYTE, 0, dst,-1, 4) |
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.
| MemorySegment.copy(src, JAVA_BYTE, 0, dst,-1, 4) | |
| MemorySegment.copy(src, JAVA_BYTE, 0, dst, -1, 4) |
| MemorySegment.copy(src, JAVA_BYTE, 0, dst,-1, 4) | ||
| ); | ||
| assertThrows(IndexOutOfBoundsException.class, () -> | ||
| MemorySegment.copy(src, JAVA_BYTE, 0, dst,0, -1) |
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.
| MemorySegment.copy(src, JAVA_BYTE, 0, dst,0, -1) | |
| MemorySegment.copy(src, JAVA_BYTE, 0, dst, 0, -1) |
|
@minborg This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be: You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been no new commits pushed to the ➡️ To integrate this PR with the above commit message to the |
|
/integrate |
|
Going to push as commit 7edd10e.
Your commit was automatically rebased without conflicts. |
|
/backport jdk22 |
|
@minborg the backport was successfully created on the branch backport-minborg-7edd10e5 in my personal fork of openjdk/jdk22. To create a pull request with this backport targeting openjdk/jdk22:master, just click the following link: The title of the pull request is automatically filled in correctly and below you find a suggestion for the pull request body:
If you need to update the source branch of the pull then run the following commands in a local clone of your personal fork of openjdk/jdk22: |
This PR proposes to change the specification for some methods that take
longoffsets so that they will throw anIllegalArgumentExceptionrather than anIndexOutOfBoundsExceptionfor negative values.The PR also proposes to fix a bug where the allocation size would overflow and the specified exception was not thrown.
Progress
Issues
Reviewers
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/17079/head:pull/17079$ git checkout pull/17079Update a local copy of the PR:
$ git checkout pull/17079$ git pull https://git.openjdk.org/jdk.git pull/17079/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 17079View PR using the GUI difftool:
$ git pr show -t 17079Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/17079.diff
Webrev
Link to Webrev Comment