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 */
dvmSetObjectArrayElement(const ArrayObject * obj,int index,Object * val)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
dvmFieldPtr(const Object * obj,int offset)50 INLINE JValue* dvmFieldPtr(const Object* obj, int offset) {
51 return ((JValue*)BYTE_OFFSET(obj, offset));
52 }
53
dvmGetFieldBoolean(const Object * obj,int offset)54 INLINE bool dvmGetFieldBoolean(const Object* obj, int offset) {
55 return ((JValue*)BYTE_OFFSET(obj, offset))->z;
56 }
dvmGetFieldByte(const Object * obj,int offset)57 INLINE s1 dvmGetFieldByte(const Object* obj, int offset) {
58 return ((JValue*)BYTE_OFFSET(obj, offset))->b;
59 }
dvmGetFieldShort(const Object * obj,int offset)60 INLINE s2 dvmGetFieldShort(const Object* obj, int offset) {
61 return ((JValue*)BYTE_OFFSET(obj, offset))->s;
62 }
dvmGetFieldChar(const Object * obj,int offset)63 INLINE u2 dvmGetFieldChar(const Object* obj, int offset) {
64 return ((JValue*)BYTE_OFFSET(obj, offset))->c;
65 }
dvmGetFieldInt(const Object * obj,int offset)66 INLINE s4 dvmGetFieldInt(const Object* obj, int offset) {
67 return ((JValue*)BYTE_OFFSET(obj, offset))->i;
68 }
dvmGetFieldLong(const Object * obj,int offset)69 INLINE s8 dvmGetFieldLong(const Object* obj, int offset) {
70 return ((JValue*)BYTE_OFFSET(obj, offset))->j;
71 }
dvmGetFieldFloat(const Object * obj,int offset)72 INLINE float dvmGetFieldFloat(const Object* obj, int offset) {
73 return ((JValue*)BYTE_OFFSET(obj, offset))->f;
74 }
dvmGetFieldDouble(const Object * obj,int offset)75 INLINE double dvmGetFieldDouble(const Object* obj, int offset) {
76 return ((JValue*)BYTE_OFFSET(obj, offset))->d;
77 }
dvmGetFieldObject(const Object * obj,int offset)78 INLINE Object* dvmGetFieldObject(const Object* obj, int offset) {
79 return ((JValue*)BYTE_OFFSET(obj, offset))->l;
80 }
dvmGetFieldBooleanVolatile(const Object * obj,int offset)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 }
dvmGetFieldByteVolatile(const Object * obj,int offset)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 }
dvmGetFieldShortVolatile(const Object * obj,int offset)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 }
dvmGetFieldCharVolatile(const Object * obj,int offset)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 }
dvmGetFieldIntVolatile(const Object * obj,int offset)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 }
dvmGetFieldFloatVolatile(const Object * obj,int offset)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 }
dvmGetFieldLongVolatile(const Object * obj,int offset)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 }
dvmGetFieldDoubleVolatile(const Object * obj,int offset)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 }
dvmGetFieldObjectVolatile(const Object * obj,int offset)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
dvmSetFieldBoolean(Object * obj,int offset,bool val)125 INLINE void dvmSetFieldBoolean(Object* obj, int offset, bool val) {
126 ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
127 }
dvmSetFieldByte(Object * obj,int offset,s1 val)128 INLINE void dvmSetFieldByte(Object* obj, int offset, s1 val) {
129 ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
130 }
dvmSetFieldShort(Object * obj,int offset,s2 val)131 INLINE void dvmSetFieldShort(Object* obj, int offset, s2 val) {
132 ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
133 }
dvmSetFieldChar(Object * obj,int offset,u2 val)134 INLINE void dvmSetFieldChar(Object* obj, int offset, u2 val) {
135 ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
136 }
dvmSetFieldInt(Object * obj,int offset,s4 val)137 INLINE void dvmSetFieldInt(Object* obj, int offset, s4 val) {
138 ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
139 }
dvmSetFieldFloat(Object * obj,int offset,float val)140 INLINE void dvmSetFieldFloat(Object* obj, int offset, float val) {
141 ((JValue*)BYTE_OFFSET(obj, offset))->f = val;
142 }
dvmSetFieldLong(Object * obj,int offset,s8 val)143 INLINE void dvmSetFieldLong(Object* obj, int offset, s8 val) {
144 ((JValue*)BYTE_OFFSET(obj, offset))->j = val;
145 }
dvmSetFieldDouble(Object * obj,int offset,double val)146 INLINE void dvmSetFieldDouble(Object* obj, int offset, double val) {
147 ((JValue*)BYTE_OFFSET(obj, offset))->d = val;
148 }
dvmSetFieldObject(Object * obj,int offset,Object * val)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 }
dvmSetFieldIntVolatile(Object * obj,int offset,s4 val)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 }
dvmSetFieldBooleanVolatile(Object * obj,int offset,bool val)167 INLINE void dvmSetFieldBooleanVolatile(Object* obj, int offset, bool val) {
168 dvmSetFieldIntVolatile(obj, offset, val);
169 }
dvmSetFieldByteVolatile(Object * obj,int offset,s1 val)170 INLINE void dvmSetFieldByteVolatile(Object* obj, int offset, s1 val) {
171 dvmSetFieldIntVolatile(obj, offset, val);
172 }
dvmSetFieldShortVolatile(Object * obj,int offset,s2 val)173 INLINE void dvmSetFieldShortVolatile(Object* obj, int offset, s2 val) {
174 dvmSetFieldIntVolatile(obj, offset, val);
175 }
dvmSetFieldCharVolatile(Object * obj,int offset,u2 val)176 INLINE void dvmSetFieldCharVolatile(Object* obj, int offset, u2 val) {
177 dvmSetFieldIntVolatile(obj, offset, val);
178 }
dvmSetFieldFloatVolatile(Object * obj,int offset,float val)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 }
dvmSetFieldLongVolatile(Object * obj,int offset,s8 val)184 INLINE void dvmSetFieldLongVolatile(Object* obj, int offset, s8 val) {
185 s8* addr = (s8*)BYTE_OFFSET(obj, offset);
186 dvmQuasiAtomicSwap64Sync(val, addr);
187 }
dvmSetFieldDoubleVolatile(Object * obj,int offset,double val)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 }
dvmSetFieldObjectVolatile(Object * obj,int offset,Object * val)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 */
dvmStaticFieldPtr(const StaticField * sfield)206 INLINE JValue* dvmStaticFieldPtr(const StaticField* sfield) {
207 return (JValue*)&sfield->value;
208 }
209
dvmGetStaticFieldBoolean(const StaticField * sfield)210 INLINE bool dvmGetStaticFieldBoolean(const StaticField* sfield) {
211 return sfield->value.z;
212 }
dvmGetStaticFieldByte(const StaticField * sfield)213 INLINE s1 dvmGetStaticFieldByte(const StaticField* sfield) {
214 return sfield->value.b;
215 }
dvmGetStaticFieldShort(const StaticField * sfield)216 INLINE s2 dvmGetStaticFieldShort(const StaticField* sfield) {
217 return sfield->value.s;
218 }
dvmGetStaticFieldChar(const StaticField * sfield)219 INLINE u2 dvmGetStaticFieldChar(const StaticField* sfield) {
220 return sfield->value.c;
221 }
dvmGetStaticFieldInt(const StaticField * sfield)222 INLINE s4 dvmGetStaticFieldInt(const StaticField* sfield) {
223 return sfield->value.i;
224 }
dvmGetStaticFieldFloat(const StaticField * sfield)225 INLINE float dvmGetStaticFieldFloat(const StaticField* sfield) {
226 return sfield->value.f;
227 }
dvmGetStaticFieldLong(const StaticField * sfield)228 INLINE s8 dvmGetStaticFieldLong(const StaticField* sfield) {
229 return sfield->value.j;
230 }
dvmGetStaticFieldDouble(const StaticField * sfield)231 INLINE double dvmGetStaticFieldDouble(const StaticField* sfield) {
232 return sfield->value.d;
233 }
dvmGetStaticFieldObject(const StaticField * sfield)234 INLINE Object* dvmGetStaticFieldObject(const StaticField* sfield) {
235 return sfield->value.l;
236 }
dvmGetStaticFieldBooleanVolatile(const StaticField * sfield)237 INLINE bool dvmGetStaticFieldBooleanVolatile(const StaticField* sfield) {
238 const s4* ptr = &(sfield->value.i);
239 return (bool)android_atomic_acquire_load((s4*)ptr);
240 }
dvmGetStaticFieldByteVolatile(const StaticField * sfield)241 INLINE s1 dvmGetStaticFieldByteVolatile(const StaticField* sfield) {
242 const s4* ptr = &(sfield->value.i);
243 return (s1)android_atomic_acquire_load((s4*)ptr);
244 }
dvmGetStaticFieldShortVolatile(const StaticField * sfield)245 INLINE s2 dvmGetStaticFieldShortVolatile(const StaticField* sfield) {
246 const s4* ptr = &(sfield->value.i);
247 return (s2)android_atomic_acquire_load((s4*)ptr);
248 }
dvmGetStaticFieldCharVolatile(const StaticField * sfield)249 INLINE u2 dvmGetStaticFieldCharVolatile(const StaticField* sfield) {
250 const s4* ptr = &(sfield->value.i);
251 return (u2)android_atomic_acquire_load((s4*)ptr);
252 }
dvmGetStaticFieldIntVolatile(const StaticField * sfield)253 INLINE s4 dvmGetStaticFieldIntVolatile(const StaticField* sfield) {
254 const s4* ptr = &(sfield->value.i);
255 return android_atomic_acquire_load((s4*)ptr);
256 }
dvmGetStaticFieldFloatVolatile(const StaticField * sfield)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 }
dvmGetStaticFieldLongVolatile(const StaticField * sfield)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 }
dvmGetStaticFieldDoubleVolatile(const StaticField * sfield)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 }
dvmGetStaticFieldObjectVolatile(const StaticField * sfield)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
dvmSetStaticFieldBoolean(StaticField * sfield,bool val)281 INLINE void dvmSetStaticFieldBoolean(StaticField* sfield, bool val) {
282 sfield->value.i = val;
283 }
dvmSetStaticFieldByte(StaticField * sfield,s1 val)284 INLINE void dvmSetStaticFieldByte(StaticField* sfield, s1 val) {
285 sfield->value.i = val;
286 }
dvmSetStaticFieldShort(StaticField * sfield,s2 val)287 INLINE void dvmSetStaticFieldShort(StaticField* sfield, s2 val) {
288 sfield->value.i = val;
289 }
dvmSetStaticFieldChar(StaticField * sfield,u2 val)290 INLINE void dvmSetStaticFieldChar(StaticField* sfield, u2 val) {
291 sfield->value.i = val;
292 }
dvmSetStaticFieldInt(StaticField * sfield,s4 val)293 INLINE void dvmSetStaticFieldInt(StaticField* sfield, s4 val) {
294 sfield->value.i = val;
295 }
dvmSetStaticFieldFloat(StaticField * sfield,float val)296 INLINE void dvmSetStaticFieldFloat(StaticField* sfield, float val) {
297 sfield->value.f = val;
298 }
dvmSetStaticFieldLong(StaticField * sfield,s8 val)299 INLINE void dvmSetStaticFieldLong(StaticField* sfield, s8 val) {
300 sfield->value.j = val;
301 }
dvmSetStaticFieldDouble(StaticField * sfield,double val)302 INLINE void dvmSetStaticFieldDouble(StaticField* sfield, double val) {
303 sfield->value.d = val;
304 }
dvmSetStaticFieldObject(StaticField * sfield,Object * val)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 }
dvmSetStaticFieldIntVolatile(StaticField * sfield,s4 val)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 }
dvmSetStaticFieldBooleanVolatile(StaticField * sfield,bool val)317 INLINE void dvmSetStaticFieldBooleanVolatile(StaticField* sfield, bool val) {
318 dvmSetStaticFieldIntVolatile(sfield, val);
319 }
dvmSetStaticFieldByteVolatile(StaticField * sfield,s1 val)320 INLINE void dvmSetStaticFieldByteVolatile(StaticField* sfield, s1 val) {
321 dvmSetStaticFieldIntVolatile(sfield, val);
322 }
dvmSetStaticFieldShortVolatile(StaticField * sfield,s2 val)323 INLINE void dvmSetStaticFieldShortVolatile(StaticField* sfield, s2 val) {
324 dvmSetStaticFieldIntVolatile(sfield, val);
325 }
dvmSetStaticFieldCharVolatile(StaticField * sfield,u2 val)326 INLINE void dvmSetStaticFieldCharVolatile(StaticField* sfield, u2 val) {
327 dvmSetStaticFieldIntVolatile(sfield, val);
328 }
dvmSetStaticFieldFloatVolatile(StaticField * sfield,float val)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 }
dvmSetStaticFieldLongVolatile(StaticField * sfield,s8 val)334 INLINE void dvmSetStaticFieldLongVolatile(StaticField* sfield, s8 val) {
335 s8* addr = &sfield->value.j;
336 dvmQuasiAtomicSwap64Sync(val, addr);
337 }
dvmSetStaticFieldDoubleVolatile(StaticField * sfield,double val)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 }
dvmSetStaticFieldObjectVolatile(StaticField * sfield,Object * val)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