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 */ 27static 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 */ 40static 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 */ 51static void Dalvik_sun_misc_Unsafe_arrayIndexScale0(const u4* args, 52 JValue* pResult) 53{ 54 ClassObject* clazz = (ClassObject*) args[0]; 55 int result; 56 57 if ((clazz == gDvm.classArrayBoolean) || 58 (clazz == gDvm.classArrayByte)) { 59 result = sizeof(u1); 60 } else if ((clazz == gDvm.classArrayChar) || 61 (clazz == gDvm.classArrayShort)) { 62 result = sizeof(u2); 63 } else if ((clazz == gDvm.classArrayLong) || 64 (clazz == gDvm.classArrayDouble)) { 65 result = sizeof(u8); 66 } else { 67 result = sizeof(u4); 68 } 69 70 RETURN_INT(result); 71} 72 73/* 74 * public native boolean compareAndSwapInt(Object obj, long offset, 75 * int expectedValue, int newValue); 76 */ 77static void Dalvik_sun_misc_Unsafe_compareAndSwapInt(const u4* args, 78 JValue* pResult) 79{ 80 // We ignore the this pointer in args[0]. 81 Object* obj = (Object*) args[1]; 82 s8 offset = GET_ARG_LONG(args, 2); 83 s4 expectedValue = args[4]; 84 s4 newValue = args[5]; 85 volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset); 86 87 // Note: android_atomic_cmpxchg() returns 0 on success, not failure. 88 int result = android_atomic_cmpxchg(expectedValue, newValue, address); 89 90 RETURN_BOOLEAN(result == 0); 91} 92 93/* 94 * public native boolean compareAndSwapLong(Object obj, long offset, 95 * long expectedValue, long newValue); 96 */ 97static void Dalvik_sun_misc_Unsafe_compareAndSwapLong(const u4* args, 98 JValue* pResult) 99{ 100 // We ignore the this pointer in args[0]. 101 Object* obj = (Object*) args[1]; 102 s8 offset = GET_ARG_LONG(args, 2); 103 s8 expectedValue = GET_ARG_LONG(args, 4); 104 s8 newValue = GET_ARG_LONG(args, 6); 105 volatile int64_t* address = (volatile int64_t*) (((u1*) obj) + offset); 106 107 // Note: android_atomic_cmpxchg() returns 0 on success, not failure. 108 int result = 109 android_quasiatomic_cmpxchg_64(expectedValue, newValue, address); 110 111 RETURN_BOOLEAN(result == 0); 112} 113 114/* 115 * public native boolean compareAndSwapObject(Object obj, long offset, 116 * Object expectedValue, Object newValue); 117 */ 118static void Dalvik_sun_misc_Unsafe_compareAndSwapObject(const u4* args, 119 JValue* pResult) 120{ 121 // We ignore the this pointer in args[0]. 122 Object* obj = (Object*) args[1]; 123 s8 offset = GET_ARG_LONG(args, 2); 124 Object* expectedValue = (Object*) args[4]; 125 Object* newValue = (Object*) args[5]; 126 int32_t* address = (int32_t*) (((u1*) obj) + offset); 127 128 // Note: android_atomic_cmpxchg() returns 0 on success, not failure. 129 int result = android_atomic_cmpxchg((int32_t) expectedValue, 130 (int32_t) newValue, address); 131 132 RETURN_BOOLEAN(result == 0); 133} 134 135/* 136 * public native int getIntVolatile(Object obj, long offset); 137 */ 138static void Dalvik_sun_misc_Unsafe_getIntVolatile(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 volatile s4* address = (volatile s4*) (((u1*) obj) + offset); 145 146 RETURN_INT(*address); 147} 148 149/* 150 * public native void putIntVolatile(Object obj, long offset, int newValue); 151 */ 152static void Dalvik_sun_misc_Unsafe_putIntVolatile(const u4* args, 153 JValue* pResult) 154{ 155 // We ignore the this pointer in args[0]. 156 Object* obj = (Object*) args[1]; 157 s8 offset = GET_ARG_LONG(args, 2); 158 s4 value = (s4) args[4]; 159 volatile s4* address = (volatile s4*) (((u1*) obj) + offset); 160 161 *address = value; 162 RETURN_VOID(); 163} 164 165/* 166 * public native long getLongVolatile(Object obj, long offset); 167 */ 168static void Dalvik_sun_misc_Unsafe_getLongVolatile(const u4* args, 169 JValue* pResult) 170{ 171 // We ignore the this pointer in args[0]. 172 Object* obj = (Object*) args[1]; 173 s8 offset = GET_ARG_LONG(args, 2); 174 volatile s8* address = (volatile s8*) (((u1*) obj) + offset); 175 176 RETURN_LONG(android_quasiatomic_read_64(address)); 177} 178 179/* 180 * public native void putLongVolatile(Object obj, long offset, long newValue); 181 */ 182static void Dalvik_sun_misc_Unsafe_putLongVolatile(const u4* args, 183 JValue* pResult) 184{ 185 // We ignore the this pointer in args[0]. 186 Object* obj = (Object*) args[1]; 187 s8 offset = GET_ARG_LONG(args, 2); 188 s8 value = GET_ARG_LONG(args, 4); 189 volatile s8* address = (volatile s8*) (((u1*) obj) + offset); 190 191 android_quasiatomic_swap_64(value, address); 192 RETURN_VOID(); 193} 194 195/* 196 * public native Object getObjectVolatile(Object obj, long offset); 197 */ 198static void Dalvik_sun_misc_Unsafe_getObjectVolatile(const u4* args, 199 JValue* pResult) 200{ 201 // We ignore the this pointer in args[0]. 202 Object* obj = (Object*) args[1]; 203 s8 offset = GET_ARG_LONG(args, 2); 204 volatile Object** address = (volatile Object**) (((u1*) obj) + offset); 205 206 RETURN_PTR((void*) *address); 207} 208 209/* 210 * public native void putObjectVolatile(Object obj, long offset, 211 * Object newValue); 212 */ 213static void Dalvik_sun_misc_Unsafe_putObjectVolatile(const u4* args, 214 JValue* pResult) 215{ 216 // We ignore the this pointer in args[0]. 217 Object* obj = (Object*) args[1]; 218 s8 offset = GET_ARG_LONG(args, 2); 219 Object* value = (Object*) args[4]; 220 volatile Object** address = (volatile Object**) (((u1*) obj) + offset); 221 222 *address = value; 223 RETURN_VOID(); 224} 225 226/* 227 * public native int getInt(Object obj, long offset); 228 */ 229static void Dalvik_sun_misc_Unsafe_getInt(const u4* args, JValue* pResult) 230{ 231 // We ignore the this pointer in args[0]. 232 Object* obj = (Object*) args[1]; 233 s8 offset = GET_ARG_LONG(args, 2); 234 s4* address = (s4*) (((u1*) obj) + offset); 235 236 RETURN_INT(*address); 237} 238 239/* 240 * public native void putInt(Object obj, long offset, int newValue); 241 */ 242static void Dalvik_sun_misc_Unsafe_putInt(const u4* args, JValue* pResult) 243{ 244 // We ignore the this pointer in args[0]. 245 Object* obj = (Object*) args[1]; 246 s8 offset = GET_ARG_LONG(args, 2); 247 s4 value = (s4) args[4]; 248 s4* address = (s4*) (((u1*) obj) + offset); 249 250 *address = value; 251 RETURN_VOID(); 252} 253 254/* 255 * public native long getLong(Object obj, long offset); 256 */ 257static void Dalvik_sun_misc_Unsafe_getLong(const u4* args, JValue* pResult) 258{ 259 // We ignore the this pointer in args[0]. 260 Object* obj = (Object*) args[1]; 261 s8 offset = GET_ARG_LONG(args, 2); 262 s8* address = (s8*) (((u1*) obj) + offset); 263 264 RETURN_LONG(*address); 265} 266 267/* 268 * public native void putLong(Object obj, long offset, long newValue); 269 */ 270static void Dalvik_sun_misc_Unsafe_putLong(const u4* args, JValue* pResult) 271{ 272 // We ignore the this pointer in args[0]. 273 Object* obj = (Object*) args[1]; 274 s8 offset = GET_ARG_LONG(args, 2); 275 s8 value = GET_ARG_LONG(args, 4); 276 s8* address = (s8*) (((u1*) obj) + offset); 277 278 *address = value; 279 RETURN_VOID(); 280} 281 282/* 283 * public native Object getObject(Object obj, long offset); 284 */ 285static void Dalvik_sun_misc_Unsafe_getObject(const u4* args, JValue* pResult) 286{ 287 // We ignore the this pointer in args[0]. 288 Object* obj = (Object*) args[1]; 289 s8 offset = GET_ARG_LONG(args, 2); 290 Object** address = (Object**) (((u1*) obj) + offset); 291 292 RETURN_PTR(*address); 293} 294 295/* 296 * public native void putObject(Object obj, long offset, Object newValue); 297 */ 298static void Dalvik_sun_misc_Unsafe_putObject(const u4* args, JValue* pResult) 299{ 300 // We ignore the this pointer in args[0]. 301 Object* obj = (Object*) args[1]; 302 s8 offset = GET_ARG_LONG(args, 2); 303 Object* value = (Object*) args[4]; 304 Object** address = (Object**) (((u1*) obj) + offset); 305 306 *address = value; 307 RETURN_VOID(); 308} 309 310const DalvikNativeMethod dvm_sun_misc_Unsafe[] = { 311 { "objectFieldOffset0", "(Ljava/lang/reflect/Field;)J", 312 Dalvik_sun_misc_Unsafe_objectFieldOffset0 }, 313 { "arrayBaseOffset0", "(Ljava/lang/Class;)I", 314 Dalvik_sun_misc_Unsafe_arrayBaseOffset0 }, 315 { "arrayIndexScale0", "(Ljava/lang/Class;)I", 316 Dalvik_sun_misc_Unsafe_arrayIndexScale0 }, 317 { "compareAndSwapInt", "(Ljava/lang/Object;JII)Z", 318 Dalvik_sun_misc_Unsafe_compareAndSwapInt }, 319 { "compareAndSwapLong", "(Ljava/lang/Object;JJJ)Z", 320 Dalvik_sun_misc_Unsafe_compareAndSwapLong }, 321 { "compareAndSwapObject", 322 "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", 323 Dalvik_sun_misc_Unsafe_compareAndSwapObject }, 324 { "getIntVolatile", "(Ljava/lang/Object;J)I", 325 Dalvik_sun_misc_Unsafe_getIntVolatile }, 326 { "putIntVolatile", "(Ljava/lang/Object;JI)V", 327 Dalvik_sun_misc_Unsafe_putIntVolatile }, 328 { "getLongVolatile", "(Ljava/lang/Object;J)J", 329 Dalvik_sun_misc_Unsafe_getLongVolatile }, 330 { "putLongVolatile", "(Ljava/lang/Object;JJ)V", 331 Dalvik_sun_misc_Unsafe_putLongVolatile }, 332 { "getObjectVolatile", "(Ljava/lang/Object;J)Ljava/lang/Object;", 333 Dalvik_sun_misc_Unsafe_getObjectVolatile }, 334 { "putObjectVolatile", "(Ljava/lang/Object;JLjava/lang/Object;)V", 335 Dalvik_sun_misc_Unsafe_putObjectVolatile }, 336 { "getInt", "(Ljava/lang/Object;J)I", 337 Dalvik_sun_misc_Unsafe_getInt }, 338 { "putInt", "(Ljava/lang/Object;JI)V", 339 Dalvik_sun_misc_Unsafe_putInt }, 340 { "getLong", "(Ljava/lang/Object;J)J", 341 Dalvik_sun_misc_Unsafe_getLong }, 342 { "putLong", "(Ljava/lang/Object;JJ)V", 343 Dalvik_sun_misc_Unsafe_putLong }, 344 { "getObject", "(Ljava/lang/Object;J)Ljava/lang/Object;", 345 Dalvik_sun_misc_Unsafe_getObject }, 346 { "putObject", "(Ljava/lang/Object;JLjava/lang/Object;)V", 347 Dalvik_sun_misc_Unsafe_putObject }, 348 { NULL, NULL, NULL }, 349}; 350 351