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(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 long getLong(Object obj, long offset); 245 */ 246 static void Dalvik_sun_misc_Unsafe_getLong(const u4* args, JValue* pResult) 247 { 248 // We ignore the this pointer in args[0]. 249 Object* obj = (Object*) args[1]; 250 s8 offset = GET_ARG_LONG(args, 2); 251 s8* address = (s8*) (((u1*) obj) + offset); 252 253 RETURN_LONG(*address); 254 } 255 256 /* 257 * public native void putLong(Object obj, long offset, long newValue); 258 */ 259 static void Dalvik_sun_misc_Unsafe_putLong(const u4* args, JValue* pResult) 260 { 261 // We ignore the this pointer in args[0]. 262 Object* obj = (Object*) args[1]; 263 s8 offset = GET_ARG_LONG(args, 2); 264 s8 value = GET_ARG_LONG(args, 4); 265 s8* address = (s8*) (((u1*) obj) + offset); 266 267 *address = value; 268 RETURN_VOID(); 269 } 270 271 /* 272 * public native Object getObject(Object obj, long offset); 273 */ 274 static void Dalvik_sun_misc_Unsafe_getObject(const u4* args, JValue* pResult) 275 { 276 // We ignore the this pointer in args[0]. 277 Object* obj = (Object*) args[1]; 278 s8 offset = GET_ARG_LONG(args, 2); 279 Object** address = (Object**) (((u1*) obj) + offset); 280 281 RETURN_PTR(*address); 282 } 283 284 /* 285 * public native void putObject(Object obj, long offset, Object newValue); 286 */ 287 static void Dalvik_sun_misc_Unsafe_putObject(const u4* args, JValue* pResult) 288 { 289 // We ignore the this pointer in args[0]. 290 Object* obj = (Object*) args[1]; 291 s8 offset = GET_ARG_LONG(args, 2); 292 Object* value = (Object*) args[4]; 293 Object** address = (Object**) (((u1*) obj) + offset); 294 295 *address = value; 296 dvmWriteBarrierField(obj, address); 297 RETURN_VOID(); 298 } 299 300 const DalvikNativeMethod dvm_sun_misc_Unsafe[] = { 301 { "objectFieldOffset0", "(Ljava/lang/reflect/Field;)J", 302 Dalvik_sun_misc_Unsafe_objectFieldOffset0 }, 303 { "arrayBaseOffset0", "(Ljava/lang/Class;)I", 304 Dalvik_sun_misc_Unsafe_arrayBaseOffset0 }, 305 { "arrayIndexScale0", "(Ljava/lang/Class;)I", 306 Dalvik_sun_misc_Unsafe_arrayIndexScale0 }, 307 { "compareAndSwapInt", "(Ljava/lang/Object;JII)Z", 308 Dalvik_sun_misc_Unsafe_compareAndSwapInt }, 309 { "compareAndSwapLong", "(Ljava/lang/Object;JJJ)Z", 310 Dalvik_sun_misc_Unsafe_compareAndSwapLong }, 311 { "compareAndSwapObject", 312 "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", 313 Dalvik_sun_misc_Unsafe_compareAndSwapObject }, 314 { "getIntVolatile", "(Ljava/lang/Object;J)I", 315 Dalvik_sun_misc_Unsafe_getIntVolatile }, 316 { "putIntVolatile", "(Ljava/lang/Object;JI)V", 317 Dalvik_sun_misc_Unsafe_putIntVolatile }, 318 { "getLongVolatile", "(Ljava/lang/Object;J)J", 319 Dalvik_sun_misc_Unsafe_getLongVolatile }, 320 { "putLongVolatile", "(Ljava/lang/Object;JJ)V", 321 Dalvik_sun_misc_Unsafe_putLongVolatile }, 322 { "getObjectVolatile", "(Ljava/lang/Object;J)Ljava/lang/Object;", 323 Dalvik_sun_misc_Unsafe_getObjectVolatile }, 324 { "putObjectVolatile", "(Ljava/lang/Object;JLjava/lang/Object;)V", 325 Dalvik_sun_misc_Unsafe_putObjectVolatile }, 326 { "getInt", "(Ljava/lang/Object;J)I", 327 Dalvik_sun_misc_Unsafe_getInt }, 328 { "putInt", "(Ljava/lang/Object;JI)V", 329 Dalvik_sun_misc_Unsafe_putInt }, 330 { "getLong", "(Ljava/lang/Object;J)J", 331 Dalvik_sun_misc_Unsafe_getLong }, 332 { "putLong", "(Ljava/lang/Object;JJ)V", 333 Dalvik_sun_misc_Unsafe_putLong }, 334 { "getObject", "(Ljava/lang/Object;J)Ljava/lang/Object;", 335 Dalvik_sun_misc_Unsafe_getObject }, 336 { "putObject", "(Ljava/lang/Object;JLjava/lang/Object;)V", 337 Dalvik_sun_misc_Unsafe_putObject }, 338 { NULL, NULL, NULL }, 339 }; 340