1 /*
   2  * Copyright (c) 2011, 2014, 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 package org.graalvm.compiler.core.test.ea;
  24 
  25 import jdk.vm.ci.meta.JavaConstant;
  26 
  27 import org.junit.Assert;
  28 import org.junit.Test;
  29 
  30 import org.graalvm.compiler.nodes.PhiNode;
  31 import org.graalvm.compiler.nodes.ValuePhiNode;
  32 import org.graalvm.compiler.nodes.java.LoadFieldNode;
  33 
  34 public class UnsafeEATest extends EATestBase {
  35 
  36     public static int zero = 0;
  37 
  38     private static final long fieldOffset1;
  39     private static final long fieldOffset2;
  40 
  41     static {
  42         try {
  43             long localFieldOffset1 = UNSAFE.objectFieldOffset(TestClassInt.class.getField("x"));
  44             // Make the fields 8 byte aligned (Required for testing setLong on Architectures which
  45             // does not support unaligned memory access
  46             if (localFieldOffset1 % 8 == 0) {
  47                 fieldOffset1 = localFieldOffset1;
  48                 fieldOffset2 = UNSAFE.objectFieldOffset(TestClassInt.class.getField("y"));
  49             } else {
  50                 fieldOffset1 = UNSAFE.objectFieldOffset(TestClassInt.class.getField("y"));
  51                 fieldOffset2 = UNSAFE.objectFieldOffset(TestClassInt.class.getField("z"));
  52             }
  53             assert fieldOffset2 == fieldOffset1 + 4;
  54         } catch (Exception e) {
  55             throw new RuntimeException(e);
  56         }
  57     }
  58 
  59     @Test
  60     public void testSimpleInt() {
  61         testEscapeAnalysis("testSimpleIntSnippet", JavaConstant.forInt(101), false);
  62     }
  63 
  64     public static int testSimpleIntSnippet() {
  65         TestClassInt x = new TestClassInt();
  66         UNSAFE.putInt(x, fieldOffset1, 101);
  67         return UNSAFE.getInt(x, fieldOffset1);
  68     }
  69 
  70     @Test
  71     public void testMaterializedInt() {
  72         test("testMaterializedIntSnippet");
  73     }
  74 
  75     public static TestClassInt testMaterializedIntSnippet() {
  76         TestClassInt x = new TestClassInt();
  77         UNSAFE.putInt(x, fieldOffset1, 101);
  78         return x;
  79     }
  80 
  81     @Test
  82     public void testSimpleDouble() {
  83         testEscapeAnalysis("testSimpleDoubleSnippet", JavaConstant.forDouble(10.1), false);
  84     }
  85 
  86     public static double testSimpleDoubleSnippet() {
  87         TestClassInt x = new TestClassInt();
  88         UNSAFE.putDouble(x, fieldOffset1, 10.1);
  89         return UNSAFE.getDouble(x, fieldOffset1);
  90     }
  91 
  92     @Test
  93     public void testMergedDouble() {
  94         testEscapeAnalysis("testMergedDoubleSnippet", null, false);
  95         Assert.assertEquals(1, returnNodes.size());
  96         Assert.assertTrue(returnNodes.get(0).result() instanceof ValuePhiNode);
  97         PhiNode phi = (PhiNode) returnNodes.get(0).result();
  98         Assert.assertTrue(phi.valueAt(0) instanceof LoadFieldNode);
  99         Assert.assertTrue(phi.valueAt(1) instanceof LoadFieldNode);
 100     }
 101 
 102     public static double testMergedDoubleSnippet(boolean a) {
 103         TestClassInt x;
 104         if (a) {
 105             x = new TestClassInt(0, 0);
 106             UNSAFE.putDouble(x, fieldOffset1, doubleField);
 107         } else {
 108             x = new TestClassInt();
 109             UNSAFE.putDouble(x, fieldOffset1, doubleField2);
 110         }
 111         return UNSAFE.getDouble(x, fieldOffset1);
 112     }
 113 
 114     @Test
 115     public void testMaterializedDouble() {
 116         test("testMaterializedDoubleSnippet");
 117     }
 118 
 119     public static TestClassInt testMaterializedDoubleSnippet() {
 120         TestClassInt x = new TestClassInt();
 121         UNSAFE.putDouble(x, fieldOffset1, 10.1);
 122         return x;
 123     }
 124 
 125     @Test
 126     public void testDeoptDoubleVar() {
 127         test("testDeoptDoubleVarSnippet");
 128     }
 129 
 130     public static double doubleField = 10.1e99;
 131     public static double doubleField2;
 132 
 133     public static TestClassInt testDeoptDoubleVarSnippet() {
 134         TestClassInt x = new TestClassInt();
 135         UNSAFE.putDouble(x, fieldOffset1, doubleField);
 136         doubleField2 = 123;
 137         try {
 138             doubleField = ((int) UNSAFE.getDouble(x, fieldOffset1)) / zero;
 139         } catch (RuntimeException e) {
 140             return x;
 141         }
 142         return x;
 143     }
 144 
 145     @Test
 146     public void testDeoptDoubleConstant() {
 147         test("testDeoptDoubleConstantSnippet");
 148     }
 149 
 150     public static TestClassInt testDeoptDoubleConstantSnippet() {
 151         TestClassInt x = new TestClassInt();
 152         UNSAFE.putDouble(x, fieldOffset1, 10.123);
 153         doubleField2 = 123;
 154         try {
 155             doubleField = ((int) UNSAFE.getDouble(x, fieldOffset1)) / zero;
 156         } catch (RuntimeException e) {
 157             return x;
 158         }
 159         return x;
 160     }
 161 
 162     @Test
 163     public void testDeoptLongVar() {
 164         test("testDeoptLongVarSnippet");
 165     }
 166 
 167     public static long longField = 0x133443218aaaffffL;
 168     public static long longField2;
 169 
 170     public static TestClassInt testDeoptLongVarSnippet() {
 171         TestClassInt x = new TestClassInt();
 172         UNSAFE.putLong(x, fieldOffset1, longField);
 173         longField2 = 123;
 174         try {
 175             longField = UNSAFE.getLong(x, fieldOffset1) / zero;
 176         } catch (RuntimeException e) {
 177             return x;
 178         }
 179         return x;
 180     }
 181 
 182     @Test
 183     public void testDeoptLongConstant() {
 184         test("testDeoptLongConstantSnippet");
 185     }
 186 
 187     public static TestClassInt testDeoptLongConstantSnippet() {
 188         TestClassInt x = new TestClassInt();
 189         UNSAFE.putLong(x, fieldOffset1, 0x2222222210123L);
 190         longField2 = 123;
 191         try {
 192             longField = UNSAFE.getLong(x, fieldOffset1) / zero;
 193         } catch (RuntimeException e) {
 194             return x;
 195         }
 196         return x;
 197     }
 198 }