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