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