blob: 282731dc8d1a9d7ffcbe30dc60ebfc918123fa74 [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
17#include "jni_internal.h"
18#include "object.h"
Ian Rogers00f7d0e2012-07-19 15:28:27 -070019#include "scoped_thread_state_change.h"
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070020
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070021namespace art {
22
Elliott Hughes0512f022012-03-15 22:10:52 -070023static jlong Unsafe_objectFieldOffset0(JNIEnv* env, jclass, jobject javaField) {
Ian Rogersa15e67d2012-02-28 13:51:55 -080024 // TODO: move to Java code
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070025 jfieldID fid = env->FromReflectedField(javaField);
Ian Rogers00f7d0e2012-07-19 15:28:27 -070026 ScopedObjectAccess soa(env);
27 Field* field = soa.DecodeField(fid);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070028 return field->GetOffset().Int32Value();
29}
30
Elliott Hughes0512f022012-03-15 22:10:52 -070031static jint Unsafe_arrayBaseOffset0(JNIEnv* env, jclass, jclass javaArrayClass) {
Ian Rogersa15e67d2012-02-28 13:51:55 -080032 // TODO: move to Java code
Ian Rogers00f7d0e2012-07-19 15:28:27 -070033 ScopedObjectAccess soa(env);
34 Class* array_class = soa.Decode<Class*>(javaArrayClass);
Ian Rogersa15e67d2012-02-28 13:51:55 -080035 return Array::DataOffset(array_class->GetComponentSize()).Int32Value();
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070036}
37
Elliott Hughes0512f022012-03-15 22:10:52 -070038static jint Unsafe_arrayIndexScale0(JNIEnv* env, jclass, jclass javaClass) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070039 ScopedObjectAccess soa(env);
40 Class* c = soa.Decode<Class*>(javaClass);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070041 return c->GetComponentSize();
42}
43
Elliott Hughes0512f022012-03-15 22:10:52 -070044static jboolean Unsafe_compareAndSwapInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint expectedValue, jint newValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070045 ScopedObjectAccess soa(env);
46 Object* obj = soa.Decode<Object*>(javaObj);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070047 byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
48 volatile int32_t* address = reinterpret_cast<volatile int32_t*>(raw_addr);
49 // Note: android_atomic_release_cas() returns 0 on success, not failure.
50 int result = android_atomic_release_cas(expectedValue, newValue, address);
51 return (result == 0);
52}
53
Elliott Hughes0512f022012-03-15 22:10:52 -070054static jboolean Unsafe_compareAndSwapLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong expectedValue, jlong newValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070055 ScopedObjectAccess soa(env);
56 Object* obj = soa.Decode<Object*>(javaObj);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070057 byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
58 volatile int64_t* address = reinterpret_cast<volatile int64_t*>(raw_addr);
59 // Note: android_atomic_cmpxchg() returns 0 on success, not failure.
Elliott Hughes7c6169d2012-05-02 16:11:48 -070060 int result = QuasiAtomic::Cas64(expectedValue, newValue, address);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070061 return (result == 0);
62}
63
Elliott Hughes0512f022012-03-15 22:10:52 -070064static jboolean Unsafe_compareAndSwapObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaExpectedValue, jobject javaNewValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070065 ScopedObjectAccess soa(env);
66 Object* obj = soa.Decode<Object*>(javaObj);
67 Object* expectedValue = soa.Decode<Object*>(javaExpectedValue);
68 Object* newValue = soa.Decode<Object*>(javaNewValue);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070069 byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
70 int32_t* address = reinterpret_cast<int32_t*>(raw_addr);
71 // Note: android_atomic_cmpxchg() returns 0 on success, not failure.
72 int result = android_atomic_release_cas(reinterpret_cast<int32_t>(expectedValue),
73 reinterpret_cast<int32_t>(newValue), address);
Ian Rogers5d76c432011-10-31 21:42:49 -070074 if (result == 0) {
Elliott Hughesb3bd5f02012-03-08 21:05:27 -080075 Runtime::Current()->GetHeap()->WriteBarrierField(obj, MemberOffset(offset), newValue);
Ian Rogers5d76c432011-10-31 21:42:49 -070076 }
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070077 return (result == 0);
78}
79
Elliott Hughes0512f022012-03-15 22:10:52 -070080static jint Unsafe_getInt(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070081 ScopedObjectAccess soa(env);
82 Object* obj = soa.Decode<Object*>(javaObj);
Ian Rogers5d76c432011-10-31 21:42:49 -070083 return obj->GetField32(MemberOffset(offset), false);
84}
85
Elliott Hughes0512f022012-03-15 22:10:52 -070086static jint Unsafe_getIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070087 ScopedObjectAccess soa(env);
88 Object* obj = soa.Decode<Object*>(javaObj);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -070089 byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
90 volatile int32_t* address = reinterpret_cast<volatile int32_t*>(raw_addr);
91 return android_atomic_acquire_load(address);
92}
93
Elliott Hughes0512f022012-03-15 22:10:52 -070094static void Unsafe_putInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070095 ScopedObjectAccess soa(env);
96 Object* obj = soa.Decode<Object*>(javaObj);
Ian Rogers5d76c432011-10-31 21:42:49 -070097 obj->SetField32(MemberOffset(offset), newValue, false);
98}
99
Elliott Hughes0512f022012-03-15 22:10:52 -0700100static void Unsafe_putIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700101 ScopedObjectAccess soa(env);
102 Object* obj = soa.Decode<Object*>(javaObj);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700103 byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
104 volatile int32_t* address = reinterpret_cast<volatile int32_t*>(raw_addr);
105 android_atomic_release_store(newValue, address);
106}
107
Elliott Hughes0512f022012-03-15 22:10:52 -0700108static void Unsafe_putOrderedInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700109 ScopedObjectAccess soa(env);
110 Object* obj = soa.Decode<Object*>(javaObj);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700111 ANDROID_MEMBAR_STORE();
Ian Rogers5d76c432011-10-31 21:42:49 -0700112 obj->SetField32(MemberOffset(offset), newValue, false);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700113}
114
Elliott Hughes0512f022012-03-15 22:10:52 -0700115static jlong Unsafe_getLong(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700116 ScopedObjectAccess soa(env);
117 Object* obj = soa.Decode<Object*>(javaObj);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700118 byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
119 int64_t* address = reinterpret_cast<int64_t*>(raw_addr);
120 return *address;
121}
122
Elliott Hughes0512f022012-03-15 22:10:52 -0700123static jlong Unsafe_getLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700124 ScopedObjectAccess soa(env);
125 Object* obj = soa.Decode<Object*>(javaObj);
Ian Rogers5d76c432011-10-31 21:42:49 -0700126 return obj->GetField64(MemberOffset(offset), true);
127}
128
Elliott Hughes0512f022012-03-15 22:10:52 -0700129static void Unsafe_putLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700130 ScopedObjectAccess soa(env);
131 Object* obj = soa.Decode<Object*>(javaObj);
Ian Rogers5d76c432011-10-31 21:42:49 -0700132 obj->SetField64(MemberOffset(offset), newValue, false);
133}
134
Elliott Hughes0512f022012-03-15 22:10:52 -0700135static void Unsafe_putLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700136 ScopedObjectAccess soa(env);
137 Object* obj = soa.Decode<Object*>(javaObj);
Ian Rogers5d76c432011-10-31 21:42:49 -0700138 obj->SetField64(MemberOffset(offset), newValue, true);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700139}
140
Elliott Hughes0512f022012-03-15 22:10:52 -0700141static void Unsafe_putOrderedLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700142 ScopedObjectAccess soa(env);
143 Object* obj = soa.Decode<Object*>(javaObj);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700144 ANDROID_MEMBAR_STORE();
Ian Rogers5d76c432011-10-31 21:42:49 -0700145 obj->SetField64(MemberOffset(offset), newValue, false);
146}
147
Elliott Hughes0512f022012-03-15 22:10:52 -0700148static jobject Unsafe_getObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700149 ScopedObjectAccess soa(env);
150 Object* obj = soa.Decode<Object*>(javaObj);
Ian Rogers5d76c432011-10-31 21:42:49 -0700151 Object* value = obj->GetFieldObject<Object*>(MemberOffset(offset), true);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700152 return soa.AddLocalReference<jobject>(value);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700153}
154
Elliott Hughes0512f022012-03-15 22:10:52 -0700155static jobject Unsafe_getObject(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700156 ScopedObjectAccess soa(env);
157 Object* obj = soa.Decode<Object*>(javaObj);
Ian Rogers5d76c432011-10-31 21:42:49 -0700158 Object* value = obj->GetFieldObject<Object*>(MemberOffset(offset), false);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700159 return soa.AddLocalReference<jobject>(value);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700160}
161
Elliott Hughes0512f022012-03-15 22:10:52 -0700162static void Unsafe_putObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700163 ScopedObjectAccess soa(env);
164 Object* obj = soa.Decode<Object*>(javaObj);
165 Object* newValue = soa.Decode<Object*>(javaNewValue);
Ian Rogers5d76c432011-10-31 21:42:49 -0700166 obj->SetFieldObject(MemberOffset(offset), newValue, false);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700167}
168
Elliott Hughes0512f022012-03-15 22:10:52 -0700169static void Unsafe_putObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700170 ScopedObjectAccess soa(env);
171 Object* obj = soa.Decode<Object*>(javaObj);
172 Object* newValue = soa.Decode<Object*>(javaNewValue);
Ian Rogers5d76c432011-10-31 21:42:49 -0700173 obj->SetFieldObject(MemberOffset(offset), newValue, true);
174}
175
Elliott Hughes0512f022012-03-15 22:10:52 -0700176static void Unsafe_putOrderedObject(JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700177 ScopedObjectAccess soa(env);
178 Object* obj = soa.Decode<Object*>(javaObj);
179 Object* newValue = soa.Decode<Object*>(javaNewValue);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700180 ANDROID_MEMBAR_STORE();
Ian Rogers5d76c432011-10-31 21:42:49 -0700181 obj->SetFieldObject(MemberOffset(offset), newValue, false);
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700182}
183
Elliott Hughes0512f022012-03-15 22:10:52 -0700184static JNINativeMethod gMethods[] = {
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700185 NATIVE_METHOD(Unsafe, objectFieldOffset0, "(Ljava/lang/reflect/Field;)J"),
186 NATIVE_METHOD(Unsafe, arrayBaseOffset0, "(Ljava/lang/Class;)I"),
187 NATIVE_METHOD(Unsafe, arrayIndexScale0, "(Ljava/lang/Class;)I"),
188 NATIVE_METHOD(Unsafe, compareAndSwapInt, "(Ljava/lang/Object;JII)Z"),
189 NATIVE_METHOD(Unsafe, compareAndSwapLong, "(Ljava/lang/Object;JJJ)Z"),
190 NATIVE_METHOD(Unsafe, compareAndSwapObject, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z"),
191 NATIVE_METHOD(Unsafe, getIntVolatile, "(Ljava/lang/Object;J)I"),
192 NATIVE_METHOD(Unsafe, putIntVolatile, "(Ljava/lang/Object;JI)V"),
193 NATIVE_METHOD(Unsafe, getLongVolatile, "(Ljava/lang/Object;J)J"),
194 NATIVE_METHOD(Unsafe, putLongVolatile, "(Ljava/lang/Object;JJ)V"),
195 NATIVE_METHOD(Unsafe, getObjectVolatile, "(Ljava/lang/Object;J)Ljava/lang/Object;"),
196 NATIVE_METHOD(Unsafe, putObjectVolatile, "(Ljava/lang/Object;JLjava/lang/Object;)V"),
197 NATIVE_METHOD(Unsafe, getInt, "(Ljava/lang/Object;J)I"),
198 NATIVE_METHOD(Unsafe, putInt, "(Ljava/lang/Object;JI)V"),
199 NATIVE_METHOD(Unsafe, putOrderedInt, "(Ljava/lang/Object;JI)V"),
200 NATIVE_METHOD(Unsafe, getLong, "(Ljava/lang/Object;J)J"),
201 NATIVE_METHOD(Unsafe, putLong, "(Ljava/lang/Object;JJ)V"),
202 NATIVE_METHOD(Unsafe, putOrderedLong, "(Ljava/lang/Object;JJ)V"),
203 NATIVE_METHOD(Unsafe, getObject, "(Ljava/lang/Object;J)Ljava/lang/Object;"),
204 NATIVE_METHOD(Unsafe, putObject, "(Ljava/lang/Object;JLjava/lang/Object;)V"),
205 NATIVE_METHOD(Unsafe, putOrderedObject, "(Ljava/lang/Object;JLjava/lang/Object;)V"),
206};
207
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700208void register_sun_misc_Unsafe(JNIEnv* env) {
Elliott Hugheseac76672012-05-24 21:56:51 -0700209 REGISTER_NATIVE_METHODS("sun/misc/Unsafe");
Elliott Hughes5ee7a8b2011-09-13 16:40:07 -0700210}
211
212} // namespace art