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