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