test/compiler/whitebox/CompilerWhiteBoxTest.java

Wed, 28 Aug 2013 19:25:18 -0400

author
dholmes
date
Wed, 28 Aug 2013 19:25:18 -0400
changeset 5590
2b113b65a051
parent 5541
f99558245e5c
child 5796
303826f477c6
permissions
-rw-r--r--

8023900: [TESTBUG] Initial compact profile test groups need adjusting
Reviewed-by: dcubed, mchung, hseigel

     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;
    78     static {
    79         if (TIERED_COMPILATION) {
    80             THRESHOLD = 150000;
    81             BACKEDGE_THRESHOLD = 0xFFFFFFFFL;
    82         } else {
    83             THRESHOLD = COMPILE_THRESHOLD;
    84             BACKEDGE_THRESHOLD = COMPILE_THRESHOLD * Long.parseLong(getVMOption(
    85                     "OnStackReplacePercentage"));
    86         }
    87     }
    89     /**
    90      * Returns value of VM option.
    91      *
    92      * @param name option's name
    93      * @return value of option or {@code null}, if option doesn't exist
    94      * @throws NullPointerException if name is null
    95      */
    96     protected static String getVMOption(String name) {
    97         Objects.requireNonNull(name);
    98         HotSpotDiagnosticMXBean diagnostic
    99                 = ManagementFactoryHelper.getDiagnosticMXBean();
   100         VMOption tmp;
   101         try {
   102             tmp = diagnostic.getVMOption(name);
   103         } catch (IllegalArgumentException e) {
   104             tmp = null;
   105         }
   106         return (tmp == null ? null : tmp.getValue());
   107     }
   109     /**
   110      * Returns value of VM option or default value.
   111      *
   112      * @param name         option's name
   113      * @param defaultValue default value
   114      * @return value of option or {@code defaultValue}, if option doesn't exist
   115      * @throws NullPointerException if name is null
   116      * @see #getVMOption(String)
   117      */
   118     protected static String getVMOption(String name, String defaultValue) {
   119         String result = getVMOption(name);
   120         return result == null ? defaultValue : result;
   121     }
   123     /** copy of is_c1_compile(int) from utilities/globalDefinitions.hpp */
   124     protected static boolean isC1Compile(int compLevel) {
   125         return (compLevel > COMP_LEVEL_NONE)
   126                 && (compLevel < COMP_LEVEL_FULL_OPTIMIZATION);
   127     }
   129     /** copy of is_c2_compile(int) from utilities/globalDefinitions.hpp */
   130     protected static boolean isC2Compile(int compLevel) {
   131         return compLevel == COMP_LEVEL_FULL_OPTIMIZATION;
   132     }
   134     /** tested method */
   135     protected final Executable method;
   136     protected final TestCase testCase;
   138     /**
   139      * Constructor.
   140      *
   141      * @param testCase object, that contains tested method and way to invoke it.
   142      */
   143     protected CompilerWhiteBoxTest(TestCase testCase) {
   144         Objects.requireNonNull(testCase);
   145         System.out.println("TEST CASE:" + testCase.name());
   146         method = testCase.executable;
   147         this.testCase = testCase;
   148     }
   150     /**
   151      * Template method for testing. Prints tested method's info before
   152      * {@linkplain #test()} and after {@linkplain #test()} or on thrown
   153      * exception.
   154      *
   155      * @throws RuntimeException if method {@linkplain #test()} throws any
   156      *                          exception
   157      * @see #test()
   158      */
   159     protected final void runTest() {
   160         if (ManagementFactoryHelper.getCompilationMXBean() == null) {
   161             System.err.println(
   162                     "Warning: test is not applicable in interpreted mode");
   163             return;
   164         }
   165         System.out.println("at test's start:");
   166         printInfo();
   167         try {
   168             test();
   169         } catch (Exception e) {
   170             System.out.printf("on exception '%s':", e.getMessage());
   171             printInfo();
   172             e.printStackTrace();
   173             if (e instanceof RuntimeException) {
   174                 throw (RuntimeException) e;
   175             }
   176             throw new RuntimeException(e);
   177         }
   178         System.out.println("at test's end:");
   179         printInfo();
   180     }
   182     /**
   183      * Checks, that {@linkplain #method} is not compiled.
   184      *
   185      * @throws RuntimeException if {@linkplain #method} is in compiler queue or
   186      *                          is compiled, or if {@linkplain #method} has zero
   187      *                          compilation level.
   188      */
   189     protected final void checkNotCompiled() {
   190         if (WHITE_BOX.isMethodQueuedForCompilation(method)) {
   191             throw new RuntimeException(method + " must not be in queue");
   192         }
   193         if (WHITE_BOX.isMethodCompiled(method, false)) {
   194             throw new RuntimeException(method + " must be not compiled");
   195         }
   196         if (WHITE_BOX.getMethodCompilationLevel(method, false) != 0) {
   197             throw new RuntimeException(method + " comp_level must be == 0");
   198         }
   199         if (WHITE_BOX.isMethodCompiled(method, true)) {
   200             throw new RuntimeException(method + " must be not osr_compiled");
   201         }
   202         if (WHITE_BOX.getMethodCompilationLevel(method, true) != 0) {
   203             throw new RuntimeException(method + " osr_comp_level must be == 0");
   204         }
   205     }
   207     /**
   208      * Checks, that {@linkplain #method} is compiled.
   209      *
   210      * @throws RuntimeException if {@linkplain #method} isn't in compiler queue
   211      *                          and isn't compiled, or if {@linkplain #method}
   212      *                          has nonzero compilation level
   213      */
   214     protected final void checkCompiled() {
   215         final long start = System.currentTimeMillis();
   216         waitBackgroundCompilation();
   217         if (WHITE_BOX.isMethodQueuedForCompilation(method)) {
   218             System.err.printf("Warning: %s is still in queue after %dms%n",
   219                     method, System.currentTimeMillis() - start);
   220             return;
   221         }
   222         if (!WHITE_BOX.isMethodCompiled(method, testCase.isOsr)) {
   223             throw new RuntimeException(method + " must be "
   224                     + (testCase.isOsr ? "osr_" : "") + "compiled");
   225         }
   226         if (WHITE_BOX.getMethodCompilationLevel(method, testCase.isOsr) == 0) {
   227             throw new RuntimeException(method
   228                     + (testCase.isOsr ? " osr_" : " ")
   229                     + "comp_level must be != 0");
   230         }
   231     }
   233     protected final void deoptimize() {
   234         WHITE_BOX.deoptimizeMethod(method, testCase.isOsr);
   235         if (testCase.isOsr) {
   236             WHITE_BOX.deoptimizeMethod(method, false);
   237         }
   238     }
   240     protected final int getCompLevel() {
   241         return WHITE_BOX.getMethodCompilationLevel(method, testCase.isOsr);
   242     }
   244     protected final boolean isCompilable() {
   245         return WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY,
   246                 testCase.isOsr);
   247     }
   249     protected final boolean isCompilable(int compLevel) {
   250         return WHITE_BOX.isMethodCompilable(method, compLevel, testCase.isOsr);
   251     }
   253     protected final void makeNotCompilable() {
   254         WHITE_BOX.makeMethodNotCompilable(method, COMP_LEVEL_ANY,
   255                 testCase.isOsr);
   256     }
   258     protected final void makeNotCompilable(int compLevel) {
   259         WHITE_BOX.makeMethodNotCompilable(method, compLevel, testCase.isOsr);
   260     }
   262     /**
   263      * Waits for completion of background compilation of {@linkplain #method}.
   264      */
   265     protected final void waitBackgroundCompilation() {
   266         if (!BACKGROUND_COMPILATION) {
   267             return;
   268         }
   269         final Object obj = new Object();
   270         for (int i = 0; i < 10
   271                 && WHITE_BOX.isMethodQueuedForCompilation(method); ++i) {
   272             synchronized (obj) {
   273                 try {
   274                     obj.wait(1000);
   275                 } catch (InterruptedException e) {
   276                     Thread.currentThread().interrupt();
   277                 }
   278             }
   279         }
   280     }
   282     /**
   283      * Prints information about {@linkplain #method}.
   284      */
   285     protected final void printInfo() {
   286         System.out.printf("%n%s:%n", method);
   287         System.out.printf("\tcompilable:\t%b%n",
   288                 WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY, false));
   289         System.out.printf("\tcompiled:\t%b%n",
   290                 WHITE_BOX.isMethodCompiled(method, false));
   291         System.out.printf("\tcomp_level:\t%d%n",
   292                 WHITE_BOX.getMethodCompilationLevel(method, false));
   293         System.out.printf("\tosr_compilable:\t%b%n",
   294                 WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY, true));
   295         System.out.printf("\tosr_compiled:\t%b%n",
   296                 WHITE_BOX.isMethodCompiled(method, true));
   297         System.out.printf("\tosr_comp_level:\t%d%n",
   298                 WHITE_BOX.getMethodCompilationLevel(method, true));
   299          System.out.printf("\tin_queue:\t%b%n",
   300                 WHITE_BOX.isMethodQueuedForCompilation(method));
   301         System.out.printf("compile_queues_size:\t%d%n%n",
   302                 WHITE_BOX.getCompileQueuesSize());
   303     }
   305     /**
   306      * Executes testing.
   307      */
   308     protected abstract void test() throws Exception;
   310     /**
   311      * Tries to trigger compilation of {@linkplain #method} by call
   312      * {@linkplain #testCase.callable} enough times.
   313      *
   314      * @return accumulated result
   315      * @see #compile(int)
   316      */
   317     protected final int compile() {
   318         if (testCase.isOsr) {
   319             return compile(1);
   320         } else {
   321             return compile(THRESHOLD);
   322         }
   323     }
   325     /**
   326      * Tries to trigger compilation of {@linkplain #method} by call
   327      * {@linkplain #testCase.callable} specified times.
   328      *
   329      * @param count invocation count
   330      * @return accumulated result
   331      */
   332     protected final int compile(int count) {
   333         int result = 0;
   334         Integer tmp;
   335         for (int i = 0; i < count; ++i) {
   336             try {
   337                 tmp = testCase.callable.call();
   338             } catch (Exception e) {
   339                 tmp = null;
   340             }
   341             result += tmp == null ? 0 : tmp;
   342         }
   343         if (IS_VERBOSE) {
   344             System.out.println("method was invoked " + count + " times");
   345         }
   346         return result;
   347     }
   348 }
   350 /**
   351  * Utility structure containing tested method and object to invoke it.
   352  */
   353 enum TestCase {
   354     /** constructor test case */
   355     CONSTRUCTOR_TEST(Helper.CONSTRUCTOR, Helper.CONSTRUCTOR_CALLABLE, false),
   356     /** method test case */
   357     METOD_TEST(Helper.METHOD, Helper.METHOD_CALLABLE, false),
   358     /** static method test case */
   359     STATIC_TEST(Helper.STATIC, Helper.STATIC_CALLABLE, false),
   361     /** OSR constructor test case */
   362     OSR_CONSTRUCTOR_TEST(Helper.OSR_CONSTRUCTOR,
   363             Helper.OSR_CONSTRUCTOR_CALLABLE, true),
   364      /** OSR method test case */
   365     OSR_METOD_TEST(Helper.OSR_METHOD, Helper.OSR_METHOD_CALLABLE, true),
   366     /** OSR static method test case */
   367     OSR_STATIC_TEST(Helper.OSR_STATIC, Helper.OSR_STATIC_CALLABLE, true);
   369     /** tested method */
   370     final Executable executable;
   371     /** object to invoke {@linkplain #executable} */
   372     final Callable<Integer> callable;
   373    /** flag for OSR test case */
   374     final boolean isOsr;
   376     private TestCase(Executable executable, Callable<Integer> callable,
   377             boolean isOsr) {
   378         this.executable = executable;
   379         this.callable = callable;
   380         this.isOsr = isOsr;
   381     }
   383     private static class Helper {
   385         private static final Callable<Integer> CONSTRUCTOR_CALLABLE
   386                 = new Callable<Integer>() {
   387             @Override
   388             public Integer call() throws Exception {
   389                 return new Helper(1337).hashCode();
   390             }
   391         };
   393         private static final Callable<Integer> METHOD_CALLABLE
   394                 = new Callable<Integer>() {
   395             private final Helper helper = new Helper();
   397             @Override
   398             public Integer call() throws Exception {
   399                 return helper.method();
   400             }
   401         };
   403         private static final Callable<Integer> STATIC_CALLABLE
   404                 = new Callable<Integer>() {
   405             @Override
   406             public Integer call() throws Exception {
   407                 return staticMethod();
   408             }
   409         };
   411         private static final Callable<Integer> OSR_CONSTRUCTOR_CALLABLE
   412                 = new Callable<Integer>() {
   413             @Override
   414             public Integer call() throws Exception {
   415                 return new Helper(null).hashCode();
   416             }
   417         };
   419         private static final Callable<Integer> OSR_METHOD_CALLABLE
   420                 = new Callable<Integer>() {
   421             private final Helper helper = new Helper();
   423             @Override
   424             public Integer call() throws Exception {
   425                 return helper.osrMethod();
   426             }
   427         };
   429         private static final Callable<Integer> OSR_STATIC_CALLABLE
   430                 = new Callable<Integer>() {
   431             @Override
   432             public Integer call() throws Exception {
   433                 return osrStaticMethod();
   434             }
   435         };
   438         private static final Constructor CONSTRUCTOR;
   439         private static final Constructor OSR_CONSTRUCTOR;
   440         private static final Method METHOD;
   441         private static final Method STATIC;
   442         private static final Method OSR_METHOD;
   443         private static final Method OSR_STATIC;
   445         static {
   446             try {
   447                 CONSTRUCTOR = Helper.class.getDeclaredConstructor(int.class);
   448             } catch (NoSuchMethodException | SecurityException e) {
   449                 throw new RuntimeException(
   450                         "exception on getting method Helper.<init>(int)", e);
   451             }
   452             try {
   453                 OSR_CONSTRUCTOR = Helper.class.getDeclaredConstructor(
   454                         Object.class);
   455             } catch (NoSuchMethodException | SecurityException e) {
   456                 throw new RuntimeException(
   457                         "exception on getting method Helper.<init>(Object)", e);
   458             }
   459             METHOD = getMethod("method");
   460             STATIC = getMethod("staticMethod");
   461             OSR_METHOD = getMethod("osrMethod");
   462             OSR_STATIC = getMethod("osrStaticMethod");
   463         }
   465         private static Method getMethod(String name) {
   466             try {
   467                 return Helper.class.getDeclaredMethod(name);
   468             } catch (NoSuchMethodException | SecurityException e) {
   469                 throw new RuntimeException(
   470                         "exception on getting method Helper." + name, e);
   471             }
   473         }
   475         private static int staticMethod() {
   476             return 1138;
   477         }
   479         private int method() {
   480             return 42;
   481         }
   483         private static int osrStaticMethod() {
   484             int result = 0;
   485             for (long i = 0; i < CompilerWhiteBoxTest.BACKEDGE_THRESHOLD; ++i) {
   486                 result += staticMethod();
   487             }
   488             return result;
   489         }
   491         private int osrMethod() {
   492             int result = 0;
   493             for (long i = 0; i < CompilerWhiteBoxTest.BACKEDGE_THRESHOLD; ++i) {
   494                 result += method();
   495             }
   496             return result;
   497         }
   499         private final int x;
   501         // for method and OSR method test case
   502         public Helper() {
   503             x = 0;
   504         }
   506         // for OSR constructor test case
   507         private Helper(Object o) {
   508             int result = 0;
   509             for (long i = 0; i < CompilerWhiteBoxTest.BACKEDGE_THRESHOLD; ++i) {
   510                 result += method();
   511             }
   512             x = result;
   513         }
   515         // for constructor test case
   516         private Helper(int x) {
   517             this.x = x;
   518         }
   520         @Override
   521         public int hashCode() {
   522             return x;
   523         }
   524     }
   525 }

mercurial