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(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 long getLong(Object obj, long offset);
    245  */
    246 static void Dalvik_sun_misc_Unsafe_getLong(const u4* args, JValue* pResult)
    247 {
    248     // We ignore the this pointer in args[0].
    249     Object* obj = (Object*) args[1];
    250     s8 offset = GET_ARG_LONG(args, 2);
    251     s8* address = (s8*) (((u1*) obj) + offset);
    252 
    253     RETURN_LONG(*address);
    254 }
    255 
    256 /*
    257  * public native void putLong(Object obj, long offset, long newValue);
    258  */
    259 static void Dalvik_sun_misc_Unsafe_putLong(const u4* args, JValue* pResult)
    260 {
    261     // We ignore the this pointer in args[0].
    262     Object* obj = (Object*) args[1];
    263     s8 offset = GET_ARG_LONG(args, 2);
    264     s8 value = GET_ARG_LONG(args, 4);
    265     s8* address = (s8*) (((u1*) obj) + offset);
    266 
    267     *address = value;
    268     RETURN_VOID();
    269 }
    270 
    271 /*
    272  * public native Object getObject(Object obj, long offset);
    273  */
    274 static void Dalvik_sun_misc_Unsafe_getObject(const u4* args, JValue* pResult)
    275 {
    276     // We ignore the this pointer in args[0].
    277     Object* obj = (Object*) args[1];
    278     s8 offset = GET_ARG_LONG(args, 2);
    279     Object** address = (Object**) (((u1*) obj) + offset);
    280 
    281     RETURN_PTR(*address);
    282 }
    283 
    284 /*
    285  * public native void putObject(Object obj, long offset, Object newValue);
    286  */
    287 static void Dalvik_sun_misc_Unsafe_putObject(const u4* args, JValue* pResult)
    288 {
    289     // We ignore the this pointer in args[0].
    290     Object* obj = (Object*) args[1];
    291     s8 offset = GET_ARG_LONG(args, 2);
    292     Object* value = (Object*) args[4];
    293     Object** address = (Object**) (((u1*) obj) + offset);
    294 
    295     *address = value;
    296     dvmWriteBarrierField(obj, address);
    297     RETURN_VOID();
    298 }
    299 
    300 const DalvikNativeMethod dvm_sun_misc_Unsafe[] = {
    301     { "objectFieldOffset0", "(Ljava/lang/reflect/Field;)J",
    302       Dalvik_sun_misc_Unsafe_objectFieldOffset0 },
    303     { "arrayBaseOffset0", "(Ljava/lang/Class;)I",
    304       Dalvik_sun_misc_Unsafe_arrayBaseOffset0 },
    305     { "arrayIndexScale0", "(Ljava/lang/Class;)I",
    306       Dalvik_sun_misc_Unsafe_arrayIndexScale0 },
    307     { "compareAndSwapInt", "(Ljava/lang/Object;JII)Z",
    308       Dalvik_sun_misc_Unsafe_compareAndSwapInt },
    309     { "compareAndSwapLong", "(Ljava/lang/Object;JJJ)Z",
    310       Dalvik_sun_misc_Unsafe_compareAndSwapLong },
    311     { "compareAndSwapObject",
    312       "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z",
    313       Dalvik_sun_misc_Unsafe_compareAndSwapObject },
    314     { "getIntVolatile", "(Ljava/lang/Object;J)I",
    315       Dalvik_sun_misc_Unsafe_getIntVolatile },
    316     { "putIntVolatile", "(Ljava/lang/Object;JI)V",
    317       Dalvik_sun_misc_Unsafe_putIntVolatile },
    318     { "getLongVolatile", "(Ljava/lang/Object;J)J",
    319       Dalvik_sun_misc_Unsafe_getLongVolatile },
    320     { "putLongVolatile", "(Ljava/lang/Object;JJ)V",
    321       Dalvik_sun_misc_Unsafe_putLongVolatile },
    322     { "getObjectVolatile", "(Ljava/lang/Object;J)Ljava/lang/Object;",
    323       Dalvik_sun_misc_Unsafe_getObjectVolatile },
    324     { "putObjectVolatile", "(Ljava/lang/Object;JLjava/lang/Object;)V",
    325       Dalvik_sun_misc_Unsafe_putObjectVolatile },
    326     { "getInt", "(Ljava/lang/Object;J)I",
    327       Dalvik_sun_misc_Unsafe_getInt },
    328     { "putInt", "(Ljava/lang/Object;JI)V",
    329       Dalvik_sun_misc_Unsafe_putInt },
    330     { "getLong", "(Ljava/lang/Object;J)J",
    331       Dalvik_sun_misc_Unsafe_getLong },
    332     { "putLong", "(Ljava/lang/Object;JJ)V",
    333       Dalvik_sun_misc_Unsafe_putLong },
    334     { "getObject", "(Ljava/lang/Object;J)Ljava/lang/Object;",
    335       Dalvik_sun_misc_Unsafe_getObject },
    336     { "putObject", "(Ljava/lang/Object;JLjava/lang/Object;)V",
    337       Dalvik_sun_misc_Unsafe_putObject },
    338     { NULL, NULL, NULL },
    339 };
    340