RFR: 8290892: C2: Intrinsify Reference.reachabilityFence [v8]
Emanuel Peter
epeter at openjdk.org
Mon Sep 8 14:52:18 UTC 2025
On Wed, 3 Sep 2025 21:29:43 GMT, Vladimir Ivanov <vlivanov at openjdk.org> wrote:
>> This PR introduces C2 support for `Reference.reachabilityFence()`.
>>
>> After [JDK-8199462](https://bugs.openjdk.org/browse/JDK-8199462) went in, it was discovered that C2 may break the invariant the fix relied upon [1]. So, this is an attempt to introduce proper support for `Reference.reachabilityFence()` in C2. C1 is left intact for now, because there are no signs yet it is affected.
>>
>> `Reference.reachabilityFence()` can be used in performance critical code, so the primary goal for C2 is to reduce its runtime overhead as much as possible. The ultimate goal is to ensure liveness information is attached to interfering safepoints, but it takes multiple steps to properly propagate the information through compilation pipeline without negatively affecting generated code quality.
>>
>> Also, I don't consider this fix as complete. It does fix the reported problem, but it doesn't provide any strong guarantees yet. In particular, since `ReachabilityFence` is CFG-only node, nothing explicitly forbids memory operations to float past `Reference.reachabilityFence()` and potentially reaching some other safepoints current analysis treats as non-interfering. Representing `ReachabilityFence` as memory barrier (e.g., `MemBarCPUOrder`) would solve the issue, but performance costs are prohibitively high. Alternatively, the optimization proposed in this PR can be improved to conservatively extend referent's live range beyond `ReachabilityFence` nodes associated with it. It would meet performance criteria, but I prefer to implement it as a followup fix.
>>
>> Another known issue relates to reachability fences on constant oops. If such constant is GCed (most likely, due to a bug in Java code), similar reachability issues may arise. For now, RFs on constants are treated as no-ops, but there's a diagnostic flag `PreserveReachabilityFencesOnConstants` to keep the fences. I plan to address it separately.
>>
>> [1] https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/lang/ref/Reference.java#L667
>> "HotSpot JVM retains the ref and does not GC it before a call to this method, because the JIT-compilers do not have GC-only safepoints."
>>
>> Testing:
>> - [x] hs-tier1 - hs-tier8
>> - [x] hs-tier1 - hs-tier6 w/ -XX:+StressReachabilityFences -XX:+VerifyLoopOptimizations
>> - [x] java/lang/foreign microbenchmarks
>
> Vladimir Ivanov has updated the pull request incrementally with one additional commit since the last revision:
>
> whitespaces
A few comments about the `reachability.cpp` intro. I think we are on a good way here :)
src/hotspot/share/opto/reachability.cpp line 49:
> 47: *
> 48: * It is tempting to directly attach referents to interfering safepoints right from the beginning, but it
> 49: * doesn't play well with some optimizations C2 does.
Do you have an example for such optimizations?
src/hotspot/share/opto/reachability.cpp line 67:
> 65: * RF nodes may interfere with RA, so stand-alone RF nodes are eliminated and their referents are
> 66: * transferred to corresponding safepoints (phase #2). When safepoints are pruned during macro expansion,
> 67: * corresponding reachability edges also go away.
Spell our RA on first use. Make more clear that this is why we eliminate RF before RA.
Suggestion:
* RF nodes may interfere with register allocation (RA), hence we eliminate RF nodes and transfer their
* referents to corresponding safepoints (phase #2). When safepoints are pruned during macro expansion,
* corresponding reachability edges also go away.
`reachability edges also go away` ... and that is ok why? Sketch of what you could write, is it correct?
- reachability only needs to be correct at SafePoints. If all the SafePoints are removed for a referent, then we don't need to ensure its reachablility.
src/hotspot/share/opto/reachability.cpp line 71:
> 69: * Unfortunately, it's not straightforward to stay with safepoint-attached representation till the very end,
> 70: * because information about derived oops is attached to safepoints the very same similar way. So, for now RFs are
> 71: * rematerialized at safepoints before RA (phase #3).
`the very same similar way` sounds a little funny. I'm also not quite seeing the problem yet. What is the issue with the edges being attached to safepoints here?
-------------
PR Review: https://git.openjdk.org/jdk/pull/25315#pullrequestreview-3196820681
PR Review Comment: https://git.openjdk.org/jdk/pull/25315#discussion_r2330441117
PR Review Comment: https://git.openjdk.org/jdk/pull/25315#discussion_r2330487392
PR Review Comment: https://git.openjdk.org/jdk/pull/25315#discussion_r2330491632
More information about the hotspot-compiler-dev
mailing list