• 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_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 
FindFieldTypeIsRead(FindFieldType type)31 inline constexpr bool FindFieldTypeIsRead(FindFieldType type) {
32   return type == InstanceObjectRead ||
33          type == InstancePrimitiveRead ||
34          type == StaticObjectRead ||
35          type == StaticPrimitiveRead;
36 }
37 
38 // Helper function to do a null check after trying to resolve the field. Not for statics since obj
39 // does not exist there. There is a suspend check, object is a double pointer to update the value
40 // in the caller in case it moves.
41 template<FindFieldType type, bool kAccessCheck>
FindInstanceField(uint32_t field_idx,ArtMethod * referrer,Thread * self,size_t size,mirror::Object ** obj)42 ALWAYS_INLINE static inline ArtField* FindInstanceField(uint32_t field_idx,
43                                                         ArtMethod* referrer,
44                                                         Thread* self,
45                                                         size_t size,
46                                                         mirror::Object** obj)
47     REQUIRES(!Roles::uninterruptible_)
48     REQUIRES_SHARED(Locks::mutator_lock_) {
49   StackHandleScope<1> hs(self);
50   HandleWrapper<mirror::Object> h(hs.NewHandleWrapper(obj));
51   ArtField* field = FindFieldFromCode<type, kAccessCheck>(field_idx, referrer, self, size);
52   if (LIKELY(field != nullptr) && UNLIKELY(h == nullptr)) {
53     ThrowNullPointerExceptionForFieldAccess(field, /*is_read*/FindFieldTypeIsRead(type));
54     return nullptr;
55   }
56   return field;
57 }
58 
GetReferrer(Thread * self)59 static ArtMethod* GetReferrer(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) {
60   if (kIsDebugBuild) {
61     // stub_test doesn't call this code with a proper frame, so get the outer, and if
62     // it does not have compiled code return it.
63     ArtMethod* outer = GetCalleeSaveOuterMethod(self, CalleeSaveType::kSaveRefsOnly);
64     if (outer->GetEntryPointFromQuickCompiledCode() == nullptr) {
65       return outer;
66     }
67   }
68   return GetCalleeSaveMethodCallerAndOuterMethod(self, CalleeSaveType::kSaveRefsOnly).caller;
69 }
70 
71 #define ART_GET_FIELD_FROM_CODE(Kind, PrimitiveType, RetType, SetType,         \
72                                 PrimitiveOrObject, IsObject, Ptr)              \
73   extern "C" RetType artGet ## Kind ## StaticFromCode(uint32_t field_idx,      \
74                                                       ArtMethod* referrer,     \
75                                                       Thread* self)            \
76       REQUIRES_SHARED(Locks::mutator_lock_) {                                  \
77     ScopedQuickEntrypointChecks sqec(self);                                    \
78     ArtField* field = FindFieldFast(                                           \
79         field_idx, referrer, Static ## PrimitiveOrObject ## Read,              \
80         sizeof(PrimitiveType));                                                \
81     if (LIKELY(field != nullptr)) {                                            \
82       return field->Get ## Kind (field->GetDeclaringClass())Ptr;               \
83     }                                                                          \
84     field = FindFieldFromCode<Static ## PrimitiveOrObject ## Read, true>(      \
85         field_idx, referrer, self, sizeof(PrimitiveType));                     \
86     if (LIKELY(field != nullptr)) {                                            \
87       return field->Get ## Kind (field->GetDeclaringClass())Ptr;               \
88     }                                                                          \
89     /* Will throw exception by checking with Thread::Current. */               \
90     return 0;                                                                  \
91   }                                                                            \
92                                                                                \
93   extern "C" RetType artGet ## Kind ## InstanceFromCode(uint32_t field_idx,    \
94                                                         mirror::Object* obj,   \
95                                                         ArtMethod* referrer,   \
96                                                         Thread* self)          \
97       REQUIRES_SHARED(Locks::mutator_lock_) {                                  \
98     ScopedQuickEntrypointChecks sqec(self);                                    \
99     ArtField* field = FindFieldFast(                                           \
100         field_idx, referrer, Instance ## PrimitiveOrObject ## Read,            \
101         sizeof(PrimitiveType));                                                \
102     if (LIKELY(field != nullptr) && obj != nullptr) {                          \
103       return field->Get ## Kind (obj)Ptr;                                      \
104     }                                                                          \
105     field = FindInstanceField<Instance ## PrimitiveOrObject ## Read, true>(    \
106         field_idx, referrer, self, sizeof(PrimitiveType), &obj);               \
107     if (LIKELY(field != nullptr)) {                                            \
108       return field->Get ## Kind (obj)Ptr;                                      \
109     }                                                                          \
110     /* Will throw exception by checking with Thread::Current. */               \
111     return 0;                                                                  \
112   }                                                                            \
113                                                                                \
114   extern "C" int artSet ## Kind ## StaticFromCode(uint32_t field_idx,          \
115                                                   SetType new_value,           \
116                                                   ArtMethod* referrer,         \
117                                                   Thread* self)                \
118       REQUIRES_SHARED(Locks::mutator_lock_) {                                  \
119     ScopedQuickEntrypointChecks sqec(self);                                    \
120     ArtField* field = FindFieldFast(                                           \
121         field_idx, referrer, Static ## PrimitiveOrObject ## Write,             \
122         sizeof(PrimitiveType));                                                \
123     if (LIKELY(field != nullptr)) {                                            \
124       field->Set ## Kind <false>(field->GetDeclaringClass(), new_value);       \
125       return 0;                                                                \
126     }                                                                          \
127     if (IsObject) {                                                            \
128       StackHandleScope<1> hs(self);                                            \
129       HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(                 \
130           reinterpret_cast<mirror::Object**>(&new_value)));                    \
131       field = FindFieldFromCode<Static ## PrimitiveOrObject ## Write, true>(   \
132           field_idx, referrer, self, sizeof(PrimitiveType));                   \
133     } else {                                                                   \
134       field = FindFieldFromCode<Static ## PrimitiveOrObject ## Write, true>(   \
135           field_idx, referrer, self, sizeof(PrimitiveType));                   \
136     }                                                                          \
137     if (LIKELY(field != nullptr)) {                                            \
138       field->Set ## Kind <false>(field->GetDeclaringClass(), new_value);       \
139       return 0;                                                                \
140     }                                                                          \
141     return -1;                                                                 \
142   }                                                                            \
143                                                                                \
144   extern "C" int artSet ## Kind ## InstanceFromCode(uint32_t field_idx,        \
145                                                     mirror::Object* obj,       \
146                                                     SetType new_value,         \
147                                                     ArtMethod* referrer,       \
148                                                     Thread* self)              \
149     REQUIRES_SHARED(Locks::mutator_lock_) {                                    \
150     ScopedQuickEntrypointChecks sqec(self);                                    \
151     ArtField* field = FindFieldFast(                                           \
152         field_idx, referrer, Instance ## PrimitiveOrObject ## Write,           \
153         sizeof(PrimitiveType));                                                \
154     if (LIKELY(field != nullptr && obj != nullptr)) {                          \
155       field->Set ## Kind <false>(obj, new_value);                              \
156       return 0;                                                                \
157     }                                                                          \
158     if (IsObject) {                                                            \
159       StackHandleScope<1> hs(self);                                            \
160       HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(                 \
161           reinterpret_cast<mirror::Object**>(&new_value)));                    \
162       field = FindInstanceField<Instance ## PrimitiveOrObject ## Write, true>( \
163           field_idx,                                                           \
164           referrer,                                                            \
165           self,                                                                \
166           sizeof(PrimitiveType),                                               \
167           &obj);                                                               \
168     } else {                                                                   \
169       field = FindInstanceField<Instance ## PrimitiveOrObject ## Write, true>( \
170           field_idx,                                                           \
171           referrer,                                                            \
172           self,                                                                \
173           sizeof(PrimitiveType),                                               \
174           &obj);                                                               \
175     }                                                                          \
176     if (LIKELY(field != nullptr)) {                                            \
177       field->Set ## Kind<false>(obj, new_value);                               \
178       return 0;                                                                \
179     }                                                                          \
180     return -1;                                                                 \
181   }                                                                            \
182                                                                                \
183   extern "C" RetType artGet ## Kind ## StaticFromCompiledCode(                 \
184       uint32_t field_idx,                                                      \
185       Thread* self)                                                            \
186       REQUIRES_SHARED(Locks::mutator_lock_) {                                  \
187     return artGet ## Kind ## StaticFromCode(                                   \
188         field_idx, GetReferrer(self), self);                                   \
189   }                                                                            \
190                                                                                \
191   extern "C" RetType artGet ## Kind ## InstanceFromCompiledCode(               \
192       uint32_t field_idx,                                                      \
193       mirror::Object* obj,                                                     \
194       Thread* self)                                                            \
195       REQUIRES_SHARED(Locks::mutator_lock_) {                                  \
196     return artGet ## Kind ## InstanceFromCode(                                 \
197         field_idx, obj, GetReferrer(self), self);                              \
198   }                                                                            \
199                                                                                \
200   extern "C" int artSet ## Kind ## StaticFromCompiledCode(                     \
201       uint32_t field_idx,                                                      \
202       SetType new_value,                                                       \
203       Thread* self)                                                            \
204       REQUIRES_SHARED(Locks::mutator_lock_) {                                  \
205     return artSet ## Kind ## StaticFromCode(                                   \
206         field_idx, new_value, GetReferrer(self), self);                        \
207   }                                                                            \
208                                                                                \
209   extern "C" int artSet ## Kind ## InstanceFromCompiledCode(                   \
210       uint32_t field_idx,                                                      \
211       mirror::Object* obj,                                                     \
212       SetType new_value,                                                       \
213       Thread* self)                                                            \
214       REQUIRES_SHARED(Locks::mutator_lock_) {                                  \
215     return artSet ## Kind ## InstanceFromCode(                                 \
216         field_idx, obj, new_value, GetReferrer(self), self);                   \
217   }
218 
219 ART_GET_FIELD_FROM_CODE(Byte, int8_t, ssize_t, uint32_t, Primitive, false, )
220 ART_GET_FIELD_FROM_CODE(Boolean, int8_t, size_t, uint32_t, Primitive, false, )
221 ART_GET_FIELD_FROM_CODE(Short, int16_t, ssize_t, uint16_t, Primitive, false, )
222 ART_GET_FIELD_FROM_CODE(Char, int16_t, size_t, uint16_t, Primitive, false, )
223 ART_GET_FIELD_FROM_CODE(32, int32_t, size_t, uint32_t, Primitive, false, )
224 ART_GET_FIELD_FROM_CODE(64, int64_t, uint64_t, uint64_t, Primitive, false, )
225 ART_GET_FIELD_FROM_CODE(Obj, mirror::HeapReference<mirror::Object>, mirror::Object*,
226                         mirror::Object*, Object, true, .Ptr())
227 
228 
229 // To cut on the number of entrypoints, we have shared entries for
230 // byte/boolean and char/short for setting an instance or static field. We just
231 // forward those to the unsigned variant.
artSet8StaticFromCompiledCode(uint32_t field_idx,uint32_t new_value,Thread * self)232 extern "C" int artSet8StaticFromCompiledCode(uint32_t field_idx,
233                                              uint32_t new_value,
234                                              Thread* self)
235     REQUIRES_SHARED(Locks::mutator_lock_) {
236   return artSetBooleanStaticFromCode(field_idx, new_value, GetReferrer(self), self);
237 }
238 
artSet16StaticFromCompiledCode(uint32_t field_idx,uint16_t new_value,Thread * self)239 extern "C" int artSet16StaticFromCompiledCode(uint32_t field_idx,
240                                               uint16_t new_value,
241                                               Thread* self)
242     REQUIRES_SHARED(Locks::mutator_lock_) {
243   return artSetCharStaticFromCode(field_idx, new_value, GetReferrer(self), self);
244 }
245 
artSet8InstanceFromCompiledCode(uint32_t field_idx,mirror::Object * obj,uint8_t new_value,Thread * self)246 extern "C" int artSet8InstanceFromCompiledCode(uint32_t field_idx,
247                                                mirror::Object* obj,
248                                                uint8_t new_value,
249                                                Thread* self)
250     REQUIRES_SHARED(Locks::mutator_lock_) {
251   return artSetBooleanInstanceFromCode(field_idx, obj, new_value, GetReferrer(self), self);
252 }
253 
artSet16InstanceFromCompiledCode(uint32_t field_idx,mirror::Object * obj,uint16_t new_value,Thread * self)254 extern "C" int artSet16InstanceFromCompiledCode(uint32_t field_idx,
255                                                 mirror::Object* obj,
256                                                 uint16_t new_value,
257                                                 Thread* self)
258     REQUIRES_SHARED(Locks::mutator_lock_) {
259   return artSetCharInstanceFromCode(field_idx, obj, new_value, GetReferrer(self), self);
260 }
261 
artSet8StaticFromCode(uint32_t field_idx,uint32_t new_value,ArtMethod * referrer,Thread * self)262 extern "C" int artSet8StaticFromCode(uint32_t field_idx,
263                                      uint32_t new_value,
264                                      ArtMethod* referrer,
265                                      Thread* self)
266     REQUIRES_SHARED(Locks::mutator_lock_) {
267   return artSetBooleanStaticFromCode(field_idx, new_value, referrer, self);
268 }
269 
artSet16StaticFromCode(uint32_t field_idx,uint16_t new_value,ArtMethod * referrer,Thread * self)270 extern "C" int artSet16StaticFromCode(uint32_t field_idx,
271                                       uint16_t new_value,
272                                       ArtMethod* referrer,
273                                       Thread* self)
274     REQUIRES_SHARED(Locks::mutator_lock_) {
275   return artSetCharStaticFromCode(field_idx, new_value, referrer, self);
276 }
277 
artSet8InstanceFromCode(uint32_t field_idx,mirror::Object * obj,uint8_t new_value,ArtMethod * referrer,Thread * self)278 extern "C" int artSet8InstanceFromCode(uint32_t field_idx,
279                                        mirror::Object* obj,
280                                        uint8_t new_value,
281                                        ArtMethod* referrer,
282                                        Thread* self)
283     REQUIRES_SHARED(Locks::mutator_lock_) {
284   return artSetBooleanInstanceFromCode(field_idx, obj, new_value, referrer, self);
285 }
286 
artSet16InstanceFromCode(uint32_t field_idx,mirror::Object * obj,uint16_t new_value,ArtMethod * referrer,Thread * self)287 extern "C" int artSet16InstanceFromCode(uint32_t field_idx,
288                                         mirror::Object* obj,
289                                         uint16_t new_value,
290                                         ArtMethod* referrer,
291                                         Thread* self)
292     REQUIRES_SHARED(Locks::mutator_lock_) {
293   return artSetCharInstanceFromCode(field_idx, obj, new_value, referrer, self);
294 }
295 
artReadBarrierMark(mirror::Object * obj)296 extern "C" mirror::Object* artReadBarrierMark(mirror::Object* obj) {
297   DCHECK(kEmitCompilerReadBarrier);
298   return ReadBarrier::Mark(obj);
299 }
300 
artReadBarrierSlow(mirror::Object * ref ATTRIBUTE_UNUSED,mirror::Object * obj,uint32_t offset)301 extern "C" mirror::Object* artReadBarrierSlow(mirror::Object* ref ATTRIBUTE_UNUSED,
302                                               mirror::Object* obj,
303                                               uint32_t offset) {
304   DCHECK(kEmitCompilerReadBarrier);
305   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(obj) + offset;
306   mirror::HeapReference<mirror::Object>* ref_addr =
307      reinterpret_cast<mirror::HeapReference<mirror::Object>*>(raw_addr);
308   constexpr ReadBarrierOption kReadBarrierOption =
309       kUseReadBarrier ? kWithReadBarrier : kWithoutReadBarrier;
310   mirror::Object* result =
311       ReadBarrier::Barrier<mirror::Object, kReadBarrierOption>(obj,
312                                                                MemberOffset(offset),
313                                                                ref_addr);
314   return result;
315 }
316 
artReadBarrierForRootSlow(GcRoot<mirror::Object> * root)317 extern "C" mirror::Object* artReadBarrierForRootSlow(GcRoot<mirror::Object>* root) {
318   DCHECK(kEmitCompilerReadBarrier);
319   return root->Read();
320 }
321 
322 }  // namespace art
323