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     private static final long byteArrayBaseOffset;
  42     private static final long intArrayBaseOffset;
  43     private static final long longArrayBaseOffset;
  44 
  45     static {
  46         try {
  47             long localFieldOffset1 = UNSAFE.objectFieldOffset(TestClassInt.class.getField("x"));
  48             // Make the fields 8 byte aligned (Required for testing setLong on Architectures which
  49             // does not support unaligned memory access
  50             if (localFieldOffset1 % 8 == 0) {
  51                 fieldOffset1 = localFieldOffset1;
  52                 fieldOffset2 = UNSAFE.objectFieldOffset(TestClassInt.class.getField("y"));
  53             } else {
  54                 fieldOffset1 = UNSAFE.objectFieldOffset(TestClassInt.class.getField("y"));
  55                 fieldOffset2 = UNSAFE.objectFieldOffset(TestClassInt.class.getField("z"));
  56             }
  57             assert fieldOffset2 == fieldOffset1 + 4;
  58             byteArrayBaseOffset = UNSAFE.arrayBaseOffset(byte[].class);
  59             intArrayBaseOffset = UNSAFE.arrayBaseOffset(int[].class);
  60             longArrayBaseOffset = UNSAFE.arrayBaseOffset(long[].class);
  61         } catch (Exception e) {
  62             throw new RuntimeException(e);
  63         }
  64     }
  65 
  66     @Test
  67     public void testSimpleInt() {
  68         testEscapeAnalysis("testSimpleIntSnippet", JavaConstant.forInt(101), false);
  69     }
  70 
  71     public static int testSimpleIntSnippet() {
  72         TestClassInt x = new TestClassInt();
  73         UNSAFE.putInt(x, fieldOffset1, 101);
  74         return UNSAFE.getInt(x, fieldOffset1);
  75     }
  76 
  77     @Test
  78     public void testMaterializedInt() {
  79         test("testMaterializedIntSnippet");
  80     }
  81 
  82     public static TestClassInt testMaterializedIntSnippet() {
  83         TestClassInt x = new TestClassInt();
  84         UNSAFE.putInt(x, fieldOffset1, 101);
  85         return x;
  86     }
  87 
  88     @Test
  89     public void testSimpleDouble() {
  90         testEscapeAnalysis("testSimpleDoubleSnippet", JavaConstant.forDouble(10.1), false);
  91     }
  92 
  93     public static double testSimpleDoubleSnippet() {
  94         TestClassInt x = new TestClassInt();
  95         UNSAFE.putDouble(x, fieldOffset1, 10.1);
  96         return UNSAFE.getDouble(x, fieldOffset1);
  97     }
  98 
  99     @Test
 100     public void testMergedDouble() {
 101         testEscapeAnalysis("testMergedDoubleSnippet", null, false);
 102         Assert.assertEquals(1, returnNodes.size());
 103         Assert.assertTrue(returnNodes.get(0).result() instanceof ValuePhiNode);
 104         PhiNode phi = (PhiNode) returnNodes.get(0).result();
 105         Assert.assertTrue(phi.valueAt(0) instanceof LoadFieldNode);
 106         Assert.assertTrue(phi.valueAt(1) instanceof LoadFieldNode);
 107     }
 108 
 109     public static double testMergedDoubleSnippet(boolean a) {
 110         TestClassInt x;
 111         if (a) {
 112             x = new TestClassInt(0, 0);
 113             UNSAFE.putDouble(x, fieldOffset1, doubleField);
 114         } else {
 115             x = new TestClassInt();
 116             UNSAFE.putDouble(x, fieldOffset1, doubleField2);
 117         }
 118         return UNSAFE.getDouble(x, fieldOffset1);
 119     }
 120 
 121     @Test
 122     public void testMaterializedDouble() {
 123         test("testMaterializedDoubleSnippet");
 124     }
 125 
 126     public static TestClassInt testMaterializedDoubleSnippet() {
 127         TestClassInt x = new TestClassInt();
 128         UNSAFE.putDouble(x, fieldOffset1, 10.1);
 129         return x;
 130     }
 131 
 132     @Test
 133     public void testDeoptDoubleVar() {
 134         test("testDeoptDoubleVarSnippet");
 135     }
 136 
 137     public static double doubleField = 10.1e99;
 138     public static double doubleField2;
 139 
 140     public static TestClassInt testDeoptDoubleVarSnippet() {
 141         TestClassInt x = new TestClassInt();
 142         UNSAFE.putDouble(x, fieldOffset1, doubleField);
 143         doubleField2 = 123;
 144         try {
 145             doubleField = ((int) UNSAFE.getDouble(x, fieldOffset1)) / zero;
 146         } catch (RuntimeException e) {
 147             return x;
 148         }
 149         return x;
 150     }
 151 
 152     @Test
 153     public void testDeoptDoubleConstant() {
 154         test("testDeoptDoubleConstantSnippet");
 155     }
 156 
 157     public static TestClassInt testDeoptDoubleConstantSnippet() {
 158         TestClassInt x = new TestClassInt();
 159         UNSAFE.putDouble(x, fieldOffset1, 10.123);
 160         doubleField2 = 123;
 161         try {
 162             doubleField = ((int) UNSAFE.getDouble(x, fieldOffset1)) / zero;
 163         } catch (RuntimeException e) {
 164             return x;
 165         }
 166         return x;
 167     }
 168 
 169     @Test
 170     public void testDeoptLongVar() {
 171         test("testDeoptLongVarSnippet");
 172     }
 173 
 174     public static long longField = 0x133443218aaaffffL;
 175     public static long longField2;
 176 
 177     public static TestClassInt testDeoptLongVarSnippet() {
 178         TestClassInt x = new TestClassInt();
 179         UNSAFE.putLong(x, fieldOffset1, longField);
 180         longField2 = 123;
 181         try {
 182             longField = UNSAFE.getLong(x, fieldOffset1) / zero;
 183         } catch (RuntimeException e) {
 184             return x;
 185         }
 186         return x;
 187     }
 188 
 189     @Test
 190     public void testDeoptLongConstant() {
 191         test("testDeoptLongConstantSnippet");
 192     }
 193 
 194     public static TestClassInt testDeoptLongConstantSnippet() {
 195         TestClassInt x = new TestClassInt();
 196         UNSAFE.putLong(x, fieldOffset1, 0x2222222210123L);
 197         longField2 = 123;
 198         try {
 199             longField = UNSAFE.getLong(x, fieldOffset1) / zero;
 200         } catch (RuntimeException e) {
 201             return x;
 202         }
 203         return x;
 204     }
 205 
 206     public static int testWriteIntToByteArraySnippet() {
 207         byte[] array = new byte[4];
 208         UNSAFE.putInt(array, byteArrayBaseOffset, 0x01020304);
 209         return array[0];
 210     }
 211 
 212     @Test
 213     public void testWriteIntToByteArray() {
 214         test("testWriteIntToByteArraySnippet");
 215     }
 216 
 217     public static byte testWriteSignedExtendedByteToByteArraySnippet(byte b) {
 218         byte[] array = new byte[4];
 219         array[0] = 0x01;
 220         array[1] = 0x02;
 221         array[2] = 0x03;
 222         array[3] = 0x04;
 223         UNSAFE.putInt(array, byteArrayBaseOffset, b);
 224         return array[3];
 225     }
 226 
 227     @Test
 228     public void testWriteSignedExtendedByteToByteArray() {
 229         test("testWriteSignedExtendedByteToByteArraySnippet", (byte) 0);
 230     }
 231 
 232     public static int testWriteLongToIntArraySnippet() {
 233         int[] array = new int[2];
 234         UNSAFE.putLong(array, intArrayBaseOffset, 0x0102030405060708L);
 235         return array[0];
 236     }
 237 
 238     @Test
 239     public void testWriteLongToIntArray() {
 240         test("testWriteLongToIntArraySnippet");
 241     }
 242 
 243     public static int testWriteByteToIntArraySnippet() {
 244         int[] array = new int[1];
 245         array[0] = 0x01020304;
 246         UNSAFE.putByte(array, intArrayBaseOffset, (byte) 0x05);
 247         return array[0];
 248     }
 249 
 250     @Test
 251     public void testWriteByteToIntArray() {
 252         test("testWriteByteToIntArraySnippet");
 253     }
 254 
 255     public static long testWriteIntToLongArraySnippet() {
 256         long[] array = new long[1];
 257         array[0] = 0x0102030405060708L;
 258         UNSAFE.putInt(array, longArrayBaseOffset, 0x04030201);
 259         return array[0];
 260     }
 261 
 262     @Test
 263     public void testWriteIntToLongArray() {
 264         test("testWriteIntToLongArraySnippet");
 265     }
 266 
 267     public static float testWriteFloatToIntArraySnippet() {
 268         float[] array = new float[1];
 269         UNSAFE.putInt(array, intArrayBaseOffset, Float.floatToRawIntBits(0.5f));
 270         return array[0];
 271     }
 272 
 273     @Test
 274     public void testWriteFloatToIntArray() {
 275         test("testWriteFloatToIntArraySnippet");
 276     }
 277 
 278 }