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
     21 #define _DALVIK_OO_OBJECTINLINES
     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 **)(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 = 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 = 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     void** 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 = 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     android_atomic_release_store(val, ptr);
    159 }
    160 INLINE void dvmSetFieldBooleanVolatile(Object* obj, int offset, bool val) {
    161     dvmSetFieldIntVolatile(obj, offset, val);
    162 }
    163 INLINE void dvmSetFieldByteVolatile(Object* obj, int offset, s1 val) {
    164     dvmSetFieldIntVolatile(obj, offset, val);
    165 }
    166 INLINE void dvmSetFieldShortVolatile(Object* obj, int offset, s2 val) {
    167     dvmSetFieldIntVolatile(obj, offset, val);
    168 }
    169 INLINE void dvmSetFieldCharVolatile(Object* obj, int offset, u2 val) {
    170     dvmSetFieldIntVolatile(obj, offset, val);
    171 }
    172 INLINE void dvmSetFieldFloatVolatile(Object* obj, int offset, float val) {
    173     union { s4 ival; float fval; } alias;
    174     alias.fval = val;
    175     dvmSetFieldIntVolatile(obj, offset, alias.ival);
    176 }
    177 INLINE void dvmSetFieldLongVolatile(Object* obj, int offset, s8 val) {
    178     s8* addr = BYTE_OFFSET(obj, offset);
    179     ANDROID_MEMBAR_FULL();
    180     dvmQuasiAtomicSwap64(val, addr);
    181 }
    182 INLINE void dvmSetFieldDoubleVolatile(Object* obj, int offset, double val) {
    183     union { s8 lval; double dval; } alias;
    184     alias.dval = val;
    185     dvmSetFieldLongVolatile(obj, offset, alias.lval);
    186 }
    187 INLINE void dvmSetFieldObjectVolatile(Object* obj, int offset, Object* val) {
    188     void** ptr = &((JValue*)BYTE_OFFSET(obj, offset))->l;
    189     android_atomic_release_store((int32_t)val, (int32_t*)ptr);
    190     if (val != NULL) {
    191         dvmWriteBarrierField(obj, ptr);
    192     }
    193 }
    194 
    195 /*
    196  * Static field access functions.
    197  */
    198 INLINE JValue* dvmStaticFieldPtr(const StaticField* sfield) {
    199     return (JValue*)&sfield->value;
    200 }
    201 
    202 INLINE bool dvmGetStaticFieldBoolean(const StaticField* sfield) {
    203     return sfield->value.z;
    204 }
    205 INLINE s1 dvmGetStaticFieldByte(const StaticField* sfield) {
    206     return sfield->value.b;
    207 }
    208 INLINE s2 dvmGetStaticFieldShort(const StaticField* sfield) {
    209     return sfield->value.s;
    210 }
    211 INLINE u2 dvmGetStaticFieldChar(const StaticField* sfield) {
    212     return sfield->value.c;
    213 }
    214 INLINE s4 dvmGetStaticFieldInt(const StaticField* sfield) {
    215     return sfield->value.i;
    216 }
    217 INLINE float dvmGetStaticFieldFloat(const StaticField* sfield) {
    218     return sfield->value.f;
    219 }
    220 INLINE s8 dvmGetStaticFieldLong(const StaticField* sfield) {
    221     return sfield->value.j;
    222 }
    223 INLINE double dvmGetStaticFieldDouble(const StaticField* sfield) {
    224     return sfield->value.d;
    225 }
    226 INLINE Object* dvmGetStaticFieldObject(const StaticField* sfield) {
    227     return sfield->value.l;
    228 }
    229 INLINE bool dvmGetStaticFieldBooleanVolatile(const StaticField* sfield) {
    230     const s4* ptr = &(sfield->value.i);
    231     return (bool)android_atomic_acquire_load((s4*)ptr);
    232 }
    233 INLINE s1 dvmGetStaticFieldByteVolatile(const StaticField* sfield) {
    234     const s4* ptr = &(sfield->value.i);
    235     return (s1)android_atomic_acquire_load((s4*)ptr);
    236 }
    237 INLINE s2 dvmGetStaticFieldShortVolatile(const StaticField* sfield) {
    238     const s4* ptr = &(sfield->value.i);
    239     return (s2)android_atomic_acquire_load((s4*)ptr);
    240 }
    241 INLINE u2 dvmGetStaticFieldCharVolatile(const StaticField* sfield) {
    242     const s4* ptr = &(sfield->value.i);
    243     return (u2)android_atomic_acquire_load((s4*)ptr);
    244 }
    245 INLINE s4 dvmGetStaticFieldIntVolatile(const StaticField* sfield) {
    246     const s4* ptr = &(sfield->value.i);
    247     return android_atomic_acquire_load((s4*)ptr);
    248 }
    249 INLINE float dvmGetStaticFieldFloatVolatile(const StaticField* sfield) {
    250     union { s4 ival; float fval; } alias;
    251     const s4* ptr = &(sfield->value.i);
    252     alias.ival = android_atomic_acquire_load((s4*)ptr);
    253     return alias.fval;
    254 }
    255 INLINE s8 dvmGetStaticFieldLongVolatile(const StaticField* sfield) {
    256     const s8* addr = &sfield->value.j;
    257     s8 val = dvmQuasiAtomicRead64(addr);
    258     ANDROID_MEMBAR_FULL();
    259     return val;
    260 }
    261 INLINE double dvmGetStaticFieldDoubleVolatile(const StaticField* sfield) {
    262     union { s8 lval; double dval; } alias;
    263     const s8* addr = &sfield->value.j;
    264     alias.lval = dvmQuasiAtomicRead64(addr);
    265     ANDROID_MEMBAR_FULL();
    266     return alias.dval;
    267 }
    268 INLINE Object* dvmGetStaticFieldObjectVolatile(const StaticField* sfield) {
    269     void* const* ptr = &(sfield->value.l);
    270     return (Object*)android_atomic_acquire_load((int32_t*)ptr);
    271 }
    272 
    273 INLINE void dvmSetStaticFieldBoolean(StaticField* sfield, bool val) {
    274     sfield->value.i = val;
    275 }
    276 INLINE void dvmSetStaticFieldByte(StaticField* sfield, s1 val) {
    277     sfield->value.i = val;
    278 }
    279 INLINE void dvmSetStaticFieldShort(StaticField* sfield, s2 val) {
    280     sfield->value.i = val;
    281 }
    282 INLINE void dvmSetStaticFieldChar(StaticField* sfield, u2 val) {
    283     sfield->value.i = val;
    284 }
    285 INLINE void dvmSetStaticFieldInt(StaticField* sfield, s4 val) {
    286     sfield->value.i = val;
    287 }
    288 INLINE void dvmSetStaticFieldFloat(StaticField* sfield, float val) {
    289     sfield->value.f = val;
    290 }
    291 INLINE void dvmSetStaticFieldLong(StaticField* sfield, s8 val) {
    292     sfield->value.j = val;
    293 }
    294 INLINE void dvmSetStaticFieldDouble(StaticField* sfield, double val) {
    295     sfield->value.d = val;
    296 }
    297 INLINE void dvmSetStaticFieldObject(StaticField* sfield, Object* val) {
    298     sfield->value.l = val;
    299     if (val != NULL) {
    300         dvmWriteBarrierField((Object *)sfield->field.clazz, &sfield->value.l);
    301     }
    302 }
    303 INLINE void dvmSetStaticFieldIntVolatile(StaticField* sfield, s4 val) {
    304     s4* ptr = &sfield->value.i;
    305     android_atomic_release_store(val, ptr);
    306 }
    307 INLINE void dvmSetStaticFieldBooleanVolatile(StaticField* sfield, bool val) {
    308     dvmSetStaticFieldIntVolatile(sfield, val);
    309 }
    310 INLINE void dvmSetStaticFieldByteVolatile(StaticField* sfield, s1 val) {
    311     dvmSetStaticFieldIntVolatile(sfield, val);
    312 }
    313 INLINE void dvmSetStaticFieldShortVolatile(StaticField* sfield, s2 val) {
    314     dvmSetStaticFieldIntVolatile(sfield, val);
    315 }
    316 INLINE void dvmSetStaticFieldCharVolatile(StaticField* sfield, u2 val) {
    317     dvmSetStaticFieldIntVolatile(sfield, val);
    318 }
    319 INLINE void dvmSetStaticFieldFloatVolatile(StaticField* sfield, float val) {
    320     union { s4 ival; float fval; } alias;
    321     alias.fval = val;
    322     dvmSetStaticFieldIntVolatile(sfield, alias.ival);
    323 }
    324 INLINE void dvmSetStaticFieldLongVolatile(StaticField* sfield, s8 val) {
    325     s8* addr = &sfield->value.j;
    326     ANDROID_MEMBAR_FULL();
    327     dvmQuasiAtomicSwap64(val, addr);
    328 }
    329 INLINE void dvmSetStaticFieldDoubleVolatile(StaticField* sfield, double val) {
    330     union { s8 lval; double dval; } alias;
    331     alias.dval = val;
    332     dvmSetStaticFieldLongVolatile(sfield, alias.lval);
    333 }
    334 INLINE void dvmSetStaticFieldObjectVolatile(StaticField* sfield, Object* val) {
    335     void** ptr = &(sfield->value.l);
    336     android_atomic_release_store((int32_t)val, (int32_t*)ptr);
    337     if (val != NULL) {
    338         dvmWriteBarrierField((Object *)sfield->field.clazz, &sfield->value.l);
    339     }
    340 }
    341 
    342 #endif /*_DALVIK_OO_OBJECTINLINES*/
    343