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