blob: 1579a56c78e27ad55a1872b15bac8014fed3b7d8 [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
Carl Shapiroae188c62011-04-08 13:11:58 -070023#ifdef __cplusplus
24extern "C" {
25#endif
26
Barry Hayes7ef07552010-06-25 13:36:37 -070027/*
Barry Hayes4ac66a92010-07-09 08:50:19 -070028 * Store a single value in the array, and if the value isn't null,
29 * note in the write barrier.
Barry Hayes7ef07552010-06-25 13:36:37 -070030 */
31INLINE void dvmSetObjectArrayElement(const ArrayObject* obj, int index,
32 Object* val) {
Carl Shapirofc75f3e2010-12-07 11:43:38 -080033 ((Object **)(void *)(obj)->contents)[index] = val;
Barry Hayes4ac66a92010-07-09 08:50:19 -070034 if (val != NULL) {
35 dvmWriteBarrierArray(obj, index, index + 1);
36 }
Barry Hayes7ef07552010-06-25 13:36:37 -070037}
38
39
40/*
41 * Field access functions. Pass in the word offset from Field->byteOffset.
42 *
43 * We guarantee that long/double field data is 64-bit aligned, so it's safe
44 * to access them with ldrd/strd on ARM.
45 *
46 * The VM treats all fields as 32 or 64 bits, so the field set functions
47 * write 32 bits even if the underlying type is smaller.
Barry Hayes4ac66a92010-07-09 08:50:19 -070048 *
49 * Setting Object types to non-null values includes a call to the
50 * write barrier.
Barry Hayes7ef07552010-06-25 13:36:37 -070051 */
52#define BYTE_OFFSET(_ptr, _offset) ((void*) (((u1*)(_ptr)) + (_offset)))
53
54INLINE JValue* dvmFieldPtr(const Object* obj, int offset) {
55 return ((JValue*)BYTE_OFFSET(obj, offset));
56}
57
58INLINE bool dvmGetFieldBoolean(const Object* obj, int offset) {
59 return ((JValue*)BYTE_OFFSET(obj, offset))->z;
60}
61INLINE s1 dvmGetFieldByte(const Object* obj, int offset) {
62 return ((JValue*)BYTE_OFFSET(obj, offset))->b;
63}
64INLINE s2 dvmGetFieldShort(const Object* obj, int offset) {
65 return ((JValue*)BYTE_OFFSET(obj, offset))->s;
66}
67INLINE u2 dvmGetFieldChar(const Object* obj, int offset) {
68 return ((JValue*)BYTE_OFFSET(obj, offset))->c;
69}
70INLINE s4 dvmGetFieldInt(const Object* obj, int offset) {
71 return ((JValue*)BYTE_OFFSET(obj, offset))->i;
72}
73INLINE s8 dvmGetFieldLong(const Object* obj, int offset) {
74 return ((JValue*)BYTE_OFFSET(obj, offset))->j;
75}
76INLINE float dvmGetFieldFloat(const Object* obj, int offset) {
77 return ((JValue*)BYTE_OFFSET(obj, offset))->f;
78}
79INLINE double dvmGetFieldDouble(const Object* obj, int offset) {
80 return ((JValue*)BYTE_OFFSET(obj, offset))->d;
81}
82INLINE Object* dvmGetFieldObject(const Object* obj, int offset) {
Carl Shapirofc75f3e2010-12-07 11:43:38 -080083 return (Object*)((JValue*)BYTE_OFFSET(obj, offset))->l;
Barry Hayes7ef07552010-06-25 13:36:37 -070084}
Andy McFaddenf16cfef2010-08-18 15:51:37 -070085INLINE bool dvmGetFieldBooleanVolatile(const Object* obj, int offset) {
86 s4* ptr = &((JValue*)BYTE_OFFSET(obj, offset))->i;
87 return (bool)android_atomic_acquire_load(ptr);
88}
89INLINE s1 dvmGetFieldByteVolatile(const Object* obj, int offset) {
90 s4* ptr = &((JValue*)BYTE_OFFSET(obj, offset))->i;
91 return (s1)android_atomic_acquire_load(ptr);
92}
93INLINE s2 dvmGetFieldShortVolatile(const Object* obj, int offset) {
94 s4* ptr = &((JValue*)BYTE_OFFSET(obj, offset))->i;
95 return (s2)android_atomic_acquire_load(ptr);
96}
97INLINE u2 dvmGetFieldCharVolatile(const Object* obj, int offset) {
98 s4* ptr = &((JValue*)BYTE_OFFSET(obj, offset))->i;
99 return (u2)android_atomic_acquire_load(ptr);
100}
Barry Hayes7ef07552010-06-25 13:36:37 -0700101INLINE s4 dvmGetFieldIntVolatile(const Object* obj, int offset) {
102 s4* ptr = &((JValue*)BYTE_OFFSET(obj, offset))->i;
103 return android_atomic_acquire_load(ptr);
104}
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700105INLINE float dvmGetFieldFloatVolatile(const Object* obj, int offset) {
106 union { s4 ival; float fval; } alias;
107 s4* ptr = &((JValue*)BYTE_OFFSET(obj, offset))->i;
108 alias.ival = android_atomic_acquire_load(ptr);
109 return alias.fval;
Barry Hayes7ef07552010-06-25 13:36:37 -0700110}
111INLINE s8 dvmGetFieldLongVolatile(const Object* obj, int offset) {
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800112 const s8* addr = (const s8*)BYTE_OFFSET(obj, offset);
Barry Hayes7ef07552010-06-25 13:36:37 -0700113 s8 val = dvmQuasiAtomicRead64(addr);
114 ANDROID_MEMBAR_FULL();
115 return val;
116}
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700117INLINE double dvmGetFieldDoubleVolatile(const Object* obj, int offset) {
118 union { s8 lval; double dval; } alias;
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800119 const s8* addr = (const s8*)BYTE_OFFSET(obj, offset);
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700120 alias.lval = dvmQuasiAtomicRead64(addr);
121 ANDROID_MEMBAR_FULL();
122 return alias.dval;
123}
124INLINE Object* dvmGetFieldObjectVolatile(const Object* obj, int offset) {
125 void** ptr = &((JValue*)BYTE_OFFSET(obj, offset))->l;
126 return (Object*)android_atomic_acquire_load((int32_t*)ptr);
127}
Barry Hayes7ef07552010-06-25 13:36:37 -0700128
129INLINE void dvmSetFieldBoolean(Object* obj, int offset, bool val) {
130 ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
131}
132INLINE void dvmSetFieldByte(Object* obj, int offset, s1 val) {
133 ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
134}
135INLINE void dvmSetFieldShort(Object* obj, int offset, s2 val) {
136 ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
137}
138INLINE void dvmSetFieldChar(Object* obj, int offset, u2 val) {
139 ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
140}
141INLINE void dvmSetFieldInt(Object* obj, int offset, s4 val) {
142 ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
143}
Barry Hayes7ef07552010-06-25 13:36:37 -0700144INLINE void dvmSetFieldFloat(Object* obj, int offset, float val) {
145 ((JValue*)BYTE_OFFSET(obj, offset))->f = val;
146}
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700147INLINE void dvmSetFieldLong(Object* obj, int offset, s8 val) {
148 ((JValue*)BYTE_OFFSET(obj, offset))->j = val;
149}
Barry Hayes7ef07552010-06-25 13:36:37 -0700150INLINE void dvmSetFieldDouble(Object* obj, int offset, double val) {
151 ((JValue*)BYTE_OFFSET(obj, offset))->d = val;
152}
153INLINE void dvmSetFieldObject(Object* obj, int offset, Object* val) {
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800154 JValue* lhs = (JValue*)BYTE_OFFSET(obj, offset);
Barry Hayes7ef07552010-06-25 13:36:37 -0700155 lhs->l = val;
Barry Hayes4ac66a92010-07-09 08:50:19 -0700156 if (val != NULL) {
157 dvmWriteBarrierField(obj, &lhs->l);
158 }
Barry Hayes7ef07552010-06-25 13:36:37 -0700159}
160INLINE void dvmSetFieldIntVolatile(Object* obj, int offset, s4 val) {
161 s4* ptr = &((JValue*)BYTE_OFFSET(obj, offset))->i;
Andy McFaddendcc5a452011-01-13 13:09:26 -0800162 /*
163 * TODO: add an android_atomic_synchronization_store() function and
164 * use it in the 32-bit volatile set handlers. On some platforms we
165 * can use a fast atomic instruction and avoid the barriers.
166 */
167 ANDROID_MEMBAR_STORE();
168 *ptr = val;
169 ANDROID_MEMBAR_FULL();
Barry Hayes7ef07552010-06-25 13:36:37 -0700170}
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700171INLINE void dvmSetFieldBooleanVolatile(Object* obj, int offset, bool val) {
172 dvmSetFieldIntVolatile(obj, offset, val);
173}
174INLINE void dvmSetFieldByteVolatile(Object* obj, int offset, s1 val) {
175 dvmSetFieldIntVolatile(obj, offset, val);
176}
177INLINE void dvmSetFieldShortVolatile(Object* obj, int offset, s2 val) {
178 dvmSetFieldIntVolatile(obj, offset, val);
179}
180INLINE void dvmSetFieldCharVolatile(Object* obj, int offset, u2 val) {
181 dvmSetFieldIntVolatile(obj, offset, val);
182}
183INLINE void dvmSetFieldFloatVolatile(Object* obj, int offset, float val) {
184 union { s4 ival; float fval; } alias;
185 alias.fval = val;
186 dvmSetFieldIntVolatile(obj, offset, alias.ival);
187}
188INLINE void dvmSetFieldLongVolatile(Object* obj, int offset, s8 val) {
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800189 s8* addr = (s8*)BYTE_OFFSET(obj, offset);
Andy McFaddendcc5a452011-01-13 13:09:26 -0800190 ANDROID_MEMBAR_STORE();
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700191 dvmQuasiAtomicSwap64(val, addr);
Andy McFaddendcc5a452011-01-13 13:09:26 -0800192 /* post-store barrier not required due to use of atomic op or mutex */
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700193}
194INLINE void dvmSetFieldDoubleVolatile(Object* obj, int offset, double val) {
195 union { s8 lval; double dval; } alias;
196 alias.dval = val;
197 dvmSetFieldLongVolatile(obj, offset, alias.lval);
198}
Barry Hayes7ef07552010-06-25 13:36:37 -0700199INLINE void dvmSetFieldObjectVolatile(Object* obj, int offset, Object* val) {
200 void** ptr = &((JValue*)BYTE_OFFSET(obj, offset))->l;
Andy McFaddendcc5a452011-01-13 13:09:26 -0800201 ANDROID_MEMBAR_STORE();
202 *ptr = val;
203 ANDROID_MEMBAR_FULL();
Barry Hayes4ac66a92010-07-09 08:50:19 -0700204 if (val != NULL) {
205 dvmWriteBarrierField(obj, ptr);
206 }
Barry Hayes7ef07552010-06-25 13:36:37 -0700207}
Barry Hayes7ef07552010-06-25 13:36:37 -0700208
209/*
210 * Static field access functions.
211 */
212INLINE JValue* dvmStaticFieldPtr(const StaticField* sfield) {
213 return (JValue*)&sfield->value;
214}
215
216INLINE bool dvmGetStaticFieldBoolean(const StaticField* sfield) {
217 return sfield->value.z;
218}
219INLINE s1 dvmGetStaticFieldByte(const StaticField* sfield) {
220 return sfield->value.b;
221}
222INLINE s2 dvmGetStaticFieldShort(const StaticField* sfield) {
223 return sfield->value.s;
224}
225INLINE u2 dvmGetStaticFieldChar(const StaticField* sfield) {
226 return sfield->value.c;
227}
228INLINE s4 dvmGetStaticFieldInt(const StaticField* sfield) {
229 return sfield->value.i;
230}
Barry Hayes7ef07552010-06-25 13:36:37 -0700231INLINE float dvmGetStaticFieldFloat(const StaticField* sfield) {
232 return sfield->value.f;
233}
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700234INLINE s8 dvmGetStaticFieldLong(const StaticField* sfield) {
235 return sfield->value.j;
236}
Barry Hayes7ef07552010-06-25 13:36:37 -0700237INLINE double dvmGetStaticFieldDouble(const StaticField* sfield) {
238 return sfield->value.d;
239}
240INLINE Object* dvmGetStaticFieldObject(const StaticField* sfield) {
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800241 return (Object*)sfield->value.l;
Barry Hayes7ef07552010-06-25 13:36:37 -0700242}
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700243INLINE bool dvmGetStaticFieldBooleanVolatile(const StaticField* sfield) {
244 const s4* ptr = &(sfield->value.i);
245 return (bool)android_atomic_acquire_load((s4*)ptr);
246}
247INLINE s1 dvmGetStaticFieldByteVolatile(const StaticField* sfield) {
248 const s4* ptr = &(sfield->value.i);
249 return (s1)android_atomic_acquire_load((s4*)ptr);
250}
251INLINE s2 dvmGetStaticFieldShortVolatile(const StaticField* sfield) {
252 const s4* ptr = &(sfield->value.i);
253 return (s2)android_atomic_acquire_load((s4*)ptr);
254}
255INLINE u2 dvmGetStaticFieldCharVolatile(const StaticField* sfield) {
256 const s4* ptr = &(sfield->value.i);
257 return (u2)android_atomic_acquire_load((s4*)ptr);
258}
Barry Hayes7ef07552010-06-25 13:36:37 -0700259INLINE s4 dvmGetStaticFieldIntVolatile(const StaticField* sfield) {
260 const s4* ptr = &(sfield->value.i);
261 return android_atomic_acquire_load((s4*)ptr);
262}
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700263INLINE float dvmGetStaticFieldFloatVolatile(const StaticField* sfield) {
264 union { s4 ival; float fval; } alias;
265 const s4* ptr = &(sfield->value.i);
266 alias.ival = android_atomic_acquire_load((s4*)ptr);
267 return alias.fval;
Barry Hayes7ef07552010-06-25 13:36:37 -0700268}
269INLINE s8 dvmGetStaticFieldLongVolatile(const StaticField* sfield) {
270 const s8* addr = &sfield->value.j;
271 s8 val = dvmQuasiAtomicRead64(addr);
272 ANDROID_MEMBAR_FULL();
273 return val;
274}
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700275INLINE double dvmGetStaticFieldDoubleVolatile(const StaticField* sfield) {
276 union { s8 lval; double dval; } alias;
277 const s8* addr = &sfield->value.j;
278 alias.lval = dvmQuasiAtomicRead64(addr);
279 ANDROID_MEMBAR_FULL();
280 return alias.dval;
281}
282INLINE Object* dvmGetStaticFieldObjectVolatile(const StaticField* sfield) {
283 void* const* ptr = &(sfield->value.l);
284 return (Object*)android_atomic_acquire_load((int32_t*)ptr);
285}
Barry Hayes7ef07552010-06-25 13:36:37 -0700286
287INLINE void dvmSetStaticFieldBoolean(StaticField* sfield, bool val) {
288 sfield->value.i = val;
289}
290INLINE void dvmSetStaticFieldByte(StaticField* sfield, s1 val) {
291 sfield->value.i = val;
292}
293INLINE void dvmSetStaticFieldShort(StaticField* sfield, s2 val) {
294 sfield->value.i = val;
295}
296INLINE void dvmSetStaticFieldChar(StaticField* sfield, u2 val) {
297 sfield->value.i = val;
298}
299INLINE void dvmSetStaticFieldInt(StaticField* sfield, s4 val) {
300 sfield->value.i = val;
301}
Barry Hayes7ef07552010-06-25 13:36:37 -0700302INLINE void dvmSetStaticFieldFloat(StaticField* sfield, float val) {
303 sfield->value.f = val;
304}
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700305INLINE void dvmSetStaticFieldLong(StaticField* sfield, s8 val) {
306 sfield->value.j = val;
307}
Barry Hayes7ef07552010-06-25 13:36:37 -0700308INLINE void dvmSetStaticFieldDouble(StaticField* sfield, double val) {
309 sfield->value.d = val;
310}
311INLINE void dvmSetStaticFieldObject(StaticField* sfield, Object* val) {
312 sfield->value.l = val;
Barry Hayes4ac66a92010-07-09 08:50:19 -0700313 if (val != NULL) {
314 dvmWriteBarrierField((Object *)sfield->field.clazz, &sfield->value.l);
315 }
Barry Hayes7ef07552010-06-25 13:36:37 -0700316}
317INLINE void dvmSetStaticFieldIntVolatile(StaticField* sfield, s4 val) {
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700318 s4* ptr = &sfield->value.i;
Andy McFaddendcc5a452011-01-13 13:09:26 -0800319 ANDROID_MEMBAR_STORE();
320 *ptr = val;
321 ANDROID_MEMBAR_FULL();
Barry Hayes7ef07552010-06-25 13:36:37 -0700322}
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700323INLINE void dvmSetStaticFieldBooleanVolatile(StaticField* sfield, bool val) {
324 dvmSetStaticFieldIntVolatile(sfield, val);
325}
326INLINE void dvmSetStaticFieldByteVolatile(StaticField* sfield, s1 val) {
327 dvmSetStaticFieldIntVolatile(sfield, val);
328}
329INLINE void dvmSetStaticFieldShortVolatile(StaticField* sfield, s2 val) {
330 dvmSetStaticFieldIntVolatile(sfield, val);
331}
332INLINE void dvmSetStaticFieldCharVolatile(StaticField* sfield, u2 val) {
333 dvmSetStaticFieldIntVolatile(sfield, val);
334}
335INLINE void dvmSetStaticFieldFloatVolatile(StaticField* sfield, float val) {
336 union { s4 ival; float fval; } alias;
337 alias.fval = val;
338 dvmSetStaticFieldIntVolatile(sfield, alias.ival);
339}
340INLINE void dvmSetStaticFieldLongVolatile(StaticField* sfield, s8 val) {
341 s8* addr = &sfield->value.j;
Andy McFaddendcc5a452011-01-13 13:09:26 -0800342 ANDROID_MEMBAR_STORE();
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700343 dvmQuasiAtomicSwap64(val, addr);
Andy McFaddendcc5a452011-01-13 13:09:26 -0800344 /* post-store barrier not required due to use of atomic op or mutex */
Andy McFaddenf16cfef2010-08-18 15:51:37 -0700345}
346INLINE void dvmSetStaticFieldDoubleVolatile(StaticField* sfield, double val) {
347 union { s8 lval; double dval; } alias;
348 alias.dval = val;
349 dvmSetStaticFieldLongVolatile(sfield, alias.lval);
350}
Barry Hayes7ef07552010-06-25 13:36:37 -0700351INLINE void dvmSetStaticFieldObjectVolatile(StaticField* sfield, Object* val) {
352 void** ptr = &(sfield->value.l);
Andy McFaddendcc5a452011-01-13 13:09:26 -0800353 ANDROID_MEMBAR_STORE();
354 *ptr = val;
355 ANDROID_MEMBAR_FULL();
Barry Hayes4ac66a92010-07-09 08:50:19 -0700356 if (val != NULL) {
357 dvmWriteBarrierField((Object *)sfield->field.clazz, &sfield->value.l);
358 }
Barry Hayes7ef07552010-06-25 13:36:37 -0700359}
Barry Hayes7ef07552010-06-25 13:36:37 -0700360
Carl Shapiroae188c62011-04-08 13:11:58 -0700361#ifdef __cplusplus
362}
363#endif
364
Barry Hayes0dfa7bf2010-06-25 13:50:29 -0700365#endif /*_DALVIK_OO_OBJECTINLINES*/