sun_misc_Unsafe.cc revision b122a4bbed34ab22b4c1541ee25e5cf22f12a926
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#include "atomic.h"
18#include "gc/accounting/card_table-inl.h"
19#include "jni_internal.h"
20#include "mirror/object.h"
21#include "mirror/object-inl.h"
22#include "scoped_fast_native_object_access.h"
23
24namespace art {
25
26static jboolean Unsafe_compareAndSwapInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint expectedValue, jint newValue) {
27  ScopedFastNativeObjectAccess soa(env);
28  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
29  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);
33  return (result == 0) ? JNI_TRUE : JNI_FALSE;
34}
35
36static jboolean Unsafe_compareAndSwapLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong expectedValue, jlong newValue) {
37  ScopedFastNativeObjectAccess soa(env);
38  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
39  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.
42  bool success = QuasiAtomic::Cas64(expectedValue, newValue, address);
43  return success ? JNI_TRUE : JNI_FALSE;
44}
45
46static jboolean Unsafe_compareAndSwapObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaExpectedValue, jobject javaNewValue) {
47  ScopedFastNativeObjectAccess soa(env);
48  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);
51  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);
56  if (result == 0) {
57    Runtime::Current()->GetHeap()->WriteBarrierField(obj, MemberOffset(offset), newValue);
58  }
59  return (result == 0) ? JNI_TRUE : JNI_FALSE;
60}
61
62static jint Unsafe_getInt(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
63  ScopedFastNativeObjectAccess soa(env);
64  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
65  return obj->GetField32(MemberOffset(offset), false);
66}
67
68static jint Unsafe_getIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
69  ScopedFastNativeObjectAccess soa(env);
70  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
71  return obj->GetField32(MemberOffset(offset), true);
72}
73
74static void Unsafe_putInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) {
75  ScopedFastNativeObjectAccess soa(env);
76  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
77  obj->SetField32(MemberOffset(offset), newValue, false);
78}
79
80static void Unsafe_putIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) {
81  ScopedFastNativeObjectAccess soa(env);
82  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
83  obj->SetField32(MemberOffset(offset), newValue, true);
84}
85
86static void Unsafe_putOrderedInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) {
87  ScopedFastNativeObjectAccess soa(env);
88  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
89  QuasiAtomic::MembarStoreStore();
90  obj->SetField32(MemberOffset(offset), newValue, false);
91}
92
93static jlong Unsafe_getLong(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
94  ScopedFastNativeObjectAccess soa(env);
95  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
96  return obj->GetField64(MemberOffset(offset), false);
97}
98
99static jlong Unsafe_getLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
100  ScopedFastNativeObjectAccess soa(env);
101  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
102  return obj->GetField64(MemberOffset(offset), true);
103}
104
105static void Unsafe_putLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) {
106  ScopedFastNativeObjectAccess soa(env);
107  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
108  obj->SetField64(MemberOffset(offset), newValue, false);
109}
110
111static void Unsafe_putLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) {
112  ScopedFastNativeObjectAccess soa(env);
113  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
114  obj->SetField64(MemberOffset(offset), newValue, true);
115}
116
117static void Unsafe_putOrderedLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) {
118  ScopedFastNativeObjectAccess soa(env);
119  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
120  QuasiAtomic::MembarStoreStore();
121  obj->SetField64(MemberOffset(offset), newValue, false);
122}
123
124static jobject Unsafe_getObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
125  ScopedFastNativeObjectAccess soa(env);
126  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
127  mirror::Object* value = obj->GetFieldObject<mirror::Object*>(MemberOffset(offset), true);
128  return soa.AddLocalReference<jobject>(value);
129}
130
131static jobject Unsafe_getObject(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
132  ScopedFastNativeObjectAccess soa(env);
133  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
134  mirror::Object* value = obj->GetFieldObject<mirror::Object*>(MemberOffset(offset), false);
135  return soa.AddLocalReference<jobject>(value);
136}
137
138static void Unsafe_putObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) {
139  ScopedFastNativeObjectAccess soa(env);
140  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
141  mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
142  obj->SetFieldObject(MemberOffset(offset), newValue, false);
143}
144
145static void Unsafe_putObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) {
146  ScopedFastNativeObjectAccess soa(env);
147  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
148  mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
149  obj->SetFieldObject(MemberOffset(offset), newValue, true);
150}
151
152static void Unsafe_putOrderedObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) {
153  ScopedFastNativeObjectAccess soa(env);
154  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
155  mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
156  QuasiAtomic::MembarStoreStore();
157  obj->SetFieldObject(MemberOffset(offset), newValue, false);
158}
159
160static JNINativeMethod gMethods[] = {
161  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
181void register_sun_misc_Unsafe(JNIEnv* env) {
182  REGISTER_NATIVE_METHODS("sun/misc/Unsafe");
183}
184
185}  // namespace art
186