OSDN Git Service

Fix a bug in ClassTableGet code generation for IMTs.
[android-x86/art.git] / test / 566-polymorphic-inlining / src / Main.java
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 {
18   public Class sameInvokeInterface();
19   public Class sameInvokeInterface2();
20   public Class sameInvokeInterface3();
21 }
22
23 public 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     // Make testInvokeVirtual and testInvokeInterface hot to get them jitted.
45     // We pass Main and Subclass to get polymorphic inlining based on calling
46     // the same method.
47     for (int i = 0; i < 10000; ++i) {
48       testInvokeVirtual(mains[0]);
49       testInvokeVirtual(mains[1]);
50       testInvokeInterface(itfs[0]);
51       testInvokeInterface(itfs[1]);
52       testInvokeInterface2(itfs[0]);
53       testInvokeInterface2(itfs[1]);
54       $noinline$testInlineToSameTarget(mains[0]);
55       $noinline$testInlineToSameTarget(mains[1]);
56     }
57
58     ensureJittedAndPolymorphicInline();
59
60     // At this point, the JIT should have compiled both methods, and inline
61     // sameInvokeVirtual and sameInvokeInterface.
62     assertEquals(Main.class, testInvokeVirtual(mains[0]));
63     assertEquals(Main.class, testInvokeVirtual(mains[1]));
64
65     assertEquals(Itf.class, testInvokeInterface(itfs[0]));
66     assertEquals(Itf.class, testInvokeInterface(itfs[1]));
67
68     assertEquals(Itf.class, testInvokeInterface2(itfs[0]));
69     assertEquals(Itf.class, testInvokeInterface2(itfs[1]));
70
71     // This will trigger a deoptimization of the compiled code.
72     assertEquals(OtherSubclass.class, testInvokeVirtual(mains[2]));
73     assertEquals(OtherSubclass.class, testInvokeInterface(itfs[2]));
74     assertEquals(null, testInvokeInterface2(itfs[2]));
75
76     // Run this once to make sure we execute the JITted code.
77     $noinline$testInlineToSameTarget(mains[0]);
78     assertEquals(20001, counter);
79   }
80
81   public Class sameInvokeVirtual() {
82     field.getClass(); // null check to ensure we get an inlined frame in the CodeInfo
83     return Main.class;
84   }
85
86   public Class sameInvokeInterface() {
87     field.getClass(); // null check to ensure we get an inlined frame in the CodeInfo
88     return Itf.class;
89   }
90
91   public Class sameInvokeInterface2() {
92     field.getClass(); // null check to ensure we get an inlined frame in the CodeInfo.
93     return Itf.class;
94   }
95
96   public Class sameInvokeInterface3() {
97     field.getClass(); // null check to ensure we get an inlined frame in the CodeInfo.
98     return Itf.class;
99   }
100
101   public static Class testInvokeInterface(Itf i) {
102     return i.sameInvokeInterface();
103   }
104
105   public static Class testInvokeInterface2(Itf i) {
106     // Make three interface calls that will do a ClassTableGet to ensure bogus code
107     // generation of ClassTableGet will crash.
108     i.sameInvokeInterface();
109     i.sameInvokeInterface2();
110     return i.sameInvokeInterface3();
111   }
112
113   public static Class testInvokeVirtual(Main m) {
114     return m.sameInvokeVirtual();
115   }
116
117   public static void $noinline$testInlineToSameTarget(Main m) {
118     if (doThrow) throw new Error("");
119     m.increment();
120   }
121
122   public Object field = new Object();
123
124   public static native void ensureJittedAndPolymorphicInline();
125
126   public void increment() {
127     counter++;
128   }
129   public static int counter = 0;
130   public static boolean doThrow = false;
131 }
132
133 class Subclass extends Main {
134 }
135
136 class OtherSubclass extends Main {
137   public Class sameInvokeVirtual() {
138     return OtherSubclass.class;
139   }
140
141   public Class sameInvokeInterface() {
142     return OtherSubclass.class;
143   }
144
145   public Class sameInvokeInterface2() {
146     return null;
147   }
148   public Class sameInvokeInterface3() {
149     return null;
150   }
151 }