• 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
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  */
dvmSetObjectArrayElement(const ArrayObject * obj,int index,Object * val)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 
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 = 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 = 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     void** 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 = 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     android_atomic_release_store(val, ptr);
159 }
dvmSetFieldBooleanVolatile(Object * obj,int offset,bool val)160 INLINE void dvmSetFieldBooleanVolatile(Object* obj, int offset, bool val) {
161     dvmSetFieldIntVolatile(obj, offset, val);
162 }
dvmSetFieldByteVolatile(Object * obj,int offset,s1 val)163 INLINE void dvmSetFieldByteVolatile(Object* obj, int offset, s1 val) {
164     dvmSetFieldIntVolatile(obj, offset, val);
165 }
dvmSetFieldShortVolatile(Object * obj,int offset,s2 val)166 INLINE void dvmSetFieldShortVolatile(Object* obj, int offset, s2 val) {
167     dvmSetFieldIntVolatile(obj, offset, val);
168 }
dvmSetFieldCharVolatile(Object * obj,int offset,u2 val)169 INLINE void dvmSetFieldCharVolatile(Object* obj, int offset, u2 val) {
170     dvmSetFieldIntVolatile(obj, offset, val);
171 }
dvmSetFieldFloatVolatile(Object * obj,int offset,float val)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 }
dvmSetFieldLongVolatile(Object * obj,int offset,s8 val)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 }
dvmSetFieldDoubleVolatile(Object * obj,int offset,double val)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 }
dvmSetFieldObjectVolatile(Object * obj,int offset,Object * val)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  */
dvmStaticFieldPtr(const StaticField * sfield)198 INLINE JValue* dvmStaticFieldPtr(const StaticField* sfield) {
199     return (JValue*)&sfield->value;
200 }
201 
dvmGetStaticFieldBoolean(const StaticField * sfield)202 INLINE bool dvmGetStaticFieldBoolean(const StaticField* sfield) {
203     return sfield->value.z;
204 }
dvmGetStaticFieldByte(const StaticField * sfield)205 INLINE s1 dvmGetStaticFieldByte(const StaticField* sfield) {
206     return sfield->value.b;
207 }
dvmGetStaticFieldShort(const StaticField * sfield)208 INLINE s2 dvmGetStaticFieldShort(const StaticField* sfield) {
209     return sfield->value.s;
210 }
dvmGetStaticFieldChar(const StaticField * sfield)211 INLINE u2 dvmGetStaticFieldChar(const StaticField* sfield) {
212     return sfield->value.c;
213 }
dvmGetStaticFieldInt(const StaticField * sfield)214 INLINE s4 dvmGetStaticFieldInt(const StaticField* sfield) {
215     return sfield->value.i;
216 }
dvmGetStaticFieldFloat(const StaticField * sfield)217 INLINE float dvmGetStaticFieldFloat(const StaticField* sfield) {
218     return sfield->value.f;
219 }
dvmGetStaticFieldLong(const StaticField * sfield)220 INLINE s8 dvmGetStaticFieldLong(const StaticField* sfield) {
221     return sfield->value.j;
222 }
dvmGetStaticFieldDouble(const StaticField * sfield)223 INLINE double dvmGetStaticFieldDouble(const StaticField* sfield) {
224     return sfield->value.d;
225 }
dvmGetStaticFieldObject(const StaticField * sfield)226 INLINE Object* dvmGetStaticFieldObject(const StaticField* sfield) {
227     return sfield->value.l;
228 }
dvmGetStaticFieldBooleanVolatile(const StaticField * sfield)229 INLINE bool dvmGetStaticFieldBooleanVolatile(const StaticField* sfield) {
230     const s4* ptr = &(sfield->value.i);
231     return (bool)android_atomic_acquire_load((s4*)ptr);
232 }
dvmGetStaticFieldByteVolatile(const StaticField * sfield)233 INLINE s1 dvmGetStaticFieldByteVolatile(const StaticField* sfield) {
234     const s4* ptr = &(sfield->value.i);
235     return (s1)android_atomic_acquire_load((s4*)ptr);
236 }
dvmGetStaticFieldShortVolatile(const StaticField * sfield)237 INLINE s2 dvmGetStaticFieldShortVolatile(const StaticField* sfield) {
238     const s4* ptr = &(sfield->value.i);
239     return (s2)android_atomic_acquire_load((s4*)ptr);
240 }
dvmGetStaticFieldCharVolatile(const StaticField * sfield)241 INLINE u2 dvmGetStaticFieldCharVolatile(const StaticField* sfield) {
242     const s4* ptr = &(sfield->value.i);
243     return (u2)android_atomic_acquire_load((s4*)ptr);
244 }
dvmGetStaticFieldIntVolatile(const StaticField * sfield)245 INLINE s4 dvmGetStaticFieldIntVolatile(const StaticField* sfield) {
246     const s4* ptr = &(sfield->value.i);
247     return android_atomic_acquire_load((s4*)ptr);
248 }
dvmGetStaticFieldFloatVolatile(const StaticField * sfield)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 }
dvmGetStaticFieldLongVolatile(const StaticField * sfield)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 }
dvmGetStaticFieldDoubleVolatile(const StaticField * sfield)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 }
dvmGetStaticFieldObjectVolatile(const StaticField * sfield)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 
dvmSetStaticFieldBoolean(StaticField * sfield,bool val)273 INLINE void dvmSetStaticFieldBoolean(StaticField* sfield, bool val) {
274     sfield->value.i = val;
275 }
dvmSetStaticFieldByte(StaticField * sfield,s1 val)276 INLINE void dvmSetStaticFieldByte(StaticField* sfield, s1 val) {
277     sfield->value.i = val;
278 }
dvmSetStaticFieldShort(StaticField * sfield,s2 val)279 INLINE void dvmSetStaticFieldShort(StaticField* sfield, s2 val) {
280     sfield->value.i = val;
281 }
dvmSetStaticFieldChar(StaticField * sfield,u2 val)282 INLINE void dvmSetStaticFieldChar(StaticField* sfield, u2 val) {
283     sfield->value.i = val;
284 }
dvmSetStaticFieldInt(StaticField * sfield,s4 val)285 INLINE void dvmSetStaticFieldInt(StaticField* sfield, s4 val) {
286     sfield->value.i = val;
287 }
dvmSetStaticFieldFloat(StaticField * sfield,float val)288 INLINE void dvmSetStaticFieldFloat(StaticField* sfield, float val) {
289     sfield->value.f = val;
290 }
dvmSetStaticFieldLong(StaticField * sfield,s8 val)291 INLINE void dvmSetStaticFieldLong(StaticField* sfield, s8 val) {
292     sfield->value.j = val;
293 }
dvmSetStaticFieldDouble(StaticField * sfield,double val)294 INLINE void dvmSetStaticFieldDouble(StaticField* sfield, double val) {
295     sfield->value.d = val;
296 }
dvmSetStaticFieldObject(StaticField * sfield,Object * val)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 }
dvmSetStaticFieldIntVolatile(StaticField * sfield,s4 val)303 INLINE void dvmSetStaticFieldIntVolatile(StaticField* sfield, s4 val) {
304     s4* ptr = &sfield->value.i;
305     android_atomic_release_store(val, ptr);
306 }
dvmSetStaticFieldBooleanVolatile(StaticField * sfield,bool val)307 INLINE void dvmSetStaticFieldBooleanVolatile(StaticField* sfield, bool val) {
308     dvmSetStaticFieldIntVolatile(sfield, val);
309 }
dvmSetStaticFieldByteVolatile(StaticField * sfield,s1 val)310 INLINE void dvmSetStaticFieldByteVolatile(StaticField* sfield, s1 val) {
311     dvmSetStaticFieldIntVolatile(sfield, val);
312 }
dvmSetStaticFieldShortVolatile(StaticField * sfield,s2 val)313 INLINE void dvmSetStaticFieldShortVolatile(StaticField* sfield, s2 val) {
314     dvmSetStaticFieldIntVolatile(sfield, val);
315 }
dvmSetStaticFieldCharVolatile(StaticField * sfield,u2 val)316 INLINE void dvmSetStaticFieldCharVolatile(StaticField* sfield, u2 val) {
317     dvmSetStaticFieldIntVolatile(sfield, val);
318 }
dvmSetStaticFieldFloatVolatile(StaticField * sfield,float val)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 }
dvmSetStaticFieldLongVolatile(StaticField * sfield,s8 val)324 INLINE void dvmSetStaticFieldLongVolatile(StaticField* sfield, s8 val) {
325     s8* addr = &sfield->value.j;
326     ANDROID_MEMBAR_FULL();
327     dvmQuasiAtomicSwap64(val, addr);
328 }
dvmSetStaticFieldDoubleVolatile(StaticField * sfield,double val)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 }
dvmSetStaticFieldObjectVolatile(StaticField * sfield,Object * val)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