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 }