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 = {
 772             IRNode.STORE_OF_FIELD, "myClassEmpty", "1",
 773             IRNode.STORE_OF_CLASS, "oodCount", "0",
 774             IRNode.STORE_OF_CLASS, "GoodCount", "1",
 775             IRNode.STORE_OF_CLASS, "/GoodCount", "1",
 776             IRNode.STORE_OF_CLASS, "tests/GoodCount", "1",
 777             IRNode.STORE_OF_CLASS, "/tests/GoodCount", "1",
 778             IRNode.STORE_OF_CLASS, "ir_framework/tests/GoodCount", "1",
 779             IRNode.STORE_OF_CLASS, "/ir_framework/tests/GoodCount", "0",
 780             IRNode.STORE_OF_CLASS, "MyClassEmpty", "0"
 781         },
 782         failOn = {IRNode.STORE_OF_CLASS, "MyClassEmpty"})
 783     public void good6() {
 784         myClassEmpty = new MyClassEmpty();
 785     }
 786 
 787     @Test
 788     @IR(counts = {IRNode.STORE_OF_FIELD, "iFld", "3", IRNode.STORE_OF_CLASS, "GoodCount", "0",
 789                   IRNode.STORE_OF_CLASS, "MyClass", "2", IRNode.STORE_OF_CLASS, "MyClassSub", "1",
 790                   IRNode.STORE, "3"},
 791         failOn = {IRNode.STORE_OF_CLASS, "GoodCount"})
 792     public void good7() {
 793         myClass.iFld = 1;
 794         myClassSubPoly.iFld = 2;
 795         myClassSub.iFld = 3;
 796     }
 797 
 798     @Test
 799     @IR(counts = {IRNode.LOAD, "1", IRNode.STORE, "1"})
 800     public void good8() {
 801         result = iFld;
 802     }
 803 
 804 
 805     @Test
 806     @IR(counts = {IRNode.LOAD, "4", IRNode.STORE, "1", IRNode.LOAD_OF_FIELD, "iFld", "2", IRNode.LOAD_OF_FIELD, "iFld2", "0",
 807                   IRNode.LOAD_OF_FIELD, "lFldStatic", "1", IRNode.LOAD_OF_CLASS, "GoodCount", "2", IRNode.LOAD_OF_CLASS, "MyClass", "1",
 808                   IRNode.STORE_OF_CLASS, "GoodCount", "1", IRNode.STORE_OF_FIELD, "result", "1",
 809                   IRNode.LOAD_OF_FIELD, "myClass", "1"})
 810     public void good9() {
 811         result = iFld + MyClass.lFldStatic + myClass.iFld; // 1 + 1 + 2 loads (myClass is LoadN of GoodCount and myClass.iFld a LoadI of MyClass)
 812     }
 813 
 814     @Test
 815     @IR(counts = {IRNode.LOAD, "8",
 816                   IRNode.LOAD_B, "1",
 817                   IRNode.LOAD_UB, "1",
 818                   IRNode.LOAD_S, "1",
 819                   IRNode.LOAD_US, "1",
 820                   IRNode.LOAD_I, "1",
 821                   IRNode.LOAD_L, "1",
 822                   IRNode.LOAD_F, "1",
 823                   IRNode.LOAD_D, "1"})
 824     public void good10() {
 825         bFld++;
 826         cFld++;
 827         sFld++;
 828         iFld++;
 829         lFld++;
 830         fFld++;
 831         dFld++;
 832         flag = !flag;
 833     }
 834 
 835     @Test
 836     @IR(counts = {IRNode.LOAD, "8", IRNode.LOAD_OF_CLASS, "GoodCount", "8",
 837                   IRNode.LOAD_B, "1", IRNode.LOAD_B_OF_CLASS, "GoodCount", "1",
 838                   IRNode.LOAD_UB, "1", IRNode.LOAD_UB_OF_CLASS, "GoodCount", "1",
 839                   IRNode.LOAD_S, "1", IRNode.LOAD_S_OF_CLASS, "GoodCount", "1",
 840                   IRNode.LOAD_US, "1", IRNode.LOAD_US_OF_CLASS, "GoodCount", "1",
 841                   IRNode.LOAD_I, "1", IRNode.LOAD_I_OF_CLASS, "GoodCount", "1",
 842                   IRNode.LOAD_L, "1", IRNode.LOAD_L_OF_CLASS, "GoodCount", "1",
 843                   IRNode.LOAD_F, "1", IRNode.LOAD_F_OF_CLASS, "GoodCount", "1",
 844                   IRNode.LOAD_D, "1", IRNode.LOAD_D_OF_CLASS, "GoodCount", "1"})
 845     public void good11() {
 846         bFld++;
 847         cFld++;
 848         sFld++;
 849         iFld++;
 850         lFld++;
 851         fFld++;
 852         dFld++;
 853         flag = !flag;
 854     }
 855 }
 856 
 857 class BadCount {
 858     int iFld;
 859     int iFld2;
 860     int result;
 861     int result2;
 862     @Test
 863     @IR(counts = {IRNode.LOAD, "> 1000"}) // fail
 864     @IR(counts = {IRNode.STORE, "> 0"})
 865     public void bad1() {
 866         result = iFld;
 867         result2 = iFld2;
 868     }
 869 
 870     @Test
 871     @IR(counts = {IRNode.LOAD, "2"}) // fail
 872     @IR(counts = {IRNode.STORE, "< 2"})
 873     public void bad2() {
 874         result = iFld;
 875         result2 = iFld2;
 876     }
 877 
 878 
 879     @Test
 880     @IR(counts = {IRNode.LOAD, "0"}) // fail
 881     @IR(counts = {IRNode.STORE, " <= 1"}) // fail
 882     public void bad3() {
 883         result = iFld;
 884         result2 = iFld2;
 885     }
 886 }
 887 
 888 
 889 class RunTests {
 890     public int iFld;
 891 
 892     @Test
 893     @IR(counts = {IRNode.STORE, "1"})
 894     @IR(failOn = IRNode.LOAD)
 895     public void good1() {
 896         iFld = 42;
 897     }
 898 
 899     @Test
 900     @IR(counts = {IRNode.LOAD, "1"})
 901     @IR(failOn = IRNode.STORE)
 902     public int good2() {
 903         return iFld;
 904     }
 905 
 906     @Run(test = {"good1", "good2"})
 907     public void runGood1() {
 908         good1();
 909         good2();
 910     }
 911 
 912 
 913     @Test
 914     @IR(counts = {IRNode.STORE, "1"})
 915     @IR(failOn = IRNode.LOAD)
 916     public void good3(int x) {
 917         iFld = x;
 918     }
 919 
 920     @Test
 921     @IR(counts = {IRNode.STORE, "1"})
 922     @IR(failOn = IRNode.LOAD)
 923     public int bad1(int x) {
 924         return iFld + x;
 925     }
 926 
 927     @Run(test = {"bad1", "good3"})
 928     public void run() {
 929         bad1(2);
 930         good3(4);
 931     }
 932 }
 933 
 934 class Calls {
 935 
 936     @Test
 937     @IR(counts = {IRNode.CALL, "1"})
 938     @IR(failOn = {IRNode.CALL_OF_METHOD, "dontInline",  // Fails
 939                   IRNode.STATIC_CALL_OF_METHOD, "dontInline"}) // Fails
 940     @IR(failOn = {IRNode.CALL_OF_METHOD, "forceInline",
 941                   IRNode.STATIC_CALL_OF_METHOD, "forceInline",
 942                   IRNode.CALL_OF_METHOD, "dontInlines",
 943                   IRNode.STATIC_CALL_OF_METHOD, "dontInlines",
 944                   IRNode.CALL_OF_METHOD, "dont",
 945                   IRNode.STATIC_CALL_OF_METHOD, "dont"})
 946     public void calls() {
 947         dontInline();
 948         forceInline();
 949     }
 950 
 951     @DontInline
 952     public void dontInline() {}
 953 
 954     @ForceInline
 955     public void forceInline() {}
 956 }
 957 
 958 class AllocInstance {
 959     MyClass myClass;
 960 
 961     @Test
 962     @IR(failOn = {IRNode.ALLOC})
 963     @IR(failOn = {IRNode.ALLOC_OF, "MyClass"})
 964     @IR(failOn = {IRNode.ALLOC_OF, "Class"}) // Does not fail
 965     @IR(failOn = {IRNode.ALLOC_OF, "MyClasss"}) // Does not fail
 966     @IR(failOn = {IRNode.ALLOC_OF, "ir_framework/tests/MySubClass"}) // Does not fail
 967     @IR(failOn = {IRNode.ALLOC_OF, "ir_framework/tests/MyClass"})
 968     @IR(failOn = {IRNode.ALLOC_OF, "tests/MyClass"})
 969     @IR(failOn = {IRNode.ALLOC_OF, "ests/MyClass"}) // Does not fail
 970     @IR(failOn = {IRNode.ALLOC_OF, "Atests/MyClass"}) // Does not fail
 971     @IR(failOn = {IRNode.ALLOC_OF, "tests"}) // Does not fail
 972     public void allocInstance() {
 973         myClass = new MyClass();
 974     }
 975 }
 976 
 977 class AllocArray {
 978     MyClass[] myClassArray;
 979     MyClass[][] myClassMultiArray;
 980 
 981     @Test
 982     @IR(failOn = {IRNode.ALLOC_ARRAY})
 983     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "MyClass"})
 984     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "Class"}) // Does not fail
 985     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "MyClasss"}) // Does not fail
 986     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "ir_framework/tests/MySubClass"}) // Does not fail
 987     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "ir_framework/tests/MyClass"})
 988     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "tests/MyClass"})
 989     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "ests/MyClass"}) // Does not fail
 990     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "Atests/MyClass"}) // Does not fail
 991     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "tests"}) // Does not fail
 992     public void allocArray() {
 993         myClassArray = new MyClass[2];
 994     }
 995 
 996     @Test
 997     @IR(failOn = {IRNode.ALLOC_ARRAY})
 998     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "MyClass"})
 999     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "Class"}) // Does not fail
1000     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "MyClasss"}) // Does not fail
1001     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "ir_framework/tests/MySubClass"}) // Does not fail
1002     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "ir_framework/tests/MyClass"})
1003     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "tests/MyClass"})
1004     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "ests/MyClass"}) // Does not fail
1005     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "Atests/MyClass"}) // Does not fail
1006     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "tests"}) // Does not fail
1007     public void allocMultiArray() {
1008         myClassMultiArray = new MyClass[2][3];
1009     }
1010 }
1011 
1012 class Loads {
1013     int iFld = 34;
1014     int result = 0;
1015     Object myClass = new MyClass();
1016 
1017     @Test
1018     @IR(failOn = {IRNode.LOAD, IRNode.LOOP, IRNode.LOAD_I}, counts = {IRNode.LOOP, "2", IRNode.LOAD, "2", IRNode.STORE, "2"})
1019     @IR(failOn = {IRNode.LOOP, IRNode.LOOP}, counts = {IRNode.LOOP, "0", IRNode.LOAD, "1"}) // Does not fail
1020     @IR(failOn = {IRNode.LOOP, IRNode.LOOP}, counts = {IRNode.LOOP, "0", IRNode.STORE, "1"})
1021     @IR(failOn = {IRNode.LOOP, IRNode.STORE}, counts = {IRNode.LOOP, "0", IRNode.LOAD, "1"})
1022     @IR(failOn = {IRNode.LOAD_OF_CLASS, "ir_framework/tests/Loads"})
1023     @IR(failOn = {IRNode.LOAD_OF_CLASS, "Loads"})
1024     @IR(failOn = {IRNode.LOAD_OF_FIELD, "iFld"})
1025     @IR(failOn = {IRNode.LOAD_OF_FIELD, "iFld2", IRNode.LOAD_OF_CLASS, "Load"}) // Does not fail
1026     @IR(failOn = {IRNode.LOAD_KLASS}) // Does not fail
1027     @IR(counts = {IRNode.FIELD_ACCESS, "3"}) // Does not fail
1028     public void load() {
1029         result = iFld;
1030         iFld = 3;
1031     }
1032 
1033     @Test
1034     @IR(failOn = {IRNode.LOAD_KLASS})
1035     @IR(counts = {IRNode.FIELD_ACCESS, "3"})
1036     public void loadKlass() {
1037         if (myClass instanceof MyClass) {
1038             result = 3;
1039         }
1040     }
1041 }
1042 
1043 class Loops {
1044     int limit = 1024;
1045     int[] iArr = new int[100];
1046 
1047     @DontInline
1048     public void dontInline() {}
1049 
1050     @Test
1051     @IR(failOn = IRNode.LOOP) // fails
1052     @IR(failOn = IRNode.COUNTED_LOOP)
1053     @IR(failOn = IRNode.COUNTED_LOOP_MAIN)
1054     public void loop() {
1055         for (int i = 0; i < limit; i++) {
1056             dontInline();
1057         }
1058     }
1059 
1060     @Test
1061     @IR(failOn = IRNode.LOOP)
1062     @IR(failOn = IRNode.COUNTED_LOOP) // fails
1063     @IR(failOn = IRNode.COUNTED_LOOP_MAIN)
1064     public void countedLoop() {
1065         for (int i = 0; i < 2000; i++) {
1066             dontInline();
1067         }
1068     }
1069 
1070     @Test
1071     @IR(failOn = IRNode.LOOP) // fails
1072     @IR(failOn = IRNode.COUNTED_LOOP) // fails
1073     @IR(failOn = IRNode.COUNTED_LOOP_MAIN)
1074     public void loopAndCountedLoop() {
1075         for (int i = 0; i < 2000; i++) {
1076             for (int j = 0; j < limit; j++) {
1077                 dontInline();
1078             }
1079         }
1080     }
1081 
1082     @Test
1083     @IR(failOn = IRNode.LOOP)
1084     @IR(failOn = IRNode.COUNTED_LOOP) // fails
1085     @IR(failOn = IRNode.COUNTED_LOOP_MAIN) // fails
1086     public void countedLoopMain() {
1087         // Cannot unroll completely -> create pre/main/post
1088         for (int i = 0; i < 100; i++) {
1089             iArr[i] = i;
1090         }
1091     }
1092 
1093     @Test
1094     @IR(failOn = IRNode.LOOP)
1095     @IR(failOn = IRNode.COUNTED_LOOP)
1096     @IR(failOn = IRNode.COUNTED_LOOP_MAIN)
1097     public void countedLoopUnrolled() {
1098         // Completely unrolled -> no pre/main/post
1099         for (int i = 0; i < 8; i++) {
1100             iArr[i] = i;
1101         }
1102     }
1103 }
1104 
1105 class Traps {
1106     int number42 = 42;
1107     int iFld = 10;
1108     int[] iArr = new int[2];
1109     MyClass myClass = new MyClass();
1110     MyClassSub myClassSub = new MyClassSub();
1111     NotLoaded notLoaded = new NotLoaded();
1112     Object[] oArr = new Object[10];
1113     MyClass[] mArr = new MyClass[10];
1114 
1115     @Test
1116     @IR(failOn = IRNode.TRAP)
1117     @IR(failOn = {IRNode.STORE_OF_FIELD, "iFld"}) // fails
1118     @IR(failOn = {IRNode.PREDICATE_TRAP,
1119                   IRNode.UNSTABLE_IF_TRAP,
1120                   IRNode.NULL_CHECK_TRAP,
1121                   IRNode.NULL_ASSERT_TRAP,
1122                   IRNode.RANGE_CHECK_TRAP,
1123                   IRNode.CLASS_CHECK_TRAP,
1124                   IRNode.INTRINSIC_TRAP,
1125                   IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
1126                   IRNode.UNHANDLED_TRAP})
1127     public void noTraps() {
1128         for (int i = 0; i < 100; i++) {
1129             if (i < 42) {
1130                 // Reached, no uncommon trap
1131                 iFld = i;
1132             }
1133         }
1134     }
1135 
1136     @Test
1137     @IR(failOn = IRNode.TRAP) // fails
1138     @IR(failOn = IRNode.PREDICATE_TRAP) // fails
1139     @IR(failOn = {IRNode.STORE_OF_FIELD, "iFld"})
1140     @IR(failOn = {IRNode.UNSTABLE_IF_TRAP,
1141                   IRNode.NULL_CHECK_TRAP,
1142                   IRNode.NULL_ASSERT_TRAP,
1143                   IRNode.RANGE_CHECK_TRAP,
1144                   IRNode.CLASS_CHECK_TRAP,
1145                   IRNode.INTRINSIC_TRAP,
1146                   IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
1147                   IRNode.UNHANDLED_TRAP})
1148     public void predicateTrap() {
1149         for (int i = 0; i < 100; i++) {
1150             if (number42 != 42) {
1151                 // Never reached
1152                 iFld = i;
1153             }
1154         }
1155     }
1156 
1157     @Test
1158     @IR(failOn = IRNode.TRAP) // fails
1159     @IR(failOn = IRNode.NULL_CHECK_TRAP) // fails
1160     @IR(failOn = IRNode.CLASS_CHECK_TRAP) // fails
1161     @IR(failOn = {IRNode.PREDICATE_TRAP,
1162                   IRNode.NULL_ASSERT_TRAP,
1163                   IRNode.RANGE_CHECK_TRAP,
1164                   IRNode.UNSTABLE_IF_TRAP,
1165                   IRNode.INTRINSIC_TRAP,
1166                   IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
1167                   IRNode.UNHANDLED_TRAP})
1168     public void nullCheck() {
1169         if (myClass instanceof MyClassSub) {
1170             iFld = 4;
1171         }
1172     }
1173 
1174     @Test
1175     @IR(failOn = IRNode.TRAP) // fails
1176     @IR(failOn = IRNode.NULL_ASSERT_TRAP) // fails
1177     @IR(failOn = IRNode.NULL_CHECK_TRAP) // fails
1178     @IR(failOn = {IRNode.PREDICATE_TRAP,
1179                   IRNode.UNSTABLE_IF_TRAP,
1180                   IRNode.RANGE_CHECK_TRAP,
1181                   IRNode.CLASS_CHECK_TRAP,
1182                   IRNode.INTRINSIC_TRAP,
1183                   IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
1184                   IRNode.UNHANDLED_TRAP})
1185     public Object nullAssert() {
1186         return notLoaded.notLoadedFld;
1187     }
1188 
1189     @Test
1190     @Arguments(values = Argument.TRUE)
1191     @IR(failOn = IRNode.TRAP) // fails
1192     @IR(failOn = IRNode.UNSTABLE_IF_TRAP) // fails
1193     @IR(failOn = {IRNode.PREDICATE_TRAP,
1194                   IRNode.NULL_CHECK_TRAP,
1195                   IRNode.NULL_ASSERT_TRAP,
1196                   IRNode.RANGE_CHECK_TRAP,
1197                   IRNode.CLASS_CHECK_TRAP,
1198                   IRNode.INTRINSIC_TRAP,
1199                   IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
1200                   IRNode.UNHANDLED_TRAP})
1201     public void unstableIf(boolean flag) {
1202         if (flag) {
1203             iFld++;
1204         } else {
1205             iFld--;
1206         }
1207     }
1208 
1209     @Test
1210     @IR(failOn = IRNode.TRAP) // fails
1211     @IR(failOn = IRNode.CLASS_CHECK_TRAP) // fails
1212     @IR(failOn = IRNode.NULL_CHECK_TRAP) // fails
1213     @IR(failOn = {IRNode.PREDICATE_TRAP,
1214                   IRNode.UNSTABLE_IF_TRAP,
1215                   IRNode.NULL_ASSERT_TRAP,
1216                   IRNode.RANGE_CHECK_TRAP,
1217                   IRNode.INTRINSIC_TRAP,
1218                   IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
1219                   IRNode.UNHANDLED_TRAP})
1220     public void classCheck() {
1221         try {
1222             myClassSub = (MyClassSub) myClass;
1223         } catch (ClassCastException e) {
1224             // Expected
1225         }
1226     }
1227 
1228     @Test
1229     @IR(failOn = IRNode.TRAP) // fails
1230     @IR(failOn = IRNode.RANGE_CHECK_TRAP) // fails
1231     @IR(failOn = IRNode.NULL_CHECK_TRAP) // fails
1232     @IR(failOn = {IRNode.PREDICATE_TRAP,
1233                   IRNode.UNSTABLE_IF_TRAP,
1234                   IRNode.NULL_ASSERT_TRAP,
1235                   IRNode.CLASS_CHECK_TRAP,
1236                   IRNode.INTRINSIC_TRAP,
1237                   IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
1238                   IRNode.UNHANDLED_TRAP})
1239     public void rangeCheck() {
1240         iArr[1] = 3;
1241     }
1242 
1243 
1244     @Test
1245     @IR(failOn = IRNode.TRAP) // fails
1246     @IR(failOn = IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP) // fails
1247     @IR(failOn = IRNode.INTRINSIC_TRAP) // fails
1248     @IR(failOn = IRNode.NULL_CHECK_TRAP) // fails
1249     @IR(failOn = {IRNode.PREDICATE_TRAP,
1250                   IRNode.UNSTABLE_IF_TRAP,
1251                   IRNode.NULL_ASSERT_TRAP,
1252                   IRNode.CLASS_CHECK_TRAP,
1253                   IRNode.RANGE_CHECK_TRAP,
1254                   IRNode.UNHANDLED_TRAP})
1255     public void instrinsicOrTypeCheckedInlining() {
1256         System.arraycopy(oArr, 0, mArr, 0, 8);
1257     }
1258 }
1259 
1260 class UnhandledTrap {
1261     int iFld = 34;
1262 
1263     @Test
1264     @IR(failOn = IRNode.TRAP) // fails
1265     @IR(failOn = IRNode.UNHANDLED_TRAP) // fails
1266     @IR(failOn = {IRNode.PREDICATE_TRAP,
1267                   IRNode.UNSTABLE_IF_TRAP,
1268                   IRNode.NULL_CHECK_TRAP,
1269                   IRNode.NULL_ASSERT_TRAP,
1270                   IRNode.RANGE_CHECK_TRAP,
1271                   IRNode.CLASS_CHECK_TRAP})
1272     public void unhandled() {
1273         try {
1274             throw new RuntimeException();
1275         } catch (RuntimeException e) {
1276             // Expected
1277         }
1278     }
1279 }
1280 
1281 class ScopeObj {
1282 
1283     @DontInline
1284     public void dontInline(int i) {}
1285 
1286     @Test
1287     @IR(failOn = IRNode.SCOPE_OBJECT) // fails
1288     public int scopeObject() {
1289         MyClass myClass = new MyClass();
1290         for (int i = 0; i < 100; i++) {
1291             dontInline(myClass.iFld);
1292         }
1293         return 3;
1294     }
1295 }
1296 
1297 class Membar {
1298     volatile MyClass myClass;
1299 
1300     @Test
1301     @IR(failOn = IRNode.MEMBAR) // fails
1302     public int membar() {
1303         myClass = new MyClass();
1304         return myClass.x;
1305     }
1306 }
1307 
1308 class CheckCastArray {
1309     Object[] oArr = new Object[10];
1310     MyClass[] mArr = new MyClass[10];
1311 
1312     @Test
1313     @IR(failOn = IRNode.CHECKCAST_ARRAY) // fails
1314     @IR(failOn = {IRNode.CHECKCAST_ARRAY_OF, "MyClass", // fails
1315                   IRNode.CHECKCAST_ARRAY_OF, "ir_framework/tests/MyClass"}) // fails
1316     @IR(failOn = {IRNode.CHECKCAST_ARRAY_OF, "MyClasss", IRNode.CHECKCAST_ARRAY_OF, "Object"})
1317     public boolean array(Object[] arr) {
1318         return arr instanceof MyClass[];
1319     }
1320 
1321     @Run(test = "array")
1322     public void testArray() {
1323         array(oArr);
1324         array(mArr);
1325     }
1326 
1327     @Test
1328     @IR(failOn = IRNode.CHECKCAST_ARRAYCOPY) // fails
1329     public Object[] arrayCopy(Object[] src, Class klass) {
1330         return Arrays.copyOf(src, 8, klass);
1331     }
1332 
1333     @Run(test = "arrayCopy")
1334     public void testArrayCopy() {
1335         arrayCopy(mArr, MyClass[].class);
1336         arrayCopy(mArr, Object[].class);
1337         arrayCopy(mArr, MyClassEmpty[].class);
1338     }
1339 }
1340 
1341 class CompilationOutputOfFails {
1342     private Object obj;
1343 
1344     @Test
1345     @IR(failOn = IRNode.COUNTED_LOOP)
1346     @IR(failOn = {"call"},
1347         phase = CompilePhase.PRINT_OPTO_ASSEMBLY)
1348     public void both1() {
1349         for (int i = 0; i < 100; i++) {
1350             dontInline();
1351         }
1352     }
1353 
1354     @Test
1355     @IR(failOn = "CountedLoop|call",
1356         phase = {CompilePhase.PRINT_IDEAL, CompilePhase.PRINT_OPTO_ASSEMBLY})
1357     public void both2() {
1358         for (int i = 0; i < 100; i++) {
1359             dontInline();
1360         }
1361     }
1362 
1363     @Test
1364     @IR(failOn = IRNode.COUNTED_LOOP)
1365     @IR(failOn = "call", phase = CompilePhase.PRINT_OPTO_ASSEMBLY)
1366     public void both3() {
1367         for (int i = 0; i < 100; i++) {
1368             dontInline();
1369         }
1370     }
1371 
1372     @Test
1373     @IR(counts = {IRNode.COUNTED_LOOP, "0"})
1374     @IR(counts = {"call", "0"},
1375         phase = {CompilePhase.PRINT_OPTO_ASSEMBLY})
1376     public void both4() {
1377         for (int i = 0; i < 100; i++) {
1378             dontInline();
1379         }
1380     }
1381 
1382     @Test
1383     @IR(counts = {"CountedLoop|call", "10"},
1384         phase = {CompilePhase.PRINT_IDEAL, CompilePhase.PRINT_OPTO_ASSEMBLY})
1385     public void both5() {
1386         for (int i = 0; i < 100; i++) {
1387             dontInline();
1388         }
1389     }
1390 
1391     @Test
1392     @IR(counts = {IRNode.COUNTED_LOOP, "0"})
1393     @IR(counts = {"call", "0"}, phase = CompilePhase.PRINT_OPTO_ASSEMBLY)
1394     public void both6() {
1395         for (int i = 0; i < 100; i++) {
1396             dontInline();
1397         }
1398     }
1399 
1400     @Test
1401     @IR(failOn = IRNode.COUNTED_LOOP)
1402     @IR(counts = {"call", "0"}, phase = CompilePhase.PRINT_OPTO_ASSEMBLY)
1403     public void both7() {
1404         for (int i = 0; i < 100; i++) {
1405             dontInline();
1406         }
1407     }
1408 
1409     @Test
1410     @IR(failOn = IRNode.COUNTED_LOOP)
1411     public void ideal1() {
1412         for (int i = 0; i < 100; i++) {
1413             dontInline();
1414         }
1415     }
1416 
1417     @Test
1418     @IR(failOn = IRNode.COUNTED_LOOP)
1419     @IR(failOn = IRNode.ALLOC) // not fail
1420     public void ideal2() {
1421         for (int i = 0; i < 100; i++) {
1422             dontInline();
1423         }
1424     }
1425 
1426     @Test
1427     @IR(failOn = IRNode.COUNTED_LOOP)
1428     @IR(counts = {IRNode.ALLOC, "0"}) // not fail
1429     public void ideal3() {
1430         for (int i = 0; i < 100; i++) {
1431             dontInline();
1432         }
1433     }
1434 
1435     @Test
1436     @IR(counts = {IRNode.COUNTED_LOOP, "2"})
1437     public void ideal4() {
1438         for (int i = 0; i < 100; i++) {
1439             dontInline();
1440         }
1441     }
1442 
1443     @Test
1444     @IR(failOn = IRNode.ALLOC) // not fail
1445     @IR(counts = {IRNode.COUNTED_LOOP, "2"})
1446     public void ideal5() {
1447         for (int i = 0; i < 100; i++) {
1448             dontInline();
1449         }
1450     }
1451 
1452     @Test
1453     @IR(counts = {IRNode.ALLOC, "0"}) // not fail
1454     @IR(counts = {IRNode.COUNTED_LOOP, "2"})
1455     public void ideal6() {
1456         for (int i = 0; i < 100; i++) {
1457             dontInline();
1458         }
1459     }
1460 
1461     @Test
1462     @IR(counts = {IRNode.COUNTED_LOOP, "5"})
1463     @IR(counts = {IRNode.COUNTED_LOOP, "2"})
1464     public void ideal7() {
1465         for (int i = 0; i < 100; i++) {
1466             dontInline();
1467         }
1468     }
1469 
1470     @Test
1471     @IR(failOn = IRNode.ALLOC)
1472     public void macro1() {
1473         obj = new Object();
1474     }
1475 
1476     @Test
1477     @IR(failOn = IRNode.ALLOC)
1478     @IR(failOn = IRNode.STORE_F) // not fail
1479     public void macro2() {
1480         obj = new Object();
1481     }
1482 
1483     @Test
1484     @IR(failOn = IRNode.ALLOC)
1485     @IR(counts = {IRNode.COUNTED_LOOP, "1"}) // not fail
1486     public void macro3() {
1487         for (int i = 0; i < 100; i++) {
1488             obj = new Object();
1489         }
1490     }
1491 
1492     @Test
1493     @IR(counts = {IRNode.ALLOC, "0"})
1494     public void macro4() {
1495         obj = new Object();
1496     }
1497 
1498     @Test
1499     @IR(failOn = IRNode.STORE_F) // not fail
1500     @IR(counts = {IRNode.ALLOC, "0"})
1501     public void macro5() {
1502         obj = new Object();
1503     }
1504 
1505     @Test
1506     @IR(counts = {IRNode.STORE_F, "0"}) // not fail
1507     @IR(counts = {IRNode.ALLOC, "0"})
1508     public void macro6() {
1509         obj = new Object();
1510     }
1511 
1512     @Test
1513     @IR(counts = {IRNode.ALLOC, "10"})
1514     @IR(counts = {IRNode.ALLOC, "0"})
1515     public void macro7() {
1516         obj = new Object();
1517     }
1518 
1519     @DontInline
1520     private void dontInline() {}
1521 }
1522 
1523 
1524 // Used only by class Traps
1525 class NotLoaded {
1526     NotLoadedHelper notLoadedFld;
1527 }
1528 
1529 // Used only by class Traps
1530 class NotLoadedHelper {}
1531 
1532 class MyClass {
1533     int iFld = 3;
1534     int x = 5;
1535     static long lFldStatic;
1536 }
1537 
1538 class MyClassEmpty {}
1539 
1540 class MyClassEmptySub extends MyClassEmpty {}
1541 
1542 class MyClassSub extends MyClass {
1543     int iFld;
1544     static int iFldStatic;
1545 }
1546 
1547 
1548 // Base class for any kind of constraint that is used to verify if the framework reports the correct IR failures.
1549 abstract class Constraint {
1550     private final Class<?> klass;
1551     protected final int ruleIdx;
1552     private final Pattern methodPattern;
1553     private final String classAndMethod;
1554     protected final Pattern irPattern;
1555     private final String methodName;
1556     protected boolean matched;
1557 
1558     Constraint(Class<?> klass, String methodName, int ruleIdx, Pattern irPattern) {
1559         this.klass = klass;
1560         classAndMethod = klass.getSimpleName() + "." + methodName;
1561         this.ruleIdx = ruleIdx;
1562         this.methodPattern = Pattern.compile(Pattern.quote(classAndMethod));
1563         this.irPattern = irPattern;
1564         this.methodName = methodName;
1565         this.matched = false;
1566     }
1567 
1568     // For good constraints only
1569     Constraint(Class<?> klass, String methodName, int ruleIdx) {
1570         this.klass = klass;
1571         classAndMethod = klass.getSimpleName() + "." + methodName;
1572         this.ruleIdx = ruleIdx;
1573         this.methodPattern = Pattern.compile(Pattern.quote(classAndMethod));
1574         this.irPattern = null;
1575         this.methodName = methodName;
1576         this.matched = false;
1577     }
1578 
1579     @Override
1580     public String toString() {
1581         return "Constraint " + getClass().getSimpleName() + ", " + errorPrefix();
1582     }
1583 
1584     public Class<?> getKlass() {
1585         return klass;
1586     }
1587 
1588     protected String errorPrefix() {
1589         return "Class " + klass.getSimpleName() + ", Method " + methodName + ", Rule " + ruleIdx;
1590     }
1591 
1592     public void checkConstraint(IRViolationException e) {
1593         String message = e.getExceptionInfo();
1594         String[] splitMethods = message.split("Method");
1595         for (int i = 1; i < splitMethods.length; i++) {
1596             String method = splitMethods[i];
1597             if (methodPattern.matcher(method).find()) {
1598                 String[] splitIrRules = method.split("@IR ");
1599                 for (int j = 1; j < splitIrRules.length; j++) {
1600                     String irRule = splitIrRules[j];
1601                     if (irRule.startsWith("rule " + ruleIdx)) {
1602                         checkIRRule(irRule);
1603                     }
1604                 }
1605             }
1606         }
1607         Asserts.assertTrue(matched, this + " should have been matched");
1608     }
1609 
1610     abstract protected void checkIRRule(String irRule);
1611 }
1612 
1613 // Constraint for rule that does not fail.
1614 class GoodRuleConstraint extends Constraint {
1615 
1616     GoodRuleConstraint(Class<?> klass, String methodName, int ruleIdx) {
1617         super(klass, methodName, ruleIdx);
1618         matched = true;
1619     }
1620 
1621     public static GoodRuleConstraint create(Class<?> klass, String methodName, int ruleIdx) {
1622         return new GoodRuleConstraint(klass, methodName, ruleIdx);
1623     }
1624 
1625     @Override
1626     protected void checkIRRule(String irRule) {
1627         Asserts.fail(errorPrefix() + " should not fail:" + System.lineSeparator() + irRule);
1628     }
1629 }
1630 
1631 // Constraint for rule that might fail but not with "failOn".
1632 class GoodFailOnConstraint extends GoodRuleConstraint {
1633 
1634     private GoodFailOnConstraint(Class<?> klass, String methodName, int ruleIdx) {
1635         super(klass, methodName, ruleIdx);
1636     }
1637 
1638     public static GoodFailOnConstraint create(Class<?> klass, String methodName, int ruleIdx) {
1639         return new GoodFailOnConstraint(klass, methodName, ruleIdx);
1640     }
1641 
1642     @Override
1643     protected void checkIRRule(String irRule) {
1644         Asserts.assertFalse(irRule.contains("- failOn"), errorPrefix() + " should not have failed:" + System.lineSeparator() + irRule);
1645     }
1646 }
1647 
1648 // Constraint for rule that might fail but not with "counts".
1649 class GoodCountsConstraint extends GoodRuleConstraint {
1650 
1651     private GoodCountsConstraint(Class<?> klass, String methodName, int ruleIdx) {
1652         super(klass, methodName, ruleIdx);
1653     }
1654 
1655     public static GoodCountsConstraint create(Class<?> klass, String methodName, int ruleIdx) {
1656         return new GoodCountsConstraint(klass, methodName, ruleIdx);
1657     }
1658 
1659     @Override
1660     protected void checkIRRule(String irRule) {
1661         Asserts.assertFalse(irRule.contains("- counts"), errorPrefix() + " should not have failed with counts:"
1662                                                          + System.lineSeparator() + irRule);
1663     }
1664 }
1665 
1666 // Base class for all Regex based constraint.
1667 abstract class RegexConstraint extends Constraint {
1668     final String category;
1669     final String otherCategory;
1670     final int[] regexIndexes;
1671     final boolean isGood;
1672     final List<String> matches;
1673 
1674     RegexConstraint(Class<?> klass, String methodName, String category, boolean isGood, List<String> matches, int ruleIdx, int... regexIndexes) {
1675         super(klass, methodName, ruleIdx, initIRPattern(category, ruleIdx));
1676         this.category = category;
1677         this.regexIndexes = regexIndexes;
1678         if (category.equals("failOn")) {
1679             this.otherCategory = "counts";
1680         } else {
1681             Asserts.assertTrue(category.equals("counts"));
1682             this.otherCategory = "failOn";
1683         }
1684         this.isGood = isGood;
1685         this.matches = matches;
1686     }
1687 
1688     @Override
1689     public String toString() {
1690         String msg = super.toString() + ", ";
1691         if (regexIndexes.length > 1) {
1692             msg += "regexes: [" + String.join(", ", Arrays.stream(regexIndexes).mapToObj(String::valueOf).toArray(String[]::new)) + "]";
1693         } else {
1694             msg += "regex: " + regexIndexes[0];
1695         }
1696         return msg;
1697     }
1698 
1699     @Override
1700     protected String errorPrefix() {
1701         return super.errorPrefix() + " with \"" + category + "\"";
1702     }
1703 
1704     private static Pattern initIRPattern(String category, int ruleIdx) {
1705         if (category.equals("failOn")) {
1706             return Pattern.compile("rule " + ruleIdx + ":.*\\R.*- failOn: Graph contains forbidden nodes.*\\R" +
1707                                    ".*Constraint \\d+:.*\\R.*Matched forbidden node.*");
1708         } else {
1709             return Pattern.compile("rule " + ruleIdx + ":.*\\R.*- counts: Graph contains wrong number of nodes:\\R" +
1710                                    ".*Constraint \\d+:.*\\R.*Expected.*");
1711         }
1712     }
1713 
1714     @Override
1715     protected void checkIRRule(String irRule) {
1716         int categoryIndex = irRule.indexOf("- " + category);
1717         Asserts.assertTrue(categoryIndex != -1, errorPrefix() + " should have failed");
1718 
1719         int endIndex;
1720         int otherCategoryIndex = irRule.indexOf("- " + otherCategory);
1721         if (otherCategoryIndex == -1 || categoryIndex > otherCategoryIndex) {
1722             endIndex = irRule.length();
1723         } else {
1724             endIndex = otherCategoryIndex;
1725         }
1726         String categoryString = irRule.substring(irRule.indexOf("- " + category), endIndex);
1727         Pattern pattern;
1728         Matcher matcher;
1729         for (int regexIndex : this.regexIndexes) {
1730             pattern = Pattern.compile("Constraint " + regexIndex + ":.*");
1731             matcher = pattern.matcher(categoryString);
1732             if (isGood) {
1733                 Asserts.assertFalse(matcher.find(), errorPrefix() + " failed with Constraint " + regexIndex);
1734                 matched = true;
1735             } else {
1736                 Asserts.assertTrue(matcher.find(), errorPrefix() + " should have failed at Constraint " + regexIndex);
1737                 String[] splitRegex = categoryString.split("Constraint ");
1738                 if (matches != null) {
1739                     for (int i = 1; i < splitRegex.length; i++) {
1740                         String regexString = splitRegex[i];
1741                         if (regexString.startsWith(String.valueOf(regexIndex))) {
1742                             // Do matching on actual match and not on regex string
1743                             String actualMatch = regexString.split("\\R", 2)[1];
1744                             Asserts.assertTrue(matches.stream().allMatch(actualMatch::contains),
1745                                                errorPrefix() + " could not find all matches at Constraint " + regexIndex);
1746                             matched = true;
1747                         }
1748                     }
1749                 }
1750             }
1751         }
1752     }
1753 }
1754 
1755 // Base class for all good regex based constraints.
1756 abstract class GoodRegexConstraint extends RegexConstraint {
1757 
1758     GoodRegexConstraint(Class<?> klass, String methodName, String category, int ruleIdx, int... regexIndexes) {
1759         super(klass, methodName, category, true, null, ruleIdx, regexIndexes);
1760     }
1761 }
1762 
1763 // Constraint for rule that might fail with "counts" or "failOn", but the specified regex in "failOn" does not fail.
1764 class GoodFailOnRegexConstraint extends GoodRegexConstraint {
1765 
1766     private GoodFailOnRegexConstraint(Class<?> klass, String methodName, int ruleIdx, int... regexIndexes) {
1767         super(klass, methodName, "failOn", ruleIdx, regexIndexes);
1768     }
1769 
1770 
1771     public static GoodFailOnRegexConstraint create(Class<?> klass, String methodName, int ruleIdx, int... regexIndexes) {
1772         return new GoodFailOnRegexConstraint(klass, methodName, ruleIdx, regexIndexes);
1773     }
1774 }
1775 
1776 
1777 // Constraint for rule that might fail with "counts" or "failOn", but the specified regex in "counts" does not fail.
1778 class GoodCountsRegexConstraint extends GoodRegexConstraint {
1779 
1780     private GoodCountsRegexConstraint(Class<?> klass, String methodName, int ruleIdx, int... regexIndexes) {
1781         super(klass, methodName, "counts", ruleIdx, regexIndexes);
1782     }
1783 
1784 
1785     public static GoodCountsRegexConstraint create(Class<?> klass, String methodName, int ruleIdx, int... regexIndexes) {
1786         return new GoodCountsRegexConstraint(klass, methodName, ruleIdx, regexIndexes);
1787     }
1788 }
1789 
1790 // Constraint for rule that fails with "failOn" and the specified regex must also fail.
1791 class BadFailOnConstraint extends RegexConstraint {
1792 
1793     BadFailOnConstraint(Class<?> klass, String methodName, int ruleIdx, List<String> matches, int... regexIndexes) {
1794         super(klass, methodName, "failOn", false, matches, ruleIdx, regexIndexes);
1795     }
1796 
1797     public static BadFailOnConstraint create(Class<?> klass, String methodName, int ruleIdx, int regexId, String... matches) {
1798         return new BadFailOnConstraint(klass, methodName, ruleIdx, new ArrayList<>(Arrays.asList(matches)), regexId);
1799     }
1800 
1801     public static BadFailOnConstraint create(Class<?> klass, String methodName, int ruleIdx, String... matches) {
1802         return new BadFailOnConstraint(klass, methodName, ruleIdx, new ArrayList<>(Arrays.asList(matches)), 1);
1803     }
1804 }
1805 
1806 // Constraint for rule that fails with "counts" and the specified regex must also fail.
1807 class BadCountsConstraint extends RegexConstraint {
1808 
1809     BadCountsConstraint(Class<?> klass, String methodName, int ruleIdx, List<String> matches, int... regexIndexes) {
1810         super(klass, methodName, "counts", false, matches, ruleIdx, regexIndexes);
1811     }
1812 
1813     public static BadCountsConstraint create(Class<?> klass, String methodName, int ruleIdx, int regexId, int foundCount, String... matches) {
1814         List<String> matchesList = getMatchesList(foundCount, matches, Arrays.asList(matches));
1815         return new BadCountsConstraint(klass, methodName, ruleIdx, matchesList, regexId);
1816     }
1817 
1818     public static BadCountsConstraint create(Class<?> klass, String methodName, int ruleIdx, int foundCount, String... matches) {
1819         List<String> matchesList = getMatchesList(foundCount, matches, Arrays.asList(matches));
1820         return new BadCountsConstraint(klass, methodName, ruleIdx, matchesList, 1);
1821     }
1822 
1823     private static List<String> getMatchesList(int foundCount, String[] matches, List<String> strings) {
1824         List<String> matchesList = new ArrayList<>();
1825         matchesList.add("Failed comparison: [found] " + foundCount);
1826         if (matches != null) {
1827             matchesList.addAll(strings);
1828         }
1829         return matchesList;
1830     }
1831 }