hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java
changeset 17015 92390f57e8b1
parent 16689 efce070b8d42
child 17126 42a942feeea2
equal deleted inserted replaced
17014:11c1a00efeb4 17015:92390f57e8b1
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    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
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    21  * questions.
    22  */
    22  */
    23 
    23 
       
    24 import com.sun.management.HotSpotDiagnosticMXBean;
       
    25 import com.sun.management.VMOption;
    24 import sun.hotspot.WhiteBox;
    26 import sun.hotspot.WhiteBox;
    25 import sun.management.ManagementFactoryHelper;
    27 import sun.management.ManagementFactoryHelper;
    26 import com.sun.management.HotSpotDiagnosticMXBean;
    28 
    27 
    29 import java.lang.reflect.Constructor;
       
    30 import java.lang.reflect.Executable;
    28 import java.lang.reflect.Method;
    31 import java.lang.reflect.Method;
    29 
    32 import java.util.Objects;
    30 /*
    33 import java.util.concurrent.Callable;
       
    34 
       
    35 /**
       
    36  * Abstract class for WhiteBox testing of JIT.
       
    37  *
    31  * @author igor.ignatyev@oracle.com
    38  * @author igor.ignatyev@oracle.com
    32  */
    39  */
    33 public abstract class CompilerWhiteBoxTest {
    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     /** Instance of WhiteBox */
    34     protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
    46     protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
    35     protected static final Method METHOD = getMethod("method");
    47     /** Value of {@code -XX:CompileThreshold} */
    36     protected static final int COMPILE_THRESHOLD
    48     protected static final int COMPILE_THRESHOLD
    37             = Integer.parseInt(getVMOption("CompileThreshold", "10000"));
    49             = Integer.parseInt(getVMOption("CompileThreshold", "10000"));
       
    50     /** Value of {@code -XX:BackgroundCompilation} */
    38     protected static final boolean BACKGROUND_COMPILATION
    51     protected static final boolean BACKGROUND_COMPILATION
    39             = Boolean.valueOf(getVMOption("BackgroundCompilation", "true"));
    52             = Boolean.valueOf(getVMOption("BackgroundCompilation", "true"));
       
    53     /** Value of {@code -XX:TieredCompilation} */
    40     protected static final boolean TIERED_COMPILATION
    54     protected static final boolean TIERED_COMPILATION
    41             = Boolean.valueOf(getVMOption("TieredCompilation", "false"));
    55             = Boolean.valueOf(getVMOption("TieredCompilation", "false"));
    42 
    56     /** Value of {@code -XX:TieredStopAtLevel} */
    43     protected static Method getMethod(String name) {
    57     protected static final int TIERED_STOP_AT_LEVEL
    44         try {
    58             = Integer.parseInt(getVMOption("TieredStopAtLevel", "0"));
    45             return CompilerWhiteBoxTest.class.getDeclaredMethod(name);
    59 
    46         } catch (NoSuchMethodException | SecurityException e) {
    60     /**
    47             throw new RuntimeException(
    61      * Returns value of VM option.
    48                     "exception on getting method " + name, e);
    62      *
    49         }
    63      * @param name option's name
    50     }
    64      * @return value of option or {@code null}, if option doesn't exist
    51 
    65      * @throws NullPointerException if name is null
       
    66      */
    52     protected static String getVMOption(String name) {
    67     protected static String getVMOption(String name) {
    53         String result;
    68         Objects.requireNonNull(name);
    54         HotSpotDiagnosticMXBean diagnostic
    69         HotSpotDiagnosticMXBean diagnostic
    55                 = ManagementFactoryHelper.getDiagnosticMXBean();
    70                 = ManagementFactoryHelper.getDiagnosticMXBean();
    56         result = diagnostic.getVMOption(name).getValue();
    71         VMOption tmp;
    57         return result;
    72         try {
    58     }
    73             tmp = diagnostic.getVMOption(name);
    59 
    74         } catch (IllegalArgumentException e) {
       
    75             tmp = null;
       
    76         }
       
    77         return (tmp == null ? null : tmp.getValue());
       
    78     }
       
    79 
       
    80     /**
       
    81      * Returns value of VM option or default value.
       
    82      *
       
    83      * @param name         option's name
       
    84      * @param defaultValue default value
       
    85      * @return value of option or {@code defaultValue}, if option doesn't exist
       
    86      * @throws NullPointerException if name is null
       
    87      * @see #getVMOption(String)
       
    88      */
    60     protected static String getVMOption(String name, String defaultValue) {
    89     protected static String getVMOption(String name, String defaultValue) {
    61         String result = getVMOption(name);
    90         String result = getVMOption(name);
    62         return result == null ? defaultValue : result;
    91         return result == null ? defaultValue : result;
    63     }
    92     }
    64 
    93 
    65     protected final void runTest() throws RuntimeException {
    94     /** tested method */
       
    95     protected final Executable method;
       
    96     private final Callable<Integer> callable;
       
    97 
       
    98     /**
       
    99      * Constructor.
       
   100      *
       
   101      * @param testCase object, that contains tested method and way to invoke it.
       
   102      */
       
   103     protected CompilerWhiteBoxTest(TestCase testCase) {
       
   104         Objects.requireNonNull(testCase);
       
   105         System.out.println("TEST CASE:" + testCase.name());
       
   106         method = testCase.executable;
       
   107         callable = testCase.callable;
       
   108     }
       
   109 
       
   110     /**
       
   111      * Template method for testing. Prints tested method's info before
       
   112      * {@linkplain #test()} and after {@linkplain #test()} or on thrown
       
   113      * exception.
       
   114      *
       
   115      * @throws RuntimeException if method {@linkplain #test()} throws any
       
   116      *                          exception
       
   117      * @see #test()
       
   118      */
       
   119     protected final void runTest() {
    66         if (ManagementFactoryHelper.getCompilationMXBean() == null) {
   120         if (ManagementFactoryHelper.getCompilationMXBean() == null) {
    67             System.err.println(
   121             System.err.println(
    68                     "Warning: test is not applicable in interpreted mode");
   122                     "Warning: test is not applicable in interpreted mode");
    69             return;
   123             return;
    70         }
   124         }
    71         System.out.println("at test's start:");
   125         System.out.println("at test's start:");
    72         printInfo(METHOD);
   126         printInfo();
    73         try {
   127         try {
    74             test();
   128             test();
    75         } catch (Exception e) {
   129         } catch (Exception e) {
    76             System.out.printf("on exception '%s':", e.getMessage());
   130             System.out.printf("on exception '%s':", e.getMessage());
    77             printInfo(METHOD);
   131             printInfo();
    78             e.printStackTrace();
   132             e.printStackTrace();
       
   133             if (e instanceof RuntimeException) {
       
   134                 throw (RuntimeException) e;
       
   135             }
    79             throw new RuntimeException(e);
   136             throw new RuntimeException(e);
    80         }
   137         }
    81         System.out.println("at test's end:");
   138         System.out.println("at test's end:");
    82         printInfo(METHOD);
   139         printInfo();
    83     }
   140     }
    84 
   141 
    85     protected static void checkNotCompiled(Method method) {
   142     /**
       
   143      * Checks, that {@linkplain #method} is not compiled.
       
   144      *
       
   145      * @throws RuntimeException if {@linkplain #method} is in compiler queue or
       
   146      *                          is compiled, or if {@linkplain #method} has zero
       
   147      *                          compilation level.
       
   148      */
       
   149     protected final void checkNotCompiled() {
    86         if (WHITE_BOX.isMethodQueuedForCompilation(method)) {
   150         if (WHITE_BOX.isMethodQueuedForCompilation(method)) {
    87             throw new RuntimeException(method + " must not be in queue");
   151             throw new RuntimeException(method + " must not be in queue");
    88         }
   152         }
    89         if (WHITE_BOX.isMethodCompiled(method)) {
   153         if (WHITE_BOX.isMethodCompiled(method)) {
    90             throw new RuntimeException(method + " must be not compiled");
   154             throw new RuntimeException(method + " must be not compiled");
    92         if (WHITE_BOX.getMethodCompilationLevel(method) != 0) {
   156         if (WHITE_BOX.getMethodCompilationLevel(method) != 0) {
    93             throw new RuntimeException(method + " comp_level must be == 0");
   157             throw new RuntimeException(method + " comp_level must be == 0");
    94         }
   158         }
    95     }
   159     }
    96 
   160 
    97     protected static void checkCompiled(Method method)
   161     /**
    98             throws InterruptedException {
   162      * Checks, that {@linkplain #method} is compiled.
       
   163      *
       
   164      * @throws RuntimeException if {@linkplain #method} isn't in compiler queue
       
   165      *                          and isn't compiled, or if {@linkplain #method}
       
   166      *                          has nonzero compilation level
       
   167      */
       
   168     protected final void checkCompiled() {
    99         final long start = System.currentTimeMillis();
   169         final long start = System.currentTimeMillis();
   100         waitBackgroundCompilation(method);
   170         waitBackgroundCompilation();
   101         if (WHITE_BOX.isMethodQueuedForCompilation(method)) {
   171         if (WHITE_BOX.isMethodQueuedForCompilation(method)) {
   102             System.err.printf("Warning: %s is still in queue after %dms%n",
   172             System.err.printf("Warning: %s is still in queue after %dms%n",
   103                     method, System.currentTimeMillis() - start);
   173                     method, System.currentTimeMillis() - start);
   104             return;
   174             return;
   105         }
   175         }
   109         if (WHITE_BOX.getMethodCompilationLevel(method) == 0) {
   179         if (WHITE_BOX.getMethodCompilationLevel(method) == 0) {
   110             throw new RuntimeException(method + " comp_level must be != 0");
   180             throw new RuntimeException(method + " comp_level must be != 0");
   111         }
   181         }
   112     }
   182     }
   113 
   183 
   114     protected static void waitBackgroundCompilation(Method method)
   184     /**
   115             throws InterruptedException {
   185      * Waits for completion of background compilation of {@linkplain #method}.
       
   186      */
       
   187     protected final void waitBackgroundCompilation() {
   116         if (!BACKGROUND_COMPILATION) {
   188         if (!BACKGROUND_COMPILATION) {
   117             return;
   189             return;
   118         }
   190         }
   119         final Object obj = new Object();
   191         final Object obj = new Object();
   120         synchronized (obj) {
   192         for (int i = 0; i < 10
   121             for (int i = 0; i < 10; ++i) {
   193                 && WHITE_BOX.isMethodQueuedForCompilation(method); ++i) {
   122                 if (!WHITE_BOX.isMethodQueuedForCompilation(method)) {
   194             synchronized (obj) {
   123                     break;
   195                 try {
       
   196                     obj.wait(1000);
       
   197                 } catch (InterruptedException e) {
       
   198                     Thread.currentThread().interrupt();
   124                 }
   199                 }
   125                 obj.wait(1000);
   200             }
   126             }
   201         }
   127         }
   202     }
   128     }
   203 
   129 
   204     /**
   130     protected static void printInfo(Method method) {
   205      * Prints information about {@linkplain #method}.
       
   206      */
       
   207     protected final void printInfo() {
   131         System.out.printf("%n%s:%n", method);
   208         System.out.printf("%n%s:%n", method);
   132         System.out.printf("\tcompilable:\t%b%n",
   209         System.out.printf("\tcompilable:\t%b%n",
   133                 WHITE_BOX.isMethodCompilable(method));
   210                 WHITE_BOX.isMethodCompilable(method));
   134         System.out.printf("\tcompiled:\t%b%n",
   211         System.out.printf("\tcompiled:\t%b%n",
   135                 WHITE_BOX.isMethodCompiled(method));
   212                 WHITE_BOX.isMethodCompiled(method));
   139                 WHITE_BOX.isMethodQueuedForCompilation(method));
   216                 WHITE_BOX.isMethodQueuedForCompilation(method));
   140         System.out.printf("compile_queues_size:\t%d%n%n",
   217         System.out.printf("compile_queues_size:\t%d%n%n",
   141                 WHITE_BOX.getCompileQueuesSize());
   218                 WHITE_BOX.getCompileQueuesSize());
   142     }
   219     }
   143 
   220 
       
   221     /**
       
   222      * Executes testing.
       
   223      */
   144     protected abstract void test() throws Exception;
   224     protected abstract void test() throws Exception;
   145 
   225 
       
   226     /**
       
   227      * Tries to trigger compilation of {@linkplain #method} by call
       
   228      * {@linkplain #callable} enough times.
       
   229      *
       
   230      * @return accumulated result
       
   231      * @see #compile(int)
       
   232      */
   146     protected final int compile() {
   233     protected final int compile() {
   147         return compile(Math.max(COMPILE_THRESHOLD, 150000));
   234         return compile(Math.max(COMPILE_THRESHOLD, 150000));
   148     }
   235     }
   149 
   236 
       
   237     /**
       
   238      * Tries to trigger compilation of {@linkplain #method} by call
       
   239      * {@linkplain #callable} specified times.
       
   240      *
       
   241      * @param count invocation count
       
   242      * @return accumulated result
       
   243      */
   150     protected final int compile(int count) {
   244     protected final int compile(int count) {
   151         int result = 0;
   245         int result = 0;
       
   246         Integer tmp;
   152         for (int i = 0; i < count; ++i) {
   247         for (int i = 0; i < count; ++i) {
   153             result += method();
   248             try {
       
   249                 tmp = callable.call();
       
   250             } catch (Exception e) {
       
   251                 tmp = null;
       
   252             }
       
   253             result += tmp == null ? 0 : tmp;
   154         }
   254         }
   155         System.out.println("method was invoked " + count + " times");
   255         System.out.println("method was invoked " + count + " times");
   156         return result;
   256         return result;
   157     }
   257     }
   158 
       
   159     protected int method() {
       
   160         return 42;
       
   161     }
       
   162 }
   258 }
       
   259 
       
   260 /**
       
   261  * Utility structure containing tested method and object to invoke it.
       
   262  */
       
   263 enum TestCase {
       
   264     /** constructor test case */
       
   265     CONSTRUCTOR_TEST(Helper.CONSTRUCTOR, Helper.CONSTRUCTOR_CALLABLE),
       
   266     /** method test case */
       
   267     METOD_TEST(Helper.METHOD, Helper.METHOD_CALLABLE),
       
   268     /** static method test case */
       
   269     STATIC_TEST(Helper.STATIC, Helper.STATIC_CALLABLE);
       
   270 
       
   271     /** tested method */
       
   272     final Executable executable;
       
   273     /** object to invoke {@linkplain #executable} */
       
   274     final Callable<Integer> callable;
       
   275 
       
   276     private TestCase(Executable executable, Callable<Integer> callable) {
       
   277         this.executable = executable;
       
   278         this.callable = callable;
       
   279     }
       
   280 
       
   281     private static class Helper {
       
   282         private static final Callable<Integer> CONSTRUCTOR_CALLABLE
       
   283                 = new Callable<Integer>() {
       
   284             @Override
       
   285             public Integer call() throws Exception {
       
   286                 return new Helper(1337).hashCode();
       
   287             }
       
   288         };
       
   289 
       
   290         private static final Callable<Integer> METHOD_CALLABLE
       
   291                 = new Callable<Integer>() {
       
   292             private final Helper helper = new Helper();
       
   293 
       
   294             @Override
       
   295             public Integer call() throws Exception {
       
   296                 return helper.method();
       
   297             }
       
   298         };
       
   299 
       
   300         private static final Callable<Integer> STATIC_CALLABLE
       
   301                 = new Callable<Integer>() {
       
   302             @Override
       
   303             public Integer call() throws Exception {
       
   304                 return staticMethod();
       
   305             }
       
   306         };
       
   307 
       
   308         private static final Constructor CONSTRUCTOR;
       
   309         private static final Method METHOD;
       
   310         private static final Method STATIC;
       
   311 
       
   312         static {
       
   313             try {
       
   314                 CONSTRUCTOR = Helper.class.getDeclaredConstructor(int.class);
       
   315             } catch (NoSuchMethodException | SecurityException e) {
       
   316                 throw new RuntimeException(
       
   317                         "exception on getting method Helper.<init>(int)", e);
       
   318             }
       
   319             try {
       
   320                 METHOD = Helper.class.getDeclaredMethod("method");
       
   321             } catch (NoSuchMethodException | SecurityException e) {
       
   322                 throw new RuntimeException(
       
   323                         "exception on getting method Helper.method()", e);
       
   324             }
       
   325             try {
       
   326                 STATIC = Helper.class.getDeclaredMethod("staticMethod");
       
   327             } catch (NoSuchMethodException | SecurityException e) {
       
   328                 throw new RuntimeException(
       
   329                         "exception on getting method Helper.staticMethod()", e);
       
   330             }
       
   331         }
       
   332 
       
   333         private static int staticMethod() {
       
   334             return 1138;
       
   335         }
       
   336 
       
   337         private int method() {
       
   338             return 42;
       
   339         }
       
   340 
       
   341         private final int x;
       
   342 
       
   343         public Helper() {
       
   344             x = 0;
       
   345         }
       
   346 
       
   347         private Helper(int x) {
       
   348             this.x = x;
       
   349         }
       
   350 
       
   351         @Override
       
   352         public int hashCode() {
       
   353             return x;
       
   354         }
       
   355     }
       
   356 }