rev 10493 : keep
rev 10504 : value type calling convention

   1 /*
   2  * Copyright (c) 2016, 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 // TODO add bugid and summary
  25 
  26 /*
  27  * @test
  28  * @library /testlibrary /test/lib /compiler/whitebox /
  29  * @build compiler.valhalla.valuetypes.ValueTypeTestBench
  30  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  31  * @run main ClassFileInstaller jdk.test.lib.Platform
  32  * @run main/othervm -noverify -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI



  33  *                   compiler.valhalla.valuetypes.ValueTypeTestBench
  34  */
  35 
  36 package compiler.valhalla.valuetypes;
  37 
  38 import compiler.whitebox.CompilerWhiteBoxTest;
  39 import jdk.internal.misc.Unsafe;
  40 import jdk.test.lib.Asserts;
  41 import jdk.test.lib.Platform;
  42 import jdk.test.lib.ProcessTools;
  43 import jdk.test.lib.OutputAnalyzer;
  44 import jdk.test.lib.Utils;
  45 import sun.hotspot.WhiteBox;
  46 
  47 import java.lang.annotation.Retention;
  48 import java.lang.annotation.RetentionPolicy;

  49 import java.lang.reflect.Method;
  50 import java.util.ArrayList;

  51 import java.util.Hashtable;

  52 import java.util.regex.Matcher;
  53 import java.util.regex.Pattern;
  54 
  55 // Test value types
  56 __ByValue final class MyValue1 {
  57     final int x;
  58     final long y;
  59     final MyValue2 v1;
  60     final MyValue2 v2;
  61     final int c;
  62 
  63     private MyValue1(int x, long y, MyValue2 v1, MyValue2 v2, int c) {
  64         this.x = x;
  65         this.y = y;
  66         this.v1 = v1;
  67         this.v2 = v2;
  68         this.c = c;
  69     }
  70 
  71     @DontInline
  72     public static MyValue1 createDontInline(int x, long y) {
  73         return __Make MyValue1(x, y, MyValue2.createInline(x, x < y), MyValue2.createInline(x, x > y), ValueTypeTestBench.rI);
  74     }
  75 
  76     @ForceInline
  77     public static MyValue1 createInline(int x, long y) {
  78         return __Make MyValue1(x, y, MyValue2.createInline(x, x < y), MyValue2.createInline(x, x > y), ValueTypeTestBench.rI);
  79     }
  80 
  81     @ForceInline
  82     public long hash() {
  83         return x + y + c + v1.hash() + v2.hash();
  84     }
  85 
  86     @DontCompile
  87     public long hashInterpreted() {
  88         return x + y + c + v1.hash() + v2.hash();
  89     }
  90 }
  91 
  92 __ByValue final class MyValue2 {
  93     final int x;
  94     final boolean b;
  95     final long c;
  96 
  97     private MyValue2(int x, boolean b, long c) {
  98         this.x = x;
  99         this.b = b;
 100         this.c = c;
 101     }
 102 
 103     @ForceInline
 104     public static MyValue2 createInline(int x, boolean b) {
 105         return __Make MyValue2(x, b, ValueTypeTestBench.rL);
 106     }
 107 
 108     @ForceInline
 109     public long hash() {
 110         return x + (b ? 0 : 1) + c;
 111     }





 112 }
 113 
 114 public class ValueTypeTestBench {
 115     // Print ideal graph after execution of each test
 116     private static final boolean PRINT_GRAPH = true;
 117 
 118     // ========== Helper methods ==========
 119 
 120     public long hash() {
 121         return hash(rI, rL);
 122     }
 123 
 124     public long hash(int x, long y) {
 125         return MyValue1.createInline(x, y).hash();
 126     }
 127 
 128     // ========== Test definitions ==========
 129 
 130     // Receive value type through call to interpreter
 131     @Test(failOn = ALLOC + STORE + TRAP)
 132     public long test1() {
 133         MyValue1 v = MyValue1.createDontInline(rI, rL);
 134         return v.hash();
 135     }
 136 
 137     @DontCompile
 138     public void test1_verifier(boolean warmup) {
 139         long result = test1();
 140         Asserts.assertEQ(result, hash());
 141     }
 142 
 143     // Receive value type from interpreter via parameter
 144     @Test(failOn = ALLOC + STORE + TRAP)
 145     public long test2(MyValue1 v) {
 146         return v.hash();
 147     }
 148 
 149     @DontCompile
 150     public void test2_verifier(boolean warmup) {
 151         MyValue1 v = MyValue1.createDontInline(rI, rL);
 152         long result = test2(v);
 153         Asserts.assertEQ(result, hash());
 154     }
 155 
 156     // Return incoming value type without accessing fields
 157     @Test(failOn = ALLOC + LOAD + STORE + TRAP)

 158     public MyValue1 test3(MyValue1 v) {
 159         return v;
 160     }
 161 
 162     @DontCompile
 163     public void test3_verifier(boolean warmup) {
 164         MyValue1 v1 = MyValue1.createDontInline(rI, rL);
 165         MyValue1 v2 = test3(v1);
 166         Asserts.assertEQ(v1.x, v2.x);
 167         Asserts.assertEQ(v1.y, v2.y);
 168     }
 169 
 170     // Create a value type in compiled code and only use fields.
 171     // Allocation should go away because value type does not escape.
 172     @Test(failOn = ALLOC + LOAD + STORE + TRAP)
 173     public long test4() {
 174         MyValue1 v = MyValue1.createInline(rI, rL);
 175         return v.hash();
 176     }
 177 
 178     @DontCompile
 179     public void test4_verifier(boolean warmup) {
 180         long result = test4();
 181         Asserts.assertEQ(result, hash());
 182     }
 183 
 184     // Create a value type in compiled code and pass it to
 185     // an inlined compiled method via a call.
 186     @Test(failOn = ALLOC + LOAD + STORE + TRAP)
 187     public long test5() {
 188         MyValue1 v = MyValue1.createInline(rI, rL);
 189         return test5Inline(v);
 190     }
 191 
 192     @ForceInline
 193     public long test5Inline(MyValue1 v) {
 194         return v.hash();
 195     }
 196 
 197     @DontCompile
 198     public void test5_verifier(boolean warmup) {
 199         long result = test5();
 200         Asserts.assertEQ(result, hash());
 201     }
 202 
 203     // Create a value type in compiled code and pass it to
 204     // the interpreter via a call.
 205     @Test(match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)

 206     public long test6() {
 207         MyValue1 v = MyValue1.createInline(rI, rL);
 208         // Pass to interpreter
 209         return v.hashInterpreted();
 210     }
 211 
 212     @DontCompile
 213     public void test6_verifier(boolean warmup) {
 214         long result = test6();
 215         Asserts.assertEQ(result, hash());
 216     }
 217 
 218     // Create a value type in compiled code and pass it to
 219     // the interpreter by returning.
 220     @Test(match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
 221     public MyValue1 test7(int x, long y) {
 222         return MyValue1.createInline(x, y);
 223     }
 224 
 225     @DontCompile
 226     public void test7_verifier(boolean warmup) {
 227         MyValue1 v = test7(rI, rL);
 228         Asserts.assertEQ(v.hash(), hash());
 229     }
 230 
 231     // Merge value types created from two branches
 232     @Test(failOn = ALLOC + STORE + TRAP)
 233     public long test8(boolean b) {
 234         MyValue1 v;
 235         if (b) {
 236             v = MyValue1.createInline(rI, rL);
 237         } else {
 238             v = MyValue1.createDontInline(rI + 1, rL + 1);
 239         }
 240         return v.hash();
 241     }
 242 
 243     @DontCompile
 244     public void test8_verifier(boolean warmup) {
 245         Asserts.assertEQ(test8(true), hash());
 246         Asserts.assertEQ(test8(false), hash(rI + 1, rL + 1));
 247     }
 248 
 249     // Merge value types created from two branches
 250     @Test(match = {ALLOC, STORE}, matchCount = {1, 9}, failOn = LOAD + TRAP)

 251     public MyValue1 test9(boolean b) {
 252         MyValue1 v;
 253         if (b) {
 254             // Value type is not allocated
 255             v = MyValue1.createInline(rI, rL);
 256         } else {
 257             // Value type is allocated by the callee
 258             v = MyValue1.createDontInline(rI + 1, rL + 1);
 259         }
 260         // Need to allocate value type if 'b' is true
 261         long sum = v.hashInterpreted();
 262         if (b) {
 263             v = MyValue1.createDontInline(rI, sum);
 264         } else {
 265             v = MyValue1.createDontInline(rI, sum + 1);
 266         }
 267         // Don't need to allocate value type because both branches allocate
 268         return v;
 269     }
 270 
 271     @DontCompile
 272     public void test9_verifier(boolean warmup) {
 273         MyValue1 v = test9(true);
 274         Asserts.assertEQ(v.x, rI);
 275         Asserts.assertEQ(v.y, hash());
 276         v = test9(false);
 277         Asserts.assertEQ(v.x, rI);
 278         Asserts.assertEQ(v.y, hash(rI + 1, rL + 1) + 1);
 279     }
 280 
 281     // Merge value types created in a loop (not inlined)
 282     @Test(failOn = ALLOC + STORE + TRAP)
 283     public long test10(int x, long y) {
 284         MyValue1 v = MyValue1.createDontInline(x, y);
 285         for (int i = 0; i < 10; ++i) {
 286             v = MyValue1.createDontInline(v.x + 1, v.y + 1);
 287         }
 288         return v.hash();
 289     }
 290 
 291     @DontCompile
 292     public void test10_verifier(boolean warmup) {
 293         long result = test10(rI, rL);
 294         Asserts.assertEQ(result, hash(rI + 10, rL + 10));
 295     }
 296 
 297     // Merge value types created in a loop (inlined)
 298     @Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP)
 299     public long test11(int x, long y) {
 300         MyValue1 v = MyValue1.createInline(x, y);
 301         for (int i = 0; i < 10; ++i) {
 302             v = MyValue1.createInline(v.x + 1, v.y + 1);
 303         }
 304         return v.hash();
 305     }
 306 
 307     @DontCompile
 308     public void test11_verifier(boolean warmup) {
 309         long result = test11(rI, rL);
 310         Asserts.assertEQ(result, hash(rI + 10, rL + 10));
 311     }
 312 
 313     // Test loop with uncommon trap referencing a value type
 314     @Test(match = {TRAP, SCOBJ}, matchCount = {1, 1}, failOn = ALLOC + LOAD + STORE)
 315     public long test12(boolean b) {
 316         MyValue1 v = MyValue1.createInline(rI, rL);
 317         long result = 42;
 318         for (int i = 0; i < 1000; ++i) {
 319             if (b) {
 320                 result += v.x;
 321             } else {
 322                 // Uncommon trap referencing v. We delegate allocation to the
 323                 // interpreter by adding a SafePointScalarObjectNode.
 324                 result = v.hashInterpreted();
 325             }
 326         }
 327         return result;
 328     }
 329 
 330     @DontCompile
 331     public void test12_verifier(boolean warmup) {
 332         long result = test12(warmup);
 333         Asserts.assertEQ(result, warmup ? 42 + (1000*rI) : hash());
 334     }
 335 
 336     // Test loop with uncommon trap referencing a value type
 337     @Test(match = {TRAP, LOAD}, matchCount = {1, 1}, failOn = ALLOC + STORE + SCOBJ)
 338     public long test13(boolean b) {
 339         MyValue1 v = MyValue1.createDontInline(rI, rL);
 340         long result = 42;
 341         for (int i = 0; i < 1000; ++i) {
 342             if (b) {
 343                 result += v.x;
 344             } else {
 345                 // Uncommon trap referencing v. Should not allocate
 346                 // but just pass the existing oop to the uncommon trap.
 347                 result = v.hashInterpreted();
 348             }
 349         }
 350         return result;
 351     }
 352 
 353     @DontCompile
 354     public void test13_verifier(boolean warmup) {
 355         long result = test13(warmup);
 356         Asserts.assertEQ(result, warmup ? 42 + (1000*rI) : hash());
 357     }
 358 
 359     // Create a value type in a non-inlined method and then call a
 360     // non-inlined method on that value type.
 361     @Test(failOn = (ALLOC + LOAD + STORE + TRAP))

 362     public long test14() {
 363         MyValue1 v = MyValue1.createDontInline(rI, rL);
 364         return v.hashInterpreted();
 365     }
 366 
 367     @DontCompile
 368     public void test14_verifier(boolean b) {
 369         long result = test14();
 370         Asserts.assertEQ(result, hash());
 371     }
 372 
 373     // Create a value type in an inlined method and then call a
 374     // non-inlined method on that value type.
 375     @Test(failOn = (LOAD + TRAP), match = {ALLOC}, matchCount = {1})

 376     public long test15() {
 377         MyValue1 v = MyValue1.createInline(rI, rL);
 378         return v.hashInterpreted();
 379     }
 380 
 381     @DontCompile
 382     public void test15_verifier(boolean b) {
 383         long result = test15();
 384         Asserts.assertEQ(result, hash());
 385     }
 386 
 387     // Create a value type in a non-inlined method and then call an
 388     // inlined method on that value type.
 389     @Test(failOn = (ALLOC + STORE + TRAP))
 390     public long test16() {
 391         MyValue1 v = MyValue1.createDontInline(rI, rL);
 392         return v.hash();
 393     }
 394 
 395     @DontCompile
 396     public void test16_verifier(boolean b) {
 397         long result = test16();
 398         Asserts.assertEQ(result, hash());
 399     }
 400 
 401     // Create a value type in an inlined method and then call an
 402     // inlined method on that value type.
 403     @Test(failOn = (ALLOC + LOAD + STORE + TRAP))
 404     public long test17() {
 405         MyValue1 v = MyValue1.createInline(rI, rL);
 406         return v.hash();
 407     }
 408 
 409     @DontCompile
 410     public void test17_verifier(boolean b) {
 411         long result = test17();
 412         Asserts.assertEQ(result, hash());
 413     }
 414 
 415     // Create a value type in compiled code and pass it to the
 416     // interpreter via a call. The value is live at the first call so
 417     // debug info should include a reference to all its fields.
 418     @Test(match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)

 419     public long test18() {
 420         MyValue1 v = MyValue1.createInline(rI, rL);
 421         v.hashInterpreted();
 422         return v.hashInterpreted();
 423     }
 424 
 425     @DontCompile
 426     public void test18_verifier(boolean warmup) {
 427         long result = test18();
 428         Asserts.assertEQ(result, hash());
 429     }
 430 
 431     // Create a value type in compiled code and pass it to the
 432     // interpreter via a call. The value type is passed twice but
 433     // should only be allocated once.
 434     @Test(match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)

 435     public long test19() {
 436         MyValue1 v = MyValue1.createInline(rI, rL);
 437         return sumValue(v, v);
 438     }
 439 
 440     @DontCompile
 441     public long sumValue(MyValue1 v, MyValue1 dummy) {
 442         return v.hash();
 443     }
 444 
 445     @DontCompile
 446     public void test19_verifier(boolean warmup) {
 447         long result = test19();
 448         Asserts.assertEQ(result, hash());
 449     }
 450 
 451     // Create a value type in compiled code and pass it to the
 452     // interpreter via a call. The value type is live at the uncommon
 453     // trap: verify that deoptimization causes the value type to be
 454     // correctly allocated.
 455     @Test(match = {ALLOC}, matchCount = {1}, failOn = LOAD)

 456     public long test20(boolean flag) {
 457         MyValue1 v = MyValue1.createInline(rI, rL);
 458         if (flag) {
 459             // uncommon trap
 460             WHITE_BOX.deoptimizeMethod(tests.get("ValueTypeTestBench::test16"));
 461         }
 462         return v.hashInterpreted();
 463     }
 464 
 465     @DontCompile
 466     public void test20_verifier(boolean warmup) {
 467         long result = test20(false);
 468         Asserts.assertEQ(result, hash());
 469         if (!warmup) {
 470             result = test20(true);
 471             Asserts.assertEQ(result, hash());
 472         }
 473     }
 474 
 475     // Value type fields in regular object
 476     MyValue1 val1;
 477     MyValue2 val2;
 478 
 479     // Test value type fields in objects
 480     @Test(failOn = (ALLOC + TRAP))
 481     public long test21(int x, long y) {
 482         // Compute hash of value type fields
 483         long result = val1.hash() + val2.hash();
 484         // Update fields
 485         val1 = MyValue1.createInline(x, y);
 486         val2 = MyValue2.createInline(x, true);
 487         return result;
 488     }
 489 
 490     @DontCompile
 491     public void test21_verifier(boolean warmup) {
 492         // Check if hash computed by test18 is correct
 493         val1 = MyValue1.createInline(rI, rL);
 494         val2 = val1.v2;
 495         long hash = val1.hash() + val2.hash();
 496         long result = test21(rI + 1, rL + 1);
 497         Asserts.assertEQ(result, hash);
 498         // Check if value type fields were updated
 499         Asserts.assertEQ(val1.hash(), hash(rI + 1, rL + 1));
 500         Asserts.assertEQ(val2.hash(), MyValue2.createInline(rI + 1, true).hash());
 501     }
 502 











































































































































































































 503 
 504     // ========== Test infrastructure ==========
 505 
 506     private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();




 507     private static final int COMP_LEVEL_ANY = -1;
 508     private static final int COMP_LEVEL_FULL_OPTIMIZATION = 4;
 509     private static final Hashtable<String, Method> tests = new Hashtable<String, Method>();
 510     private static final int WARMUP = 10;
 511     private static boolean USE_COMPILER = WHITE_BOX.getBooleanVMFlag("UseCompiler");
 512     private static boolean PRINT_IDEAL  = WHITE_BOX.getBooleanVMFlag("PrintIdeal");
 513 
 514     // Regular expressions used  to match nodes in the PrintIdeal output
 515     private static final String START = "(\\d+\\t(.*";
 516     private static final String MID = ".*)+\\t===.*";
 517     private static final String END = ")|";
 518     private static final String ALLOC = START + "CallStaticJava" + MID + "_new_instance_Java" + END;
 519     private static final String LOAD  = START + "Load" + MID + "valuetype\\*" + END;
 520     private static final String STORE = START + "Store" + MID + "valuetype\\*" + END;
 521     private static final String LOOP  = START + "Loop" + MID + "" + END;
 522     private static final String TRAP  = START + "CallStaticJava" + MID + "uncommon_trap" + END;
 523     // TODO: match field values of scalar replaced object
 524     private static final String SCOBJ = "(.*# ScObj.*" + END;
 525 
 526     // Random test values
 527     public static final int  rI = Utils.getRandomInstance().nextInt() % 1000;
 528     public static final long rL = Utils.getRandomInstance().nextLong() % 1000;
 529 
 530     static {
 531         // Gather all test methods and put them in Hashtable
 532         for (Method m : ValueTypeTestBench.class.getDeclaredMethods()) {
 533             if (m.isAnnotationPresent(Test.class)) {

 534                 tests.put("ValueTypeTestBench::" + m.getName(), m);
 535             }
 536         }
 537     }
 538 
 539     public static void main(String[] args) throws Throwable {
 540         if (args.length == 0) {
 541             // Run tests in own process and verify output
 542             OutputAnalyzer oa = ProcessTools.executeTestJvm("-noverify",
 543                     "-XX:+UnlockDiagnosticVMOptions", "-Xbootclasspath/a:.", "-XX:+WhiteBoxAPI",
 544                     "-XX:-TieredCompilation", "-XX:-BackgroundCompilation", "-XX:-UseOnStackReplacement",
 545                     "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+PrintCompilation", "-XX:+PrintIdeal", "-XX:+PrintOptoAssembly",
 546                     "-XX:CompileCommand=quiet", "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.ValueTypeTestBench::*",
 547                     "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.MyValue1::*",
 548                     "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.MyValue2::*",
 549                     ValueTypeTestBench.class.getName(), "run");










 550             // If ideal graph printing is enabled/supported, verify output
 551             String output = oa.getOutput();
 552             oa.shouldHaveExitValue(0);
 553             if (output.contains("PrintIdeal enabled")) {
 554                 parseOutput(output);
 555             } else {
 556                 System.out.println("WARNING: test methods not compiled or PrintIdeal disabled! Running with -Xint or release build?");
 557             }
 558         } else {
 559             if (USE_COMPILER && PRINT_IDEAL) {
 560                 System.out.println("PrintIdeal enabled");
 561             }
 562             // Execute tests
 563             ValueTypeTestBench bench = new ValueTypeTestBench();
 564             bench.run();
 565         }
 566     }
 567 
 568     public static void parseOutput(String output) throws Exception {
 569         String split = "b        compiler.valhalla.valuetypes.";
 570         String[] compilations = output.split(split);
 571         // Print header
 572         System.out.println(compilations[0]);
 573         // Iterate over compilation output
 574         for (String graph : compilations) {
 575             String[] lines = graph.split("\\n");
 576             String testName = lines[0].split(" ")[0];
 577             Method test = tests.get(testName);
 578             if (test == null) {
 579                 // Skip helper methods
 580                 continue;
 581             }
 582             if (PRINT_GRAPH) {
 583                 System.out.println("\nGraph for " + graph);
 584             }
 585             // Parse graph using regular expressions to determine if it contains forbidden nodes
 586             Test anno = test.getAnnotation(Test.class);











 587             String regexFail = anno.failOn();
 588             if (!regexFail.isEmpty()) {
 589                 Pattern pattern = Pattern.compile(regexFail.substring(0, regexFail.length()-1));
 590                 Matcher matcher = pattern.matcher(graph);
 591                 boolean fail = false;
 592                 while (matcher.find()) {
 593                     System.out.println("Graph for '" + testName + "' contains forbidden node:");
 594                     System.out.println(matcher.group());
 595                     fail = true;
 596                 }
 597                 Asserts.assertFalse(fail, "Graph for '" + testName + "' contains forbidden nodes");
 598             }
 599             String[] regexMatch = anno.match();
 600             int[] matchCount = anno.matchCount();
 601             for (int i = 0; i < regexMatch.length; ++i) {
 602                 Pattern pattern = Pattern.compile(regexMatch[i].substring(0, regexMatch[i].length()-1));
 603                 Matcher matcher = pattern.matcher(graph);
 604                 int count = 0;
 605                 String nodes = "";
 606                 while (matcher.find()) {
 607                     count++;
 608                     nodes += matcher.group() + "\n";
 609                 }
 610                 if (matchCount[i] != count) {
 611                     System.out.println("Graph for '" + testName + "' contains different number of match nodes:");
 612                     System.out.println(nodes);
 613                 }
 614                 Asserts.assertEQ(matchCount[i], count, "Graph for '" + testName + "' contains different number of match nodes");
 615             }
 616             tests.remove(testName);
 617             System.out.println(testName + " passed");
 618         }
 619         // Check if all tests were compiled
 620         if (tests.size() != 0) {
 621             for (String name : tests.keySet()) {
 622                 System.out.println("Test '" + name + "' not compiled!");
 623             }
 624             throw new RuntimeException("Not all tests were compiled");
 625         }
 626     }
 627 
 628     public void setup(Method[] methods) {
 629         for (Method m : methods) {
 630             if (m.isAnnotationPresent(Test.class)) {
 631                 // Don't inline tests
 632                 WHITE_BOX.testSetDontInlineMethod(m, true);
 633             }
 634             if (m.isAnnotationPresent(DontCompile.class)) {
 635                 WHITE_BOX.makeMethodNotCompilable(m, COMP_LEVEL_ANY, true);
 636                 WHITE_BOX.makeMethodNotCompilable(m, COMP_LEVEL_ANY, false);
 637             }
 638             if (m.isAnnotationPresent(ForceInline.class)) {
 639                 WHITE_BOX.testSetForceInlineMethod(m, true);
 640             } else if (m.isAnnotationPresent(DontInline.class)) {
 641                 WHITE_BOX.testSetDontInlineMethod(m, true);
 642             }
 643         }
 644     }
 645 
 646     public void run() throws Exception {
 647         System.out.format("rI = %d, rL = %d\n", rI, rL);
 648         setup(this.getClass().getDeclaredMethods());
 649         setup(MyValue1.class.getDeclaredMethods());
 650         setup(MyValue2.class.getDeclaredMethods());
 651 
 652         // Execute tests
 653         for (Method test : tests.values()) {
 654             Method verifier = getClass().getDeclaredMethod(test.getName() + "_verifier", boolean.class);
 655             // Warmup using verifier method
 656             for (int i = 0; i < WARMUP; ++i) {
 657                 verifier.invoke(this, true);
 658             }
 659             // Trigger compilation
 660             WHITE_BOX.enqueueMethodForCompilation(test, COMP_LEVEL_FULL_OPTIMIZATION);
 661             Asserts.assertTrue(!USE_COMPILER || WHITE_BOX.isMethodCompiled(test, false), test + " not compiled");
 662             // Check result
 663             verifier.invoke(this, false);
 664         }
 665     }
 666 }
 667 
 668 // Mark method as test
 669 @Retention(RetentionPolicy.RUNTIME)

 670 @interface Test {
 671     // Regular expression used to match forbidden IR nodes
 672     // in the C2 IR emitted for this test.
 673     String failOn() default "";
 674     // Regular expressions used to match and count IR nodes.
 675     String[] match() default { };
 676     int[] matchCount() default { };






 677 }
 678 
 679 // Force method inlining during compilation
 680 @Retention(RetentionPolicy.RUNTIME)
 681 @interface ForceInline { }
 682 
 683 // Prevent method inlining during compilation
 684 @Retention(RetentionPolicy.RUNTIME)
 685 @interface DontInline { }
 686 
 687 // Prevent method compilation
 688 @Retention(RetentionPolicy.RUNTIME)
 689 @interface DontCompile { }
--- EOF ---