1 /*
2 * Copyright (C) 2012 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 #include <stdint.h>
18
19 #include "art_field-inl.h"
20 #include "art_method-inl.h"
21 #include "base/callee_save_type.h"
22 #include "callee_save_frame.h"
23 #include "dex/dex_file-inl.h"
24 #include "entrypoints/entrypoint_utils-inl.h"
25 #include "gc_root-inl.h"
26 #include "mirror/class-inl.h"
27 #include "mirror/object_reference.h"
28
29 namespace art {
30
31 // Helper function to do a null check after trying to resolve the field. Not for statics since obj
32 // does not exist there. There is a suspend check, object is a double pointer to update the value
33 // in the caller in case it moves.
34 template<FindFieldType type, bool kAccessCheck>
FindInstanceField(uint32_t field_idx,ArtMethod * referrer,Thread * self,size_t size,mirror::Object ** obj)35 ALWAYS_INLINE static inline ArtField* FindInstanceField(uint32_t field_idx,
36 ArtMethod* referrer,
37 Thread* self,
38 size_t size,
39 mirror::Object** obj)
40 REQUIRES(!Roles::uninterruptible_)
41 REQUIRES_SHARED(Locks::mutator_lock_) {
42 StackHandleScope<1> hs(self);
43 HandleWrapper<mirror::Object> h(hs.NewHandleWrapper(obj));
44 ArtField* field = FindFieldFromCode<type, kAccessCheck>(field_idx, referrer, self, size);
45 if (LIKELY(field != nullptr) && UNLIKELY(h == nullptr)) {
46 ThrowNullPointerExceptionForFieldAccess(field, (type & FindFieldFlags::ReadBit) != 0);
47 return nullptr;
48 }
49 return field;
50 }
51
GetReferrer(Thread * self)52 static ArtMethod* GetReferrer(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) {
53 if (kIsDebugBuild) {
54 // stub_test doesn't call this code with a proper frame, so get the outer, and if
55 // it does not have compiled code return it.
56 ArtMethod* outer = GetCalleeSaveOuterMethod(self, CalleeSaveType::kSaveRefsOnly);
57 if (outer->GetEntryPointFromQuickCompiledCode() == nullptr) {
58 return outer;
59 }
60 }
61 return GetCalleeSaveMethodCallerAndOuterMethod(self, CalleeSaveType::kSaveRefsOnly).caller;
62 }
63
64 // Macro used to define this set of functions:
65 //
66 // art{Get,Set}<Kind>{Static,Instance}FromCode
67 // art{Get,Set}<Kind>{Static,Instance}FromCompiledCode
68 //
69 #define ART_GET_FIELD_FROM_CODE(Kind, PrimitiveType, RetType, SetType, \
70 PrimitiveOrObject, IsObject, Ptr) \
71 extern "C" RetType artGet ## Kind ## StaticFromCode(uint32_t field_idx, \
72 ArtMethod* referrer, \
73 Thread* self) \
74 REQUIRES_SHARED(Locks::mutator_lock_) { \
75 ScopedQuickEntrypointChecks sqec(self); \
76 ArtField* field = FindFieldFast( \
77 field_idx, referrer, Static ## PrimitiveOrObject ## Read, \
78 sizeof(PrimitiveType)); \
79 if (LIKELY(field != nullptr)) { \
80 return field->Get ## Kind (field->GetDeclaringClass())Ptr; /* NOLINT */ \
81 } \
82 field = FindFieldFromCode<Static ## PrimitiveOrObject ## Read, true>( \
83 field_idx, referrer, self, sizeof(PrimitiveType)); \
84 if (LIKELY(field != nullptr)) { \
85 return field->Get ## Kind (field->GetDeclaringClass())Ptr; /* NOLINT */ \
86 } \
87 /* Will throw exception by checking with Thread::Current. */ \
88 return 0; \
89 } \
90 \
91 extern "C" RetType artGet ## Kind ## InstanceFromCode(uint32_t field_idx, \
92 mirror::Object* obj, \
93 ArtMethod* referrer, \
94 Thread* self) \
95 REQUIRES_SHARED(Locks::mutator_lock_) { \
96 ScopedQuickEntrypointChecks sqec(self); \
97 ArtField* field = FindFieldFast( \
98 field_idx, referrer, Instance ## PrimitiveOrObject ## Read, \
99 sizeof(PrimitiveType)); \
100 if (LIKELY(field != nullptr) && obj != nullptr) { \
101 return field->Get ## Kind (obj)Ptr; /* NOLINT */ \
102 } \
103 field = FindInstanceField<Instance ## PrimitiveOrObject ## Read, true>( \
104 field_idx, referrer, self, sizeof(PrimitiveType), &obj); \
105 if (LIKELY(field != nullptr)) { \
106 return field->Get ## Kind (obj)Ptr; /* NOLINT */ \
107 } \
108 /* Will throw exception by checking with Thread::Current. */ \
109 return 0; \
110 } \
111 \
112 extern "C" int artSet ## Kind ## StaticFromCode(uint32_t field_idx, \
113 SetType new_value, \
114 ArtMethod* referrer, \
115 Thread* self) \
116 REQUIRES_SHARED(Locks::mutator_lock_) { \
117 ScopedQuickEntrypointChecks sqec(self); \
118 ArtField* field = FindFieldFast( \
119 field_idx, referrer, Static ## PrimitiveOrObject ## Write, \
120 sizeof(PrimitiveType)); \
121 if (LIKELY(field != nullptr)) { \
122 field->Set ## Kind <false>(field->GetDeclaringClass(), new_value); \
123 return 0; \
124 } \
125 if (IsObject) { \
126 StackHandleScope<1> hs(self); \
127 HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper( \
128 reinterpret_cast<mirror::Object**>(&new_value))); \
129 field = FindFieldFromCode<Static ## PrimitiveOrObject ## Write, true>( \
130 field_idx, referrer, self, sizeof(PrimitiveType)); \
131 } else { \
132 field = FindFieldFromCode<Static ## PrimitiveOrObject ## Write, true>( \
133 field_idx, referrer, self, sizeof(PrimitiveType)); \
134 } \
135 if (LIKELY(field != nullptr)) { \
136 field->Set ## Kind <false>(field->GetDeclaringClass(), new_value); \
137 return 0; \
138 } \
139 return -1; \
140 } \
141 \
142 extern "C" int artSet ## Kind ## InstanceFromCode(uint32_t field_idx, \
143 mirror::Object* obj, \
144 SetType new_value, \
145 ArtMethod* referrer, \
146 Thread* self) \
147 REQUIRES_SHARED(Locks::mutator_lock_) { \
148 ScopedQuickEntrypointChecks sqec(self); \
149 ArtField* field = FindFieldFast( \
150 field_idx, referrer, Instance ## PrimitiveOrObject ## Write, \
151 sizeof(PrimitiveType)); \
152 if (LIKELY(field != nullptr && obj != nullptr)) { \
153 field->Set ## Kind <false>(obj, new_value); \
154 return 0; \
155 } \
156 if (IsObject) { \
157 StackHandleScope<1> hs(self); \
158 HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper( \
159 reinterpret_cast<mirror::Object**>(&new_value))); \
160 field = FindInstanceField<Instance ## PrimitiveOrObject ## Write, true>( \
161 field_idx, \
162 referrer, \
163 self, \
164 sizeof(PrimitiveType), \
165 &obj); \
166 } else { \
167 field = FindInstanceField<Instance ## PrimitiveOrObject ## Write, true>( \
168 field_idx, \
169 referrer, \
170 self, \
171 sizeof(PrimitiveType), \
172 &obj); \
173 } \
174 if (LIKELY(field != nullptr)) { \
175 field->Set ## Kind<false>(obj, new_value); \
176 return 0; \
177 } \
178 return -1; \
179 } \
180 \
181 extern "C" RetType artGet ## Kind ## StaticFromCompiledCode( \
182 uint32_t field_idx, \
183 Thread* self) \
184 REQUIRES_SHARED(Locks::mutator_lock_) { \
185 return artGet ## Kind ## StaticFromCode( \
186 field_idx, GetReferrer(self), self); \
187 } \
188 \
189 extern "C" RetType artGet ## Kind ## InstanceFromCompiledCode( \
190 uint32_t field_idx, \
191 mirror::Object* obj, \
192 Thread* self) \
193 REQUIRES_SHARED(Locks::mutator_lock_) { \
194 return artGet ## Kind ## InstanceFromCode( \
195 field_idx, obj, GetReferrer(self), self); \
196 } \
197 \
198 extern "C" int artSet ## Kind ## StaticFromCompiledCode( \
199 uint32_t field_idx, \
200 SetType new_value, \
201 Thread* self) \
202 REQUIRES_SHARED(Locks::mutator_lock_) { \
203 return artSet ## Kind ## StaticFromCode( \
204 field_idx, new_value, GetReferrer(self), self); \
205 } \
206 \
207 extern "C" int artSet ## Kind ## InstanceFromCompiledCode( \
208 uint32_t field_idx, \
209 mirror::Object* obj, \
210 SetType new_value, \
211 Thread* self) \
212 REQUIRES_SHARED(Locks::mutator_lock_) { \
213 return artSet ## Kind ## InstanceFromCode( \
214 field_idx, obj, new_value, GetReferrer(self), self); \
215 }
216
217 // Define these functions:
218 //
219 // artGetByteStaticFromCode
220 // artGetByteInstanceFromCode
221 // artSetByteStaticFromCode
222 // artSetByteInstanceFromCode
223 // artGetByteStaticFromCompiledCode
224 // artGetByteInstanceFromCompiledCode
225 // artSetByteStaticFromCompiledCode
226 // artSetByteInstanceFromCompiledCode
227 //
228 ART_GET_FIELD_FROM_CODE(Byte, int8_t, ssize_t, uint32_t, Primitive, false, )
229
230 // Define these functions:
231 //
232 // artGetBooleanStaticFromCode
233 // artGetBooleanInstanceFromCode
234 // artSetBooleanStaticFromCode
235 // artSetBooleanInstanceFromCode
236 // artGetBooleanStaticFromCompiledCode
237 // artGetBooleanInstanceFromCompiledCode
238 // artSetBooleanStaticFromCompiledCode
239 // artSetBooleanInstanceFromCompiledCode
240 //
241 ART_GET_FIELD_FROM_CODE(Boolean, int8_t, size_t, uint32_t, Primitive, false, )
242
243 // Define these functions:
244 //
245 // artGetShortStaticFromCode
246 // artGetShortInstanceFromCode
247 // artSetShortStaticFromCode
248 // artSetShortInstanceFromCode
249 // artGetShortStaticFromCompiledCode
250 // artGetShortInstanceFromCompiledCode
251 // artSetShortStaticFromCompiledCode
252 // artSetShortInstanceFromCompiledCode
253 //
254 ART_GET_FIELD_FROM_CODE(Short, int16_t, ssize_t, uint16_t, Primitive, false, )
255
256 // Define these functions:
257 //
258 // artGetCharStaticFromCode
259 // artGetCharInstanceFromCode
260 // artSetCharStaticFromCode
261 // artSetCharInstanceFromCode
262 // artGetCharStaticFromCompiledCode
263 // artGetCharInstanceFromCompiledCode
264 // artSetCharStaticFromCompiledCode
265 // artSetCharInstanceFromCompiledCode
266 //
267 ART_GET_FIELD_FROM_CODE(Char, int16_t, size_t, uint16_t, Primitive, false, )
268
269 // Define these functions:
270 //
271 // artGet32StaticFromCode
272 // artGet32InstanceFromCode
273 // artSet32StaticFromCode
274 // artSet32InstanceFromCode
275 // artGet32StaticFromCompiledCode
276 // artGet32InstanceFromCompiledCode
277 // artSet32StaticFromCompiledCode
278 // artSet32InstanceFromCompiledCode
279 //
280 ART_GET_FIELD_FROM_CODE(32, int32_t, size_t, uint32_t, Primitive, false, )
281
282 // Define these functions:
283 //
284 // artGet64StaticFromCode
285 // artGet64InstanceFromCode
286 // artSet64StaticFromCode
287 // artSet64InstanceFromCode
288 // artGet64StaticFromCompiledCode
289 // artGet64InstanceFromCompiledCode
290 // artSet64StaticFromCompiledCode
291 // artSet64InstanceFromCompiledCode
292 //
293 ART_GET_FIELD_FROM_CODE(64, int64_t, uint64_t, uint64_t, Primitive, false, )
294
295 // Define these functions:
296 //
297 // artGetObjStaticFromCode
298 // artGetObjInstanceFromCode
299 // artSetObjStaticFromCode
300 // artSetObjInstanceFromCode
301 // artGetObjStaticFromCompiledCode
302 // artGetObjInstanceFromCompiledCode
303 // artSetObjStaticFromCompiledCode
304 // artSetObjInstanceFromCompiledCode
305 //
306 ART_GET_FIELD_FROM_CODE(Obj, mirror::HeapReference<mirror::Object>, mirror::Object*,
307 mirror::Object*, Object, true, .Ptr())
308
309 #undef ART_GET_FIELD_FROM_CODE
310
311
312 // To cut on the number of entrypoints, we have shared entries for
313 // byte/boolean and char/short for setting an instance or static field. We just
314 // forward those to the unsigned variant.
artSet8StaticFromCompiledCode(uint32_t field_idx,uint32_t new_value,Thread * self)315 extern "C" int artSet8StaticFromCompiledCode(uint32_t field_idx,
316 uint32_t new_value,
317 Thread* self)
318 REQUIRES_SHARED(Locks::mutator_lock_) {
319 return artSetBooleanStaticFromCode(field_idx, new_value, GetReferrer(self), self);
320 }
321
artSet16StaticFromCompiledCode(uint32_t field_idx,uint16_t new_value,Thread * self)322 extern "C" int artSet16StaticFromCompiledCode(uint32_t field_idx,
323 uint16_t new_value,
324 Thread* self)
325 REQUIRES_SHARED(Locks::mutator_lock_) {
326 return artSetCharStaticFromCode(field_idx, new_value, GetReferrer(self), self);
327 }
328
artSet8InstanceFromCompiledCode(uint32_t field_idx,mirror::Object * obj,uint8_t new_value,Thread * self)329 extern "C" int artSet8InstanceFromCompiledCode(uint32_t field_idx,
330 mirror::Object* obj,
331 uint8_t new_value,
332 Thread* self)
333 REQUIRES_SHARED(Locks::mutator_lock_) {
334 return artSetBooleanInstanceFromCode(field_idx, obj, new_value, GetReferrer(self), self);
335 }
336
artSet16InstanceFromCompiledCode(uint32_t field_idx,mirror::Object * obj,uint16_t new_value,Thread * self)337 extern "C" int artSet16InstanceFromCompiledCode(uint32_t field_idx,
338 mirror::Object* obj,
339 uint16_t new_value,
340 Thread* self)
341 REQUIRES_SHARED(Locks::mutator_lock_) {
342 return artSetCharInstanceFromCode(field_idx, obj, new_value, GetReferrer(self), self);
343 }
344
artSet8StaticFromCode(uint32_t field_idx,uint32_t new_value,ArtMethod * referrer,Thread * self)345 extern "C" int artSet8StaticFromCode(uint32_t field_idx,
346 uint32_t new_value,
347 ArtMethod* referrer,
348 Thread* self)
349 REQUIRES_SHARED(Locks::mutator_lock_) {
350 return artSetBooleanStaticFromCode(field_idx, new_value, referrer, self);
351 }
352
artSet16StaticFromCode(uint32_t field_idx,uint16_t new_value,ArtMethod * referrer,Thread * self)353 extern "C" int artSet16StaticFromCode(uint32_t field_idx,
354 uint16_t new_value,
355 ArtMethod* referrer,
356 Thread* self)
357 REQUIRES_SHARED(Locks::mutator_lock_) {
358 return artSetCharStaticFromCode(field_idx, new_value, referrer, self);
359 }
360
artSet8InstanceFromCode(uint32_t field_idx,mirror::Object * obj,uint8_t new_value,ArtMethod * referrer,Thread * self)361 extern "C" int artSet8InstanceFromCode(uint32_t field_idx,
362 mirror::Object* obj,
363 uint8_t new_value,
364 ArtMethod* referrer,
365 Thread* self)
366 REQUIRES_SHARED(Locks::mutator_lock_) {
367 return artSetBooleanInstanceFromCode(field_idx, obj, new_value, referrer, self);
368 }
369
artSet16InstanceFromCode(uint32_t field_idx,mirror::Object * obj,uint16_t new_value,ArtMethod * referrer,Thread * self)370 extern "C" int artSet16InstanceFromCode(uint32_t field_idx,
371 mirror::Object* obj,
372 uint16_t new_value,
373 ArtMethod* referrer,
374 Thread* self)
375 REQUIRES_SHARED(Locks::mutator_lock_) {
376 return artSetCharInstanceFromCode(field_idx, obj, new_value, referrer, self);
377 }
378
artReadBarrierMark(mirror::Object * obj)379 extern "C" mirror::Object* artReadBarrierMark(mirror::Object* obj) {
380 DCHECK(kEmitCompilerReadBarrier);
381 return ReadBarrier::Mark(obj);
382 }
383
artReadBarrierSlow(mirror::Object * ref ATTRIBUTE_UNUSED,mirror::Object * obj,uint32_t offset)384 extern "C" mirror::Object* artReadBarrierSlow(mirror::Object* ref ATTRIBUTE_UNUSED,
385 mirror::Object* obj,
386 uint32_t offset) {
387 // Used only in connection with non-volatile loads.
388 DCHECK(kEmitCompilerReadBarrier);
389 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(obj) + offset;
390 mirror::HeapReference<mirror::Object>* ref_addr =
391 reinterpret_cast<mirror::HeapReference<mirror::Object>*>(raw_addr);
392 constexpr ReadBarrierOption kReadBarrierOption =
393 kUseReadBarrier ? kWithReadBarrier : kWithoutReadBarrier;
394 mirror::Object* result =
395 ReadBarrier::Barrier<mirror::Object, /* kIsVolatile= */ false, kReadBarrierOption>(
396 obj,
397 MemberOffset(offset),
398 ref_addr);
399 return result;
400 }
401
artReadBarrierForRootSlow(GcRoot<mirror::Object> * root)402 extern "C" mirror::Object* artReadBarrierForRootSlow(GcRoot<mirror::Object>* root) {
403 DCHECK(kEmitCompilerReadBarrier);
404 return root->Read();
405 }
406
407 } // namespace art
408