blob: ef01834c4aafeee7f9651665c7e4f96da3c6f627 [file] [log] [blame]
Barry Hayes7ef07552010-06-25 13:36:37 -07001/*
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 */
Barry Hayes0dfa7bf2010-06-25 13:50:29 -070020#ifndef _DALVIK_OO_OBJECTINLINES
21#define _DALVIK_OO_OBJECTINLINES
Barry Hayes7ef07552010-06-25 13:36:37 -070022
23/*
Barry Hayes4ac66a92010-07-09 08:50:19 -070024 * Store a single value in the array, and if the value isn't null,
25 * note in the write barrier.
Barry Hayes7ef07552010-06-25 13:36:37 -070026 */
27INLINE void dvmSetObjectArrayElement(const ArrayObject* obj, int index,
28 Object* val) {
Carl Shapirofc75f3e2010-12-07 11:43:38 -080029 ((Object **)(void *)(obj)->contents)[index] = val;
Barry Hayes4ac66a92010-07-09 08:50:19 -070030 if (val != NULL) {
31 dvmWriteBarrierArray(obj, index, index + 1);
32 }
Barry Hayes7ef07552010-06-25 13:36:37 -070033}
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.
Barry Hayes4ac66a92010-07-09 08:50:19 -070044 *
45 * Setting Object types to non-null values includes a call to the
46 * write barrier.
Barry Hayes7ef07552010-06-25 13:36:37 -070047 */
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) {
Carl Shapirofc75f3e2010-12-07 11:43:38 -080079 return (Object*)((JValue*)BYTE_OFFSET(obj, offset))->l;
Barry Hayes7ef07552010-06-25 13:36:37 -070080}
Andy McFaddenf16cfef2010-08-18 15:51:37 -070081INLINE 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}
Barry Hayes7ef07552010-06-25 13:36:37 -070097INLINE s4 dvmGetFieldIntVolatile(const Object* obj, int offset) {
98 s4* ptr = &((JValue*)BYTE_OFFSET(obj, offset))->i;
99 return android_atomic_acquire_load(ptr);
100}
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700101INLINE 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;
Barry Hayes7ef07552010-06-25 13:36:37 -0700106}
107INLINE s8 dvmGetFieldLongVolatile(const Object* obj, int offset) {
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800108 const s8* addr = (const s8*)BYTE_OFFSET(obj, offset);
Barry Hayes7ef07552010-06-25 13:36:37 -0700109 s8 val = dvmQuasiAtomicRead64(addr);
110 ANDROID_MEMBAR_FULL();
111 return val;
112}
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700113INLINE double dvmGetFieldDoubleVolatile(const Object* obj, int offset) {
114 union { s8 lval; double dval; } alias;
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800115 const s8* addr = (const s8*)BYTE_OFFSET(obj, offset);
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700116 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}
Barry Hayes7ef07552010-06-25 13:36:37 -0700124
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}
Barry Hayes7ef07552010-06-25 13:36:37 -0700140INLINE void dvmSetFieldFloat(Object* obj, int offset, float val) {
141 ((JValue*)BYTE_OFFSET(obj, offset))->f = val;
142}
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700143INLINE void dvmSetFieldLong(Object* obj, int offset, s8 val) {
144 ((JValue*)BYTE_OFFSET(obj, offset))->j = val;
145}
Barry Hayes7ef07552010-06-25 13:36:37 -0700146INLINE 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) {
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800150 JValue* lhs = (JValue*)BYTE_OFFSET(obj, offset);
Barry Hayes7ef07552010-06-25 13:36:37 -0700151 lhs->l = val;
Barry Hayes4ac66a92010-07-09 08:50:19 -0700152 if (val != NULL) {
153 dvmWriteBarrierField(obj, &lhs->l);
154 }
Barry Hayes7ef07552010-06-25 13:36:37 -0700155}
156INLINE void dvmSetFieldIntVolatile(Object* obj, int offset, s4 val) {
157 s4* ptr = &((JValue*)BYTE_OFFSET(obj, offset))->i;
Andy McFaddendcc5a452011-01-13 13:09:26 -0800158 /*
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();
Barry Hayes7ef07552010-06-25 13:36:37 -0700166}
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700167INLINE void dvmSetFieldBooleanVolatile(Object* obj, int offset, bool val) {
168 dvmSetFieldIntVolatile(obj, offset, val);
169}
170INLINE void dvmSetFieldByteVolatile(Object* obj, int offset, s1 val) {
171 dvmSetFieldIntVolatile(obj, offset, val);
172}
173INLINE void dvmSetFieldShortVolatile(Object* obj, int offset, s2 val) {
174 dvmSetFieldIntVolatile(obj, offset, val);
175}
176INLINE void dvmSetFieldCharVolatile(Object* obj, int offset, u2 val) {
177 dvmSetFieldIntVolatile(obj, offset, val);
178}
179INLINE 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}
184INLINE void dvmSetFieldLongVolatile(Object* obj, int offset, s8 val) {
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800185 s8* addr = (s8*)BYTE_OFFSET(obj, offset);
Andy McFaddendcc5a452011-01-13 13:09:26 -0800186 ANDROID_MEMBAR_STORE();
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700187 dvmQuasiAtomicSwap64(val, addr);
Andy McFaddendcc5a452011-01-13 13:09:26 -0800188 /* post-store barrier not required due to use of atomic op or mutex */
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700189}
190INLINE void dvmSetFieldDoubleVolatile(Object* obj, int offset, double val) {
191 union { s8 lval; double dval; } alias;
192 alias.dval = val;
193 dvmSetFieldLongVolatile(obj, offset, alias.lval);
194}
Barry Hayes7ef07552010-06-25 13:36:37 -0700195INLINE void dvmSetFieldObjectVolatile(Object* obj, int offset, Object* val) {
196 void** ptr = &((JValue*)BYTE_OFFSET(obj, offset))->l;
Andy McFaddendcc5a452011-01-13 13:09:26 -0800197 ANDROID_MEMBAR_STORE();
198 *ptr = val;
199 ANDROID_MEMBAR_FULL();
Barry Hayes4ac66a92010-07-09 08:50:19 -0700200 if (val != NULL) {
201 dvmWriteBarrierField(obj, ptr);
202 }
Barry Hayes7ef07552010-06-25 13:36:37 -0700203}
Barry Hayes7ef07552010-06-25 13:36:37 -0700204
205/*
206 * Static field access functions.
207 */
208INLINE JValue* dvmStaticFieldPtr(const StaticField* sfield) {
209 return (JValue*)&sfield->value;
210}
211
212INLINE bool dvmGetStaticFieldBoolean(const StaticField* sfield) {
213 return sfield->value.z;
214}
215INLINE s1 dvmGetStaticFieldByte(const StaticField* sfield) {
216 return sfield->value.b;
217}
218INLINE s2 dvmGetStaticFieldShort(const StaticField* sfield) {
219 return sfield->value.s;
220}
221INLINE u2 dvmGetStaticFieldChar(const StaticField* sfield) {
222 return sfield->value.c;
223}
224INLINE s4 dvmGetStaticFieldInt(const StaticField* sfield) {
225 return sfield->value.i;
226}
Barry Hayes7ef07552010-06-25 13:36:37 -0700227INLINE float dvmGetStaticFieldFloat(const StaticField* sfield) {
228 return sfield->value.f;
229}
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700230INLINE s8 dvmGetStaticFieldLong(const StaticField* sfield) {
231 return sfield->value.j;
232}
Barry Hayes7ef07552010-06-25 13:36:37 -0700233INLINE double dvmGetStaticFieldDouble(const StaticField* sfield) {
234 return sfield->value.d;
235}
236INLINE Object* dvmGetStaticFieldObject(const StaticField* sfield) {
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800237 return (Object*)sfield->value.l;
Barry Hayes7ef07552010-06-25 13:36:37 -0700238}
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700239INLINE bool dvmGetStaticFieldBooleanVolatile(const StaticField* sfield) {
240 const s4* ptr = &(sfield->value.i);
241 return (bool)android_atomic_acquire_load((s4*)ptr);
242}
243INLINE s1 dvmGetStaticFieldByteVolatile(const StaticField* sfield) {
244 const s4* ptr = &(sfield->value.i);
245 return (s1)android_atomic_acquire_load((s4*)ptr);
246}
247INLINE s2 dvmGetStaticFieldShortVolatile(const StaticField* sfield) {
248 const s4* ptr = &(sfield->value.i);
249 return (s2)android_atomic_acquire_load((s4*)ptr);
250}
251INLINE u2 dvmGetStaticFieldCharVolatile(const StaticField* sfield) {
252 const s4* ptr = &(sfield->value.i);
253 return (u2)android_atomic_acquire_load((s4*)ptr);
254}
Barry Hayes7ef07552010-06-25 13:36:37 -0700255INLINE s4 dvmGetStaticFieldIntVolatile(const StaticField* sfield) {
256 const s4* ptr = &(sfield->value.i);
257 return android_atomic_acquire_load((s4*)ptr);
258}
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700259INLINE float dvmGetStaticFieldFloatVolatile(const StaticField* sfield) {
260 union { s4 ival; float fval; } alias;
261 const s4* ptr = &(sfield->value.i);
262 alias.ival = android_atomic_acquire_load((s4*)ptr);
263 return alias.fval;
Barry Hayes7ef07552010-06-25 13:36:37 -0700264}
265INLINE s8 dvmGetStaticFieldLongVolatile(const StaticField* sfield) {
266 const s8* addr = &sfield->value.j;
267 s8 val = dvmQuasiAtomicRead64(addr);
268 ANDROID_MEMBAR_FULL();
269 return val;
270}
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700271INLINE double dvmGetStaticFieldDoubleVolatile(const StaticField* sfield) {
272 union { s8 lval; double dval; } alias;
273 const s8* addr = &sfield->value.j;
274 alias.lval = dvmQuasiAtomicRead64(addr);
275 ANDROID_MEMBAR_FULL();
276 return alias.dval;
277}
278INLINE Object* dvmGetStaticFieldObjectVolatile(const StaticField* sfield) {
279 void* const* ptr = &(sfield->value.l);
280 return (Object*)android_atomic_acquire_load((int32_t*)ptr);
281}
Barry Hayes7ef07552010-06-25 13:36:37 -0700282
283INLINE void dvmSetStaticFieldBoolean(StaticField* sfield, bool val) {
284 sfield->value.i = val;
285}
286INLINE void dvmSetStaticFieldByte(StaticField* sfield, s1 val) {
287 sfield->value.i = val;
288}
289INLINE void dvmSetStaticFieldShort(StaticField* sfield, s2 val) {
290 sfield->value.i = val;
291}
292INLINE void dvmSetStaticFieldChar(StaticField* sfield, u2 val) {
293 sfield->value.i = val;
294}
295INLINE void dvmSetStaticFieldInt(StaticField* sfield, s4 val) {
296 sfield->value.i = val;
297}
Barry Hayes7ef07552010-06-25 13:36:37 -0700298INLINE void dvmSetStaticFieldFloat(StaticField* sfield, float val) {
299 sfield->value.f = val;
300}
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700301INLINE void dvmSetStaticFieldLong(StaticField* sfield, s8 val) {
302 sfield->value.j = val;
303}
Barry Hayes7ef07552010-06-25 13:36:37 -0700304INLINE void dvmSetStaticFieldDouble(StaticField* sfield, double val) {
305 sfield->value.d = val;
306}
307INLINE void dvmSetStaticFieldObject(StaticField* sfield, Object* val) {
308 sfield->value.l = val;
Barry Hayes4ac66a92010-07-09 08:50:19 -0700309 if (val != NULL) {
310 dvmWriteBarrierField((Object *)sfield->field.clazz, &sfield->value.l);
311 }
Barry Hayes7ef07552010-06-25 13:36:37 -0700312}
313INLINE void dvmSetStaticFieldIntVolatile(StaticField* sfield, s4 val) {
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700314 s4* ptr = &sfield->value.i;
Andy McFaddendcc5a452011-01-13 13:09:26 -0800315 ANDROID_MEMBAR_STORE();
316 *ptr = val;
317 ANDROID_MEMBAR_FULL();
Barry Hayes7ef07552010-06-25 13:36:37 -0700318}
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700319INLINE void dvmSetStaticFieldBooleanVolatile(StaticField* sfield, bool val) {
320 dvmSetStaticFieldIntVolatile(sfield, val);
321}
322INLINE void dvmSetStaticFieldByteVolatile(StaticField* sfield, s1 val) {
323 dvmSetStaticFieldIntVolatile(sfield, val);
324}
325INLINE void dvmSetStaticFieldShortVolatile(StaticField* sfield, s2 val) {
326 dvmSetStaticFieldIntVolatile(sfield, val);
327}
328INLINE void dvmSetStaticFieldCharVolatile(StaticField* sfield, u2 val) {
329 dvmSetStaticFieldIntVolatile(sfield, val);
330}
331INLINE void dvmSetStaticFieldFloatVolatile(StaticField* sfield, float val) {
332 union { s4 ival; float fval; } alias;
333 alias.fval = val;
334 dvmSetStaticFieldIntVolatile(sfield, alias.ival);
335}
336INLINE void dvmSetStaticFieldLongVolatile(StaticField* sfield, s8 val) {
337 s8* addr = &sfield->value.j;
Andy McFaddendcc5a452011-01-13 13:09:26 -0800338 ANDROID_MEMBAR_STORE();
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700339 dvmQuasiAtomicSwap64(val, addr);
Andy McFaddendcc5a452011-01-13 13:09:26 -0800340 /* post-store barrier not required due to use of atomic op or mutex */
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700341}
342INLINE void dvmSetStaticFieldDoubleVolatile(StaticField* sfield, double val) {
343 union { s8 lval; double dval; } alias;
344 alias.dval = val;
345 dvmSetStaticFieldLongVolatile(sfield, alias.lval);
346}
Barry Hayes7ef07552010-06-25 13:36:37 -0700347INLINE void dvmSetStaticFieldObjectVolatile(StaticField* sfield, Object* val) {
348 void** ptr = &(sfield->value.l);
Andy McFaddendcc5a452011-01-13 13:09:26 -0800349 ANDROID_MEMBAR_STORE();
350 *ptr = val;
351 ANDROID_MEMBAR_FULL();
Barry Hayes4ac66a92010-07-09 08:50:19 -0700352 if (val != NULL) {
353 dvmWriteBarrierField((Object *)sfield->field.clazz, &sfield->value.l);
354 }
Barry Hayes7ef07552010-06-25 13:36:37 -0700355}
Barry Hayes7ef07552010-06-25 13:36:37 -0700356
Barry Hayes0dfa7bf2010-06-25 13:50:29 -0700357#endif /*_DALVIK_OO_OBJECTINLINES*/