test/compiler/whitebox/CompilerWhiteBoxTest.java

Wed, 22 Jan 2014 12:37:28 -0800

author
katleman
date
Wed, 22 Jan 2014 12:37:28 -0800
changeset 6575
2bac854670c0
parent 5983
600c83f8e6a5
child 6211
d1760952ebdd
permissions
-rw-r--r--

Added tag jdk8u5-b05 for changeset b90de55aca30

     1 /*
     2  * Copyright (c) 2013, 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.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  */
    24 import com.sun.management.HotSpotDiagnosticMXBean;
    25 import com.sun.management.VMOption;
    26 import sun.hotspot.WhiteBox;
    27 import sun.management.ManagementFactoryHelper;
    29 import java.lang.reflect.Constructor;
    30 import java.lang.reflect.Executable;
    31 import java.lang.reflect.Method;
    32 import java.util.Objects;
    33 import java.util.concurrent.Callable;
    35 /**
    36  * Abstract class for WhiteBox testing of JIT.
    37  *
    38  * @author igor.ignatyev@oracle.com
    39  */
    40 public abstract class CompilerWhiteBoxTest {
    41     /** {@code CompLevel::CompLevel_none} -- Interpreter */
    42     protected static int COMP_LEVEL_NONE = 0;
    43     /** {@code CompLevel::CompLevel_any}, {@code CompLevel::CompLevel_all} */
    44     protected static int COMP_LEVEL_ANY = -1;
    45     /** {@code CompLevel::CompLevel_simple} -- C1 */
    46     protected static int COMP_LEVEL_SIMPLE = 1;
    47     /** {@code CompLevel::CompLevel_limited_profile} -- C1, invocation & backedge counters */
    48     protected static int COMP_LEVEL_LIMITED_PROFILE = 2;
    49     /** {@code CompLevel::CompLevel_full_profile} -- C1, invocation & backedge counters + mdo */
    50     protected static int COMP_LEVEL_FULL_PROFILE = 3;
    51     /** {@code CompLevel::CompLevel_full_optimization} -- C2 or Shark */
    52     protected static int COMP_LEVEL_FULL_OPTIMIZATION = 4;
    53     /** Maximal value for CompLeveL */
    54     protected static int COMP_LEVEL_MAX = COMP_LEVEL_FULL_OPTIMIZATION;
    56     /** Instance of WhiteBox */
    57     protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
    58     /** Value of {@code -XX:CompileThreshold} */
    59     protected static final int COMPILE_THRESHOLD
    60             = Integer.parseInt(getVMOption("CompileThreshold", "10000"));
    61     /** Value of {@code -XX:BackgroundCompilation} */
    62     protected static final boolean BACKGROUND_COMPILATION
    63             = Boolean.valueOf(getVMOption("BackgroundCompilation", "true"));
    64     /** Value of {@code -XX:TieredCompilation} */
    65     protected static final boolean TIERED_COMPILATION
    66             = Boolean.valueOf(getVMOption("TieredCompilation", "false"));
    67     /** Value of {@code -XX:TieredStopAtLevel} */
    68     protected static final int TIERED_STOP_AT_LEVEL
    69             = Integer.parseInt(getVMOption("TieredStopAtLevel", "0"));
    70     /** Flag for verbose output, true if {@code -Dverbose} specified */
    71     protected static final boolean IS_VERBOSE
    72             = System.getProperty("verbose") != null;
    73     /** count of invocation to triger compilation */
    74     protected static final int THRESHOLD;
    75     /** count of invocation to triger OSR compilation */
    76     protected static final long BACKEDGE_THRESHOLD;
    77     /** Value of {@code java.vm.info} (interpreted|mixed|comp mode) */
    78     protected static final String MODE
    79             = System.getProperty("java.vm.info");
    81     static {
    82         if (TIERED_COMPILATION) {
    83             BACKEDGE_THRESHOLD = THRESHOLD = 150000;
    84         } else {
    85             THRESHOLD = COMPILE_THRESHOLD;
    86             BACKEDGE_THRESHOLD = COMPILE_THRESHOLD * Long.parseLong(getVMOption(
    87                     "OnStackReplacePercentage"));
    88         }
    89     }
    91     /**
    92      * Returns value of VM option.
    93      *
    94      * @param name option's name
    95      * @return value of option or {@code null}, if option doesn't exist
    96      * @throws NullPointerException if name is null
    97      */
    98     protected static String getVMOption(String name) {
    99         Objects.requireNonNull(name);
   100         HotSpotDiagnosticMXBean diagnostic
   101                 = ManagementFactoryHelper.getDiagnosticMXBean();
   102         VMOption tmp;
   103         try {
   104             tmp = diagnostic.getVMOption(name);
   105         } catch (IllegalArgumentException e) {
   106             tmp = null;
   107         }
   108         return (tmp == null ? null : tmp.getValue());
   109     }
   111     /**
   112      * Returns value of VM option or default value.
   113      *
   114      * @param name         option's name
   115      * @param defaultValue default value
   116      * @return value of option or {@code defaultValue}, if option doesn't exist
   117      * @throws NullPointerException if name is null
   118      * @see #getVMOption(String)
   119      */
   120     protected static String getVMOption(String name, String defaultValue) {
   121         String result = getVMOption(name);
   122         return result == null ? defaultValue : result;
   123     }
   125     /** copy of is_c1_compile(int) from utilities/globalDefinitions.hpp */
   126     protected static boolean isC1Compile(int compLevel) {
   127         return (compLevel > COMP_LEVEL_NONE)
   128                 && (compLevel < COMP_LEVEL_FULL_OPTIMIZATION);
   129     }
   131     /** copy of is_c2_compile(int) from utilities/globalDefinitions.hpp */
   132     protected static boolean isC2Compile(int compLevel) {
   133         return compLevel == COMP_LEVEL_FULL_OPTIMIZATION;
   134     }
   136     /** tested method */
   137     protected final Executable method;
   138     protected final TestCase testCase;
   140     /**
   141      * Constructor.
   142      *
   143      * @param testCase object, that contains tested method and way to invoke it.
   144      */
   145     protected CompilerWhiteBoxTest(TestCase testCase) {
   146         Objects.requireNonNull(testCase);
   147         System.out.println("TEST CASE:" + testCase.name());
   148         method = testCase.executable;
   149         this.testCase = testCase;
   150     }
   152     /**
   153      * Template method for testing. Prints tested method's info before
   154      * {@linkplain #test()} and after {@linkplain #test()} or on thrown
   155      * exception.
   156      *
   157      * @throws RuntimeException if method {@linkplain #test()} throws any
   158      *                          exception
   159      * @see #test()
   160      */
   161     protected final void runTest() {
   162         if (ManagementFactoryHelper.getCompilationMXBean() == null) {
   163             System.err.println(
   164                     "Warning: test is not applicable in interpreted mode");
   165             return;
   166         }
   167         System.out.println("at test's start:");
   168         printInfo();
   169         try {
   170             test();
   171         } catch (Exception e) {
   172             System.out.printf("on exception '%s':", e.getMessage());
   173             printInfo();
   174             e.printStackTrace();
   175             if (e instanceof RuntimeException) {
   176                 throw (RuntimeException) e;
   177             }
   178             throw new RuntimeException(e);
   179         }
   180         System.out.println("at test's end:");
   181         printInfo();
   182     }
   184     /**
   185      * Checks, that {@linkplain #method} is not compiled.
   186      *
   187      * @throws RuntimeException if {@linkplain #method} is in compiler queue or
   188      *                          is compiled, or if {@linkplain #method} has zero
   189      *                          compilation level.
   190      */
   191     protected final void checkNotCompiled() {
   192         if (WHITE_BOX.isMethodQueuedForCompilation(method)) {
   193             throw new RuntimeException(method + " must not be in queue");
   194         }
   195         if (WHITE_BOX.isMethodCompiled(method, false)) {
   196             throw new RuntimeException(method + " must be not compiled");
   197         }
   198         if (WHITE_BOX.getMethodCompilationLevel(method, false) != 0) {
   199             throw new RuntimeException(method + " comp_level must be == 0");
   200         }
   201         if (WHITE_BOX.isMethodCompiled(method, true)) {
   202             throw new RuntimeException(method + " must be not osr_compiled");
   203         }
   204         if (WHITE_BOX.getMethodCompilationLevel(method, true) != 0) {
   205             throw new RuntimeException(method + " osr_comp_level must be == 0");
   206         }
   207    }
   209     /**
   210      * Checks, that {@linkplain #method} is compiled.
   211      *
   212      * @throws RuntimeException if {@linkplain #method} isn't in compiler queue
   213      *                          and isn't compiled, or if {@linkplain #method}
   214      *                          has nonzero compilation level
   215      */
   216     protected final void checkCompiled() {
   217         final long start = System.currentTimeMillis();
   218         waitBackgroundCompilation();
   219         if (WHITE_BOX.isMethodQueuedForCompilation(method)) {
   220             System.err.printf("Warning: %s is still in queue after %dms%n",
   221                     method, System.currentTimeMillis() - start);
   222             return;
   223         }
   224         if (!WHITE_BOX.isMethodCompiled(method, testCase.isOsr)) {
   225             throw new RuntimeException(method + " must be "
   226                     + (testCase.isOsr ? "osr_" : "") + "compiled");
   227         }
   228         if (WHITE_BOX.getMethodCompilationLevel(method, testCase.isOsr) == 0) {
   229             throw new RuntimeException(method
   230                     + (testCase.isOsr ? " osr_" : " ")
   231                     + "comp_level must be != 0");
   232         }
   233     }
   235     protected final void deoptimize() {
   236         WHITE_BOX.deoptimizeMethod(method, testCase.isOsr);
   237         if (testCase.isOsr) {
   238             WHITE_BOX.deoptimizeMethod(method, false);
   239         }
   240     }
   242     protected final int getCompLevel() {
   243         return WHITE_BOX.getMethodCompilationLevel(method, testCase.isOsr);
   244     }
   246     protected final boolean isCompilable() {
   247         return WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY,
   248                 testCase.isOsr);
   249     }
   251     protected final boolean isCompilable(int compLevel) {
   252         return WHITE_BOX.isMethodCompilable(method, compLevel, testCase.isOsr);
   253     }
   255     protected final void makeNotCompilable() {
   256         WHITE_BOX.makeMethodNotCompilable(method, COMP_LEVEL_ANY,
   257                 testCase.isOsr);
   258     }
   260     protected final void makeNotCompilable(int compLevel) {
   261         WHITE_BOX.makeMethodNotCompilable(method, compLevel, testCase.isOsr);
   262     }
   264     /**
   265      * Waits for completion of background compilation of {@linkplain #method}.
   266      */
   267     protected final void waitBackgroundCompilation() {
   268         if (!BACKGROUND_COMPILATION) {
   269             return;
   270         }
   271         final Object obj = new Object();
   272         for (int i = 0; i < 10
   273                 && WHITE_BOX.isMethodQueuedForCompilation(method); ++i) {
   274             synchronized (obj) {
   275                 try {
   276                     obj.wait(1000);
   277                 } catch (InterruptedException e) {
   278                     Thread.currentThread().interrupt();
   279                 }
   280             }
   281         }
   282     }
   284     /**
   285      * Prints information about {@linkplain #method}.
   286      */
   287     protected final void printInfo() {
   288         System.out.printf("%n%s:%n", method);
   289         System.out.printf("\tcompilable:\t%b%n",
   290                 WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY, false));
   291         System.out.printf("\tcompiled:\t%b%n",
   292                 WHITE_BOX.isMethodCompiled(method, false));
   293         System.out.printf("\tcomp_level:\t%d%n",
   294                 WHITE_BOX.getMethodCompilationLevel(method, false));
   295         System.out.printf("\tosr_compilable:\t%b%n",
   296                 WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY, true));
   297         System.out.printf("\tosr_compiled:\t%b%n",
   298                 WHITE_BOX.isMethodCompiled(method, true));
   299         System.out.printf("\tosr_comp_level:\t%d%n",
   300                 WHITE_BOX.getMethodCompilationLevel(method, true));
   301          System.out.printf("\tin_queue:\t%b%n",
   302                 WHITE_BOX.isMethodQueuedForCompilation(method));
   303         System.out.printf("compile_queues_size:\t%d%n%n",
   304                 WHITE_BOX.getCompileQueuesSize());
   305     }
   307     /**
   308      * Executes testing.
   309      */
   310     protected abstract void test() throws Exception;
   312     /**
   313      * Tries to trigger compilation of {@linkplain #method} by call
   314      * {@linkplain #testCase.callable} enough times.
   315      *
   316      * @return accumulated result
   317      * @see #compile(int)
   318      */
   319     protected final int compile() {
   320         if (testCase.isOsr) {
   321             return compile(1);
   322         } else {
   323             return compile(THRESHOLD);
   324         }
   325     }
   327     /**
   328      * Tries to trigger compilation of {@linkplain #method} by call
   329      * {@linkplain #testCase.callable} specified times.
   330      *
   331      * @param count invocation count
   332      * @return accumulated result
   333      */
   334     protected final int compile(int count) {
   335         int result = 0;
   336         Integer tmp;
   337         for (int i = 0; i < count; ++i) {
   338             try {
   339                 tmp = testCase.callable.call();
   340             } catch (Exception e) {
   341                 tmp = null;
   342             }
   343             result += tmp == null ? 0 : tmp;
   344         }
   345         if (IS_VERBOSE) {
   346             System.out.println("method was invoked " + count + " times");
   347         }
   348         return result;
   349     }
   350 }
   352 /**
   353  * Utility structure containing tested method and object to invoke it.
   354  */
   355 enum TestCase {
   356     /** constructor test case */
   357     CONSTRUCTOR_TEST(Helper.CONSTRUCTOR, Helper.CONSTRUCTOR_CALLABLE, false),
   358     /** method test case */
   359     METOD_TEST(Helper.METHOD, Helper.METHOD_CALLABLE, false),
   360     /** static method test case */
   361     STATIC_TEST(Helper.STATIC, Helper.STATIC_CALLABLE, false),
   363     /** OSR constructor test case */
   364     OSR_CONSTRUCTOR_TEST(Helper.OSR_CONSTRUCTOR,
   365             Helper.OSR_CONSTRUCTOR_CALLABLE, true),
   366     /** OSR method test case */
   367     OSR_METOD_TEST(Helper.OSR_METHOD, Helper.OSR_METHOD_CALLABLE, true),
   368     /** OSR static method test case */
   369     OSR_STATIC_TEST(Helper.OSR_STATIC, Helper.OSR_STATIC_CALLABLE, true);
   371     /** tested method */
   372     final Executable executable;
   373     /** object to invoke {@linkplain #executable} */
   374     final Callable<Integer> callable;
   375     /** flag for OSR test case */
   376     final boolean isOsr;
   378     private TestCase(Executable executable, Callable<Integer> callable,
   379             boolean isOsr) {
   380         this.executable = executable;
   381         this.callable = callable;
   382         this.isOsr = isOsr;
   383     }
   385     private static class Helper {
   387         private static final Callable<Integer> CONSTRUCTOR_CALLABLE
   388                 = new Callable<Integer>() {
   389             @Override
   390             public Integer call() throws Exception {
   391                 return new Helper(1337).hashCode();
   392             }
   393         };
   395         private static final Callable<Integer> METHOD_CALLABLE
   396                 = new Callable<Integer>() {
   397             private final Helper helper = new Helper();
   399             @Override
   400             public Integer call() throws Exception {
   401                 return helper.method();
   402             }
   403         };
   405         private static final Callable<Integer> STATIC_CALLABLE
   406                 = new Callable<Integer>() {
   407             @Override
   408             public Integer call() throws Exception {
   409                 return staticMethod();
   410             }
   411         };
   413         private static final Callable<Integer> OSR_CONSTRUCTOR_CALLABLE
   414                 = new Callable<Integer>() {
   415             @Override
   416             public Integer call() throws Exception {
   417                 return new Helper(null).hashCode();
   418             }
   419         };
   421         private static final Callable<Integer> OSR_METHOD_CALLABLE
   422                 = new Callable<Integer>() {
   423             private final Helper helper = new Helper();
   425             @Override
   426             public Integer call() throws Exception {
   427                 return helper.osrMethod();
   428             }
   429         };
   431         private static final Callable<Integer> OSR_STATIC_CALLABLE
   432                 = new Callable<Integer>() {
   433             @Override
   434             public Integer call() throws Exception {
   435                 return osrStaticMethod();
   436             }
   437         };
   440         private static final Constructor CONSTRUCTOR;
   441         private static final Constructor OSR_CONSTRUCTOR;
   442         private static final Method METHOD;
   443         private static final Method STATIC;
   444         private static final Method OSR_METHOD;
   445         private static final Method OSR_STATIC;
   447         static {
   448             try {
   449                 CONSTRUCTOR = Helper.class.getDeclaredConstructor(int.class);
   450             } catch (NoSuchMethodException | SecurityException e) {
   451                 throw new RuntimeException(
   452                         "exception on getting method Helper.<init>(int)", e);
   453             }
   454             try {
   455                 OSR_CONSTRUCTOR = Helper.class.getDeclaredConstructor(
   456                         Object.class);
   457             } catch (NoSuchMethodException | SecurityException e) {
   458                 throw new RuntimeException(
   459                         "exception on getting method Helper.<init>(Object)", e);
   460             }
   461             METHOD = getMethod("method");
   462             STATIC = getMethod("staticMethod");
   463             OSR_METHOD = getMethod("osrMethod");
   464             OSR_STATIC = getMethod("osrStaticMethod");
   465         }
   467         private static Method getMethod(String name) {
   468             try {
   469                 return Helper.class.getDeclaredMethod(name);
   470             } catch (NoSuchMethodException | SecurityException e) {
   471                 throw new RuntimeException(
   472                         "exception on getting method Helper." + name, e);
   473             }
   475         }
   477         private static int staticMethod() {
   478             return 1138;
   479         }
   481         private int method() {
   482             return 42;
   483         }
   485         private static int osrStaticMethod() {
   486             int result = 0;
   487             for (long i = 0; i < CompilerWhiteBoxTest.BACKEDGE_THRESHOLD; ++i) {
   488                 result += staticMethod();
   489             }
   490             return result;
   491         }
   493         private int osrMethod() {
   494             int result = 0;
   495             for (long i = 0; i < CompilerWhiteBoxTest.BACKEDGE_THRESHOLD; ++i) {
   496                 result += method();
   497             }
   498             return result;
   499         }
   501         private final int x;
   503         // for method and OSR method test case
   504         public Helper() {
   505             x = 0;
   506         }
   508         // for OSR constructor test case
   509         private Helper(Object o) {
   510             int result = 0;
   511             for (long i = 0; i < CompilerWhiteBoxTest.BACKEDGE_THRESHOLD; ++i) {
   512                 result += method();
   513             }
   514             x = result;
   515         }
   517         // for constructor test case
   518         private Helper(int x) {
   519             this.x = x;
   520         }
   522         @Override
   523         public int hashCode() {
   524             return x;
   525         }
   526     }
   527 }

mercurial