[jdk18] Integrated: 8279515: C1: No inlining through invokedynamic and invokestatic call sites when resolved class is not linked

Vladimir Ivanov vlivanov at openjdk.java.net
Mon Jan 10 13:58:40 UTC 2022


On Wed, 5 Jan 2022 15:30:27 GMT, Vladimir Ivanov <vlivanov at openjdk.org> wrote:

> [JDK-8267806](https://bugs.openjdk.java.net/browse/JDK-8267806) broke inlining at `invokedynamic` and `invokestatic` call sites in some circumstances. Though the enhancement was intended to relax the inlining checks, it introduced one new check to ensure that resolved klass (`REFC`) is linked. It turned out the check is too strong: resolution of the symbolic class reference at a call site does not trigger class linkage.  
> 
> For `invokestatic` consider the following example:
> 
> class A { static m() { ... } }
> class B extends A {}
> 
> invokestatic "B"::"m" => A::m
> 
> 
> Method resolution loads class `B` along the way, but neither initialises nor links it. Invocation does trigger class initialisation, but only for class `A`. 
> 
> For `invokedynamic` it's a bit more complicated. Syntactically, there's no symbolic class reference at the call site, but CI assigns an artificial one (`java.lang.invoke.MethodHandle`, see `ciBytecodeStream::get_declared_method_holder()`). The problem is `MethodHandle` class doesn't have to be loaded by the class loader of the accessing class, so `ciEnv::get_klass_by_name()` can produce unloaded CI mirror (`ciKlass`).
> 
> For example, indy call site linkage of indified string concatenation (`StringConcatFactory.makeConcatWithConstants()`) doesn't get `MethodHandle` class recorded in the context class loader [1]  while `LambdaMetafactory.metafactory()` introduces a class loader constraint for it [2] which reveals the class to the subsequent class lookup.  ​
> 
> I decided to make `ciBytecodeStream::get_declared_method_holder()` predictable and return well-known VM class right away without doing the lookup.
> 
> Proposed fix relaxes the constraint on resolved class (`REFC`) and requires it to be loaded.
> 
> Also, while working on the fix, I spotted that the constraint for `invokestatic` is also too strong (requires resolved class to be initialized while the specification mandates resolved method holder to be initialized instead):
> 
>     if ((code == Bytecodes::_invokestatic && callee_holder->is_initialized()) || // invokestatic involves an initialization barrier on resolved klass
> 
> 
> I fixed it as well (`s/callee_holder/klass/`).
> 
> Testing: hs-tier1 - hs-tier4
> 
> [1]
> 
> [0.160s][debug][class,resolve           ] Test1 java.lang.invoke.StringConcatFactory Test.java:3
> [0.160s][info ][class,loader,constraints] adding new constraint for name: java/lang/invoke/MethodHandles$Lookup, loader[0]: 'app', loader[1]: 'bootstrap'
> [0.160s][info ][class,loader,constraints] adding new constraint for name: java/lang/invoke/MethodType, loader[0]: 'app', loader[1]: 'bootstrap'
> [0.160s][info ][class,loader,constraints] adding new constraint for name: java/lang/invoke/CallSite, loader[0]: 'app', loader[1]: 'bootstrap'
> 
> 
> [2] 
> 
> [0.130s][debug][class,resolve          ] Test java.lang.invoke.LambdaMetafactory Test.java:21
> [0.130s][info ][class,loader,constraints] adding new constraint for name: java/lang/invoke/MethodHandles$Lookup, loader[0]: 'app', loader[1]: 'bootstrap'
> [0.130s][info ][class,loader,constraints] adding new constraint for name: java/lang/invoke/MethodType, loader[0]: 'app', loader[1]: 'bootstrap'
> [0.130s][info ][class,loader,constraints] adding new constraint for name: java/lang/invoke/MethodHandle, loader[0]: 'app', loader[1]: 'bootstrap'
> [0.130s][info ][class,loader,constraints] adding new constraint for name: java/lang/invoke/CallSite, loader[0]: 'app', loader[1]: 'bootstrap'

This pull request has now been integrated.

Changeset: ad34f03b
Author:    Vladimir Ivanov <vlivanov at openjdk.org>
URL:       https://git.openjdk.java.net/jdk18/commit/ad34f03b549e6f37825efc3e554d2232b557611a
Stats:     166 lines in 4 files changed: 162 ins; 0 del; 4 mod

8279515: C1: No inlining through invokedynamic and invokestatic call sites when resolved class is not linked

Reviewed-by: kvn, dlong

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

PR: https://git.openjdk.java.net/jdk18/pull/80


More information about the hotspot-compiler-dev mailing list