xref: /aosp_15_r20/art/test/2235-JdkUnsafeTest/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2021 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Field;
18*795d594fSAndroid Build Coastguard Worker import jdk.internal.misc.Unsafe;
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker public class Main {
check(boolean actual, boolean expected, String msg)21*795d594fSAndroid Build Coastguard Worker   private static void check(boolean actual, boolean expected, String msg) {
22*795d594fSAndroid Build Coastguard Worker     if (actual != expected) {
23*795d594fSAndroid Build Coastguard Worker       System.out.println(msg + " : " + actual + " != " + expected);
24*795d594fSAndroid Build Coastguard Worker       System.exit(1);
25*795d594fSAndroid Build Coastguard Worker     }
26*795d594fSAndroid Build Coastguard Worker   }
27*795d594fSAndroid Build Coastguard Worker 
check(byte actual, byte expected, String msg)28*795d594fSAndroid Build Coastguard Worker   private static void check(byte actual, byte expected, String msg) {
29*795d594fSAndroid Build Coastguard Worker     if (actual != expected) {
30*795d594fSAndroid Build Coastguard Worker       System.out.println(msg + " : " + actual + " != " + expected);
31*795d594fSAndroid Build Coastguard Worker       System.exit(1);
32*795d594fSAndroid Build Coastguard Worker     }
33*795d594fSAndroid Build Coastguard Worker   }
34*795d594fSAndroid Build Coastguard Worker 
check(char actual, char expected, String msg)35*795d594fSAndroid Build Coastguard Worker   private static void check(char actual, char expected, String msg) {
36*795d594fSAndroid Build Coastguard Worker     if (actual != expected) {
37*795d594fSAndroid Build Coastguard Worker       System.out.println(msg + " : " + actual + " != " + expected);
38*795d594fSAndroid Build Coastguard Worker       System.exit(1);
39*795d594fSAndroid Build Coastguard Worker     }
40*795d594fSAndroid Build Coastguard Worker   }
41*795d594fSAndroid Build Coastguard Worker 
check(short actual, short expected, String msg)42*795d594fSAndroid Build Coastguard Worker   private static void check(short actual, short expected, String msg) {
43*795d594fSAndroid Build Coastguard Worker     if (actual != expected) {
44*795d594fSAndroid Build Coastguard Worker       System.out.println(msg + " : " + actual + " != " + expected);
45*795d594fSAndroid Build Coastguard Worker       System.exit(1);
46*795d594fSAndroid Build Coastguard Worker     }
47*795d594fSAndroid Build Coastguard Worker   }
48*795d594fSAndroid Build Coastguard Worker 
check(int actual, int expected, String msg)49*795d594fSAndroid Build Coastguard Worker   private static void check(int actual, int expected, String msg) {
50*795d594fSAndroid Build Coastguard Worker     if (actual != expected) {
51*795d594fSAndroid Build Coastguard Worker       System.out.println(msg + " : " + actual + " != " + expected);
52*795d594fSAndroid Build Coastguard Worker       System.exit(1);
53*795d594fSAndroid Build Coastguard Worker     }
54*795d594fSAndroid Build Coastguard Worker   }
55*795d594fSAndroid Build Coastguard Worker 
check(long actual, long expected, String msg)56*795d594fSAndroid Build Coastguard Worker   private static void check(long actual, long expected, String msg) {
57*795d594fSAndroid Build Coastguard Worker     if (actual != expected) {
58*795d594fSAndroid Build Coastguard Worker       System.out.println(msg + " : " + actual + " != " + expected);
59*795d594fSAndroid Build Coastguard Worker       System.exit(1);
60*795d594fSAndroid Build Coastguard Worker     }
61*795d594fSAndroid Build Coastguard Worker   }
62*795d594fSAndroid Build Coastguard Worker 
check(float actual, float expected, String msg)63*795d594fSAndroid Build Coastguard Worker   private static void check(float actual, float expected, String msg) {
64*795d594fSAndroid Build Coastguard Worker     if (actual != expected) {
65*795d594fSAndroid Build Coastguard Worker       System.out.println(msg + " : " + actual + " != " + expected);
66*795d594fSAndroid Build Coastguard Worker       System.exit(1);
67*795d594fSAndroid Build Coastguard Worker     }
68*795d594fSAndroid Build Coastguard Worker   }
69*795d594fSAndroid Build Coastguard Worker 
check(double actual, double expected, String msg)70*795d594fSAndroid Build Coastguard Worker   private static void check(double actual, double expected, String msg) {
71*795d594fSAndroid Build Coastguard Worker     if (actual != expected) {
72*795d594fSAndroid Build Coastguard Worker       System.out.println(msg + " : " + actual + " != " + expected);
73*795d594fSAndroid Build Coastguard Worker       System.exit(1);
74*795d594fSAndroid Build Coastguard Worker     }
75*795d594fSAndroid Build Coastguard Worker   }
76*795d594fSAndroid Build Coastguard Worker 
check(Object actual, Object expected, String msg)77*795d594fSAndroid Build Coastguard Worker   private static void check(Object actual, Object expected, String msg) {
78*795d594fSAndroid Build Coastguard Worker     if (actual != expected) {
79*795d594fSAndroid Build Coastguard Worker       System.out.println(msg + " : " + actual + " != " + expected);
80*795d594fSAndroid Build Coastguard Worker       System.exit(1);
81*795d594fSAndroid Build Coastguard Worker     }
82*795d594fSAndroid Build Coastguard Worker   }
83*795d594fSAndroid Build Coastguard Worker 
expectThrow(Class<?> exceptionClass, String msg)84*795d594fSAndroid Build Coastguard Worker   private static void expectThrow(Class<?> exceptionClass, String msg) {
85*795d594fSAndroid Build Coastguard Worker     System.out.println(msg + " : expected " + exceptionClass.getName());
86*795d594fSAndroid Build Coastguard Worker     System.exit(1);
87*795d594fSAndroid Build Coastguard Worker   }
88*795d594fSAndroid Build Coastguard Worker 
getUnsafe()89*795d594fSAndroid Build Coastguard Worker   private static Unsafe getUnsafe() throws NoSuchFieldException, IllegalAccessException {
90*795d594fSAndroid Build Coastguard Worker     Class<?> unsafeClass = Unsafe.class;
91*795d594fSAndroid Build Coastguard Worker     Field f = unsafeClass.getDeclaredField("theUnsafe");
92*795d594fSAndroid Build Coastguard Worker     f.setAccessible(true);
93*795d594fSAndroid Build Coastguard Worker     return (Unsafe) f.get(null);
94*795d594fSAndroid Build Coastguard Worker   }
95*795d594fSAndroid Build Coastguard Worker 
main(String[] args)96*795d594fSAndroid Build Coastguard Worker   public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
97*795d594fSAndroid Build Coastguard Worker     System.loadLibrary(args[0]);
98*795d594fSAndroid Build Coastguard Worker     Unsafe unsafe = getUnsafe();
99*795d594fSAndroid Build Coastguard Worker 
100*795d594fSAndroid Build Coastguard Worker     testArrayBaseOffset(unsafe);
101*795d594fSAndroid Build Coastguard Worker     testArrayIndexScale(unsafe);
102*795d594fSAndroid Build Coastguard Worker     testGetAndPutAndCAS(unsafe);
103*795d594fSAndroid Build Coastguard Worker     testCompareAndSet(unsafe);
104*795d594fSAndroid Build Coastguard Worker     testGetAndPutVolatile(unsafe);
105*795d594fSAndroid Build Coastguard Worker     testGetAcquireAndPutRelease(unsafe);
106*795d594fSAndroid Build Coastguard Worker     testCopyMemory(unsafe);
107*795d594fSAndroid Build Coastguard Worker   }
108*795d594fSAndroid Build Coastguard Worker 
testArrayBaseOffset(Unsafe unsafe)109*795d594fSAndroid Build Coastguard Worker   private static void testArrayBaseOffset(Unsafe unsafe) {
110*795d594fSAndroid Build Coastguard Worker     check(unsafe.arrayBaseOffset(boolean[].class), vmJdkArrayBaseOffset(boolean[].class),
111*795d594fSAndroid Build Coastguard Worker         "Unsafe.arrayBaseOffset(boolean[])");
112*795d594fSAndroid Build Coastguard Worker     check(unsafe.arrayBaseOffset(byte[].class), vmJdkArrayBaseOffset(byte[].class),
113*795d594fSAndroid Build Coastguard Worker         "Unsafe.arrayBaseOffset(byte[])");
114*795d594fSAndroid Build Coastguard Worker     check(unsafe.arrayBaseOffset(char[].class), vmJdkArrayBaseOffset(char[].class),
115*795d594fSAndroid Build Coastguard Worker         "Unsafe.arrayBaseOffset(char[])");
116*795d594fSAndroid Build Coastguard Worker     check(unsafe.arrayBaseOffset(double[].class), vmJdkArrayBaseOffset(double[].class),
117*795d594fSAndroid Build Coastguard Worker         "Unsafe.arrayBaseOffset(double[])");
118*795d594fSAndroid Build Coastguard Worker     check(unsafe.arrayBaseOffset(float[].class), vmJdkArrayBaseOffset(float[].class),
119*795d594fSAndroid Build Coastguard Worker         "Unsafe.arrayBaseOffset(float[])");
120*795d594fSAndroid Build Coastguard Worker     check(unsafe.arrayBaseOffset(int[].class), vmJdkArrayBaseOffset(int[].class),
121*795d594fSAndroid Build Coastguard Worker         "Unsafe.arrayBaseOffset(int[])");
122*795d594fSAndroid Build Coastguard Worker     check(unsafe.arrayBaseOffset(long[].class), vmJdkArrayBaseOffset(long[].class),
123*795d594fSAndroid Build Coastguard Worker         "Unsafe.arrayBaseOffset(long[])");
124*795d594fSAndroid Build Coastguard Worker     check(unsafe.arrayBaseOffset(Object[].class), vmJdkArrayBaseOffset(Object[].class),
125*795d594fSAndroid Build Coastguard Worker         "Unsafe.arrayBaseOffset(Object[])");
126*795d594fSAndroid Build Coastguard Worker   }
127*795d594fSAndroid Build Coastguard Worker 
testArrayIndexScale(Unsafe unsafe)128*795d594fSAndroid Build Coastguard Worker   private static void testArrayIndexScale(Unsafe unsafe) {
129*795d594fSAndroid Build Coastguard Worker     check(unsafe.arrayIndexScale(boolean[].class), vmJdkArrayIndexScale(boolean[].class),
130*795d594fSAndroid Build Coastguard Worker         "Unsafe.arrayIndexScale(boolean[])");
131*795d594fSAndroid Build Coastguard Worker     check(unsafe.arrayIndexScale(byte[].class), vmJdkArrayIndexScale(byte[].class),
132*795d594fSAndroid Build Coastguard Worker         "Unsafe.arrayIndexScale(byte[])");
133*795d594fSAndroid Build Coastguard Worker     check(unsafe.arrayIndexScale(char[].class), vmJdkArrayIndexScale(char[].class),
134*795d594fSAndroid Build Coastguard Worker         "Unsafe.arrayIndexScale(char[])");
135*795d594fSAndroid Build Coastguard Worker     check(unsafe.arrayIndexScale(double[].class), vmJdkArrayIndexScale(double[].class),
136*795d594fSAndroid Build Coastguard Worker         "Unsafe.arrayIndexScale(double[])");
137*795d594fSAndroid Build Coastguard Worker     check(unsafe.arrayIndexScale(float[].class), vmJdkArrayIndexScale(float[].class),
138*795d594fSAndroid Build Coastguard Worker         "Unsafe.arrayIndexScale(float[])");
139*795d594fSAndroid Build Coastguard Worker     check(unsafe.arrayIndexScale(int[].class), vmJdkArrayIndexScale(int[].class),
140*795d594fSAndroid Build Coastguard Worker         "Unsafe.arrayIndexScale(int[])");
141*795d594fSAndroid Build Coastguard Worker     check(unsafe.arrayIndexScale(long[].class), vmJdkArrayIndexScale(long[].class),
142*795d594fSAndroid Build Coastguard Worker         "Unsafe.arrayIndexScale(long[])");
143*795d594fSAndroid Build Coastguard Worker     check(unsafe.arrayIndexScale(Object[].class), vmJdkArrayIndexScale(Object[].class),
144*795d594fSAndroid Build Coastguard Worker         "Unsafe.arrayIndexScale(Object[])");
145*795d594fSAndroid Build Coastguard Worker   }
146*795d594fSAndroid Build Coastguard Worker 
testGetAndPutAndCAS(Unsafe unsafe)147*795d594fSAndroid Build Coastguard Worker   private static void testGetAndPutAndCAS(Unsafe unsafe) throws NoSuchFieldException {
148*795d594fSAndroid Build Coastguard Worker     TestClass t = new TestClass();
149*795d594fSAndroid Build Coastguard Worker 
150*795d594fSAndroid Build Coastguard Worker     int intValue = 12345678;
151*795d594fSAndroid Build Coastguard Worker     Field intField = TestClass.class.getDeclaredField("intVar");
152*795d594fSAndroid Build Coastguard Worker     long intOffset = unsafe.objectFieldOffset(intField);
153*795d594fSAndroid Build Coastguard Worker     check(unsafe.getInt(t, intOffset), 0, "Unsafe.getInt(Object, long) - initial");
154*795d594fSAndroid Build Coastguard Worker     unsafe.putInt(t, intOffset, intValue);
155*795d594fSAndroid Build Coastguard Worker     check(t.intVar, intValue, "Unsafe.putInt(Object, long, int)");
156*795d594fSAndroid Build Coastguard Worker     check(unsafe.getInt(t, intOffset), intValue, "Unsafe.getInt(Object, long)");
157*795d594fSAndroid Build Coastguard Worker 
158*795d594fSAndroid Build Coastguard Worker     long longValue = 1234567887654321L;
159*795d594fSAndroid Build Coastguard Worker     Field longField = TestClass.class.getDeclaredField("longVar");
160*795d594fSAndroid Build Coastguard Worker     long longOffset = unsafe.objectFieldOffset(longField);
161*795d594fSAndroid Build Coastguard Worker     check(unsafe.getLong(t, longOffset), 0, "Unsafe.getLong(Object, long) - initial");
162*795d594fSAndroid Build Coastguard Worker     unsafe.putLong(t, longOffset, longValue);
163*795d594fSAndroid Build Coastguard Worker     check(t.longVar, longValue, "Unsafe.putLong(Object, long, long)");
164*795d594fSAndroid Build Coastguard Worker     check(unsafe.getLong(t, longOffset), longValue, "Unsafe.getLong(Object, long)");
165*795d594fSAndroid Build Coastguard Worker 
166*795d594fSAndroid Build Coastguard Worker     Object objectValue = new Object();
167*795d594fSAndroid Build Coastguard Worker     Field objectField = TestClass.class.getDeclaredField("objectVar");
168*795d594fSAndroid Build Coastguard Worker     long objectOffset = unsafe.objectFieldOffset(objectField);
169*795d594fSAndroid Build Coastguard Worker     check(unsafe.getObject(t, objectOffset), null, "Unsafe.getObject(Object, long) - initial");
170*795d594fSAndroid Build Coastguard Worker     unsafe.putObject(t, objectOffset, objectValue);
171*795d594fSAndroid Build Coastguard Worker     check(t.objectVar, objectValue, "Unsafe.putObject(Object, long, Object)");
172*795d594fSAndroid Build Coastguard Worker     check(unsafe.getObject(t, objectOffset), objectValue, "Unsafe.getObject(Object, long)");
173*795d594fSAndroid Build Coastguard Worker 
174*795d594fSAndroid Build Coastguard Worker     if (unsafe.compareAndSwapInt(t, intOffset, 0, 1)) {
175*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly succeeding compareAndSwapInt(t, intOffset, 0, 1)");
176*795d594fSAndroid Build Coastguard Worker     }
177*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSwapInt(t, intOffset, intValue, 0)) {
178*795d594fSAndroid Build Coastguard Worker       System.out.println(
179*795d594fSAndroid Build Coastguard Worker           "Unexpectedly not succeeding compareAndSwapInt(t, intOffset, intValue, 0)");
180*795d594fSAndroid Build Coastguard Worker     }
181*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSwapInt(t, intOffset, 0, 1)) {
182*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly not succeeding compareAndSwapInt(t, intOffset, 0, 1)");
183*795d594fSAndroid Build Coastguard Worker     }
184*795d594fSAndroid Build Coastguard Worker     // Exercise jdk.internal.misc.Unsafe.compareAndSwapInt using the same
185*795d594fSAndroid Build Coastguard Worker     // integer (1) for the `expectedValue` and `newValue` arguments.
186*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSwapInt(t, intOffset, 1, 1)) {
187*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly not succeeding compareAndSwapInt(t, intOffset, 1, 1)");
188*795d594fSAndroid Build Coastguard Worker     }
189*795d594fSAndroid Build Coastguard Worker 
190*795d594fSAndroid Build Coastguard Worker     if (unsafe.compareAndSwapLong(t, longOffset, 0, 1)) {
191*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly succeeding compareAndSwapLong(t, longOffset, 0, 1)");
192*795d594fSAndroid Build Coastguard Worker     }
193*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSwapLong(t, longOffset, longValue, 0)) {
194*795d594fSAndroid Build Coastguard Worker       System.out.println(
195*795d594fSAndroid Build Coastguard Worker           "Unexpectedly not succeeding compareAndSwapLong(t, longOffset, longValue, 0)");
196*795d594fSAndroid Build Coastguard Worker     }
197*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSwapLong(t, longOffset, 0, 1)) {
198*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly not succeeding compareAndSwapLong(t, longOffset, 0, 1)");
199*795d594fSAndroid Build Coastguard Worker     }
200*795d594fSAndroid Build Coastguard Worker     // Exercise jdk.internal.misc.Unsafe.compareAndSwapLong using the same
201*795d594fSAndroid Build Coastguard Worker     // integer (1) for the `expectedValue` and `newValue` arguments.
202*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSwapLong(t, longOffset, 1, 1)) {
203*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly not succeeding compareAndSwapLong(t, longOffset, 1, 1)");
204*795d594fSAndroid Build Coastguard Worker     }
205*795d594fSAndroid Build Coastguard Worker 
206*795d594fSAndroid Build Coastguard Worker     // We do not use `null` as argument to jdk.internal.misc.Unsafe.compareAndSwapObject
207*795d594fSAndroid Build Coastguard Worker     // in those tests, as this value is not affected by heap poisoning
208*795d594fSAndroid Build Coastguard Worker     // (which uses address negation to poison and unpoison heap object
209*795d594fSAndroid Build Coastguard Worker     // references).  This way, when heap poisoning is enabled, we can
210*795d594fSAndroid Build Coastguard Worker     // better exercise its implementation within that method.
211*795d594fSAndroid Build Coastguard Worker     if (unsafe.compareAndSwapObject(t, objectOffset, new Object(), new Object())) {
212*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly succeeding " +
213*795d594fSAndroid Build Coastguard Worker           "compareAndSwapObject(t, objectOffset, new Object(), new Object())");
214*795d594fSAndroid Build Coastguard Worker     }
215*795d594fSAndroid Build Coastguard Worker     Object objectValue2 = new Object();
216*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSwapObject(t, objectOffset, objectValue, objectValue2)) {
217*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly not succeeding " +
218*795d594fSAndroid Build Coastguard Worker           "compareAndSwapObject(t, objectOffset, objectValue, objectValue2)");
219*795d594fSAndroid Build Coastguard Worker     }
220*795d594fSAndroid Build Coastguard Worker     Object objectValue3 = new Object();
221*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSwapObject(t, objectOffset, objectValue2, objectValue3)) {
222*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly not succeeding " +
223*795d594fSAndroid Build Coastguard Worker           "compareAndSwapObject(t, objectOffset, objectValue2, objectValue3)");
224*795d594fSAndroid Build Coastguard Worker     }
225*795d594fSAndroid Build Coastguard Worker     // Exercise jdk.internal.misc.Unsafe.compareAndSwapObject using the same
226*795d594fSAndroid Build Coastguard Worker     // object (`objectValue3`) for the `expectedValue` and `newValue` arguments.
227*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSwapObject(t, objectOffset, objectValue3, objectValue3)) {
228*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly not succeeding " +
229*795d594fSAndroid Build Coastguard Worker           "compareAndSwapObject(t, objectOffset, objectValue3, objectValue3)");
230*795d594fSAndroid Build Coastguard Worker     }
231*795d594fSAndroid Build Coastguard Worker     // Exercise jdk.internal.misc.Unsafe.compareAndSwapObject using the same
232*795d594fSAndroid Build Coastguard Worker     // object (`t`) for the `obj` and `newValue` arguments.
233*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSwapObject(t, objectOffset, objectValue3, t)) {
234*795d594fSAndroid Build Coastguard Worker       System.out.println(
235*795d594fSAndroid Build Coastguard Worker           "Unexpectedly not succeeding compareAndSwapObject(t, objectOffset, objectValue3, t)");
236*795d594fSAndroid Build Coastguard Worker     }
237*795d594fSAndroid Build Coastguard Worker     // Exercise jdk.internal.misc.Unsafe.compareAndSwapObject using the same
238*795d594fSAndroid Build Coastguard Worker     // object (`t`) for the `obj`, `expectedValue` and `newValue` arguments.
239*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSwapObject(t, objectOffset, t, t)) {
240*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly not succeeding compareAndSwapObject(t, objectOffset, t, t)");
241*795d594fSAndroid Build Coastguard Worker     }
242*795d594fSAndroid Build Coastguard Worker     // Exercise jdk.internal.misc.Unsafe.compareAndSwapObject using the same
243*795d594fSAndroid Build Coastguard Worker     // object (`t`) for the `obj` and `expectedValue` arguments.
244*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSwapObject(t, objectOffset, t, new Object())) {
245*795d594fSAndroid Build Coastguard Worker       System.out.println(
246*795d594fSAndroid Build Coastguard Worker           "Unexpectedly not succeeding compareAndSwapObject(t, objectOffset, t, new Object())");
247*795d594fSAndroid Build Coastguard Worker     }
248*795d594fSAndroid Build Coastguard Worker   }
249*795d594fSAndroid Build Coastguard Worker 
testCompareAndSet(Unsafe unsafe)250*795d594fSAndroid Build Coastguard Worker   private static void testCompareAndSet(Unsafe unsafe) throws NoSuchFieldException {
251*795d594fSAndroid Build Coastguard Worker     TestClass t = new TestClass();
252*795d594fSAndroid Build Coastguard Worker 
253*795d594fSAndroid Build Coastguard Worker     int intValue = 12345678;
254*795d594fSAndroid Build Coastguard Worker     Field intField = TestClass.class.getDeclaredField("intVar");
255*795d594fSAndroid Build Coastguard Worker     long intOffset = unsafe.objectFieldOffset(intField);
256*795d594fSAndroid Build Coastguard Worker     unsafe.putInt(t, intOffset, intValue);
257*795d594fSAndroid Build Coastguard Worker 
258*795d594fSAndroid Build Coastguard Worker     long longValue = 1234567887654321L;
259*795d594fSAndroid Build Coastguard Worker     Field longField = TestClass.class.getDeclaredField("longVar");
260*795d594fSAndroid Build Coastguard Worker     long longOffset = unsafe.objectFieldOffset(longField);
261*795d594fSAndroid Build Coastguard Worker     unsafe.putLong(t, longOffset, longValue);
262*795d594fSAndroid Build Coastguard Worker 
263*795d594fSAndroid Build Coastguard Worker     Object objectValue = new Object();
264*795d594fSAndroid Build Coastguard Worker     Field objectField = TestClass.class.getDeclaredField("objectVar");
265*795d594fSAndroid Build Coastguard Worker     long objectOffset = unsafe.objectFieldOffset(objectField);
266*795d594fSAndroid Build Coastguard Worker     unsafe.putObject(t, objectOffset, objectValue);
267*795d594fSAndroid Build Coastguard Worker 
268*795d594fSAndroid Build Coastguard Worker     if (unsafe.compareAndSetInt(t, intOffset, 0, 1)) {
269*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly succeeding compareAndSetInt(t, intOffset, 0, 1)");
270*795d594fSAndroid Build Coastguard Worker     }
271*795d594fSAndroid Build Coastguard Worker     check(t.intVar, intValue, "Unsafe.compareAndSetInt(Object, long, int, int) - not set");
272*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSetInt(t, intOffset, intValue, 0)) {
273*795d594fSAndroid Build Coastguard Worker       System.out.println(
274*795d594fSAndroid Build Coastguard Worker           "Unexpectedly not succeeding compareAndSetInt(t, intOffset, intValue, 0)");
275*795d594fSAndroid Build Coastguard Worker     }
276*795d594fSAndroid Build Coastguard Worker     check(t.intVar, 0, "Unsafe.compareAndSetInt(Object, long, int, int) - gets set");
277*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSetInt(t, intOffset, 0, 1)) {
278*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly not succeeding compareAndSetInt(t, intOffset, 0, 1)");
279*795d594fSAndroid Build Coastguard Worker     }
280*795d594fSAndroid Build Coastguard Worker     check(t.intVar, 1, "Unsafe.compareAndSetInt(Object, long, int, int) - gets re-set");
281*795d594fSAndroid Build Coastguard Worker     // Exercise jdk.internal.misc.Unsafe.compareAndSetInt using the same
282*795d594fSAndroid Build Coastguard Worker     // integer (1) for the `expectedValue` and `newValue` arguments.
283*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSetInt(t, intOffset, 1, 1)) {
284*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly not succeeding compareAndSetInt(t, intOffset, 1, 1)");
285*795d594fSAndroid Build Coastguard Worker     }
286*795d594fSAndroid Build Coastguard Worker     check(t.intVar, 1, "Unsafe.compareAndSetInt(Object, long, int, int) - gets set to same");
287*795d594fSAndroid Build Coastguard Worker 
288*795d594fSAndroid Build Coastguard Worker     if (unsafe.compareAndSetLong(t, longOffset, 0, 1)) {
289*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly succeeding compareAndSetLong(t, longOffset, 0, 1)");
290*795d594fSAndroid Build Coastguard Worker     }
291*795d594fSAndroid Build Coastguard Worker     check(t.longVar, longValue, "Unsafe.compareAndSetLong(Object, long, long, long) - not set");
292*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSetLong(t, longOffset, longValue, 0)) {
293*795d594fSAndroid Build Coastguard Worker       System.out.println(
294*795d594fSAndroid Build Coastguard Worker           "Unexpectedly not succeeding compareAndSetLong(t, longOffset, longValue, 0)");
295*795d594fSAndroid Build Coastguard Worker     }
296*795d594fSAndroid Build Coastguard Worker     check(t.longVar, 0, "Unsafe.compareAndSetLong(Object, long, long, long) - gets set");
297*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSetLong(t, longOffset, 0, 1)) {
298*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly not succeeding compareAndSetLong(t, longOffset, 0, 1)");
299*795d594fSAndroid Build Coastguard Worker     }
300*795d594fSAndroid Build Coastguard Worker     check(t.longVar, 1, "Unsafe.compareAndSetLong(Object, long, long, long) - gets re-set");
301*795d594fSAndroid Build Coastguard Worker     // Exercise jdk.internal.misc.Unsafe.compareAndSetLong using the same
302*795d594fSAndroid Build Coastguard Worker     // integer (1) for the `expectedValue` and `newValue` arguments.
303*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSetLong(t, longOffset, 1, 1)) {
304*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly not succeeding compareAndSetLong(t, longOffset, 1, 1)");
305*795d594fSAndroid Build Coastguard Worker     }
306*795d594fSAndroid Build Coastguard Worker     check(t.longVar, 1, "Unsafe.compareAndSetLong(Object, long, long, long) - gets set to same");
307*795d594fSAndroid Build Coastguard Worker 
308*795d594fSAndroid Build Coastguard Worker     // We do not use `null` as argument to jdk.internal.misc.Unsafe.compareAndSwapObject
309*795d594fSAndroid Build Coastguard Worker     // in those tests, as this value is not affected by heap poisoning
310*795d594fSAndroid Build Coastguard Worker     // (which uses address negation to poison and unpoison heap object
311*795d594fSAndroid Build Coastguard Worker     // references).  This way, when heap poisoning is enabled, we can
312*795d594fSAndroid Build Coastguard Worker     // better exercise its implementation within that method.
313*795d594fSAndroid Build Coastguard Worker     if (unsafe.compareAndSetObject(t, objectOffset, new Object(), new Object())) {
314*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly succeeding compareAndSetObject(t, objectOffset, 0, 1)");
315*795d594fSAndroid Build Coastguard Worker     }
316*795d594fSAndroid Build Coastguard Worker     check(t.objectVar, objectValue, "Unsafe.compareAndSetObject(Object, long, Object, Object) - not set");
317*795d594fSAndroid Build Coastguard Worker     Object objectValue2 = new Object();
318*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSetObject(t, objectOffset, objectValue, objectValue2)) {
319*795d594fSAndroid Build Coastguard Worker       System.out.println(
320*795d594fSAndroid Build Coastguard Worker           "Unexpectedly not succeeding compareAndSetObject(t, objectOffset, objectValue, 0)");
321*795d594fSAndroid Build Coastguard Worker     }
322*795d594fSAndroid Build Coastguard Worker     check(t.objectVar, objectValue2, "Unsafe.compareAndSetObject(Object, long, Object, Object) - gets set");
323*795d594fSAndroid Build Coastguard Worker     Object objectValue3 = new Object();
324*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSetObject(t, objectOffset, objectValue2, objectValue3)) {
325*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly not succeeding compareAndSetObject(t, objectOffset, 0, 1)");
326*795d594fSAndroid Build Coastguard Worker     }
327*795d594fSAndroid Build Coastguard Worker     check(t.objectVar, objectValue3, "Unsafe.compareAndSetObject(Object, long, Object, Object) - gets re-set");
328*795d594fSAndroid Build Coastguard Worker     // Exercise jdk.internal.misc.Unsafe.compareAndSetObject using the same
329*795d594fSAndroid Build Coastguard Worker     // object for the `expectedValue` and `newValue` arguments.
330*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSetObject(t, objectOffset, objectValue3, objectValue3)) {
331*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly not succeeding compareAndSetObject(t, objectOffset, 1, 1)");
332*795d594fSAndroid Build Coastguard Worker     }
333*795d594fSAndroid Build Coastguard Worker     check(t.objectVar, objectValue3, "Unsafe.compareAndSetObject(Object, long, Object, Object) - gets set to same");
334*795d594fSAndroid Build Coastguard Worker 
335*795d594fSAndroid Build Coastguard Worker     // Reset and now try with `compareAndSetReference` which replaced `compareAndSetObject`.
336*795d594fSAndroid Build Coastguard Worker     unsafe.putObject(t, objectOffset, objectValue);
337*795d594fSAndroid Build Coastguard Worker 
338*795d594fSAndroid Build Coastguard Worker     if (unsafe.compareAndSetReference(t, objectOffset, new Object(), new Object())) {
339*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly succeeding compareAndSetReference(t, objectOffset, 0, 1)");
340*795d594fSAndroid Build Coastguard Worker     }
341*795d594fSAndroid Build Coastguard Worker     check(t.objectVar, objectValue, "Unsafe.compareAndSetReference(Object, long, Object, Object) - not set");
342*795d594fSAndroid Build Coastguard Worker     objectValue2 = new Object();
343*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSetReference(t, objectOffset, objectValue, objectValue2)) {
344*795d594fSAndroid Build Coastguard Worker       System.out.println(
345*795d594fSAndroid Build Coastguard Worker           "Unexpectedly not succeeding compareAndSetReference(t, objectOffset, objectValue, 0)");
346*795d594fSAndroid Build Coastguard Worker     }
347*795d594fSAndroid Build Coastguard Worker     check(t.objectVar, objectValue2, "Unsafe.compareAndSetReference(Object, long, Object, Object) - gets set");
348*795d594fSAndroid Build Coastguard Worker     objectValue3 = new Object();
349*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSetReference(t, objectOffset, objectValue2, objectValue3)) {
350*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly not succeeding compareAndSetReference(t, objectOffset, 0, 1)");
351*795d594fSAndroid Build Coastguard Worker     }
352*795d594fSAndroid Build Coastguard Worker     check(t.objectVar, objectValue3, "Unsafe.compareAndSetReference(Object, long, Object, Object) - gets re-set");
353*795d594fSAndroid Build Coastguard Worker     // Exercise jdk.internal.misc.Unsafe.compareAndSetReference using the same
354*795d594fSAndroid Build Coastguard Worker     // object for the `expectedValue` and `newValue` arguments.
355*795d594fSAndroid Build Coastguard Worker     if (!unsafe.compareAndSetReference(t, objectOffset, objectValue3, objectValue3)) {
356*795d594fSAndroid Build Coastguard Worker       System.out.println("Unexpectedly not succeeding compareAndSetReference(t, objectOffset, 1, 1)");
357*795d594fSAndroid Build Coastguard Worker     }
358*795d594fSAndroid Build Coastguard Worker     check(t.objectVar, objectValue3, "Unsafe.compareAndSetReference(Object, long, Object, Object) - gets set to same");
359*795d594fSAndroid Build Coastguard Worker  }
360*795d594fSAndroid Build Coastguard Worker 
testGetAndPutVolatile(Unsafe unsafe)361*795d594fSAndroid Build Coastguard Worker   private static void testGetAndPutVolatile(Unsafe unsafe) throws NoSuchFieldException {
362*795d594fSAndroid Build Coastguard Worker     TestVolatileClass tv = new TestVolatileClass();
363*795d594fSAndroid Build Coastguard Worker 
364*795d594fSAndroid Build Coastguard Worker     int intValue = 12345678;
365*795d594fSAndroid Build Coastguard Worker     Field volatileIntField = TestVolatileClass.class.getDeclaredField("volatileIntVar");
366*795d594fSAndroid Build Coastguard Worker     long volatileIntOffset = unsafe.objectFieldOffset(volatileIntField);
367*795d594fSAndroid Build Coastguard Worker     check(unsafe.getIntVolatile(tv, volatileIntOffset),
368*795d594fSAndroid Build Coastguard Worker           0,
369*795d594fSAndroid Build Coastguard Worker           "Unsafe.getIntVolatile(Object, long) - initial");
370*795d594fSAndroid Build Coastguard Worker     unsafe.putIntVolatile(tv, volatileIntOffset, intValue);
371*795d594fSAndroid Build Coastguard Worker     check(tv.volatileIntVar, intValue, "Unsafe.putIntVolatile(Object, long, int)");
372*795d594fSAndroid Build Coastguard Worker     check(unsafe.getIntVolatile(tv, volatileIntOffset),
373*795d594fSAndroid Build Coastguard Worker           intValue,
374*795d594fSAndroid Build Coastguard Worker           "Unsafe.getIntVolatile(Object, long)");
375*795d594fSAndroid Build Coastguard Worker 
376*795d594fSAndroid Build Coastguard Worker     boolean booleanValue = true;
377*795d594fSAndroid Build Coastguard Worker     Field volatileBooleanField = TestVolatileClass.class.getDeclaredField("volatileBooleanVar");
378*795d594fSAndroid Build Coastguard Worker     long volatileBooleanOffset = unsafe.objectFieldOffset(volatileBooleanField);
379*795d594fSAndroid Build Coastguard Worker     check(unsafe.getBooleanVolatile(tv, volatileBooleanOffset),
380*795d594fSAndroid Build Coastguard Worker           false,
381*795d594fSAndroid Build Coastguard Worker           "Unsafe.getBooleanVolatile(Object, long) - initial");
382*795d594fSAndroid Build Coastguard Worker     unsafe.putBooleanVolatile(tv, volatileBooleanOffset, booleanValue);
383*795d594fSAndroid Build Coastguard Worker     check(tv.volatileBooleanVar, booleanValue, "Unsafe.putBooleanVolatile(Object, long, boolean)");
384*795d594fSAndroid Build Coastguard Worker     check(unsafe.getBooleanVolatile(tv, volatileBooleanOffset),
385*795d594fSAndroid Build Coastguard Worker           booleanValue,
386*795d594fSAndroid Build Coastguard Worker           "Unsafe.getBooleanVolatile(Object, long)");
387*795d594fSAndroid Build Coastguard Worker 
388*795d594fSAndroid Build Coastguard Worker     byte byteValue = 125;
389*795d594fSAndroid Build Coastguard Worker     Field volatileByteField = TestVolatileClass.class.getDeclaredField("volatileByteVar");
390*795d594fSAndroid Build Coastguard Worker     long volatileByteOffset = unsafe.objectFieldOffset(volatileByteField);
391*795d594fSAndroid Build Coastguard Worker     check(unsafe.getByteVolatile(tv, volatileByteOffset),
392*795d594fSAndroid Build Coastguard Worker           0,
393*795d594fSAndroid Build Coastguard Worker           "Unsafe.getByteVolatile(Object, long) - initial");
394*795d594fSAndroid Build Coastguard Worker     unsafe.putByteVolatile(tv, volatileByteOffset, byteValue);
395*795d594fSAndroid Build Coastguard Worker     check(tv.volatileByteVar, byteValue, "Unsafe.putByteVolatile(Object, long, byte)");
396*795d594fSAndroid Build Coastguard Worker     check(unsafe.getByteVolatile(tv, volatileByteOffset),
397*795d594fSAndroid Build Coastguard Worker           byteValue,
398*795d594fSAndroid Build Coastguard Worker           "Unsafe.getByteVolatile(Object, long)");
399*795d594fSAndroid Build Coastguard Worker 
400*795d594fSAndroid Build Coastguard Worker     char charValue = 'X';
401*795d594fSAndroid Build Coastguard Worker     Field volatileCharField = TestVolatileClass.class.getDeclaredField("volatileCharVar");
402*795d594fSAndroid Build Coastguard Worker     long volatileCharOffset = unsafe.objectFieldOffset(volatileCharField);
403*795d594fSAndroid Build Coastguard Worker     check(unsafe.getCharVolatile(tv, volatileCharOffset),
404*795d594fSAndroid Build Coastguard Worker           '\0',
405*795d594fSAndroid Build Coastguard Worker           "Unsafe.getCharVolatile(Object, long) - initial");
406*795d594fSAndroid Build Coastguard Worker     unsafe.putCharVolatile(tv, volatileCharOffset, charValue);
407*795d594fSAndroid Build Coastguard Worker     check(tv.volatileCharVar, charValue, "Unsafe.putCharVolatile(Object, long, char)");
408*795d594fSAndroid Build Coastguard Worker     check(unsafe.getCharVolatile(tv, volatileCharOffset),
409*795d594fSAndroid Build Coastguard Worker           charValue,
410*795d594fSAndroid Build Coastguard Worker           "Unsafe.getCharVolatile(Object, long)");
411*795d594fSAndroid Build Coastguard Worker 
412*795d594fSAndroid Build Coastguard Worker     short shortValue = 32523;
413*795d594fSAndroid Build Coastguard Worker     Field volatileShortField = TestVolatileClass.class.getDeclaredField("volatileShortVar");
414*795d594fSAndroid Build Coastguard Worker     long volatileShortOffset = unsafe.objectFieldOffset(volatileShortField);
415*795d594fSAndroid Build Coastguard Worker     check(unsafe.getShortVolatile(tv, volatileShortOffset),
416*795d594fSAndroid Build Coastguard Worker           0,
417*795d594fSAndroid Build Coastguard Worker           "Unsafe.getShortVolatile(Object, long) - initial");
418*795d594fSAndroid Build Coastguard Worker     unsafe.putShortVolatile(tv, volatileShortOffset, shortValue);
419*795d594fSAndroid Build Coastguard Worker     check(tv.volatileShortVar, shortValue, "Unsafe.putShortVolatile(Object, long, short)");
420*795d594fSAndroid Build Coastguard Worker     check(unsafe.getShortVolatile(tv, volatileShortOffset),
421*795d594fSAndroid Build Coastguard Worker           shortValue,
422*795d594fSAndroid Build Coastguard Worker           "Unsafe.getShortVolatile(Object, long)");
423*795d594fSAndroid Build Coastguard Worker 
424*795d594fSAndroid Build Coastguard Worker     long longValue = 1234567887654321L;
425*795d594fSAndroid Build Coastguard Worker     Field volatileLongField = TestVolatileClass.class.getDeclaredField("volatileLongVar");
426*795d594fSAndroid Build Coastguard Worker     long volatileLongOffset = unsafe.objectFieldOffset(volatileLongField);
427*795d594fSAndroid Build Coastguard Worker     check(unsafe.getLongVolatile(tv, volatileLongOffset),
428*795d594fSAndroid Build Coastguard Worker           0,
429*795d594fSAndroid Build Coastguard Worker           "Unsafe.getLongVolatile(Object, long) - initial");
430*795d594fSAndroid Build Coastguard Worker     unsafe.putLongVolatile(tv, volatileLongOffset, longValue);
431*795d594fSAndroid Build Coastguard Worker     check(tv.volatileLongVar, longValue, "Unsafe.putLongVolatile(Object, long, long)");
432*795d594fSAndroid Build Coastguard Worker     check(unsafe.getLongVolatile(tv, volatileLongOffset),
433*795d594fSAndroid Build Coastguard Worker           longValue,
434*795d594fSAndroid Build Coastguard Worker           "Unsafe.getLongVolatile(Object, long)");
435*795d594fSAndroid Build Coastguard Worker 
436*795d594fSAndroid Build Coastguard Worker     float floatValue = 123456.7890123f;
437*795d594fSAndroid Build Coastguard Worker     Field volatileFloatField = TestVolatileClass.class.getDeclaredField("volatileFloatVar");
438*795d594fSAndroid Build Coastguard Worker     long volatileFloatOffset = unsafe.objectFieldOffset(volatileFloatField);
439*795d594fSAndroid Build Coastguard Worker     check(unsafe.getFloatVolatile(tv, volatileFloatOffset),
440*795d594fSAndroid Build Coastguard Worker           0.0f,
441*795d594fSAndroid Build Coastguard Worker           "Unsafe.getFloatVolatile(Object, long) - initial");
442*795d594fSAndroid Build Coastguard Worker     unsafe.putFloatVolatile(tv, volatileFloatOffset, floatValue);
443*795d594fSAndroid Build Coastguard Worker     check(tv.volatileFloatVar, floatValue, "Unsafe.putFloatVolatile(Object, long, float)");
444*795d594fSAndroid Build Coastguard Worker     check(unsafe.getFloatVolatile(tv, volatileFloatOffset),
445*795d594fSAndroid Build Coastguard Worker           floatValue,
446*795d594fSAndroid Build Coastguard Worker           "Unsafe.getFloatVolatile(Object, long)");
447*795d594fSAndroid Build Coastguard Worker 
448*795d594fSAndroid Build Coastguard Worker     double doubleValue = 654321.7890123d;
449*795d594fSAndroid Build Coastguard Worker     Field volatileDoubleField = TestVolatileClass.class.getDeclaredField("volatileDoubleVar");
450*795d594fSAndroid Build Coastguard Worker     long volatileDoubleOffset = unsafe.objectFieldOffset(volatileDoubleField);
451*795d594fSAndroid Build Coastguard Worker     check(unsafe.getDoubleVolatile(tv, volatileDoubleOffset),
452*795d594fSAndroid Build Coastguard Worker           0.0d,
453*795d594fSAndroid Build Coastguard Worker           "Unsafe.getDoubleVolatile(Object, double) - initial");
454*795d594fSAndroid Build Coastguard Worker     unsafe.putDoubleVolatile(tv, volatileDoubleOffset, doubleValue);
455*795d594fSAndroid Build Coastguard Worker     check(tv.volatileDoubleVar, doubleValue, "Unsafe.putDoubleVolatile(Object, long, double)");
456*795d594fSAndroid Build Coastguard Worker     check(unsafe.getDoubleVolatile(tv, volatileDoubleOffset),
457*795d594fSAndroid Build Coastguard Worker           doubleValue,
458*795d594fSAndroid Build Coastguard Worker           "Unsafe.getDoubleVolatile(Object, long)");
459*795d594fSAndroid Build Coastguard Worker 
460*795d594fSAndroid Build Coastguard Worker     Object objectValue = new Object();
461*795d594fSAndroid Build Coastguard Worker     Field volatileObjectField = TestVolatileClass.class.getDeclaredField("volatileObjectVar");
462*795d594fSAndroid Build Coastguard Worker     long volatileObjectOffset = unsafe.objectFieldOffset(volatileObjectField);
463*795d594fSAndroid Build Coastguard Worker     check(unsafe.getReferenceVolatile(tv, volatileObjectOffset),
464*795d594fSAndroid Build Coastguard Worker           null,
465*795d594fSAndroid Build Coastguard Worker           "Unsafe.getReferenceVolatile(Object, long) - initial");
466*795d594fSAndroid Build Coastguard Worker     unsafe.putReferenceVolatile(tv, volatileObjectOffset, objectValue);
467*795d594fSAndroid Build Coastguard Worker     check(tv.volatileObjectVar, objectValue, "Unsafe.putReferenceVolatile(Object, long, Object)");
468*795d594fSAndroid Build Coastguard Worker     check(unsafe.getReferenceVolatile(tv, volatileObjectOffset),
469*795d594fSAndroid Build Coastguard Worker           objectValue,
470*795d594fSAndroid Build Coastguard Worker           "Unsafe.getReferenceVolatile(Object, long)");
471*795d594fSAndroid Build Coastguard Worker   }
472*795d594fSAndroid Build Coastguard Worker 
testGetAcquireAndPutRelease(Unsafe unsafe)473*795d594fSAndroid Build Coastguard Worker   private static void testGetAcquireAndPutRelease(Unsafe unsafe) throws NoSuchFieldException {
474*795d594fSAndroid Build Coastguard Worker     TestVolatileClass tv = new TestVolatileClass();
475*795d594fSAndroid Build Coastguard Worker 
476*795d594fSAndroid Build Coastguard Worker     int intValue = 12345678;
477*795d594fSAndroid Build Coastguard Worker     Field volatileIntField = TestVolatileClass.class.getDeclaredField("volatileIntVar");
478*795d594fSAndroid Build Coastguard Worker     long volatileIntOffset = unsafe.objectFieldOffset(volatileIntField);
479*795d594fSAndroid Build Coastguard Worker     check(unsafe.getIntAcquire(tv, volatileIntOffset),
480*795d594fSAndroid Build Coastguard Worker           0,
481*795d594fSAndroid Build Coastguard Worker           "Unsafe.getIntAcquire(Object, long) - initial");
482*795d594fSAndroid Build Coastguard Worker     unsafe.putIntRelease(tv, volatileIntOffset, intValue);
483*795d594fSAndroid Build Coastguard Worker     check(tv.volatileIntVar, intValue, "Unsafe.putIntRelease(Object, long, int)");
484*795d594fSAndroid Build Coastguard Worker     check(unsafe.getIntAcquire(tv, volatileIntOffset),
485*795d594fSAndroid Build Coastguard Worker           intValue,
486*795d594fSAndroid Build Coastguard Worker           "Unsafe.getIntAcquire(Object, long)");
487*795d594fSAndroid Build Coastguard Worker 
488*795d594fSAndroid Build Coastguard Worker     long longValue = 1234567887654321L;
489*795d594fSAndroid Build Coastguard Worker     Field volatileLongField = TestVolatileClass.class.getDeclaredField("volatileLongVar");
490*795d594fSAndroid Build Coastguard Worker     long volatileLongOffset = unsafe.objectFieldOffset(volatileLongField);
491*795d594fSAndroid Build Coastguard Worker     check(unsafe.getLongAcquire(tv, volatileLongOffset),
492*795d594fSAndroid Build Coastguard Worker           0,
493*795d594fSAndroid Build Coastguard Worker           "Unsafe.getLongAcquire(Object, long) - initial");
494*795d594fSAndroid Build Coastguard Worker     unsafe.putLongRelease(tv, volatileLongOffset, longValue);
495*795d594fSAndroid Build Coastguard Worker     check(tv.volatileLongVar, longValue, "Unsafe.putLongRelease(Object, long, long)");
496*795d594fSAndroid Build Coastguard Worker     check(unsafe.getLongAcquire(tv, volatileLongOffset),
497*795d594fSAndroid Build Coastguard Worker           longValue,
498*795d594fSAndroid Build Coastguard Worker           "Unsafe.getLongAcquire(Object, long)");
499*795d594fSAndroid Build Coastguard Worker 
500*795d594fSAndroid Build Coastguard Worker     Object objectValue = new Object();
501*795d594fSAndroid Build Coastguard Worker     Field volatileObjectField = TestVolatileClass.class.getDeclaredField("volatileObjectVar");
502*795d594fSAndroid Build Coastguard Worker     long volatileObjectOffset = unsafe.objectFieldOffset(volatileObjectField);
503*795d594fSAndroid Build Coastguard Worker     check(unsafe.getObjectAcquire(tv, volatileObjectOffset),
504*795d594fSAndroid Build Coastguard Worker           null,
505*795d594fSAndroid Build Coastguard Worker           "Unsafe.getObjectAcquire(Object, long) - initial");
506*795d594fSAndroid Build Coastguard Worker     unsafe.putObjectRelease(tv, volatileObjectOffset, objectValue);
507*795d594fSAndroid Build Coastguard Worker     check(tv.volatileObjectVar, objectValue, "Unsafe.putObjectRelease(Object, long, Object)");
508*795d594fSAndroid Build Coastguard Worker     check(unsafe.getObjectAcquire(tv, volatileObjectOffset),
509*795d594fSAndroid Build Coastguard Worker           objectValue,
510*795d594fSAndroid Build Coastguard Worker           "Unsafe.getObjectAcquire(Object, long)");
511*795d594fSAndroid Build Coastguard Worker   }
512*795d594fSAndroid Build Coastguard Worker 
testCopyMemory(Unsafe unsafe)513*795d594fSAndroid Build Coastguard Worker   private static void testCopyMemory(Unsafe unsafe) {
514*795d594fSAndroid Build Coastguard Worker     final int size = 4 * 1024;
515*795d594fSAndroid Build Coastguard Worker 
516*795d594fSAndroid Build Coastguard Worker     final int intSize = 4;
517*795d594fSAndroid Build Coastguard Worker     int[] inputInts = new int[size / intSize];
518*795d594fSAndroid Build Coastguard Worker     for (int i = 0; i != inputInts.length; ++i) {
519*795d594fSAndroid Build Coastguard Worker       inputInts[i] = ((int)i) + 1;
520*795d594fSAndroid Build Coastguard Worker     }
521*795d594fSAndroid Build Coastguard Worker     int[] outputInts = new int[size / intSize];
522*795d594fSAndroid Build Coastguard Worker     unsafe.copyMemory(inputInts, Unsafe.ARRAY_INT_BASE_OFFSET,
523*795d594fSAndroid Build Coastguard Worker                       outputInts, Unsafe.ARRAY_INT_BASE_OFFSET,
524*795d594fSAndroid Build Coastguard Worker                       size);
525*795d594fSAndroid Build Coastguard Worker     for (int i = 0; i != inputInts.length; ++i) {
526*795d594fSAndroid Build Coastguard Worker       check(inputInts[i], outputInts[i], "unsafe.copyMemory/int");
527*795d594fSAndroid Build Coastguard Worker     }
528*795d594fSAndroid Build Coastguard Worker 
529*795d594fSAndroid Build Coastguard Worker     final int longSize = 8;
530*795d594fSAndroid Build Coastguard Worker     long[] inputLongs = new long[size / longSize];
531*795d594fSAndroid Build Coastguard Worker     for (int i = 0; i != inputLongs.length; ++i) {
532*795d594fSAndroid Build Coastguard Worker       inputLongs[i] = ((long)i) + 1L;
533*795d594fSAndroid Build Coastguard Worker     }
534*795d594fSAndroid Build Coastguard Worker     long[] outputLongs = new long[size / longSize];
535*795d594fSAndroid Build Coastguard Worker     unsafe.copyMemory(inputLongs, 0, outputLongs, 0, size);
536*795d594fSAndroid Build Coastguard Worker     unsafe.copyMemory(inputLongs, Unsafe.ARRAY_LONG_BASE_OFFSET,
537*795d594fSAndroid Build Coastguard Worker                       outputLongs, Unsafe.ARRAY_LONG_BASE_OFFSET,
538*795d594fSAndroid Build Coastguard Worker                       size);
539*795d594fSAndroid Build Coastguard Worker     for (int i = 0; i != inputLongs.length; ++i) {
540*795d594fSAndroid Build Coastguard Worker       check(inputLongs[i], outputLongs[i], "unsafe.copyMemory/long");
541*795d594fSAndroid Build Coastguard Worker     }
542*795d594fSAndroid Build Coastguard Worker 
543*795d594fSAndroid Build Coastguard Worker     final int floatSize = 4;
544*795d594fSAndroid Build Coastguard Worker     float[] inputFloats = new float[size / floatSize];
545*795d594fSAndroid Build Coastguard Worker     for (int i = 0; i != inputFloats.length; ++i) {
546*795d594fSAndroid Build Coastguard Worker       inputFloats[i] = ((float)i) + 0.5f;
547*795d594fSAndroid Build Coastguard Worker     }
548*795d594fSAndroid Build Coastguard Worker     float[] outputFloats = new float[size / floatSize];
549*795d594fSAndroid Build Coastguard Worker     unsafe.copyMemory(inputFloats, 0, outputFloats, 0, size);
550*795d594fSAndroid Build Coastguard Worker     unsafe.copyMemory(inputFloats, Unsafe.ARRAY_FLOAT_BASE_OFFSET,
551*795d594fSAndroid Build Coastguard Worker                       outputFloats, Unsafe.ARRAY_FLOAT_BASE_OFFSET,
552*795d594fSAndroid Build Coastguard Worker                       size);
553*795d594fSAndroid Build Coastguard Worker     for (int i = 0; i != inputFloats.length; ++i) {
554*795d594fSAndroid Build Coastguard Worker       check(inputFloats[i], outputFloats[i], "unsafe.copyMemory/float");
555*795d594fSAndroid Build Coastguard Worker     }
556*795d594fSAndroid Build Coastguard Worker 
557*795d594fSAndroid Build Coastguard Worker     final int doubleSize = 8;
558*795d594fSAndroid Build Coastguard Worker     double[] inputDoubles = new double[size / doubleSize];
559*795d594fSAndroid Build Coastguard Worker     for (int i = 0; i != inputDoubles.length; ++i) {
560*795d594fSAndroid Build Coastguard Worker       inputDoubles[i] = ((double)i) + 0.5;
561*795d594fSAndroid Build Coastguard Worker     }
562*795d594fSAndroid Build Coastguard Worker     double[] outputDoubles = new double[size / doubleSize];
563*795d594fSAndroid Build Coastguard Worker     unsafe.copyMemory(inputDoubles, Unsafe.ARRAY_DOUBLE_BASE_OFFSET,
564*795d594fSAndroid Build Coastguard Worker                       outputDoubles, Unsafe.ARRAY_DOUBLE_BASE_OFFSET,
565*795d594fSAndroid Build Coastguard Worker                       size);
566*795d594fSAndroid Build Coastguard Worker     for (int i = 0; i != inputDoubles.length; ++i) {
567*795d594fSAndroid Build Coastguard Worker       check(inputDoubles[i], outputDoubles[i], "unsafe.copyMemory/double");
568*795d594fSAndroid Build Coastguard Worker     }
569*795d594fSAndroid Build Coastguard Worker 
570*795d594fSAndroid Build Coastguard Worker     // check the version that works with memory pointers
571*795d594fSAndroid Build Coastguard Worker     try (TestMemoryPtr srcPtr = new TestMemoryPtr(size);
572*795d594fSAndroid Build Coastguard Worker          TestMemoryPtr dstPtr = new TestMemoryPtr(size)) {
573*795d594fSAndroid Build Coastguard Worker         // use the integer array to fill the source
574*795d594fSAndroid Build Coastguard Worker         unsafe.copyMemory(inputInts, Unsafe.ARRAY_INT_BASE_OFFSET,
575*795d594fSAndroid Build Coastguard Worker                           null, srcPtr.get(),
576*795d594fSAndroid Build Coastguard Worker                           size);
577*795d594fSAndroid Build Coastguard Worker 
578*795d594fSAndroid Build Coastguard Worker         unsafe.copyMemory(srcPtr.get(), dstPtr.get(), size);
579*795d594fSAndroid Build Coastguard Worker         for (int i = 0; i != size; ++i) {
580*795d594fSAndroid Build Coastguard Worker           check(unsafe.getByte(srcPtr.get() + i),
581*795d594fSAndroid Build Coastguard Worker                 unsafe.getByte(dstPtr.get() + i),
582*795d594fSAndroid Build Coastguard Worker                 "unsafe.copyMemory/memoryAddress");
583*795d594fSAndroid Build Coastguard Worker         }
584*795d594fSAndroid Build Coastguard Worker     }
585*795d594fSAndroid Build Coastguard Worker 
586*795d594fSAndroid Build Coastguard Worker     try {
587*795d594fSAndroid Build Coastguard Worker         TestClass srcObj = new TestClass();
588*795d594fSAndroid Build Coastguard Worker         srcObj.intVar = 12345678;
589*795d594fSAndroid Build Coastguard Worker         int[] dstArray = new int[1];
590*795d594fSAndroid Build Coastguard Worker         unsafe.copyMemory(srcObj, unsafe.objectFieldOffset(TestClass.class, "intVar"),
591*795d594fSAndroid Build Coastguard Worker                           dstArray, Unsafe.ARRAY_INT_BASE_OFFSET,
592*795d594fSAndroid Build Coastguard Worker                           4);
593*795d594fSAndroid Build Coastguard Worker         expectThrow(RuntimeException.class, "unsafe.copyMemory/non-array-src");
594*795d594fSAndroid Build Coastguard Worker     } catch (RuntimeException expected) {
595*795d594fSAndroid Build Coastguard Worker     }
596*795d594fSAndroid Build Coastguard Worker 
597*795d594fSAndroid Build Coastguard Worker     try {
598*795d594fSAndroid Build Coastguard Worker         int[] srcArray = { 12345678 };
599*795d594fSAndroid Build Coastguard Worker         TestClass dstObj = new TestClass();
600*795d594fSAndroid Build Coastguard Worker         unsafe.copyMemory(srcArray, Unsafe.ARRAY_INT_BASE_OFFSET,
601*795d594fSAndroid Build Coastguard Worker                           dstObj, unsafe.objectFieldOffset(TestClass.class, "intVar"),
602*795d594fSAndroid Build Coastguard Worker                           4);
603*795d594fSAndroid Build Coastguard Worker         expectThrow(RuntimeException.class, "unsafe.copyMemory/non-array-dst");
604*795d594fSAndroid Build Coastguard Worker     } catch (RuntimeException expected) {
605*795d594fSAndroid Build Coastguard Worker     }
606*795d594fSAndroid Build Coastguard Worker   }
607*795d594fSAndroid Build Coastguard Worker 
608*795d594fSAndroid Build Coastguard Worker   private static class TestClass {
609*795d594fSAndroid Build Coastguard Worker     public int intVar = 0;
610*795d594fSAndroid Build Coastguard Worker     public long longVar = 0;
611*795d594fSAndroid Build Coastguard Worker     public Object objectVar = null;
612*795d594fSAndroid Build Coastguard Worker   }
613*795d594fSAndroid Build Coastguard Worker 
614*795d594fSAndroid Build Coastguard Worker   private static class TestVolatileClass {
615*795d594fSAndroid Build Coastguard Worker     public volatile int volatileIntVar = 0;
616*795d594fSAndroid Build Coastguard Worker     public volatile boolean volatileBooleanVar = false;
617*795d594fSAndroid Build Coastguard Worker     public volatile byte volatileByteVar = 0;
618*795d594fSAndroid Build Coastguard Worker     public volatile short volatileShortVar = 0;
619*795d594fSAndroid Build Coastguard Worker     public volatile char volatileCharVar = 0;
620*795d594fSAndroid Build Coastguard Worker     public volatile long volatileLongVar = 0;
621*795d594fSAndroid Build Coastguard Worker     public volatile float volatileFloatVar = 0.0f;
622*795d594fSAndroid Build Coastguard Worker     public volatile double volatileDoubleVar = 0.0d;
623*795d594fSAndroid Build Coastguard Worker     public volatile Object volatileObjectVar = null;
624*795d594fSAndroid Build Coastguard Worker   }
625*795d594fSAndroid Build Coastguard Worker 
626*795d594fSAndroid Build Coastguard Worker   private static class TestMemoryPtr implements AutoCloseable {
627*795d594fSAndroid Build Coastguard Worker       private long ptr = 0;
628*795d594fSAndroid Build Coastguard Worker 
TestMemoryPtr(int size)629*795d594fSAndroid Build Coastguard Worker       public TestMemoryPtr(int size) {
630*795d594fSAndroid Build Coastguard Worker           ptr = jdkUnsafeTestMalloc(size);
631*795d594fSAndroid Build Coastguard Worker       }
632*795d594fSAndroid Build Coastguard Worker 
get()633*795d594fSAndroid Build Coastguard Worker       public long get() {
634*795d594fSAndroid Build Coastguard Worker           return ptr;
635*795d594fSAndroid Build Coastguard Worker       }
636*795d594fSAndroid Build Coastguard Worker 
637*795d594fSAndroid Build Coastguard Worker       @Override
close()638*795d594fSAndroid Build Coastguard Worker       public void close() {
639*795d594fSAndroid Build Coastguard Worker           if (ptr != 0) {
640*795d594fSAndroid Build Coastguard Worker               jdkUnsafeTestFree(ptr);
641*795d594fSAndroid Build Coastguard Worker               ptr = 0;
642*795d594fSAndroid Build Coastguard Worker           }
643*795d594fSAndroid Build Coastguard Worker       }
644*795d594fSAndroid Build Coastguard Worker   }
645*795d594fSAndroid Build Coastguard Worker 
vmJdkArrayBaseOffset(Class<?> clazz)646*795d594fSAndroid Build Coastguard Worker   private static native int vmJdkArrayBaseOffset(Class<?> clazz);
vmJdkArrayIndexScale(Class<?> clazz)647*795d594fSAndroid Build Coastguard Worker   private static native int vmJdkArrayIndexScale(Class<?> clazz);
jdkUnsafeTestMalloc(long size)648*795d594fSAndroid Build Coastguard Worker   private static native long jdkUnsafeTestMalloc(long size);
jdkUnsafeTestFree(long memory)649*795d594fSAndroid Build Coastguard Worker   private static native void jdkUnsafeTestFree(long memory);
650*795d594fSAndroid Build Coastguard Worker }
651