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