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