blob: abb0d5cd5c58d21f9f1b048aac85a72e7e888ac6 [file] [log] [blame]
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -07001/*
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
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080017#include "atomic.h"
18#include "gc/card_table-inl.h"
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070019#include "jni_internal.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080020#include "mirror/object.h"
21#include "mirror/object-inl.h"
Ian Rogers00f7d0e2012-07-19 15:28:27 -070022#include "scoped_thread_state_change.h"
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070023
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070024namespace art {
25
Elliott Hughes0512f022012-03-15 22:10:52 -070026static jboolean Unsafe_compareAndSwapInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint expectedValue, jint newValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070027 ScopedObjectAccess soa(env);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080028 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070029 byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
30 volatile int32_t* address = reinterpret_cast<volatile int32_t*>(raw_addr);
31 // Note: android_atomic_release_cas() returns 0 on success, not failure.
32 int result = android_atomic_release_cas(expectedValue, newValue, address);
Ian Rogers9adbff52013-01-23 18:19:03 -080033 return (result == 0) ? JNI_TRUE : JNI_FALSE;
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070034}
35
Elliott Hughes0512f022012-03-15 22:10:52 -070036static jboolean Unsafe_compareAndSwapLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong expectedValue, jlong newValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070037 ScopedObjectAccess soa(env);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080038 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070039 byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
40 volatile int64_t* address = reinterpret_cast<volatile int64_t*>(raw_addr);
41 // Note: android_atomic_cmpxchg() returns 0 on success, not failure.
Ian Rogers9adbff52013-01-23 18:19:03 -080042 bool success = QuasiAtomic::Cas64(expectedValue, newValue, address);
43 return success ? JNI_TRUE : JNI_FALSE;
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070044}
45
Elliott Hughes0512f022012-03-15 22:10:52 -070046static jboolean Unsafe_compareAndSwapObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaExpectedValue, jobject javaNewValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070047 ScopedObjectAccess soa(env);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080048 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
49 mirror::Object* expectedValue = soa.Decode<mirror::Object*>(javaExpectedValue);
50 mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070051 byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
52 int32_t* address = reinterpret_cast<int32_t*>(raw_addr);
53 // Note: android_atomic_cmpxchg() returns 0 on success, not failure.
54 int result = android_atomic_release_cas(reinterpret_cast<int32_t>(expectedValue),
55 reinterpret_cast<int32_t>(newValue), address);
Ian Rogers5d76c432011-10-31 21:42:49 -070056 if (result == 0) {
Elliott Hughesb3bd5f02012-03-08 21:05:27 -080057 Runtime::Current()->GetHeap()->WriteBarrierField(obj, MemberOffset(offset), newValue);
Ian Rogers5d76c432011-10-31 21:42:49 -070058 }
Ian Rogers9adbff52013-01-23 18:19:03 -080059 return (result == 0) ? JNI_TRUE : JNI_FALSE;
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070060}
61
Elliott Hughes0512f022012-03-15 22:10:52 -070062static jint Unsafe_getInt(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070063 ScopedObjectAccess soa(env);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080064 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
Ian Rogers5d76c432011-10-31 21:42:49 -070065 return obj->GetField32(MemberOffset(offset), false);
66}
67
Elliott Hughes0512f022012-03-15 22:10:52 -070068static jint Unsafe_getIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070069 ScopedObjectAccess soa(env);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080070 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
Ian Rogers3eace702012-08-16 10:44:47 -070071 return obj->GetField32(MemberOffset(offset), true);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070072}
73
Elliott Hughes0512f022012-03-15 22:10:52 -070074static void Unsafe_putInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070075 ScopedObjectAccess soa(env);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080076 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
Ian Rogers5d76c432011-10-31 21:42:49 -070077 obj->SetField32(MemberOffset(offset), newValue, false);
78}
79
Elliott Hughes0512f022012-03-15 22:10:52 -070080static void Unsafe_putIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070081 ScopedObjectAccess soa(env);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080082 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
Ian Rogers3eace702012-08-16 10:44:47 -070083 obj->SetField32(MemberOffset(offset), newValue, true);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070084}
85
Elliott Hughes0512f022012-03-15 22:10:52 -070086static void Unsafe_putOrderedInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070087 ScopedObjectAccess soa(env);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080088 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070089 ANDROID_MEMBAR_STORE();
Ian Rogers5d76c432011-10-31 21:42:49 -070090 obj->SetField32(MemberOffset(offset), newValue, false);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070091}
92
Elliott Hughes0512f022012-03-15 22:10:52 -070093static jlong Unsafe_getLong(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070094 ScopedObjectAccess soa(env);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080095 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
Ian Rogers3eace702012-08-16 10:44:47 -070096 return obj->GetField64(MemberOffset(offset), false);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070097}
98
Elliott Hughes0512f022012-03-15 22:10:52 -070099static jlong Unsafe_getLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700100 ScopedObjectAccess soa(env);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800101 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
Ian Rogers5d76c432011-10-31 21:42:49 -0700102 return obj->GetField64(MemberOffset(offset), true);
103}
104
Elliott Hughes0512f022012-03-15 22:10:52 -0700105static void Unsafe_putLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700106 ScopedObjectAccess soa(env);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800107 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
Ian Rogers5d76c432011-10-31 21:42:49 -0700108 obj->SetField64(MemberOffset(offset), newValue, false);
109}
110
Elliott Hughes0512f022012-03-15 22:10:52 -0700111static void Unsafe_putLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700112 ScopedObjectAccess soa(env);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800113 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
Ian Rogers5d76c432011-10-31 21:42:49 -0700114 obj->SetField64(MemberOffset(offset), newValue, true);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700115}
116
Elliott Hughes0512f022012-03-15 22:10:52 -0700117static void Unsafe_putOrderedLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700118 ScopedObjectAccess soa(env);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800119 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700120 ANDROID_MEMBAR_STORE();
Ian Rogers5d76c432011-10-31 21:42:49 -0700121 obj->SetField64(MemberOffset(offset), newValue, false);
122}
123
Elliott Hughes0512f022012-03-15 22:10:52 -0700124static jobject Unsafe_getObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700125 ScopedObjectAccess soa(env);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800126 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
127 mirror::Object* value = obj->GetFieldObject<mirror::Object*>(MemberOffset(offset), true);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700128 return soa.AddLocalReference<jobject>(value);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700129}
130
Elliott Hughes0512f022012-03-15 22:10:52 -0700131static jobject Unsafe_getObject(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700132 ScopedObjectAccess soa(env);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800133 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
134 mirror::Object* value = obj->GetFieldObject<mirror::Object*>(MemberOffset(offset), false);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700135 return soa.AddLocalReference<jobject>(value);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700136}
137
Elliott Hughes0512f022012-03-15 22:10:52 -0700138static void Unsafe_putObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700139 ScopedObjectAccess soa(env);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800140 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
141 mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
Ian Rogers5d76c432011-10-31 21:42:49 -0700142 obj->SetFieldObject(MemberOffset(offset), newValue, false);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700143}
144
Elliott Hughes0512f022012-03-15 22:10:52 -0700145static void Unsafe_putObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700146 ScopedObjectAccess soa(env);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800147 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
148 mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
Ian Rogers5d76c432011-10-31 21:42:49 -0700149 obj->SetFieldObject(MemberOffset(offset), newValue, true);
150}
151
Elliott Hughes0512f022012-03-15 22:10:52 -0700152static void Unsafe_putOrderedObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700153 ScopedObjectAccess soa(env);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800154 mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
155 mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700156 ANDROID_MEMBAR_STORE();
Ian Rogers5d76c432011-10-31 21:42:49 -0700157 obj->SetFieldObject(MemberOffset(offset), newValue, false);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700158}
159
Elliott Hughes0512f022012-03-15 22:10:52 -0700160static JNINativeMethod gMethods[] = {
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700161 NATIVE_METHOD(Unsafe, compareAndSwapInt, "(Ljava/lang/Object;JII)Z"),
162 NATIVE_METHOD(Unsafe, compareAndSwapLong, "(Ljava/lang/Object;JJJ)Z"),
163 NATIVE_METHOD(Unsafe, compareAndSwapObject, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z"),
164 NATIVE_METHOD(Unsafe, getIntVolatile, "(Ljava/lang/Object;J)I"),
165 NATIVE_METHOD(Unsafe, putIntVolatile, "(Ljava/lang/Object;JI)V"),
166 NATIVE_METHOD(Unsafe, getLongVolatile, "(Ljava/lang/Object;J)J"),
167 NATIVE_METHOD(Unsafe, putLongVolatile, "(Ljava/lang/Object;JJ)V"),
168 NATIVE_METHOD(Unsafe, getObjectVolatile, "(Ljava/lang/Object;J)Ljava/lang/Object;"),
169 NATIVE_METHOD(Unsafe, putObjectVolatile, "(Ljava/lang/Object;JLjava/lang/Object;)V"),
170 NATIVE_METHOD(Unsafe, getInt, "(Ljava/lang/Object;J)I"),
171 NATIVE_METHOD(Unsafe, putInt, "(Ljava/lang/Object;JI)V"),
172 NATIVE_METHOD(Unsafe, putOrderedInt, "(Ljava/lang/Object;JI)V"),
173 NATIVE_METHOD(Unsafe, getLong, "(Ljava/lang/Object;J)J"),
174 NATIVE_METHOD(Unsafe, putLong, "(Ljava/lang/Object;JJ)V"),
175 NATIVE_METHOD(Unsafe, putOrderedLong, "(Ljava/lang/Object;JJ)V"),
176 NATIVE_METHOD(Unsafe, getObject, "(Ljava/lang/Object;J)Ljava/lang/Object;"),
177 NATIVE_METHOD(Unsafe, putObject, "(Ljava/lang/Object;JLjava/lang/Object;)V"),
178 NATIVE_METHOD(Unsafe, putOrderedObject, "(Ljava/lang/Object;JLjava/lang/Object;)V"),
179};
180
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700181void register_sun_misc_Unsafe(JNIEnv* env) {
Elliott Hugheseac76672012-05-24 21:56:51 -0700182 REGISTER_NATIVE_METHODS("sun/misc/Unsafe");
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700183}
184
185} // namespace art