diff options
Diffstat (limited to 'vm/native/sun_misc_Unsafe.c')
-rw-r--r-- | vm/native/sun_misc_Unsafe.c | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/vm/native/sun_misc_Unsafe.c b/vm/native/sun_misc_Unsafe.c new file mode 100644 index 0000000..9b9caba --- /dev/null +++ b/vm/native/sun_misc_Unsafe.c @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * sun.misc.Unsafe + */ +#include "Dalvik.h" +#include "native/InternalNativePriv.h" + + +/* + * private static native long objectFieldOffset0(Field field); + */ +static void Dalvik_sun_misc_Unsafe_objectFieldOffset0(const u4* args, + JValue* pResult) +{ + Object* fieldObject = (Object*) args[0]; + InstField* field = (InstField*) dvmGetFieldFromReflectObj(fieldObject); + s8 result = ((s8) field->byteOffset); + + RETURN_LONG(result); +} + +/* + * private static native int arrayBaseOffset0(Class clazz); + */ +static void Dalvik_sun_misc_Unsafe_arrayBaseOffset0(const u4* args, + JValue* pResult) +{ + // The base offset is not type-dependent in this vm. + UNUSED_PARAMETER(args); + RETURN_INT(offsetof(ArrayObject, contents)); +} + +/* + * private static native int arrayIndexScale0(Class clazz); + */ +static void Dalvik_sun_misc_Unsafe_arrayIndexScale0(const u4* args, + JValue* pResult) +{ + ClassObject* clazz = (ClassObject*) args[0]; + RETURN_INT(dvmArrayClassElementWidth(clazz)); +} + +/* + * public native boolean compareAndSwapInt(Object obj, long offset, + * int expectedValue, int newValue); + */ +static void Dalvik_sun_misc_Unsafe_compareAndSwapInt(const u4* args, + JValue* pResult) +{ + // We ignore the this pointer in args[0]. + Object* obj = (Object*) args[1]; + s8 offset = GET_ARG_LONG(args, 2); + s4 expectedValue = args[4]; + s4 newValue = args[5]; + volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset); + + // Note: android_atomic_release_cas() returns 0 on success, not failure. + int result = android_atomic_release_cas(expectedValue, newValue, address); + + RETURN_BOOLEAN(result == 0); +} + +/* + * public native boolean compareAndSwapLong(Object obj, long offset, + * long expectedValue, long newValue); + */ +static void Dalvik_sun_misc_Unsafe_compareAndSwapLong(const u4* args, + JValue* pResult) +{ + // We ignore the this pointer in args[0]. + Object* obj = (Object*) args[1]; + s8 offset = GET_ARG_LONG(args, 2); + s8 expectedValue = GET_ARG_LONG(args, 4); + s8 newValue = GET_ARG_LONG(args, 6); + volatile int64_t* address = (volatile int64_t*) (((u1*) obj) + offset); + + // Note: android_atomic_cmpxchg() returns 0 on success, not failure. + int result = + dvmQuasiAtomicCas64(expectedValue, newValue, address); + + RETURN_BOOLEAN(result == 0); +} + +/* + * public native boolean compareAndSwapObject(Object obj, long offset, + * Object expectedValue, Object newValue); + */ +static void Dalvik_sun_misc_Unsafe_compareAndSwapObject(const u4* args, + JValue* pResult) +{ + // We ignore the this pointer in args[0]. + Object* obj = (Object*) args[1]; + s8 offset = GET_ARG_LONG(args, 2); + Object* expectedValue = (Object*) args[4]; + Object* newValue = (Object*) args[5]; + int32_t* address = (int32_t*) (((u1*) obj) + offset); + + // Note: android_atomic_cmpxchg() returns 0 on success, not failure. + int result = android_atomic_release_cas((int32_t) expectedValue, + (int32_t) newValue, address); + dvmWriteBarrierField(obj, address); + RETURN_BOOLEAN(result == 0); +} + +/* + * public native int getIntVolatile(Object obj, long offset); + */ +static void Dalvik_sun_misc_Unsafe_getIntVolatile(const u4* args, + JValue* pResult) +{ + // We ignore the this pointer in args[0]. + Object* obj = (Object*) args[1]; + s8 offset = GET_ARG_LONG(args, 2); + volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset); + + int32_t value = android_atomic_acquire_load(address); + RETURN_INT(value); +} + +/* + * public native void putIntVolatile(Object obj, long offset, int newValue); + */ +static void Dalvik_sun_misc_Unsafe_putIntVolatile(const u4* args, + JValue* pResult) +{ + // We ignore the this pointer in args[0]. + Object* obj = (Object*) args[1]; + s8 offset = GET_ARG_LONG(args, 2); + s4 value = (s4) args[4]; + volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset); + + android_atomic_release_store(value, address); + RETURN_VOID(); +} + +/* + * public native long getLongVolatile(Object obj, long offset); + */ +static void Dalvik_sun_misc_Unsafe_getLongVolatile(const u4* args, + JValue* pResult) +{ + // We ignore the this pointer in args[0]. + Object* obj = (Object*) args[1]; + s8 offset = GET_ARG_LONG(args, 2); + volatile int64_t* address = (volatile int64_t*) (((u1*) obj) + offset); + + assert((offset & 7) == 0); + RETURN_LONG(dvmQuasiAtomicRead64(address)); +} + +/* + * public native void putLongVolatile(Object obj, long offset, long newValue); + */ +static void Dalvik_sun_misc_Unsafe_putLongVolatile(const u4* args, + JValue* pResult) +{ + // We ignore the this pointer in args[0]. + Object* obj = (Object*) args[1]; + s8 offset = GET_ARG_LONG(args, 2); + s8 value = GET_ARG_LONG(args, 4); + volatile int64_t* address = (volatile int64_t*) (((u1*) obj) + offset); + + assert((offset & 7) == 0); + dvmQuasiAtomicSwap64(value, address); + RETURN_VOID(); +} + +/* + * public native Object getObjectVolatile(Object obj, long offset); + */ +static void Dalvik_sun_misc_Unsafe_getObjectVolatile(const u4* args, + JValue* pResult) +{ + // We ignore the this pointer in args[0]. + Object* obj = (Object*) args[1]; + s8 offset = GET_ARG_LONG(args, 2); + volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset); + + RETURN_PTR((Object*) android_atomic_acquire_load(address)); +} + +/* + * public native void putObjectVolatile(Object obj, long offset, + * Object newValue); + */ +static void Dalvik_sun_misc_Unsafe_putObjectVolatile(const u4* args, + JValue* pResult) +{ + // We ignore the this pointer in args[0]. + Object* obj = (Object*) args[1]; + s8 offset = GET_ARG_LONG(args, 2); + Object* value = (Object*) args[4]; + volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset); + + android_atomic_release_store((int32_t)value, address); + dvmWriteBarrierField(obj, (void *)address); + RETURN_VOID(); +} + +/* + * public native int getInt(Object obj, long offset); + */ +static void Dalvik_sun_misc_Unsafe_getInt(const u4* args, JValue* pResult) +{ + // We ignore the this pointer in args[0]. + Object* obj = (Object*) args[1]; + s8 offset = GET_ARG_LONG(args, 2); + s4* address = (s4*) (((u1*) obj) + offset); + + RETURN_INT(*address); +} + +/* + * public native void putInt(Object obj, long offset, int newValue); + */ +static void Dalvik_sun_misc_Unsafe_putInt(const u4* args, JValue* pResult) +{ + // We ignore the this pointer in args[0]. + Object* obj = (Object*) args[1]; + s8 offset = GET_ARG_LONG(args, 2); + s4 value = (s4) args[4]; + s4* address = (s4*) (((u1*) obj) + offset); + + *address = value; + RETURN_VOID(); +} + +/* + * public native long getLong(Object obj, long offset); + */ +static void Dalvik_sun_misc_Unsafe_getLong(const u4* args, JValue* pResult) +{ + // We ignore the this pointer in args[0]. + Object* obj = (Object*) args[1]; + s8 offset = GET_ARG_LONG(args, 2); + s8* address = (s8*) (((u1*) obj) + offset); + + RETURN_LONG(*address); +} + +/* + * public native void putLong(Object obj, long offset, long newValue); + */ +static void Dalvik_sun_misc_Unsafe_putLong(const u4* args, JValue* pResult) +{ + // We ignore the this pointer in args[0]. + Object* obj = (Object*) args[1]; + s8 offset = GET_ARG_LONG(args, 2); + s8 value = GET_ARG_LONG(args, 4); + s8* address = (s8*) (((u1*) obj) + offset); + + *address = value; + RETURN_VOID(); +} + +/* + * public native Object getObject(Object obj, long offset); + */ +static void Dalvik_sun_misc_Unsafe_getObject(const u4* args, JValue* pResult) +{ + // We ignore the this pointer in args[0]. + Object* obj = (Object*) args[1]; + s8 offset = GET_ARG_LONG(args, 2); + Object** address = (Object**) (((u1*) obj) + offset); + + RETURN_PTR(*address); +} + +/* + * public native void putObject(Object obj, long offset, Object newValue); + */ +static void Dalvik_sun_misc_Unsafe_putObject(const u4* args, JValue* pResult) +{ + // We ignore the this pointer in args[0]. + Object* obj = (Object*) args[1]; + s8 offset = GET_ARG_LONG(args, 2); + Object* value = (Object*) args[4]; + Object** address = (Object**) (((u1*) obj) + offset); + + *address = value; + dvmWriteBarrierField(obj, address); + RETURN_VOID(); +} + +const DalvikNativeMethod dvm_sun_misc_Unsafe[] = { + { "objectFieldOffset0", "(Ljava/lang/reflect/Field;)J", + Dalvik_sun_misc_Unsafe_objectFieldOffset0 }, + { "arrayBaseOffset0", "(Ljava/lang/Class;)I", + Dalvik_sun_misc_Unsafe_arrayBaseOffset0 }, + { "arrayIndexScale0", "(Ljava/lang/Class;)I", + Dalvik_sun_misc_Unsafe_arrayIndexScale0 }, + { "compareAndSwapInt", "(Ljava/lang/Object;JII)Z", + Dalvik_sun_misc_Unsafe_compareAndSwapInt }, + { "compareAndSwapLong", "(Ljava/lang/Object;JJJ)Z", + Dalvik_sun_misc_Unsafe_compareAndSwapLong }, + { "compareAndSwapObject", + "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", + Dalvik_sun_misc_Unsafe_compareAndSwapObject }, + { "getIntVolatile", "(Ljava/lang/Object;J)I", + Dalvik_sun_misc_Unsafe_getIntVolatile }, + { "putIntVolatile", "(Ljava/lang/Object;JI)V", + Dalvik_sun_misc_Unsafe_putIntVolatile }, + { "getLongVolatile", "(Ljava/lang/Object;J)J", + Dalvik_sun_misc_Unsafe_getLongVolatile }, + { "putLongVolatile", "(Ljava/lang/Object;JJ)V", + Dalvik_sun_misc_Unsafe_putLongVolatile }, + { "getObjectVolatile", "(Ljava/lang/Object;J)Ljava/lang/Object;", + Dalvik_sun_misc_Unsafe_getObjectVolatile }, + { "putObjectVolatile", "(Ljava/lang/Object;JLjava/lang/Object;)V", + Dalvik_sun_misc_Unsafe_putObjectVolatile }, + { "getInt", "(Ljava/lang/Object;J)I", + Dalvik_sun_misc_Unsafe_getInt }, + { "putInt", "(Ljava/lang/Object;JI)V", + Dalvik_sun_misc_Unsafe_putInt }, + { "getLong", "(Ljava/lang/Object;J)J", + Dalvik_sun_misc_Unsafe_getLong }, + { "putLong", "(Ljava/lang/Object;JJ)V", + Dalvik_sun_misc_Unsafe_putLong }, + { "getObject", "(Ljava/lang/Object;J)Ljava/lang/Object;", + Dalvik_sun_misc_Unsafe_getObject }, + { "putObject", "(Ljava/lang/Object;JLjava/lang/Object;)V", + Dalvik_sun_misc_Unsafe_putObject }, + { NULL, NULL, NULL }, +}; |