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