Home | History | Annotate | Download | only in oo
      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  * Helper functions to access data fields in Objects.
     19  */
     20 #ifndef DALVIK_OO_OBJECTINLINES_H_
     21 #define DALVIK_OO_OBJECTINLINES_H_
     22 
     23 /*
     24  * Store a single value in the array, and if the value isn't null,
     25  * note in the write barrier.
     26  */
     27 INLINE void dvmSetObjectArrayElement(const ArrayObject* obj, int index,
     28                                      Object* val) {
     29     ((Object **)(void *)(obj)->contents)[index] = val;
     30     if (val != NULL) {
     31         dvmWriteBarrierArray(obj, index, index + 1);
     32     }
     33 }
     34 
     35 
     36 /*
     37  * Field access functions.  Pass in the word offset from Field->byteOffset.
     38  *
     39  * We guarantee that long/double field data is 64-bit aligned, so it's safe
     40  * to access them with ldrd/strd on ARM.
     41  *
     42  * The VM treats all fields as 32 or 64 bits, so the field set functions
     43  * write 32 bits even if the underlying type is smaller.
     44  *
     45  * Setting Object types to non-null values includes a call to the
     46  * write barrier.
     47  */
     48 #define BYTE_OFFSET(_ptr, _offset)  ((void*) (((u1*)(_ptr)) + (_offset)))
     49 
     50 INLINE JValue* dvmFieldPtr(const Object* obj, int offset) {
     51     return ((JValue*)BYTE_OFFSET(obj, offset));
     52 }
     53 
     54 INLINE bool dvmGetFieldBoolean(const Object* obj, int offset) {
     55     return ((JValue*)BYTE_OFFSET(obj, offset))->z;
     56 }
     57 INLINE s1 dvmGetFieldByte(const Object* obj, int offset) {
     58     return ((JValue*)BYTE_OFFSET(obj, offset))->b;
     59 }
     60 INLINE s2 dvmGetFieldShort(const Object* obj, int offset) {
     61     return ((JValue*)BYTE_OFFSET(obj, offset))->s;
     62 }
     63 INLINE u2 dvmGetFieldChar(const Object* obj, int offset) {
     64     return ((JValue*)BYTE_OFFSET(obj, offset))->c;
     65 }
     66 INLINE s4 dvmGetFieldInt(const Object* obj, int offset) {
     67     return ((JValue*)BYTE_OFFSET(obj, offset))->i;
     68 }
     69 INLINE s8 dvmGetFieldLong(const Object* obj, int offset) {
     70     return ((JValue*)BYTE_OFFSET(obj, offset))->j;
     71 }
     72 INLINE float dvmGetFieldFloat(const Object* obj, int offset) {
     73     return ((JValue*)BYTE_OFFSET(obj, offset))->f;
     74 }
     75 INLINE double dvmGetFieldDouble(const Object* obj, int offset) {
     76     return ((JValue*)BYTE_OFFSET(obj, offset))->d;
     77 }
     78 INLINE Object* dvmGetFieldObject(const Object* obj, int offset) {
     79     return ((JValue*)BYTE_OFFSET(obj, offset))->l;
     80 }
     81 INLINE bool dvmGetFieldBooleanVolatile(const Object* obj, int offset) {
     82     s4* ptr = &((JValue*)BYTE_OFFSET(obj, offset))->i;
     83     return (bool)android_atomic_acquire_load(ptr);
     84 }
     85 INLINE s1 dvmGetFieldByteVolatile(const Object* obj, int offset) {
     86     s4* ptr = &((JValue*)BYTE_OFFSET(obj, offset))->i;
     87     return (s1)android_atomic_acquire_load(ptr);
     88 }
     89 INLINE s2 dvmGetFieldShortVolatile(const Object* obj, int offset) {
     90     s4* ptr = &((JValue*)BYTE_OFFSET(obj, offset))->i;
     91     return (s2)android_atomic_acquire_load(ptr);
     92 }
     93 INLINE u2 dvmGetFieldCharVolatile(const Object* obj, int offset) {
     94     s4* ptr = &((JValue*)BYTE_OFFSET(obj, offset))->i;
     95     return (u2)android_atomic_acquire_load(ptr);
     96 }
     97 INLINE s4 dvmGetFieldIntVolatile(const Object* obj, int offset) {
     98     s4* ptr = &((JValue*)BYTE_OFFSET(obj, offset))->i;
     99     return android_atomic_acquire_load(ptr);
    100 }
    101 INLINE float dvmGetFieldFloatVolatile(const Object* obj, int offset) {
    102     union { s4 ival; float fval; } alias;
    103     s4* ptr = &((JValue*)BYTE_OFFSET(obj, offset))->i;
    104     alias.ival = android_atomic_acquire_load(ptr);
    105     return alias.fval;
    106 }
    107 INLINE s8 dvmGetFieldLongVolatile(const Object* obj, int offset) {
    108     const s8* addr = (const s8*)BYTE_OFFSET(obj, offset);
    109     s8 val = dvmQuasiAtomicRead64(addr);
    110     ANDROID_MEMBAR_FULL();
    111     return val;
    112 }
    113 INLINE double dvmGetFieldDoubleVolatile(const Object* obj, int offset) {
    114     union { s8 lval; double dval; } alias;
    115     const s8* addr = (const s8*)BYTE_OFFSET(obj, offset);
    116     alias.lval = dvmQuasiAtomicRead64(addr);
    117     ANDROID_MEMBAR_FULL();
    118     return alias.dval;
    119 }
    120 INLINE Object* dvmGetFieldObjectVolatile(const Object* obj, int offset) {
    121     Object** ptr = &((JValue*)BYTE_OFFSET(obj, offset))->l;
    122     return (Object*)android_atomic_acquire_load((int32_t*)ptr);
    123 }
    124 
    125 INLINE void dvmSetFieldBoolean(Object* obj, int offset, bool val) {
    126     ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
    127 }
    128 INLINE void dvmSetFieldByte(Object* obj, int offset, s1 val) {
    129     ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
    130 }
    131 INLINE void dvmSetFieldShort(Object* obj, int offset, s2 val) {
    132     ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
    133 }
    134 INLINE void dvmSetFieldChar(Object* obj, int offset, u2 val) {
    135     ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
    136 }
    137 INLINE void dvmSetFieldInt(Object* obj, int offset, s4 val) {
    138     ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
    139 }
    140 INLINE void dvmSetFieldFloat(Object* obj, int offset, float val) {
    141     ((JValue*)BYTE_OFFSET(obj, offset))->f = val;
    142 }
    143 INLINE void dvmSetFieldLong(Object* obj, int offset, s8 val) {
    144     ((JValue*)BYTE_OFFSET(obj, offset))->j = val;
    145 }
    146 INLINE void dvmSetFieldDouble(Object* obj, int offset, double val) {
    147     ((JValue*)BYTE_OFFSET(obj, offset))->d = val;
    148 }
    149 INLINE void dvmSetFieldObject(Object* obj, int offset, Object* val) {
    150     JValue* lhs = (JValue*)BYTE_OFFSET(obj, offset);
    151     lhs->l = val;
    152     if (val != NULL) {
    153         dvmWriteBarrierField(obj, &lhs->l);
    154     }
    155 }
    156 INLINE void dvmSetFieldIntVolatile(Object* obj, int offset, s4 val) {
    157     s4* ptr = &((JValue*)BYTE_OFFSET(obj, offset))->i;
    158     /*
    159      * TODO: add an android_atomic_synchronization_store() function and
    160      * use it in the 32-bit volatile set handlers.  On some platforms we
    161      * can use a fast atomic instruction and avoid the barriers.
    162      */
    163     ANDROID_MEMBAR_STORE();
    164     *ptr = val;
    165     ANDROID_MEMBAR_FULL();
    166 }
    167 INLINE void dvmSetFieldBooleanVolatile(Object* obj, int offset, bool val) {
    168     dvmSetFieldIntVolatile(obj, offset, val);
    169 }
    170 INLINE void dvmSetFieldByteVolatile(Object* obj, int offset, s1 val) {
    171     dvmSetFieldIntVolatile(obj, offset, val);
    172 }
    173 INLINE void dvmSetFieldShortVolatile(Object* obj, int offset, s2 val) {
    174     dvmSetFieldIntVolatile(obj, offset, val);
    175 }
    176 INLINE void dvmSetFieldCharVolatile(Object* obj, int offset, u2 val) {
    177     dvmSetFieldIntVolatile(obj, offset, val);
    178 }
    179 INLINE void dvmSetFieldFloatVolatile(Object* obj, int offset, float val) {
    180     union { s4 ival; float fval; } alias;
    181     alias.fval = val;
    182     dvmSetFieldIntVolatile(obj, offset, alias.ival);
    183 }
    184 INLINE void dvmSetFieldLongVolatile(Object* obj, int offset, s8 val) {
    185     s8* addr = (s8*)BYTE_OFFSET(obj, offset);
    186     dvmQuasiAtomicSwap64Sync(val, addr);
    187 }
    188 INLINE void dvmSetFieldDoubleVolatile(Object* obj, int offset, double val) {
    189     union { s8 lval; double dval; } alias;
    190     alias.dval = val;
    191     dvmSetFieldLongVolatile(obj, offset, alias.lval);
    192 }
    193 INLINE void dvmSetFieldObjectVolatile(Object* obj, int offset, Object* val) {
    194     Object** ptr = &((JValue*)BYTE_OFFSET(obj, offset))->l;
    195     ANDROID_MEMBAR_STORE();
    196     *ptr = val;
    197     ANDROID_MEMBAR_FULL();
    198     if (val != NULL) {
    199         dvmWriteBarrierField(obj, ptr);
    200     }
    201 }
    202 
    203 /*
    204  * Static field access functions.
    205  */
    206 INLINE JValue* dvmStaticFieldPtr(const StaticField* sfield) {
    207     return (JValue*)&sfield->value;
    208 }
    209 
    210 INLINE bool dvmGetStaticFieldBoolean(const StaticField* sfield) {
    211     return sfield->value.z;
    212 }
    213 INLINE s1 dvmGetStaticFieldByte(const StaticField* sfield) {
    214     return sfield->value.b;
    215 }
    216 INLINE s2 dvmGetStaticFieldShort(const StaticField* sfield) {
    217     return sfield->value.s;
    218 }
    219 INLINE u2 dvmGetStaticFieldChar(const StaticField* sfield) {
    220     return sfield->value.c;
    221 }
    222 INLINE s4 dvmGetStaticFieldInt(const StaticField* sfield) {
    223     return sfield->value.i;
    224 }
    225 INLINE float dvmGetStaticFieldFloat(const StaticField* sfield) {
    226     return sfield->value.f;
    227 }
    228 INLINE s8 dvmGetStaticFieldLong(const StaticField* sfield) {
    229     return sfield->value.j;
    230 }
    231 INLINE double dvmGetStaticFieldDouble(const StaticField* sfield) {
    232     return sfield->value.d;
    233 }
    234 INLINE Object* dvmGetStaticFieldObject(const StaticField* sfield) {
    235     return sfield->value.l;
    236 }
    237 INLINE bool dvmGetStaticFieldBooleanVolatile(const StaticField* sfield) {
    238     const s4* ptr = &(sfield->value.i);
    239     return (bool)android_atomic_acquire_load((s4*)ptr);
    240 }
    241 INLINE s1 dvmGetStaticFieldByteVolatile(const StaticField* sfield) {
    242     const s4* ptr = &(sfield->value.i);
    243     return (s1)android_atomic_acquire_load((s4*)ptr);
    244 }
    245 INLINE s2 dvmGetStaticFieldShortVolatile(const StaticField* sfield) {
    246     const s4* ptr = &(sfield->value.i);
    247     return (s2)android_atomic_acquire_load((s4*)ptr);
    248 }
    249 INLINE u2 dvmGetStaticFieldCharVolatile(const StaticField* sfield) {
    250     const s4* ptr = &(sfield->value.i);
    251     return (u2)android_atomic_acquire_load((s4*)ptr);
    252 }
    253 INLINE s4 dvmGetStaticFieldIntVolatile(const StaticField* sfield) {
    254     const s4* ptr = &(sfield->value.i);
    255     return android_atomic_acquire_load((s4*)ptr);
    256 }
    257 INLINE float dvmGetStaticFieldFloatVolatile(const StaticField* sfield) {
    258     union { s4 ival; float fval; } alias;
    259     const s4* ptr = &(sfield->value.i);
    260     alias.ival = android_atomic_acquire_load((s4*)ptr);
    261     return alias.fval;
    262 }
    263 INLINE s8 dvmGetStaticFieldLongVolatile(const StaticField* sfield) {
    264     const s8* addr = &sfield->value.j;
    265     s8 val = dvmQuasiAtomicRead64(addr);
    266     ANDROID_MEMBAR_FULL();
    267     return val;
    268 }
    269 INLINE double dvmGetStaticFieldDoubleVolatile(const StaticField* sfield) {
    270     union { s8 lval; double dval; } alias;
    271     const s8* addr = &sfield->value.j;
    272     alias.lval = dvmQuasiAtomicRead64(addr);
    273     ANDROID_MEMBAR_FULL();
    274     return alias.dval;
    275 }
    276 INLINE Object* dvmGetStaticFieldObjectVolatile(const StaticField* sfield) {
    277     Object* const* ptr = &(sfield->value.l);
    278     return (Object*)android_atomic_acquire_load((int32_t*)ptr);
    279 }
    280 
    281 INLINE void dvmSetStaticFieldBoolean(StaticField* sfield, bool val) {
    282     sfield->value.i = val;
    283 }
    284 INLINE void dvmSetStaticFieldByte(StaticField* sfield, s1 val) {
    285     sfield->value.i = val;
    286 }
    287 INLINE void dvmSetStaticFieldShort(StaticField* sfield, s2 val) {
    288     sfield->value.i = val;
    289 }
    290 INLINE void dvmSetStaticFieldChar(StaticField* sfield, u2 val) {
    291     sfield->value.i = val;
    292 }
    293 INLINE void dvmSetStaticFieldInt(StaticField* sfield, s4 val) {
    294     sfield->value.i = val;
    295 }
    296 INLINE void dvmSetStaticFieldFloat(StaticField* sfield, float val) {
    297     sfield->value.f = val;
    298 }
    299 INLINE void dvmSetStaticFieldLong(StaticField* sfield, s8 val) {
    300     sfield->value.j = val;
    301 }
    302 INLINE void dvmSetStaticFieldDouble(StaticField* sfield, double val) {
    303     sfield->value.d = val;
    304 }
    305 INLINE void dvmSetStaticFieldObject(StaticField* sfield, Object* val) {
    306     sfield->value.l = val;
    307     if (val != NULL) {
    308         dvmWriteBarrierField(sfield->clazz, &sfield->value.l);
    309     }
    310 }
    311 INLINE void dvmSetStaticFieldIntVolatile(StaticField* sfield, s4 val) {
    312     s4* ptr = &sfield->value.i;
    313     ANDROID_MEMBAR_STORE();
    314     *ptr = val;
    315     ANDROID_MEMBAR_FULL();
    316 }
    317 INLINE void dvmSetStaticFieldBooleanVolatile(StaticField* sfield, bool val) {
    318     dvmSetStaticFieldIntVolatile(sfield, val);
    319 }
    320 INLINE void dvmSetStaticFieldByteVolatile(StaticField* sfield, s1 val) {
    321     dvmSetStaticFieldIntVolatile(sfield, val);
    322 }
    323 INLINE void dvmSetStaticFieldShortVolatile(StaticField* sfield, s2 val) {
    324     dvmSetStaticFieldIntVolatile(sfield, val);
    325 }
    326 INLINE void dvmSetStaticFieldCharVolatile(StaticField* sfield, u2 val) {
    327     dvmSetStaticFieldIntVolatile(sfield, val);
    328 }
    329 INLINE void dvmSetStaticFieldFloatVolatile(StaticField* sfield, float val) {
    330     union { s4 ival; float fval; } alias;
    331     alias.fval = val;
    332     dvmSetStaticFieldIntVolatile(sfield, alias.ival);
    333 }
    334 INLINE void dvmSetStaticFieldLongVolatile(StaticField* sfield, s8 val) {
    335     s8* addr = &sfield->value.j;
    336     dvmQuasiAtomicSwap64Sync(val, addr);
    337 }
    338 INLINE void dvmSetStaticFieldDoubleVolatile(StaticField* sfield, double val) {
    339     union { s8 lval; double dval; } alias;
    340     alias.dval = val;
    341     dvmSetStaticFieldLongVolatile(sfield, alias.lval);
    342 }
    343 INLINE void dvmSetStaticFieldObjectVolatile(StaticField* sfield, Object* val) {
    344     Object** ptr = &(sfield->value.l);
    345     ANDROID_MEMBAR_STORE();
    346     *ptr = val;
    347     ANDROID_MEMBAR_FULL();
    348     if (val != NULL) {
    349         dvmWriteBarrierField(sfield->clazz, &sfield->value.l);
    350     }
    351 }
    352 
    353 #endif  // DALVIK_OO_OBJECTINLINES_H_
    354