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