RFR: 8362832: compiler/macronodes/TestTopInMacroElimination.java hits assert(false) failed: unexpected node

Benoît Maillard bmaillard at openjdk.org
Tue Oct 21 08:59:36 UTC 2025


This PR prevents hitting an assert caused by encountering `top` while following the memory
slice associated with a field when eliminating allocations in macro node elimination. This situation
is the result of another elimination (boxing node elimination) that happened at the same
macro expansion iteration.

### Analysis

The issue appears in the macro expansion phase. We have a nested `synchronized` block,
with the outer block synchronizing on `new A()` and the inner one on `TestTopInMacroElimination.class`.
In the inner `synchronized` block we have an `Integer.valueOf` call in a loop.

In `PhaseMacroExpand::eliminate_boxing_node` we are getting rid of the `Integer.valueOf`
call, as it is a non-escaping boxing node. After having eliminated the call,
`PhaseMacroExpand::process_users_of_allocation` takes care of the users of the removed node.
There, we replace usages of the fallthrough memory projection with `top`.

In the same macro expansion iteration, we later attempt to get rid of the `new A()` allocation
in `PhaseMacroExpand::create_scalarized_object_description`. There, we have to make
sure that all safepoints can still see the object fields as if the allocation was never deleted.
For this, we attempt to find the last value on the slice of each specific field (`a`
in this case). Because field `a` is never written to, and it is not explicitely initialized,
there is no `Store` associated to it and not even a dedicated memory slice (we end up
taking the `Bot` input on `MergeMem` nodes). By going up the memory chain, we eventually
encounter the `MemBarReleaseLock` whose input was set to `top`. This is where the assert
is hit.

### Proposed Fix

In the end I opted for an analog fix as the similar [JDK-8325030](https://git.openjdk.org/jdk/pull/23104).
If we get `top` from `scan_mem_chain` in `PhaseMacroExpand::value_from_mem`, then we can safely
return `top` as well. This means that the safepoint will have `top` as data input, but this will
eventually cleaned up by the next round of IGVN.

Another (tempting) option would have been to simply return `nullptr` from `PhaseMacroExpand::value_from_mem` when encoutering `top`. However this would result in bailing
out from eliminating this allocation temporarily and effectively delaying it to a subsqequent
macro expansion round.


### Testing
- [x] [GitHub Actions](https://github.com/benoitmaillard/jdk/actions?query=branch%3AJDK-8362832)
- [x] tier1-4, plus some internal testing

Thank you for reviewing!

-------------

Commit messages:
 - Add comment
 - Remove file commited by mistake
 - Add issue number to jtreg headers
 - 8362832: Return top in value_from_mem as last value on the slice if the path is dead
 - 8362832: Remove test from problemlist

Changes: https://git.openjdk.org/jdk/pull/27903/files
  Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27903&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8362832
  Stats: 8 lines in 3 files changed: 4 ins; 3 del; 1 mod
  Patch: https://git.openjdk.org/jdk/pull/27903.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/27903/head:pull/27903

PR: https://git.openjdk.org/jdk/pull/27903


More information about the hotspot-compiler-dev mailing list