test/compiler/types/TypeSpeculation.java

Wed, 23 Oct 2013 12:40:23 +0200

author
roland
date
Wed, 23 Oct 2013 12:40:23 +0200
changeset 5991
b2ee5dc63353
child 6212
29463147336b
permissions
-rw-r--r--

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

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

mercurial