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