src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File
*** old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java	Mon Mar 20 17:37:40 2017
--- new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java	Mon Mar 20 17:37:40 2017

*** 1,7 **** --- 1,7 ---- /* ! * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. ! * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.
*** 20,44 **** --- 20,49 ---- * or visit www.oracle.com if you need additional information or have any * questions. */ package org.graalvm.compiler.core.test.ea; ! import jdk.vm.ci.meta.JavaConstant; import org.junit.Assert; import org.junit.Test; ! import java.util.List; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.loop.DefaultLoopPolicies; import org.graalvm.compiler.loop.phases.LoopFullUnrollPhase; import org.graalvm.compiler.loop.phases.LoopPeelingPhase; + import org.graalvm.compiler.nodes.ConstantNode; + import org.graalvm.compiler.nodes.ReturnNode; + import org.graalvm.compiler.nodes.extended.BoxNode; import org.graalvm.compiler.nodes.extended.ValueAnchorNode; + import org.graalvm.compiler.nodes.java.LoadFieldNode; import org.graalvm.compiler.nodes.virtual.AllocatedObjectNode; import org.graalvm.compiler.nodes.virtual.CommitAllocationNode; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; + import org.junit.Assert; + import org.junit.Test; + + import jdk.vm.ci.meta.JavaConstant; /** * The PartialEscapeAnalysisPhase is expected to remove all allocations and return the correct * values. */
*** 178,187 **** --- 183,236 ---- } return obj.x <= 3 ? 1 : 0; } @Test + public void testMergeAllocationsInt2() { + testEscapeAnalysis("testMergeAllocationsInt2Snippet", JavaConstant.forInt(1), true); + } + + public int testMergeAllocationsInt2Snippet(int a) { + /* + * The initial object in obj exists until the end of the function, but it can still be + * merged with the one allocated in the else block because noone can observe the identity. + */ + TestClassInt obj = new TestClassInt(1, 2); + if (a < 0) { + notInlineable(); + } else { + obj = new TestClassInt(1, 2); + notInlineable(); + } + return obj.x <= 3 ? 1 : 0; + } + + @Test + public void testMergeAllocationsInt3() { + // ensure that the result is not constant: + assertTrue(testMergeAllocationsInt3Snippet(true)); + assertFalse(testMergeAllocationsInt3Snippet(false)); + + prepareGraph("testMergeAllocationsInt3Snippet", true); + assertFalse(graph.getNodes().filter(ReturnNode.class).first().result().isConstant()); + } + + public boolean testMergeAllocationsInt3Snippet(boolean a) { + TestClassInt phi1; + TestClassInt phi2; + if (a) { + field = new TestClassObject(); + field = new TestClassObject(); + phi1 = phi2 = new TestClassInt(1, 2); + } else { + phi1 = new TestClassInt(2, 3); + phi2 = new TestClassInt(3, 4); + } + return phi1 == phi2; + } + + @Test public void testMergeAllocationsObj() { testEscapeAnalysis("testMergeAllocationsObjSnippet", JavaConstant.forInt(1), false); } public int testMergeAllocationsObjSnippet(int a) {
*** 257,269 **** --- 306,382 ---- notInlineable(); } return obj.value <= 3 ? 1 : 0; } + /** + * Tests that a graph with allocations that does not make progress during PEA will not be + * changed. + */ + @Test + public void testChangeHandling() { + prepareGraph("testChangeHandlingSnippet", false); + Assert.assertEquals(2, graph.getNodes().filter(CommitAllocationNode.class).count()); + Assert.assertEquals(1, graph.getNodes().filter(BoxNode.class).count()); + List<Node> nodes = graph.getNodes().snapshot(); + // verify that an additional run doesn't add or remove nodes + new PartialEscapePhase(false, false, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); + Assert.assertEquals(nodes.size(), graph.getNodeCount()); + for (Node node : nodes) { + Assert.assertTrue(node.isAlive()); + } + } + + public volatile Object field; + + public int testChangeHandlingSnippet(int a) { + Object obj; + Integer one = 1; + obj = new MyException(one); + if (a < 0) { + notInlineable(); + } else { + obj = new Integer(1); + notInlineable(); + } + field = obj; + return 1; + } + + /** + * Test the case where allocations before and during a loop that have no usages other than their + * phi need to be recognized as an important change. This needs a loop so that the allocation is + * not trivially removed by dead code elimination. + */ + @Test + public void testRemovalSpecialCase() { + prepareGraph("testRemovalSpecialCaseSnippet", false); + Assert.assertEquals(2, graph.getNodes().filter(CommitAllocationNode.class).count()); + // create the situation by removing the if + graph.replaceFixedWithFloating(graph.getNodes().filter(LoadFieldNode.class).first(), graph.unique(ConstantNode.forInt(0))); + new CanonicalizerPhase().apply(graph, context); + // verify that an additional run removes all allocations + new PartialEscapePhase(false, false, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); + Assert.assertEquals(0, graph.getNodes().filter(CommitAllocationNode.class).count()); + } + + public volatile int field2; + + public int testRemovalSpecialCaseSnippet(int a) { + Object phi = new Object(); + for (int i = 0; i < a; i++) { + field = null; + if (field2 == 1) { + phi = new Object(); + } + } + return phi == null ? 1 : 0; + } + @Test public void testCheckCast() { ! testEscapeAnalysis("testCheckCastSnippet", getSnippetReflection().forObject(TestClassObject.class), false); ! testEscapeAnalysis("testCheckCastSnippet", getSnippetReflection().forObject(TestClassObject.class), true); } public Object testCheckCastSnippet() { TestClassObject obj = new TestClassObject(TestClassObject.class); TestClassObject obj2 = new TestClassObject(obj);
*** 312,322 **** --- 425,435 ---- @Test public void testFullyUnrolledLoop() { prepareGraph("testFullyUnrolledLoopSnippet", false); new LoopFullUnrollPhase(new CanonicalizerPhase(), new DefaultLoopPolicies()).apply(graph, context); ! new PartialEscapePhase(false, new CanonicalizerPhase(), graph.getOptions()).apply(graph, context); Assert.assertEquals(1, returnNodes.size()); Assert.assertTrue(returnNodes.get(0).result() instanceof AllocatedObjectNode); CommitAllocationNode commit = ((AllocatedObjectNode) returnNodes.get(0).result()).getCommit(); Assert.assertEquals(2, commit.getValues().size()); Assert.assertEquals(1, commit.getVirtualObjects().size());
*** 343,353 **** --- 456,466 ---- @Test public void testPeeledLoop() { prepareGraph("testPeeledLoopSnippet", false); new LoopPeelingPhase(new DefaultLoopPolicies()).apply(graph, getDefaultHighTierContext()); ! new SchedulePhase(graph.getOptions()).apply(graph); } public static void testDeoptMonitorSnippetInner(Object o2, Object t, int i) { staticField = null; if (i == 0) {

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File