blob: b3c7141811c5c0445569df2d4be2945e40c06fce [file] [log] [blame]
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001/*
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/*
18 * sun.misc.Unsafe
19 */
20#include "Dalvik.h"
21#include "native/InternalNativePriv.h"
22
23
24/*
25 * private static native long objectFieldOffset0(Field field);
26 */
27static void Dalvik_sun_misc_Unsafe_objectFieldOffset0(const u4* args,
28 JValue* pResult)
29{
30 Object* fieldObject = (Object*) args[0];
31 InstField* field = (InstField*) dvmGetFieldFromReflectObj(fieldObject);
32 s8 result = ((s8) field->byteOffset);
33
34 RETURN_LONG(result);
35}
36
37/*
38 * private static native int arrayBaseOffset0(Class clazz);
39 */
40static void Dalvik_sun_misc_Unsafe_arrayBaseOffset0(const u4* args,
41 JValue* pResult)
42{
43 // The base offset is not type-dependent in this vm.
44 UNUSED_PARAMETER(args);
45 RETURN_INT(offsetof(ArrayObject, contents));
46}
47
48/*
49 * private static native int arrayIndexScale0(Class clazz);
50 */
51static void Dalvik_sun_misc_Unsafe_arrayIndexScale0(const u4* args,
52 JValue* pResult)
53{
54 ClassObject* clazz = (ClassObject*) args[0];
55 int result;
56
57 if ((clazz == gDvm.classArrayBoolean) ||
58 (clazz == gDvm.classArrayByte)) {
59 result = sizeof(u1);
60 } else if ((clazz == gDvm.classArrayChar) ||
61 (clazz == gDvm.classArrayShort)) {
62 result = sizeof(u2);
63 } else if ((clazz == gDvm.classArrayLong) ||
64 (clazz == gDvm.classArrayDouble)) {
65 result = sizeof(u8);
66 } else {
67 result = sizeof(u4);
68 }
69
70 RETURN_INT(result);
71}
72
73/*
74 * public native boolean compareAndSwapInt(Object obj, long offset,
75 * int expectedValue, int newValue);
76 */
77static void Dalvik_sun_misc_Unsafe_compareAndSwapInt(const u4* args,
78 JValue* pResult)
79{
80 // We ignore the this pointer in args[0].
81 Object* obj = (Object*) args[1];
82 s8 offset = GET_ARG_LONG(args, 2);
83 s4 expectedValue = args[4];
84 s4 newValue = args[5];
85 volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset);
86
Andy McFaddendeeeeb22010-06-16 08:32:04 -070087 // Note: android_atomic_release_cas() returns 0 on success, not failure.
88 int result = android_atomic_release_cas(expectedValue, newValue, address);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080089
90 RETURN_BOOLEAN(result == 0);
91}
92
93/*
94 * public native boolean compareAndSwapLong(Object obj, long offset,
95 * long expectedValue, long newValue);
96 */
97static void Dalvik_sun_misc_Unsafe_compareAndSwapLong(const u4* args,
98 JValue* pResult)
99{
100 // We ignore the this pointer in args[0].
101 Object* obj = (Object*) args[1];
102 s8 offset = GET_ARG_LONG(args, 2);
103 s8 expectedValue = GET_ARG_LONG(args, 4);
104 s8 newValue = GET_ARG_LONG(args, 6);
105 volatile int64_t* address = (volatile int64_t*) (((u1*) obj) + offset);
106
107 // Note: android_atomic_cmpxchg() returns 0 on success, not failure.
108 int result =
Andy McFadden6e10b9a2010-06-14 15:24:39 -0700109 dvmQuasiAtomicCas64(expectedValue, newValue, address);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800110
111 RETURN_BOOLEAN(result == 0);
112}
113
114/*
115 * public native boolean compareAndSwapObject(Object obj, long offset,
116 * Object expectedValue, Object newValue);
117 */
118static void Dalvik_sun_misc_Unsafe_compareAndSwapObject(const u4* args,
119 JValue* pResult)
120{
121 // We ignore the this pointer in args[0].
122 Object* obj = (Object*) args[1];
123 s8 offset = GET_ARG_LONG(args, 2);
124 Object* expectedValue = (Object*) args[4];
125 Object* newValue = (Object*) args[5];
126 int32_t* address = (int32_t*) (((u1*) obj) + offset);
127
128 // Note: android_atomic_cmpxchg() returns 0 on success, not failure.
Andy McFaddendeeeeb22010-06-16 08:32:04 -0700129 int result = android_atomic_release_cas((int32_t) expectedValue,
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800130 (int32_t) newValue, address);
Carl Shapirode750892010-06-08 16:37:12 -0700131
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800132 RETURN_BOOLEAN(result == 0);
133}
134
135/*
136 * public native int getIntVolatile(Object obj, long offset);
137 */
138static void Dalvik_sun_misc_Unsafe_getIntVolatile(const u4* args,
139 JValue* pResult)
140{
141 // We ignore the this pointer in args[0].
142 Object* obj = (Object*) args[1];
143 s8 offset = GET_ARG_LONG(args, 2);
Andy McFaddendeeeeb22010-06-16 08:32:04 -0700144 volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800145
Andy McFaddendeeeeb22010-06-16 08:32:04 -0700146 int32_t value = android_atomic_acquire_load(address);
147 RETURN_INT(value);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800148}
149
150/*
151 * public native void putIntVolatile(Object obj, long offset, int newValue);
152 */
153static void Dalvik_sun_misc_Unsafe_putIntVolatile(const u4* args,
154 JValue* pResult)
155{
156 // We ignore the this pointer in args[0].
157 Object* obj = (Object*) args[1];
158 s8 offset = GET_ARG_LONG(args, 2);
159 s4 value = (s4) args[4];
Andy McFaddendeeeeb22010-06-16 08:32:04 -0700160 volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800161
Andy McFaddendeeeeb22010-06-16 08:32:04 -0700162 android_atomic_release_store(value, address);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800163 RETURN_VOID();
164}
165
166/*
167 * public native long getLongVolatile(Object obj, long offset);
168 */
169static void Dalvik_sun_misc_Unsafe_getLongVolatile(const u4* args,
170 JValue* pResult)
171{
172 // We ignore the this pointer in args[0].
173 Object* obj = (Object*) args[1];
174 s8 offset = GET_ARG_LONG(args, 2);
Andy McFaddendeeeeb22010-06-16 08:32:04 -0700175 volatile int64_t* address = (volatile int64_t*) (((u1*) obj) + offset);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800176
Andy McFadden6e10b9a2010-06-14 15:24:39 -0700177 RETURN_LONG(dvmQuasiAtomicRead64(address));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800178}
179
180/*
181 * public native void putLongVolatile(Object obj, long offset, long newValue);
182 */
183static void Dalvik_sun_misc_Unsafe_putLongVolatile(const u4* args,
184 JValue* pResult)
185{
186 // We ignore the this pointer in args[0].
187 Object* obj = (Object*) args[1];
188 s8 offset = GET_ARG_LONG(args, 2);
189 s8 value = GET_ARG_LONG(args, 4);
Andy McFaddendeeeeb22010-06-16 08:32:04 -0700190 volatile int64_t* address = (volatile int64_t*) (((u1*) obj) + offset);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800191
Andy McFadden6e10b9a2010-06-14 15:24:39 -0700192 dvmQuasiAtomicSwap64(value, address);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800193 RETURN_VOID();
194}
195
196/*
197 * public native Object getObjectVolatile(Object obj, long offset);
198 */
199static void Dalvik_sun_misc_Unsafe_getObjectVolatile(const u4* args,
200 JValue* pResult)
201{
202 // We ignore the this pointer in args[0].
203 Object* obj = (Object*) args[1];
204 s8 offset = GET_ARG_LONG(args, 2);
Andy McFaddendeeeeb22010-06-16 08:32:04 -0700205 volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800206
Andy McFaddendeeeeb22010-06-16 08:32:04 -0700207 RETURN_PTR((Object*) android_atomic_acquire_load(address));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800208}
209
210/*
211 * public native void putObjectVolatile(Object obj, long offset,
212 * Object newValue);
213 */
214static void Dalvik_sun_misc_Unsafe_putObjectVolatile(const u4* args,
215 JValue* pResult)
216{
217 // We ignore the this pointer in args[0].
218 Object* obj = (Object*) args[1];
219 s8 offset = GET_ARG_LONG(args, 2);
220 Object* value = (Object*) args[4];
Andy McFaddendeeeeb22010-06-16 08:32:04 -0700221 volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800222
Andy McFaddendeeeeb22010-06-16 08:32:04 -0700223 android_atomic_release_store((int32_t)value, address);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800224 RETURN_VOID();
225}
Carl Shapirode750892010-06-08 16:37:12 -0700226
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800227/*
228 * public native int getInt(Object obj, long offset);
229 */
230static void Dalvik_sun_misc_Unsafe_getInt(const u4* args, JValue* pResult)
231{
232 // We ignore the this pointer in args[0].
233 Object* obj = (Object*) args[1];
234 s8 offset = GET_ARG_LONG(args, 2);
235 s4* address = (s4*) (((u1*) obj) + offset);
236
237 RETURN_INT(*address);
238}
239
240/*
241 * public native void putInt(Object obj, long offset, int newValue);
242 */
243static void Dalvik_sun_misc_Unsafe_putInt(const u4* args, JValue* pResult)
244{
245 // We ignore the this pointer in args[0].
246 Object* obj = (Object*) args[1];
247 s8 offset = GET_ARG_LONG(args, 2);
248 s4 value = (s4) args[4];
249 s4* address = (s4*) (((u1*) obj) + offset);
250
251 *address = value;
252 RETURN_VOID();
253}
254
255/*
256 * public native long getLong(Object obj, long offset);
257 */
258static void Dalvik_sun_misc_Unsafe_getLong(const u4* args, JValue* pResult)
259{
260 // We ignore the this pointer in args[0].
261 Object* obj = (Object*) args[1];
262 s8 offset = GET_ARG_LONG(args, 2);
263 s8* address = (s8*) (((u1*) obj) + offset);
264
265 RETURN_LONG(*address);
266}
267
268/*
269 * public native void putLong(Object obj, long offset, long newValue);
270 */
271static void Dalvik_sun_misc_Unsafe_putLong(const u4* args, JValue* pResult)
272{
273 // We ignore the this pointer in args[0].
274 Object* obj = (Object*) args[1];
275 s8 offset = GET_ARG_LONG(args, 2);
276 s8 value = GET_ARG_LONG(args, 4);
277 s8* address = (s8*) (((u1*) obj) + offset);
278
279 *address = value;
280 RETURN_VOID();
281}
282
283/*
284 * public native Object getObject(Object obj, long offset);
285 */
286static void Dalvik_sun_misc_Unsafe_getObject(const u4* args, JValue* pResult)
287{
288 // We ignore the this pointer in args[0].
289 Object* obj = (Object*) args[1];
290 s8 offset = GET_ARG_LONG(args, 2);
291 Object** address = (Object**) (((u1*) obj) + offset);
292
293 RETURN_PTR(*address);
294}
295
296/*
297 * public native void putObject(Object obj, long offset, Object newValue);
298 */
299static void Dalvik_sun_misc_Unsafe_putObject(const u4* args, JValue* pResult)
300{
301 // We ignore the this pointer in args[0].
302 Object* obj = (Object*) args[1];
303 s8 offset = GET_ARG_LONG(args, 2);
304 Object* value = (Object*) args[4];
305 Object** address = (Object**) (((u1*) obj) + offset);
306
307 *address = value;
308 RETURN_VOID();
309}
310
311const DalvikNativeMethod dvm_sun_misc_Unsafe[] = {
312 { "objectFieldOffset0", "(Ljava/lang/reflect/Field;)J",
313 Dalvik_sun_misc_Unsafe_objectFieldOffset0 },
314 { "arrayBaseOffset0", "(Ljava/lang/Class;)I",
315 Dalvik_sun_misc_Unsafe_arrayBaseOffset0 },
316 { "arrayIndexScale0", "(Ljava/lang/Class;)I",
317 Dalvik_sun_misc_Unsafe_arrayIndexScale0 },
318 { "compareAndSwapInt", "(Ljava/lang/Object;JII)Z",
319 Dalvik_sun_misc_Unsafe_compareAndSwapInt },
320 { "compareAndSwapLong", "(Ljava/lang/Object;JJJ)Z",
321 Dalvik_sun_misc_Unsafe_compareAndSwapLong },
322 { "compareAndSwapObject",
323 "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z",
324 Dalvik_sun_misc_Unsafe_compareAndSwapObject },
325 { "getIntVolatile", "(Ljava/lang/Object;J)I",
326 Dalvik_sun_misc_Unsafe_getIntVolatile },
327 { "putIntVolatile", "(Ljava/lang/Object;JI)V",
328 Dalvik_sun_misc_Unsafe_putIntVolatile },
329 { "getLongVolatile", "(Ljava/lang/Object;J)J",
330 Dalvik_sun_misc_Unsafe_getLongVolatile },
331 { "putLongVolatile", "(Ljava/lang/Object;JJ)V",
332 Dalvik_sun_misc_Unsafe_putLongVolatile },
333 { "getObjectVolatile", "(Ljava/lang/Object;J)Ljava/lang/Object;",
334 Dalvik_sun_misc_Unsafe_getObjectVolatile },
335 { "putObjectVolatile", "(Ljava/lang/Object;JLjava/lang/Object;)V",
336 Dalvik_sun_misc_Unsafe_putObjectVolatile },
337 { "getInt", "(Ljava/lang/Object;J)I",
338 Dalvik_sun_misc_Unsafe_getInt },
339 { "putInt", "(Ljava/lang/Object;JI)V",
340 Dalvik_sun_misc_Unsafe_putInt },
341 { "getLong", "(Ljava/lang/Object;J)J",
342 Dalvik_sun_misc_Unsafe_getLong },
343 { "putLong", "(Ljava/lang/Object;JJ)V",
344 Dalvik_sun_misc_Unsafe_putLong },
345 { "getObject", "(Ljava/lang/Object;J)Ljava/lang/Object;",
346 Dalvik_sun_misc_Unsafe_getObject },
347 { "putObject", "(Ljava/lang/Object;JLjava/lang/Object;)V",
348 Dalvik_sun_misc_Unsafe_putObject },
349 { NULL, NULL, NULL },
350};