1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 interface Itf {
sameInvokeInterface()18   public Class<?> sameInvokeInterface();
sameInvokeInterface2()19   public Class<?> sameInvokeInterface2();
sameInvokeInterface3()20   public Class<?> sameInvokeInterface3();
21 }
22 
23 public class Main implements Itf {
assertEquals(Object expected, Object actual)24   public static void assertEquals(Object expected, Object actual) {
25     if (expected != actual) {
26       throw new Error("Expected " + expected  + ", got " + actual);
27     }
28   }
29 
assertEquals(int expected, int actual)30   public static void assertEquals(int expected, int actual) {
31     if (expected != actual) {
32       throw new Error("Expected " + expected  + ", got " + actual);
33     }
34   }
35 
main(String[] args)36   public static void main(String[] args) throws Exception {
37     System.loadLibrary(args[0]);
38     Main[] mains = new Main[3];
39     Itf[] itfs = new Itf[3];
40     itfs[0] = mains[0] = new Main();
41     itfs[1] = mains[1] = new Subclass();
42     itfs[2] = mains[2] = new OtherSubclass();
43 
44     // Create the profiling info eagerly to make sure they are filled.
45     ensureProfilingInfo566();
46 
47     // Make $noinline$testInvokeVirtual and $noinline$testInvokeInterface hot to get them jitted.
48     // We pass Main and Subclass to get polymorphic inlining based on calling
49     // the same method.
50     for (int i = 0; i < 1000000; ++i) {
51       $noinline$testInvokeVirtual(mains[0]);
52       $noinline$testInvokeVirtual(mains[1]);
53       $noinline$testInvokeInterface(itfs[0]);
54       $noinline$testInvokeInterface(itfs[1]);
55       $noinline$testInvokeInterface2(itfs[0]);
56       $noinline$testInvokeInterface2(itfs[1]);
57       $noinline$testInlineToSameTarget(mains[0]);
58       $noinline$testInlineToSameTarget(mains[1]);
59     }
60 
61     ensureJittedAndPolymorphicInline566();
62 
63     // At this point, the JIT should have compiled both methods, and inline
64     // sameInvokeVirtual and sameInvokeInterface.
65     assertEquals(Main.class, $noinline$testInvokeVirtual(mains[0]));
66     assertEquals(Main.class, $noinline$testInvokeVirtual(mains[1]));
67 
68     assertEquals(Itf.class, $noinline$testInvokeInterface(itfs[0]));
69     assertEquals(Itf.class, $noinline$testInvokeInterface(itfs[1]));
70 
71     assertEquals(Itf.class, $noinline$testInvokeInterface2(itfs[0]));
72     assertEquals(Itf.class, $noinline$testInvokeInterface2(itfs[1]));
73 
74     // This will trigger a deoptimization of the compiled code.
75     assertEquals(OtherSubclass.class, $noinline$testInvokeVirtual(mains[2]));
76     assertEquals(OtherSubclass.class, $noinline$testInvokeInterface(itfs[2]));
77     assertEquals(null, $noinline$testInvokeInterface2(itfs[2]));
78 
79     // Run this once to make sure we execute the JITted code.
80     $noinline$testInlineToSameTarget(mains[0]);
81     assertEquals(2000001, counter);
82   }
83 
sameInvokeVirtual()84   public Class<?> sameInvokeVirtual() {
85     field.getClass(); // null check to ensure we get an inlined frame in the CodeInfo.
86     return Main.class;
87   }
88 
sameInvokeInterface()89   public Class<?> sameInvokeInterface() {
90     field.getClass(); // null check to ensure we get an inlined frame in the CodeInfo.
91     return Itf.class;
92   }
93 
sameInvokeInterface2()94   public Class<?> sameInvokeInterface2() {
95     field.getClass(); // null check to ensure we get an inlined frame in the CodeInfo.
96     return Itf.class;
97   }
98 
sameInvokeInterface3()99   public Class<?> sameInvokeInterface3() {
100     field.getClass(); // null check to ensure we get an inlined frame in the CodeInfo.
101     return Itf.class;
102   }
103 
$noinline$testInvokeInterface(Itf i)104   public static Class<?> $noinline$testInvokeInterface(Itf i) {
105     return i.sameInvokeInterface();
106   }
107 
$noinline$testInvokeInterface2(Itf i)108   public static Class<?> $noinline$testInvokeInterface2(Itf i) {
109     // Make three interface calls that will do a ClassTableGet to ensure bogus code
110     // generation of ClassTableGet will crash.
111     i.sameInvokeInterface();
112     i.sameInvokeInterface2();
113     return i.sameInvokeInterface3();
114   }
115 
$noinline$testInvokeVirtual(Main m)116   public static Class<?> $noinline$testInvokeVirtual(Main m) {
117     return m.sameInvokeVirtual();
118   }
119 
$noinline$testInlineToSameTarget(Main m)120   public static void $noinline$testInlineToSameTarget(Main m) {
121     if (doThrow) throw new Error("");
122     m.increment();
123   }
124 
125   public Object field = new Object();
126 
ensureJittedAndPolymorphicInline566()127   public static native void ensureJittedAndPolymorphicInline566();
ensureProfilingInfo566()128   public static native void ensureProfilingInfo566();
129 
increment()130   public void increment() {
131     field.getClass(); // null check to ensure we get an inlined frame in the CodeInfo
132     counter++;
133   }
134   public static int counter = 0;
135   public static boolean doThrow = false;
136 }
137 
138 class Subclass extends Main {
139 }
140 
141 class OtherSubclass extends Main {
sameInvokeVirtual()142   public Class<?> sameInvokeVirtual() {
143     return OtherSubclass.class;
144   }
145 
sameInvokeInterface()146   public Class<?> sameInvokeInterface() {
147     return OtherSubclass.class;
148   }
149 
sameInvokeInterface2()150   public Class<?> sameInvokeInterface2() {
151     return null;
152   }
sameInvokeInterface3()153   public Class<?> sameInvokeInterface3() {
154     return null;
155   }
156 }
157