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