RFR: 8327963: [Umbrella] Incorrect result of C2 compiled code since JDK-8237581
Roland Westrelin
roland at openjdk.org
Thu Apr 10 11:54:20 UTC 2025
An `Initialize` node for an `Allocate` node is created with a memory
`Proj` of adr type raw memory. In order for stores to be captured, the
memory state out of the allocation is a `MergeMem` with slices for the
various object fields/array element set to the raw memory `Proj` of
the `Initialize` node. If `Phi`s need to be created during later
transformations from this memory state, The `Phi` for a particular
slice gets its adr type from the type of the `Proj` which is raw
memory. If during macro expansion, the `Allocate` is found to have no
use and so can be removed, the `Proj` out of the `Initialize` is
replaced by the memory state on input to the `Allocate`. A `Phi` for
some slice for a field of an object will end up with the raw memory
state on input to the `Allocate` node. As a result, memory state at
the `Phi` is incorrect and incorrect execution can happen.
The fix I propose is, rather than have a single `Proj` for the memory
state out of the `Initialize` with adr type raw memory, to use one
`Proj` per slice added to the memory state after the `Initalize`. Each
of the `Proj` should return the right adr type for its slice. For that
I propose having a new type of `Proj`: `NarrowMemProj` that captures
the right adr type.
Logic for the construction of the `Allocate`/`Initialize` subgraph is
tweaked so the right adr type captured in is own `NarrowMemProj` is
added to the memory sugraph. Code that removes an allocation or moves
it also has to be changed so it correctly takes the multiple memory
projections out of the `Initialize` node into account.
One tricky issue is that when EA split types for a scalar replaceable
`Allocate` node:
1- the adr type captured in the `NarrowMemProj` becomes out of sync
with the type of the slices for the allocation
2- before EA, the memory state for one particular field out of the
`Initialize` node can be used for a `Store` to the just allocated
object or some other. So we can have a chain of `Store`s, some to
the newly allocated object, some to some other objects, all of them
using the state of `NarrowMemProj` out of the `Initialize`. After
split unique types, the `NarrowMemProj` is for the slice of a
particular allocation. So `Store`s to some other objects shouldn't
use that memory state but the memory state before the `Allocate`.
For that, I added logic to update the adr type of `NarrowMemProj`
during split unique types and update the memory input of `Store`s that
don't depend on the memory state out of the allocation site.
I also wrote a verification pass to check that, in the memory graph,
nodes on a particular slice have the right adr type. That verification
pass is not included here because it uncovered issues that are
unrelated to this particular issue so I intend to propose it (with
fixes for those other issues) separately.
I reused the test cases that Emanuel included in
https://github.com/openjdk/jdk/pull/18265 and went over all issues
linked to this one, tried the test cases and added the ones that I
could reproduce.
-------------
Commit messages:
- whitespace
- fix & extra tests
- more tests, WIP
- initializing store capturing: test stub
- test4
- 8327012
Changes: https://git.openjdk.org/jdk/pull/24570/files
Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=24570&range=00
Issue: https://bugs.openjdk.org/browse/JDK-8327963
Stats: 574 lines in 11 files changed: 539 ins; 15 del; 20 mod
Patch: https://git.openjdk.org/jdk/pull/24570.diff
Fetch: git fetch https://git.openjdk.org/jdk.git pull/24570/head:pull/24570
PR: https://git.openjdk.org/jdk/pull/24570
More information about the hotspot-compiler-dev
mailing list