1 /*
   2  * Copyright (c) 2021, 2025, 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 ir_framework.tests;
  25 
  26 import compiler.lib.ir_framework.*;
  27 import compiler.lib.ir_framework.driver.irmatching.IRViolationException;
  28 import jdk.test.lib.Asserts;
  29 import jdk.test.lib.Platform;
  30 import jdk.test.whitebox.WhiteBox;
  31 
  32 import java.io.ByteArrayOutputStream;
  33 import java.io.PrintStream;
  34 import java.util.*;
  35 import java.util.regex.Matcher;
  36 import java.util.regex.Pattern;
  37 
  38 /*
  39  * @test
  40  * @requires vm.debug == true & vm.compMode != "Xint" & vm.compiler1.enabled & vm.compiler2.enabled & vm.flagless
  41  * @summary Test IR matcher with different default IR node regexes. Use -DPrintIREncoding.
  42  *          Normally, the framework should be called with driver.
  43  * @library /test/lib /testlibrary_tests /
  44  * @build jdk.test.whitebox.WhiteBox
  45  * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
  46  * @run main/othervm/timeout=240 -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
  47  *                               -XX:+WhiteBoxAPI -DPrintIREncoding=true  ir_framework.tests.TestIRMatching
  48  */
  49 
  50 public class TestIRMatching {
  51 
  52     private static final Map<Exception, String> exceptions = new LinkedHashMap<>();
  53     private static final ByteArrayOutputStream baos = new ByteArrayOutputStream();
  54     private static final ByteArrayOutputStream baosErr = new ByteArrayOutputStream();
  55     private static final PrintStream ps = new PrintStream(baos);
  56     private static final PrintStream psErr = new PrintStream(baosErr);
  57     private static final PrintStream oldOut = System.out;
  58     private static final PrintStream oldErr = System.err;
  59 
  60     private static void addException(Exception e) {
  61         System.out.flush();
  62         System.err.flush();
  63         exceptions.put(e, baos + System.lineSeparator() + baosErr);
  64     }
  65 
  66     public static void main(String[] args) {
  67         // Redirect System.out and System.err to reduce noise.
  68         System.setOut(ps);
  69         System.setErr(psErr);
  70         runWithArguments(AndOr1.class, "-XX:TLABRefillWasteFraction=52", "-XX:+UsePerfData", "-XX:+UseTLAB");
  71         runWithArguments(CountComparisons.class, "-XX:TLABRefillWasteFraction=50");
  72         runWithArguments(GoodCount.class, "-XX:TLABRefillWasteFraction=50");
  73         runWithArguments(MultipleFailOnGood.class, "-XX:TLABRefillWasteFraction=50");
  74 
  75         runCheck(new String[] {"-XX:TLABRefillWasteFraction=50", "-XX:+UsePerfData", "-XX:+UseTLAB"}, BadFailOnConstraint.create(AndOr1.class, "test1(int)", 1, "CallStaticJava"));
  76         runCheck(new String[] {"-XX:TLABRefillWasteFraction=50", "-XX:-UsePerfData", "-XX:+UseTLAB"}, BadFailOnConstraint.create(AndOr1.class, "test2()", 1, "CallStaticJava"));
  77 
  78         runCheck(BadFailOnConstraint.create(MultipleFailOnBad.class, "fail1()", 1, 1, "Store"),
  79                  BadFailOnConstraint.create(MultipleFailOnBad.class, "fail1()", 1,  3, "Store"),
  80                  GoodFailOnRegexConstraint.create(MultipleFailOnBad.class, "fail1()", 1,  2, 4),
  81                  GoodFailOnRegexConstraint.create(MultipleFailOnBad.class, "fail2()", 1,  1),
  82                  BadFailOnConstraint.create(MultipleFailOnBad.class, "fail2()", 1,  2, "CallStaticJava"),
  83                  BadFailOnConstraint.create(MultipleFailOnBad.class, "fail3()", 1,  2, "Store"),
  84                  GoodFailOnRegexConstraint.create(MultipleFailOnBad.class, "fail3()", 1,  1, 3),
  85                  BadFailOnConstraint.create(MultipleFailOnBad.class, "fail4()", 1,  1, "Store"),
  86                  GoodFailOnRegexConstraint.create(MultipleFailOnBad.class, "fail4()", 1,  2, 3),
  87                  BadFailOnConstraint.create(MultipleFailOnBad.class, "fail5()", 1,  1, "Store"),
  88                  GoodFailOnRegexConstraint.create(MultipleFailOnBad.class, "fail5()", 1,  2, 3),
  89                  GoodFailOnRegexConstraint.create(MultipleFailOnBad.class, "fail6()", 1,  1),
  90                  BadFailOnConstraint.create(MultipleFailOnBad.class, "fail6()", 1,  2, "MyClass"),
  91                  BadFailOnConstraint.create(MultipleFailOnBad.class, "fail6()", 1,  3, "CallStaticJava"),
  92                  GoodFailOnRegexConstraint.create(MultipleFailOnBad.class, "fail7()", 1,  1),
  93                  BadFailOnConstraint.create(MultipleFailOnBad.class, "fail7()", 1,  2, "MyClass"),
  94                  GoodFailOnRegexConstraint.create(MultipleFailOnBad.class, "fail8()", 1,  1),
  95                  BadFailOnConstraint.create(MultipleFailOnBad.class, "fail8()", 1,  2, "MyClass"),
  96                  BadFailOnConstraint.create(MultipleFailOnBad.class, "fail9()", 1,  1, "Store"),
  97                  BadFailOnConstraint.create(MultipleFailOnBad.class, "fail9()", 1,  2, "CallStaticJava"),
  98                  BadFailOnConstraint.create(MultipleFailOnBad.class, "fail10()", 1,  1, "Store", "iFld"),
  99                  GoodFailOnRegexConstraint.create(MultipleFailOnBad.class, "fail10()", 1,  2, 3)
 100         );
 101 
 102         runCheck(BadCountsConstraint.create(BadCount.class, "bad1()", 1, 2, "Load"),
 103                  GoodCountsConstraint.create(BadCount.class, "bad1()", 2),
 104                  GoodCountsConstraint.create(BadCount.class, "bad2()", 1),
 105                  BadCountsConstraint.create(BadCount.class, "bad2()", 2,  2, "Store"),
 106                  BadCountsConstraint.create(BadCount.class, "bad3()", 1,  2, "Load"),
 107                  BadCountsConstraint.create(BadCount.class, "bad3()", 2,  2, "Store")
 108         );
 109 
 110         runCheck(GoodRuleConstraint.create(Calls.class, "calls()", 1),
 111                  BadFailOnConstraint.create(Calls.class, "calls()", 2, 1, "CallStaticJava", "dontInline"),
 112                  BadFailOnConstraint.create(Calls.class, "calls()", 2, 2, "CallStaticJava", "dontInline"),
 113                  GoodRuleConstraint.create(Calls.class, "calls()", 3)
 114         );
 115 
 116         runCheck(BadFailOnConstraint.create(AllocInstance.class, "allocInstance()", 1),
 117                 BadFailOnConstraint.create(AllocInstance.class, "allocInstance()", 2),
 118                 GoodFailOnConstraint.create(AllocInstance.class, "allocInstance()", 3),
 119                 GoodFailOnConstraint.create(AllocInstance.class, "allocInstance()", 4),
 120                 GoodFailOnConstraint.create(AllocInstance.class, "allocInstance()", 5),
 121                 BadFailOnConstraint.create(AllocInstance.class, "allocInstance()", 6),
 122                 BadFailOnConstraint.create(AllocInstance.class, "allocInstance()", 7),
 123                 GoodFailOnConstraint.create(AllocInstance.class, "allocInstance()", 8),
 124                 GoodFailOnConstraint.create(AllocInstance.class, "allocInstance()", 9),
 125                 GoodFailOnConstraint.create(AllocInstance.class, "allocInstance()", 10)
 126         );
 127 
 128         runCheck(
 129                 BadFailOnConstraint.create(AllocInstance.class, "allocNested()", 1),
 130                 BadFailOnConstraint.create(AllocInstance.class, "allocNested()", 2),
 131                 BadFailOnConstraint.create(AllocInstance.class, "allocNested()", 3)
 132         );
 133 
 134         runCheck(BadFailOnConstraint.create(AllocArray.class, "allocArray()", 1),
 135                  BadFailOnConstraint.create(AllocArray.class, "allocArray()", 2),
 136                  GoodFailOnConstraint.create(AllocArray.class, "allocArray()", 3),
 137                  GoodFailOnConstraint.create(AllocArray.class, "allocArray()", 4),
 138                  GoodFailOnConstraint.create(AllocArray.class, "allocArray()", 5),
 139                  BadFailOnConstraint.create(AllocArray.class, "allocArray()", 6),
 140                  BadFailOnConstraint.create(AllocArray.class, "allocArray()", 7),
 141                  GoodFailOnConstraint.create(AllocArray.class, "allocArray()", 8),
 142                  GoodFailOnConstraint.create(AllocArray.class, "allocArray()", 9),
 143                  GoodFailOnConstraint.create(AllocArray.class, "allocArray()", 10)
 144         );
 145 
 146         runCheck(BadFailOnConstraint.create(AllocArray.class, "allocMultiArray()", 1),
 147                  BadFailOnConstraint.create(AllocArray.class, "allocMultiArray()", 2),
 148                  GoodFailOnConstraint.create(AllocArray.class, "allocMultiArray()", 3),
 149                  GoodFailOnConstraint.create(AllocArray.class, "allocMultiArray()", 4),
 150                  GoodFailOnConstraint.create(AllocArray.class, "allocMultiArray()", 5),
 151                  BadFailOnConstraint.create(AllocArray.class, "allocMultiArray()", 6),
 152                  BadFailOnConstraint.create(AllocArray.class, "allocMultiArray()", 7),
 153                  GoodFailOnConstraint.create(AllocArray.class, "allocMultiArray()", 8),
 154                  GoodFailOnConstraint.create(AllocArray.class, "allocMultiArray()", 9),
 155                  GoodFailOnConstraint.create(AllocArray.class, "allocMultiArray()", 10)
 156         );
 157 
 158         runCheck(GoodRuleConstraint.create(RunTests.class, "good1()", 1),
 159                  GoodRuleConstraint.create(RunTests.class, "good1()", 2),
 160                  GoodRuleConstraint.create(RunTests.class, "good2()", 1),
 161                  GoodRuleConstraint.create(RunTests.class, "good2()", 2),
 162                  GoodRuleConstraint.create(RunTests.class, "good3(int)", 1),
 163                  BadCountsConstraint.create(RunTests.class, "bad1(int)", 1, 0),
 164                  BadFailOnConstraint.create(RunTests.class, "bad1(int)", 2, "Load")
 165         );
 166 
 167         runCheck(new String[] {"-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UseCompressedClassPointers"},
 168                  BadFailOnConstraint.create(Loads.class, "load()", 1, 1, "Load"),
 169                  BadFailOnConstraint.create(Loads.class, "load()", 1, 3, "LoadI"),
 170                  BadCountsConstraint.create(Loads.class, "load()", 1, 1, 0),
 171                  BadCountsConstraint.create(Loads.class, "load()", 1, 2, 1,"Load"),
 172                  GoodRuleConstraint.create(Loads.class, "load()", 2),
 173                  GoodFailOnConstraint.create(Loads.class, "load()", 3),
 174                  BadCountsConstraint.create(Loads.class, "load()", 3, 2, 2,"Store"),
 175                  BadFailOnConstraint.create(Loads.class, "load()", 4, 2, "Store"),
 176                  BadFailOnConstraint.create(Loads.class, "load()", 5, "Load"),
 177                  BadFailOnConstraint.create(Loads.class, "load()", 6, "Load"),
 178                  BadFailOnConstraint.create(Loads.class, "load()", 7, "Load"),
 179                  GoodRuleConstraint.create(Loads.class, "load()", 8),
 180                  GoodRuleConstraint.create(Loads.class, "load()", 9),
 181                  GoodRuleConstraint.create(Loads.class, "load()", 10),
 182                  BadFailOnConstraint.create(Loads.class, "loadKlass()", 1),
 183                  BadCountsConstraint.create(Loads.class, "loadKlass()", 2, 2,"Field")
 184                  );
 185 
 186         // Loops
 187         runCheck(BadFailOnConstraint.create(Loops.class, "loop()", 1, "Loop"),
 188                  GoodRuleConstraint.create(Loops.class, "loop()", 2),
 189                  GoodRuleConstraint.create(Loops.class, "loop()", 3),
 190                  GoodRuleConstraint.create(Loops.class, "countedLoop()", 1),
 191                  BadFailOnConstraint.create(Loops.class, "countedLoop()", 2, "CountedLoop"),
 192                  GoodRuleConstraint.create(Loops.class, "countedLoop()", 3),
 193                  BadFailOnConstraint.create(Loops.class, "loopAndCountedLoop()", 1, "Loop"),
 194                  BadFailOnConstraint.create(Loops.class, "loopAndCountedLoop()", 2, "CountedLoop"),
 195                  GoodRuleConstraint.create(Loops.class, "loopAndCountedLoop()", 3),
 196                  GoodRuleConstraint.create(Loops.class, "countedLoopMain()", 1),
 197                  BadFailOnConstraint.create(Loops.class, "countedLoopMain()", 2, "CountedLoop"),
 198                  BadFailOnConstraint.create(Loops.class, "countedLoopMain()", 3, "CountedLoop", "main"),
 199                  GoodRuleConstraint.create(Loops.class, "countedLoopUnrolled()", 1),
 200                  GoodRuleConstraint.create(Loops.class, "countedLoopUnrolled()", 2),
 201                  GoodRuleConstraint.create(Loops.class, "countedLoopUnrolled()", 3)
 202         );
 203 
 204         // Traps
 205         runCheck(GoodRuleConstraint.create(Traps.class, "noTraps()", 1),
 206                  BadFailOnConstraint.create(Traps.class, "noTraps()", 2, "Store", "iFld"),
 207                  GoodRuleConstraint.create(Traps.class, "noTraps()", 3),
 208                  BadFailOnConstraint.create(Traps.class, "predicateTrap()", 1, "CallStaticJava", "uncommon_trap"),
 209                  BadFailOnConstraint.create(Traps.class, "predicateTrap()", 2, "CallStaticJava", "uncommon_trap", "predicate"),
 210                  GoodRuleConstraint.create(Traps.class, "predicateTrap()", 3),
 211                  GoodRuleConstraint.create(Traps.class, "predicateTrap()", 4),
 212                  BadFailOnConstraint.create(Traps.class, "nullCheck()", 1, "CallStaticJava", "uncommon_trap"),
 213                  BadFailOnConstraint.create(Traps.class, "nullCheck()", 2, "CallStaticJava", "uncommon_trap", "null_check"),
 214                  BadFailOnConstraint.create(Traps.class, "nullCheck()", 3, "uncommon_trap", "class_check"),
 215                  GoodRuleConstraint.create(Traps.class, "nullCheck()", 4),
 216                  BadFailOnConstraint.create(Traps.class, "nullAssert()", 1, "CallStaticJava", "uncommon_trap"),
 217                  BadFailOnConstraint.create(Traps.class, "nullAssert()", 2, "CallStaticJava", "uncommon_trap", "null_assert"),
 218                  BadFailOnConstraint.create(Traps.class, "nullAssert()", 3, "CallStaticJava", "uncommon_trap", "null_check"),
 219                  GoodRuleConstraint.create(Traps.class, "nullAssert()", 4),
 220                  BadFailOnConstraint.create(Traps.class, "unstableIf(boolean)", 1, "CallStaticJava", "uncommon_trap"),
 221                  BadFailOnConstraint.create(Traps.class, "unstableIf(boolean)",  2, "CallStaticJava", "uncommon_trap", "unstable_if"),
 222                  GoodRuleConstraint.create(Traps.class, "unstableIf(boolean)", 3),
 223                  BadFailOnConstraint.create(Traps.class, "classCheck()", 1, "CallStaticJava", "uncommon_trap"),
 224                  BadFailOnConstraint.create(Traps.class, "classCheck()", 2, "CallStaticJava", "uncommon_trap", "class_check"),
 225                  BadFailOnConstraint.create(Traps.class, "classCheck()", 3, "CallStaticJava", "uncommon_trap", "null_check"),
 226                  GoodRuleConstraint.create(Traps.class, "classCheck()", 4),
 227                  BadFailOnConstraint.create(Traps.class, "rangeCheck()", 1, "CallStaticJava", "uncommon_trap"),
 228                  BadFailOnConstraint.create(Traps.class, "rangeCheck()", 2, "CallStaticJava", "uncommon_trap", "range_check"),
 229                  BadFailOnConstraint.create(Traps.class, "rangeCheck()", 3, "CallStaticJava", "uncommon_trap", "null_check"),
 230                  GoodRuleConstraint.create(Traps.class, "rangeCheck()", 4),
 231                  BadFailOnConstraint.create(Traps.class, "instrinsicOrTypeCheckedInlining()", 1, "CallStaticJava", "uncommon_trap"),
 232                  WhiteBox.getWhiteBox().isJVMCISupportedByGC() ?
 233                     BadFailOnConstraint.create(Traps.class, "instrinsicOrTypeCheckedInlining()", 2, "CallStaticJava", "uncommon_trap", "intrinsic_or_type_checked_inlining")
 234                     : GoodRuleConstraint.create(Traps.class, "instrinsicOrTypeCheckedInlining()", 2),
 235                  BadFailOnConstraint.create(Traps.class, "instrinsicOrTypeCheckedInlining()", 3, "CallStaticJava", "uncommon_trap", "intrinsic"),
 236                  BadFailOnConstraint.create(Traps.class, "instrinsicOrTypeCheckedInlining()", 4, "CallStaticJava", "uncommon_trap", "null_check"),
 237                  GoodRuleConstraint.create(Traps.class, "instrinsicOrTypeCheckedInlining()", 5)
 238         );
 239 
 240 
 241         runCheck(new String[] {"-XX:+BailoutToInterpreterForThrows"},
 242                  BadFailOnConstraint.create(UnhandledTrap.class, "unhandled()", 1, "CallStaticJava", "uncommon_trap"),
 243                  BadFailOnConstraint.create(UnhandledTrap.class, "unhandled()", 2, "CallStaticJava", "uncommon_trap", "unhandled"),
 244                  GoodRuleConstraint.create(UnhandledTrap.class, "unhandled()", 3)
 245         );
 246 
 247         runCheck(BadFailOnConstraint.create(ScopeObj.class, "scopeObject()", 1, "ScObj"));
 248         runCheck(BadFailOnConstraint.create(Membar.class, "membar()", 1, "MemBar"));
 249 
 250         String cmp;
 251         if (Platform.isPPC() || Platform.isX86()) {
 252             cmp = "CMP";
 253         } else if (Platform.isS390x()){
 254             cmp = "CLFI";
 255         } else {
 256             cmp = "cmp";
 257         }
 258         runCheck(BadFailOnConstraint.create(CheckCastArray.class, "array(java.lang.Object[])", 1, cmp, "precise"),
 259                  BadFailOnConstraint.create(CheckCastArray.class, "array(java.lang.Object[])", 2, 1,cmp, "precise", "MyClass"),
 260                  BadFailOnConstraint.create(CheckCastArray.class, "array(java.lang.Object[])", 2, 2,cmp, "precise", "ir_framework/tests/MyClass"),
 261                  GoodFailOnConstraint.create(CheckCastArray.class, "array(java.lang.Object[])", 3),
 262                  Platform.isS390x() ? // There is no checkcast_arraycopy stub for C2 on s390
 263                      GoodFailOnConstraint.create(CheckCastArray.class, "arrayCopy(java.lang.Object[],java.lang.Class)", 1)
 264                      : BadFailOnConstraint.create(CheckCastArray.class, "arrayCopy(java.lang.Object[],java.lang.Class)", 1, "checkcast_arraycopy")
 265         );
 266 
 267         try {
 268             runWithArgumentsFail(CompilationOutputOfFails.class);
 269             Asserts.fail("Should have thrown exception");
 270         } catch (IRViolationException e) {
 271             try {
 272                 StringBuilder failures = new StringBuilder();
 273                 System.out.flush();
 274                 String output = baos.toString();
 275                 baos.reset();
 276                 Pattern pattern = Pattern.compile(compilationPrefix() + ".*both\\d.*\\R> Phase \""
 277                                                   + CompilePhase.PRINT_IDEAL.getName()
 278                                                   + "\":(?:(?!PrintOpto|" + compilationPrefix()
 279                                                   + ")[\\S\\s])+PrintOptoAssembly");
 280                 Matcher matcher = pattern.matcher(output);
 281                 long bothCount = matcher.results().count();
 282                 if (bothCount != 7L) {
 283                     failures.append("- Could not find all both() methods, expected 7 but found ").append(bothCount)
 284                             .append(System.lineSeparator());
 285                 }
 286                 pattern = Pattern.compile(compilationPrefix() + ".*ideal\\d.*\\R> Phase \""
 287                                           + CompilePhase.PRINT_IDEAL.getName()
 288                                           + "\":(?:(?!" + compilationPrefix() + ")[\\S\\s])+");
 289                 matcher = pattern.matcher(output);
 290                 int count = 0;
 291                 while (matcher.find()) {
 292                     String match = matcher.group();
 293                     if (match.contains("PrintOptoAssembly")) {
 294                         failures.append("Cannot contain opto assembly: ").append(System.lineSeparator()).append(match);
 295                     }
 296                     count++;
 297                 }
 298                 if (count != 7) {
 299                     failures.append("- Could not find all ideal() methods, expected 7 but found ").append(count)
 300                             .append(System.lineSeparator());
 301                 }
 302                 pattern = Pattern.compile(compilationPrefix() + ".*macro\\d.*\\R> Phase \""
 303                         + CompilePhase.BEFORE_MACRO_EXPANSION.getName()
 304                         + "\":(?:(?!" + compilationPrefix() + ")[\\S\\s])+");
 305                 matcher = pattern.matcher(output);
 306                 count = 0;
 307                 while (matcher.find()) {
 308                     String match = matcher.group();
 309                     if (match.contains("PrintIdeal")) {
 310                         failures.append("Cannot contain print assembly: ").append(System.lineSeparator()).append(match);
 311                     }
 312                     count++;
 313                 }
 314                 if (count != 7) {
 315                     failures.append("- Could not find all macro() methods, expected 7 but found ").append(count).append(System.lineSeparator());
 316                 }
 317                 if (!failures.isEmpty()) {
 318                     addException(new RuntimeException(failures.toString()));
 319                 }
 320             } catch (Exception e1) {
 321                 addException(e1);
 322             }
 323         } catch (Exception e) {
 324             addException(e);
 325         }
 326 
 327         runWithArguments(FlagComparisons.class, "-XX:TLABRefillWasteFraction=50");
 328         System.out.flush();
 329         String output = baos.toString();
 330         findIrIds(output, "testMatchAllIf50", 1, 22);
 331         findIrIds(output, "testMatchNoneIf50", -1, -1);
 332 
 333         runWithArguments(FlagComparisons.class, "-XX:TLABRefillWasteFraction=49");
 334         System.out.flush();
 335         output = baos.toString();
 336         findIrIds(output, "testMatchAllIf50", 5, 7, 14, 19);
 337         findIrIds(output, "testMatchNoneIf50", 1, 4, 9, 11, 18, 23);
 338 
 339         runWithArguments(FlagComparisons.class, "-XX:TLABRefillWasteFraction=51");
 340         System.out.flush();
 341         output = baos.toString();
 342         findIrIds(output, "testMatchAllIf50", 8, 13, 20, 22);
 343         findIrIds(output, "testMatchNoneIf50", 5, 8, 12, 17, 21, 23);
 344         System.setOut(oldOut);
 345         System.setErr(oldErr);
 346 
 347         if (!exceptions.isEmpty()) {
 348             System.err.println("TestIRMatching failed with " + exceptions.size() + " exception(s):");
 349             int i = 1;
 350             System.err.println("************************");
 351             for (Map.Entry<Exception, String> entry : exceptions.entrySet()) {
 352                 System.err.println("***** Exception " + String.format("%02d", i++) +" *****");
 353                 System.err.println("************************");
 354 
 355                 Exception e = entry.getKey();
 356                 e.printStackTrace(System.err);
 357                 System.err.println();
 358                 System.err.println("===== OUTPUT ======");
 359                 System.err.println(entry.getValue());
 360                 System.err.println("MESSAGE: " + e.getMessage());
 361                 System.err.println("************************");
 362             }
 363             i = 1;
 364             System.err.println("====================================");
 365             System.err.println("********************");
 366             System.err.println("***** OVERVIEW *****");
 367             System.err.println("********************");
 368             for (Map.Entry<Exception, String> entry : exceptions.entrySet()) {
 369                 System.err.print((i++) + ") ");
 370                 entry.getKey().printStackTrace(System.err);
 371                 System.err.println("********************");
 372             }
 373             throw new RuntimeException("TestIRMatching failed with " + exceptions.size() + " exception(s) - check stderr and stdout");
 374         }
 375     }
 376 
 377     private static void runFramework(TestFramework framework) {
 378         baos.reset();
 379         baosErr.reset();
 380         framework.start();
 381     }
 382 
 383     private static void runWithArguments(Class<?> clazz, String... args) {
 384         try {
 385             runFramework(new TestFramework(clazz).addFlags(args));
 386         } catch (Exception e) {
 387             addException(e);
 388         }
 389     }
 390 
 391     private static void runWithArgumentsFail(Class<?> clazz, String... args) {
 392         runFramework(new TestFramework(clazz).addFlags(args));
 393     }
 394 
 395     private static void runCheck(String[] args , Constraint... constraints) {
 396         try {
 397             TestFramework framework = new TestFramework(constraints[0].getKlass()); // All constraints have the same class.
 398             if (args != null) {
 399                 framework.addFlags(args);
 400             }
 401             runFramework(framework);
 402             Asserts.fail("Should have thrown exception");
 403         } catch (IRViolationException e) {
 404             checkConstraints(e, constraints);
 405         } catch (Exception e) {
 406             addException(e);
 407         }
 408     }
 409 
 410     private static void runCheck(Constraint... constraints) {
 411         runCheck(null, constraints);
 412     }
 413 
 414     private static void checkConstraints(IRViolationException e, Constraint[] constraints) {
 415         String message = e.getExceptionInfo();
 416         try {
 417             for (Constraint constraint : constraints) {
 418                 constraint.checkConstraint(e);
 419             }
 420         } catch (Exception e1) {
 421             System.out.println(e.getCompilations());
 422             System.out.println(message);
 423             addException(e1);
 424         }
 425     }
 426 
 427     private static String compilationPrefix() {
 428         return "\\d\\) Compilation";
 429     }
 430 
 431     private static void findIrIds(String output, String method, int... numbers) {
 432         StringBuilder builder = new StringBuilder();
 433         builder.append(method);
 434         for (int i = 0; i < numbers.length; i+=2) {
 435             int start = numbers[i];
 436             int endIncluded = numbers[i + 1];
 437             for (int j = start; j <= endIncluded; j++) {
 438                 builder.append(",");
 439                 builder.append(j);
 440             }
 441         }
 442         if (!output.contains(builder.toString())) {
 443             addException(new RuntimeException("Could not find encoding: \"" + builder + System.lineSeparator()));
 444         }
 445     }
 446 }
 447 
 448 class AndOr1 {
 449     @Test
 450     @Arguments(values = Argument.DEFAULT)
 451     @IR(applyIfAnd = {"UsePerfData", "true", "TLABRefillWasteFraction", "50", "UseTLAB", "true"}, failOn = {IRNode.CALL})
 452     public void test1(int i) {
 453         dontInline();
 454     }
 455 
 456     @Test
 457     @IR(applyIfOr = {"UsePerfData", "false", "TLABRefillWasteFraction", "51", "UseTLAB", "false"}, failOn = {IRNode.CALL})
 458     public void test2() {
 459         dontInline();
 460     }
 461 
 462     @DontInline
 463     private void dontInline() {
 464     }
 465 }
 466 
 467 class MultipleFailOnGood {
 468     private int iFld;
 469     private MyClassSub myClassSub = new MyClassSub();
 470 
 471     @Test
 472     @IR(applyIf = {"TLABRefillWasteFraction", "50"}, failOn = {IRNode.STORE, IRNode.CALL})
 473     @IR(failOn = {IRNode.STORE, IRNode.CALL})
 474     @IR(applyIfOr = {"TLABRefillWasteFraction", "99", "TLABRefillWasteFraction", "100"}, failOn = {IRNode.LOOP, IRNode.CALL}) // Not applied
 475     public void good1() {
 476         forceInline();
 477     }
 478 
 479     @Test
 480     @IR(failOn = {IRNode.STORE, IRNode.CALL})
 481     @IR(applyIfNot = {"TLABRefillWasteFraction", "20"}, failOn = {IRNode.ALLOC})
 482     @IR(applyIfNot = {"TLABRefillWasteFraction", "< 100"}, failOn = {IRNode.ALLOC_OF, "Test"})
 483     public void good2() {
 484         forceInline();
 485     }
 486 
 487     @Test
 488     @IR(failOn = {IRNode.STORE_OF_CLASS, "Test", IRNode.CALL})
 489     @IR(applyIfNot = {"TLABRefillWasteFraction", "20"}, failOn = {IRNode.ALLOC})
 490     @IR(applyIfNot = {"TLABRefillWasteFraction", "< 100"}, failOn = {IRNode.ALLOC_OF, "Test"})
 491     public void good3() {
 492         forceInline();
 493     }
 494 
 495     @Test
 496     @IR(failOn = {IRNode.CALL, IRNode.STORE_OF_CLASS, "UnknownClass"})
 497     public void good4() {
 498         iFld = 42;
 499     }
 500 
 501     @Test
 502     @IR(failOn = {IRNode.STORE_OF_FIELD, "xFld", IRNode.CALL})
 503     public void good5() {
 504         iFld = 42;
 505     }
 506 
 507     @Test
 508     @IR(failOn = {IRNode.STORE_OF_CLASS, "MyClass"}) // Needs exact match to fail
 509     public void good6() {
 510         myClassSub.iFld = 42;
 511     }
 512 
 513     @Test
 514     @IR(failOn = {IRNode.STORE_OF_CLASS, "MyClassSub"}) // Static write is with Class and not MySubClass
 515     public void good7() {
 516         MyClassSub.iFldStatic = 42;
 517     }
 518 
 519     @ForceInline
 520     private void forceInline() {}
 521 }
 522 
 523 class MultipleFailOnBad {
 524     private int iFld;
 525     private int myInt;
 526     private MyClassEmpty myClass;
 527 
 528     @Test
 529     @IR(failOn = {IRNode.STORE, IRNode.CALL, IRNode.STORE_I, IRNode.LOOP})
 530     public void fail1() {
 531         iFld = 42;
 532     }
 533 
 534     @Test
 535     @IR(failOn = {IRNode.STORE, IRNode.CALL})
 536     public void fail2() {
 537         dontInline();
 538     }
 539 
 540     @Test
 541     @IR(failOn = {IRNode.CALL, IRNode.STORE_OF_CLASS, "MultipleFailOnBad", IRNode.ALLOC})
 542     public void fail3() {
 543         iFld = 42;
 544     }
 545 
 546     @Test
 547     @IR(failOn = {IRNode.STORE_OF_CLASS, "ir_framework/tests/MultipleFailOnBad", IRNode.CALL, IRNode.ALLOC})
 548     public void fail4() {
 549         iFld = 42;
 550     }
 551 
 552     @Test
 553     @IR(failOn = {IRNode.STORE_OF_FIELD, "iFld", IRNode.CALL, IRNode.ALLOC})
 554     public void fail5() {
 555         iFld = 42;
 556     }
 557 
 558     @Test
 559     @IR(failOn = {IRNode.STORE_OF_CLASS, "MyClassEmpty", IRNode.ALLOC, IRNode.CALL})
 560     public void fail6() {
 561         myClass = new MyClassEmpty();
 562     }
 563 
 564     @Test
 565     @IR(failOn = {IRNode.STORE_OF_CLASS, "UnknownClass", IRNode.ALLOC_OF, "MyClassEmpty"})
 566     public void fail7() {
 567         myClass = new MyClassEmpty();
 568     }
 569 
 570     @Test
 571     @IR(failOn = {IRNode.STORE_OF_CLASS, "UnknownClass", IRNode.ALLOC_OF, "ir_framework/tests/MyClassEmptySub"})
 572     public void fail8() {
 573         myClass = new MyClassEmptySub();
 574     }
 575 
 576     @Test
 577     @IR(failOn = {IRNode.STORE, IRNode.CALL})
 578     public void fail9() {
 579         iFld = 42;
 580         dontInline();
 581     }
 582 
 583     @Test
 584     @IR(failOn = {IRNode.STORE_OF_FIELD, "iFld", IRNode.CALL, IRNode.ALLOC})
 585     public void fail10() {
 586         myInt = 34;
 587         iFld = 42;
 588     }
 589 
 590     @DontInline
 591     private void dontInline() {}
 592 }
 593 
 594 // Called with -XX:TLABRefillWasteFraction=X.
 595 class FlagComparisons {
 596     // Applies all IR rules if TLABRefillWasteFraction=50
 597     @Test
 598     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "50"}) // Index 1
 599     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "=50"})
 600     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "= 50"})
 601     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " =   50"})
 602     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<=50"}) // Index 5
 603     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<= 50"})
 604     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " <=  50"})
 605     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">=50"}) // Index 8
 606     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">= 50"})
 607     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " >=  50"})
 608     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">49"})
 609     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "> 49"})
 610     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " >  49"})
 611     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<51"}) // Index 14
 612     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "< 51"})
 613     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " <  51"})
 614     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "!=51"})
 615     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "!= 51"})
 616     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " !=  51"})
 617     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "!=49"})
 618     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "!= 49"})
 619     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " !=  49"}) // Index 22
 620     public void testMatchAllIf50() {}
 621 
 622     // Applies no IR rules if TLABRefillWasteFraction=50
 623     @Test
 624     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "49"}) // Index 1
 625     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "=49"})
 626     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "= 49"})
 627     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " =  49"})
 628     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "51"}) // Index 5
 629     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "=51"})
 630     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "= 51"})
 631     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " =  51"})
 632     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<=49"}) // Index 9
 633     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<= 49"})
 634     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " <=  49"})
 635     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">=51"}) // Index 12
 636     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">= 51"})
 637     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " >=  51"})
 638     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">50"})
 639     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "> 50"})
 640     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " >  50"})
 641     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<50"}) // Index 18
 642     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "< 50"})
 643     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " <  50"})
 644     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "!=50"})
 645     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "!= 50"})
 646     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " !=  50"}) // Index 23
 647     public void testMatchNoneIf50() {}
 648 }
 649 
 650 class CountComparisons {
 651     int iFld;
 652 
 653     @Test
 654     @IR(counts = {IRNode.STORE, "= 1",
 655                   IRNode.STORE, "=1",
 656                   IRNode.STORE, " = 1",
 657                   IRNode.STORE, "  =  1",
 658                   IRNode.STORE, ">= 1",
 659                   IRNode.STORE, ">=1",
 660                   IRNode.STORE, " >= 1",
 661                   IRNode.STORE, "  >=  1",
 662                   IRNode.STORE, "<= 1",
 663                   IRNode.STORE, "<=1",
 664                   IRNode.STORE, " <= 1",
 665                   IRNode.STORE, "  <=  1",
 666                   IRNode.STORE, "> 0",
 667                   IRNode.STORE, ">0",
 668                   IRNode.STORE, " > 0",
 669                   IRNode.STORE, "  >  0",
 670                   IRNode.STORE, "< 2",
 671                   IRNode.STORE, "<2",
 672                   IRNode.STORE, " < 2",
 673                   IRNode.STORE, "  <  2",
 674     })
 675     public void countComparison() {
 676         iFld = 3;
 677     }
 678 }
 679 
 680 class GoodCount {
 681     boolean flag;
 682     char cFld;
 683     byte bFld;
 684     short sFld;
 685     int iFld;
 686     long lFld;
 687     float fFld;
 688     double dFld;
 689     long x;
 690 
 691     long result;
 692     MyClass myClass = new MyClass();
 693     MyClassEmpty myClassEmpty = new MyClassEmpty();
 694     MyClass myClassSubPoly = new MyClassSub();
 695     MyClassSub myClassSub = new MyClassSub();
 696 
 697     @Test
 698     @IR(counts = {IRNode.STORE, "1", IRNode.STORE_I, "1"},
 699         failOn = {IRNode.STORE_B, IRNode.STORE_C, IRNode.STORE_D,
 700                   IRNode.STORE_F, IRNode.STORE_L})
 701     public void good1() {
 702         iFld = 3;
 703     }
 704 
 705     @Test
 706     @IR(counts = {IRNode.STORE, "8",
 707                   IRNode.STORE_B, "2", // bFld + flag
 708                   IRNode.STORE_C, "2", // cFld + sFld
 709                   IRNode.STORE_I, "1",
 710                   IRNode.STORE_L, "1",
 711                   IRNode.STORE_F, "1",
 712                   IRNode.STORE_D, "1"})
 713     public void good2() {
 714         flag = true;
 715         cFld = 'a';
 716         bFld = 1;
 717         sFld = 2;
 718         iFld = 3;
 719         lFld = 4L;
 720         fFld = 5.0f;
 721         dFld = 6.0;
 722     }
 723 
 724     @Test
 725     @IR(counts = {IRNode.STORE, "8", IRNode.STORE_OF_CLASS, "GoodCount", "8",
 726                   IRNode.STORE_B, "2", IRNode.STORE_B_OF_CLASS, "GoodCount", "2",
 727                   IRNode.STORE_C, "2", IRNode.STORE_C_OF_CLASS, "GoodCount", "2",
 728                   IRNode.STORE_I, "1", IRNode.STORE_I_OF_CLASS, "GoodCount", "1",
 729                   IRNode.STORE_L, "1", IRNode.STORE_L_OF_CLASS, "GoodCount", "1",
 730                   IRNode.STORE_F, "1", IRNode.STORE_F_OF_CLASS, "GoodCount", "1",
 731                   IRNode.STORE_D, "1", IRNode.STORE_D_OF_CLASS, "GoodCount", "1"})
 732     public void good3() {
 733         flag = true;
 734         cFld = 'a';
 735         bFld = 1;
 736         sFld = 2;
 737         iFld = 3;
 738         lFld = 4L;
 739         fFld = 5.0f;
 740         dFld = 6.0;
 741     }
 742 
 743     @Test
 744     @IR(counts = {IRNode.STORE, "8", IRNode.STORE_OF_CLASS, "GoodCount", "8",
 745                   IRNode.STORE_B, "2", IRNode.STORE_B_OF_CLASS, "GoodCount", "2",
 746                   IRNode.STORE_C, "2", IRNode.STORE_C_OF_CLASS, "GoodCount", "2",
 747                   IRNode.STORE_I, "1", IRNode.STORE_I_OF_CLASS, "GoodCount", "1",
 748                   IRNode.STORE_L, "1", IRNode.STORE_L_OF_CLASS, "GoodCount", "1",
 749                   IRNode.STORE_F, "1", IRNode.STORE_F_OF_CLASS, "GoodCount", "1",
 750                   IRNode.STORE_D, "1", IRNode.STORE_D_OF_CLASS, "GoodCount", "1",
 751                   IRNode.STORE_OF_FIELD, "lFld", "1"})
 752     public void good4() {
 753         flag = true;
 754         cFld = 'a';
 755         bFld = 1;
 756         sFld = 2;
 757         iFld = 3;
 758         lFld = 4L;
 759         fFld = 5.0f;
 760         dFld = 6.0;
 761     }
 762 
 763     @Test
 764     @IR(counts = {IRNode.STORE, "2", IRNode.STORE_I, "1", IRNode.STORE_L, "1",
 765                   IRNode.STORE_OF_CLASS, "GoodCount", "1", IRNode.STORE_L_OF_CLASS, "GoodCount", "1",
 766                   IRNode.STORE_OF_CLASS, "ir_framework/tests/MyClass", "1",
 767                   IRNode.STORE_I_OF_CLASS, "ir_framework/tests/MyClass", "1",
 768                   IRNode.STORE_OF_CLASS, "ir_framework/tests/GoodCount", "1",
 769                   IRNode.STORE_L_OF_CLASS, "ir_framework/tests/GoodCount", "1",
 770                   IRNode.STORE_OF_FIELD, "x", "2"})
 771     public void good5() {
 772         x = 3; // long
 773         myClass.x = 4; // int
 774     }
 775 
 776     @Test
 777     @IR(counts = {
 778             IRNode.STORE_OF_FIELD, "myClassEmpty", "1",
 779             IRNode.STORE_OF_CLASS, "oodCount", "0",
 780             IRNode.STORE_OF_CLASS, "GoodCount", "1",
 781             IRNode.STORE_OF_CLASS, "/GoodCount", "1",
 782             IRNode.STORE_OF_CLASS, "tests/GoodCount", "1",
 783             IRNode.STORE_OF_CLASS, "/tests/GoodCount", "1",
 784             IRNode.STORE_OF_CLASS, "ir_framework/tests/GoodCount", "1",
 785             IRNode.STORE_OF_CLASS, "/ir_framework/tests/GoodCount", "0",
 786             IRNode.STORE_OF_CLASS, "MyClassEmpty", "0"
 787         },
 788         failOn = {IRNode.STORE_OF_CLASS, "MyClassEmpty"})
 789     public void good6() {
 790         myClassEmpty = new MyClassEmpty();
 791     }
 792 
 793     @Test
 794     @IR(counts = {IRNode.STORE_OF_FIELD, "iFld", "3", IRNode.STORE_OF_CLASS, "GoodCount", "0",
 795                   IRNode.STORE_OF_CLASS, "MyClass", "2", IRNode.STORE_OF_CLASS, "MyClassSub", "1",
 796                   IRNode.STORE, "3"},
 797         failOn = {IRNode.STORE_OF_CLASS, "GoodCount"})
 798     public void good7() {
 799         myClass.iFld = 1;
 800         myClassSubPoly.iFld = 2;
 801         myClassSub.iFld = 3;
 802     }
 803 
 804     @Test
 805     @IR(counts = {IRNode.LOAD, "1", IRNode.STORE, "1"})
 806     public void good8() {
 807         result = iFld;
 808     }
 809 
 810 
 811     @Test
 812     @IR(counts = {IRNode.LOAD, "4", IRNode.STORE, "1", IRNode.LOAD_OF_FIELD, "iFld", "2", IRNode.LOAD_OF_FIELD, "iFld2", "0",
 813                   IRNode.LOAD_OF_FIELD, "lFldStatic", "1", IRNode.LOAD_OF_CLASS, "GoodCount", "2", IRNode.LOAD_OF_CLASS, "MyClass", "1",
 814                   IRNode.STORE_OF_CLASS, "GoodCount", "1", IRNode.STORE_OF_FIELD, "result", "1",
 815                   IRNode.LOAD_OF_FIELD, "myClass", "1"})
 816     public void good9() {
 817         result = iFld + MyClass.lFldStatic + myClass.iFld; // 1 + 1 + 2 loads (myClass is LoadN of GoodCount and myClass.iFld a LoadI of MyClass)
 818     }
 819 
 820     @Test
 821     @IR(counts = {IRNode.LOAD, "8",
 822                   IRNode.LOAD_B, "1",
 823                   IRNode.LOAD_UB, "1",
 824                   IRNode.LOAD_S, "1",
 825                   IRNode.LOAD_US, "1",
 826                   IRNode.LOAD_I, "1",
 827                   IRNode.LOAD_L, "1",
 828                   IRNode.LOAD_F, "1",
 829                   IRNode.LOAD_D, "1"})
 830     public void good10() {
 831         bFld++;
 832         cFld++;
 833         sFld++;
 834         iFld++;
 835         lFld++;
 836         fFld++;
 837         dFld++;
 838         flag = !flag;
 839     }
 840 
 841     @Test
 842     @IR(counts = {IRNode.LOAD, "8", IRNode.LOAD_OF_CLASS, "GoodCount", "8",
 843                   IRNode.LOAD_B, "1", IRNode.LOAD_B_OF_CLASS, "GoodCount", "1",
 844                   IRNode.LOAD_UB, "1", IRNode.LOAD_UB_OF_CLASS, "GoodCount", "1",
 845                   IRNode.LOAD_S, "1", IRNode.LOAD_S_OF_CLASS, "GoodCount", "1",
 846                   IRNode.LOAD_US, "1", IRNode.LOAD_US_OF_CLASS, "GoodCount", "1",
 847                   IRNode.LOAD_I, "1", IRNode.LOAD_I_OF_CLASS, "GoodCount", "1",
 848                   IRNode.LOAD_L, "1", IRNode.LOAD_L_OF_CLASS, "GoodCount", "1",
 849                   IRNode.LOAD_F, "1", IRNode.LOAD_F_OF_CLASS, "GoodCount", "1",
 850                   IRNode.LOAD_D, "1", IRNode.LOAD_D_OF_CLASS, "GoodCount", "1"})
 851     public void good11() {
 852         bFld++;
 853         cFld++;
 854         sFld++;
 855         iFld++;
 856         lFld++;
 857         fFld++;
 858         dFld++;
 859         flag = !flag;
 860     }
 861 }
 862 
 863 class BadCount {
 864     int iFld;
 865     int iFld2;
 866     int result;
 867     int result2;
 868     @Test
 869     @IR(counts = {IRNode.LOAD, "> 1000"}) // fail
 870     @IR(counts = {IRNode.STORE, "> 0"})
 871     public void bad1() {
 872         result = iFld;
 873         result2 = iFld2;
 874     }
 875 
 876     @Test
 877     @IR(counts = {IRNode.LOAD, "2"}) // fail
 878     @IR(counts = {IRNode.STORE, "< 2"})
 879     public void bad2() {
 880         result = iFld;
 881         result2 = iFld2;
 882     }
 883 
 884 
 885     @Test
 886     @IR(counts = {IRNode.LOAD, "0"}) // fail
 887     @IR(counts = {IRNode.STORE, " <= 1"}) // fail
 888     public void bad3() {
 889         result = iFld;
 890         result2 = iFld2;
 891     }
 892 }
 893 
 894 
 895 class RunTests {
 896     public int iFld;
 897 
 898     @Test
 899     @IR(counts = {IRNode.STORE, "1"})
 900     @IR(failOn = IRNode.LOAD)
 901     public void good1() {
 902         iFld = 42;
 903     }
 904 
 905     @Test
 906     @IR(counts = {IRNode.LOAD, "1"})
 907     @IR(failOn = IRNode.STORE)
 908     public int good2() {
 909         return iFld;
 910     }
 911 
 912     @Run(test = {"good1", "good2"})
 913     public void runGood1() {
 914         good1();
 915         good2();
 916     }
 917 
 918 
 919     @Test
 920     @IR(counts = {IRNode.STORE, "1"})
 921     @IR(failOn = IRNode.LOAD)
 922     public void good3(int x) {
 923         iFld = x;
 924     }
 925 
 926     @Test
 927     @IR(counts = {IRNode.STORE, "1"})
 928     @IR(failOn = IRNode.LOAD)
 929     public int bad1(int x) {
 930         return iFld + x;
 931     }
 932 
 933     @Run(test = {"bad1", "good3"})
 934     public void run() {
 935         bad1(2);
 936         good3(4);
 937     }
 938 }
 939 
 940 class Calls {
 941 
 942     @Test
 943     @IR(counts = {IRNode.CALL, "1"})
 944     @IR(failOn = {IRNode.CALL_OF_METHOD, "dontInline",  // Fails
 945                   IRNode.STATIC_CALL_OF_METHOD, "dontInline"}) // Fails
 946     @IR(failOn = {IRNode.CALL_OF_METHOD, "forceInline",
 947                   IRNode.STATIC_CALL_OF_METHOD, "forceInline",
 948                   IRNode.CALL_OF_METHOD, "dontInlines",
 949                   IRNode.STATIC_CALL_OF_METHOD, "dontInlines",
 950                   IRNode.CALL_OF_METHOD, "dont",
 951                   IRNode.STATIC_CALL_OF_METHOD, "dont"})
 952     public void calls() {
 953         dontInline();
 954         forceInline();
 955     }
 956 
 957     @DontInline
 958     public void dontInline() {}
 959 
 960     @ForceInline
 961     public void forceInline() {}
 962 }
 963 
 964 class AllocInstance {
 965     MyClass myClass;
 966 
 967     @Test
 968     @IR(failOn = {IRNode.ALLOC})
 969     @IR(failOn = {IRNode.ALLOC_OF, "MyClass"})
 970     @IR(failOn = {IRNode.ALLOC_OF, "Class"}) // Does not fail
 971     @IR(failOn = {IRNode.ALLOC_OF, "MyClasss"}) // Does not fail
 972     @IR(failOn = {IRNode.ALLOC_OF, "ir_framework/tests/MySubClass"}) // Does not fail
 973     @IR(failOn = {IRNode.ALLOC_OF, "ir_framework/tests/MyClass"})
 974     @IR(failOn = {IRNode.ALLOC_OF, "tests/MyClass"})
 975     @IR(failOn = {IRNode.ALLOC_OF, "ests/MyClass"}) // Does not fail
 976     @IR(failOn = {IRNode.ALLOC_OF, "Atests/MyClass"}) // Does not fail
 977     @IR(failOn = {IRNode.ALLOC_OF, "tests"}) // Does not fail
 978     public void allocInstance() {
 979         myClass = new MyClass();
 980     }
 981 
 982     static class Nested {}
 983     @Test
 984     @IR(failOn = {IRNode.ALLOC_OF, "Nested"})
 985     @IR(failOn = {IRNode.ALLOC_OF, "AllocInstance\\$Nested"})
 986     @IR(failOn = {IRNode.ALLOC_OF, "AllocInst\\w+\\$Nested"})
 987     public Nested allocNested() { return new Nested(); }
 988 }
 989 
 990 class AllocArray {
 991     MyClass[] myClassArray;
 992     MyClass[][] myClassMultiArray;
 993 
 994     @Test
 995     @IR(failOn = {IRNode.ALLOC_ARRAY})
 996     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "MyClass"})
 997     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "Class"}) // Does not fail
 998     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "MyClasss"}) // Does not fail
 999     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "ir_framework/tests/MySubClass"}) // Does not fail
1000     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "ir_framework/tests/MyClass"})
1001     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "tests/MyClass"})
1002     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "ests/MyClass"}) // Does not fail
1003     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "Atests/MyClass"}) // Does not fail
1004     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "tests"}) // Does not fail
1005     public void allocArray() {
1006         myClassArray = new MyClass[2];
1007     }
1008 
1009     @Test
1010     @IR(failOn = {IRNode.ALLOC_ARRAY})
1011     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "MyClass"})
1012     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "Class"}) // Does not fail
1013     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "MyClasss"}) // Does not fail
1014     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "ir_framework/tests/MySubClass"}) // Does not fail
1015     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "ir_framework/tests/MyClass"})
1016     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "tests/MyClass"})
1017     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "ests/MyClass"}) // Does not fail
1018     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "Atests/MyClass"}) // Does not fail
1019     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "tests"}) // Does not fail
1020     public void allocMultiArray() {
1021         myClassMultiArray = new MyClass[2][3];
1022     }
1023 }
1024 
1025 class Loads {
1026     int iFld = 34;
1027     int result = 0;
1028     Object myClass = new MyClass();
1029 
1030     @Test
1031     @IR(failOn = {IRNode.LOAD, IRNode.LOOP, IRNode.LOAD_I}, counts = {IRNode.LOOP, "2", IRNode.LOAD, "2", IRNode.STORE, "2"})
1032     @IR(failOn = {IRNode.LOOP, IRNode.LOOP}, counts = {IRNode.LOOP, "0", IRNode.LOAD, "1"}) // Does not fail
1033     @IR(failOn = {IRNode.LOOP, IRNode.LOOP}, counts = {IRNode.LOOP, "0", IRNode.STORE, "1"})
1034     @IR(failOn = {IRNode.LOOP, IRNode.STORE}, counts = {IRNode.LOOP, "0", IRNode.LOAD, "1"})
1035     @IR(failOn = {IRNode.LOAD_OF_CLASS, "ir_framework/tests/Loads"})
1036     @IR(failOn = {IRNode.LOAD_OF_CLASS, "Loads"})
1037     @IR(failOn = {IRNode.LOAD_OF_FIELD, "iFld"})
1038     @IR(failOn = {IRNode.LOAD_OF_FIELD, "iFld2", IRNode.LOAD_OF_CLASS, "Load"}) // Does not fail
1039     @IR(failOn = {IRNode.LOAD_KLASS}) // Does not fail
1040     @IR(counts = {IRNode.FIELD_ACCESS, "3"}) // Does not fail
1041     public void load() {
1042         result = iFld;
1043         iFld = 3;
1044     }
1045 
1046     @Test
1047     @IR(failOn = {IRNode.LOAD_KLASS})
1048     @IR(counts = {IRNode.FIELD_ACCESS, "3"})
1049     public void loadKlass() {
1050         if (myClass instanceof MyClass) {
1051             result = 3;
1052         }
1053     }
1054 }
1055 
1056 class Loops {
1057     int limit = 1024;
1058     int[] iArr = new int[100];
1059 
1060     @DontInline
1061     public void dontInline() {}
1062 
1063     @Test
1064     @IR(failOn = IRNode.LOOP) // fails
1065     @IR(failOn = IRNode.COUNTED_LOOP)
1066     @IR(failOn = IRNode.COUNTED_LOOP_MAIN)
1067     public void loop() {
1068         for (int i = 0; i < limit; i++) {
1069             dontInline();
1070         }
1071     }
1072 
1073     @Test
1074     @IR(failOn = IRNode.LOOP)
1075     @IR(failOn = IRNode.COUNTED_LOOP) // fails
1076     @IR(failOn = IRNode.COUNTED_LOOP_MAIN)
1077     public void countedLoop() {
1078         for (int i = 0; i < 2000; i++) {
1079             dontInline();
1080         }
1081     }
1082 
1083     @Test
1084     @IR(failOn = IRNode.LOOP) // fails
1085     @IR(failOn = IRNode.COUNTED_LOOP) // fails
1086     @IR(failOn = IRNode.COUNTED_LOOP_MAIN)
1087     public void loopAndCountedLoop() {
1088         for (int i = 0; i < 2000; i++) {
1089             for (int j = 0; j < limit; j++) {
1090                 dontInline();
1091             }
1092         }
1093     }
1094 
1095     @Test
1096     @IR(failOn = IRNode.LOOP)
1097     @IR(failOn = IRNode.COUNTED_LOOP) // fails
1098     @IR(failOn = IRNode.COUNTED_LOOP_MAIN) // fails
1099     public void countedLoopMain() {
1100         // Cannot unroll completely -> create pre/main/post
1101         for (int i = 0; i < 100; i++) {
1102             iArr[i] = i;
1103         }
1104     }
1105 
1106     @Test
1107     @IR(failOn = IRNode.LOOP)
1108     @IR(failOn = IRNode.COUNTED_LOOP)
1109     @IR(failOn = IRNode.COUNTED_LOOP_MAIN)
1110     public void countedLoopUnrolled() {
1111         // Completely unrolled -> no pre/main/post
1112         for (int i = 0; i < 8; i++) {
1113             iArr[i] = i;
1114         }
1115     }
1116 }
1117 
1118 class Traps {
1119     int number42 = 42;
1120     int iFld = 10;
1121     int[] iArr = new int[2];
1122     MyClass myClass = new MyClass();
1123     MyClassSub myClassSub = new MyClassSub();
1124     NotLoaded notLoaded = new NotLoaded();
1125     Object[] oArr = new Object[10];
1126     MyClass[] mArr = new MyClass[10];
1127 
1128     @Test
1129     @IR(failOn = IRNode.TRAP)
1130     @IR(failOn = {IRNode.STORE_OF_FIELD, "iFld"}) // fails
1131     @IR(failOn = {IRNode.PREDICATE_TRAP,
1132                   IRNode.UNSTABLE_IF_TRAP,
1133                   IRNode.NULL_CHECK_TRAP,
1134                   IRNode.NULL_ASSERT_TRAP,
1135                   IRNode.RANGE_CHECK_TRAP,
1136                   IRNode.CLASS_CHECK_TRAP,
1137                   IRNode.INTRINSIC_TRAP,
1138                   IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
1139                   IRNode.UNHANDLED_TRAP})
1140     public void noTraps() {
1141         for (int i = 0; i < 100; i++) {
1142             if (i < 42) {
1143                 // Reached, no uncommon trap
1144                 iFld = i;
1145             }
1146         }
1147     }
1148 
1149     @Test
1150     @IR(failOn = IRNode.TRAP) // fails
1151     @IR(failOn = IRNode.PREDICATE_TRAP) // fails
1152     @IR(failOn = {IRNode.STORE_OF_FIELD, "iFld"})
1153     @IR(failOn = {IRNode.UNSTABLE_IF_TRAP,
1154                   IRNode.NULL_CHECK_TRAP,
1155                   IRNode.NULL_ASSERT_TRAP,
1156                   IRNode.RANGE_CHECK_TRAP,
1157                   IRNode.CLASS_CHECK_TRAP,
1158                   IRNode.INTRINSIC_TRAP,
1159                   IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
1160                   IRNode.UNHANDLED_TRAP})
1161     public void predicateTrap() {
1162         for (int i = 0; i < 100; i++) {
1163             if (number42 != 42) {
1164                 // Never reached
1165                 iFld = i;
1166             }
1167         }
1168     }
1169 
1170     @Test
1171     @IR(failOn = IRNode.TRAP) // fails
1172     @IR(failOn = IRNode.NULL_CHECK_TRAP) // fails
1173     @IR(failOn = IRNode.CLASS_CHECK_TRAP) // fails
1174     @IR(failOn = {IRNode.PREDICATE_TRAP,
1175                   IRNode.NULL_ASSERT_TRAP,
1176                   IRNode.RANGE_CHECK_TRAP,
1177                   IRNode.UNSTABLE_IF_TRAP,
1178                   IRNode.INTRINSIC_TRAP,
1179                   IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
1180                   IRNode.UNHANDLED_TRAP})
1181     public void nullCheck() {
1182         if (myClass instanceof MyClassSub) {
1183             iFld = 4;
1184         }
1185     }
1186 
1187     @Test
1188     @IR(failOn = IRNode.TRAP) // fails
1189     @IR(failOn = IRNode.NULL_ASSERT_TRAP) // fails
1190     @IR(failOn = IRNode.NULL_CHECK_TRAP) // fails
1191     @IR(failOn = {IRNode.PREDICATE_TRAP,
1192                   IRNode.UNSTABLE_IF_TRAP,
1193                   IRNode.RANGE_CHECK_TRAP,
1194                   IRNode.CLASS_CHECK_TRAP,
1195                   IRNode.INTRINSIC_TRAP,
1196                   IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
1197                   IRNode.UNHANDLED_TRAP})
1198     public Object nullAssert() {
1199         return notLoaded.notLoadedFld;
1200     }
1201 
1202     @Test
1203     @Arguments(values = Argument.TRUE)
1204     @IR(failOn = IRNode.TRAP) // fails
1205     @IR(failOn = IRNode.UNSTABLE_IF_TRAP) // fails
1206     @IR(failOn = {IRNode.PREDICATE_TRAP,
1207                   IRNode.NULL_CHECK_TRAP,
1208                   IRNode.NULL_ASSERT_TRAP,
1209                   IRNode.RANGE_CHECK_TRAP,
1210                   IRNode.CLASS_CHECK_TRAP,
1211                   IRNode.INTRINSIC_TRAP,
1212                   IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
1213                   IRNode.UNHANDLED_TRAP})
1214     public void unstableIf(boolean flag) {
1215         if (flag) {
1216             iFld++;
1217         } else {
1218             iFld--;
1219         }
1220     }
1221 
1222     @Test
1223     @IR(failOn = IRNode.TRAP) // fails
1224     @IR(failOn = IRNode.CLASS_CHECK_TRAP) // fails
1225     @IR(failOn = IRNode.NULL_CHECK_TRAP) // fails
1226     @IR(failOn = {IRNode.PREDICATE_TRAP,
1227                   IRNode.UNSTABLE_IF_TRAP,
1228                   IRNode.NULL_ASSERT_TRAP,
1229                   IRNode.RANGE_CHECK_TRAP,
1230                   IRNode.INTRINSIC_TRAP,
1231                   IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
1232                   IRNode.UNHANDLED_TRAP})
1233     public void classCheck() {
1234         try {
1235             myClassSub = (MyClassSub) myClass;
1236         } catch (ClassCastException e) {
1237             // Expected
1238         }
1239     }
1240 
1241     @Test
1242     @IR(failOn = IRNode.TRAP) // fails
1243     @IR(failOn = IRNode.RANGE_CHECK_TRAP) // fails
1244     @IR(failOn = IRNode.NULL_CHECK_TRAP) // fails
1245     @IR(failOn = {IRNode.PREDICATE_TRAP,
1246                   IRNode.UNSTABLE_IF_TRAP,
1247                   IRNode.NULL_ASSERT_TRAP,
1248                   IRNode.CLASS_CHECK_TRAP,
1249                   IRNode.INTRINSIC_TRAP,
1250                   IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
1251                   IRNode.UNHANDLED_TRAP})
1252     public void rangeCheck() {
1253         iArr[1] = 3;
1254     }
1255 
1256 
1257     @Test
1258     @IR(failOn = IRNode.TRAP) // fails
1259     @IR(failOn = IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP) // fails
1260     @IR(failOn = IRNode.INTRINSIC_TRAP) // fails
1261     @IR(failOn = IRNode.NULL_CHECK_TRAP) // fails
1262     @IR(failOn = {IRNode.PREDICATE_TRAP,
1263                   IRNode.UNSTABLE_IF_TRAP,
1264                   IRNode.NULL_ASSERT_TRAP,
1265                   IRNode.CLASS_CHECK_TRAP,
1266                   IRNode.RANGE_CHECK_TRAP,
1267                   IRNode.UNHANDLED_TRAP})
1268     public void instrinsicOrTypeCheckedInlining() {
1269         System.arraycopy(oArr, 0, mArr, 0, 8);
1270     }
1271 }
1272 
1273 class UnhandledTrap {
1274     int iFld = 34;
1275 
1276     @Test
1277     @IR(failOn = IRNode.TRAP) // fails
1278     @IR(failOn = IRNode.UNHANDLED_TRAP) // fails
1279     @IR(failOn = {IRNode.PREDICATE_TRAP,
1280                   IRNode.UNSTABLE_IF_TRAP,
1281                   IRNode.NULL_CHECK_TRAP,
1282                   IRNode.NULL_ASSERT_TRAP,
1283                   IRNode.RANGE_CHECK_TRAP,
1284                   IRNode.CLASS_CHECK_TRAP})
1285     public void unhandled() {
1286         try {
1287             throw new RuntimeException();
1288         } catch (RuntimeException e) {
1289             // Expected
1290         }
1291     }
1292 }
1293 
1294 class ScopeObj {
1295 
1296     @DontInline
1297     public void dontInline(int i) {}
1298 
1299     @Test
1300     @IR(failOn = IRNode.SCOPE_OBJECT) // fails
1301     public int scopeObject() {
1302         MyClass myClass = new MyClass();
1303         for (int i = 0; i < 100; i++) {
1304             dontInline(myClass.iFld);
1305         }
1306         return 3;
1307     }
1308 }
1309 
1310 class Membar {
1311     volatile MyClass myClass;
1312 
1313     @Test
1314     @IR(failOn = IRNode.MEMBAR) // fails
1315     public int membar() {
1316         myClass = new MyClass();
1317         return myClass.x;
1318     }
1319 }
1320 
1321 class CheckCastArray {
1322     Object[] oArr = new Object[10];
1323     MyClass[] mArr = new MyClass[10];
1324 
1325     @Test
1326     @IR(failOn = IRNode.CHECKCAST_ARRAY) // fails
1327     @IR(failOn = {IRNode.CHECKCAST_ARRAY_OF, "MyClass", // fails
1328                   IRNode.CHECKCAST_ARRAY_OF, "ir_framework/tests/MyClass"}) // fails
1329     @IR(failOn = {IRNode.CHECKCAST_ARRAY_OF, "MyClasss", IRNode.CHECKCAST_ARRAY_OF, "Object"})
1330     public boolean array(Object[] arr) {
1331         return arr instanceof MyClass[];
1332     }
1333 
1334     @Run(test = "array")
1335     public void testArray() {
1336         array(oArr);
1337         array(mArr);
1338     }
1339 
1340     @Test
1341     @IR(failOn = IRNode.CHECKCAST_ARRAYCOPY) // fails
1342     public Object[] arrayCopy(Object[] src, Class klass) {
1343         return Arrays.copyOf(src, 8, klass);
1344     }
1345 
1346     @Run(test = "arrayCopy")
1347     public void testArrayCopy() {
1348         arrayCopy(mArr, MyClass[].class);
1349         arrayCopy(mArr, Object[].class);
1350         arrayCopy(mArr, MyClassEmpty[].class);
1351     }
1352 }
1353 
1354 class CompilationOutputOfFails {
1355     private Object obj;
1356 
1357     @Test
1358     @IR(failOn = IRNode.COUNTED_LOOP)
1359     @IR(failOn = {"call"},
1360         phase = CompilePhase.PRINT_OPTO_ASSEMBLY)
1361     public void both1() {
1362         for (int i = 0; i < 100; i++) {
1363             dontInline();
1364         }
1365     }
1366 
1367     @Test
1368     @IR(failOn = "CountedLoop|call",
1369         phase = {CompilePhase.PRINT_IDEAL, CompilePhase.PRINT_OPTO_ASSEMBLY})
1370     public void both2() {
1371         for (int i = 0; i < 100; i++) {
1372             dontInline();
1373         }
1374     }
1375 
1376     @Test
1377     @IR(failOn = IRNode.COUNTED_LOOP)
1378     @IR(failOn = "call", phase = CompilePhase.PRINT_OPTO_ASSEMBLY)
1379     public void both3() {
1380         for (int i = 0; i < 100; i++) {
1381             dontInline();
1382         }
1383     }
1384 
1385     @Test
1386     @IR(counts = {IRNode.COUNTED_LOOP, "0"})
1387     @IR(counts = {"call", "0"},
1388         phase = {CompilePhase.PRINT_OPTO_ASSEMBLY})
1389     public void both4() {
1390         for (int i = 0; i < 100; i++) {
1391             dontInline();
1392         }
1393     }
1394 
1395     @Test
1396     @IR(counts = {"CountedLoop|call", "10"},
1397         phase = {CompilePhase.PRINT_IDEAL, CompilePhase.PRINT_OPTO_ASSEMBLY})
1398     public void both5() {
1399         for (int i = 0; i < 100; i++) {
1400             dontInline();
1401         }
1402     }
1403 
1404     @Test
1405     @IR(counts = {IRNode.COUNTED_LOOP, "0"})
1406     @IR(counts = {"call", "0"}, phase = CompilePhase.PRINT_OPTO_ASSEMBLY)
1407     public void both6() {
1408         for (int i = 0; i < 100; i++) {
1409             dontInline();
1410         }
1411     }
1412 
1413     @Test
1414     @IR(failOn = IRNode.COUNTED_LOOP)
1415     @IR(counts = {"call", "0"}, phase = CompilePhase.PRINT_OPTO_ASSEMBLY)
1416     public void both7() {
1417         for (int i = 0; i < 100; i++) {
1418             dontInline();
1419         }
1420     }
1421 
1422     @Test
1423     @IR(failOn = IRNode.COUNTED_LOOP)
1424     public void ideal1() {
1425         for (int i = 0; i < 100; i++) {
1426             dontInline();
1427         }
1428     }
1429 
1430     @Test
1431     @IR(failOn = IRNode.COUNTED_LOOP)
1432     @IR(failOn = IRNode.ALLOC) // not fail
1433     public void ideal2() {
1434         for (int i = 0; i < 100; i++) {
1435             dontInline();
1436         }
1437     }
1438 
1439     @Test
1440     @IR(failOn = IRNode.COUNTED_LOOP)
1441     @IR(counts = {IRNode.ALLOC, "0"}) // not fail
1442     public void ideal3() {
1443         for (int i = 0; i < 100; i++) {
1444             dontInline();
1445         }
1446     }
1447 
1448     @Test
1449     @IR(counts = {IRNode.COUNTED_LOOP, "2"})
1450     public void ideal4() {
1451         for (int i = 0; i < 100; i++) {
1452             dontInline();
1453         }
1454     }
1455 
1456     @Test
1457     @IR(failOn = IRNode.ALLOC) // not fail
1458     @IR(counts = {IRNode.COUNTED_LOOP, "2"})
1459     public void ideal5() {
1460         for (int i = 0; i < 100; i++) {
1461             dontInline();
1462         }
1463     }
1464 
1465     @Test
1466     @IR(counts = {IRNode.ALLOC, "0"}) // not fail
1467     @IR(counts = {IRNode.COUNTED_LOOP, "2"})
1468     public void ideal6() {
1469         for (int i = 0; i < 100; i++) {
1470             dontInline();
1471         }
1472     }
1473 
1474     @Test
1475     @IR(counts = {IRNode.COUNTED_LOOP, "5"})
1476     @IR(counts = {IRNode.COUNTED_LOOP, "2"})
1477     public void ideal7() {
1478         for (int i = 0; i < 100; i++) {
1479             dontInline();
1480         }
1481     }
1482 
1483     @Test
1484     @IR(failOn = IRNode.ALLOC)
1485     public void macro1() {
1486         obj = new Object();
1487     }
1488 
1489     @Test
1490     @IR(failOn = IRNode.ALLOC)
1491     @IR(failOn = IRNode.STORE_F) // not fail
1492     public void macro2() {
1493         obj = new Object();
1494     }
1495 
1496     @Test
1497     @IR(failOn = IRNode.ALLOC)
1498     @IR(counts = {IRNode.COUNTED_LOOP, "1"}) // not fail
1499     public void macro3() {
1500         for (int i = 0; i < 100; i++) {
1501             obj = new Object();
1502         }
1503     }
1504 
1505     @Test
1506     @IR(counts = {IRNode.ALLOC, "0"})
1507     public void macro4() {
1508         obj = new Object();
1509     }
1510 
1511     @Test
1512     @IR(failOn = IRNode.STORE_F) // not fail
1513     @IR(counts = {IRNode.ALLOC, "0"})
1514     public void macro5() {
1515         obj = new Object();
1516     }
1517 
1518     @Test
1519     @IR(counts = {IRNode.STORE_F, "0"}) // not fail
1520     @IR(counts = {IRNode.ALLOC, "0"})
1521     public void macro6() {
1522         obj = new Object();
1523     }
1524 
1525     @Test
1526     @IR(counts = {IRNode.ALLOC, "10"})
1527     @IR(counts = {IRNode.ALLOC, "0"})
1528     public void macro7() {
1529         obj = new Object();
1530     }
1531 
1532     @DontInline
1533     private void dontInline() {}
1534 }
1535 
1536 
1537 // Used only by class Traps
1538 class NotLoaded {
1539     NotLoadedHelper notLoadedFld;
1540 }
1541 
1542 // Used only by class Traps
1543 class NotLoadedHelper {}
1544 
1545 class MyClass {
1546     int iFld = 3;
1547     int x = 5;
1548     static long lFldStatic;
1549 }
1550 
1551 class MyClassEmpty {}
1552 
1553 class MyClassEmptySub extends MyClassEmpty {}
1554 
1555 class MyClassSub extends MyClass {
1556     int iFld;
1557     static int iFldStatic;
1558 }
1559 
1560 
1561 // Base class for any kind of constraint that is used to verify if the framework reports the correct IR failures.
1562 abstract class Constraint {
1563     private final Class<?> klass;
1564     protected final int ruleIdx;
1565     private final Pattern methodPattern;
1566     private final String classAndMethod;
1567     protected final Pattern irPattern;
1568     private final String methodName;
1569     protected boolean matched;
1570 
1571     Constraint(Class<?> klass, String methodName, int ruleIdx, Pattern irPattern) {
1572         this.klass = klass;
1573         classAndMethod = klass.getSimpleName() + "." + methodName;
1574         this.ruleIdx = ruleIdx;
1575         this.methodPattern = Pattern.compile(Pattern.quote(classAndMethod));
1576         this.irPattern = irPattern;
1577         this.methodName = methodName;
1578         this.matched = false;
1579     }
1580 
1581     // For good constraints only
1582     Constraint(Class<?> klass, String methodName, int ruleIdx) {
1583         this.klass = klass;
1584         classAndMethod = klass.getSimpleName() + "." + methodName;
1585         this.ruleIdx = ruleIdx;
1586         this.methodPattern = Pattern.compile(Pattern.quote(classAndMethod));
1587         this.irPattern = null;
1588         this.methodName = methodName;
1589         this.matched = false;
1590     }
1591 
1592     @Override
1593     public String toString() {
1594         return "Constraint " + getClass().getSimpleName() + ", " + errorPrefix();
1595     }
1596 
1597     public Class<?> getKlass() {
1598         return klass;
1599     }
1600 
1601     protected String errorPrefix() {
1602         return "Class " + klass.getSimpleName() + ", Method " + methodName + ", Rule " + ruleIdx;
1603     }
1604 
1605     public void checkConstraint(IRViolationException e) {
1606         String message = e.getExceptionInfo();
1607         String[] splitMethods = message.split("Method");
1608         for (int i = 1; i < splitMethods.length; i++) {
1609             String method = splitMethods[i];
1610             if (methodPattern.matcher(method).find()) {
1611                 String[] splitIrRules = method.split("@IR ");
1612                 for (int j = 1; j < splitIrRules.length; j++) {
1613                     String irRule = splitIrRules[j];
1614                     if (irRule.startsWith("rule " + ruleIdx)) {
1615                         checkIRRule(irRule);
1616                     }
1617                 }
1618             }
1619         }
1620         Asserts.assertTrue(matched, this + " should have been matched");
1621     }
1622 
1623     abstract protected void checkIRRule(String irRule);
1624 }
1625 
1626 // Constraint for rule that does not fail.
1627 class GoodRuleConstraint extends Constraint {
1628 
1629     GoodRuleConstraint(Class<?> klass, String methodName, int ruleIdx) {
1630         super(klass, methodName, ruleIdx);
1631         matched = true;
1632     }
1633 
1634     public static GoodRuleConstraint create(Class<?> klass, String methodName, int ruleIdx) {
1635         return new GoodRuleConstraint(klass, methodName, ruleIdx);
1636     }
1637 
1638     @Override
1639     protected void checkIRRule(String irRule) {
1640         Asserts.fail(errorPrefix() + " should not fail:" + System.lineSeparator() + irRule);
1641     }
1642 }
1643 
1644 // Constraint for rule that might fail but not with "failOn".
1645 class GoodFailOnConstraint extends GoodRuleConstraint {
1646 
1647     private GoodFailOnConstraint(Class<?> klass, String methodName, int ruleIdx) {
1648         super(klass, methodName, ruleIdx);
1649     }
1650 
1651     public static GoodFailOnConstraint create(Class<?> klass, String methodName, int ruleIdx) {
1652         return new GoodFailOnConstraint(klass, methodName, ruleIdx);
1653     }
1654 
1655     @Override
1656     protected void checkIRRule(String irRule) {
1657         Asserts.assertFalse(irRule.contains("- failOn"), errorPrefix() + " should not have failed:" + System.lineSeparator() + irRule);
1658     }
1659 }
1660 
1661 // Constraint for rule that might fail but not with "counts".
1662 class GoodCountsConstraint extends GoodRuleConstraint {
1663 
1664     private GoodCountsConstraint(Class<?> klass, String methodName, int ruleIdx) {
1665         super(klass, methodName, ruleIdx);
1666     }
1667 
1668     public static GoodCountsConstraint create(Class<?> klass, String methodName, int ruleIdx) {
1669         return new GoodCountsConstraint(klass, methodName, ruleIdx);
1670     }
1671 
1672     @Override
1673     protected void checkIRRule(String irRule) {
1674         Asserts.assertFalse(irRule.contains("- counts"), errorPrefix() + " should not have failed with counts:"
1675                                                          + System.lineSeparator() + irRule);
1676     }
1677 }
1678 
1679 // Base class for all Regex based constraint.
1680 abstract class RegexConstraint extends Constraint {
1681     final String category;
1682     final String otherCategory;
1683     final int[] regexIndexes;
1684     final boolean isGood;
1685     final List<String> matches;
1686 
1687     RegexConstraint(Class<?> klass, String methodName, String category, boolean isGood, List<String> matches, int ruleIdx, int... regexIndexes) {
1688         super(klass, methodName, ruleIdx, initIRPattern(category, ruleIdx));
1689         this.category = category;
1690         this.regexIndexes = regexIndexes;
1691         if (category.equals("failOn")) {
1692             this.otherCategory = "counts";
1693         } else {
1694             Asserts.assertTrue(category.equals("counts"));
1695             this.otherCategory = "failOn";
1696         }
1697         this.isGood = isGood;
1698         this.matches = matches;
1699     }
1700 
1701     @Override
1702     public String toString() {
1703         String msg = super.toString() + ", ";
1704         if (regexIndexes.length > 1) {
1705             msg += "regexes: [" + String.join(", ", Arrays.stream(regexIndexes).mapToObj(String::valueOf).toArray(String[]::new)) + "]";
1706         } else {
1707             msg += "regex: " + regexIndexes[0];
1708         }
1709         return msg;
1710     }
1711 
1712     @Override
1713     protected String errorPrefix() {
1714         return super.errorPrefix() + " with \"" + category + "\"";
1715     }
1716 
1717     private static Pattern initIRPattern(String category, int ruleIdx) {
1718         if (category.equals("failOn")) {
1719             return Pattern.compile("rule " + ruleIdx + ":.*\\R.*- failOn: Graph contains forbidden nodes.*\\R" +
1720                                    ".*Constraint \\d+:.*\\R.*Matched forbidden node.*");
1721         } else {
1722             return Pattern.compile("rule " + ruleIdx + ":.*\\R.*- counts: Graph contains wrong number of nodes:\\R" +
1723                                    ".*Constraint \\d+:.*\\R.*Expected.*");
1724         }
1725     }
1726 
1727     @Override
1728     protected void checkIRRule(String irRule) {
1729         int categoryIndex = irRule.indexOf("- " + category);
1730         Asserts.assertTrue(categoryIndex != -1, errorPrefix() + " should have failed");
1731 
1732         int endIndex;
1733         int otherCategoryIndex = irRule.indexOf("- " + otherCategory);
1734         if (otherCategoryIndex == -1 || categoryIndex > otherCategoryIndex) {
1735             endIndex = irRule.length();
1736         } else {
1737             endIndex = otherCategoryIndex;
1738         }
1739         String categoryString = irRule.substring(irRule.indexOf("- " + category), endIndex);
1740         Pattern pattern;
1741         Matcher matcher;
1742         for (int regexIndex : this.regexIndexes) {
1743             pattern = Pattern.compile("Constraint " + regexIndex + ":.*");
1744             matcher = pattern.matcher(categoryString);
1745             if (isGood) {
1746                 Asserts.assertFalse(matcher.find(), errorPrefix() + " failed with Constraint " + regexIndex);
1747                 matched = true;
1748             } else {
1749                 Asserts.assertTrue(matcher.find(), errorPrefix() + " should have failed at Constraint " + regexIndex);
1750                 String[] splitRegex = categoryString.split("Constraint ");
1751                 if (matches != null) {
1752                     for (int i = 1; i < splitRegex.length; i++) {
1753                         String regexString = splitRegex[i];
1754                         if (regexString.startsWith(String.valueOf(regexIndex))) {
1755                             // Do matching on actual match and not on regex string
1756                             String actualMatch = regexString.split("\\R", 2)[1];
1757                             Asserts.assertTrue(matches.stream().allMatch(actualMatch::contains),
1758                                                errorPrefix() + " could not find all matches at Constraint " + regexIndex);
1759                             matched = true;
1760                         }
1761                     }
1762                 }
1763             }
1764         }
1765     }
1766 }
1767 
1768 // Base class for all good regex based constraints.
1769 abstract class GoodRegexConstraint extends RegexConstraint {
1770 
1771     GoodRegexConstraint(Class<?> klass, String methodName, String category, int ruleIdx, int... regexIndexes) {
1772         super(klass, methodName, category, true, null, ruleIdx, regexIndexes);
1773     }
1774 }
1775 
1776 // Constraint for rule that might fail with "counts" or "failOn", but the specified regex in "failOn" does not fail.
1777 class GoodFailOnRegexConstraint extends GoodRegexConstraint {
1778 
1779     private GoodFailOnRegexConstraint(Class<?> klass, String methodName, int ruleIdx, int... regexIndexes) {
1780         super(klass, methodName, "failOn", ruleIdx, regexIndexes);
1781     }
1782 
1783 
1784     public static GoodFailOnRegexConstraint create(Class<?> klass, String methodName, int ruleIdx, int... regexIndexes) {
1785         return new GoodFailOnRegexConstraint(klass, methodName, ruleIdx, regexIndexes);
1786     }
1787 }
1788 
1789 
1790 // Constraint for rule that might fail with "counts" or "failOn", but the specified regex in "counts" does not fail.
1791 class GoodCountsRegexConstraint extends GoodRegexConstraint {
1792 
1793     private GoodCountsRegexConstraint(Class<?> klass, String methodName, int ruleIdx, int... regexIndexes) {
1794         super(klass, methodName, "counts", ruleIdx, regexIndexes);
1795     }
1796 
1797 
1798     public static GoodCountsRegexConstraint create(Class<?> klass, String methodName, int ruleIdx, int... regexIndexes) {
1799         return new GoodCountsRegexConstraint(klass, methodName, ruleIdx, regexIndexes);
1800     }
1801 }
1802 
1803 // Constraint for rule that fails with "failOn" and the specified regex must also fail.
1804 class BadFailOnConstraint extends RegexConstraint {
1805 
1806     BadFailOnConstraint(Class<?> klass, String methodName, int ruleIdx, List<String> matches, int... regexIndexes) {
1807         super(klass, methodName, "failOn", false, matches, ruleIdx, regexIndexes);
1808     }
1809 
1810     public static BadFailOnConstraint create(Class<?> klass, String methodName, int ruleIdx, int regexId, String... matches) {
1811         return new BadFailOnConstraint(klass, methodName, ruleIdx, new ArrayList<>(Arrays.asList(matches)), regexId);
1812     }
1813 
1814     public static BadFailOnConstraint create(Class<?> klass, String methodName, int ruleIdx, String... matches) {
1815         return new BadFailOnConstraint(klass, methodName, ruleIdx, new ArrayList<>(Arrays.asList(matches)), 1);
1816     }
1817 }
1818 
1819 // Constraint for rule that fails with "counts" and the specified regex must also fail.
1820 class BadCountsConstraint extends RegexConstraint {
1821 
1822     BadCountsConstraint(Class<?> klass, String methodName, int ruleIdx, List<String> matches, int... regexIndexes) {
1823         super(klass, methodName, "counts", false, matches, ruleIdx, regexIndexes);
1824     }
1825 
1826     public static BadCountsConstraint create(Class<?> klass, String methodName, int ruleIdx, int regexId, int foundCount, String... matches) {
1827         List<String> matchesList = getMatchesList(foundCount, matches, Arrays.asList(matches));
1828         return new BadCountsConstraint(klass, methodName, ruleIdx, matchesList, regexId);
1829     }
1830 
1831     public static BadCountsConstraint create(Class<?> klass, String methodName, int ruleIdx, int foundCount, String... matches) {
1832         List<String> matchesList = getMatchesList(foundCount, matches, Arrays.asList(matches));
1833         return new BadCountsConstraint(klass, methodName, ruleIdx, matchesList, 1);
1834     }
1835 
1836     private static List<String> getMatchesList(int foundCount, String[] matches, List<String> strings) {
1837         List<String> matchesList = new ArrayList<>();
1838         matchesList.add("Failed comparison: [found] " + foundCount);
1839         if (matches != null) {
1840             matchesList.addAll(strings);
1841         }
1842         return matchesList;
1843     }
1844 }