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