# HG changeset patch # User Lukas Stadler # Date 1382970327 -3600 # Node ID f40b8d0d9dcb5ec5a5656d30f39923a1e20b6a2b # Parent 7f55cdeec6af6998adccd9933b72f79c2cd2f38f PEA: more tests, common base class for tests diff -r 7f55cdeec6af -r f40b8d0d9dcb graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EAMergingTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EAMergingTest.java Mon Oct 28 15:25:27 2013 +0100 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2011, 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.test.ea; + +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.graal.nodes.*; + +public class EAMergingTest extends EATestBase { + + @Test + public void testSimpleMerge() { + testEscapeAnalysis("simpleMergeSnippet", null, false); + assertTrue(returnNode.result() instanceof PhiNode); + PhiNode phi = (PhiNode) returnNode.result(); + assertTrue(phi.valueAt(0) instanceof LocalNode); + assertTrue(phi.valueAt(1) instanceof LocalNode); + } + + public static int simpleMergeSnippet(boolean b, int u, int v) { + TestClassInt obj; + if (b) { + obj = new TestClassInt(u, 0); + notInlineable(); + } else { + obj = new TestClassInt(v, 0); + notInlineable(); + } + return obj.x; + } +} diff -r 7f55cdeec6af -r f40b8d0d9dcb graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java Mon Oct 28 15:25:27 2013 +0100 @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2011, 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.test.ea; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.java.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.virtual.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; +import com.oracle.graal.virtual.phases.ea.*; + +public class EATestBase extends GraalCompilerTest { + + public static class TestClassInt { + public int x; + public int y; + + public TestClassInt() { + this(0, 0); + } + + public TestClassInt(int x) { + this(x, 0); + } + + public TestClassInt(int x, int y) { + this.x = x; + this.y = y; + } + + @Override + public boolean equals(Object obj) { + TestClassInt other = (TestClassInt) obj; + return x == other.x && y == other.y; + } + + @Override + public String toString() { + return "{" + x + "," + y + "}"; + } + + @Override + public int hashCode() { + return x + 13 * y; + } + } + + public static class TestClassObject { + public Object x; + public Object y; + + public TestClassObject() { + this(null, null); + } + + public TestClassObject(Object x) { + this(x, null); + } + + public TestClassObject(Object x, Object y) { + this.x = x; + this.y = y; + } + + @Override + public boolean equals(Object obj) { + TestClassObject other = (TestClassObject) obj; + return x == other.x && y == other.y; + } + + @Override + public String toString() { + return "{" + x + "," + y + "}"; + } + + @Override + public int hashCode() { + return (x == null ? 0 : x.hashCode()) + 13 * (y == null ? 0 : y.hashCode()); + } + } + + protected static native void notInlineable(); + + protected StructuredGraph graph; + protected HighTierContext context; + protected ReturnNode returnNode; + + /** + * Runs Escape Analysis on the given snippet and makes sure that no allocations remain in the + * graph. + * + * @param snippet the name of the method whose graph should be processed + * @param expectedConstantResult if this is non-null, the resulting graph needs to have the + * given constant return value + * @param iterativeEscapeAnalysis true if escape analysis should be run for more than one + * iteration + */ + protected void testEscapeAnalysis(String snippet, final Constant expectedConstantResult, final boolean iterativeEscapeAnalysis) { + prepareGraph(snippet, iterativeEscapeAnalysis); + if (expectedConstantResult != null) { + Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant()); + Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant()); + } + int newInstanceCount = graph.getNodes().filter(NewInstanceNode.class).count() + graph.getNodes().filter(NewArrayNode.class).count() + + graph.getNodes().filter(CommitAllocationNode.class).count(); + Assert.assertEquals(0, newInstanceCount); + } + + protected void prepareGraph(String snippet, final boolean iterativeEscapeAnalysis) { + ResolvedJavaMethod method = getMetaAccess().lookupJavaMethod(getMethod(snippet)); + graph = new StructuredGraph(method); + Debug.scope(getClass().getSimpleName(), new Object[]{graph, method, getCodeCache()}, new Runnable() { + + public void run() { + new GraphBuilderPhase(getMetaAccess(), getForeignCalls(), GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); + Assumptions assumptions = new Assumptions(false); + context = new HighTierContext(getProviders(), assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); + new DeadCodeEliminationPhase().apply(graph); + new CanonicalizerPhase(true).apply(graph, context); + new PartialEscapePhase(iterativeEscapeAnalysis, false, new CanonicalizerPhase(true)).apply(graph, context); + Assert.assertEquals(1, graph.getNodes().filter(ReturnNode.class).count()); + returnNode = graph.getNodes().filter(ReturnNode.class).first(); + } + }); + } +} diff -r 7f55cdeec6af -r f40b8d0d9dcb graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Mon Oct 28 17:03:59 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Mon Oct 28 15:25:27 2013 +0100 @@ -24,28 +24,20 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.test.*; -import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; -import com.oracle.graal.java.*; import com.oracle.graal.loop.phases.*; -import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.virtual.*; -import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.schedule.*; -import com.oracle.graal.phases.tiers.*; import com.oracle.graal.virtual.phases.ea.*; /** * The PartialEscapeAnalysisPhase is expected to remove all allocations and return the correct * values. */ -public class EscapeAnalysisTest extends GraalCompilerTest { +public class EscapeAnalysisTest extends EATestBase { @Test public void test1() { @@ -82,8 +74,6 @@ testEscapeAnalysis("testMonitorSnippet", Constant.forInt(0), false); } - private static native void notInlineable(); - public static int testMonitorSnippet() { Integer x = new Integer(0); Double y = new Double(0); @@ -126,19 +116,8 @@ testEscapeAnalysis("testMerge1Snippet", Constant.forInt(0), true); } - public static class TestObject { - - int x; - int y; - - public TestObject(int x, int y) { - this.x = x; - this.y = y; - } - } - public static int testMerge1Snippet(int a) { - TestObject obj = new TestObject(1, 0); + TestClassInt obj = new TestClassInt(1, 0); if (a < 0) { obj.x = obj.x + 1; } else { @@ -157,7 +136,7 @@ } public int testSimpleLoopSnippet(int a) { - TestObject obj = new TestObject(1, 2); + TestClassInt obj = new TestClassInt(1, 2); for (int i = 0; i < a; i++) { notInlineable(); } @@ -170,7 +149,7 @@ } public int testModifyingLoopSnippet(int a) { - TestObject obj = new TestObject(1, 2); + TestClassInt obj = new TestClassInt(1, 2); for (int i = 0; i < a; i++) { obj.x = 3; notInlineable(); @@ -178,24 +157,15 @@ return obj.x <= 3 ? 1 : 0; } - public static class TestObject2 { - - Object o; - - public TestObject2(Object o) { - this.o = o; - } - } - @Test public void testCheckCast() { - testEscapeAnalysis("testCheckCastSnippet", Constant.forObject(TestObject2.class), false); + testEscapeAnalysis("testCheckCastSnippet", Constant.forObject(TestClassObject.class), false); } public Object testCheckCastSnippet() { - TestObject2 obj = new TestObject2(TestObject2.class); - TestObject2 obj2 = new TestObject2(obj); - return ((TestObject2) obj2.o).o; + TestClassObject obj = new TestClassObject(TestClassObject.class); + TestClassObject obj2 = new TestClassObject(obj); + return ((TestClassObject) obj2.x).x; } @Test @@ -204,9 +174,9 @@ } public boolean testInstanceOfSnippet() { - TestObject2 obj = new TestObject2(TestObject2.class); - TestObject2 obj2 = new TestObject2(obj); - return obj2.o instanceof TestObject2; + TestClassObject obj = new TestClassObject(TestClassObject.class); + TestClassObject obj2 = new TestClassObject(obj); + return obj2.x instanceof TestClassObject; } @SuppressWarnings("unused") @@ -223,98 +193,56 @@ testEscapeAnalysis("testNewNodeSnippet", null, false); } - private static final TestObject2 staticObj = new TestObject2(null); + private static final TestClassObject staticObj = new TestClassObject(); public static Object testFullyUnrolledLoopSnippet() { /* * This tests a case that can appear if PEA is performed both before and after loop - * unrolling/peeling: If the VirtualInstanceNode is not anchored correctly to stay within - * the loop, it will not be duplicated, and therefore the resulting object will reference - * itself, and not a second (different) object. + * unrolling/peeling: If the VirtualInstanceNode is not duplicated correctly with the loop, + * the resulting object will reference itself, and not a second (different) object. */ - TestObject2 obj = staticObj; + TestClassObject obj = staticObj; for (int i = 0; i < 2; i++) { - obj = new TestObject2(obj); + obj = new TestClassObject(obj); } - return obj.o; + return obj.x; } @Test public void testFullyUnrolledLoop() { - testEscapeAnalysisUnrolled("testFullyUnrolledLoopSnippet"); + prepareGraph("testFullyUnrolledLoopSnippet", false); + new LoopFullUnrollPhase(new CanonicalizerPhase(true)).apply(graph, context); + new PartialEscapePhase(false, new CanonicalizerPhase(true)).apply(graph, context); + Assert.assertTrue(returnNode.result() instanceof AllocatedObjectNode); + CommitAllocationNode commit = ((AllocatedObjectNode) returnNode.result()).getCommit(); + Assert.assertEquals(2, commit.getValues().size()); + Assert.assertEquals(1, commit.getVirtualObjects().size()); + Assert.assertTrue("non-cyclic data structure expected", commit.getVirtualObjects().get(0) != commit.getValues().get(0)); } - private static Object staticField; + @SuppressWarnings("unused") private static Object staticField; - private static TestObject2 inlinedPart(TestObject2 obj) { - TestObject2 ret = new TestObject2(obj); + private static TestClassObject inlinedPart(TestClassObject obj) { + TestClassObject ret = new TestClassObject(obj); staticField = null; return ret; } public static Object testPeeledLoopSnippet() { - TestObject2 obj = staticObj; + TestClassObject obj = staticObj; int i = 0; do { obj = inlinedPart(obj); } while (i++ < 10); staticField = obj; - return obj.o; + return obj.x; } @Test public void testPeeledLoop() { - testEscapeAnalysisPeeled("testPeeledLoopSnippet"); - } - - private StructuredGraph graph; - private HighTierContext context; - private ReturnNode returnNode; - - private void testEscapeAnalysis(String snippet, final Constant expectedConstantResult, final boolean iterativeEscapeAnalysis) { - prepareGraph(snippet, iterativeEscapeAnalysis); - if (expectedConstantResult != null) { - Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant()); - Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant()); - } - int newInstanceCount = graph.getNodes().filter(NewInstanceNode.class).count() + graph.getNodes().filter(NewArrayNode.class).count() + - graph.getNodes().filter(CommitAllocationNode.class).count(); - Assert.assertEquals(0, newInstanceCount); - } - - private void testEscapeAnalysisUnrolled(String snippet) { - prepareGraph(snippet, false); - new LoopFullUnrollPhase(new CanonicalizerPhase(true)).apply(graph, context); - new PartialEscapePhase(false, new CanonicalizerPhase(true)).apply(graph, context); - Assert.assertTrue(returnNode.result() instanceof AllocatedObjectNode); - CommitAllocationNode commit = ((AllocatedObjectNode) returnNode.result()).getCommit(); - Assert.assertEquals(1, commit.getValues().size()); - Assert.assertEquals(1, commit.getVirtualObjects().size()); - Assert.assertTrue("non-cyclic data structure expected", commit.getVirtualObjects().get(0) != commit.getValues().get(0)); - } - - private void testEscapeAnalysisPeeled(String snippet) { - prepareGraph(snippet, false); + prepareGraph("testPeeledLoopSnippet", false); new LoopTransformHighPhase().apply(graph); new LoopTransformLowPhase().apply(graph); new SchedulePhase().apply(graph); } - - private void prepareGraph(String snippet, final boolean iterativeEscapeAnalysis) { - graph = new StructuredGraph(getMetaAccess().lookupJavaMethod(getMethod(snippet))); - Debug.scope("GraalCompiler", new Object[]{graph, getMetaAccess().lookupJavaMethod(getMethod(snippet)), getCodeCache()}, new Runnable() { - - public void run() { - new GraphBuilderPhase(getMetaAccess(), getForeignCalls(), GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); - Assumptions assumptions = new Assumptions(false); - context = new HighTierContext(getProviders(), assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); - new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); - new DeadCodeEliminationPhase().apply(graph); - new CanonicalizerPhase(true).apply(graph, context); - new PartialEscapePhase(iterativeEscapeAnalysis, new CanonicalizerPhase(true)).apply(graph, context); - Assert.assertEquals(1, graph.getNodes().filter(ReturnNode.class).count()); - returnNode = graph.getNodes().filter(ReturnNode.class).first(); - } - }); - } } diff -r 7f55cdeec6af -r f40b8d0d9dcb graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java Mon Oct 28 17:03:59 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java Mon Oct 28 15:25:27 2013 +0100 @@ -30,6 +30,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.test.*; +import com.oracle.graal.compiler.test.ea.EATestBase.TestClassInt; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; @@ -50,14 +51,10 @@ } } - public static class TestInt implements Callable { - - public int x; - public int y; + public static class TestInt extends TestClassInt implements Callable { public TestInt(int x, int y) { - this.x = x; - this.y = y; + super(x, y); } @Override diff -r 7f55cdeec6af -r f40b8d0d9dcb graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Mon Oct 28 17:03:59 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Mon Oct 28 15:25:27 2013 +0100 @@ -23,29 +23,23 @@ package com.oracle.graal.compiler.test.ea; import java.lang.ref.*; -import java.util.concurrent.*; import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.test.*; -import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.nodes.virtual.*; -import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.graph.*; -import com.oracle.graal.phases.tiers.*; -import com.oracle.graal.virtual.phases.ea.*; /** * The PartialEscapeAnalysisPhase is expected to remove all allocations and return the correct * values. */ -public class PartialEscapeAnalysisTest extends GraalCompilerTest { +public class PartialEscapeAnalysisTest extends EATestBase { public static class TestObject { @@ -71,7 +65,7 @@ @Test public void test1() { - testMaterialize("test1Snippet", 0.25, 1); + testPartialEscapeAnalysis("test1Snippet", 0.25, 1); } @SuppressWarnings("all") @@ -90,7 +84,7 @@ @Test public void test2() { - testMaterialize("test2Snippet", 1.5, 3, LoadIndexedNode.class); + testPartialEscapeAnalysis("test2Snippet", 1.5, 3, LoadIndexedNode.class); } public static Object test2Snippet(int a, Object x, Object y, Object z) { @@ -109,7 +103,7 @@ @Test public void test3() { - testMaterialize("test3Snippet", 0.5, 1, StoreFieldNode.class, LoadFieldNode.class); + testPartialEscapeAnalysis("test3Snippet", 0.5, 1, StoreFieldNode.class, LoadFieldNode.class); } public static Object test3Snippet(int a) { @@ -127,7 +121,7 @@ @Test public void testCache() { - testMaterialize("testCacheSnippet", 0.75, 1); + testPartialEscapeAnalysis("testCacheSnippet", 0.75, 1); } public static class CacheKey { @@ -175,57 +169,40 @@ @Test public void testReference1() { - assertEquals(1, processMethod("testReference1Snippet").getNodes().filter(NewInstanceNode.class).count()); + prepareGraph("testReference1Snippet", false); + assertEquals(1, graph.getNodes().filter(NewInstanceNode.class).count()); } @SafeVarargs - final void testMaterialize(final String snippet, double expectedProbability, int expectedCount, Class... invalidNodeClasses) { - StructuredGraph result = processMethod(snippet); + protected final void testPartialEscapeAnalysis(final String snippet, double expectedProbability, int expectedCount, Class... invalidNodeClasses) { + prepareGraph(snippet, false); + for (MergeNode merge : graph.getNodes(MergeNode.class)) { + merge.setStateAfter(null); + } + new DeadCodeEliminationPhase().apply(graph); + new CanonicalizerPhase(true).apply(graph, context); try { - Assert.assertTrue("partial escape analysis should have removed all NewInstanceNode allocations", result.getNodes().filter(NewInstanceNode.class).isEmpty()); - Assert.assertTrue("partial escape analysis should have removed all NewArrayNode allocations", result.getNodes().filter(NewArrayNode.class).isEmpty()); + Assert.assertTrue("partial escape analysis should have removed all NewInstanceNode allocations", graph.getNodes().filter(NewInstanceNode.class).isEmpty()); + Assert.assertTrue("partial escape analysis should have removed all NewArrayNode allocations", graph.getNodes().filter(NewArrayNode.class).isEmpty()); - NodesToDoubles nodeProbabilities = new ComputeProbabilityClosure(result).apply(); + NodesToDoubles nodeProbabilities = new ComputeProbabilityClosure(graph).apply(); double probabilitySum = 0; int materializeCount = 0; - for (CommitAllocationNode materialize : result.getNodes().filter(CommitAllocationNode.class)) { + for (CommitAllocationNode materialize : graph.getNodes().filter(CommitAllocationNode.class)) { probabilitySum += nodeProbabilities.get(materialize) * materialize.getVirtualObjects().size(); materializeCount += materialize.getVirtualObjects().size(); } Assert.assertEquals("unexpected number of MaterializeObjectNodes", expectedCount, materializeCount); Assert.assertEquals("unexpected probability of MaterializeObjectNodes", expectedProbability, probabilitySum, 0.01); - for (Node node : result.getNodes()) { + for (Node node : graph.getNodes()) { for (Class clazz : invalidNodeClasses) { Assert.assertFalse("instance of invalid class: " + clazz.getSimpleName(), clazz.isInstance(node) && node.usages().isNotEmpty()); } } } catch (AssertionError e) { - TypeSystemTest.outputGraph(result, snippet + ": " + e.getMessage()); + TypeSystemTest.outputGraph(graph, snippet + ": " + e.getMessage()); throw e; } } - private StructuredGraph processMethod(final String snippet) { - return Debug.scope("PartialEscapeAnalysisTest " + snippet, new DebugDumpScope(snippet), new Callable() { - - @Override - public StructuredGraph call() { - StructuredGraph graph = parse(snippet); - - Assumptions assumptions = new Assumptions(false); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); - new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); - new DeadCodeEliminationPhase().apply(graph); - new CanonicalizerPhase(true).apply(graph, context); - new PartialEscapePhase(false, new CanonicalizerPhase(true)).apply(graph, context); - - for (MergeNode merge : graph.getNodes(MergeNode.class)) { - merge.setStateAfter(null); - } - new DeadCodeEliminationPhase().apply(graph); - new CanonicalizerPhase(true).apply(graph, context); - return graph; - } - }); - } } diff -r 7f55cdeec6af -r f40b8d0d9dcb graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/UnsafeEATest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/UnsafeEATest.java Mon Oct 28 15:25:27 2013 +0100 @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2011, 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.test.ea; + +import org.junit.*; + +import sun.misc.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; + +public class UnsafeEATest extends EATestBase { + + public static int zero = 0; + + private static final Unsafe unsafe; + private static final long fieldOffsetX; + private static final long fieldOffsetY; + + static { + unsafe = UnsafeAccess.unsafe; + try { + fieldOffsetX = unsafe.objectFieldOffset(TestClassInt.class.getField("x")); + fieldOffsetY = unsafe.objectFieldOffset(TestClassInt.class.getField("y")); + assert fieldOffsetY == fieldOffsetX + 4; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Test + public void testSimpleInt() { + testEscapeAnalysis("testSimpleIntSnippet", Constant.forInt(101), false); + } + + public static int testSimpleIntSnippet() { + TestClassInt x = new TestClassInt(); + unsafe.putInt(x, fieldOffsetX, 101); + return unsafe.getInt(x, fieldOffsetX); + } + + @Test + public void testMaterializedInt() { + test("testMaterializedIntSnippet"); + } + + public static TestClassInt testMaterializedIntSnippet() { + TestClassInt x = new TestClassInt(); + unsafe.putInt(x, fieldOffsetX, 101); + return x; + } + + @Test + public void testSimpleDouble() { + testEscapeAnalysis("testSimpleDoubleSnippet", Constant.forDouble(10.1), false); + } + + public static double testSimpleDoubleSnippet() { + TestClassInt x = new TestClassInt(); + unsafe.putDouble(x, fieldOffsetX, 10.1); + return unsafe.getDouble(x, fieldOffsetX); + } + + @Test + public void testMergedDouble() { + testEscapeAnalysis("testMergedDoubleSnippet", null, false); + Assert.assertTrue(returnNode.result() instanceof PhiNode); + PhiNode phi = (PhiNode) returnNode.result(); + Assert.assertTrue(phi.valueAt(0) instanceof LoadFieldNode); + Assert.assertTrue(phi.valueAt(1) instanceof LoadFieldNode); + } + + public static double testMergedDoubleSnippet(boolean a) { + TestClassInt x; + if (a) { + x = new TestClassInt(0, 0); + unsafe.putDouble(x, fieldOffsetX, doubleField); + } else { + x = new TestClassInt(); + unsafe.putDouble(x, fieldOffsetX, doubleField2); + } + return unsafe.getDouble(x, fieldOffsetX); + } + + @Test + public void testMaterializedDouble() { + test("testMaterializedDoubleSnippet"); + } + + public static TestClassInt testMaterializedDoubleSnippet() { + TestClassInt x = new TestClassInt(); + unsafe.putDouble(x, fieldOffsetX, 10.1); + return x; + } + + @Test + public void testDeoptDoubleVar() { + test("testDeoptDoubleVarSnippet"); + } + + public static double doubleField = 10.1e99; + public static double doubleField2; + + public static TestClassInt testDeoptDoubleVarSnippet() { + TestClassInt x = new TestClassInt(); + unsafe.putDouble(x, fieldOffsetX, doubleField); + doubleField2 = 123; + try { + doubleField = ((int) unsafe.getDouble(x, fieldOffsetX)) / zero; + } catch (RuntimeException e) { + return x; + } + return x; + } + + @Test + public void testDeoptDoubleConstant() { + test("testDeoptDoubleConstantSnippet"); + } + + public static TestClassInt testDeoptDoubleConstantSnippet() { + TestClassInt x = new TestClassInt(); + unsafe.putDouble(x, fieldOffsetX, 10.123); + doubleField2 = 123; + try { + doubleField = ((int) unsafe.getDouble(x, fieldOffsetX)) / zero; + } catch (RuntimeException e) { + return x; + } + return x; + } + + @Test + public void testDeoptLongVar() { + test("testDeoptLongVarSnippet"); + } + + public static long longField = 0x133443218aaaffffL; + public static long longField2; + + public static TestClassInt testDeoptLongVarSnippet() { + TestClassInt x = new TestClassInt(); + unsafe.putLong(x, fieldOffsetX, longField); + longField2 = 123; + try { + longField = unsafe.getLong(x, fieldOffsetX) / zero; + } catch (RuntimeException e) { + return x; + } + return x; + } + + @Test + public void testDeoptLongConstant() { + test("testDeoptLongConstantSnippet"); + } + + public static TestClassInt testDeoptLongConstantSnippet() { + TestClassInt x = new TestClassInt(); + unsafe.putLong(x, fieldOffsetX, 0x2222222210123L); + longField2 = 123; + try { + longField = unsafe.getLong(x, fieldOffsetX) / zero; + } catch (RuntimeException e) { + return x; + } + return x; + } +}