001/*
002 * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.compiler.test.ea;
024
025import jdk.internal.jvmci.common.*;
026import jdk.internal.jvmci.meta.*;
027
028import org.junit.*;
029
030import sun.misc.*;
031
032import com.oracle.graal.nodes.*;
033import com.oracle.graal.nodes.java.*;
034
035public class UnsafeEATest extends EATestBase {
036
037    public static int zero = 0;
038
039    private static final Unsafe unsafe;
040    private static final long fieldOffset1;
041    private static final long fieldOffset2;
042
043    static {
044        unsafe = UnsafeAccess.unsafe;
045        try {
046            long localFieldOffset1 = unsafe.objectFieldOffset(TestClassInt.class.getField("x"));
047            // Make the fields 8 byte aligned (Required for testing setLong on Architectures which
048            // does not support unaligned memory access
049            if (localFieldOffset1 % 8 == 0) {
050                fieldOffset1 = localFieldOffset1;
051                fieldOffset2 = unsafe.objectFieldOffset(TestClassInt.class.getField("y"));
052            } else {
053                fieldOffset1 = unsafe.objectFieldOffset(TestClassInt.class.getField("y"));
054                fieldOffset2 = unsafe.objectFieldOffset(TestClassInt.class.getField("z"));
055            }
056            assert fieldOffset2 == fieldOffset1 + 4;
057        } catch (Exception e) {
058            throw new RuntimeException(e);
059        }
060    }
061
062    @Test
063    public void testSimpleInt() {
064        testEscapeAnalysis("testSimpleIntSnippet", JavaConstant.forInt(101), false);
065    }
066
067    public static int testSimpleIntSnippet() {
068        TestClassInt x = new TestClassInt();
069        unsafe.putInt(x, fieldOffset1, 101);
070        return unsafe.getInt(x, fieldOffset1);
071    }
072
073    @Test
074    public void testMaterializedInt() {
075        test("testMaterializedIntSnippet");
076    }
077
078    public static TestClassInt testMaterializedIntSnippet() {
079        TestClassInt x = new TestClassInt();
080        unsafe.putInt(x, fieldOffset1, 101);
081        return x;
082    }
083
084    @Test
085    public void testSimpleDouble() {
086        testEscapeAnalysis("testSimpleDoubleSnippet", JavaConstant.forDouble(10.1), false);
087    }
088
089    public static double testSimpleDoubleSnippet() {
090        TestClassInt x = new TestClassInt();
091        unsafe.putDouble(x, fieldOffset1, 10.1);
092        return unsafe.getDouble(x, fieldOffset1);
093    }
094
095    @Test
096    public void testMergedDouble() {
097        testEscapeAnalysis("testMergedDoubleSnippet", null, false);
098        Assert.assertEquals(1, returnNodes.size());
099        Assert.assertTrue(returnNodes.get(0).result() instanceof ValuePhiNode);
100        PhiNode phi = (PhiNode) returnNodes.get(0).result();
101        Assert.assertTrue(phi.valueAt(0) instanceof LoadFieldNode);
102        Assert.assertTrue(phi.valueAt(1) instanceof LoadFieldNode);
103    }
104
105    public static double testMergedDoubleSnippet(boolean a) {
106        TestClassInt x;
107        if (a) {
108            x = new TestClassInt(0, 0);
109            unsafe.putDouble(x, fieldOffset1, doubleField);
110        } else {
111            x = new TestClassInt();
112            unsafe.putDouble(x, fieldOffset1, doubleField2);
113        }
114        return unsafe.getDouble(x, fieldOffset1);
115    }
116
117    @Test
118    public void testMaterializedDouble() {
119        test("testMaterializedDoubleSnippet");
120    }
121
122    public static TestClassInt testMaterializedDoubleSnippet() {
123        TestClassInt x = new TestClassInt();
124        unsafe.putDouble(x, fieldOffset1, 10.1);
125        return x;
126    }
127
128    @Test
129    public void testDeoptDoubleVar() {
130        test("testDeoptDoubleVarSnippet");
131    }
132
133    public static double doubleField = 10.1e99;
134    public static double doubleField2;
135
136    public static TestClassInt testDeoptDoubleVarSnippet() {
137        TestClassInt x = new TestClassInt();
138        unsafe.putDouble(x, fieldOffset1, doubleField);
139        doubleField2 = 123;
140        try {
141            doubleField = ((int) unsafe.getDouble(x, fieldOffset1)) / zero;
142        } catch (RuntimeException e) {
143            return x;
144        }
145        return x;
146    }
147
148    @Test
149    public void testDeoptDoubleConstant() {
150        test("testDeoptDoubleConstantSnippet");
151    }
152
153    public static TestClassInt testDeoptDoubleConstantSnippet() {
154        TestClassInt x = new TestClassInt();
155        unsafe.putDouble(x, fieldOffset1, 10.123);
156        doubleField2 = 123;
157        try {
158            doubleField = ((int) unsafe.getDouble(x, fieldOffset1)) / zero;
159        } catch (RuntimeException e) {
160            return x;
161        }
162        return x;
163    }
164
165    @Test
166    public void testDeoptLongVar() {
167        test("testDeoptLongVarSnippet");
168    }
169
170    public static long longField = 0x133443218aaaffffL;
171    public static long longField2;
172
173    public static TestClassInt testDeoptLongVarSnippet() {
174        TestClassInt x = new TestClassInt();
175        unsafe.putLong(x, fieldOffset1, longField);
176        longField2 = 123;
177        try {
178            longField = unsafe.getLong(x, fieldOffset1) / zero;
179        } catch (RuntimeException e) {
180            return x;
181        }
182        return x;
183    }
184
185    @Test
186    public void testDeoptLongConstant() {
187        test("testDeoptLongConstantSnippet");
188    }
189
190    public static TestClassInt testDeoptLongConstantSnippet() {
191        TestClassInt x = new TestClassInt();
192        unsafe.putLong(x, fieldOffset1, 0x2222222210123L);
193        longField2 = 123;
194        try {
195            longField = unsafe.getLong(x, fieldOffset1) / zero;
196        } catch (RuntimeException e) {
197            return x;
198        }
199        return x;
200    }
201}