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 }