1 /* 2 * Copyright (c) 2014, 2018, 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 TestStableInt 26 * @summary tests on stable fields and arrays 27 * @library /test/lib / 28 * @modules java.base/jdk.internal.misc 29 * @modules java.base/jdk.internal.vm.annotation 30 * @build sun.hotspot.WhiteBox 31 * 32 * @run main/bootclasspath/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp 33 * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 34 * -XX:-TieredCompilation 35 * -XX:+FoldStableValues 36 * compiler.stable.TestStableInt 37 * @run main/bootclasspath/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp 38 * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 39 * -XX:-TieredCompilation 40 * -XX:-FoldStableValues 41 * compiler.stable.TestStableInt 42 * 43 * @run main/bootclasspath/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp 44 * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 45 * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 46 * -XX:+FoldStableValues 47 * compiler.stable.TestStableInt 48 * @run main/bootclasspath/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp 49 * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 50 * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 51 * -XX:-FoldStableValues 52 * compiler.stable.TestStableInt 53 */ 54 55 package compiler.stable; 56 57 import jdk.internal.vm.annotation.Stable; 58 59 import java.lang.reflect.InvocationTargetException; 60 61 public class TestStableInt { 62 static final boolean isStableEnabled = StableConfiguration.isStableEnabled; 63 main(String[] args)64 public static void main(String[] args) throws Exception { 65 run(DefaultValue.class); 66 run(IntStable.class); 67 run(DefaultStaticValue.class); 68 run(StaticIntStable.class); 69 run(VolatileIntStable.class); 70 71 // @Stable arrays: Dim 1-4 72 run(IntArrayDim1.class); 73 run(IntArrayDim2.class); 74 run(IntArrayDim3.class); 75 run(IntArrayDim4.class); 76 77 // @Stable Object field: dynamic arrays 78 run(ObjectArrayLowerDim0.class); 79 run(ObjectArrayLowerDim1.class); 80 run(ObjectArrayLowerDim2.class); 81 82 // Nested @Stable fields 83 run(NestedStableField.class); 84 run(NestedStableField1.class); 85 run(NestedStableField2.class); 86 run(NestedStableField3.class); 87 88 if (failed) { 89 throw new Error("TEST FAILED"); 90 } 91 } 92 93 /* ==================================================== */ 94 95 static class DefaultValue { 96 public @Stable int v; 97 98 public static final DefaultValue c = new DefaultValue(); get()99 public static int get() { return c.v; } test()100 public static void test() throws Exception { 101 int val1 = get(); 102 c.v = 1; int val2 = get(); 103 assertEquals(val1, 0); 104 assertEquals(val2, 1); 105 } 106 } 107 108 /* ==================================================== */ 109 110 static class IntStable { 111 public @Stable int v; 112 113 public static final IntStable c = new IntStable(); get()114 public static int get() { return c.v; } test()115 public static void test() throws Exception { 116 c.v = 1; int val1 = get(); 117 c.v = 2; int val2 = get(); 118 assertEquals(val1, 1); 119 assertEquals(val2, (isStableEnabled ? 1 : 2)); 120 } 121 } 122 123 /* ==================================================== */ 124 125 static class DefaultStaticValue { 126 public static @Stable int v; 127 128 public static final DefaultStaticValue c = new DefaultStaticValue(); get()129 public static int get() { return c.v; } test()130 public static void test() throws Exception { 131 int val1 = get(); 132 c.v = 1; int val2 = get(); 133 assertEquals(val1, 0); 134 assertEquals(val2, 1); 135 } 136 } 137 138 /* ==================================================== */ 139 140 static class StaticIntStable { 141 public static @Stable int v; 142 143 public static final StaticIntStable c = new StaticIntStable(); get()144 public static int get() { return c.v; } test()145 public static void test() throws Exception { 146 c.v = 1; int val1 = get(); 147 c.v = 2; int val2 = get(); 148 assertEquals(val1, 1); 149 assertEquals(val2, (isStableEnabled ? 1 : 2)); 150 } 151 } 152 153 /* ==================================================== */ 154 155 static class VolatileIntStable { 156 public @Stable volatile int v; 157 158 public static final VolatileIntStable c = new VolatileIntStable(); get()159 public static int get() { return c.v; } test()160 public static void test() throws Exception { 161 c.v = 1; int val1 = get(); 162 c.v = 2; int val2 = get(); 163 assertEquals(val1, 1); 164 assertEquals(val2, (isStableEnabled ? 1 : 2)); 165 } 166 } 167 168 /* ==================================================== */ 169 // @Stable array == field && all components are stable 170 171 static class IntArrayDim1 { 172 public @Stable int[] v; 173 174 public static final IntArrayDim1 c = new IntArrayDim1(); get()175 public static int get() { return c.v[0]; } get1()176 public static int get1() { return c.v[10]; } get2()177 public static int[] get2() { return c.v; } test()178 public static void test() throws Exception { 179 { 180 c.v = new int[1]; c.v[0] = 1; int val1 = get(); 181 c.v[0] = 2; int val2 = get(); 182 assertEquals(val1, 1); 183 assertEquals(val2, (isStableEnabled ? 1 : 2)); 184 185 c.v = new int[1]; c.v[0] = 3; int val3 = get(); 186 assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) 187 : 3)); 188 } 189 190 { 191 c.v = new int[20]; c.v[10] = 1; int val1 = get1(); 192 c.v[10] = 2; int val2 = get1(); 193 assertEquals(val1, 1); 194 assertEquals(val2, (isStableEnabled ? 1 : 2)); 195 196 c.v = new int[20]; c.v[10] = 3; int val3 = get1(); 197 assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) 198 : 3)); 199 } 200 201 { 202 c.v = new int[1]; int[] val1 = get2(); 203 c.v = new int[1]; int[] val2 = get2(); 204 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 205 } 206 } 207 } 208 209 /* ==================================================== */ 210 211 static class IntArrayDim2 { 212 public @Stable int[][] v; 213 214 public static final IntArrayDim2 c = new IntArrayDim2(); get()215 public static int get() { return c.v[0][0]; } get1()216 public static int[] get1() { return c.v[0]; } get2()217 public static int[][] get2() { return c.v; } test()218 public static void test() throws Exception { 219 { 220 c.v = new int[1][1]; c.v[0][0] = 1; int val1 = get(); 221 c.v[0][0] = 2; int val2 = get(); 222 assertEquals(val1, 1); 223 assertEquals(val2, (isStableEnabled ? 1 : 2)); 224 225 c.v = new int[1][1]; c.v[0][0] = 3; int val3 = get(); 226 assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) 227 : 3)); 228 229 c.v[0] = new int[1]; c.v[0][0] = 4; int val4 = get(); 230 assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) 231 : 4)); 232 } 233 234 { 235 c.v = new int[1][1]; int[] val1 = get1(); 236 c.v[0] = new int[1]; int[] val2 = get1(); 237 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 238 } 239 240 { 241 c.v = new int[1][1]; int[][] val1 = get2(); 242 c.v = new int[1][1]; int[][] val2 = get2(); 243 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 244 } 245 } 246 } 247 248 /* ==================================================== */ 249 250 static class IntArrayDim3 { 251 public @Stable int[][][] v; 252 253 public static final IntArrayDim3 c = new IntArrayDim3(); get()254 public static int get() { return c.v[0][0][0]; } get1()255 public static int[] get1() { return c.v[0][0]; } get2()256 public static int[][] get2() { return c.v[0]; } get3()257 public static int[][][] get3() { return c.v; } test()258 public static void test() throws Exception { 259 { 260 c.v = new int[1][1][1]; c.v[0][0][0] = 1; int val1 = get(); 261 c.v[0][0][0] = 2; int val2 = get(); 262 assertEquals(val1, 1); 263 assertEquals(val2, (isStableEnabled ? 1 : 2)); 264 265 c.v = new int[1][1][1]; c.v[0][0][0] = 3; int val3 = get(); 266 assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) 267 : 3)); 268 269 c.v[0] = new int[1][1]; c.v[0][0][0] = 4; int val4 = get(); 270 assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) 271 : 4)); 272 273 c.v[0][0] = new int[1]; c.v[0][0][0] = 5; int val5 = get(); 274 assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1 : 2) 275 : 5)); 276 } 277 278 { 279 c.v = new int[1][1][1]; int[] val1 = get1(); 280 c.v[0][0] = new int[1]; int[] val2 = get1(); 281 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 282 } 283 284 { 285 c.v = new int[1][1][1]; int[][] val1 = get2(); 286 c.v[0] = new int[1][1]; int[][] val2 = get2(); 287 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 288 } 289 290 { 291 c.v = new int[1][1][1]; int[][][] val1 = get3(); 292 c.v = new int[1][1][1]; int[][][] val2 = get3(); 293 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 294 } 295 } 296 } 297 298 /* ==================================================== */ 299 300 static class IntArrayDim4 { 301 public @Stable int[][][][] v; 302 303 public static final IntArrayDim4 c = new IntArrayDim4(); get()304 public static int get() { return c.v[0][0][0][0]; } get1()305 public static int[] get1() { return c.v[0][0][0]; } get2()306 public static int[][] get2() { return c.v[0][0]; } get3()307 public static int[][][] get3() { return c.v[0]; } get4()308 public static int[][][][] get4() { return c.v; } test()309 public static void test() throws Exception { 310 { 311 c.v = new int[1][1][1][1]; c.v[0][0][0][0] = 1; int val1 = get(); 312 c.v[0][0][0][0] = 2; int val2 = get(); 313 assertEquals(val1, 1); 314 assertEquals(val2, (isStableEnabled ? 1 : 2)); 315 316 c.v = new int[1][1][1][1]; c.v[0][0][0][0] = 3; int val3 = get(); 317 assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) 318 : 3)); 319 320 c.v[0] = new int[1][1][1]; c.v[0][0][0][0] = 4; int val4 = get(); 321 assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) 322 : 4)); 323 324 c.v[0][0] = new int[1][1]; c.v[0][0][0][0] = 5; int val5 = get(); 325 assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1 : 2) 326 : 5)); 327 328 c.v[0][0][0] = new int[1]; c.v[0][0][0][0] = 6; int val6 = get(); 329 assertEquals(val6, (isStableEnabled ? (isStableEnabled ? 1 : 2) 330 : 6)); 331 } 332 333 { 334 c.v = new int[1][1][1][1]; int[] val1 = get1(); 335 c.v[0][0][0] = new int[1]; int[] val2 = get1(); 336 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 337 } 338 339 { 340 c.v = new int[1][1][1][1]; int[][] val1 = get2(); 341 c.v[0][0] = new int[1][1]; int[][] val2 = get2(); 342 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 343 } 344 345 { 346 c.v = new int[1][1][1][1]; int[][][] val1 = get3(); 347 c.v[0] = new int[1][1][1]; int[][][] val2 = get3(); 348 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 349 } 350 351 { 352 c.v = new int[1][1][1][1]; int[][][][] val1 = get4(); 353 c.v = new int[1][1][1][1]; int[][][][] val2 = get4(); 354 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 355 } 356 } 357 } 358 359 /* ==================================================== */ 360 // Dynamic Dim is higher than static 361 static class ObjectArrayLowerDim0 { 362 public @Stable Object v; 363 364 public static final ObjectArrayLowerDim0 c = new ObjectArrayLowerDim0(); get()365 public static int get() { return ((int[])c.v)[0]; } get1()366 public static int[] get1() { return (int[])c.v; } 367 test()368 public static void test() throws Exception { 369 { 370 c.v = new int[1]; ((int[])c.v)[0] = 1; int val1 = get(); 371 ((int[])c.v)[0] = 2; int val2 = get(); 372 373 assertEquals(val1, 1); 374 assertEquals(val2, 2); 375 } 376 377 { 378 c.v = new int[1]; int[] val1 = get1(); 379 c.v = new int[1]; int[] val2 = get1(); 380 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 381 } 382 } 383 } 384 385 /* ==================================================== */ 386 387 static class ObjectArrayLowerDim1 { 388 public @Stable Object[] v; 389 390 public static final ObjectArrayLowerDim1 c = new ObjectArrayLowerDim1(); get()391 public static int get() { return ((int[][])c.v)[0][0]; } get1()392 public static int[] get1() { return (int[])(c.v[0]); } get2()393 public static Object[] get2() { return c.v; } 394 test()395 public static void test() throws Exception { 396 { 397 c.v = new int[1][1]; ((int[][])c.v)[0][0] = 1; int val1 = get(); 398 ((int[][])c.v)[0][0] = 2; int val2 = get(); 399 400 assertEquals(val1, 1); 401 assertEquals(val2, 2); 402 } 403 404 { 405 c.v = new int[1][1]; c.v[0] = new int[0]; int[] val1 = get1(); 406 c.v[0] = new int[0]; int[] val2 = get1(); 407 408 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 409 } 410 411 { 412 c.v = new int[0][0]; Object[] val1 = get2(); 413 c.v = new int[0][0]; Object[] val2 = get2(); 414 415 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 416 } 417 } 418 } 419 420 /* ==================================================== */ 421 422 static class ObjectArrayLowerDim2 { 423 public @Stable Object[][] v; 424 425 public static final ObjectArrayLowerDim2 c = new ObjectArrayLowerDim2(); get()426 public static int get() { return ((int[][][])c.v)[0][0][0]; } get1()427 public static int[] get1() { return (int[])(c.v[0][0]); } get2()428 public static int[][] get2() { return (int[][])(c.v[0]); } get3()429 public static Object[][] get3() { return c.v; } 430 test()431 public static void test() throws Exception { 432 { 433 c.v = new int[1][1][1]; ((int[][][])c.v)[0][0][0] = 1; int val1 = get(); 434 ((int[][][])c.v)[0][0][0] = 2; int val2 = get(); 435 436 assertEquals(val1, 1); 437 assertEquals(val2, 2); 438 } 439 440 { 441 c.v = new int[1][1][1]; c.v[0][0] = new int[0]; int[] val1 = get1(); 442 c.v[0][0] = new int[0]; int[] val2 = get1(); 443 444 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 445 } 446 447 { 448 c.v = new int[1][1][1]; c.v[0] = new int[0][0]; int[][] val1 = get2(); 449 c.v[0] = new int[0][0]; int[][] val2 = get2(); 450 451 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 452 } 453 454 { 455 c.v = new int[0][0][0]; Object[][] val1 = get3(); 456 c.v = new int[0][0][0]; Object[][] val2 = get3(); 457 458 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 459 } 460 } 461 } 462 463 /* ==================================================== */ 464 465 static class NestedStableField { 466 static class A { 467 public @Stable int a; 468 469 } 470 public @Stable A v; 471 472 public static final NestedStableField c = new NestedStableField(); get()473 public static A get() { return c.v; } get1()474 public static int get1() { return get().a; } 475 test()476 public static void test() throws Exception { 477 { 478 c.v = new A(); c.v.a = 1; A val1 = get(); 479 c.v.a = 2; A val2 = get(); 480 481 assertEquals(val1.a, 2); 482 assertEquals(val2.a, 2); 483 } 484 485 { 486 c.v = new A(); c.v.a = 1; int val1 = get1(); 487 c.v.a = 2; int val2 = get1(); 488 c.v = new A(); c.v.a = 3; int val3 = get1(); 489 490 assertEquals(val1, 1); 491 assertEquals(val2, (isStableEnabled ? 1 : 2)); 492 assertEquals(val3, (isStableEnabled ? 1 : 3)); 493 } 494 } 495 } 496 497 /* ==================================================== */ 498 499 static class NestedStableField1 { 500 static class A { 501 public @Stable int a; 502 public @Stable A next; 503 } 504 public @Stable A v; 505 506 public static final NestedStableField1 c = new NestedStableField1(); get()507 public static A get() { return c.v.next.next.next.next.next.next.next; } get1()508 public static int get1() { return get().a; } 509 test()510 public static void test() throws Exception { 511 { 512 c.v = new A(); c.v.next = new A(); c.v.next.next = c.v; 513 c.v.a = 1; c.v.next.a = 1; A val1 = get(); 514 c.v.a = 2; c.v.next.a = 2; A val2 = get(); 515 516 assertEquals(val1.a, 2); 517 assertEquals(val2.a, 2); 518 } 519 520 { 521 c.v = new A(); c.v.next = c.v; 522 c.v.a = 1; int val1 = get1(); 523 c.v.a = 2; int val2 = get1(); 524 c.v = new A(); c.v.next = c.v; 525 c.v.a = 3; int val3 = get1(); 526 527 assertEquals(val1, 1); 528 assertEquals(val2, (isStableEnabled ? 1 : 2)); 529 assertEquals(val3, (isStableEnabled ? 1 : 3)); 530 } 531 } 532 } 533 /* ==================================================== */ 534 535 static class NestedStableField2 { 536 static class A { 537 public @Stable int a; 538 public @Stable A left; 539 public A right; 540 } 541 542 public @Stable A v; 543 544 public static final NestedStableField2 c = new NestedStableField2(); get()545 public static int get() { return c.v.left.left.left.a; } get1()546 public static int get1() { return c.v.left.left.right.left.a; } 547 test()548 public static void test() throws Exception { 549 { 550 c.v = new A(); c.v.left = c.v.right = c.v; 551 c.v.a = 1; int val1 = get(); int val2 = get1(); 552 c.v.a = 2; int val3 = get(); int val4 = get1(); 553 554 assertEquals(val1, 1); 555 assertEquals(val3, (isStableEnabled ? 1 : 2)); 556 557 assertEquals(val2, 1); 558 assertEquals(val4, 2); 559 } 560 } 561 } 562 563 /* ==================================================== */ 564 565 static class NestedStableField3 { 566 static class A { 567 public @Stable int a; 568 public @Stable A[] left; 569 public A[] right; 570 } 571 572 public @Stable A[] v; 573 574 public static final NestedStableField3 c = new NestedStableField3(); get()575 public static int get() { return c.v[0].left[1].left[0].left[1].a; } get1()576 public static int get1() { return c.v[1].left[0].left[1].right[0].left[1].a; } 577 test()578 public static void test() throws Exception { 579 { 580 A elem = new A(); 581 c.v = new A[] { elem, elem }; c.v[0].left = c.v[0].right = c.v; 582 elem.a = 1; int val1 = get(); int val2 = get1(); 583 elem.a = 2; int val3 = get(); int val4 = get1(); 584 585 assertEquals(val1, 1); 586 assertEquals(val3, (isStableEnabled ? 1 : 2)); 587 588 assertEquals(val2, 1); 589 assertEquals(val4, 2); 590 } 591 } 592 } 593 594 /* ==================================================== */ 595 // Auxiliary methods assertEquals(int i, int j)596 static void assertEquals(int i, int j) { if (i != j) throw new AssertionError(i + " != " + j); } assertTrue(boolean b)597 static void assertTrue(boolean b) { if (!b) throw new AssertionError(); } 598 599 static boolean failed = false; 600 run(Class<?> test)601 public static void run(Class<?> test) { 602 Throwable ex = null; 603 System.out.print(test.getName()+": "); 604 try { 605 test.getMethod("test").invoke(null); 606 } catch (InvocationTargetException e) { 607 ex = e.getCause(); 608 } catch (Throwable e) { 609 ex = e; 610 } finally { 611 if (ex == null) { 612 System.out.println("PASSED"); 613 } else { 614 failed = true; 615 System.out.println("FAILED"); 616 ex.printStackTrace(System.out); 617 } 618 } 619 } 620 } 621