1 /*
2  * Copyright (c) 2015, 2017, 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 8143628
27  * @summary Test unsafe access for byte
28  *
29  * @modules java.base/jdk.internal.misc:+open
30  * @run testng/othervm -Diters=100   -Xint                   compiler.unsafe.JdkInternalMiscUnsafeAccessTestByte
31  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 compiler.unsafe.JdkInternalMiscUnsafeAccessTestByte
32  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  compiler.unsafe.JdkInternalMiscUnsafeAccessTestByte
33  * @run testng/othervm -Diters=20000                         compiler.unsafe.JdkInternalMiscUnsafeAccessTestByte
34  */
35 
36 package compiler.unsafe;
37 
38 import org.testng.annotations.Test;
39 
40 import java.lang.reflect.Field;
41 
42 import static org.testng.Assert.*;
43 
44 public class JdkInternalMiscUnsafeAccessTestByte {
45     static final int ITERS = Integer.getInteger("iters", 1);
46     static final int WEAK_ATTEMPTS = Integer.getInteger("weakAttempts", 10);
47 
48     static final jdk.internal.misc.Unsafe UNSAFE;
49 
50     static final long V_OFFSET;
51 
52     static final Object STATIC_V_BASE;
53 
54     static final long STATIC_V_OFFSET;
55 
56     static int ARRAY_OFFSET;
57 
58     static int ARRAY_SHIFT;
59 
60     static {
61         try {
62             Field f = jdk.internal.misc.Unsafe.class.getDeclaredField("theUnsafe");
63             f.setAccessible(true);
64             UNSAFE = (jdk.internal.misc.Unsafe) f.get(null);
65         } catch (Exception e) {
66             throw new RuntimeException("Unable to get Unsafe instance.", e);
67         }
68 
69         try {
70             Field staticVField = JdkInternalMiscUnsafeAccessTestByte.class.getDeclaredField("static_v");
71             STATIC_V_BASE = UNSAFE.staticFieldBase(staticVField);
72             STATIC_V_OFFSET = UNSAFE.staticFieldOffset(staticVField);
73         } catch (Exception e) {
74             throw new RuntimeException(e);
75         }
76 
77         try {
78             Field vField = JdkInternalMiscUnsafeAccessTestByte.class.getDeclaredField("v");
79             V_OFFSET = UNSAFE.objectFieldOffset(vField);
80         } catch (Exception e) {
81             throw new RuntimeException(e);
82         }
83 
84         ARRAY_OFFSET = UNSAFE.arrayBaseOffset(byte[].class);
85         int ascale = UNSAFE.arrayIndexScale(byte[].class);
86         ARRAY_SHIFT = 31 - Integer.numberOfLeadingZeros(ascale);
87     }
88 
89     static byte static_v;
90 
91     byte v;
92 
93     @Test
testFieldInstance()94     public void testFieldInstance() {
95         JdkInternalMiscUnsafeAccessTestByte t = new JdkInternalMiscUnsafeAccessTestByte();
96         for (int c = 0; c < ITERS; c++) {
97             testAccess(t, V_OFFSET);
98         }
99     }
100 
101     @Test
testFieldStatic()102     public void testFieldStatic() {
103         for (int c = 0; c < ITERS; c++) {
104             testAccess(STATIC_V_BASE, STATIC_V_OFFSET);
105         }
106     }
107 
108     @Test
testArray()109     public void testArray() {
110         byte[] array = new byte[10];
111         for (int c = 0; c < ITERS; c++) {
112             for (int i = 0; i < array.length; i++) {
113                 testAccess(array, (((long) i) << ARRAY_SHIFT) + ARRAY_OFFSET);
114             }
115         }
116     }
117 
118     @Test
testArrayOffHeap()119     public void testArrayOffHeap() {
120         int size = 10;
121         long address = UNSAFE.allocateMemory(size << ARRAY_SHIFT);
122         try {
123             for (int c = 0; c < ITERS; c++) {
124                 for (int i = 0; i < size; i++) {
125                     testAccess(null, (((long) i) << ARRAY_SHIFT) + address);
126                 }
127             }
128         } finally {
129             UNSAFE.freeMemory(address);
130         }
131     }
132 
133     @Test
testArrayOffHeapDirect()134     public void testArrayOffHeapDirect() {
135         int size = 10;
136         long address = UNSAFE.allocateMemory(size << ARRAY_SHIFT);
137         try {
138             for (int c = 0; c < ITERS; c++) {
139                 for (int i = 0; i < size; i++) {
140                     testAccess((((long) i) << ARRAY_SHIFT) + address);
141                 }
142             }
143         } finally {
144             UNSAFE.freeMemory(address);
145         }
146     }
147 
testAccess(Object base, long offset)148     static void testAccess(Object base, long offset) {
149         // Plain
150         {
151             UNSAFE.putByte(base, offset, (byte)0x01);
152             byte x = UNSAFE.getByte(base, offset);
153             assertEquals(x, (byte)0x01, "set byte value");
154         }
155 
156         // Volatile
157         {
158             UNSAFE.putByteVolatile(base, offset, (byte)0x23);
159             byte x = UNSAFE.getByteVolatile(base, offset);
160             assertEquals(x, (byte)0x23, "putVolatile byte value");
161         }
162 
163 
164         // Lazy
165         {
166             UNSAFE.putByteRelease(base, offset, (byte)0x01);
167             byte x = UNSAFE.getByteAcquire(base, offset);
168             assertEquals(x, (byte)0x01, "putRelease byte value");
169         }
170 
171         // Opaque
172         {
173             UNSAFE.putByteOpaque(base, offset, (byte)0x23);
174             byte x = UNSAFE.getByteOpaque(base, offset);
175             assertEquals(x, (byte)0x23, "putOpaque byte value");
176         }
177 
178 
179         UNSAFE.putByte(base, offset, (byte)0x01);
180 
181         // Compare
182         {
183             boolean r = UNSAFE.compareAndSetByte(base, offset, (byte)0x01, (byte)0x23);
184             assertEquals(r, true, "success compareAndSet byte");
185             byte x = UNSAFE.getByte(base, offset);
186             assertEquals(x, (byte)0x23, "success compareAndSet byte value");
187         }
188 
189         {
190             boolean r = UNSAFE.compareAndSetByte(base, offset, (byte)0x01, (byte)0x45);
191             assertEquals(r, false, "failing compareAndSet byte");
192             byte x = UNSAFE.getByte(base, offset);
193             assertEquals(x, (byte)0x23, "failing compareAndSet byte value");
194         }
195 
196         // Advanced compare
197         {
198             byte r = UNSAFE.compareAndExchangeByte(base, offset, (byte)0x23, (byte)0x01);
199             assertEquals(r, (byte)0x23, "success compareAndExchange byte");
200             byte x = UNSAFE.getByte(base, offset);
201             assertEquals(x, (byte)0x01, "success compareAndExchange byte value");
202         }
203 
204         {
205             byte r = UNSAFE.compareAndExchangeByte(base, offset, (byte)0x23, (byte)0x45);
206             assertEquals(r, (byte)0x01, "failing compareAndExchange byte");
207             byte x = UNSAFE.getByte(base, offset);
208             assertEquals(x, (byte)0x01, "failing compareAndExchange byte value");
209         }
210 
211         {
212             byte r = UNSAFE.compareAndExchangeByteAcquire(base, offset, (byte)0x01, (byte)0x23);
213             assertEquals(r, (byte)0x01, "success compareAndExchangeAcquire byte");
214             byte x = UNSAFE.getByte(base, offset);
215             assertEquals(x, (byte)0x23, "success compareAndExchangeAcquire byte value");
216         }
217 
218         {
219             byte r = UNSAFE.compareAndExchangeByteAcquire(base, offset, (byte)0x01, (byte)0x45);
220             assertEquals(r, (byte)0x23, "failing compareAndExchangeAcquire byte");
221             byte x = UNSAFE.getByte(base, offset);
222             assertEquals(x, (byte)0x23, "failing compareAndExchangeAcquire byte value");
223         }
224 
225         {
226             byte r = UNSAFE.compareAndExchangeByteRelease(base, offset, (byte)0x23, (byte)0x01);
227             assertEquals(r, (byte)0x23, "success compareAndExchangeRelease byte");
228             byte x = UNSAFE.getByte(base, offset);
229             assertEquals(x, (byte)0x01, "success compareAndExchangeRelease byte value");
230         }
231 
232         {
233             byte r = UNSAFE.compareAndExchangeByteRelease(base, offset, (byte)0x23, (byte)0x45);
234             assertEquals(r, (byte)0x01, "failing compareAndExchangeRelease byte");
235             byte x = UNSAFE.getByte(base, offset);
236             assertEquals(x, (byte)0x01, "failing compareAndExchangeRelease byte value");
237         }
238 
239         {
240             boolean success = false;
241             for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
242                 success = UNSAFE.weakCompareAndSetBytePlain(base, offset, (byte)0x01, (byte)0x23);
243             }
244             assertEquals(success, true, "weakCompareAndSetPlain byte");
245             byte x = UNSAFE.getByte(base, offset);
246             assertEquals(x, (byte)0x23, "weakCompareAndSetPlain byte value");
247         }
248 
249         {
250             boolean success = false;
251             for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
252                 success = UNSAFE.weakCompareAndSetByteAcquire(base, offset, (byte)0x23, (byte)0x01);
253             }
254             assertEquals(success, true, "weakCompareAndSetAcquire byte");
255             byte x = UNSAFE.getByte(base, offset);
256             assertEquals(x, (byte)0x01, "weakCompareAndSetAcquire byte");
257         }
258 
259         {
260             boolean success = false;
261             for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
262                 success = UNSAFE.weakCompareAndSetByteRelease(base, offset, (byte)0x01, (byte)0x23);
263             }
264             assertEquals(success, true, "weakCompareAndSetRelease byte");
265             byte x = UNSAFE.getByte(base, offset);
266             assertEquals(x, (byte)0x23, "weakCompareAndSetRelease byte");
267         }
268 
269         {
270             boolean success = false;
271             for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
272                 success = UNSAFE.weakCompareAndSetByte(base, offset, (byte)0x23, (byte)0x01);
273             }
274             assertEquals(success, true, "weakCompareAndSet byte");
275             byte x = UNSAFE.getByte(base, offset);
276             assertEquals(x, (byte)0x01, "weakCompareAndSet byte");
277         }
278 
279         UNSAFE.putByte(base, offset, (byte)0x23);
280 
281         // Compare set and get
282         {
283             byte o = UNSAFE.getAndSetByte(base, offset, (byte)0x01);
284             assertEquals(o, (byte)0x23, "getAndSet byte");
285             byte x = UNSAFE.getByte(base, offset);
286             assertEquals(x, (byte)0x01, "getAndSet byte value");
287         }
288 
289         UNSAFE.putByte(base, offset, (byte)0x01);
290 
291         // get and add, add and get
292         {
293             byte o = UNSAFE.getAndAddByte(base, offset, (byte)0x23);
294             assertEquals(o, (byte)0x01, "getAndAdd byte");
295             byte x = UNSAFE.getByte(base, offset);
296             assertEquals(x, (byte)((byte)0x01 + (byte)0x23), "getAndAdd byte");
297         }
298     }
299 
testAccess(long address)300     static void testAccess(long address) {
301         // Plain
302         {
303             UNSAFE.putByte(address, (byte)0x01);
304             byte x = UNSAFE.getByte(address);
305             assertEquals(x, (byte)0x01, "set byte value");
306         }
307     }
308 }
309