-
Notifications
You must be signed in to change notification settings - Fork 6.1k
8315954: getArgumentValues002.java fails on Graal #15705
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 dnsimon! A progress list of the required criteria for merging this PR into |
| void InterpreterOopMap::initialize() { | ||
| _method = nullptr; | ||
| _mask_size = USHRT_MAX; // This value should cause a failure quickly | ||
| _mask_size = INT_MAX; // This value should cause a failure quickly |
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.
Unless I'm mistaken, USHRT_MAX is a legal (but unlikely) value (i.e. max_locals in a class file can be 65635) so I changed this to use INT_MAX instead.
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's actually not legal since _mask_size is always a multiple of bits_per_entry which is 2 so any odd value would work. I would be leery of touching this unless you really need to.
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.
Ok, I'll revert it to USHRT_MAX.
Webrevs
|
| } | ||
|
|
||
| @Override | ||
| public long getLiveObjectLocalsAt(int bci, BitSet bigOopMap) { |
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.
This seems overly complicated to me. Why isn't it simply:
public BitSet getLiveObjectLocalsAt(int bci) {
int locals = getMaxLocals();
int nwords = ((locals - 1) / 64) + 1;
long liveness[] = new long[nwords];
compilerToVM().getLiveObjectLocalsAt(this, bci, liveness);
return new BitSet(liveness);
}
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.
In the common case we can avoid the overhead of allocating a long array and initializing each of it elements with a JNI upcall.
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's premature optimization. This is called once per OSR compile and the call itself is doing a dataflow over the bytecodes which seems more expensive then a couple JNI calls. The array can be filled in using copy_bytes_to from HotSpot, which is a pair of JNI calls. You already have 2 JNI calls because of the unsafe allocation. I can maybe accept that returning a long from the JVM to avoid an allocation for the < 64 case isn't a terrible idea but I can't see any universe where we care about that.
This method should be returning a BitSet not a long. Having the caller do that fixup is super ugly.
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.
Ok, I'm convinced.
| * @throws UnsupportedOperationException if local variable liveness is not provided | ||
| * by the current JVMCI runtime | ||
| */ | ||
| default long getLiveObjectLocalsAt(int bci, BitSet bigOopMap) { |
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 should be in HotSpotResolvedJavaMethod since there's no apparent need for it in SVM.
… to HotSpotResolvedJavaMethod
| tmp->fill(method, bci); | ||
| entry->resource_copy(tmp); | ||
| if (tmp->has_valid_mask()) { | ||
| entry->resource_copy(tmp); |
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 tmp is invalid (e.g. oop map was requested for invalid BCI), then resource_copy crashes the VM in strange ways since it blindly trusts the mask size to be valid.
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.
This is not the only place where resource_copy() is called, could you add an assert in resource_copy() itself to check that it is never called with an invalid bci/mask_size.
Thank you.
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.
Ok, I've added that assertion.
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.
This looks good now.
| /** | ||
| * Computes which local variables contain live object values | ||
| * at the instruction denoted by {@code bci}. This is the "oop map" used | ||
| * by the garbage collector. |
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.
by the garbage collector for interpreter frames.
| int nwords = ((nlocals - 1) / 64) + 1; | ||
| JVMCIPrimitiveArray oop_map = JVMCIENV->wrap(oop_map_handle); | ||
| int oop_map_len = JVMCIENV->get_length(oop_map); | ||
| if (nwords > oop_map_len) { |
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.
Should we sanity check against mask.number_of_entries()? One wrinkle here is that compute_one_oop_map also computes information about the stack so the mask it computes can be larger than just max_locals. For the purposes of OSR this doesn't matter as none of the JITs support OSR with a non-empty stack, so we would never call it for a bci with a non-empty stack. So should we disallow calling it with a non-empty stack or just properly handle it by passing in an array long enough to contain max_locals + max_stack?
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 only look up the mask for locals and so ignore stack indexes in the mask altogether. I'm assuming therefore that mask.is_oop(i) can never hit any problems.
Note that this API should be safe when called for any valid BCI, not just those for an OSR entry point. Even if called for a BCI with a non-empty stack, the current implementation simply ignores that part of the mask.
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.
Yes that's implied by the name of the method. It would make me happy if there was a comment pointing out that we're explicitly ignoring whether the stack is non-empty and contains oops.
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.
Instead, I generalized getLiveObjectLocalsAt to getOopMapAt since the VM computation is for both locals and operand stack anyway.
When called for OSR entry points, the result will be the same since (currently) HotSpot requires the stack to be empty.
|
@dougxc 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 137 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. ➡️ To integrate this PR with the above commit message to the |
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.
New version looks good.
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.
Runtime changes look good to me. Thank you for the additional assert.
|
Thanks for the reviews. /integrate |
|
Going to push as commit 542b300.
Your commit was automatically rebased without conflicts. |
This PR adds
HotSpotResolvedJavaMethod.getOopMapAtto get the oop map for a method at a given BCI. This is required to do correct clearing of oops at OSR entry points.As part of this addition, I needed to be able to detect requests for oop maps at invalid BCIs. For this, I added
InterpreterOopMap::has_valid_mask(). When an oop map computation is requested for an invalid BCI, this method returns false.Progress
Issue
Reviewers
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/15705/head:pull/15705$ git checkout pull/15705Update a local copy of the PR:
$ git checkout pull/15705$ git pull https://git.openjdk.org/jdk.git pull/15705/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 15705View PR using the GUI difftool:
$ git pr show -t 15705Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/15705.diff
Webrev
Link to Webrev Comment