• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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