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