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 }