JDK-8325681 : C2 inliner rejects to inline a deeper callee because the methoddata of caller is immature.
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 18,21,23
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: generic
  • Submitted: 2024-02-13
  • Updated: 2024-02-20
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbdUnresolved
Related Reports
Relates :  
Description
Since JDK-8273712, C2 inliner has changed to reject a callee based on 'MinInlineFrequencyRatio'.  In the changeset, we obtains call_site_count from intermediate object 'ciCallProfile'. 

ciCallProfile is generated from its caller in Compile::call_generator(). It's worth noting that caller here may not be the root method. it's possible that the method data of caller here has not been mature yet.  When ciCallProfiler is  immature, ciCallProfiler::_count is -1.  call_site_count is negative and can't pass freq < min_freq check. As a result, c2 inliner rejects to inline the callsite. 

We develop a simple program to demonstrate this case. For simplicity, we can imagine that an inline tree that contains > 3 levels.  

foo
> bar 
>> baz 
>>>   ....

method foo is the root method that c2 compiles. It's possible that the invocation count of bar is less than foo. it's up to the control flow.  We introduce a parameter 'ODD'. It indicates that foo() calls method bar() with possibility ODD%. eg. ODD=20 says that there's 20% possibility that foo() calls bar(). 

We found that jvm option ProfileMaturityPercentage determines whether the method data of method is regarded as 'mature'.  when ODD< ProfileMaturityPercentage,  it's likely that the method data of bar has not been mature when c2 is triggered to compile foo(). 

eg. we spot that c2 rejects baz because of 'low call site frequency'

$java -XX:+UnlockDiagnosticVMOptions -XX:CompileOnly='UnderProfiledSubprocedure.foo' -XX:+PrintInlining -XX:+PrintCompilation -XX:CompileCommand=quiet -Xbatch UnderProfiledSubprocedure 19


60   13    b  4       UnderProfiledSubprocedure::foo (9 bytes)
                              @ 5   UnderProfiledSubprocedure::bar (6 bytes)   inline (hot)
                                @ 1   UnderProfiledSubprocedure::baz (19 bytes)   failed to inline: low call site frequency

 
Comments
for ODD=10, we can get methodata of bar() as follows: UnderProfiledSubprocedure::bar()V interpreter_invocation_count: 557 invocation_counter: 557 backedge_counter: 0 decompile_count: 0 mdo size: 472 bytes 0 fast_aload_0 1 invokevirtual 25 <UnderProfiledSubprocedure.baz()I> 0 bci: 1 VirtualCallData count(0) entries(1) 'UnderProfiledSubprocedure'(540 1.00) 4 pop 5 return the methodata is immature because the absolute number of invocation count(557) is too small comparing with 'Tier4InvocationThreshold * ProfileMaturityPercentage / 100' (roughly 600). Even though it's immature, we still can tell that the vcall goes to baz() 540 times and it's a monomorphic call.we also know that its frequency is 96.9%
20-02-2024

We found that whether method baz is inlined is correlate with controlflow of program and jvm option ProfileMaturityPercentage. We expect c2 to inline method baz all the time. Even when ODD=1, the frequency is 1% relative to foo() and 100% relative to its direct caller. No matter what, it's still greater than MinInlineFrequencyRatio=0.0085. In run.sh, we iterate ODD from 1 to 30. higer ODD is, the more likely c2 inlines method baz. As depicted in inlineBaz.png, there's a tipping point around ProfileMaturityPercentage. When ODD < ProfileMaturityPercentage, c2 doesn't inline method baz because the methodata of bar has not mature when c2 compiles foo. we run the test using the following command and plot data in excel. ProfileMaturityPercentage=15 ./run.sh ProfileMaturityPercentage=20 ./run.sh ProfileMaturityPercentage=30 ./run.sh
13-02-2024