ObjectInlines.h revision fc75f3ed87b55d625b6054e18645da5cbdba31c6
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 */
27INLINE 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
50INLINE JValue* dvmFieldPtr(const Object* obj, int offset) {
51    return ((JValue*)BYTE_OFFSET(obj, offset));
52}
53
54INLINE bool dvmGetFieldBoolean(const Object* obj, int offset) {
55    return ((JValue*)BYTE_OFFSET(obj, offset))->z;
56}
57INLINE s1 dvmGetFieldByte(const Object* obj, int offset) {
58    return ((JValue*)BYTE_OFFSET(obj, offset))->b;
59}
60INLINE s2 dvmGetFieldShort(const Object* obj, int offset) {
61    return ((JValue*)BYTE_OFFSET(obj, offset))->s;
62}
63INLINE u2 dvmGetFieldChar(const Object* obj, int offset) {
64    return ((JValue*)BYTE_OFFSET(obj, offset))->c;
65}
66INLINE s4 dvmGetFieldInt(const Object* obj, int offset) {
67    return ((JValue*)BYTE_OFFSET(obj, offset))->i;
68}
69INLINE s8 dvmGetFieldLong(const Object* obj, int offset) {
70    return ((JValue*)BYTE_OFFSET(obj, offset))->j;
71}
72INLINE float dvmGetFieldFloat(const Object* obj, int offset) {
73    return ((JValue*)BYTE_OFFSET(obj, offset))->f;
74}
75INLINE double dvmGetFieldDouble(const Object* obj, int offset) {
76    return ((JValue*)BYTE_OFFSET(obj, offset))->d;
77}
78INLINE Object* dvmGetFieldObject(const Object* obj, int offset) {
79    return (Object*)((JValue*)BYTE_OFFSET(obj, offset))->l;
80}
81INLINE 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}
85INLINE 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}
89INLINE 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}
93INLINE 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}
97INLINE s4 dvmGetFieldIntVolatile(const Object* obj, int offset) {
98    s4* ptr = &((JValue*)BYTE_OFFSET(obj, offset))->i;
99    return android_atomic_acquire_load(ptr);
100}
101INLINE 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}
107INLINE 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}
113INLINE 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}
120INLINE 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
125INLINE void dvmSetFieldBoolean(Object* obj, int offset, bool val) {
126    ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
127}
128INLINE void dvmSetFieldByte(Object* obj, int offset, s1 val) {
129    ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
130}
131INLINE void dvmSetFieldShort(Object* obj, int offset, s2 val) {
132    ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
133}
134INLINE void dvmSetFieldChar(Object* obj, int offset, u2 val) {
135    ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
136}
137INLINE void dvmSetFieldInt(Object* obj, int offset, s4 val) {
138    ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
139}
140INLINE void dvmSetFieldFloat(Object* obj, int offset, float val) {
141    ((JValue*)BYTE_OFFSET(obj, offset))->f = val;
142}
143INLINE void dvmSetFieldLong(Object* obj, int offset, s8 val) {
144    ((JValue*)BYTE_OFFSET(obj, offset))->j = val;
145}
146INLINE void dvmSetFieldDouble(Object* obj, int offset, double val) {
147    ((JValue*)BYTE_OFFSET(obj, offset))->d = val;
148}
149INLINE 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}
156INLINE 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}
160INLINE void dvmSetFieldBooleanVolatile(Object* obj, int offset, bool val) {
161    dvmSetFieldIntVolatile(obj, offset, val);
162}
163INLINE void dvmSetFieldByteVolatile(Object* obj, int offset, s1 val) {
164    dvmSetFieldIntVolatile(obj, offset, val);
165}
166INLINE void dvmSetFieldShortVolatile(Object* obj, int offset, s2 val) {
167    dvmSetFieldIntVolatile(obj, offset, val);
168}
169INLINE void dvmSetFieldCharVolatile(Object* obj, int offset, u2 val) {
170    dvmSetFieldIntVolatile(obj, offset, val);
171}
172INLINE 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}
177INLINE void dvmSetFieldLongVolatile(Object* obj, int offset, s8 val) {
178    s8* addr = (s8*)BYTE_OFFSET(obj, offset);
179    ANDROID_MEMBAR_FULL();
180    dvmQuasiAtomicSwap64(val, addr);
181}
182INLINE 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}
187INLINE 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 */
198INLINE JValue* dvmStaticFieldPtr(const StaticField* sfield) {
199    return (JValue*)&sfield->value;
200}
201
202INLINE bool dvmGetStaticFieldBoolean(const StaticField* sfield) {
203    return sfield->value.z;
204}
205INLINE s1 dvmGetStaticFieldByte(const StaticField* sfield) {
206    return sfield->value.b;
207}
208INLINE s2 dvmGetStaticFieldShort(const StaticField* sfield) {
209    return sfield->value.s;
210}
211INLINE u2 dvmGetStaticFieldChar(const StaticField* sfield) {
212    return sfield->value.c;
213}
214INLINE s4 dvmGetStaticFieldInt(const StaticField* sfield) {
215    return sfield->value.i;
216}
217INLINE float dvmGetStaticFieldFloat(const StaticField* sfield) {
218    return sfield->value.f;
219}
220INLINE s8 dvmGetStaticFieldLong(const StaticField* sfield) {
221    return sfield->value.j;
222}
223INLINE double dvmGetStaticFieldDouble(const StaticField* sfield) {
224    return sfield->value.d;
225}
226INLINE Object* dvmGetStaticFieldObject(const StaticField* sfield) {
227    return (Object*)sfield->value.l;
228}
229INLINE bool dvmGetStaticFieldBooleanVolatile(const StaticField* sfield) {
230    const s4* ptr = &(sfield->value.i);
231    return (bool)android_atomic_acquire_load((s4*)ptr);
232}
233INLINE s1 dvmGetStaticFieldByteVolatile(const StaticField* sfield) {
234    const s4* ptr = &(sfield->value.i);
235    return (s1)android_atomic_acquire_load((s4*)ptr);
236}
237INLINE s2 dvmGetStaticFieldShortVolatile(const StaticField* sfield) {
238    const s4* ptr = &(sfield->value.i);
239    return (s2)android_atomic_acquire_load((s4*)ptr);
240}
241INLINE u2 dvmGetStaticFieldCharVolatile(const StaticField* sfield) {
242    const s4* ptr = &(sfield->value.i);
243    return (u2)android_atomic_acquire_load((s4*)ptr);
244}
245INLINE s4 dvmGetStaticFieldIntVolatile(const StaticField* sfield) {
246    const s4* ptr = &(sfield->value.i);
247    return android_atomic_acquire_load((s4*)ptr);
248}
249INLINE 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}
255INLINE 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}
261INLINE 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}
268INLINE Object* dvmGetStaticFieldObjectVolatile(const StaticField* sfield) {
269    void* const* ptr = &(sfield->value.l);
270    return (Object*)android_atomic_acquire_load((int32_t*)ptr);
271}
272
273INLINE void dvmSetStaticFieldBoolean(StaticField* sfield, bool val) {
274    sfield->value.i = val;
275}
276INLINE void dvmSetStaticFieldByte(StaticField* sfield, s1 val) {
277    sfield->value.i = val;
278}
279INLINE void dvmSetStaticFieldShort(StaticField* sfield, s2 val) {
280    sfield->value.i = val;
281}
282INLINE void dvmSetStaticFieldChar(StaticField* sfield, u2 val) {
283    sfield->value.i = val;
284}
285INLINE void dvmSetStaticFieldInt(StaticField* sfield, s4 val) {
286    sfield->value.i = val;
287}
288INLINE void dvmSetStaticFieldFloat(StaticField* sfield, float val) {
289    sfield->value.f = val;
290}
291INLINE void dvmSetStaticFieldLong(StaticField* sfield, s8 val) {
292    sfield->value.j = val;
293}
294INLINE void dvmSetStaticFieldDouble(StaticField* sfield, double val) {
295    sfield->value.d = val;
296}
297INLINE 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}
303INLINE void dvmSetStaticFieldIntVolatile(StaticField* sfield, s4 val) {
304    s4* ptr = &sfield->value.i;
305    android_atomic_release_store(val, ptr);
306}
307INLINE void dvmSetStaticFieldBooleanVolatile(StaticField* sfield, bool val) {
308    dvmSetStaticFieldIntVolatile(sfield, val);
309}
310INLINE void dvmSetStaticFieldByteVolatile(StaticField* sfield, s1 val) {
311    dvmSetStaticFieldIntVolatile(sfield, val);
312}
313INLINE void dvmSetStaticFieldShortVolatile(StaticField* sfield, s2 val) {
314    dvmSetStaticFieldIntVolatile(sfield, val);
315}
316INLINE void dvmSetStaticFieldCharVolatile(StaticField* sfield, u2 val) {
317    dvmSetStaticFieldIntVolatile(sfield, val);
318}
319INLINE void dvmSetStaticFieldFloatVolatile(StaticField* sfield, float val) {
320    union { s4 ival; float fval; } alias;
321    alias.fval = val;
322    dvmSetStaticFieldIntVolatile(sfield, alias.ival);
323}
324INLINE void dvmSetStaticFieldLongVolatile(StaticField* sfield, s8 val) {
325    s8* addr = &sfield->value.j;
326    ANDROID_MEMBAR_FULL();
327    dvmQuasiAtomicSwap64(val, addr);
328}
329INLINE void dvmSetStaticFieldDoubleVolatile(StaticField* sfield, double val) {
330    union { s8 lval; double dval; } alias;
331    alias.dval = val;
332    dvmSetStaticFieldLongVolatile(sfield, alias.lval);
333}
334INLINE 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