Home | History | Annotate | Download | only in native
      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_MEMBER(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     RETURN_INT(dvmArrayClassElementWidth(clazz));
     56 }
     57 
     58 /*
     59  * public native boolean compareAndSwapInt(Object obj, long offset,
     60  *         int expectedValue, int newValue);
     61  */
     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  */
     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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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