1 /*
  2  * Copyright (c) 2016, 2018, 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 
 24 /*
 25  * @test
 26  * @bug 8155781
 27  * @modules java.base/jdk.internal.misc
 28  *
 29  * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
 30  *                                 -XX:-TieredCompilation -Xbatch
 31  *                                 -XX:+UseCompressedOops -XX:+UseCompressedClassPointers
 32  *                                 -XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test*
 33  *                                 compiler.unsafe.OpaqueAccesses
 34  * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
 35  *                                 -XX:-TieredCompilation -Xbatch
 36  *                                 -XX:+UseCompressedOops -XX:-UseCompressedClassPointers
 37  *                                 -XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test*
 38  *                                 compiler.unsafe.OpaqueAccesses
 39  * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
 40  *                                 -XX:-TieredCompilation -Xbatch
 41  *                                 -XX:-UseCompressedOops -XX:+UseCompressedClassPointers
 42  *                                 -XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test*
 43  *                                 compiler.unsafe.OpaqueAccesses
 44  * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
 45  *                                 -XX:-TieredCompilation -Xbatch
 46  *                                 -XX:-UseCompressedOops -XX:-UseCompressedClassPointers
 47  *                                 -XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test*
 48  *                                 compiler.unsafe.OpaqueAccesses
 49  */
 50 package compiler.unsafe;
 51 
 52 import jdk.internal.misc.Unsafe;
 53 
 54 import java.lang.reflect.Field;
 55 
 56 public class OpaqueAccesses {
 57     private static final Unsafe UNSAFE = Unsafe.getUnsafe();
 58 
 59     private static final Object INSTANCE = new OpaqueAccesses();
 60 
 61     private static final Object[] ARRAY = new Object[10];
 62 
 63     private static final long F_OFFSET;
 64     private static final long E_OFFSET;
 65 
 66     static {
 67         try {
 68             Field field = OpaqueAccesses.class.getDeclaredField("f");
 69             F_OFFSET = UNSAFE.objectFieldOffset(field);
 70 
 71             E_OFFSET = UNSAFE.arrayBaseOffset(ARRAY.getClass());
 72         } catch (NoSuchFieldException e) {
 73             throw new Error(e);
 74         }
 75     }
 76 
 77     private Object f = new Object();
 78     private long l1, l2;
 79 
 80     static Object testFixedOffsetField(Object o) {
 81         return UNSAFE.getReference(o, F_OFFSET);
 82     }
 83 
 84     static int testFixedOffsetHeader0(Object o) {
 85         return UNSAFE.getInt(o, 0);
 86     }
 87 
 88     static int testFixedOffsetHeader4(Object o) {
 89         return UNSAFE.getInt(o, 4);
 90     }
 91 
 92     static int testFixedOffsetHeader8(Object o) {
 93         return UNSAFE.getInt(o, 8);
 94     }
 95 
 96     static int testFixedOffsetHeader12(Object o) {
 97         return UNSAFE.getInt(o, 12);
 98     }
 99 
100     static int testFixedOffsetHeader16(Object o) {
101         return UNSAFE.getInt(o, 16);
102     }
103 
104     static int testFixedOffsetHeader17(Object o) {
105         return UNSAFE.getIntUnaligned(o, 17);
106     }
107 
108     static Object testFixedBase(long off) {
109         return UNSAFE.getReference(INSTANCE, off);
110     }
111 
112     static Object testOpaque(Object o, long off) {
113         return UNSAFE.getReference(o, off);
114     }
115 
116     static int testFixedOffsetHeaderArray0(Object[] arr) {
117         return UNSAFE.getInt(arr, 0);
118     }
119 
120     static int testFixedOffsetHeaderArray4(Object[] arr) {
121         return UNSAFE.getInt(arr, 4);
122     }
123 
124     static int testFixedOffsetHeaderArray8(Object[] arr) {
125         return UNSAFE.getInt(arr, 8);
126     }
127 
128     static int testFixedOffsetHeaderArray12(Object[] arr) {
129         return UNSAFE.getInt(arr, 12);
130     }
131 
132     static int testFixedOffsetHeaderArray16(Object[] arr) {
133         return UNSAFE.getInt(arr, 16);
134     }
135 
136     static int testFixedOffsetHeaderArray17(Object[] arr) {
137         return UNSAFE.getIntUnaligned(arr, 17);
138     }
139 
140     static Object testFixedOffsetArray(Object[] arr) {
141         return UNSAFE.getReference(arr, E_OFFSET);
142     }
143 
144     static Object testFixedBaseArray(long off) {
145         return UNSAFE.getReference(ARRAY, off);
146     }
147 
148     static Object testOpaqueArray(Object[] o, long off) {
149         return UNSAFE.getReference(o, off);
150     }
151 
152     static final long ADDR = UNSAFE.allocateMemory(10);
153     static boolean flag;
154 
155     static int testMixedAccess() {
156         flag = !flag;
157         Object o = (flag ? INSTANCE : null);
158         long off = (flag ? F_OFFSET : ADDR);
159         return UNSAFE.getInt(o, off);
160     }
161 
162     public static void main(String[] args) {
163         for (int i = 0; i < 20_000; i++) {
164             // Instance
165             testFixedOffsetField(INSTANCE);
166             testFixedOffsetHeader0(INSTANCE);
167             testFixedOffsetHeader4(INSTANCE);
168             testFixedOffsetHeader8(INSTANCE);
169             testFixedOffsetHeader12(INSTANCE);
170             testFixedOffsetHeader16(INSTANCE);
171             testFixedOffsetHeader17(INSTANCE);
172             testFixedBase(F_OFFSET);
173             testOpaque(INSTANCE, F_OFFSET);
174             testMixedAccess();
175 
176             // Array
177             testFixedOffsetHeaderArray0(ARRAY);
178             testFixedOffsetHeaderArray4(ARRAY);
179             testFixedOffsetHeaderArray8(ARRAY);
180             testFixedOffsetHeaderArray12(ARRAY);
181             testFixedOffsetHeaderArray16(ARRAY);
182             testFixedOffsetHeaderArray17(ARRAY);
183             testFixedOffsetArray(ARRAY);
184             testFixedBaseArray(E_OFFSET);
185             testOpaqueArray(ARRAY, E_OFFSET);
186         }
187         System.out.println("TEST PASSED");
188     }
189 }