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