comparison test/compiler/types/TypeSpeculation.java @ 12966:b2ee5dc63353

8024070: C2 needs some form of type speculation Summary: record unused type profile information with type system, propagate and use it. Reviewed-by: kvn, twisti
author roland
date Wed, 23 Oct 2013 12:40:23 +0200
parents
children 1891b98ded49
comparison
equal deleted inserted replaced
12965:8b4bbba322d3 12966:b2ee5dc63353
1 /*
2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /*
25 * @test
26 * @bug 8024070
27 * @summary Test that type speculation doesn't cause incorrect execution
28 * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:TypeProfileLevel=222 TypeSpeculation
29 *
30 */
31
32 public class TypeSpeculation {
33
34 interface I {
35 }
36
37 static class A {
38 int m() {
39 return 1;
40 }
41 }
42
43 static class B extends A implements I {
44 int m() {
45 return 2;
46 }
47 }
48
49 static class C extends B {
50 int m() {
51 return 3;
52 }
53 }
54
55 static int test1_invokevirtual(A a) {
56 return a.m();
57 }
58
59 static int test1_1(A a) {
60 return test1_invokevirtual(a);
61 }
62
63 static boolean test1() {
64 A a = new A();
65 B b = new B();
66 C c = new C();
67
68 // pollute profile at test1_invokevirtual to make sure the
69 // compiler cannot rely on it
70 for (int i = 0; i < 5000; i++) {
71 test1_invokevirtual(a);
72 test1_invokevirtual(b);
73 test1_invokevirtual(c);
74 }
75
76 // profiling + speculation should make test1_invokevirtual
77 // inline A.m() with a guard
78 for (int i = 0; i < 20000; i++) {
79 int res = test1_1(b);
80 if (res != b.m()) {
81 System.out.println("test1 failed with class B");
82 return false;
83 }
84 }
85 // check that the guard works as expected by passing a
86 // different type
87 int res = test1_1(a);
88 if (res != a.m()) {
89 System.out.println("test1 failed with class A");
90 return false;
91 }
92 return true;
93 }
94
95 static int test2_invokevirtual(A a) {
96 return a.m();
97 }
98
99 static int test2_1(A a, boolean t) {
100 A aa;
101 if (t) {
102 aa = (B)a;
103 } else {
104 aa = a;
105 }
106 // if a of type B is passed to test2_1, the static type of aa
107 // here is no better than A but the profiled type is B so this
108 // should inline
109 return test2_invokevirtual(aa);
110 }
111
112 static boolean test2() {
113 A a = new A();
114 B b = new B();
115 C c = new C();
116
117 // pollute profile at test2_invokevirtual to make sure the
118 // compiler cannot rely on it
119 for (int i = 0; i < 5000; i++) {
120 test2_invokevirtual(a);
121 test2_invokevirtual(b);
122 test2_invokevirtual(c);
123 }
124
125 // profiling + speculation should make test2_invokevirtual
126 // inline A.m() with a guard
127 for (int i = 0; i < 20000; i++) {
128 int res = test2_1(b, (i % 2) == 0);
129 if (res != b.m()) {
130 System.out.println("test2 failed with class B");
131 return false;
132 }
133 }
134 // check that the guard works as expected by passing a
135 // different type
136 int res = test2_1(a, false);
137 if (res != a.m()) {
138 System.out.println("test2 failed with class A");
139 return false;
140 }
141 return true;
142 }
143
144 static int test3_invokevirtual(A a) {
145 return a.m();
146 }
147
148 static void test3_2(A a) {
149 }
150
151 static int test3_1(A a, int i) {
152 if (i == 0) {
153 return 0;
154 }
155 // If we come here and a is of type B but parameter profiling
156 // is polluted, both branches of the if below should have
157 // profiling that tell us and inlining of the virtual call
158 // should happen
159 if (i == 1) {
160 test3_2(a);
161 } else {
162 test3_2(a);
163 }
164 return test3_invokevirtual(a);
165 }
166
167 static boolean test3() {
168 A a = new A();
169 B b = new B();
170 C c = new C();
171
172 // pollute profile at test3_invokevirtual and test3_1 to make
173 // sure the compiler cannot rely on it
174 for (int i = 0; i < 3000; i++) {
175 test3_invokevirtual(a);
176 test3_invokevirtual(b);
177 test3_invokevirtual(c);
178 test3_1(a, 0);
179 test3_1(b, 0);
180 }
181
182 // profiling + speculation should make test3_invokevirtual
183 // inline A.m() with a guard
184 for (int i = 0; i < 20000; i++) {
185 int res = test3_1(b, (i % 2) + 1);
186 if (res != b.m()) {
187 System.out.println("test3 failed with class B");
188 return false;
189 }
190 }
191 // check that the guard works as expected by passing a
192 // different type
193 int res = test3_1(a, 1);
194 if (res != a.m()) {
195 System.out.println("test3 failed with class A");
196 return false;
197 }
198 return true;
199 }
200
201 // Mix 2 incompatible profiled types
202 static int test4_invokevirtual(A a) {
203 return a.m();
204 }
205
206 static void test4_2(A a) {
207 }
208
209 static int test4_1(A a, boolean b) {
210 if (b) {
211 test4_2(a);
212 } else {
213 test4_2(a);
214 }
215 // shouldn't inline
216 return test4_invokevirtual(a);
217 }
218
219 static boolean test4() {
220 A a = new A();
221 B b = new B();
222 C c = new C();
223
224 // pollute profile at test3_invokevirtual and test3_1 to make
225 // sure the compiler cannot rely on it
226 for (int i = 0; i < 3000; i++) {
227 test4_invokevirtual(a);
228 test4_invokevirtual(b);
229 test4_invokevirtual(c);
230 }
231
232 for (int i = 0; i < 20000; i++) {
233 if ((i % 2) == 0) {
234 int res = test4_1(a, true);
235 if (res != a.m()) {
236 System.out.println("test4 failed with class A");
237 return false;
238 }
239 } else {
240 int res = test4_1(b, false);
241 if (res != b.m()) {
242 System.out.println("test4 failed with class B");
243 return false;
244 }
245 }
246 }
247 return true;
248 }
249
250 // Mix one profiled type with an incompatible type
251 static int test5_invokevirtual(A a) {
252 return a.m();
253 }
254
255 static void test5_2(A a) {
256 }
257
258 static int test5_1(A a, boolean b) {
259 if (b) {
260 test5_2(a);
261 } else {
262 A aa = (B)a;
263 }
264 // shouldn't inline
265 return test5_invokevirtual(a);
266 }
267
268 static boolean test5() {
269 A a = new A();
270 B b = new B();
271 C c = new C();
272
273 // pollute profile at test3_invokevirtual and test3_1 to make
274 // sure the compiler cannot rely on it
275 for (int i = 0; i < 3000; i++) {
276 test5_invokevirtual(a);
277 test5_invokevirtual(b);
278 test5_invokevirtual(c);
279 }
280
281 for (int i = 0; i < 20000; i++) {
282 if ((i % 2) == 0) {
283 int res = test5_1(a, true);
284 if (res != a.m()) {
285 System.out.println("test5 failed with class A");
286 return false;
287 }
288 } else {
289 int res = test5_1(b, false);
290 if (res != b.m()) {
291 System.out.println("test5 failed with class B");
292 return false;
293 }
294 }
295 }
296 return true;
297 }
298
299 // Mix incompatible profiled types
300 static void test6_2(Object o) {
301 }
302
303 static Object test6_1(Object o, boolean b) {
304 if (b) {
305 test6_2(o);
306 } else {
307 test6_2(o);
308 }
309 return o;
310 }
311
312 static boolean test6() {
313 A a = new A();
314 A[] aa = new A[10];
315
316 for (int i = 0; i < 20000; i++) {
317 if ((i % 2) == 0) {
318 test6_1(a, true);
319 } else {
320 test6_1(aa, false);
321 }
322 }
323 return true;
324 }
325
326 // Mix a profiled type with an incompatible type
327 static void test7_2(Object o) {
328 }
329
330 static Object test7_1(Object o, boolean b) {
331 if (b) {
332 test7_2(o);
333 } else {
334 Object oo = (A[])o;
335 }
336 return o;
337 }
338
339 static boolean test7() {
340 A a = new A();
341 A[] aa = new A[10];
342
343 for (int i = 0; i < 20000; i++) {
344 if ((i % 2) == 0) {
345 test7_1(a, true);
346 } else {
347 test7_1(aa, false);
348 }
349 }
350 return true;
351 }
352
353 // Mix a profiled type with an interface
354 static void test8_2(Object o) {
355 }
356
357 static I test8_1(Object o) {
358 test8_2(o);
359 return (I)o;
360 }
361
362 static boolean test8() {
363 A a = new A();
364 B b = new B();
365 C c = new C();
366
367 for (int i = 0; i < 20000; i++) {
368 test8_1(b);
369 }
370 return true;
371 }
372
373 // Mix a profiled type with a constant
374 static void test9_2(Object o) {
375 }
376
377 static Object test9_1(Object o, boolean b) {
378 Object oo;
379 if (b) {
380 test9_2(o);
381 oo = o;
382 } else {
383 oo = "some string";
384 }
385 return oo;
386 }
387
388 static boolean test9() {
389 A a = new A();
390
391 for (int i = 0; i < 20000; i++) {
392 if ((i % 2) == 0) {
393 test9_1(a, true);
394 } else {
395 test9_1(a, false);
396 }
397 }
398 return true;
399 }
400
401 static public void main(String[] args) {
402 boolean success = true;
403
404 success = test1() && success;
405
406 success = test2() && success;
407
408 success = test3() && success;
409
410 success = test4() && success;
411
412 success = test5() && success;
413
414 success = test6() && success;
415
416 success = test7() && success;
417
418 success = test8() && success;
419
420 success = test9() && success;
421
422 if (success) {
423 System.out.println("TEST PASSED");
424 } else {
425 throw new RuntimeException("TEST FAILED: erroneous bound check elimination");
426 }
427 }
428 }