src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/UnsafeEATest.java
changeset 47798 9fe9292f5931
parent 47216 71c04702a3d5
child 50858 2d3e99a72541
equal deleted inserted replaced
47797:d20059c27430 47798:9fe9292f5931
    20  * or visit www.oracle.com if you need additional information or have any
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    21  * questions.
    22  */
    22  */
    23 package org.graalvm.compiler.core.test.ea;
    23 package org.graalvm.compiler.core.test.ea;
    24 
    24 
    25 import jdk.vm.ci.meta.JavaConstant;
    25 import java.nio.ByteBuffer;
    26 
    26 
       
    27 import org.graalvm.compiler.api.directives.GraalDirectives;
       
    28 import org.graalvm.compiler.graph.Graph;
       
    29 import org.graalvm.compiler.graph.Node;
       
    30 import org.graalvm.compiler.nodes.NamedLocationIdentity;
       
    31 import org.graalvm.compiler.nodes.PhiNode;
       
    32 import org.graalvm.compiler.nodes.ValuePhiNode;
       
    33 import org.graalvm.compiler.nodes.calc.UnpackEndianHalfNode;
       
    34 import org.graalvm.compiler.nodes.extended.RawLoadNode;
       
    35 import org.graalvm.compiler.nodes.extended.RawStoreNode;
       
    36 import org.graalvm.compiler.nodes.extended.UnsafeAccessNode;
       
    37 import org.graalvm.compiler.nodes.java.LoadFieldNode;
       
    38 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
    27 import org.junit.Assert;
    39 import org.junit.Assert;
    28 import org.junit.Test;
    40 import org.junit.Test;
    29 
    41 
    30 import org.graalvm.compiler.nodes.PhiNode;
    42 import jdk.vm.ci.meta.JavaConstant;
    31 import org.graalvm.compiler.nodes.ValuePhiNode;
    43 import jdk.vm.ci.meta.JavaKind;
    32 import org.graalvm.compiler.nodes.java.LoadFieldNode;
    44 import jdk.vm.ci.meta.ResolvedJavaMethod;
    33 
    45 
    34 public class UnsafeEATest extends EATestBase {
    46 public class UnsafeEATest extends EATestBase {
    35 
    47 
    36     public static int zero = 0;
    48     public static int zero = 0;
    37 
    49 
    54         } catch (Exception e) {
    66         } catch (Exception e) {
    55             throw new RuntimeException(e);
    67             throw new RuntimeException(e);
    56         }
    68         }
    57     }
    69     }
    58 
    70 
       
    71     @Override
       
    72     protected void testEscapeAnalysis(String snippet, JavaConstant expectedConstantResult, boolean iterativeEscapeAnalysis) {
       
    73         // Exercise both a graph containing UnsafeAccessNodes and one which has been possibly been
       
    74         // canonicalized into AccessFieldNodes.
       
    75         testingUnsafe = true;
       
    76         super.testEscapeAnalysis(snippet, expectedConstantResult, iterativeEscapeAnalysis);
       
    77         testingUnsafe = false;
       
    78         super.testEscapeAnalysis(snippet, expectedConstantResult, iterativeEscapeAnalysis);
       
    79         if (expectedConstantResult != null) {
       
    80             // Check that a compiled version of this method returns the same value if we expect a
       
    81             // constant result.
       
    82             ResolvedJavaMethod method = getResolvedJavaMethod(snippet);
       
    83             JavaKind[] javaKinds = method.getSignature().toParameterKinds(false);
       
    84             Object[] args = new Object[javaKinds.length];
       
    85             int i = 0;
       
    86             for (JavaKind k : javaKinds) {
       
    87                 args[i++] = JavaConstant.defaultForKind(k).asBoxedPrimitive();
       
    88             }
       
    89             Result result = executeExpected(method, null, args);
       
    90             assertTrue(result.returnValue.equals(expectedConstantResult.asBoxedPrimitive()));
       
    91         }
       
    92     }
       
    93 
       
    94     @Override
       
    95     protected void canonicalizeGraph() {
       
    96         if (testingUnsafe) {
       
    97             // For testing purposes we'd like to ensure that our raw unsafe operations stay as
       
    98             // unsafe nodes, so force them to appear to have LocationIdentity.any to disable
       
    99             // transformation into field access nodes.
       
   100             for (Node node : graph.getNodes().filter(x -> x instanceof UnsafeAccessNode).snapshot()) {
       
   101                 if (node instanceof RawStoreNode) {
       
   102                     RawStoreNode store = (RawStoreNode) node;
       
   103                     RawStoreNode newStore = graph.add(new RawStoreNode(store.object(), store.offset(), store.value(), store.accessKind(), NamedLocationIdentity.any(),
       
   104                                     store.needsBarrier(), store.stateAfter(), true));
       
   105                     graph.replaceFixedWithFixed(store, newStore);
       
   106                 } else if (node instanceof RawLoadNode) {
       
   107                     RawLoadNode load = (RawLoadNode) node;
       
   108                     RawLoadNode newLoad = graph.add(new RawLoadNode(load.object(), load.offset(), load.accessKind(), NamedLocationIdentity.any(),
       
   109                                     true));
       
   110                     graph.replaceFixedWithFixed(load, newLoad);
       
   111                 }
       
   112             }
       
   113         }
       
   114         super.canonicalizeGraph();
       
   115     }
       
   116 
       
   117     @Override
       
   118     protected void postEACanonicalizeGraph() {
       
   119         // Simplify any UnpackEndianHalfNode so we end up with constants.
       
   120         Graph.Mark mark = graph.getMark();
       
   121         for (UnpackEndianHalfNode node : graph.getNodes().filter(UnpackEndianHalfNode.class)) {
       
   122             node.lower(getTarget().arch.getByteOrder());
       
   123         }
       
   124         new CanonicalizerPhase().applyIncremental(graph, context, mark);
       
   125     }
       
   126 
       
   127     private boolean testingUnsafe;
       
   128 
    59     @Test
   129     @Test
    60     public void testSimpleInt() {
   130     public void testSimpleInt() {
    61         testEscapeAnalysis("testSimpleIntSnippet", JavaConstant.forInt(101), false);
   131         testEscapeAnalysis("testSimpleIntSnippet", JavaConstant.forInt(101), false);
    62     }
   132     }
    63 
   133 
    85 
   155 
    86     public static double testSimpleDoubleSnippet() {
   156     public static double testSimpleDoubleSnippet() {
    87         TestClassInt x = new TestClassInt();
   157         TestClassInt x = new TestClassInt();
    88         UNSAFE.putDouble(x, fieldOffset1, 10.1);
   158         UNSAFE.putDouble(x, fieldOffset1, 10.1);
    89         return UNSAFE.getDouble(x, fieldOffset1);
   159         return UNSAFE.getDouble(x, fieldOffset1);
       
   160     }
       
   161 
       
   162     @Test
       
   163     public void testSimpleDoubleOverwriteWithInt() {
       
   164         testEscapeAnalysis("testSimpleDoubleOverwriteWithIntSnippet", JavaConstant.forInt(10), false);
       
   165     }
       
   166 
       
   167     public static int testSimpleDoubleOverwriteWithIntSnippet() {
       
   168         TestClassInt x = new TestClassInt();
       
   169         UNSAFE.putDouble(x, fieldOffset1, 10.1);
       
   170         UNSAFE.putInt(x, fieldOffset1, 10);
       
   171         return UNSAFE.getInt(x, fieldOffset1);
       
   172     }
       
   173 
       
   174     @Test
       
   175     public void testSimpleDoubleOverwriteWithSecondInt() {
       
   176         ByteBuffer bb = ByteBuffer.allocate(8).order(getTarget().arch.getByteOrder());
       
   177         bb.putDouble(10.1);
       
   178         int value = bb.getInt(4);
       
   179 
       
   180         testEscapeAnalysis("testSimpleDoubleOverwriteWithSecondIntSnippet", JavaConstant.forInt(value), false);
       
   181     }
       
   182 
       
   183     public static int testSimpleDoubleOverwriteWithSecondIntSnippet() {
       
   184         TestClassInt x = new TestClassInt();
       
   185         UNSAFE.putDouble(x, fieldOffset1, 10.1);
       
   186         UNSAFE.putInt(x, fieldOffset1, 10);
       
   187         return UNSAFE.getInt(x, fieldOffset2);
       
   188     }
       
   189 
       
   190     @Test
       
   191     public void testSimpleDoubleOverwriteWithFirstInt() {
       
   192         ByteBuffer bb = ByteBuffer.allocate(8).order(getTarget().arch.getByteOrder());
       
   193         bb.putDouble(10.1);
       
   194         int value = bb.getInt(0);
       
   195 
       
   196         testEscapeAnalysis("testSimpleDoubleOverwriteWithFirstIntSnippet", JavaConstant.forInt(value), false);
       
   197     }
       
   198 
       
   199     public static int testSimpleDoubleOverwriteWithFirstIntSnippet() {
       
   200         TestClassInt x = new TestClassInt();
       
   201         UNSAFE.putDouble(x, fieldOffset1, 10.1);
       
   202         UNSAFE.putInt(x, fieldOffset2, 10);
       
   203         return UNSAFE.getInt(x, fieldOffset1);
       
   204     }
       
   205 
       
   206     @Test
       
   207     public void testSimpleLongOverwriteWithSecondInt() {
       
   208         ByteBuffer bb = ByteBuffer.allocate(8).order(getTarget().arch.getByteOrder());
       
   209         bb.putLong(0, 0x1122334455667788L);
       
   210         int value = bb.getInt(4);
       
   211 
       
   212         testEscapeAnalysis("testSimpleLongOverwriteWithSecondIntSnippet", JavaConstant.forInt(value), false);
       
   213     }
       
   214 
       
   215     public static int testSimpleLongOverwriteWithSecondIntSnippet() {
       
   216         TestClassInt x = new TestClassInt();
       
   217         UNSAFE.putLong(x, fieldOffset1, 0x1122334455667788L);
       
   218         UNSAFE.putInt(x, fieldOffset1, 10);
       
   219         return UNSAFE.getInt(x, fieldOffset2);
       
   220     }
       
   221 
       
   222     @Test
       
   223     public void testSimpleLongOverwriteWithFirstInt() {
       
   224         ByteBuffer bb = ByteBuffer.allocate(8).order(getTarget().arch.getByteOrder());
       
   225         bb.putLong(0, 0x1122334455667788L);
       
   226         int value = bb.getInt(0);
       
   227 
       
   228         testEscapeAnalysis("testSimpleLongOverwriteWithFirstIntSnippet", JavaConstant.forInt(value), false);
       
   229     }
       
   230 
       
   231     public static int testSimpleLongOverwriteWithFirstIntSnippet() {
       
   232         TestClassInt x = new TestClassInt();
       
   233         UNSAFE.putLong(x, fieldOffset1, 0x1122334455667788L);
       
   234         UNSAFE.putInt(x, fieldOffset2, 10);
       
   235         return UNSAFE.getInt(x, fieldOffset1);
    90     }
   236     }
    91 
   237 
    92     @Test
   238     @Test
    93     public void testMergedDouble() {
   239     public void testMergedDouble() {
    94         testEscapeAnalysis("testMergedDoubleSnippet", null, false);
   240         testEscapeAnalysis("testMergedDoubleSnippet", null, false);
   109             UNSAFE.putDouble(x, fieldOffset1, doubleField2);
   255             UNSAFE.putDouble(x, fieldOffset1, doubleField2);
   110         }
   256         }
   111         return UNSAFE.getDouble(x, fieldOffset1);
   257         return UNSAFE.getDouble(x, fieldOffset1);
   112     }
   258     }
   113 
   259 
       
   260     static class ExtendedTestClassInt extends TestClassInt {
       
   261         public long l;
       
   262     }
       
   263 
       
   264     @Test
       
   265     public void testMergedVirtualObjects() {
       
   266         testEscapeAnalysis("testMergedVirtualObjectsSnippet", null, false);
       
   267     }
       
   268 
       
   269     public static TestClassInt testMergedVirtualObjectsSnippet(int value) {
       
   270         TestClassInt x;
       
   271         if (value == 1) {
       
   272             x = new TestClassInt();
       
   273             UNSAFE.putDouble(x, fieldOffset1, 10);
       
   274         } else {
       
   275             x = new TestClassInt();
       
   276             UNSAFE.putInt(x, fieldOffset1, 0);
       
   277         }
       
   278         UNSAFE.putInt(x, fieldOffset1, 0);
       
   279         if (value == 2) {
       
   280             UNSAFE.putInt(x, fieldOffset2, 0);
       
   281         }
       
   282         GraalDirectives.deoptimizeAndInvalidate();
       
   283         return x;
       
   284     }
       
   285 
   114     @Test
   286     @Test
   115     public void testMaterializedDouble() {
   287     public void testMaterializedDouble() {
   116         test("testMaterializedDoubleSnippet");
   288         test("testMaterializedDoubleSnippet");
   117     }
   289     }
   118 
   290