On Wed, 22 Apr 2026 11:30:06 GMT, Benoît Maillard <[email protected]> wrote:
> This PR prevents a missed optimization caused by a breach of idempotence in
> `InlineTypeNode::Value` when handling contradicting method return profiles.
>
> ## Conflicting return profiles
>
> Suppose we have the following java code, and that we have record profile data
> for both callsites (`call(...)` and `callWrapper(...)`):
>
>
> static MyValue callWrapper(...) {
> return call(...); // callsite #1
> }
>
> static MyValue test() {
> return callWrapper(...); // callsite #2
> }
>
>
> It could be that `test` is not the only place where we call
> `callWrapper(...)`, and that the other call sites result in wildy different
> executions of callsite `#1` with wildly different return values at that
> callsite.
>
> Suppose that callsite `#1` always returns `null`, except when `callWrapper`
> is called from callsite `#2` where it throws an exception. In
> `ciMethod::return_profiled_type`, we end up with the following
> `ProfilePtrKind` when compiling `test`:
> - For callsite `#1`: `ProfileAlwaysNull`, because we have only observed
> `null` (the rest of the time an exception was thrown, so we didn't see
> anything)
> - For callsite `#2`: `ProfileNeverNull`, because we have never observed a
> return value and this is basically the default
>
> Please look at the test from this PR for a more complete example.
>
> These two profiles contradict each other. If we do incremental inlining
> (probably not limited to it, but easier to reproduce), we can easily end up
> in a situation where a speculative type derived from the return of the
> callsite is `NotNull` before inlining the outer callsite, and then moves to
> `ptr:null` after inlining. This can confuse `Value` implementations that rely
> on `filter_speculative`. This is handled gracefully for `ConstraintCastNode`,
> but not for `InlineTypeNode`.
>
> ## Missed optimization
>
> In `InlineTypeNode::Value`, we have:
> https://github.com/openjdk/valhalla/blob/e391f76e7db834f50c1a0af466daf95a65a79f23/src/hotspot/share/opto/inlinetypenode.cpp#L1619
>
> Suppose we have the following types (only the speculative part is shown):
>
> oop:
> instptr:compiler/valhalla/inlinetypes/TestPollutedCallsiteProfileInlineType$MyValue:NotNull:exact
> *,iid=bot (flat in array)
> _type:
> instptr:compiler/valhalla/inlinetypes/TestPollutedCallsiteProfileInlineType$MyValue:NotNull:exact
> *,iid=bot (flat in array)
>
>
> After this step we have `t = oop = _type`.
>
> The oop input suddenly changes types because of incremental inlining, as
> explained in the previous section. It goes from `NotNull` to `ptr:null`
> because the type from the poll...
This pull request has now been integrated.
Changeset: f09dea67
Author: Benoît Maillard <[email protected]>
Committer: Quan Anh Mai <[email protected]>
URL:
https://git.openjdk.org/valhalla/commit/f09dea673b68e51ff3604d7c6f0f0561dd0f8c98
Stats: 102 lines in 3 files changed: 87 ins; 1 del; 14 mod
8380927: [lworld] C2: Missed Value() optimization for InlineType
Reviewed-by: qamai, thartmann
-------------
PR: https://git.openjdk.org/valhalla/pull/2351