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