1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /* 18 * sun.misc.Unsafe 19 */ 20 #include "Dalvik.h" 21 #include "native/InternalNativePriv.h" 22 23 24 /* 25 * private static native long objectFieldOffset0(Field field); 26 */ 27 static void Dalvik_sun_misc_Unsafe_objectFieldOffset0(const u4* args, 28 JValue* pResult) 29 { 30 Object* fieldObject = (Object*) args[0]; 31 InstField* field = (InstField*) dvmGetFieldFromReflectObj(fieldObject); 32 s8 result = ((s8) field->byteOffset); 33 34 RETURN_LONG(result); 35 } 36 37 /* 38 * private static native int arrayBaseOffset0(Class clazz); 39 */ 40 static void Dalvik_sun_misc_Unsafe_arrayBaseOffset0(const u4* args, 41 JValue* pResult) 42 { 43 // The base offset is not type-dependent in this vm. 44 UNUSED_PARAMETER(args); 45 RETURN_INT(OFFSETOF_MEMBER(ArrayObject, contents)); 46 } 47 48 /* 49 * private static native int arrayIndexScale0(Class clazz); 50 */ 51 static void Dalvik_sun_misc_Unsafe_arrayIndexScale0(const u4* args, 52 JValue* pResult) 53 { 54 ClassObject* clazz = (ClassObject*) args[0]; 55 RETURN_INT(dvmArrayClassElementWidth(clazz)); 56 } 57 58 /* 59 * public native boolean compareAndSwapInt(Object obj, long offset, 60 * int expectedValue, int newValue); 61 */ 62 static void Dalvik_sun_misc_Unsafe_compareAndSwapInt(const u4* args, 63 JValue* pResult) 64 { 65 // We ignore the this pointer in args[0]. 66 Object* obj = (Object*) args[1]; 67 s8 offset = GET_ARG_LONG(args, 2); 68 s4 expectedValue = args[4]; 69 s4 newValue = args[5]; 70 volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset); 71 72 // Note: android_atomic_release_cas() returns 0 on success, not failure. 73 int result = android_atomic_release_cas(expectedValue, newValue, address); 74 75 RETURN_BOOLEAN(result == 0); 76 } 77 78 /* 79 * public native boolean compareAndSwapLong(Object obj, long offset, 80 * long expectedValue, long newValue); 81 */ 82 static void Dalvik_sun_misc_Unsafe_compareAndSwapLong(const u4* args, 83 JValue* pResult) 84 { 85 // We ignore the this pointer in args[0]. 86 Object* obj = (Object*) args[1]; 87 s8 offset = GET_ARG_LONG(args, 2); 88 s8 expectedValue = GET_ARG_LONG(args, 4); 89 s8 newValue = GET_ARG_LONG(args, 6); 90 volatile int64_t* address = (volatile int64_t*) (((u1*) obj) + offset); 91 92 // Note: android_atomic_cmpxchg() returns 0 on success, not failure. 93 int result = 94 dvmQuasiAtomicCas64(expectedValue, newValue, address); 95 96 RETURN_BOOLEAN(result == 0); 97 } 98 99 /* 100 * public native boolean compareAndSwapObject(Object obj, long offset, 101 * Object expectedValue, Object newValue); 102 */ 103 static void Dalvik_sun_misc_Unsafe_compareAndSwapObject(const u4* args, 104 JValue* pResult) 105 { 106 // We ignore the this pointer in args[0]. 107 Object* obj = (Object*) args[1]; 108 s8 offset = GET_ARG_LONG(args, 2); 109 Object* expectedValue = (Object*) args[4]; 110 Object* newValue = (Object*) args[5]; 111 int32_t* address = (int32_t*) (((u1*) obj) + offset); 112 113 // Note: android_atomic_cmpxchg() returns 0 on success, not failure. 114 int result = android_atomic_release_cas((int32_t) expectedValue, 115 (int32_t) newValue, address); 116 dvmWriteBarrierField(obj, address); 117 RETURN_BOOLEAN(result == 0); 118 } 119 120 /* 121 * public native int getIntVolatile(Object obj, long offset); 122 */ 123 static void Dalvik_sun_misc_Unsafe_getIntVolatile(const u4* args, 124 JValue* pResult) 125 { 126 // We ignore the this pointer in args[0]. 127 Object* obj = (Object*) args[1]; 128 s8 offset = GET_ARG_LONG(args, 2); 129 volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset); 130 131 int32_t value = android_atomic_acquire_load(address); 132 RETURN_INT(value); 133 } 134 135 /* 136 * public native void putIntVolatile(Object obj, long offset, int newValue); 137 */ 138 static void Dalvik_sun_misc_Unsafe_putIntVolatile(const u4* args, 139 JValue* pResult) 140 { 141 // We ignore the this pointer in args[0]. 142 Object* obj = (Object*) args[1]; 143 s8 offset = GET_ARG_LONG(args, 2); 144 s4 value = (s4) args[4]; 145 volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset); 146 147 android_atomic_release_store(value, address); 148 RETURN_VOID(); 149 } 150 151 /* 152 * public native long getLongVolatile(Object obj, long offset); 153 */ 154 static void Dalvik_sun_misc_Unsafe_getLongVolatile(const u4* args, 155 JValue* pResult) 156 { 157 // We ignore the this pointer in args[0]. 158 Object* obj = (Object*) args[1]; 159 s8 offset = GET_ARG_LONG(args, 2); 160 volatile int64_t* address = (volatile int64_t*) (((u1*) obj) + offset); 161 162 assert((offset & 7) == 0); 163 RETURN_LONG(dvmQuasiAtomicRead64(address)); 164 } 165 166 /* 167 * public native void putLongVolatile(Object obj, long offset, long newValue); 168 */ 169 static void Dalvik_sun_misc_Unsafe_putLongVolatile(const u4* args, 170 JValue* pResult) 171 { 172 // We ignore the this pointer in args[0]. 173 Object* obj = (Object*) args[1]; 174 s8 offset = GET_ARG_LONG(args, 2); 175 s8 value = GET_ARG_LONG(args, 4); 176 volatile int64_t* address = (volatile int64_t*) (((u1*) obj) + offset); 177 178 assert((offset & 7) == 0); 179 dvmQuasiAtomicSwap64(value, address); 180 RETURN_VOID(); 181 } 182 183 /* 184 * public native Object getObjectVolatile(Object obj, long offset); 185 */ 186 static void Dalvik_sun_misc_Unsafe_getObjectVolatile(const u4* args, 187 JValue* pResult) 188 { 189 // We ignore the this pointer in args[0]. 190 Object* obj = (Object*) args[1]; 191 s8 offset = GET_ARG_LONG(args, 2); 192 volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset); 193 194 RETURN_PTR((Object*) android_atomic_acquire_load(address)); 195 } 196 197 /* 198 * public native void putObjectVolatile(Object obj, long offset, 199 * Object newValue); 200 */ 201 static void Dalvik_sun_misc_Unsafe_putObjectVolatile(const u4* args, 202 JValue* pResult) 203 { 204 // We ignore the this pointer in args[0]. 205 Object* obj = (Object*) args[1]; 206 s8 offset = GET_ARG_LONG(args, 2); 207 Object* value = (Object*) args[4]; 208 volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset); 209 210 android_atomic_release_store((int32_t)value, address); 211 dvmWriteBarrierField(obj, (void *)address); 212 RETURN_VOID(); 213 } 214 215 /* 216 * public native int getInt(Object obj, long offset); 217 */ 218 static void Dalvik_sun_misc_Unsafe_getInt(const u4* args, JValue* pResult) 219 { 220 // We ignore the this pointer in args[0]. 221 Object* obj = (Object*) args[1]; 222 s8 offset = GET_ARG_LONG(args, 2); 223 s4* address = (s4*) (((u1*) obj) + offset); 224 225 RETURN_INT(*address); 226 } 227 228 /* 229 * public native void putInt(Object obj, long offset, int newValue); 230 */ 231 static void Dalvik_sun_misc_Unsafe_putInt(const u4* args, JValue* pResult) 232 { 233 // We ignore the this pointer in args[0]. 234 Object* obj = (Object*) args[1]; 235 s8 offset = GET_ARG_LONG(args, 2); 236 s4 value = (s4) args[4]; 237 s4* address = (s4*) (((u1*) obj) + offset); 238 239 *address = value; 240 RETURN_VOID(); 241 } 242 243 /* 244 * public native void putOrderedInt(Object obj, long offset, int newValue); 245 */ 246 static void Dalvik_sun_misc_Unsafe_putOrderedInt(const u4* args, 247 JValue* pResult) 248 { 249 // We ignore the this pointer in args[0]. 250 Object* obj = (Object*) args[1]; 251 s8 offset = GET_ARG_LONG(args, 2); 252 s4 value = (s4) args[4]; 253 s4* address = (s4*) (((u1*) obj) + offset); 254 255 ANDROID_MEMBAR_STORE(); 256 *address = value; 257 RETURN_VOID(); 258 } 259 260 /* 261 * public native long getLong(Object obj, long offset); 262 */ 263 static void Dalvik_sun_misc_Unsafe_getLong(const u4* args, JValue* pResult) 264 { 265 // We ignore the this pointer in args[0]. 266 Object* obj = (Object*) args[1]; 267 s8 offset = GET_ARG_LONG(args, 2); 268 s8* address = (s8*) (((u1*) obj) + offset); 269 270 RETURN_LONG(*address); 271 } 272 273 /* 274 * public native void putLong(Object obj, long offset, long newValue); 275 */ 276 static void Dalvik_sun_misc_Unsafe_putLong(const u4* args, JValue* pResult) 277 { 278 // We ignore the this pointer in args[0]. 279 Object* obj = (Object*) args[1]; 280 s8 offset = GET_ARG_LONG(args, 2); 281 s8 value = GET_ARG_LONG(args, 4); 282 s8* address = (s8*) (((u1*) obj) + offset); 283 284 *address = value; 285 RETURN_VOID(); 286 } 287 288 /* 289 * public native void putOrderedLong(Object obj, long offset, long newValue); 290 */ 291 static void Dalvik_sun_misc_Unsafe_putOrderedLong(const u4* args, 292 JValue* pResult) 293 { 294 // We ignore the this pointer in args[0]. 295 Object* obj = (Object*) args[1]; 296 s8 offset = GET_ARG_LONG(args, 2); 297 s8 value = GET_ARG_LONG(args, 4); 298 s8* address = (s8*) (((u1*) obj) + offset); 299 300 ANDROID_MEMBAR_STORE(); 301 *address = value; 302 RETURN_VOID(); 303 } 304 305 /* 306 * public native Object getObject(Object obj, long offset); 307 */ 308 static void Dalvik_sun_misc_Unsafe_getObject(const u4* args, JValue* pResult) 309 { 310 // We ignore the this pointer in args[0]. 311 Object* obj = (Object*) args[1]; 312 s8 offset = GET_ARG_LONG(args, 2); 313 Object** address = (Object**) (((u1*) obj) + offset); 314 315 RETURN_PTR(*address); 316 } 317 318 /* 319 * public native void putObject(Object obj, long offset, Object newValue); 320 */ 321 static void Dalvik_sun_misc_Unsafe_putObject(const u4* args, JValue* pResult) 322 { 323 // We ignore the this pointer in args[0]. 324 Object* obj = (Object*) args[1]; 325 s8 offset = GET_ARG_LONG(args, 2); 326 Object* value = (Object*) args[4]; 327 Object** address = (Object**) (((u1*) obj) + offset); 328 329 *address = value; 330 dvmWriteBarrierField(obj, address); 331 RETURN_VOID(); 332 } 333 334 /* 335 * public native void putOrderedObject(Object obj, long offset, 336 * Object newValue); 337 */ 338 static void Dalvik_sun_misc_Unsafe_putOrderedObject(const u4* args, 339 JValue* pResult) 340 { 341 // We ignore the this pointer in args[0]. 342 Object* obj = (Object*) args[1]; 343 s8 offset = GET_ARG_LONG(args, 2); 344 Object* value = (Object*) args[4]; 345 Object** address = (Object**) (((u1*) obj) + offset); 346 347 ANDROID_MEMBAR_STORE(); 348 *address = value; 349 dvmWriteBarrierField(obj, address); 350 RETURN_VOID(); 351 } 352 353 const DalvikNativeMethod dvm_sun_misc_Unsafe[] = { 354 { "objectFieldOffset0", "(Ljava/lang/reflect/Field;)J", 355 Dalvik_sun_misc_Unsafe_objectFieldOffset0 }, 356 { "arrayBaseOffset0", "(Ljava/lang/Class;)I", 357 Dalvik_sun_misc_Unsafe_arrayBaseOffset0 }, 358 { "arrayIndexScale0", "(Ljava/lang/Class;)I", 359 Dalvik_sun_misc_Unsafe_arrayIndexScale0 }, 360 { "compareAndSwapInt", "(Ljava/lang/Object;JII)Z", 361 Dalvik_sun_misc_Unsafe_compareAndSwapInt }, 362 { "compareAndSwapLong", "(Ljava/lang/Object;JJJ)Z", 363 Dalvik_sun_misc_Unsafe_compareAndSwapLong }, 364 { "compareAndSwapObject", 365 "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", 366 Dalvik_sun_misc_Unsafe_compareAndSwapObject }, 367 { "getIntVolatile", "(Ljava/lang/Object;J)I", 368 Dalvik_sun_misc_Unsafe_getIntVolatile }, 369 { "putIntVolatile", "(Ljava/lang/Object;JI)V", 370 Dalvik_sun_misc_Unsafe_putIntVolatile }, 371 { "getLongVolatile", "(Ljava/lang/Object;J)J", 372 Dalvik_sun_misc_Unsafe_getLongVolatile }, 373 { "putLongVolatile", "(Ljava/lang/Object;JJ)V", 374 Dalvik_sun_misc_Unsafe_putLongVolatile }, 375 { "getObjectVolatile", "(Ljava/lang/Object;J)Ljava/lang/Object;", 376 Dalvik_sun_misc_Unsafe_getObjectVolatile }, 377 { "putObjectVolatile", "(Ljava/lang/Object;JLjava/lang/Object;)V", 378 Dalvik_sun_misc_Unsafe_putObjectVolatile }, 379 { "getInt", "(Ljava/lang/Object;J)I", 380 Dalvik_sun_misc_Unsafe_getInt }, 381 { "putInt", "(Ljava/lang/Object;JI)V", 382 Dalvik_sun_misc_Unsafe_putInt }, 383 { "putOrderedInt", "(Ljava/lang/Object;JI)V", 384 Dalvik_sun_misc_Unsafe_putOrderedInt }, 385 { "getLong", "(Ljava/lang/Object;J)J", 386 Dalvik_sun_misc_Unsafe_getLong }, 387 { "putLong", "(Ljava/lang/Object;JJ)V", 388 Dalvik_sun_misc_Unsafe_putLong }, 389 { "putOrderedLong", "(Ljava/lang/Object;JJ)V", 390 Dalvik_sun_misc_Unsafe_putOrderedLong }, 391 { "getObject", "(Ljava/lang/Object;J)Ljava/lang/Object;", 392 Dalvik_sun_misc_Unsafe_getObject }, 393 { "putObject", "(Ljava/lang/Object;JLjava/lang/Object;)V", 394 Dalvik_sun_misc_Unsafe_putObject }, 395 { "putOrderedObject", "(Ljava/lang/Object;JLjava/lang/Object;)V", 396 Dalvik_sun_misc_Unsafe_putOrderedObject }, 397 { NULL, NULL, NULL }, 398 }; 399