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

Vladimir Ivanov vlivanov at openjdk.java.net
Wed Jan 5 19:50:48 UTC 2022


[JDK-8267806](https://bugs.openjdk.java.net/browse/JDK-8267806) broke inlining at `invokedynamic` and `invokestatic` call sites in some circumstances. Thought 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'

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

Commit messages:
 - 8279515: C1: linkToTargetMethod is not inlined

Changes: https://git.openjdk.java.net/jdk18/pull/80/files
 Webrev: https://webrevs.openjdk.java.net/?repo=jdk18&pr=80&range=00
  Issue: https://bugs.openjdk.java.net/browse/JDK-8279515
  Stats: 166 lines in 4 files changed: 162 ins; 0 del; 4 mod
  Patch: https://git.openjdk.java.net/jdk18/pull/80.diff
  Fetch: git fetch https://git.openjdk.java.net/jdk18 pull/80/head:pull/80

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


More information about the hotspot-compiler-dev mailing list