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