8380434: [lworld]: C2: Wrong execution caused by treating a non-buffered InlineType as an oop in PredictedCallGenerator#2256
Open
benoitmaillard wants to merge 6 commits intoopenjdk:lworldfrom
Open
Conversation
|
👋 Welcome back bmaillard! A progress list of the required criteria for merging this PR into |
|
❗ This change is not yet ready to be integrated. |
ca14e32 to
0d525da
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR prevents a wrong execution / VM segfault resulting from a wrong use
of
InlineTypeNode::make_from_oopwhen generating a slow and fast path withPredictedCallGenerator.This was initially spotted as a failure with
compiler/valhalla/inlinetypes/TestUnloadedReturnTypes.java.Bug Summary
We have an OSR compilation, which matters because
ais initialized outside of the loop and thus its type won't be exact.We then try to predict the virtual call and generate both fast (inlined) and slow (dynamic call)
paths.
Another important detail here is that the result from the dynamic call is not scalarized, as it seems there are not enough registers available in this case (cf
TypeFunc::returns_inline_type_as_fields).This means that we end up with a
Phithat has on one side the result of the inlined path,which is a non-buffered
InlineTypeNode, and on the other aProjfor the oop resulting from the call.(the method and type names match the initial reproducer here)

This is wrong already, because the assumption here is that the both branches contain an oop.
In
Parse::do_call, we end up looking at the return node produced by the call generatorand determine that we should build an
InlineTypeNodefrom the oop:valhalla/src/hotspot/share/opto/doCall.cpp
Lines 812 to 820 in 1257fbd
The graph is very clearly broken at this stage, and this leads to wrong executions or even a segfault
as soon as we take the fast path (which always happens here) because the oop input for the
InlineTypeNodeis effectively null as we are trying to get rid of the allocation.Fix
In
Parse::do_call, the assumption when dealing with an inline type as return value is that we either:InlineTypeNodedirectly (inlining case) and we don't have anything to doInlineTypeNode::make_from_oopHere we have something in the middle, and clearly we have to be more careful. I think there are
several options:
The first option would be to slightly modify the existing behavior in
Parse::do_callanddetect the broken phi and call
InlineTypeNode::make_from_oopon the phi inputs that are oops.This seems a bit hacky, as we allow the broken phi to exist for a while, and it's hard to know
if we could be missing some cases.
The second option would be to fill in the blanks and add an
InlineTypeNode::make_from_oopcallin the call generator, either in
VirtualCallGeneratororPredictedCallGenerator. I think thisis also hacky, we would need to call
InlineTypeNode::make_from_oopat several places.The third option is to have the
make_from_oopcall closer to the creation of the return node. This ensures that we do not miss any caseand that we only have to do it in one place. I think
GraphKit::set_results_for_java_callfitsthese requirements, and there is already some inline type related stuff going on there. Unfortunately, I noticed after some preliminary testing that we still have to keep the the
make_from_oopcall indo_call, as there are cases where we rely on it to create anInlineTypeNodefor the inlined path.I have also added a check to ensure we never merge a non-buffered
InlineTypewith an oop inPredictedCallGenerator.Testing
Thank you for reviewing!
Progress
Issue
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/valhalla.git pull/2256/head:pull/2256$ git checkout pull/2256Update a local copy of the PR:
$ git checkout pull/2256$ git pull https://git.openjdk.org/valhalla.git pull/2256/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 2256View PR using the GUI difftool:
$ git pr show -t 2256Using diff file
Download this PR as a diff file:
https://git.openjdk.org/valhalla/pull/2256.diff