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