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