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