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 /*
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 */
Dalvik_sun_misc_Unsafe_objectFieldOffset0(const u4 * args,JValue * pResult)27 static 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 */
Dalvik_sun_misc_Unsafe_arrayBaseOffset0(const u4 * args,JValue * pResult)40 static 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_MEMBER(ArrayObject, contents));
46 }
47
48 /*
49 * private static native int arrayIndexScale0(Class clazz);
50 */
Dalvik_sun_misc_Unsafe_arrayIndexScale0(const u4 * args,JValue * pResult)51 static void Dalvik_sun_misc_Unsafe_arrayIndexScale0(const u4* args,
52 JValue* pResult)
53 {
54 ClassObject* clazz = (ClassObject*) args[0];
55 RETURN_INT(dvmArrayClassElementWidth(clazz));
56 }
57
58 /*
59 * public native boolean compareAndSwapInt(Object obj, long offset,
60 * int expectedValue, int newValue);
61 */
Dalvik_sun_misc_Unsafe_compareAndSwapInt(const u4 * args,JValue * pResult)62 static void Dalvik_sun_misc_Unsafe_compareAndSwapInt(const u4* args,
63 JValue* pResult)
64 {
65 // We ignore the this pointer in args[0].
66 Object* obj = (Object*) args[1];
67 s8 offset = GET_ARG_LONG(args, 2);
68 s4 expectedValue = args[4];
69 s4 newValue = args[5];
70 volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset);
71
72 // Note: android_atomic_release_cas() returns 0 on success, not failure.
73 int result = android_atomic_release_cas(expectedValue, newValue, address);
74
75 RETURN_BOOLEAN(result == 0);
76 }
77
78 /*
79 * public native boolean compareAndSwapLong(Object obj, long offset,
80 * long expectedValue, long newValue);
81 */
Dalvik_sun_misc_Unsafe_compareAndSwapLong(const u4 * args,JValue * pResult)82 static void Dalvik_sun_misc_Unsafe_compareAndSwapLong(const u4* args,
83 JValue* pResult)
84 {
85 // We ignore the this pointer in args[0].
86 Object* obj = (Object*) args[1];
87 s8 offset = GET_ARG_LONG(args, 2);
88 s8 expectedValue = GET_ARG_LONG(args, 4);
89 s8 newValue = GET_ARG_LONG(args, 6);
90 volatile int64_t* address = (volatile int64_t*) (((u1*) obj) + offset);
91
92 // Note: android_atomic_cmpxchg() returns 0 on success, not failure.
93 int result =
94 dvmQuasiAtomicCas64(expectedValue, newValue, address);
95
96 RETURN_BOOLEAN(result == 0);
97 }
98
99 /*
100 * public native boolean compareAndSwapObject(Object obj, long offset,
101 * Object expectedValue, Object newValue);
102 */
Dalvik_sun_misc_Unsafe_compareAndSwapObject(const u4 * args,JValue * pResult)103 static void Dalvik_sun_misc_Unsafe_compareAndSwapObject(const u4* args,
104 JValue* pResult)
105 {
106 // We ignore the this pointer in args[0].
107 Object* obj = (Object*) args[1];
108 s8 offset = GET_ARG_LONG(args, 2);
109 Object* expectedValue = (Object*) args[4];
110 Object* newValue = (Object*) args[5];
111 int32_t* address = (int32_t*) (((u1*) obj) + offset);
112
113 // Note: android_atomic_cmpxchg() returns 0 on success, not failure.
114 int result = android_atomic_release_cas((int32_t) expectedValue,
115 (int32_t) newValue, address);
116 dvmWriteBarrierField(obj, address);
117 RETURN_BOOLEAN(result == 0);
118 }
119
120 /*
121 * public native int getIntVolatile(Object obj, long offset);
122 */
Dalvik_sun_misc_Unsafe_getIntVolatile(const u4 * args,JValue * pResult)123 static void Dalvik_sun_misc_Unsafe_getIntVolatile(const u4* args,
124 JValue* pResult)
125 {
126 // We ignore the this pointer in args[0].
127 Object* obj = (Object*) args[1];
128 s8 offset = GET_ARG_LONG(args, 2);
129 volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset);
130
131 int32_t value = android_atomic_acquire_load(address);
132 RETURN_INT(value);
133 }
134
135 /*
136 * public native void putIntVolatile(Object obj, long offset, int newValue);
137 */
Dalvik_sun_misc_Unsafe_putIntVolatile(const u4 * args,JValue * pResult)138 static void Dalvik_sun_misc_Unsafe_putIntVolatile(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);
144 s4 value = (s4) args[4];
145 volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset);
146
147 android_atomic_release_store(value, address);
148 RETURN_VOID();
149 }
150
151 /*
152 * public native long getLongVolatile(Object obj, long offset);
153 */
Dalvik_sun_misc_Unsafe_getLongVolatile(const u4 * args,JValue * pResult)154 static void Dalvik_sun_misc_Unsafe_getLongVolatile(const u4* args,
155 JValue* pResult)
156 {
157 // We ignore the this pointer in args[0].
158 Object* obj = (Object*) args[1];
159 s8 offset = GET_ARG_LONG(args, 2);
160 volatile int64_t* address = (volatile int64_t*) (((u1*) obj) + offset);
161
162 assert((offset & 7) == 0);
163 RETURN_LONG(dvmQuasiAtomicRead64(address));
164 }
165
166 /*
167 * public native void putLongVolatile(Object obj, long offset, long newValue);
168 */
Dalvik_sun_misc_Unsafe_putLongVolatile(const u4 * args,JValue * pResult)169 static void Dalvik_sun_misc_Unsafe_putLongVolatile(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);
175 s8 value = GET_ARG_LONG(args, 4);
176 volatile int64_t* address = (volatile int64_t*) (((u1*) obj) + offset);
177
178 assert((offset & 7) == 0);
179 dvmQuasiAtomicSwap64(value, address);
180 RETURN_VOID();
181 }
182
183 /*
184 * public native Object getObjectVolatile(Object obj, long offset);
185 */
Dalvik_sun_misc_Unsafe_getObjectVolatile(const u4 * args,JValue * pResult)186 static void Dalvik_sun_misc_Unsafe_getObjectVolatile(const u4* args,
187 JValue* pResult)
188 {
189 // We ignore the this pointer in args[0].
190 Object* obj = (Object*) args[1];
191 s8 offset = GET_ARG_LONG(args, 2);
192 volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset);
193
194 RETURN_PTR((Object*) android_atomic_acquire_load(address));
195 }
196
197 /*
198 * public native void putObjectVolatile(Object obj, long offset,
199 * Object newValue);
200 */
Dalvik_sun_misc_Unsafe_putObjectVolatile(const u4 * args,JValue * pResult)201 static void Dalvik_sun_misc_Unsafe_putObjectVolatile(const u4* args,
202 JValue* pResult)
203 {
204 // We ignore the this pointer in args[0].
205 Object* obj = (Object*) args[1];
206 s8 offset = GET_ARG_LONG(args, 2);
207 Object* value = (Object*) args[4];
208 volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset);
209
210 android_atomic_release_store((int32_t)value, address);
211 dvmWriteBarrierField(obj, (void *)address);
212 RETURN_VOID();
213 }
214
215 /*
216 * public native int getInt(Object obj, long offset);
217 */
Dalvik_sun_misc_Unsafe_getInt(const u4 * args,JValue * pResult)218 static void Dalvik_sun_misc_Unsafe_getInt(const u4* args, JValue* pResult)
219 {
220 // We ignore the this pointer in args[0].
221 Object* obj = (Object*) args[1];
222 s8 offset = GET_ARG_LONG(args, 2);
223 s4* address = (s4*) (((u1*) obj) + offset);
224
225 RETURN_INT(*address);
226 }
227
228 /*
229 * public native void putInt(Object obj, long offset, int newValue);
230 */
Dalvik_sun_misc_Unsafe_putInt(const u4 * args,JValue * pResult)231 static void Dalvik_sun_misc_Unsafe_putInt(const u4* args, JValue* pResult)
232 {
233 // We ignore the this pointer in args[0].
234 Object* obj = (Object*) args[1];
235 s8 offset = GET_ARG_LONG(args, 2);
236 s4 value = (s4) args[4];
237 s4* address = (s4*) (((u1*) obj) + offset);
238
239 *address = value;
240 RETURN_VOID();
241 }
242
243 /*
244 * public native void putOrderedInt(Object obj, long offset, int newValue);
245 */
Dalvik_sun_misc_Unsafe_putOrderedInt(const u4 * args,JValue * pResult)246 static void Dalvik_sun_misc_Unsafe_putOrderedInt(const u4* args,
247 JValue* pResult)
248 {
249 // We ignore the this pointer in args[0].
250 Object* obj = (Object*) args[1];
251 s8 offset = GET_ARG_LONG(args, 2);
252 s4 value = (s4) args[4];
253 s4* address = (s4*) (((u1*) obj) + offset);
254
255 ANDROID_MEMBAR_STORE();
256 *address = value;
257 RETURN_VOID();
258 }
259
260 /*
261 * public native long getLong(Object obj, long offset);
262 */
Dalvik_sun_misc_Unsafe_getLong(const u4 * args,JValue * pResult)263 static void Dalvik_sun_misc_Unsafe_getLong(const u4* args, JValue* pResult)
264 {
265 // We ignore the this pointer in args[0].
266 Object* obj = (Object*) args[1];
267 s8 offset = GET_ARG_LONG(args, 2);
268 s8* address = (s8*) (((u1*) obj) + offset);
269
270 RETURN_LONG(*address);
271 }
272
273 /*
274 * public native void putLong(Object obj, long offset, long newValue);
275 */
Dalvik_sun_misc_Unsafe_putLong(const u4 * args,JValue * pResult)276 static void Dalvik_sun_misc_Unsafe_putLong(const u4* args, JValue* pResult)
277 {
278 // We ignore the this pointer in args[0].
279 Object* obj = (Object*) args[1];
280 s8 offset = GET_ARG_LONG(args, 2);
281 s8 value = GET_ARG_LONG(args, 4);
282 s8* address = (s8*) (((u1*) obj) + offset);
283
284 *address = value;
285 RETURN_VOID();
286 }
287
288 /*
289 * public native void putOrderedLong(Object obj, long offset, long newValue);
290 */
Dalvik_sun_misc_Unsafe_putOrderedLong(const u4 * args,JValue * pResult)291 static void Dalvik_sun_misc_Unsafe_putOrderedLong(const u4* args,
292 JValue* pResult)
293 {
294 // We ignore the this pointer in args[0].
295 Object* obj = (Object*) args[1];
296 s8 offset = GET_ARG_LONG(args, 2);
297 s8 value = GET_ARG_LONG(args, 4);
298 s8* address = (s8*) (((u1*) obj) + offset);
299
300 ANDROID_MEMBAR_STORE();
301 *address = value;
302 RETURN_VOID();
303 }
304
305 /*
306 * public native Object getObject(Object obj, long offset);
307 */
Dalvik_sun_misc_Unsafe_getObject(const u4 * args,JValue * pResult)308 static void Dalvik_sun_misc_Unsafe_getObject(const u4* args, JValue* pResult)
309 {
310 // We ignore the this pointer in args[0].
311 Object* obj = (Object*) args[1];
312 s8 offset = GET_ARG_LONG(args, 2);
313 Object** address = (Object**) (((u1*) obj) + offset);
314
315 RETURN_PTR(*address);
316 }
317
318 /*
319 * public native void putObject(Object obj, long offset, Object newValue);
320 */
Dalvik_sun_misc_Unsafe_putObject(const u4 * args,JValue * pResult)321 static void Dalvik_sun_misc_Unsafe_putObject(const u4* args, JValue* pResult)
322 {
323 // We ignore the this pointer in args[0].
324 Object* obj = (Object*) args[1];
325 s8 offset = GET_ARG_LONG(args, 2);
326 Object* value = (Object*) args[4];
327 Object** address = (Object**) (((u1*) obj) + offset);
328
329 *address = value;
330 dvmWriteBarrierField(obj, address);
331 RETURN_VOID();
332 }
333
334 /*
335 * public native void putOrderedObject(Object obj, long offset,
336 * Object newValue);
337 */
Dalvik_sun_misc_Unsafe_putOrderedObject(const u4 * args,JValue * pResult)338 static void Dalvik_sun_misc_Unsafe_putOrderedObject(const u4* args,
339 JValue* pResult)
340 {
341 // We ignore the this pointer in args[0].
342 Object* obj = (Object*) args[1];
343 s8 offset = GET_ARG_LONG(args, 2);
344 Object* value = (Object*) args[4];
345 Object** address = (Object**) (((u1*) obj) + offset);
346
347 ANDROID_MEMBAR_STORE();
348 *address = value;
349 dvmWriteBarrierField(obj, address);
350 RETURN_VOID();
351 }
352
353 const DalvikNativeMethod dvm_sun_misc_Unsafe[] = {
354 { "objectFieldOffset0", "(Ljava/lang/reflect/Field;)J",
355 Dalvik_sun_misc_Unsafe_objectFieldOffset0 },
356 { "arrayBaseOffset0", "(Ljava/lang/Class;)I",
357 Dalvik_sun_misc_Unsafe_arrayBaseOffset0 },
358 { "arrayIndexScale0", "(Ljava/lang/Class;)I",
359 Dalvik_sun_misc_Unsafe_arrayIndexScale0 },
360 { "compareAndSwapInt", "(Ljava/lang/Object;JII)Z",
361 Dalvik_sun_misc_Unsafe_compareAndSwapInt },
362 { "compareAndSwapLong", "(Ljava/lang/Object;JJJ)Z",
363 Dalvik_sun_misc_Unsafe_compareAndSwapLong },
364 { "compareAndSwapObject",
365 "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z",
366 Dalvik_sun_misc_Unsafe_compareAndSwapObject },
367 { "getIntVolatile", "(Ljava/lang/Object;J)I",
368 Dalvik_sun_misc_Unsafe_getIntVolatile },
369 { "putIntVolatile", "(Ljava/lang/Object;JI)V",
370 Dalvik_sun_misc_Unsafe_putIntVolatile },
371 { "getLongVolatile", "(Ljava/lang/Object;J)J",
372 Dalvik_sun_misc_Unsafe_getLongVolatile },
373 { "putLongVolatile", "(Ljava/lang/Object;JJ)V",
374 Dalvik_sun_misc_Unsafe_putLongVolatile },
375 { "getObjectVolatile", "(Ljava/lang/Object;J)Ljava/lang/Object;",
376 Dalvik_sun_misc_Unsafe_getObjectVolatile },
377 { "putObjectVolatile", "(Ljava/lang/Object;JLjava/lang/Object;)V",
378 Dalvik_sun_misc_Unsafe_putObjectVolatile },
379 { "getInt", "(Ljava/lang/Object;J)I",
380 Dalvik_sun_misc_Unsafe_getInt },
381 { "putInt", "(Ljava/lang/Object;JI)V",
382 Dalvik_sun_misc_Unsafe_putInt },
383 { "putOrderedInt", "(Ljava/lang/Object;JI)V",
384 Dalvik_sun_misc_Unsafe_putOrderedInt },
385 { "getLong", "(Ljava/lang/Object;J)J",
386 Dalvik_sun_misc_Unsafe_getLong },
387 { "putLong", "(Ljava/lang/Object;JJ)V",
388 Dalvik_sun_misc_Unsafe_putLong },
389 { "putOrderedLong", "(Ljava/lang/Object;JJ)V",
390 Dalvik_sun_misc_Unsafe_putOrderedLong },
391 { "getObject", "(Ljava/lang/Object;J)Ljava/lang/Object;",
392 Dalvik_sun_misc_Unsafe_getObject },
393 { "putObject", "(Ljava/lang/Object;JLjava/lang/Object;)V",
394 Dalvik_sun_misc_Unsafe_putObject },
395 { "putOrderedObject", "(Ljava/lang/Object;JLjava/lang/Object;)V",
396 Dalvik_sun_misc_Unsafe_putOrderedObject },
397 { NULL, NULL, NULL },
398 };
399