• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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