1 /*
   2  * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 package ir_framework.tests;
  25 
  26 import compiler.lib.ir_framework.*;
  27 import compiler.lib.ir_framework.driver.irmatching.IRViolationException;
  28 import jdk.test.lib.Asserts;
  29 import jdk.test.lib.Platform;
  30 import jdk.test.whitebox.WhiteBox;
  31 
  32 import java.io.ByteArrayOutputStream;
  33 import java.io.PrintStream;
  34 import java.util.*;
  35 import java.util.regex.Matcher;
  36 import java.util.regex.Pattern;
  37 
  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 -DPrintApplicableIRRules.
  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 -DPrintApplicableIRRules=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, "Constant"),
 259                  BadFailOnConstraint.create(CheckCastArray.class, "array(java.lang.Object[])", 2, 1,cmp, "Constant", "MyClass"),
 260                  BadFailOnConstraint.create(CheckCastArray.class, "array(java.lang.Object[])", 2, 2,cmp, "Constant", "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 line in Applicable IR Rules: \"" + builder +
 444                                                       System.lineSeparator()));
 445         }
 446     }
 447 }
 448 
 449 class AndOr1 {
 450     @Test
 451     @Arguments(values = Argument.DEFAULT)
 452     @IR(applyIfAnd = {"UsePerfData", "true", "TLABRefillWasteFraction", "50", "UseTLAB", "true"}, failOn = {IRNode.CALL})
 453     public void test1(int i) {
 454         dontInline();
 455     }
 456 
 457     @Test
 458     @IR(applyIfOr = {"UsePerfData", "false", "TLABRefillWasteFraction", "51", "UseTLAB", "false"}, failOn = {IRNode.CALL})
 459     public void test2() {
 460         dontInline();
 461     }
 462 
 463     @DontInline
 464     private void dontInline() {
 465     }
 466 }
 467 
 468 class MultipleFailOnGood {
 469     private int iFld;
 470     private MyClassSub myClassSub = new MyClassSub();
 471 
 472     @Test
 473     @IR(applyIf = {"TLABRefillWasteFraction", "50"}, failOn = {IRNode.STORE, IRNode.CALL})
 474     @IR(failOn = {IRNode.STORE, IRNode.CALL})
 475     @IR(applyIfOr = {"TLABRefillWasteFraction", "99", "TLABRefillWasteFraction", "100"}, failOn = {IRNode.LOOP, IRNode.CALL}) // Not applied
 476     public void good1() {
 477         forceInline();
 478     }
 479 
 480     @Test
 481     @IR(failOn = {IRNode.STORE, IRNode.CALL})
 482     @IR(applyIfNot = {"TLABRefillWasteFraction", "20"}, failOn = {IRNode.ALLOC})
 483     @IR(applyIfNot = {"TLABRefillWasteFraction", "< 100"}, failOn = {IRNode.ALLOC_OF, "Test"})
 484     public void good2() {
 485         forceInline();
 486     }
 487 
 488     @Test
 489     @IR(failOn = {IRNode.STORE_OF_CLASS, "Test", IRNode.CALL})
 490     @IR(applyIfNot = {"TLABRefillWasteFraction", "20"}, failOn = {IRNode.ALLOC})
 491     @IR(applyIfNot = {"TLABRefillWasteFraction", "< 100"}, failOn = {IRNode.ALLOC_OF, "Test"})
 492     public void good3() {
 493         forceInline();
 494     }
 495 
 496     @Test
 497     @IR(failOn = {IRNode.CALL, IRNode.STORE_OF_CLASS, "UnknownClass"})
 498     public void good4() {
 499         iFld = 42;
 500     }
 501 
 502     @Test
 503     @IR(failOn = {IRNode.STORE_OF_FIELD, "xFld", IRNode.CALL})
 504     public void good5() {
 505         iFld = 42;
 506     }
 507 
 508     @Test
 509     @IR(failOn = {IRNode.STORE_OF_CLASS, "MyClass"}) // Needs exact match to fail
 510     public void good6() {
 511         myClassSub.iFld = 42;
 512     }
 513 
 514     @Test
 515     @IR(failOn = {IRNode.STORE_OF_CLASS, "MyClassSub"}) // Static write is with Class and not MySubClass
 516     public void good7() {
 517         MyClassSub.iFldStatic = 42;
 518     }
 519 
 520     @ForceInline
 521     private void forceInline() {}
 522 }
 523 
 524 class MultipleFailOnBad {
 525     private int iFld;
 526     private int myInt;
 527     private MyClassEmpty myClass;
 528 
 529     @Test
 530     @IR(failOn = {IRNode.STORE, IRNode.CALL, IRNode.STORE_I, IRNode.LOOP})
 531     public void fail1() {
 532         iFld = 42;
 533     }
 534 
 535     @Test
 536     @IR(failOn = {IRNode.STORE, IRNode.CALL})
 537     public void fail2() {
 538         dontInline();
 539     }
 540 
 541     @Test
 542     @IR(failOn = {IRNode.CALL, IRNode.STORE_OF_CLASS, "MultipleFailOnBad", IRNode.ALLOC})
 543     public void fail3() {
 544         iFld = 42;
 545     }
 546 
 547     @Test
 548     @IR(failOn = {IRNode.STORE_OF_CLASS, "ir_framework/tests/MultipleFailOnBad", IRNode.CALL, IRNode.ALLOC})
 549     public void fail4() {
 550         iFld = 42;
 551     }
 552 
 553     @Test
 554     @IR(failOn = {IRNode.STORE_OF_FIELD, "iFld", IRNode.CALL, IRNode.ALLOC})
 555     public void fail5() {
 556         iFld = 42;
 557     }
 558 
 559     @Test
 560     @IR(failOn = {IRNode.STORE_OF_CLASS, "MyClassEmpty", IRNode.ALLOC, IRNode.CALL})
 561     public void fail6() {
 562         myClass = new MyClassEmpty();
 563     }
 564 
 565     @Test
 566     @IR(failOn = {IRNode.STORE_OF_CLASS, "UnknownClass", IRNode.ALLOC_OF, "MyClassEmpty"})
 567     public void fail7() {
 568         myClass = new MyClassEmpty();
 569     }
 570 
 571     @Test
 572     @IR(failOn = {IRNode.STORE_OF_CLASS, "UnknownClass", IRNode.ALLOC_OF, "ir_framework/tests/MyClassEmptySub"})
 573     public void fail8() {
 574         myClass = new MyClassEmptySub();
 575     }
 576 
 577     @Test
 578     @IR(failOn = {IRNode.STORE, IRNode.CALL})
 579     public void fail9() {
 580         iFld = 42;
 581         dontInline();
 582     }
 583 
 584     @Test
 585     @IR(failOn = {IRNode.STORE_OF_FIELD, "iFld", IRNode.CALL, IRNode.ALLOC})
 586     public void fail10() {
 587         myInt = 34;
 588         iFld = 42;
 589     }
 590 
 591     @DontInline
 592     private void dontInline() {}
 593 }
 594 
 595 // Called with -XX:TLABRefillWasteFraction=X.
 596 class FlagComparisons {
 597     // Applies all IR rules if TLABRefillWasteFraction=50
 598     @Test
 599     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "50"}) // Index 1
 600     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "=50"})
 601     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "= 50"})
 602     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " =   50"})
 603     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<=50"}) // Index 5
 604     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<= 50"})
 605     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " <=  50"})
 606     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">=50"}) // Index 8
 607     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">= 50"})
 608     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " >=  50"})
 609     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">49"})
 610     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "> 49"})
 611     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " >  49"})
 612     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<51"}) // Index 14
 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", " !=  51"})
 618     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "!=49"})
 619     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "!= 49"})
 620     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " !=  49"}) // Index 22
 621     public void testMatchAllIf50() {}
 622 
 623     // Applies no IR rules if TLABRefillWasteFraction=50
 624     @Test
 625     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "49"}) // Index 1
 626     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "=49"})
 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 5
 630     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "=51"})
 631     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "= 51"})
 632     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " =  51"})
 633     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<=49"}) // Index 9
 634     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<= 49"})
 635     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " <=  49"})
 636     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">=51"}) // Index 12
 637     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">= 51"})
 638     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " >=  51"})
 639     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">50"})
 640     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "> 50"})
 641     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " >  50"})
 642     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<50"}) // Index 18
 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"})
 647     @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " !=  50"}) // Index 23
 648     public void testMatchNoneIf50() {}
 649 }
 650 
 651 class CountComparisons {
 652     int iFld;
 653 
 654     @Test
 655     @IR(counts = {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, "  <=  1",
 667                   IRNode.STORE, "> 0",
 668                   IRNode.STORE, ">0",
 669                   IRNode.STORE, " > 0",
 670                   IRNode.STORE, "  >  0",
 671                   IRNode.STORE, "< 2",
 672                   IRNode.STORE, "<2",
 673                   IRNode.STORE, " < 2",
 674                   IRNode.STORE, "  <  2",
 675     })
 676     public void countComparison() {
 677         iFld = 3;
 678     }
 679 }
 680 
 681 class GoodCount {
 682     boolean flag;
 683     char cFld;
 684     byte bFld;
 685     short sFld;
 686     int iFld;
 687     long lFld;
 688     float fFld;
 689     double dFld;
 690     long x;
 691 
 692     long result;
 693     MyClass myClass = new MyClass();
 694     MyClassEmpty myClassEmpty = new MyClassEmpty();
 695     MyClass myClassSubPoly = new MyClassSub();
 696     MyClassSub myClassSub = new MyClassSub();
 697 
 698     @Test
 699     @IR(counts = {IRNode.STORE, "1", IRNode.STORE_I, "1"},
 700         failOn = {IRNode.STORE_B, IRNode.STORE_C, IRNode.STORE_D,
 701                   IRNode.STORE_F, IRNode.STORE_L})
 702     public void good1() {
 703         iFld = 3;
 704     }
 705 
 706     @Test
 707     @IR(counts = {IRNode.STORE, "8",
 708                   IRNode.STORE_B, "2", // bFld + flag
 709                   IRNode.STORE_C, "2", // cFld + sFld
 710                   IRNode.STORE_I, "1",
 711                   IRNode.STORE_L, "1",
 712                   IRNode.STORE_F, "1",
 713                   IRNode.STORE_D, "1"})
 714     public void good2() {
 715         flag = true;
 716         cFld = 'a';
 717         bFld = 1;
 718         sFld = 2;
 719         iFld = 3;
 720         lFld = 4L;
 721         fFld = 5.0f;
 722         dFld = 6.0;
 723     }
 724 
 725     @Test
 726     @IR(counts = {IRNode.STORE, "8", IRNode.STORE_OF_CLASS, "GoodCount", "8",
 727                   IRNode.STORE_B, "2", IRNode.STORE_B_OF_CLASS, "GoodCount", "2",
 728                   IRNode.STORE_C, "2", IRNode.STORE_C_OF_CLASS, "GoodCount", "2",
 729                   IRNode.STORE_I, "1", IRNode.STORE_I_OF_CLASS, "GoodCount", "1",
 730                   IRNode.STORE_L, "1", IRNode.STORE_L_OF_CLASS, "GoodCount", "1",
 731                   IRNode.STORE_F, "1", IRNode.STORE_F_OF_CLASS, "GoodCount", "1",
 732                   IRNode.STORE_D, "1", IRNode.STORE_D_OF_CLASS, "GoodCount", "1"})
 733     public void good3() {
 734         flag = true;
 735         cFld = 'a';
 736         bFld = 1;
 737         sFld = 2;
 738         iFld = 3;
 739         lFld = 4L;
 740         fFld = 5.0f;
 741         dFld = 6.0;
 742     }
 743 
 744     @Test
 745     @IR(counts = {IRNode.STORE, "8", IRNode.STORE_OF_CLASS, "GoodCount", "8",
 746                   IRNode.STORE_B, "2", IRNode.STORE_B_OF_CLASS, "GoodCount", "2",
 747                   IRNode.STORE_C, "2", IRNode.STORE_C_OF_CLASS, "GoodCount", "2",
 748                   IRNode.STORE_I, "1", IRNode.STORE_I_OF_CLASS, "GoodCount", "1",
 749                   IRNode.STORE_L, "1", IRNode.STORE_L_OF_CLASS, "GoodCount", "1",
 750                   IRNode.STORE_F, "1", IRNode.STORE_F_OF_CLASS, "GoodCount", "1",
 751                   IRNode.STORE_D, "1", IRNode.STORE_D_OF_CLASS, "GoodCount", "1",
 752                   IRNode.STORE_OF_FIELD, "lFld", "1"})
 753     public void good4() {
 754         flag = true;
 755         cFld = 'a';
 756         bFld = 1;
 757         sFld = 2;
 758         iFld = 3;
 759         lFld = 4L;
 760         fFld = 5.0f;
 761         dFld = 6.0;
 762     }
 763 
 764     @Test
 765     @IR(counts = {IRNode.STORE, "2", IRNode.STORE_I, "1", IRNode.STORE_L, "1",
 766                   IRNode.STORE_OF_CLASS, "GoodCount", "1", IRNode.STORE_L_OF_CLASS, "GoodCount", "1",
 767                   IRNode.STORE_OF_CLASS, "ir_framework/tests/MyClass", "1",
 768                   IRNode.STORE_I_OF_CLASS, "ir_framework/tests/MyClass", "1",
 769                   IRNode.STORE_OF_CLASS, "ir_framework/tests/GoodCount", "1",
 770                   IRNode.STORE_L_OF_CLASS, "ir_framework/tests/GoodCount", "1",
 771                   IRNode.STORE_OF_FIELD, "x", "2"})
 772     public void good5() {
 773         x = 3; // long
 774         myClass.x = 4; // int
 775     }
 776 
 777     @Test
 778     @IR(counts = {
 779             IRNode.STORE_OF_FIELD, "myClassEmpty", "1",
 780             IRNode.STORE_OF_CLASS, "oodCount", "0",
 781             IRNode.STORE_OF_CLASS, "GoodCount", "1",
 782             IRNode.STORE_OF_CLASS, "/GoodCount", "1",
 783             IRNode.STORE_OF_CLASS, "tests/GoodCount", "1",
 784             IRNode.STORE_OF_CLASS, "/tests/GoodCount", "1",
 785             IRNode.STORE_OF_CLASS, "ir_framework/tests/GoodCount", "1",
 786             IRNode.STORE_OF_CLASS, "/ir_framework/tests/GoodCount", "0",
 787             IRNode.STORE_OF_CLASS, "MyClassEmpty", "0"
 788         },
 789         failOn = {IRNode.STORE_OF_CLASS, "MyClassEmpty"})
 790     public void good6() {
 791         myClassEmpty = new MyClassEmpty();
 792     }
 793 
 794     @Test
 795     @IR(counts = {IRNode.STORE_OF_FIELD, "iFld", "3", IRNode.STORE_OF_CLASS, "GoodCount", "0",
 796                   IRNode.STORE_OF_CLASS, "MyClass", "2", IRNode.STORE_OF_CLASS, "MyClassSub", "1",
 797                   IRNode.STORE, "3"},
 798         failOn = {IRNode.STORE_OF_CLASS, "GoodCount"})
 799     public void good7() {
 800         myClass.iFld = 1;
 801         myClassSubPoly.iFld = 2;
 802         myClassSub.iFld = 3;
 803     }
 804 
 805     @Test
 806     @IR(counts = {IRNode.LOAD, "1", IRNode.STORE, "1"})
 807     public void good8() {
 808         result = iFld;
 809     }
 810 
 811 
 812     @Test
 813     @IR(counts = {IRNode.LOAD, "4", IRNode.STORE, "1", IRNode.LOAD_OF_FIELD, "iFld", "2", IRNode.LOAD_OF_FIELD, "iFld2", "0",
 814                   IRNode.LOAD_OF_FIELD, "lFldStatic", "1", IRNode.LOAD_OF_CLASS, "GoodCount", "2", IRNode.LOAD_OF_CLASS, "MyClass", "1",
 815                   IRNode.STORE_OF_CLASS, "GoodCount", "1", IRNode.STORE_OF_FIELD, "result", "1",
 816                   IRNode.LOAD_OF_FIELD, "myClass", "1"})
 817     public void good9() {
 818         result = iFld + MyClass.lFldStatic + myClass.iFld; // 1 + 1 + 2 loads (myClass is LoadN of GoodCount and myClass.iFld a LoadI of MyClass)
 819     }
 820 
 821     @Test
 822     @IR(counts = {IRNode.LOAD, "8",
 823                   IRNode.LOAD_B, "1",
 824                   IRNode.LOAD_UB, "1",
 825                   IRNode.LOAD_S, "1",
 826                   IRNode.LOAD_US, "1",
 827                   IRNode.LOAD_I, "1",
 828                   IRNode.LOAD_L, "1",
 829                   IRNode.LOAD_F, "1",
 830                   IRNode.LOAD_D, "1"})
 831     public void good10() {
 832         bFld++;
 833         cFld++;
 834         sFld++;
 835         iFld++;
 836         lFld++;
 837         fFld++;
 838         dFld++;
 839         flag = !flag;
 840     }
 841 
 842     @Test
 843     @IR(counts = {IRNode.LOAD, "8", IRNode.LOAD_OF_CLASS, "GoodCount", "8",
 844                   IRNode.LOAD_B, "1", IRNode.LOAD_B_OF_CLASS, "GoodCount", "1",
 845                   IRNode.LOAD_UB, "1", IRNode.LOAD_UB_OF_CLASS, "GoodCount", "1",
 846                   IRNode.LOAD_S, "1", IRNode.LOAD_S_OF_CLASS, "GoodCount", "1",
 847                   IRNode.LOAD_US, "1", IRNode.LOAD_US_OF_CLASS, "GoodCount", "1",
 848                   IRNode.LOAD_I, "1", IRNode.LOAD_I_OF_CLASS, "GoodCount", "1",
 849                   IRNode.LOAD_L, "1", IRNode.LOAD_L_OF_CLASS, "GoodCount", "1",
 850                   IRNode.LOAD_F, "1", IRNode.LOAD_F_OF_CLASS, "GoodCount", "1",
 851                   IRNode.LOAD_D, "1", IRNode.LOAD_D_OF_CLASS, "GoodCount", "1"})
 852     public void good11() {
 853         bFld++;
 854         cFld++;
 855         sFld++;
 856         iFld++;
 857         lFld++;
 858         fFld++;
 859         dFld++;
 860         flag = !flag;
 861     }
 862 }
 863 
 864 class BadCount {
 865     int iFld;
 866     int iFld2;
 867     int result;
 868     int result2;
 869     @Test
 870     @IR(counts = {IRNode.LOAD, "> 1000"}) // fail
 871     @IR(counts = {IRNode.STORE, "> 0"})
 872     public void bad1() {
 873         result = iFld;
 874         result2 = iFld2;
 875     }
 876 
 877     @Test
 878     @IR(counts = {IRNode.LOAD, "2"}) // fail
 879     @IR(counts = {IRNode.STORE, "< 2"})
 880     public void bad2() {
 881         result = iFld;
 882         result2 = iFld2;
 883     }
 884 
 885 
 886     @Test
 887     @IR(counts = {IRNode.LOAD, "0"}) // fail
 888     @IR(counts = {IRNode.STORE, " <= 1"}) // fail
 889     public void bad3() {
 890         result = iFld;
 891         result2 = iFld2;
 892     }
 893 }
 894 
 895 
 896 class RunTests {
 897     public int iFld;
 898 
 899     @Test
 900     @IR(counts = {IRNode.STORE, "1"})
 901     @IR(failOn = IRNode.LOAD)
 902     public void good1() {
 903         iFld = 42;
 904     }
 905 
 906     @Test
 907     @IR(counts = {IRNode.LOAD, "1"})
 908     @IR(failOn = IRNode.STORE)
 909     public int good2() {
 910         return iFld;
 911     }
 912 
 913     @Run(test = {"good1", "good2"})
 914     public void runGood1() {
 915         good1();
 916         good2();
 917     }
 918 
 919 
 920     @Test
 921     @IR(counts = {IRNode.STORE, "1"})
 922     @IR(failOn = IRNode.LOAD)
 923     public void good3(int x) {
 924         iFld = x;
 925     }
 926 
 927     @Test
 928     @IR(counts = {IRNode.STORE, "1"})
 929     @IR(failOn = IRNode.LOAD)
 930     public int bad1(int x) {
 931         return iFld + x;
 932     }
 933 
 934     @Run(test = {"bad1", "good3"})
 935     public void run() {
 936         bad1(2);
 937         good3(4);
 938     }
 939 }
 940 
 941 class Calls {
 942 
 943     @Test
 944     @IR(counts = {IRNode.CALL, "1"})
 945     @IR(failOn = {IRNode.CALL_OF_METHOD, "dontInline",  // Fails
 946                   IRNode.STATIC_CALL_OF_METHOD, "dontInline"}) // Fails
 947     @IR(failOn = {IRNode.CALL_OF_METHOD, "forceInline",
 948                   IRNode.STATIC_CALL_OF_METHOD, "forceInline",
 949                   IRNode.CALL_OF_METHOD, "dontInlines",
 950                   IRNode.STATIC_CALL_OF_METHOD, "dontInlines",
 951                   IRNode.CALL_OF_METHOD, "dont",
 952                   IRNode.STATIC_CALL_OF_METHOD, "dont"})
 953     public void calls() {
 954         dontInline();
 955         forceInline();
 956     }
 957 
 958     @DontInline
 959     public void dontInline() {}
 960 
 961     @ForceInline
 962     public void forceInline() {}
 963 }
 964 
 965 class AllocInstance {
 966     MyClass myClass;
 967 
 968     @Test
 969     @IR(failOn = {IRNode.ALLOC})
 970     @IR(failOn = {IRNode.ALLOC_OF, "MyClass"})
 971     @IR(failOn = {IRNode.ALLOC_OF, "Class"}) // Does not fail
 972     @IR(failOn = {IRNode.ALLOC_OF, "MyClasss"}) // Does not fail
 973     @IR(failOn = {IRNode.ALLOC_OF, "ir_framework/tests/MySubClass"}) // Does not fail
 974     @IR(failOn = {IRNode.ALLOC_OF, "ir_framework/tests/MyClass"})
 975     @IR(failOn = {IRNode.ALLOC_OF, "tests/MyClass"})
 976     @IR(failOn = {IRNode.ALLOC_OF, "ests/MyClass"}) // Does not fail
 977     @IR(failOn = {IRNode.ALLOC_OF, "Atests/MyClass"}) // Does not fail
 978     @IR(failOn = {IRNode.ALLOC_OF, "tests"}) // Does not fail
 979     public void allocInstance() {
 980         myClass = new MyClass();
 981     }
 982 
 983     static class Nested {}
 984     @Test
 985     @IR(failOn = {IRNode.ALLOC_OF, "Nested"})
 986     @IR(failOn = {IRNode.ALLOC_OF, "AllocInstance\\$Nested"})
 987     @IR(failOn = {IRNode.ALLOC_OF, "AllocInst\\w+\\$Nested"})
 988     public Nested allocNested() { return new Nested(); }
 989 }
 990 
 991 class AllocArray {
 992     MyClass[] myClassArray;
 993     MyClass[][] myClassMultiArray;
 994 
 995     @Test
 996     @IR(failOn = {IRNode.ALLOC_ARRAY})
 997     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "MyClass"})
 998     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "Class"}) // Does not fail
 999     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "MyClasss"}) // Does not fail
1000     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "ir_framework/tests/MySubClass"}) // Does not fail
1001     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "ir_framework/tests/MyClass"})
1002     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "tests/MyClass"})
1003     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "ests/MyClass"}) // Does not fail
1004     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "Atests/MyClass"}) // Does not fail
1005     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "tests"}) // Does not fail
1006     public void allocArray() {
1007         myClassArray = new MyClass[2];
1008     }
1009 
1010     @Test
1011     @IR(failOn = {IRNode.ALLOC_ARRAY})
1012     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "MyClass"})
1013     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "Class"}) // Does not fail
1014     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "MyClasss"}) // Does not fail
1015     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "ir_framework/tests/MySubClass"}) // Does not fail
1016     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "ir_framework/tests/MyClass"})
1017     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "tests/MyClass"})
1018     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "ests/MyClass"}) // Does not fail
1019     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "Atests/MyClass"}) // Does not fail
1020     @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "tests"}) // Does not fail
1021     public void allocMultiArray() {
1022         myClassMultiArray = new MyClass[2][3];
1023     }
1024 }
1025 
1026 class Loads {
1027     int iFld = 34;
1028     int result = 0;
1029     Object myClass = new MyClass();
1030 
1031     @Test
1032     @IR(failOn = {IRNode.LOAD, IRNode.LOOP, IRNode.LOAD_I}, counts = {IRNode.LOOP, "2", IRNode.LOAD, "2", IRNode.STORE, "2"})
1033     @IR(failOn = {IRNode.LOOP, IRNode.LOOP}, counts = {IRNode.LOOP, "0", IRNode.LOAD, "1"}) // Does not fail
1034     @IR(failOn = {IRNode.LOOP, IRNode.LOOP}, counts = {IRNode.LOOP, "0", IRNode.STORE, "1"})
1035     @IR(failOn = {IRNode.LOOP, IRNode.STORE}, counts = {IRNode.LOOP, "0", IRNode.LOAD, "1"})
1036     @IR(failOn = {IRNode.LOAD_OF_CLASS, "ir_framework/tests/Loads"})
1037     @IR(failOn = {IRNode.LOAD_OF_CLASS, "Loads"})
1038     @IR(failOn = {IRNode.LOAD_OF_FIELD, "iFld"})
1039     @IR(failOn = {IRNode.LOAD_OF_FIELD, "iFld2", IRNode.LOAD_OF_CLASS, "Load"}) // Does not fail
1040     @IR(failOn = {IRNode.LOAD_KLASS}) // Does not fail
1041     @IR(counts = {IRNode.FIELD_ACCESS, "3"}) // Does not fail
1042     public void load() {
1043         result = iFld;
1044         iFld = 3;
1045     }
1046 
1047     @Test
1048     @IR(failOn = {IRNode.LOAD_KLASS})
1049     @IR(counts = {IRNode.FIELD_ACCESS, "3"})
1050     public void loadKlass() {
1051         if (myClass instanceof MyClass) {
1052             result = 3;
1053         }
1054     }
1055 }
1056 
1057 class Loops {
1058     int limit = 1024;
1059     int[] iArr = new int[100];
1060 
1061     @DontInline
1062     public void dontInline() {}
1063 
1064     @Test
1065     @IR(failOn = IRNode.LOOP) // fails
1066     @IR(failOn = IRNode.COUNTED_LOOP)
1067     @IR(failOn = IRNode.COUNTED_LOOP_MAIN)
1068     public void loop() {
1069         for (int i = 0; i < limit; i++) {
1070             dontInline();
1071         }
1072     }
1073 
1074     @Test
1075     @IR(failOn = IRNode.LOOP)
1076     @IR(failOn = IRNode.COUNTED_LOOP) // fails
1077     @IR(failOn = IRNode.COUNTED_LOOP_MAIN)
1078     public void countedLoop() {
1079         for (int i = 0; i < 2000; i++) {
1080             dontInline();
1081         }
1082     }
1083 
1084     @Test
1085     @IR(failOn = IRNode.LOOP) // fails
1086     @IR(failOn = IRNode.COUNTED_LOOP) // fails
1087     @IR(failOn = IRNode.COUNTED_LOOP_MAIN)
1088     public void loopAndCountedLoop() {
1089         for (int i = 0; i < 2000; i++) {
1090             for (int j = 0; j < limit; j++) {
1091                 dontInline();
1092             }
1093         }
1094     }
1095 
1096     @Test
1097     @IR(failOn = IRNode.LOOP)
1098     @IR(failOn = IRNode.COUNTED_LOOP) // fails
1099     @IR(failOn = IRNode.COUNTED_LOOP_MAIN) // fails
1100     public void countedLoopMain() {
1101         // Cannot unroll completely -> create pre/main/post
1102         for (int i = 0; i < 100; i++) {
1103             iArr[i] = i;
1104         }
1105     }
1106 
1107     @Test
1108     @IR(failOn = IRNode.LOOP)
1109     @IR(failOn = IRNode.COUNTED_LOOP)
1110     @IR(failOn = IRNode.COUNTED_LOOP_MAIN)
1111     public void countedLoopUnrolled() {
1112         // Completely unrolled -> no pre/main/post
1113         for (int i = 0; i < 8; i++) {
1114             iArr[i] = i;
1115         }
1116     }
1117 }
1118 
1119 class Traps {
1120     int number42 = 42;
1121     int iFld = 10;
1122     int[] iArr = new int[2];
1123     MyClass myClass = new MyClass();
1124     MyClassSub myClassSub = new MyClassSub();
1125     NotLoaded notLoaded = new NotLoaded();
1126     Object[] oArr = new Object[10];
1127     MyClass[] mArr = new MyClass[10];
1128 
1129     @Test
1130     @IR(failOn = IRNode.TRAP)
1131     @IR(failOn = {IRNode.STORE_OF_FIELD, "iFld"}) // fails
1132     @IR(failOn = {IRNode.PREDICATE_TRAP,
1133                   IRNode.UNSTABLE_IF_TRAP,
1134                   IRNode.NULL_CHECK_TRAP,
1135                   IRNode.NULL_ASSERT_TRAP,
1136                   IRNode.RANGE_CHECK_TRAP,
1137                   IRNode.CLASS_CHECK_TRAP,
1138                   IRNode.INTRINSIC_TRAP,
1139                   IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
1140                   IRNode.UNHANDLED_TRAP})
1141     public void noTraps() {
1142         for (int i = 0; i < 100; i++) {
1143             if (i < 42) {
1144                 // Reached, no uncommon trap
1145                 iFld = i;
1146             }
1147         }
1148     }
1149 
1150     @Test
1151     @IR(failOn = IRNode.TRAP) // fails
1152     @IR(failOn = IRNode.PREDICATE_TRAP) // fails
1153     @IR(failOn = {IRNode.STORE_OF_FIELD, "iFld"})
1154     @IR(failOn = {IRNode.UNSTABLE_IF_TRAP,
1155                   IRNode.NULL_CHECK_TRAP,
1156                   IRNode.NULL_ASSERT_TRAP,
1157                   IRNode.RANGE_CHECK_TRAP,
1158                   IRNode.CLASS_CHECK_TRAP,
1159                   IRNode.INTRINSIC_TRAP,
1160                   IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
1161                   IRNode.UNHANDLED_TRAP})
1162     public void predicateTrap() {
1163         for (int i = 0; i < 100; i++) {
1164             if (number42 != 42) {
1165                 // Never reached
1166                 iFld = i;
1167             }
1168         }
1169     }
1170 
1171     @Test
1172     @IR(failOn = IRNode.TRAP) // fails
1173     @IR(failOn = IRNode.NULL_CHECK_TRAP) // fails
1174     @IR(failOn = IRNode.CLASS_CHECK_TRAP) // fails
1175     @IR(failOn = {IRNode.PREDICATE_TRAP,
1176                   IRNode.NULL_ASSERT_TRAP,
1177                   IRNode.RANGE_CHECK_TRAP,
1178                   IRNode.UNSTABLE_IF_TRAP,
1179                   IRNode.INTRINSIC_TRAP,
1180                   IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
1181                   IRNode.UNHANDLED_TRAP})
1182     public void nullCheck() {
1183         if (myClass instanceof MyClassSub) {
1184             iFld = 4;
1185         }
1186     }
1187 
1188     @Test
1189     @IR(failOn = IRNode.TRAP) // fails
1190     @IR(failOn = IRNode.NULL_ASSERT_TRAP) // fails
1191     @IR(failOn = IRNode.NULL_CHECK_TRAP) // fails
1192     @IR(failOn = {IRNode.PREDICATE_TRAP,
1193                   IRNode.UNSTABLE_IF_TRAP,
1194                   IRNode.RANGE_CHECK_TRAP,
1195                   IRNode.CLASS_CHECK_TRAP,
1196                   IRNode.INTRINSIC_TRAP,
1197                   IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
1198                   IRNode.UNHANDLED_TRAP})
1199     public Object nullAssert() {
1200         return notLoaded.notLoadedFld;
1201     }
1202 
1203     @Test
1204     @Arguments(values = Argument.TRUE)
1205     @IR(failOn = IRNode.TRAP) // fails
1206     @IR(failOn = IRNode.UNSTABLE_IF_TRAP) // fails
1207     @IR(failOn = {IRNode.PREDICATE_TRAP,
1208                   IRNode.NULL_CHECK_TRAP,
1209                   IRNode.NULL_ASSERT_TRAP,
1210                   IRNode.RANGE_CHECK_TRAP,
1211                   IRNode.CLASS_CHECK_TRAP,
1212                   IRNode.INTRINSIC_TRAP,
1213                   IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
1214                   IRNode.UNHANDLED_TRAP})
1215     public void unstableIf(boolean flag) {
1216         if (flag) {
1217             iFld++;
1218         } else {
1219             iFld--;
1220         }
1221     }
1222 
1223     @Test
1224     @IR(failOn = IRNode.TRAP) // fails
1225     @IR(failOn = IRNode.CLASS_CHECK_TRAP) // fails
1226     @IR(failOn = IRNode.NULL_CHECK_TRAP) // fails
1227     @IR(failOn = {IRNode.PREDICATE_TRAP,
1228                   IRNode.UNSTABLE_IF_TRAP,
1229                   IRNode.NULL_ASSERT_TRAP,
1230                   IRNode.RANGE_CHECK_TRAP,
1231                   IRNode.INTRINSIC_TRAP,
1232                   IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
1233                   IRNode.UNHANDLED_TRAP})
1234     public void classCheck() {
1235         try {
1236             myClassSub = (MyClassSub) myClass;
1237         } catch (ClassCastException e) {
1238             // Expected
1239         }
1240     }
1241 
1242     @Test
1243     @IR(failOn = IRNode.TRAP) // fails
1244     @IR(failOn = IRNode.RANGE_CHECK_TRAP) // fails
1245     @IR(failOn = IRNode.NULL_CHECK_TRAP) // fails
1246     @IR(failOn = {IRNode.PREDICATE_TRAP,
1247                   IRNode.UNSTABLE_IF_TRAP,
1248                   IRNode.NULL_ASSERT_TRAP,
1249                   IRNode.CLASS_CHECK_TRAP,
1250                   IRNode.INTRINSIC_TRAP,
1251                   IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
1252                   IRNode.UNHANDLED_TRAP})
1253     public void rangeCheck() {
1254         iArr[1] = 3;
1255     }
1256 
1257 
1258     @Test
1259     @IR(failOn = IRNode.TRAP) // fails
1260     @IR(failOn = IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP) // fails
1261     @IR(failOn = IRNode.INTRINSIC_TRAP) // fails
1262     @IR(failOn = IRNode.NULL_CHECK_TRAP) // fails
1263     @IR(failOn = {IRNode.PREDICATE_TRAP,
1264                   IRNode.UNSTABLE_IF_TRAP,
1265                   IRNode.NULL_ASSERT_TRAP,
1266                   IRNode.CLASS_CHECK_TRAP,
1267                   IRNode.RANGE_CHECK_TRAP,
1268                   IRNode.UNHANDLED_TRAP})
1269     public void instrinsicOrTypeCheckedInlining() {
1270         System.arraycopy(oArr, 0, mArr, 0, 8);
1271     }
1272 }
1273 
1274 class UnhandledTrap {
1275     int iFld = 34;
1276 
1277     @Test
1278     @IR(failOn = IRNode.TRAP) // fails
1279     @IR(failOn = IRNode.UNHANDLED_TRAP) // fails
1280     @IR(failOn = {IRNode.PREDICATE_TRAP,
1281                   IRNode.UNSTABLE_IF_TRAP,
1282                   IRNode.NULL_CHECK_TRAP,
1283                   IRNode.NULL_ASSERT_TRAP,
1284                   IRNode.RANGE_CHECK_TRAP,
1285                   IRNode.CLASS_CHECK_TRAP})
1286     public void unhandled() {
1287         try {
1288             throw new RuntimeException();
1289         } catch (RuntimeException e) {
1290             // Expected
1291         }
1292     }
1293 }
1294 
1295 class ScopeObj {
1296 
1297     @DontInline
1298     public void dontInline(int i) {}
1299 
1300     @Test
1301     @IR(failOn = IRNode.SCOPE_OBJECT) // fails
1302     public int scopeObject() {
1303         MyClass myClass = new MyClass();
1304         for (int i = 0; i < 100; i++) {
1305             dontInline(myClass.iFld);
1306         }
1307         return 3;
1308     }
1309 }
1310 
1311 class Membar {
1312     volatile MyClass myClass;
1313 
1314     @Test
1315     @IR(failOn = IRNode.MEMBAR) // fails
1316     public int membar() {
1317         myClass = new MyClass();
1318         return myClass.x;
1319     }
1320 }
1321 
1322 class CheckCastArray {
1323     Object[] oArr = new Object[10];
1324     MyClass[] mArr = new MyClass[10];
1325 
1326     @Test
1327     @IR(failOn = IRNode.CHECKCAST_ARRAY) // fails
1328     @IR(failOn = {IRNode.CHECKCAST_ARRAY_OF, "MyClass", // fails
1329                   IRNode.CHECKCAST_ARRAY_OF, "ir_framework/tests/MyClass"}) // fails
1330     @IR(failOn = {IRNode.CHECKCAST_ARRAY_OF, "MyClasss", IRNode.CHECKCAST_ARRAY_OF, "Object"})
1331     public boolean array(Object[] arr) {
1332         return arr instanceof MyClass[];
1333     }
1334 
1335     @Run(test = "array")
1336     public void testArray() {
1337         array(oArr);
1338         array(mArr);
1339     }
1340 
1341     @Test
1342     @IR(failOn = IRNode.CHECKCAST_ARRAYCOPY) // fails
1343     public Object[] arrayCopy(Object[] src, Class klass) {
1344         return Arrays.copyOf(src, 8, klass);
1345     }
1346 
1347     @Run(test = "arrayCopy")
1348     public void testArrayCopy() {
1349         arrayCopy(mArr, MyClass[].class);
1350         arrayCopy(mArr, Object[].class);
1351         arrayCopy(mArr, MyClassEmpty[].class);
1352     }
1353 }
1354 
1355 class CompilationOutputOfFails {
1356     private Object obj;
1357 
1358     @Test
1359     @IR(failOn = IRNode.COUNTED_LOOP)
1360     @IR(failOn = {"call"},
1361         phase = CompilePhase.PRINT_OPTO_ASSEMBLY)
1362     public void both1() {
1363         for (int i = 0; i < 100; i++) {
1364             dontInline();
1365         }
1366     }
1367 
1368     @Test
1369     @IR(failOn = "CountedLoop|call",
1370         phase = {CompilePhase.PRINT_IDEAL, CompilePhase.PRINT_OPTO_ASSEMBLY})
1371     public void both2() {
1372         for (int i = 0; i < 100; i++) {
1373             dontInline();
1374         }
1375     }
1376 
1377     @Test
1378     @IR(failOn = IRNode.COUNTED_LOOP)
1379     @IR(failOn = "call", phase = CompilePhase.PRINT_OPTO_ASSEMBLY)
1380     public void both3() {
1381         for (int i = 0; i < 100; i++) {
1382             dontInline();
1383         }
1384     }
1385 
1386     @Test
1387     @IR(counts = {IRNode.COUNTED_LOOP, "0"})
1388     @IR(counts = {"call", "0"},
1389         phase = {CompilePhase.PRINT_OPTO_ASSEMBLY})
1390     public void both4() {
1391         for (int i = 0; i < 100; i++) {
1392             dontInline();
1393         }
1394     }
1395 
1396     @Test
1397     @IR(counts = {"CountedLoop|call", "10"},
1398         phase = {CompilePhase.PRINT_IDEAL, CompilePhase.PRINT_OPTO_ASSEMBLY})
1399     public void both5() {
1400         for (int i = 0; i < 100; i++) {
1401             dontInline();
1402         }
1403     }
1404 
1405     @Test
1406     @IR(counts = {IRNode.COUNTED_LOOP, "0"})
1407     @IR(counts = {"call", "0"}, phase = CompilePhase.PRINT_OPTO_ASSEMBLY)
1408     public void both6() {
1409         for (int i = 0; i < 100; i++) {
1410             dontInline();
1411         }
1412     }
1413 
1414     @Test
1415     @IR(failOn = IRNode.COUNTED_LOOP)
1416     @IR(counts = {"call", "0"}, phase = CompilePhase.PRINT_OPTO_ASSEMBLY)
1417     public void both7() {
1418         for (int i = 0; i < 100; i++) {
1419             dontInline();
1420         }
1421     }
1422 
1423     @Test
1424     @IR(failOn = IRNode.COUNTED_LOOP)
1425     public void ideal1() {
1426         for (int i = 0; i < 100; i++) {
1427             dontInline();
1428         }
1429     }
1430 
1431     @Test
1432     @IR(failOn = IRNode.COUNTED_LOOP)
1433     @IR(failOn = IRNode.ALLOC) // not fail
1434     public void ideal2() {
1435         for (int i = 0; i < 100; i++) {
1436             dontInline();
1437         }
1438     }
1439 
1440     @Test
1441     @IR(failOn = IRNode.COUNTED_LOOP)
1442     @IR(counts = {IRNode.ALLOC, "0"}) // not fail
1443     public void ideal3() {
1444         for (int i = 0; i < 100; i++) {
1445             dontInline();
1446         }
1447     }
1448 
1449     @Test
1450     @IR(counts = {IRNode.COUNTED_LOOP, "2"})
1451     public void ideal4() {
1452         for (int i = 0; i < 100; i++) {
1453             dontInline();
1454         }
1455     }
1456 
1457     @Test
1458     @IR(failOn = IRNode.ALLOC) // not fail
1459     @IR(counts = {IRNode.COUNTED_LOOP, "2"})
1460     public void ideal5() {
1461         for (int i = 0; i < 100; i++) {
1462             dontInline();
1463         }
1464     }
1465 
1466     @Test
1467     @IR(counts = {IRNode.ALLOC, "0"}) // not fail
1468     @IR(counts = {IRNode.COUNTED_LOOP, "2"})
1469     public void ideal6() {
1470         for (int i = 0; i < 100; i++) {
1471             dontInline();
1472         }
1473     }
1474 
1475     @Test
1476     @IR(counts = {IRNode.COUNTED_LOOP, "5"})
1477     @IR(counts = {IRNode.COUNTED_LOOP, "2"})
1478     public void ideal7() {
1479         for (int i = 0; i < 100; i++) {
1480             dontInline();
1481         }
1482     }
1483 
1484     @Test
1485     @IR(failOn = IRNode.ALLOC)
1486     public void macro1() {
1487         obj = new Object();
1488     }
1489 
1490     @Test
1491     @IR(failOn = IRNode.ALLOC)
1492     @IR(failOn = IRNode.STORE_F) // not fail
1493     public void macro2() {
1494         obj = new Object();
1495     }
1496 
1497     @Test
1498     @IR(failOn = IRNode.ALLOC)
1499     @IR(counts = {IRNode.COUNTED_LOOP, ">1"}) // not fail
1500     public void macro3() {
1501         for (int i = 0; i < 100; i++) {
1502             obj = new Object();
1503         }
1504     }
1505 
1506     @Test
1507     @IR(counts = {IRNode.ALLOC, "0"})
1508     public void macro4() {
1509         obj = new Object();
1510     }
1511 
1512     @Test
1513     @IR(failOn = IRNode.STORE_F) // not fail
1514     @IR(counts = {IRNode.ALLOC, "0"})
1515     public void macro5() {
1516         obj = new Object();
1517     }
1518 
1519     @Test
1520     @IR(counts = {IRNode.STORE_F, "0"}) // not fail
1521     @IR(counts = {IRNode.ALLOC, "0"})
1522     public void macro6() {
1523         obj = new Object();
1524     }
1525 
1526     @Test
1527     @IR(counts = {IRNode.ALLOC, "10"})
1528     @IR(counts = {IRNode.ALLOC, "0"})
1529     public void macro7() {
1530         obj = new Object();
1531     }
1532 
1533     @DontInline
1534     private void dontInline() {}
1535 }
1536 
1537 
1538 // Used only by class Traps
1539 class NotLoaded {
1540     NotLoadedHelper notLoadedFld;
1541 }
1542 
1543 // Used only by class Traps
1544 class NotLoadedHelper {}
1545 
1546 class MyClass {
1547     int iFld = 3;
1548     int x = 5;
1549     static long lFldStatic;
1550 }
1551 
1552 class MyClassEmpty {}
1553 
1554 class MyClassEmptySub extends MyClassEmpty {}
1555 
1556 class MyClassSub extends MyClass {
1557     int iFld;
1558     static int iFldStatic;
1559 }
1560 
1561 
1562 // Base class for any kind of constraint that is used to verify if the framework reports the correct IR failures.
1563 abstract class Constraint {
1564     private final Class<?> klass;
1565     protected final int ruleIdx;
1566     private final Pattern methodPattern;
1567     private final String classAndMethod;
1568     protected final Pattern irPattern;
1569     private final String methodName;
1570     protected boolean matched;
1571 
1572     Constraint(Class<?> klass, String methodName, int ruleIdx, Pattern irPattern) {
1573         this.klass = klass;
1574         classAndMethod = klass.getSimpleName() + "." + methodName;
1575         this.ruleIdx = ruleIdx;
1576         this.methodPattern = Pattern.compile(Pattern.quote(classAndMethod));
1577         this.irPattern = irPattern;
1578         this.methodName = methodName;
1579         this.matched = false;
1580     }
1581 
1582     // For good constraints only
1583     Constraint(Class<?> klass, String methodName, int ruleIdx) {
1584         this.klass = klass;
1585         classAndMethod = klass.getSimpleName() + "." + methodName;
1586         this.ruleIdx = ruleIdx;
1587         this.methodPattern = Pattern.compile(Pattern.quote(classAndMethod));
1588         this.irPattern = null;
1589         this.methodName = methodName;
1590         this.matched = false;
1591     }
1592 
1593     @Override
1594     public String toString() {
1595         return "Constraint " + getClass().getSimpleName() + ", " + errorPrefix();
1596     }
1597 
1598     public Class<?> getKlass() {
1599         return klass;
1600     }
1601 
1602     protected String errorPrefix() {
1603         return "Class " + klass.getSimpleName() + ", Method " + methodName + ", Rule " + ruleIdx;
1604     }
1605 
1606     public void checkConstraint(IRViolationException e) {
1607         String message = e.getExceptionInfo();
1608         String[] splitMethods = message.split("Method");
1609         for (int i = 1; i < splitMethods.length; i++) {
1610             String method = splitMethods[i];
1611             if (methodPattern.matcher(method).find()) {
1612                 String[] splitIrRules = method.split("@IR ");
1613                 for (int j = 1; j < splitIrRules.length; j++) {
1614                     String irRule = splitIrRules[j];
1615                     if (irRule.startsWith("rule " + ruleIdx)) {
1616                         checkIRRule(irRule);
1617                     }
1618                 }
1619             }
1620         }
1621         Asserts.assertTrue(matched, this + " should have been matched");
1622     }
1623 
1624     abstract protected void checkIRRule(String irRule);
1625 }
1626 
1627 // Constraint for rule that does not fail.
1628 class GoodRuleConstraint extends Constraint {
1629 
1630     GoodRuleConstraint(Class<?> klass, String methodName, int ruleIdx) {
1631         super(klass, methodName, ruleIdx);
1632         matched = true;
1633     }
1634 
1635     public static GoodRuleConstraint create(Class<?> klass, String methodName, int ruleIdx) {
1636         return new GoodRuleConstraint(klass, methodName, ruleIdx);
1637     }
1638 
1639     @Override
1640     protected void checkIRRule(String irRule) {
1641         Asserts.fail(errorPrefix() + " should not fail:" + System.lineSeparator() + irRule);
1642     }
1643 }
1644 
1645 // Constraint for rule that might fail but not with "failOn".
1646 class GoodFailOnConstraint extends GoodRuleConstraint {
1647 
1648     private GoodFailOnConstraint(Class<?> klass, String methodName, int ruleIdx) {
1649         super(klass, methodName, ruleIdx);
1650     }
1651 
1652     public static GoodFailOnConstraint create(Class<?> klass, String methodName, int ruleIdx) {
1653         return new GoodFailOnConstraint(klass, methodName, ruleIdx);
1654     }
1655 
1656     @Override
1657     protected void checkIRRule(String irRule) {
1658         Asserts.assertFalse(irRule.contains("- failOn"), errorPrefix() + " should not have failed:" + System.lineSeparator() + irRule);
1659     }
1660 }
1661 
1662 // Constraint for rule that might fail but not with "counts".
1663 class GoodCountsConstraint extends GoodRuleConstraint {
1664 
1665     private GoodCountsConstraint(Class<?> klass, String methodName, int ruleIdx) {
1666         super(klass, methodName, ruleIdx);
1667     }
1668 
1669     public static GoodCountsConstraint create(Class<?> klass, String methodName, int ruleIdx) {
1670         return new GoodCountsConstraint(klass, methodName, ruleIdx);
1671     }
1672 
1673     @Override
1674     protected void checkIRRule(String irRule) {
1675         Asserts.assertFalse(irRule.contains("- counts"), errorPrefix() + " should not have failed with counts:"
1676                                                          + System.lineSeparator() + irRule);
1677     }
1678 }
1679 
1680 // Base class for all Regex based constraint.
1681 abstract class RegexConstraint extends Constraint {
1682     final String category;
1683     final String otherCategory;
1684     final int[] regexIndexes;
1685     final boolean isGood;
1686     final List<String> matches;
1687 
1688     RegexConstraint(Class<?> klass, String methodName, String category, boolean isGood, List<String> matches, int ruleIdx, int... regexIndexes) {
1689         super(klass, methodName, ruleIdx, initIRPattern(category, ruleIdx));
1690         this.category = category;
1691         this.regexIndexes = regexIndexes;
1692         if (category.equals("failOn")) {
1693             this.otherCategory = "counts";
1694         } else {
1695             Asserts.assertTrue(category.equals("counts"));
1696             this.otherCategory = "failOn";
1697         }
1698         this.isGood = isGood;
1699         this.matches = matches;
1700     }
1701 
1702     @Override
1703     public String toString() {
1704         String msg = super.toString() + ", ";
1705         if (regexIndexes.length > 1) {
1706             msg += "regexes: [" + String.join(", ", Arrays.stream(regexIndexes).mapToObj(String::valueOf).toArray(String[]::new)) + "]";
1707         } else {
1708             msg += "regex: " + regexIndexes[0];
1709         }
1710         return msg;
1711     }
1712 
1713     @Override
1714     protected String errorPrefix() {
1715         return super.errorPrefix() + " with \"" + category + "\"";
1716     }
1717 
1718     private static Pattern initIRPattern(String category, int ruleIdx) {
1719         if (category.equals("failOn")) {
1720             return Pattern.compile("rule " + ruleIdx + ":.*\\R.*- failOn: Graph contains forbidden nodes.*\\R" +
1721                                    ".*Constraint \\d+:.*\\R.*Matched forbidden node.*");
1722         } else {
1723             return Pattern.compile("rule " + ruleIdx + ":.*\\R.*- counts: Graph contains wrong number of nodes:\\R" +
1724                                    ".*Constraint \\d+:.*\\R.*Expected.*");
1725         }
1726     }
1727 
1728     @Override
1729     protected void checkIRRule(String irRule) {
1730         int categoryIndex = irRule.indexOf("- " + category);
1731         Asserts.assertTrue(categoryIndex != -1, errorPrefix() + " should have failed");
1732 
1733         int endIndex;
1734         int otherCategoryIndex = irRule.indexOf("- " + otherCategory);
1735         if (otherCategoryIndex == -1 || categoryIndex > otherCategoryIndex) {
1736             endIndex = irRule.length();
1737         } else {
1738             endIndex = otherCategoryIndex;
1739         }
1740         String categoryString = irRule.substring(irRule.indexOf("- " + category), endIndex);
1741         Pattern pattern;
1742         Matcher matcher;
1743         for (int regexIndex : this.regexIndexes) {
1744             pattern = Pattern.compile("Constraint " + regexIndex + ":.*");
1745             matcher = pattern.matcher(categoryString);
1746             if (isGood) {
1747                 Asserts.assertFalse(matcher.find(), errorPrefix() + " failed with Constraint " + regexIndex);
1748                 matched = true;
1749             } else {
1750                 Asserts.assertTrue(matcher.find(), errorPrefix() + " should have failed at Constraint " + regexIndex);
1751                 String[] splitRegex = categoryString.split("Constraint ");
1752                 if (matches != null) {
1753                     for (int i = 1; i < splitRegex.length; i++) {
1754                         String regexString = splitRegex[i];
1755                         if (regexString.startsWith(String.valueOf(regexIndex))) {
1756                             // Do matching on actual match and not on regex string
1757                             String actualMatch = regexString.split("\\R", 2)[1];
1758                             Asserts.assertTrue(matches.stream().allMatch(actualMatch::contains),
1759                                                errorPrefix() + " could not find all matches at Constraint " + regexIndex);
1760                             matched = true;
1761                         }
1762                     }
1763                 }
1764             }
1765         }
1766     }
1767 }
1768 
1769 // Base class for all good regex based constraints.
1770 abstract class GoodRegexConstraint extends RegexConstraint {
1771 
1772     GoodRegexConstraint(Class<?> klass, String methodName, String category, int ruleIdx, int... regexIndexes) {
1773         super(klass, methodName, category, true, null, ruleIdx, regexIndexes);
1774     }
1775 }
1776 
1777 // Constraint for rule that might fail with "counts" or "failOn", but the specified regex in "failOn" does not fail.
1778 class GoodFailOnRegexConstraint extends GoodRegexConstraint {
1779 
1780     private GoodFailOnRegexConstraint(Class<?> klass, String methodName, int ruleIdx, int... regexIndexes) {
1781         super(klass, methodName, "failOn", ruleIdx, regexIndexes);
1782     }
1783 
1784 
1785     public static GoodFailOnRegexConstraint create(Class<?> klass, String methodName, int ruleIdx, int... regexIndexes) {
1786         return new GoodFailOnRegexConstraint(klass, methodName, ruleIdx, regexIndexes);
1787     }
1788 }
1789 
1790 
1791 // Constraint for rule that might fail with "counts" or "failOn", but the specified regex in "counts" does not fail.
1792 class GoodCountsRegexConstraint extends GoodRegexConstraint {
1793 
1794     private GoodCountsRegexConstraint(Class<?> klass, String methodName, int ruleIdx, int... regexIndexes) {
1795         super(klass, methodName, "counts", ruleIdx, regexIndexes);
1796     }
1797 
1798 
1799     public static GoodCountsRegexConstraint create(Class<?> klass, String methodName, int ruleIdx, int... regexIndexes) {
1800         return new GoodCountsRegexConstraint(klass, methodName, ruleIdx, regexIndexes);
1801     }
1802 }
1803 
1804 // Constraint for rule that fails with "failOn" and the specified regex must also fail.
1805 class BadFailOnConstraint extends RegexConstraint {
1806 
1807     BadFailOnConstraint(Class<?> klass, String methodName, int ruleIdx, List<String> matches, int... regexIndexes) {
1808         super(klass, methodName, "failOn", false, matches, ruleIdx, regexIndexes);
1809     }
1810 
1811     public static BadFailOnConstraint create(Class<?> klass, String methodName, int ruleIdx, int regexId, String... matches) {
1812         return new BadFailOnConstraint(klass, methodName, ruleIdx, new ArrayList<>(Arrays.asList(matches)), regexId);
1813     }
1814 
1815     public static BadFailOnConstraint create(Class<?> klass, String methodName, int ruleIdx, String... matches) {
1816         return new BadFailOnConstraint(klass, methodName, ruleIdx, new ArrayList<>(Arrays.asList(matches)), 1);
1817     }
1818 }
1819 
1820 // Constraint for rule that fails with "counts" and the specified regex must also fail.
1821 class BadCountsConstraint extends RegexConstraint {
1822 
1823     BadCountsConstraint(Class<?> klass, String methodName, int ruleIdx, List<String> matches, int... regexIndexes) {
1824         super(klass, methodName, "counts", false, matches, ruleIdx, regexIndexes);
1825     }
1826 
1827     public static BadCountsConstraint create(Class<?> klass, String methodName, int ruleIdx, int regexId, int foundCount, String... matches) {
1828         List<String> matchesList = getMatchesList(foundCount, matches, Arrays.asList(matches));
1829         return new BadCountsConstraint(klass, methodName, ruleIdx, matchesList, regexId);
1830     }
1831 
1832     public static BadCountsConstraint create(Class<?> klass, String methodName, int ruleIdx, int foundCount, String... matches) {
1833         List<String> matchesList = getMatchesList(foundCount, matches, Arrays.asList(matches));
1834         return new BadCountsConstraint(klass, methodName, ruleIdx, matchesList, 1);
1835     }
1836 
1837     private static List<String> getMatchesList(int foundCount, String[] matches, List<String> strings) {
1838         List<String> matchesList = new ArrayList<>();
1839         matchesList.add("Failed comparison: [found] " + foundCount);
1840         if (matches != null) {
1841             matchesList.addAll(strings);
1842         }
1843         return matchesList;
1844     }
1845 }