/* * 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 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 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 void wait(long ms, int ns) throws InterruptedException */ static void Dalvik_java_lang_Object_wait(const u4* args, JValue* pResult, const Method* method, Thread* self) { Object* thisPtr = (Object*) args[0]; dvmObjectWait(self, thisPtr, GET_ARG_LONG(args,1), (s4)args[3], true); 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); }
/* * static void create(Thread t, long stacksize) * * This is eventually called as a result of Thread.start(). * * Throws an exception on failure. */ static void Dalvik_java_lang_VMThread_create(const u4* args, JValue* pResult) { Object* threadObj = (Object*) args[0]; s8 stackSize = GET_ARG_LONG(args, 1); /* copying collector will pin threadObj for us since it was an argument */ dvmCreateInterpThread(threadObj, (int) stackSize); 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 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(); }
/* * 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 void wait(long ms, int ns) throws InterruptedException */ static void Dalvik_java_lang_Object_wait(const u4* args, JValue* pResult, const Method* method, Thread* self) { Object* thisPtr = (Object*) args[0]; jlonglong millis = GET_ARG_LONG(args,1); jint nanos = (s4)args[3]; #ifdef FASTIVA void fastiva_Dalvik_java_lang_Object_wait(java_lang_Object_p self, jlonglong, jint); fastiva_Dalvik_java_lang_Object_wait(thisPtr, millis, nanos); }
/* * public native void putOrderedInt(Object obj, long offset, int newValue); */ static void Dalvik_sun_misc_Unsafe_putOrderedInt(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); ANDROID_MEMBAR_STORE(); *address = value; RETURN_VOID(); }
/* * 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 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 boolean trackExternalAllocation(long size) * * Asks the VM if <size> bytes can be allocated in an external heap. * This information may be used to limit the amount of memory available * to Dalvik threads. Returns false if the VM would rather that the caller * did not allocate that much memory. If the call returns false, the VM * will not update its internal counts. */ static void Dalvik_dalvik_system_VMRuntime_trackExternalAllocation( const u4* args, JValue* pResult) { s8 longSize = GET_ARG_LONG(args, 1); /* Fit in 32 bits. */ if (longSize < 0) { dvmThrowException("Ljava/lang/IllegalArgumentException;", "size must be positive"); RETURN_VOID(); } else if (longSize > INT_MAX) { dvmThrowException("Ljava/lang/UnsupportedOperationException;", "size must fit in 32 bits"); RETURN_VOID(); } RETURN_BOOLEAN(dvmTrackExternalAllocation((size_t)longSize)); }
/* * native long nativeMinimumHeapSize(long size, boolean set) * * If set is true, sets the new minimum heap size to size; always * returns the current (or previous) size. If size is negative or * zero, removes the current minimum constraint (if present). */ static void Dalvik_dalvik_system_VMRuntime_nativeMinimumHeapSize( const u4* args, JValue* pResult) { s8 longSize = GET_ARG_LONG(args, 1); size_t size; bool set = (args[3] != 0); /* Fit in 32 bits. */ if (longSize < 0) { size = 0; } else if (longSize > INT_MAX) { size = INT_MAX; } else { size = (size_t)longSize; } size = dvmMinimumHeapSize(size, set); RETURN_LONG(size); }
/* * static void sleep(long msec, int nsec) */ static void Dalvik_java_lang_VMThread_sleep(const u4* args, JValue* pResult) { dvmThreadSleep(GET_ARG_LONG(args,0), args[2]); RETURN_VOID(); }