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 }