OSDN Git Service

Provide "ordered" put calls.
[android-x86/dalvik.git] / vm / native / sun_misc_Unsafe.c
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  */
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  */
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  */
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  */
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_release_cas() returns 0 on success, not failure.
88     int result = android_atomic_release_cas(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  */
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         dvmQuasiAtomicCas64(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  */
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_release_cas((int32_t) expectedValue,
130             (int32_t) newValue, address);
131     dvmWriteBarrierField(obj, address);
132     RETURN_BOOLEAN(result == 0);
133 }
134
135 /*
136  * public native int getIntVolatile(Object obj, long offset);
137  */
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 int32_t* address = (volatile int32_t*) (((u1*) obj) + offset);
145
146     int32_t value = android_atomic_acquire_load(address);
147     RETURN_INT(value);
148 }
149
150 /*
151  * public native void putIntVolatile(Object obj, long offset, int newValue);
152  */
153 static 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];
160     volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset);
161
162     android_atomic_release_store(value, address);
163     RETURN_VOID();
164 }
165
166 /*
167  * public native long getLongVolatile(Object obj, long offset);
168  */
169 static 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);
175     volatile int64_t* address = (volatile int64_t*) (((u1*) obj) + offset);
176
177     RETURN_LONG(dvmQuasiAtomicRead64(address));
178 }
179
180 /*
181  * public native void putLongVolatile(Object obj, long offset, long newValue);
182  */
183 static 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);
190     volatile int64_t* address = (volatile int64_t*) (((u1*) obj) + offset);
191
192     dvmQuasiAtomicSwap64(value, address);
193     RETURN_VOID();
194 }
195
196 /*
197  * public native Object getObjectVolatile(Object obj, long offset);
198  */
199 static 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);
205     volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset);
206
207     RETURN_PTR((Object*) android_atomic_acquire_load(address));
208 }
209
210 /*
211  * public native void putObjectVolatile(Object obj, long offset,
212  *         Object newValue);
213  */
214 static 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];
221     volatile int32_t* address = (volatile int32_t*) (((u1*) obj) + offset);
222
223     android_atomic_release_store((int32_t)value, address);
224     dvmWriteBarrierField(obj, (void *)address);
225     RETURN_VOID();
226 }
227
228 /*
229  * public native int getInt(Object obj, long offset);
230  */
231 static void Dalvik_sun_misc_Unsafe_getInt(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* address = (s4*) (((u1*) obj) + offset);
237
238     RETURN_INT(*address);
239 }
240
241 /*
242  * public native void putInt(Object obj, long offset, int newValue);
243  */
244 static void Dalvik_sun_misc_Unsafe_putInt(const u4* args, JValue* pResult)
245 {
246     // We ignore the this pointer in args[0].
247     Object* obj = (Object*) args[1];
248     s8 offset = GET_ARG_LONG(args, 2);
249     s4 value = (s4) args[4];
250     s4* address = (s4*) (((u1*) obj) + offset);
251
252     *address = value;
253     RETURN_VOID();
254 }
255
256 /*
257  * public native void putOrderedInt(Object obj, long offset, int newValue);
258  */
259 static void Dalvik_sun_misc_Unsafe_putOrderedInt(const u4* args,
260     JValue* pResult)
261 {
262     // We ignore the this pointer in args[0].
263     Object* obj = (Object*) args[1];
264     s8 offset = GET_ARG_LONG(args, 2);
265     s4 value = (s4) args[4];
266     s4* address = (s4*) (((u1*) obj) + offset);
267
268     ANDROID_MEMBAR_STORE();
269     *address = value;
270     RETURN_VOID();
271 }
272
273 /*
274  * public native long getLong(Object obj, long offset);
275  */
276 static void Dalvik_sun_misc_Unsafe_getLong(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* address = (s8*) (((u1*) obj) + offset);
282
283     RETURN_LONG(*address);
284 }
285
286 /*
287  * public native void putLong(Object obj, long offset, long newValue);
288  */
289 static void Dalvik_sun_misc_Unsafe_putLong(const u4* args, JValue* pResult)
290 {
291     // We ignore the this pointer in args[0].
292     Object* obj = (Object*) args[1];
293     s8 offset = GET_ARG_LONG(args, 2);
294     s8 value = GET_ARG_LONG(args, 4);
295     s8* address = (s8*) (((u1*) obj) + offset);
296
297     *address = value;
298     RETURN_VOID();
299 }
300
301 /*
302  * public native void putOrderedLong(Object obj, long offset, long newValue);
303  */
304 static void Dalvik_sun_misc_Unsafe_putOrderedLong(const u4* args,
305     JValue* pResult)
306 {
307     // We ignore the this pointer in args[0].
308     Object* obj = (Object*) args[1];
309     s8 offset = GET_ARG_LONG(args, 2);
310     s8 value = GET_ARG_LONG(args, 4);
311     s8* address = (s8*) (((u1*) obj) + offset);
312
313     ANDROID_MEMBAR_STORE();
314     *address = value;
315     RETURN_VOID();
316 }
317
318 /*
319  * public native Object getObject(Object obj, long offset);
320  */
321 static void Dalvik_sun_misc_Unsafe_getObject(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** address = (Object**) (((u1*) obj) + offset);
327
328     RETURN_PTR(*address);
329 }
330
331 /*
332  * public native void putObject(Object obj, long offset, Object newValue);
333  */
334 static void Dalvik_sun_misc_Unsafe_putObject(const u4* args, JValue* pResult)
335 {
336     // We ignore the this pointer in args[0].
337     Object* obj = (Object*) args[1];
338     s8 offset = GET_ARG_LONG(args, 2);
339     Object* value = (Object*) args[4];
340     Object** address = (Object**) (((u1*) obj) + offset);
341
342     *address = value;
343     dvmWriteBarrierField(obj, address);
344     RETURN_VOID();
345 }
346
347 /*
348  * public native void putOrderedObject(Object obj, long offset,
349  *      Object newValue);
350  */
351 static void Dalvik_sun_misc_Unsafe_putOrderedObject(const u4* args,
352     JValue* pResult)
353 {
354     // We ignore the this pointer in args[0].
355     Object* obj = (Object*) args[1];
356     s8 offset = GET_ARG_LONG(args, 2);
357     Object* value = (Object*) args[4];
358     Object** address = (Object**) (((u1*) obj) + offset);
359
360     ANDROID_MEMBAR_STORE();
361     *address = value;
362     dvmWriteBarrierField(obj, address);
363     RETURN_VOID();
364 }
365
366 const DalvikNativeMethod dvm_sun_misc_Unsafe[] = {
367     { "objectFieldOffset0", "(Ljava/lang/reflect/Field;)J",
368       Dalvik_sun_misc_Unsafe_objectFieldOffset0 },
369     { "arrayBaseOffset0", "(Ljava/lang/Class;)I",
370       Dalvik_sun_misc_Unsafe_arrayBaseOffset0 },
371     { "arrayIndexScale0", "(Ljava/lang/Class;)I",
372       Dalvik_sun_misc_Unsafe_arrayIndexScale0 },
373     { "compareAndSwapInt", "(Ljava/lang/Object;JII)Z",
374       Dalvik_sun_misc_Unsafe_compareAndSwapInt },
375     { "compareAndSwapLong", "(Ljava/lang/Object;JJJ)Z",
376       Dalvik_sun_misc_Unsafe_compareAndSwapLong },
377     { "compareAndSwapObject",
378       "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z",
379       Dalvik_sun_misc_Unsafe_compareAndSwapObject },
380     { "getIntVolatile", "(Ljava/lang/Object;J)I",
381       Dalvik_sun_misc_Unsafe_getIntVolatile },
382     { "putIntVolatile", "(Ljava/lang/Object;JI)V",
383       Dalvik_sun_misc_Unsafe_putIntVolatile },
384     { "getLongVolatile", "(Ljava/lang/Object;J)J",
385       Dalvik_sun_misc_Unsafe_getLongVolatile },
386     { "putLongVolatile", "(Ljava/lang/Object;JJ)V",
387       Dalvik_sun_misc_Unsafe_putLongVolatile },
388     { "getObjectVolatile", "(Ljava/lang/Object;J)Ljava/lang/Object;",
389       Dalvik_sun_misc_Unsafe_getObjectVolatile },
390     { "putObjectVolatile", "(Ljava/lang/Object;JLjava/lang/Object;)V",
391       Dalvik_sun_misc_Unsafe_putObjectVolatile },
392     { "getInt", "(Ljava/lang/Object;J)I",
393       Dalvik_sun_misc_Unsafe_getInt },
394     { "putInt", "(Ljava/lang/Object;JI)V",
395       Dalvik_sun_misc_Unsafe_putInt },
396     { "putOrderedInt", "(Ljava/lang/Object;JI)V",
397       Dalvik_sun_misc_Unsafe_putOrderedInt },
398     { "getLong", "(Ljava/lang/Object;J)J",
399       Dalvik_sun_misc_Unsafe_getLong },
400     { "putLong", "(Ljava/lang/Object;JJ)V",
401       Dalvik_sun_misc_Unsafe_putLong },
402     { "putOrderedLong", "(Ljava/lang/Object;JJ)V",
403       Dalvik_sun_misc_Unsafe_putOrderedLong },
404     { "getObject", "(Ljava/lang/Object;J)Ljava/lang/Object;",
405       Dalvik_sun_misc_Unsafe_getObject },
406     { "putObject", "(Ljava/lang/Object;JLjava/lang/Object;)V",
407       Dalvik_sun_misc_Unsafe_putObject },
408     { "putOrderedObject", "(Ljava/lang/Object;JLjava/lang/Object;)V",
409       Dalvik_sun_misc_Unsafe_putOrderedObject },
410     { NULL, NULL, NULL },
411 };