-
Notifications
You must be signed in to change notification settings - Fork 6.2k
8358751: C2: Recursive inlining check for compiled lambda forms is broken #26891
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?
Conversation
👋 Welcome back vlivanov! A progress list of the required criteria for merging this PR into |
@iwanowww 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 100 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 |
@iwanowww |
Can you explain why a MH invoker needs to be handled as a special case? Also, it seems like we should be saving the receiver info as a snapshot of arg0/local0 in the callee JVMState, rather than changing it in the caller JVMState for every call site. Don't we already save the receiver somewhere, so that late inlining works correctly? |
MH invokers don't have a receiver. They are linked to indy/MH.invoke/MH.invokeExact call sites and there's no dispatching happening when they are invoked (compared to other cases when MH.invokeBasic is used).
That's what the patch does. There's a number of places where
For late inlining the situation is different: corresponding call site keeps the receiver as an argument. It's not the case with ancestor frames in deep inlined call chains. There are no guarantees that receivers from ancestor frames are still alive when a call site is being considered for inlining during parsing. (Effectively dead locals are aggressively pruned from JVMState during parsing.) |
if (method() == callee_method) { | ||
inline_level++; | ||
} | ||
const bool is_method_handle_invoker = is_compiled_lambda_form && !jvms->method()->is_compiled_lambda_form(); |
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.
Ignoring the bug you're fixing, is that logic expected to compute the same inline_level
that the current logic computes? You changed it a bit (iterate from the current frame rather than the caller, the extra test for is_method_handle_invoker
and the extra test for lform_caller_recv == nullptr
in the loop that I'm not sure what the answer to that question is.
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 don't see a compelling reason to treat immediate caller specially here. Since current logic is broken, I decided to make the unification along with the fix. I can separate it into an RFE, if you have any concerns.
Would it be possible to add a test? |
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.
Looks good to me.
What about a regression test? |
Recursive inlining checks are relaxed for compiled LambdaForms. Since LambdaForms are heavily reused, the check is performed on
MethodHandle
receivers instead.Unfortunately, the current implementation is broken. JVMState doesn't guarantee presence of receivers for caller frames.
An attempt to fetch pruned receiver reports unrelated info, but, in the worst case, it ends up as an out-of-bounds access into node's input array and crashes the JVM.
Proposed fix captures receiver information as part of inlining and preserves it on
JVMState
for every compiled LambdaForm frame, so it can be reliably recovered during subsequent inlining attempts.Testing: hs-tier1 - hs-tier8
(Special thanks to @mroth23 who prepared a reproducer of the bug.)
Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/26891/head:pull/26891
$ git checkout pull/26891
Update a local copy of the PR:
$ git checkout pull/26891
$ git pull https://git.openjdk.org/jdk.git pull/26891/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 26891
View PR using the GUI difftool:
$ git pr show -t 26891
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/26891.diff
Using Webrev
Link to Webrev Comment