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
17interface Itf {
18  public Class<?> sameInvokeInterface();
19  public Class<?> sameInvokeInterface2();
20  public Class<?> sameInvokeInterface3();
21}
22
23public class Main implements Itf {
24  public static void assertEquals(Object expected, Object actual) {
25    if (expected != actual) {
26      throw new Error("Expected " + expected  + ", got " + actual);
27    }
28  }
29
30  public static void assertEquals(int expected, int actual) {
31    if (expected != actual) {
32      throw new Error("Expected " + expected  + ", got " + actual);
33    }
34  }
35
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 testInvokeVirtual and 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 < 10000; ++i) {
51      testInvokeVirtual(mains[0]);
52      testInvokeVirtual(mains[1]);
53      testInvokeInterface(itfs[0]);
54      testInvokeInterface(itfs[1]);
55      testInvokeInterface2(itfs[0]);
56      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, testInvokeVirtual(mains[0]));
66    assertEquals(Main.class, testInvokeVirtual(mains[1]));
67
68    assertEquals(Itf.class, testInvokeInterface(itfs[0]));
69    assertEquals(Itf.class, testInvokeInterface(itfs[1]));
70
71    assertEquals(Itf.class, testInvokeInterface2(itfs[0]));
72    assertEquals(Itf.class, testInvokeInterface2(itfs[1]));
73
74    // This will trigger a deoptimization of the compiled code.
75    assertEquals(OtherSubclass.class, testInvokeVirtual(mains[2]));
76    assertEquals(OtherSubclass.class, testInvokeInterface(itfs[2]));
77    assertEquals(null, testInvokeInterface2(itfs[2]));
78
79    // Run this once to make sure we execute the JITted code.
80    $noinline$testInlineToSameTarget(mains[0]);
81    assertEquals(20001, counter);
82  }
83
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
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
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
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
104  public static Class<?> testInvokeInterface(Itf i) {
105    return i.sameInvokeInterface();
106  }
107
108  public static Class<?> 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
116  public static Class<?> testInvokeVirtual(Main m) {
117    return m.sameInvokeVirtual();
118  }
119
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
127  public static native void ensureJittedAndPolymorphicInline566();
128  public static native void ensureProfilingInfo566();
129
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
138class Subclass extends Main {
139}
140
141class OtherSubclass extends Main {
142  public Class<?> sameInvokeVirtual() {
143    return OtherSubclass.class;
144  }
145
146  public Class<?> sameInvokeInterface() {
147    return OtherSubclass.class;
148  }
149
150  public Class<?> sameInvokeInterface2() {
151    return null;
152  }
153  public Class<?> sameInvokeInterface3() {
154    return null;
155  }
156}
157