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