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