• 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_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