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