comparison test/compiler/whitebox/CompilerWhiteBoxTest.java @ 10423:a6697eaddebd

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