RFR: 8290892: C2: Intrinsify Reference.reachabilityFence [v2]
Vladimir Ivanov
vlivanov at openjdk.org
Thu May 22 22:44:12 UTC 2025
On Thu, 22 May 2025 09:15:03 GMT, Aleksey Shipilev <shade at openjdk.org> wrote:
>> Vladimir Ivanov has updated the pull request incrementally with one additional commit since the last revision:
>>
>> review feedback
>
> src/hotspot/share/opto/block.cpp line 189:
>
>> 187: !get_node(end_idx)->is_Mach() &&
>> 188: !get_node(end_idx)->is_BoxLock() &&
>> 189: !(get_node(end_idx)->is_ReachabilityFence() && C->print_assembly())) {
>
> Um. So this fairly generic method is predicated of whether a diagnostic VM option is enabled. Which risks that the compiler behavior with/without printing assembly is different? Which might hide the very issues we are trying to diagnose with printing assembly? Can we handle `RF` here without checking for `print_assembly`?
>
> This will also obviate a need to pass `Compile* C` around.
Fair enough. Treating RFs uniformly should be fine, since they are attached to safepoints now.
> src/hotspot/share/opto/callnode.cpp line 969:
>
>> 967: projs->exobj = e;
>> 968: } else {
>> 969: // exception table for rethrow case
>
> Feels like we want to assert other values of `e->in(0)->as_CatchProj()->_con` here? From the switch statement in the previous hunk, there seems to be `fall_through_index` that is not "rethrow case" (or is it?).
Makes sense. Added an assert.
> src/hotspot/share/opto/compile.cpp line 3912:
>
>> 3910: // requires that the walk visits a node's inputs before visiting the node.
>> 3911:
>> 3912: static bool has_non_debug_uses(Node* n) {
>
> This got inserted right between `------------------------------final_graph_reshaping_walk--------------------` comment and the `final_graph_reshaping_walk` implementation. Also, put `has_non_debug_uses` into `Compile`?
I moved it to `Node::has_non_debug_uses()`.
> src/hotspot/share/opto/compile.cpp line 3995:
>
>> 3993: for (int j = start; j < end; j++) {
>> 3994: Node* in = n->in(j);
>> 3995: if (in->is_DecodeNarrowPtr() && (is_uncommon || has_non_debug_uses(in))) {
>
> The comment says we can skip when node is only referenced in debug info. Here we skip when there _are_ non-debug uses. Did you mean `!has_non_debug_uses(in)`?
Good point. Fixed.
Funnily enough, it did the right job here (but not in RF case!), because `has_non_debug_uses` reported the opposite answer to what can be expected based on its name :-)
> src/hotspot/share/opto/parse1.cpp line 1225:
>
>> 1223:
>> 1224: if (StressReachabilityFences) {
>> 1225: // Keep all oop arguments alive until method return.
>
> Comment says "arguments", but we save locals. Aren't arguments on "stack" in `JVMState`? For stress mode, would make sense to hook up both locals/stack from `JVMState`, maybe?
It happens inside callee context, so all arguments are already moved to locals. The code could explicitly iterate over arguments (using `argument(uint)` query) or enumerate only those locals which hold arguments, but that would require a special case for receiver. Iteration over locals (`[0 ... max_locals)`) is uniform and enumerates only arguments since everything else is top.
> src/hotspot/share/opto/reachability.cpp line 211:
>
>> 209: }
>> 210: }
>> 211: return found;
>
> `found` is always `false` here. I don't think this function even needs a return value, judging by the uses.
My intention was to signal when not-yet-known redundant fences are found.
I prefer to keep it even if it is not used right now.
Fixed by updating `found` along with pushing newly discovered redundant node on the list.
> src/hotspot/share/opto/reachability.cpp line 431:
>
>> 429: }
>> 430: }
>> 431: redundant_rfs.push(rf);
>
> I see `PhaseIdealLoop::optimize_reachability_fences` asks for `redundant_rfs.member(rf)` before going into this analysis. Is it because we can have duplicate RFs in the `C->reachability_fence` list? Can we have duplicate here? Should we check `.member(rf)` here as well?
No duplicated entries are allowed in `Compile::_reachability_fences`.
`eliminate_reachability_fences()` is called at the end of loop opts after `optimize_reachability_fences()` is done (possibly, multiple times).
`eliminate_reachability_fences()` migrates all referents from RFs to safepoints. So, every RF node is placed on `redundant_rfs` list and there are no RF nodes left after `eliminate_reachability_fences()` is over (there's `C->reachability_fences_count() == 0` assert at the end).
After safepoints are directly linked to the referent, the corresponding RF node becomes redundant. So, I kept `redundant_rfs` as a name. I can choose a different one if you find it confusing.
Another important aspect when it comes to determining RF redundancy is that `eliminate_reachability_fences()` takes all users into account while `optimize_reachability_fences()` trusts only `ReachabilityFence`s.
> src/java.base/share/classes/java/lang/ref/Reference.java line 662:
>
>> 660: * @since 9
>> 661: */
>> 662: @IntrinsicCandidate
>
> Sounds like we also want to restore `@DontInline` to cover the case when intrinsic is not available / disabled for some compiler. I vaguely remember some intrinsic handling code checks whether method is prohibited from inlining (maybe affects only global `-XX:-Inline`, not sure), so it might be as straightforward.
I'd like to use `-XX:DisableIntrinsic=_Reference_reachabilityFence` to switch to current behavior (no fence).
Also, `@DontInline` would require special handling in C1 to unconditionally inline it.
`@ForceInline` was there primarily to communicate the interaction with JVM. (Existing inlining heuristics should just unconditionally inline empty methods.) Once `@IntrinsicCandidate` is there, I don't see much value in any other annotations.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/25315#discussion_r2103490049
PR Review Comment: https://git.openjdk.org/jdk/pull/25315#discussion_r2103488472
PR Review Comment: https://git.openjdk.org/jdk/pull/25315#discussion_r2103480961
PR Review Comment: https://git.openjdk.org/jdk/pull/25315#discussion_r2103482636
PR Review Comment: https://git.openjdk.org/jdk/pull/25315#discussion_r2103418703
PR Review Comment: https://git.openjdk.org/jdk/pull/25315#discussion_r2103447864
PR Review Comment: https://git.openjdk.org/jdk/pull/25315#discussion_r2103457174
PR Review Comment: https://git.openjdk.org/jdk/pull/25315#discussion_r2103467390
More information about the hotspot-compiler-dev
mailing list