1 /* 2 * Copyright (c) 2017, 2019, 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 */ 23 24 package compiler.valhalla.valuetypes; 25 26 import compiler.whitebox.CompilerWhiteBoxTest; 27 import jdk.test.lib.Asserts; 28 import jdk.test.lib.management.InputArguments; 29 import jdk.test.lib.Platform; 30 import jdk.test.lib.process.ProcessTools; 31 import jdk.test.lib.process.OutputAnalyzer; 32 import jdk.test.lib.Utils; 33 import sun.hotspot.WhiteBox; 34 35 import java.lang.annotation.Retention; 36 import java.lang.annotation.RetentionPolicy; 37 import java.lang.annotation.Repeatable; 38 import java.lang.invoke.*; 39 import java.lang.reflect.Method; 40 import java.util.ArrayList; 41 import java.util.Arrays; 42 import java.util.Hashtable; 43 import java.util.LinkedHashMap; 44 import java.util.List; 45 import java.util.Map; 46 import java.util.regex.Matcher; 47 import java.util.regex.Pattern; 48 import java.util.TreeMap; 49 50 // Mark method as test 51 @Retention(RetentionPolicy.RUNTIME) 52 @Repeatable(Tests.class) 53 @interface Test { 54 // Regular expression used to match forbidden IR nodes 55 // in the C2 IR emitted for this test. 56 String failOn() default ""; 57 // Regular expressions used to match and count IR nodes. 58 String[] match() default { }; 59 int[] matchCount() default { }; 60 int valid() default ValueTypeTest.AllFlags; 61 } 62 63 @Retention(RetentionPolicy.RUNTIME) 64 @interface Tests { 65 Test[] value(); 66 } 67 68 // Force method inlining during compilation 69 @Retention(RetentionPolicy.RUNTIME) 70 @interface ForceInline { } 71 72 // Prevent method inlining during compilation 73 @Retention(RetentionPolicy.RUNTIME) 74 @interface DontInline { } 75 76 // Prevent method compilation 77 @Retention(RetentionPolicy.RUNTIME) 78 @interface DontCompile { } 79 80 // Number of warmup iterations 81 @Retention(RetentionPolicy.RUNTIME) 82 @interface Warmup { 83 int value(); 84 } 85 86 public abstract class ValueTypeTest { 87 // Run "jtreg -Dtest.c1=true" to enable experimental C1 testing. 88 static final boolean TEST_C1 = Boolean.getBoolean("test.c1"); 89 90 // Should we execute tests that assume (ValueType[] <: Object[])? 91 static final boolean ENABLE_VALUE_ARRAY_COVARIANCE = Boolean.getBoolean("ValueArrayCovariance"); 92 93 // Random test values 94 public static final int rI = Utils.getRandomInstance().nextInt() % 1000; 95 public static final long rL = Utils.getRandomInstance().nextLong() % 1000; 96 97 // User defined settings 98 protected static final boolean XCOMP = Platform.isComp(); 99 private static final boolean PRINT_GRAPH = true; 100 private static final boolean PRINT_TIMES = Boolean.parseBoolean(System.getProperty("PrintTimes", "false")); 101 private static boolean VERIFY_IR = Boolean.parseBoolean(System.getProperty("VerifyIR", "true")) && !TEST_C1 && !XCOMP; 102 private static final boolean VERIFY_VM = Boolean.parseBoolean(System.getProperty("VerifyVM", "false")); 103 private static final String SCENARIOS = System.getProperty("Scenarios", ""); 104 private static final String TESTLIST = System.getProperty("Testlist", ""); 105 private static final String EXCLUDELIST = System.getProperty("Exclude", ""); 106 private static final int WARMUP = Integer.parseInt(System.getProperty("Warmup", "251")); 107 private static final boolean DUMP_REPLAY = Boolean.parseBoolean(System.getProperty("DumpReplay", "false")); 108 109 // Pre-defined settings 110 private static final List<String> defaultFlags = Arrays.asList( 111 "-XX:-BackgroundCompilation", "-XX:CICompilerCount=1", 112 "-XX:CompileCommand=quiet", 113 "-XX:CompileCommand=compileonly,java.lang.invoke.*::*", 114 "-XX:CompileCommand=compileonly,java.lang.Long::sum", 115 "-XX:CompileCommand=compileonly,java.lang.Object::<init>", 116 "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.*::*"); 117 private static final List<String> printFlags = Arrays.asList( 118 "-XX:+PrintCompilation", "-XX:+PrintIdeal", "-XX:+PrintOptoAssembly"); 119 private static final List<String> verifyFlags = Arrays.asList( 120 "-XX:+VerifyOops", "-XX:+VerifyStack", "-XX:+VerifyLastFrame", "-XX:+VerifyBeforeGC", "-XX:+VerifyAfterGC", 121 "-XX:+VerifyDuringGC", "-XX:+VerifyAdapterSharing"); 122 123 protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); 124 protected static final int ValueTypePassFieldsAsArgsOn = 0x1; 125 protected static final int ValueTypePassFieldsAsArgsOff = 0x2; 126 protected static final int ValueTypeArrayFlattenOn = 0x4; 127 protected static final int ValueTypeArrayFlattenOff = 0x8; 128 protected static final int ValueTypeReturnedAsFieldsOn = 0x10; 129 protected static final int ValueTypeReturnedAsFieldsOff = 0x20; 130 protected static final int AlwaysIncrementalInlineOn = 0x40; 131 protected static final int AlwaysIncrementalInlineOff = 0x80; 132 static final int AllFlags = ValueTypePassFieldsAsArgsOn | ValueTypePassFieldsAsArgsOff | ValueTypeArrayFlattenOn | ValueTypeArrayFlattenOff | ValueTypeReturnedAsFieldsOn; 133 protected static final boolean ValueTypePassFieldsAsArgs = (Boolean)WHITE_BOX.getVMFlag("ValueTypePassFieldsAsArgs"); 134 protected static final boolean ValueTypeArrayFlatten = (Boolean)WHITE_BOX.getVMFlag("ValueArrayFlatten"); 135 protected static final boolean ValueTypeReturnedAsFields = (Boolean)WHITE_BOX.getVMFlag("ValueTypeReturnedAsFields"); 136 protected static final boolean AlwaysIncrementalInline = (Boolean)WHITE_BOX.getVMFlag("AlwaysIncrementalInline"); 137 protected static final int COMP_LEVEL_ANY = -2; 138 protected static final int COMP_LEVEL_FULL_OPTIMIZATION = TEST_C1 ? 1 : 4; 139 protected static final Hashtable<String, Method> tests = new Hashtable<String, Method>(); 140 protected static final boolean USE_COMPILER = WHITE_BOX.getBooleanVMFlag("UseCompiler"); 141 protected static final boolean PRINT_IDEAL = WHITE_BOX.getBooleanVMFlag("PrintIdeal"); 142 143 // Regular expressions used to match nodes in the PrintIdeal output 144 protected static final String START = "(\\d+\\t(.*"; 145 protected static final String MID = ".*)+\\t===.*"; 146 protected static final String END = ")|"; 147 protected static final String ALLOC = "(.*precise klass compiler/valhalla/valuetypes/MyValue.*\\R(.*(nop|spill).*\\R)*.*_new_instance_Java" + END; 148 protected static final String ALLOCA = "(.*precise klass \\[Lcompiler/valhalla/valuetypes/MyValue.*\\R(.*(nop|spill).*\\R)*.*_new_array_Java" + END; 149 protected static final String LOAD = START + "Load(B|S|I|L|F|D|P|N)" + MID + "@compiler/valhalla/valuetypes/MyValue.*" + END; 150 protected static final String LOADK = START + "LoadK" + MID + END; 151 protected static final String STORE = START + "Store(B|C|S|I|L|F|D|P|N)" + MID + "@compiler/valhalla/valuetypes/MyValue.*" + END; 152 protected static final String LOOP = START + "Loop" + MID + "" + END; 153 protected static final String TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*(unstable_if|predicate)" + END; 154 protected static final String RETURN = START + "Return" + MID + "returns" + END; 155 protected static final String LINKTOSTATIC = START + "CallStaticJava" + MID + "linkToStatic" + END; 156 protected static final String NPE = START + "CallStaticJava" + MID + "null_check" + END; 157 protected static final String CALL = START + "CallStaticJava" + MID + END; 158 protected static final String STOREVALUETYPEFIELDS = START + "CallStaticJava" + MID + "store_value_type_fields" + END; 159 protected static final String SCOBJ = "(.*# ScObj.*" + END; 160 161 public static String[] concat(String prefix[], String... extra) { 162 ArrayList<String> list = new ArrayList<String>(); 163 if (prefix != null) { 164 for (String s : prefix) { 165 list.add(s); 166 } 167 } 168 if (extra != null) { 169 for (String s : extra) { 170 list.add(s); 171 } 172 } 173 174 return list.toArray(new String[list.size()]); 175 } 176 177 /** 178 * Override getNumScenarios and getVMParameters if you want to run with more than 179 * the 5 built-in scenarios 180 */ 181 public int getNumScenarios() { 182 if (TEST_C1) { 183 return 1; 184 } else { 185 return 6; 186 } 187 } 188 189 /** 190 * VM paramaters for the 5 built-in test scenarios. If your test needs to append 191 * extra parameters for (some of) these scenarios, override getExtraVMParameters(). 192 */ 193 public String[] getVMParameters(int scenario) { 194 if (TEST_C1) { 195 return new String[] { 196 "-XX:+EnableValhallaC1", 197 }; 198 } 199 200 switch (scenario) { 201 case 0: return new String[] { 202 "-XX:+AlwaysIncrementalInline", 203 "-XX:ValueArrayElemMaxFlatOops=-1", 204 "-XX:ValueArrayElemMaxFlatSize=-1", 205 "-XX:+ValueArrayFlatten", 206 "-XX:ValueFieldMaxFlatSize=-1", 207 "-XX:+ValueTypePassFieldsAsArgs", 208 "-XX:+ValueTypeReturnedAsFields"}; 209 case 1: return new String[] { 210 "-XX:-UseCompressedOops", 211 "-XX:ValueArrayElemMaxFlatOops=-1", 212 "-XX:ValueArrayElemMaxFlatSize=-1", 213 "-XX:+ValueArrayFlatten", 214 "-XX:ValueFieldMaxFlatSize=-1", 215 "-XX:-ValueTypePassFieldsAsArgs", 216 "-XX:-ValueTypeReturnedAsFields"}; 217 case 2: return new String[] { 218 "-DVerifyIR=false", 219 "-XX:-UseCompressedOops", 220 "-XX:ValueArrayElemMaxFlatOops=0", 221 "-XX:ValueArrayElemMaxFlatSize=0", 222 "-XX:-ValueArrayFlatten", 223 "-XX:ValueFieldMaxFlatSize=0", 224 "-XX:+ValueTypePassFieldsAsArgs", 225 "-XX:+ValueTypeReturnedAsFields", 226 "-XX:+StressValueTypePassFieldsAsArgs", 227 "-XX:+StressValueTypeReturnedAsFields"}; 228 case 3: return new String[] { 229 "-DVerifyIR=false", 230 "-XX:+AlwaysIncrementalInline", 231 "-XX:ValueArrayElemMaxFlatOops=0", 232 "-XX:ValueArrayElemMaxFlatSize=0", 233 "-XX:ValueFieldMaxFlatSize=0", 234 "-XX:-ValueTypePassFieldsAsArgs", 235 "-XX:-ValueTypeReturnedAsFields"}; 236 case 4: return new String[] { 237 "-DVerifyIR=false", 238 "-XX:ValueArrayElemMaxFlatOops=-1", 239 "-XX:ValueArrayElemMaxFlatSize=-1", 240 "-XX:+ValueArrayFlatten", 241 "-XX:ValueFieldMaxFlatSize=0", 242 "-XX:+ValueTypePassFieldsAsArgs", 243 "-XX:-ValueTypeReturnedAsFields", 244 "-XX:+StressValueTypePassFieldsAsArgs"}; 245 case 5: return new String[] { 246 "-XX:+AlwaysIncrementalInline", 247 "-XX:ValueArrayElemMaxFlatOops=-1", 248 "-XX:ValueArrayElemMaxFlatSize=-1", 249 "-XX:+ValueArrayFlatten", 250 "-XX:ValueFieldMaxFlatSize=-1", 251 "-XX:-ValueTypePassFieldsAsArgs", 252 "-XX:-ValueTypeReturnedAsFields"}; 253 } 254 255 return null; 256 } 257 258 /** 259 * Override this method to provide extra parameters for selected scenarios 260 */ 261 public String[] getExtraVMParameters(int scenario) { 262 return null; 263 } 264 265 public static void main(String[] args) throws Throwable { 266 if (args.length != 1) { 267 throw new RuntimeException("Usage: @run main/othervm/timeout=120 -Xbootclasspath/a:." + 268 " -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions" + 269 " -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:+EnableValhalla" + 270 " compiler.valhalla.valuetypes.ValueTypeTest <YourTestMainClass>"); 271 } 272 String testMainClassName = args[0]; 273 Class testMainClass = Class.forName(testMainClassName); 274 ValueTypeTest test = (ValueTypeTest)testMainClass.newInstance(); 275 List<String> scenarios = null; 276 if (!SCENARIOS.isEmpty()) { 277 scenarios = Arrays.asList(SCENARIOS.split(",")); 278 } 279 for (int i=0; i<test.getNumScenarios(); i++) { 280 if (scenarios == null || scenarios.contains(Integer.toString(i))) { 281 System.out.println("Scenario #" + i + " -------- "); 282 String[] cmds = InputArguments.getVmInputArgs(); 283 cmds = concat(cmds, test.getVMParameters(i)); 284 cmds = concat(cmds, test.getExtraVMParameters(i)); 285 cmds = concat(cmds, testMainClassName); 286 287 OutputAnalyzer oa = ProcessTools.executeTestJvm(cmds); 288 String output = oa.getOutput(); 289 oa.shouldHaveExitValue(0); 290 System.out.println(output); 291 } else { 292 System.out.println("Scenario #" + i + " is skipped due to -Dscenarios=" + SCENARIOS); 293 } 294 } 295 } 296 297 // To exclude test cases, use -DExclude=<case1>,<case2>,... 298 // Each case can be just the method name, or can be <class>.<method>. The latter form is useful 299 // when you are running several tests at the same time. 300 // 301 // jtreg -DExclude=test12 TestArrays.java 302 // jtreg -DExclude=test34 TestLWorld.java 303 // -- or -- 304 // jtreg -DExclude=TestArrays.test12,TestLWorld.test34 TestArrays.java TestLWorld.java 305 // 306 private List<String> buildExcludeList() { 307 List<String> exclude = null; 308 String classPrefix = getClass().getSimpleName() + "."; 309 if (!EXCLUDELIST.isEmpty()) { 310 exclude = new ArrayList(Arrays.asList(EXCLUDELIST.split(","))); 311 for (int i = exclude.size() - 1; i >= 0; i--) { 312 String ex = exclude.get(i); 313 if (ex.indexOf(".") > 0) { 314 if (ex.startsWith(classPrefix)) { 315 ex = ex.substring(classPrefix.length()); 316 exclude.set(i, ex); 317 } else { 318 exclude.remove(i); 319 } 320 } 321 } 322 } 323 return exclude; 324 } 325 326 protected ValueTypeTest() { 327 List<String> list = null; 328 if (!TESTLIST.isEmpty()) { 329 list = Arrays.asList(TESTLIST.split(",")); 330 } 331 List<String> exclude = buildExcludeList(); 332 333 // Gather all test methods and put them in Hashtable 334 for (Method m : getClass().getDeclaredMethods()) { 335 Test[] annos = m.getAnnotationsByType(Test.class); 336 if (annos.length != 0 && 337 ((list == null || list.contains(m.getName())) && (exclude == null || !exclude.contains(m.getName())))) { 338 tests.put(getClass().getSimpleName() + "::" + m.getName(), m); 339 } 340 } 341 } 342 343 protected void run(String[] args, Class<?>... classes) throws Throwable { 344 if (args.length == 0) { 345 // Spawn a new VM instance 346 execute_vm(); 347 } else { 348 // Execute tests 349 run(classes); 350 } 351 } 352 353 private void execute_vm() throws Throwable { 354 Asserts.assertFalse(tests.isEmpty(), "no tests to execute"); 355 ArrayList<String> args = new ArrayList<String>(defaultFlags); 356 String[] vmInputArgs = InputArguments.getVmInputArgs(); 357 for (String arg : vmInputArgs) { 358 if (arg.startsWith("-XX:CompileThreshold")) { 359 // Disable IR verification if non-default CompileThreshold is set 360 VERIFY_IR = false; 361 } 362 } 363 if (VERIFY_IR) { 364 // Add print flags for IR verification 365 args.addAll(printFlags); 366 // Always trap for exception throwing to not confuse IR verification 367 args.add("-XX:-OmitStackTraceInFastThrow"); 368 } 369 if (VERIFY_VM) { 370 args.addAll(verifyFlags); 371 } 372 // Run tests in own process and verify output 373 args.add(getClass().getName()); 374 args.add("run"); 375 // Spawn process with default JVM options from the test's run command 376 String[] cmds = Arrays.copyOf(vmInputArgs, vmInputArgs.length + args.size()); 377 System.arraycopy(args.toArray(), 0, cmds, vmInputArgs.length, args.size()); 378 OutputAnalyzer oa = ProcessTools.executeTestJvm(cmds); 379 // If ideal graph printing is enabled/supported, verify output 380 String output = oa.getOutput(); 381 oa.shouldHaveExitValue(0); 382 if (VERIFY_IR) { 383 if (output.contains("PrintIdeal enabled")) { 384 parseOutput(output); 385 } else { 386 System.out.println(output); 387 System.out.println("WARNING: IR verification failed! Running with -Xint, -Xcomp or release build?"); 388 } 389 } 390 } 391 392 private void parseOutput(String output) throws Exception { 393 Pattern comp_re = Pattern.compile("\\n\\s+\\d+\\s+\\d+\\s+(%| )(s| )(!| )b(n| )\\s+\\S+\\.(?<name>[^.]+::\\S+)\\s+(?<osr>@ \\d+\\s+)?[(]\\d+ bytes[)]\\n"); 394 Matcher m = comp_re.matcher(output); 395 Map<String,String> compilations = new LinkedHashMap<>(); 396 int prev = 0; 397 String methodName = null; 398 while (m.find()) { 399 if (prev == 0) { 400 // Print header 401 System.out.print(output.substring(0, m.start()+1)); 402 } else if (methodName != null) { 403 compilations.put(methodName, output.substring(prev, m.start()+1)); 404 } 405 if (m.group("osr") != null) { 406 methodName = null; 407 } else { 408 methodName = m.group("name"); 409 } 410 prev = m.end(); 411 } 412 if (prev == 0) { 413 // Print header 414 System.out.print(output); 415 } else if (methodName != null) { 416 compilations.put(methodName, output.substring(prev)); 417 } 418 // Iterate over compilation output 419 for (String testName : compilations.keySet()) { 420 Method test = tests.get(testName); 421 if (test == null) { 422 // Skip helper methods 423 continue; 424 } 425 String graph = compilations.get(testName); 426 if (PRINT_GRAPH) { 427 System.out.println("\nGraph for " + testName + "\n" + graph); 428 } 429 // Parse graph using regular expressions to determine if it contains forbidden nodes 430 Test[] annos = test.getAnnotationsByType(Test.class); 431 Test anno = null; 432 for (Test a : annos) { 433 if ((a.valid() & ValueTypePassFieldsAsArgsOn) != 0 && ValueTypePassFieldsAsArgs) { 434 assert anno == null; 435 anno = a; 436 } else if ((a.valid() & ValueTypePassFieldsAsArgsOff) != 0 && !ValueTypePassFieldsAsArgs) { 437 assert anno == null; 438 anno = a; 439 } else if ((a.valid() & ValueTypeArrayFlattenOn) != 0 && ValueTypeArrayFlatten) { 440 assert anno == null; 441 anno = a; 442 } else if ((a.valid() & ValueTypeArrayFlattenOff) != 0 && !ValueTypeArrayFlatten) { 443 assert anno == null; 444 anno = a; 445 } else if ((a.valid() & ValueTypeReturnedAsFieldsOn) != 0 && ValueTypeReturnedAsFields) { 446 assert anno == null; 447 anno = a; 448 } else if ((a.valid() & ValueTypeReturnedAsFieldsOff) != 0 && !ValueTypeReturnedAsFields) { 449 assert anno == null; 450 anno = a; 451 } else if ((a.valid() & AlwaysIncrementalInlineOn) != 0 && AlwaysIncrementalInline) { 452 assert anno == null; 453 anno = a; 454 } else if ((a.valid() & AlwaysIncrementalInlineOff) != 0 && !AlwaysIncrementalInline) { 455 assert anno == null; 456 anno = a; 457 } 458 } 459 assert anno != null; 460 String regexFail = anno.failOn(); 461 if (!regexFail.isEmpty()) { 462 Pattern pattern = Pattern.compile(regexFail.substring(0, regexFail.length()-1)); 463 Matcher matcher = pattern.matcher(graph); 464 boolean found = matcher.find(); 465 Asserts.assertFalse(found, "Graph for '" + testName + "' contains forbidden node:\n" + (found ? matcher.group() : "")); 466 } 467 String[] regexMatch = anno.match(); 468 int[] matchCount = anno.matchCount(); 469 for (int i = 0; i < regexMatch.length; ++i) { 470 Pattern pattern = Pattern.compile(regexMatch[i].substring(0, regexMatch[i].length()-1)); 471 Matcher matcher = pattern.matcher(graph); 472 int count = 0; 473 String nodes = ""; 474 while (matcher.find()) { 475 count++; 476 nodes += matcher.group() + "\n"; 477 } 478 if (matchCount[i] < 0) { 479 Asserts.assertLTE(Math.abs(matchCount[i]), count, "Graph for '" + testName + "' contains different number of match nodes:\n" + nodes); 480 } else { 481 Asserts.assertEQ(matchCount[i], count, "Graph for '" + testName + "' contains different number of match nodes:\n" + nodes); 482 } 483 } 484 tests.remove(testName); 485 System.out.println(testName + " passed"); 486 } 487 // Check if all tests were compiled 488 if (tests.size() != 0) { 489 for (String name : tests.keySet()) { 490 System.out.println("Test '" + name + "' not compiled!"); 491 } 492 throw new RuntimeException("Not all tests were compiled"); 493 } 494 } 495 496 private void setup(Class<?> clazz) { 497 if (XCOMP) { 498 // Don't control compilation if -Xcomp is enabled 499 return; 500 } 501 if (DUMP_REPLAY) { 502 // Generate replay compilation files 503 String directive = "[{ match: \"*.*\", DumpReplay: true }]"; 504 if (WHITE_BOX.addCompilerDirective(directive) != 1) { 505 throw new RuntimeException("Failed to add compiler directive"); 506 } 507 } 508 509 Method[] methods = clazz.getDeclaredMethods(); 510 for (Method m : methods) { 511 if (m.isAnnotationPresent(Test.class)) { 512 // Don't inline tests 513 WHITE_BOX.testSetDontInlineMethod(m, true); 514 } 515 if (m.isAnnotationPresent(DontCompile.class)) { 516 WHITE_BOX.makeMethodNotCompilable(m, COMP_LEVEL_ANY, true); 517 WHITE_BOX.makeMethodNotCompilable(m, COMP_LEVEL_ANY, false); 518 WHITE_BOX.testSetDontInlineMethod(m, true); 519 } 520 if (m.isAnnotationPresent(ForceInline.class)) { 521 WHITE_BOX.testSetForceInlineMethod(m, true); 522 } else if (m.isAnnotationPresent(DontInline.class)) { 523 WHITE_BOX.testSetDontInlineMethod(m, true); 524 } 525 } 526 527 // Compile class initializers 528 WHITE_BOX.enqueueInitializerForCompilation(clazz, COMP_LEVEL_FULL_OPTIMIZATION); 529 } 530 531 private void run(Class<?>... classes) throws Exception { 532 if (USE_COMPILER && PRINT_IDEAL && !XCOMP) { 533 System.out.println("PrintIdeal enabled"); 534 } 535 System.out.format("rI = %d, rL = %d\n", rI, rL); 536 537 setup(getClass()); 538 for (Class<?> clazz : classes) { 539 setup(clazz); 540 } 541 542 // Execute tests 543 TreeMap<Long, String> durations = PRINT_TIMES ? new TreeMap<Long, String>() : null; 544 for (Method test : tests.values()) { 545 long startTime = System.nanoTime(); 546 Method verifier = getClass().getMethod(test.getName() + "_verifier", boolean.class); 547 // Warmup using verifier method 548 Warmup anno = test.getAnnotation(Warmup.class); 549 int warmup = anno == null ? WARMUP : anno.value(); 550 for (int i = 0; i < warmup; ++i) { 551 verifier.invoke(this, true); 552 } 553 // Trigger compilation 554 WHITE_BOX.enqueueMethodForCompilation(test, COMP_LEVEL_FULL_OPTIMIZATION); 555 Asserts.assertTrue(!USE_COMPILER || WHITE_BOX.isMethodCompiled(test, false), test + " not compiled"); 556 // Check result 557 verifier.invoke(this, false); 558 if (PRINT_TIMES) { 559 long endTime = System.nanoTime(); 560 long duration = (endTime - startTime); 561 durations.put(duration, test.getName()); 562 } 563 } 564 565 // Print execution times 566 if (PRINT_TIMES) { 567 System.out.println("\n\nTest execution times:"); 568 for (Map.Entry<Long, String> entry : durations.entrySet()) { 569 System.out.format("%-10s%15d ns\n", entry.getValue() + ":", entry.getKey()); 570 } 571 } 572 } 573 }