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