JDK-6986483 : CHA: optimize calls through interfaces
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 9,10,11,12,13
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2010-09-21
  • Updated: 2022-10-07
  • Resolved: 2019-02-01
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.
JDK 13
13 b07Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Sub Tasks
JDK-8226508 :  
Description
I take a little time to create a simple test case to reproduce a bug
found by Charles Nutter with c2.
see http://groups.google.com/group/jvm-languages/browse_thread/thread/6c9e05ecd28fdcd4#

Here is the test case,
There is 3 classes A, B, C that inherit from AbstractFoo that implements Foo.
The method test do a virtual call to check() and because
check() is implemented in AbstractFoo we expect that this call should be
de-virtualized then inlined.

c2 fails, foo.check() is compiled as a virtual call :(
With c1, there is no problem, CHA works correctly.

RĂ©mi

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

public class InlineTest {
 interface Foo {
   public boolean check(int generation);
 }

 static class AbstractFoo implements Foo {
   private final int value;

   protected AbstractFoo(int value) {
     this.value = value;
   }

   public boolean check(int generation) {
     return this.getClass().hashCode() - value == generation;
   }
 }

 static class A extends AbstractFoo {
   public A(int value) {
     super(value);
   }
 }
 static class B extends AbstractFoo {
   public B(int value) {
     super(value);
   }
 }
 static class C extends AbstractFoo {
   public C(int value) {
     super(value);
   }
 }

 private static final int CONST = A.class.hashCode();

 private static int count;

 private static void test(Foo foo) {
   if (foo.check(0)) {
       count += 2;
       //System.out.println("foo");
   } else {
       count += 1;
       //System.out.println("bar");
   }
 }

 public static void main(String[] args) {
   Foo[] array = new Foo[100000];
   int threshold = 20000;
   for(int i=0; i<threshold; i++) {
     array[i] = new A(CONST);
   }

   for(int i=threshold; i<array.length; i++) {
     array[i] = (i%2 == 0)? new B(0): new C(CONST);
   }

   for(int i=0; i<array.length; i++) {
     test(array[i]);
   }

   System.out.println(count);
 }
}

Comments
URL: http://hg.openjdk.java.net/jdk/jdk/rev/8462b295c08b User: vlivanov Date: 2019-02-01 01:48:56 +0000
01-02-2019

We are likely to make more use of interfaces to represent non-Java data structures, as purely abstract behavior. In such cases, the interface will serve to hide a class, but will correspond routinely to just the one class. We should improve CHA to cover this case, so that interface calls can be bound statically. Loading a second implementation would cause dependency-based deoptimization, as is usual with CHA.
17-03-2014

EVALUATION Thanks for the test case. The reason it works well for C1 is that we have an explicit check for single implementor interfaces and insert an extra checkcast to confirm that the type really is the type we expect. The extra check is needed since interface types aren't actually checked by the verifier. In your example the extra check isn't actually needed since all array stores are actually type checked so any type loaded from the array must actually implement the interface. C2 generally relies on type profiling to get cases like this but since type profiling is tracking the type of the receiver instead of the actual method being invoked it doesn't handle this case that well. It's not hard to do something better for this case. I filed 6986483 for this.
21-09-2010