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