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
25 package org.graalvm.compiler.replacements.test;
26
27 import static org.graalvm.compiler.java.BytecodeParserOptions.InlinePartialIntrinsicExitDuringParsing;
28
29 import java.util.function.Function;
30
31 import org.graalvm.compiler.api.directives.GraalDirectives;
32 import org.graalvm.compiler.api.replacements.ClassSubstitution;
33 import org.graalvm.compiler.api.replacements.MethodSubstitution;
34 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
35 import org.graalvm.compiler.bytecode.BytecodeProvider;
36 import org.graalvm.compiler.core.common.LIRKind;
37 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
38 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
39 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
40 import org.graalvm.compiler.core.common.type.Stamp;
41 import org.graalvm.compiler.core.common.type.StampFactory;
42 import org.graalvm.compiler.debug.DebugContext;
43 import org.graalvm.compiler.graph.GraalGraphError;
44 import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
45 import org.graalvm.compiler.graph.Node.NodeIntrinsic;
46 import org.graalvm.compiler.nodes.FrameState;
47 import org.graalvm.compiler.nodes.PiNode;
48 import org.graalvm.compiler.nodes.StructuredGraph;
49 import org.graalvm.compiler.nodes.ValueNode;
50 import org.graalvm.compiler.nodes.extended.OpaqueNode;
51 import org.graalvm.compiler.nodes.extended.ForeignCallNode;
52 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
53 import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
54 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver;
55 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
56 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration;
57 import org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory;
58 import org.graalvm.compiler.nodes.spi.LoweringTool;
59 import org.graalvm.compiler.options.OptionValues;
60 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
61 import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
62 import org.graalvm.compiler.phases.common.FloatingReadPhase;
63 import org.graalvm.compiler.phases.common.FrameStateAssignmentPhase;
64 import org.graalvm.compiler.phases.common.GuardLoweringPhase;
65 import org.graalvm.compiler.phases.common.LoweringPhase;
66 import org.graalvm.compiler.phases.tiers.HighTierContext;
67 import jdk.internal.vm.compiler.word.LocationIdentity;
68 import org.junit.Assert;
69 import org.junit.BeforeClass;
70 import org.junit.Test;
71
72 import jdk.vm.ci.code.InstalledCode;
73 import jdk.vm.ci.meta.JavaKind;
74 import jdk.vm.ci.meta.ResolvedJavaMethod;
75
76 /**
77 * Tests for expected behavior when parsing snippets and intrinsics.
78 */
79 public class ReplacementsParseTest extends ReplacementsTest {
80
81 private static final String IN_COMPILED_HANDLER_MARKER = "*** in compiled handler ***";
82
83 /**
84 * Marker value to indicate an exception handler was interpreted. We cannot use a complex string
85 * expression in this context without risking non-deterministic behavior dependent on whether
86 * String intrinsics are applied or whether String expression evaluation hit an uncommon trap
87 * when executed by C1 or C2 (and thus potentially altering the profile such that the exception
88 * handler is *not* compiled by Graal even when we want it to be).
173 * @see TestObjectSubstitutions#copyFirst(byte[], byte[], boolean)
174 */
175 static int copyFirst(byte[] left, byte[] right, boolean left2right) {
176 return copyFirstBody(left, right, left2right);
177 }
178
179 /**
180 * @see TestObjectSubstitutions#copyFirstL2R(byte[], byte[])
181 */
182 static int copyFirstL2R(byte[] left, byte[] right) {
183 return copyFirstL2RBody(left, right);
184 }
185
186 static int nonVoidIntrinsicWithCall(@SuppressWarnings("unused") int x, int y) {
187 return y;
188 }
189
190 static int nonVoidIntrinsicWithOptimizedSplit(int x) {
191 return x;
192 }
193 }
194
195 @ClassSubstitution(TestObject.class)
196 static class TestObjectSubstitutions {
197
198 @MethodSubstitution(isStatic = true)
199 static double nextAfter(double x, double d) {
200 double xx = (x == -0.0 ? 0.0 : x);
201 return Math.nextAfter(xx, d);
202 }
203
204 /**
205 * Tests conditional intrinsification of a static method.
206 */
207 @MethodSubstitution
208 static String stringize(Object obj) {
209 if (obj != null && obj.getClass() == String.class) {
210 return asNonNullString(obj);
211 } else {
212 // A recursive call denotes exiting/deoptimizing
270 }
271
272 private static String apply(Function<String, String> f, String value) {
273 return f.apply(value);
274 }
275
276 @MethodSubstitution(isStatic = true)
277 static int nonVoidIntrinsicWithCall(int x, int y) {
278 nonVoidIntrinsicWithCallStub(x);
279 return y;
280 }
281
282 @MethodSubstitution(isStatic = true)
283 static int nonVoidIntrinsicWithOptimizedSplit(int x) {
284 if (x == GraalDirectives.opaque(x)) {
285 nonVoidIntrinsicWithCallStub(x);
286 }
287 return x;
288 }
289
290 public static void nonVoidIntrinsicWithCallStub(int zLen) {
291 nonVoidIntrinsicWithCallStub(STUB_CALL, zLen);
292 }
293
294 static final ForeignCallDescriptor STUB_CALL = new ForeignCallDescriptor("stubCall", void.class, int.class);
295
296 @NodeIntrinsic(ForeignCallNode.class)
297 private static native void nonVoidIntrinsicWithCallStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, int zLen);
298
299 }
300
301 @Override
302 protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) {
303 BytecodeProvider replacementBytecodeProvider = getSystemClassLoaderBytecodeProvider();
304 Registration r = new Registration(invocationPlugins, TestObject.class, replacementBytecodeProvider);
305 NodeIntrinsicPluginFactory.InjectionProvider injections = new DummyInjectionProvider();
306 new PluginFactory_ReplacementsParseTest().registerPlugins(invocationPlugins, injections);
307 r.registerMethodSubstitution(TestObjectSubstitutions.class, "nextAfter", double.class, double.class);
308 r.registerMethodSubstitution(TestObjectSubstitutions.class, "stringize", Object.class);
309 r.registerMethodSubstitution(TestObjectSubstitutions.class, "stringizeId", Receiver.class);
310 r.registerMethodSubstitution(TestObjectSubstitutions.class, "copyFirst", byte[].class, byte[].class, boolean.class);
311 r.registerMethodSubstitution(TestObjectSubstitutions.class, "copyFirstL2R", byte[].class, byte[].class);
312 r.registerMethodSubstitution(TestObjectSubstitutions.class, "nonVoidIntrinsicWithCall", int.class, int.class);
313 r.registerMethodSubstitution(TestObjectSubstitutions.class, "nonVoidIntrinsicWithOptimizedSplit", int.class);
314
315 if (replacementBytecodeProvider.supportsInvokedynamic()) {
316 r.registerMethodSubstitution(TestObjectSubstitutions.class, "identity", String.class);
317 }
318 super.registerInvocationPlugins(invocationPlugins);
319 }
320
321 @BeforeClass
322 public static void warmupProfiles() {
323 for (int i = 0; i < 40000; i++) {
324 callCopyFirst(new byte[16], new byte[16], true);
325 callCopyFirstL2R(new byte[16], new byte[16]);
326 }
327 }
328
329 /**
330 * Ensure that calling the original method from the substitution binds correctly.
331 */
332 @Test
333 public void test1() {
340
341 /**
342 * Ensure that calling the substitution method binds to the original method properly.
343 */
344 @Test
345 public void test2() {
346 test("test2Snippet", 1.0);
347 }
348
349 public double test2Snippet(double d) {
350 return TestObject.next2(d);
351 }
352
353 /**
354 * Ensure that substitution methods with assertions in them don't complain when the exception
355 * constructor is deleted.
356 */
357
358 @Test
359 public void testNextAfter() {
360 double[] inArray = new double[1024];
361 double[] outArray = new double[1024];
362 for (int i = 0; i < inArray.length; i++) {
363 inArray[i] = -0.0;
364 }
365 test("doNextAfter", inArray, outArray);
366 }
367
368 public void doNextAfter(double[] outArray, double[] inArray) {
369 for (int i = 0; i < inArray.length; i++) {
370 double direction = (i & 1) == 0 ? Double.POSITIVE_INFINITY : -Double.NEGATIVE_INFINITY;
371 outArray[i] = TestObject.nextAfter(inArray[i], direction);
372 }
373 }
374
375 private void testWithDifferentReturnValues(OptionValues options, String standardReturnValue, String compiledReturnValue, String name, Object... args) {
376 ResolvedJavaMethod method = getResolvedJavaMethod(name);
377 Object receiver = null;
378
379 Result expect = executeExpected(method, receiver, args);
571 @Test
572 public void testNonVoidIntrinsicWithCall() {
573 testGraph("nonVoidIntrinsicWithCall");
574 }
575
576 public static int nonVoidIntrinsicWithOptimizedSplit(int x) {
577 if (TestObject.nonVoidIntrinsicWithOptimizedSplit(x) == x) {
578 GraalDirectives.deoptimize();
579 }
580 return x;
581 }
582
583 /**
584 * This is similar to {@link #testNonVoidIntrinsicWithCall()} but has a merge after the call
585 * which would normally capture the {@link FrameState} but in this case we force the merge to be
586 * optimized away.
587 */
588 @Test
589 public void testNonVoidIntrinsicWithOptimizedSplit() {
590 testGraph("nonVoidIntrinsicWithOptimizedSplit");
591 }
592
593 @SuppressWarnings("try")
594 private void testGraph(String name) {
595 StructuredGraph graph = parseEager(name, StructuredGraph.AllowAssumptions.YES);
596 try (DebugContext.Scope s0 = graph.getDebug().scope(name, graph)) {
597 for (OpaqueNode node : graph.getNodes().filter(OpaqueNode.class)) {
598 node.remove();
599 }
600 HighTierContext context = getDefaultHighTierContext();
601 CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
602 new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
603 new FloatingReadPhase().apply(graph);
604 canonicalizer.apply(graph, context);
605 new DeadCodeEliminationPhase().apply(graph);
606 new GuardLoweringPhase().apply(graph, getDefaultMidTierContext());
607 new FrameStateAssignmentPhase().apply(graph);
608 } catch (Throwable e) {
609 throw graph.getDebug().handle(e);
610 }
|
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
25 package org.graalvm.compiler.replacements.test;
26
27 import static org.graalvm.compiler.debug.DebugOptions.DumpOnError;
28 import static org.graalvm.compiler.java.BytecodeParserOptions.InlinePartialIntrinsicExitDuringParsing;
29
30 import java.util.function.Function;
31
32 import org.graalvm.compiler.api.directives.GraalDirectives;
33 import org.graalvm.compiler.api.replacements.ClassSubstitution;
34 import org.graalvm.compiler.api.replacements.MethodSubstitution;
35 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
36 import org.graalvm.compiler.bytecode.BytecodeProvider;
37 import org.graalvm.compiler.core.common.LIRKind;
38 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
39 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
40 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
41 import org.graalvm.compiler.core.common.type.Stamp;
42 import org.graalvm.compiler.core.common.type.StampFactory;
43 import org.graalvm.compiler.debug.DebugContext;
44 import org.graalvm.compiler.debug.GraalError;
45 import org.graalvm.compiler.graph.GraalGraphError;
46 import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
47 import org.graalvm.compiler.graph.Node.NodeIntrinsic;
48 import org.graalvm.compiler.java.BytecodeParser.BytecodeParserError;
49 import org.graalvm.compiler.nodes.FrameState;
50 import org.graalvm.compiler.nodes.PiNode;
51 import org.graalvm.compiler.nodes.StructuredGraph;
52 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
53 import org.graalvm.compiler.nodes.StructuredGraph.Builder;
54 import org.graalvm.compiler.nodes.ValueNode;
55 import org.graalvm.compiler.nodes.extended.ForeignCallNode;
56 import org.graalvm.compiler.nodes.extended.OpaqueNode;
57 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
58 import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
59 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver;
60 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
61 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration;
62 import org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory;
63 import org.graalvm.compiler.nodes.spi.LoweringTool;
64 import org.graalvm.compiler.options.OptionValues;
65 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
66 import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
67 import org.graalvm.compiler.phases.common.FloatingReadPhase;
68 import org.graalvm.compiler.phases.common.FrameStateAssignmentPhase;
69 import org.graalvm.compiler.phases.common.GuardLoweringPhase;
70 import org.graalvm.compiler.phases.common.LoweringPhase;
71 import org.graalvm.compiler.phases.tiers.HighTierContext;
72 import org.graalvm.compiler.test.GraalTest;
73 import jdk.internal.vm.compiler.word.LocationIdentity;
74 import org.junit.Assert;
75 import org.junit.Assume;
76 import org.junit.BeforeClass;
77 import org.junit.Test;
78
79 import jdk.vm.ci.code.InstalledCode;
80 import jdk.vm.ci.meta.JavaKind;
81 import jdk.vm.ci.meta.ResolvedJavaMethod;
82
83 /**
84 * Tests for expected behavior when parsing snippets and intrinsics.
85 */
86 public class ReplacementsParseTest extends ReplacementsTest {
87
88 private static final String IN_COMPILED_HANDLER_MARKER = "*** in compiled handler ***";
89
90 /**
91 * Marker value to indicate an exception handler was interpreted. We cannot use a complex string
92 * expression in this context without risking non-deterministic behavior dependent on whether
93 * String intrinsics are applied or whether String expression evaluation hit an uncommon trap
94 * when executed by C1 or C2 (and thus potentially altering the profile such that the exception
95 * handler is *not* compiled by Graal even when we want it to be).
180 * @see TestObjectSubstitutions#copyFirst(byte[], byte[], boolean)
181 */
182 static int copyFirst(byte[] left, byte[] right, boolean left2right) {
183 return copyFirstBody(left, right, left2right);
184 }
185
186 /**
187 * @see TestObjectSubstitutions#copyFirstL2R(byte[], byte[])
188 */
189 static int copyFirstL2R(byte[] left, byte[] right) {
190 return copyFirstL2RBody(left, right);
191 }
192
193 static int nonVoidIntrinsicWithCall(@SuppressWarnings("unused") int x, int y) {
194 return y;
195 }
196
197 static int nonVoidIntrinsicWithOptimizedSplit(int x) {
198 return x;
199 }
200
201 static int div(int x, int y) {
202 return x / y;
203 }
204 }
205
206 @ClassSubstitution(TestObject.class)
207 static class TestObjectSubstitutions {
208
209 @MethodSubstitution(isStatic = true)
210 static double nextAfter(double x, double d) {
211 double xx = (x == -0.0 ? 0.0 : x);
212 return Math.nextAfter(xx, d);
213 }
214
215 /**
216 * Tests conditional intrinsification of a static method.
217 */
218 @MethodSubstitution
219 static String stringize(Object obj) {
220 if (obj != null && obj.getClass() == String.class) {
221 return asNonNullString(obj);
222 } else {
223 // A recursive call denotes exiting/deoptimizing
281 }
282
283 private static String apply(Function<String, String> f, String value) {
284 return f.apply(value);
285 }
286
287 @MethodSubstitution(isStatic = true)
288 static int nonVoidIntrinsicWithCall(int x, int y) {
289 nonVoidIntrinsicWithCallStub(x);
290 return y;
291 }
292
293 @MethodSubstitution(isStatic = true)
294 static int nonVoidIntrinsicWithOptimizedSplit(int x) {
295 if (x == GraalDirectives.opaque(x)) {
296 nonVoidIntrinsicWithCallStub(x);
297 }
298 return x;
299 }
300
301 @MethodSubstitution
302 static int div(int x, int y) {
303 assert y != 0;
304 return x / y;
305 }
306
307 public static void nonVoidIntrinsicWithCallStub(int zLen) {
308 nonVoidIntrinsicWithCallStub(STUB_CALL, zLen);
309 }
310
311 static final ForeignCallDescriptor STUB_CALL = new ForeignCallDescriptor("stubCall", void.class, int.class);
312
313 @NodeIntrinsic(ForeignCallNode.class)
314 private static native void nonVoidIntrinsicWithCallStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, int zLen);
315
316 }
317
318 @Override
319 protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) {
320 BytecodeProvider replacementBytecodeProvider = getSystemClassLoaderBytecodeProvider();
321 Registration r = new Registration(invocationPlugins, TestObject.class, replacementBytecodeProvider);
322 NodeIntrinsicPluginFactory.InjectionProvider injections = new DummyInjectionProvider();
323 new PluginFactory_ReplacementsParseTest().registerPlugins(invocationPlugins, injections);
324 r.registerMethodSubstitution(TestObjectSubstitutions.class, "nextAfter", double.class, double.class);
325 r.registerMethodSubstitution(TestObjectSubstitutions.class, "stringize", Object.class);
326 r.registerMethodSubstitution(TestObjectSubstitutions.class, "stringizeId", Receiver.class);
327 r.registerMethodSubstitution(TestObjectSubstitutions.class, "copyFirst", byte[].class, byte[].class, boolean.class);
328 r.registerMethodSubstitution(TestObjectSubstitutions.class, "copyFirstL2R", byte[].class, byte[].class);
329 r.registerMethodSubstitution(TestObjectSubstitutions.class, "nonVoidIntrinsicWithCall", int.class, int.class);
330 r.registerMethodSubstitution(TestObjectSubstitutions.class, "nonVoidIntrinsicWithOptimizedSplit", int.class);
331 r.registerMethodSubstitution(TestObjectSubstitutions.class, "div", int.class, int.class);
332
333 if (replacementBytecodeProvider.supportsInvokedynamic()) {
334 r.registerMethodSubstitution(TestObjectSubstitutions.class, "identity", String.class);
335 }
336 super.registerInvocationPlugins(invocationPlugins);
337 }
338
339 @BeforeClass
340 public static void warmupProfiles() {
341 for (int i = 0; i < 40000; i++) {
342 callCopyFirst(new byte[16], new byte[16], true);
343 callCopyFirstL2R(new byte[16], new byte[16]);
344 }
345 }
346
347 /**
348 * Ensure that calling the original method from the substitution binds correctly.
349 */
350 @Test
351 public void test1() {
358
359 /**
360 * Ensure that calling the substitution method binds to the original method properly.
361 */
362 @Test
363 public void test2() {
364 test("test2Snippet", 1.0);
365 }
366
367 public double test2Snippet(double d) {
368 return TestObject.next2(d);
369 }
370
371 /**
372 * Ensure that substitution methods with assertions in them don't complain when the exception
373 * constructor is deleted.
374 */
375
376 @Test
377 public void testNextAfter() {
378 Assume.assumeFalse(GraalTest.Java8OrEarlier);
379 double[] inArray = new double[1024];
380 double[] outArray = new double[1024];
381 for (int i = 0; i < inArray.length; i++) {
382 inArray[i] = -0.0;
383 }
384 test("doNextAfter", inArray, outArray);
385 }
386
387 public void doNextAfter(double[] outArray, double[] inArray) {
388 for (int i = 0; i < inArray.length; i++) {
389 double direction = (i & 1) == 0 ? Double.POSITIVE_INFINITY : -Double.NEGATIVE_INFINITY;
390 outArray[i] = TestObject.nextAfter(inArray[i], direction);
391 }
392 }
393
394 private void testWithDifferentReturnValues(OptionValues options, String standardReturnValue, String compiledReturnValue, String name, Object... args) {
395 ResolvedJavaMethod method = getResolvedJavaMethod(name);
396 Object receiver = null;
397
398 Result expect = executeExpected(method, receiver, args);
590 @Test
591 public void testNonVoidIntrinsicWithCall() {
592 testGraph("nonVoidIntrinsicWithCall");
593 }
594
595 public static int nonVoidIntrinsicWithOptimizedSplit(int x) {
596 if (TestObject.nonVoidIntrinsicWithOptimizedSplit(x) == x) {
597 GraalDirectives.deoptimize();
598 }
599 return x;
600 }
601
602 /**
603 * This is similar to {@link #testNonVoidIntrinsicWithCall()} but has a merge after the call
604 * which would normally capture the {@link FrameState} but in this case we force the merge to be
605 * optimized away.
606 */
607 @Test
608 public void testNonVoidIntrinsicWithOptimizedSplit() {
609 testGraph("nonVoidIntrinsicWithOptimizedSplit");
610 }
611
612 public static int div(int x, int y) {
613 return TestObject.div(x, y);
614 }
615
616 @Test
617 public void testAssertionInMethodSubstitution() {
618 try {
619 ResolvedJavaMethod method = getResolvedJavaMethod("div");
620 // avoid dumping graphs and printing exception since and exception is expected
621 OptionValues options = new OptionValues(getInitialOptions(), DumpOnError, false);
622 parse(new Builder(options, getDebugContext(options, null, method), AllowAssumptions.YES).method(method).compilationId(getCompilationId(method)), getEagerGraphBuilderSuite());
623 throw GraalError.shouldNotReachHere("BytecodeParser should have complained about using assertion in an intrinsic.");
624 } catch (BytecodeParserError e) {
625 // Expected behavior
626 }
627 }
628
629 @SuppressWarnings("try")
630 private void testGraph(String name) {
631 StructuredGraph graph = parseEager(name, StructuredGraph.AllowAssumptions.YES);
632 try (DebugContext.Scope s0 = graph.getDebug().scope(name, graph)) {
633 for (OpaqueNode node : graph.getNodes().filter(OpaqueNode.class)) {
634 node.remove();
635 }
636 HighTierContext context = getDefaultHighTierContext();
637 CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
638 new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
639 new FloatingReadPhase().apply(graph);
640 canonicalizer.apply(graph, context);
641 new DeadCodeEliminationPhase().apply(graph);
642 new GuardLoweringPhase().apply(graph, getDefaultMidTierContext());
643 new FrameStateAssignmentPhase().apply(graph);
644 } catch (Throwable e) {
645 throw graph.getDebug().handle(e);
646 }
|