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(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 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 */
Dalvik_sun_misc_Unsafe_compareAndSwapInt(const u4 * args,JValue * pResult)77 static 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
87 // Note: android_atomic_cmpxchg() returns 0 on success, not failure.
88 int result = android_atomic_cmpxchg(expectedValue, newValue, address);
89
90 RETURN_BOOLEAN(result == 0);
91 }
92
93 /*
94 * public native boolean compareAndSwapLong(Object obj, long offset,
95 * long expectedValue, long newValue);
96 */
Dalvik_sun_misc_Unsafe_compareAndSwapLong(const u4 * args,JValue * pResult)97 static 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 =
109 android_quasiatomic_cmpxchg_64(expectedValue, newValue, address);
110
111 RETURN_BOOLEAN(result == 0);
112 }
113
114 /*
115 * public native boolean compareAndSwapObject(Object obj, long offset,
116 * Object expectedValue, Object newValue);
117 */
Dalvik_sun_misc_Unsafe_compareAndSwapObject(const u4 * args,JValue * pResult)118 static 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.
129 int result = android_atomic_cmpxchg((int32_t) expectedValue,
130 (int32_t) newValue, address);
131
132 RETURN_BOOLEAN(result == 0);
133 }
134
135 /*
136 * public native int getIntVolatile(Object obj, long offset);
137 */
Dalvik_sun_misc_Unsafe_getIntVolatile(const u4 * args,JValue * pResult)138 static 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);
144 volatile s4* address = (volatile s4*) (((u1*) obj) + offset);
145
146 RETURN_INT(*address);
147 }
148
149 /*
150 * public native void putIntVolatile(Object obj, long offset, int newValue);
151 */
Dalvik_sun_misc_Unsafe_putIntVolatile(const u4 * args,JValue * pResult)152 static void Dalvik_sun_misc_Unsafe_putIntVolatile(const u4* args,
153 JValue* pResult)
154 {
155 // We ignore the this pointer in args[0].
156 Object* obj = (Object*) args[1];
157 s8 offset = GET_ARG_LONG(args, 2);
158 s4 value = (s4) args[4];
159 volatile s4* address = (volatile s4*) (((u1*) obj) + offset);
160
161 *address = value;
162 RETURN_VOID();
163 }
164
165 /*
166 * public native long getLongVolatile(Object obj, long offset);
167 */
Dalvik_sun_misc_Unsafe_getLongVolatile(const u4 * args,JValue * pResult)168 static void Dalvik_sun_misc_Unsafe_getLongVolatile(const u4* args,
169 JValue* pResult)
170 {
171 // We ignore the this pointer in args[0].
172 Object* obj = (Object*) args[1];
173 s8 offset = GET_ARG_LONG(args, 2);
174 volatile s8* address = (volatile s8*) (((u1*) obj) + offset);
175
176 RETURN_LONG(android_quasiatomic_read_64(address));
177 }
178
179 /*
180 * public native void putLongVolatile(Object obj, long offset, long newValue);
181 */
Dalvik_sun_misc_Unsafe_putLongVolatile(const u4 * args,JValue * pResult)182 static void Dalvik_sun_misc_Unsafe_putLongVolatile(const u4* args,
183 JValue* pResult)
184 {
185 // We ignore the this pointer in args[0].
186 Object* obj = (Object*) args[1];
187 s8 offset = GET_ARG_LONG(args, 2);
188 s8 value = GET_ARG_LONG(args, 4);
189 volatile s8* address = (volatile s8*) (((u1*) obj) + offset);
190
191 android_quasiatomic_swap_64(value, address);
192 RETURN_VOID();
193 }
194
195 /*
196 * public native Object getObjectVolatile(Object obj, long offset);
197 */
Dalvik_sun_misc_Unsafe_getObjectVolatile(const u4 * args,JValue * pResult)198 static void Dalvik_sun_misc_Unsafe_getObjectVolatile(const u4* args,
199 JValue* pResult)
200 {
201 // We ignore the this pointer in args[0].
202 Object* obj = (Object*) args[1];
203 s8 offset = GET_ARG_LONG(args, 2);
204 volatile Object** address = (volatile Object**) (((u1*) obj) + offset);
205
206 RETURN_PTR((void*) *address);
207 }
208
209 /*
210 * public native void putObjectVolatile(Object obj, long offset,
211 * Object newValue);
212 */
Dalvik_sun_misc_Unsafe_putObjectVolatile(const u4 * args,JValue * pResult)213 static void Dalvik_sun_misc_Unsafe_putObjectVolatile(const u4* args,
214 JValue* pResult)
215 {
216 // We ignore the this pointer in args[0].
217 Object* obj = (Object*) args[1];
218 s8 offset = GET_ARG_LONG(args, 2);
219 Object* value = (Object*) args[4];
220 volatile Object** address = (volatile Object**) (((u1*) obj) + offset);
221
222 *address = value;
223 RETURN_VOID();
224 }
225
226 /*
227 * public native int getInt(Object obj, long offset);
228 */
Dalvik_sun_misc_Unsafe_getInt(const u4 * args,JValue * pResult)229 static void Dalvik_sun_misc_Unsafe_getInt(const u4* args, JValue* pResult)
230 {
231 // We ignore the this pointer in args[0].
232 Object* obj = (Object*) args[1];
233 s8 offset = GET_ARG_LONG(args, 2);
234 s4* address = (s4*) (((u1*) obj) + offset);
235
236 RETURN_INT(*address);
237 }
238
239 /*
240 * public native void putInt(Object obj, long offset, int newValue);
241 */
Dalvik_sun_misc_Unsafe_putInt(const u4 * args,JValue * pResult)242 static void Dalvik_sun_misc_Unsafe_putInt(const u4* args, JValue* pResult)
243 {
244 // We ignore the this pointer in args[0].
245 Object* obj = (Object*) args[1];
246 s8 offset = GET_ARG_LONG(args, 2);
247 s4 value = (s4) args[4];
248 s4* address = (s4*) (((u1*) obj) + offset);
249
250 *address = value;
251 RETURN_VOID();
252 }
253
254 /*
255 * public native long getLong(Object obj, long offset);
256 */
Dalvik_sun_misc_Unsafe_getLong(const u4 * args,JValue * pResult)257 static void Dalvik_sun_misc_Unsafe_getLong(const u4* args, JValue* pResult)
258 {
259 // We ignore the this pointer in args[0].
260 Object* obj = (Object*) args[1];
261 s8 offset = GET_ARG_LONG(args, 2);
262 s8* address = (s8*) (((u1*) obj) + offset);
263
264 RETURN_LONG(*address);
265 }
266
267 /*
268 * public native void putLong(Object obj, long offset, long newValue);
269 */
Dalvik_sun_misc_Unsafe_putLong(const u4 * args,JValue * pResult)270 static void Dalvik_sun_misc_Unsafe_putLong(const u4* args, JValue* pResult)
271 {
272 // We ignore the this pointer in args[0].
273 Object* obj = (Object*) args[1];
274 s8 offset = GET_ARG_LONG(args, 2);
275 s8 value = GET_ARG_LONG(args, 4);
276 s8* address = (s8*) (((u1*) obj) + offset);
277
278 *address = value;
279 RETURN_VOID();
280 }
281
282 /*
283 * public native Object getObject(Object obj, long offset);
284 */
Dalvik_sun_misc_Unsafe_getObject(const u4 * args,JValue * pResult)285 static void Dalvik_sun_misc_Unsafe_getObject(const u4* args, JValue* pResult)
286 {
287 // We ignore the this pointer in args[0].
288 Object* obj = (Object*) args[1];
289 s8 offset = GET_ARG_LONG(args, 2);
290 Object** address = (Object**) (((u1*) obj) + offset);
291
292 RETURN_PTR(*address);
293 }
294
295 /*
296 * public native void putObject(Object obj, long offset, Object newValue);
297 */
Dalvik_sun_misc_Unsafe_putObject(const u4 * args,JValue * pResult)298 static void Dalvik_sun_misc_Unsafe_putObject(const u4* args, JValue* pResult)
299 {
300 // We ignore the this pointer in args[0].
301 Object* obj = (Object*) args[1];
302 s8 offset = GET_ARG_LONG(args, 2);
303 Object* value = (Object*) args[4];
304 Object** address = (Object**) (((u1*) obj) + offset);
305
306 *address = value;
307 RETURN_VOID();
308 }
309
310 const DalvikNativeMethod dvm_sun_misc_Unsafe[] = {
311 { "objectFieldOffset0", "(Ljava/lang/reflect/Field;)J",
312 Dalvik_sun_misc_Unsafe_objectFieldOffset0 },
313 { "arrayBaseOffset0", "(Ljava/lang/Class;)I",
314 Dalvik_sun_misc_Unsafe_arrayBaseOffset0 },
315 { "arrayIndexScale0", "(Ljava/lang/Class;)I",
316 Dalvik_sun_misc_Unsafe_arrayIndexScale0 },
317 { "compareAndSwapInt", "(Ljava/lang/Object;JII)Z",
318 Dalvik_sun_misc_Unsafe_compareAndSwapInt },
319 { "compareAndSwapLong", "(Ljava/lang/Object;JJJ)Z",
320 Dalvik_sun_misc_Unsafe_compareAndSwapLong },
321 { "compareAndSwapObject",
322 "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z",
323 Dalvik_sun_misc_Unsafe_compareAndSwapObject },
324 { "getIntVolatile", "(Ljava/lang/Object;J)I",
325 Dalvik_sun_misc_Unsafe_getIntVolatile },
326 { "putIntVolatile", "(Ljava/lang/Object;JI)V",
327 Dalvik_sun_misc_Unsafe_putIntVolatile },
328 { "getLongVolatile", "(Ljava/lang/Object;J)J",
329 Dalvik_sun_misc_Unsafe_getLongVolatile },
330 { "putLongVolatile", "(Ljava/lang/Object;JJ)V",
331 Dalvik_sun_misc_Unsafe_putLongVolatile },
332 { "getObjectVolatile", "(Ljava/lang/Object;J)Ljava/lang/Object;",
333 Dalvik_sun_misc_Unsafe_getObjectVolatile },
334 { "putObjectVolatile", "(Ljava/lang/Object;JLjava/lang/Object;)V",
335 Dalvik_sun_misc_Unsafe_putObjectVolatile },
336 { "getInt", "(Ljava/lang/Object;J)I",
337 Dalvik_sun_misc_Unsafe_getInt },
338 { "putInt", "(Ljava/lang/Object;JI)V",
339 Dalvik_sun_misc_Unsafe_putInt },
340 { "getLong", "(Ljava/lang/Object;J)J",
341 Dalvik_sun_misc_Unsafe_getLong },
342 { "putLong", "(Ljava/lang/Object;JJ)V",
343 Dalvik_sun_misc_Unsafe_putLong },
344 { "getObject", "(Ljava/lang/Object;J)Ljava/lang/Object;",
345 Dalvik_sun_misc_Unsafe_getObject },
346 { "putObject", "(Ljava/lang/Object;JLjava/lang/Object;)V",
347 Dalvik_sun_misc_Unsafe_putObject },
348 { NULL, NULL, NULL },
349 };
350
351