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 "callee_save_frame.h"
22 #include "dex_file-inl.h"
23 #include "entrypoints/entrypoint_utils-inl.h"
24 #include "gc_root-inl.h"
25 #include "mirror/class-inl.h"
26 #include "mirror/object_reference.h"
27 
28 namespace art {
29 
FindFieldTypeIsRead(FindFieldType type)30 inline constexpr bool FindFieldTypeIsRead(FindFieldType type) {
31   return type == InstanceObjectRead ||
32          type == InstancePrimitiveRead ||
33          type == StaticObjectRead ||
34          type == StaticPrimitiveRead;
35 }
36 
37 // Helper function to do a null check after trying to resolve the field. Not for statics since obj
38 // does not exist there. There is a suspend check, object is a double pointer to update the value
39 // in the caller in case it moves.
40 template<FindFieldType type, bool kAccessCheck>
FindInstanceField(uint32_t field_idx,ArtMethod * referrer,Thread * self,size_t size,mirror::Object ** obj)41 ALWAYS_INLINE static inline ArtField* FindInstanceField(uint32_t field_idx,
42                                                         ArtMethod* referrer,
43                                                         Thread* self,
44                                                         size_t size,
45                                                         mirror::Object** obj)
46     REQUIRES(!Roles::uninterruptible_)
47     SHARED_REQUIRES(Locks::mutator_lock_) {
48   StackHandleScope<1> hs(self);
49   HandleWrapper<mirror::Object> h(hs.NewHandleWrapper(obj));
50   ArtField* field = FindFieldFromCode<type, kAccessCheck>(field_idx, referrer, self, size);
51   if (LIKELY(field != nullptr) && UNLIKELY(h.Get() == nullptr)) {
52     ThrowNullPointerExceptionForFieldAccess(field, /*is_read*/FindFieldTypeIsRead(type));
53     return nullptr;
54   }
55   return field;
56 }
57 
artGetByteStaticFromCode(uint32_t field_idx,ArtMethod * referrer,Thread * self)58 extern "C" int8_t artGetByteStaticFromCode(uint32_t field_idx,
59                                            ArtMethod* referrer,
60                                            Thread* self)
61     SHARED_REQUIRES(Locks::mutator_lock_) {
62   ScopedQuickEntrypointChecks sqec(self);
63   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int8_t));
64   if (LIKELY(field != nullptr)) {
65     return field->GetByte(field->GetDeclaringClass());
66   }
67   field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int8_t));
68   if (LIKELY(field != nullptr)) {
69     return field->GetByte(field->GetDeclaringClass());
70   }
71   return 0;  // Will throw exception by checking with Thread::Current.
72 }
73 
artGetBooleanStaticFromCode(uint32_t field_idx,ArtMethod * referrer,Thread * self)74 extern "C" uint8_t artGetBooleanStaticFromCode(uint32_t field_idx,
75                                                ArtMethod* referrer,
76                                                Thread* self)
77     SHARED_REQUIRES(Locks::mutator_lock_) {
78   ScopedQuickEntrypointChecks sqec(self);
79   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int8_t));
80   if (LIKELY(field != nullptr)) {
81     return field->GetBoolean(field->GetDeclaringClass());
82   }
83   field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int8_t));
84   if (LIKELY(field != nullptr)) {
85     return field->GetBoolean(field->GetDeclaringClass());
86   }
87   return 0;  // Will throw exception by checking with Thread::Current.
88 }
89 
artGetShortStaticFromCode(uint32_t field_idx,ArtMethod * referrer,Thread * self)90 extern "C" int16_t artGetShortStaticFromCode(uint32_t field_idx,
91                                              ArtMethod* referrer,
92                                              Thread* self)
93     SHARED_REQUIRES(Locks::mutator_lock_) {
94   ScopedQuickEntrypointChecks sqec(self);
95   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int16_t));
96   if (LIKELY(field != nullptr)) {
97     return field->GetShort(field->GetDeclaringClass());
98   }
99   field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int16_t));
100   if (LIKELY(field != nullptr)) {
101     return field->GetShort(field->GetDeclaringClass());
102   }
103   return 0;  // Will throw exception by checking with Thread::Current.
104 }
105 
artGetCharStaticFromCode(uint32_t field_idx,ArtMethod * referrer,Thread * self)106 extern "C" uint16_t artGetCharStaticFromCode(uint32_t field_idx,
107                                              ArtMethod* referrer,
108                                              Thread* self)
109     SHARED_REQUIRES(Locks::mutator_lock_) {
110   ScopedQuickEntrypointChecks sqec(self);
111   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int16_t));
112   if (LIKELY(field != nullptr)) {
113     return field->GetChar(field->GetDeclaringClass());
114   }
115   field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int16_t));
116   if (LIKELY(field != nullptr)) {
117     return field->GetChar(field->GetDeclaringClass());
118   }
119   return 0;  // Will throw exception by checking with Thread::Current.
120 }
121 
artGet32StaticFromCode(uint32_t field_idx,ArtMethod * referrer,Thread * self)122 extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx,
123                                            ArtMethod* referrer,
124                                            Thread* self)
125     SHARED_REQUIRES(Locks::mutator_lock_) {
126   ScopedQuickEntrypointChecks sqec(self);
127   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int32_t));
128   if (LIKELY(field != nullptr)) {
129     return field->Get32(field->GetDeclaringClass());
130   }
131   field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int32_t));
132   if (LIKELY(field != nullptr)) {
133     return field->Get32(field->GetDeclaringClass());
134   }
135   return 0;  // Will throw exception by checking with Thread::Current.
136 }
137 
artGet64StaticFromCode(uint32_t field_idx,ArtMethod * referrer,Thread * self)138 extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx,
139                                            ArtMethod* referrer,
140                                            Thread* self)
141     SHARED_REQUIRES(Locks::mutator_lock_) {
142   ScopedQuickEntrypointChecks sqec(self);
143   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int64_t));
144   if (LIKELY(field != nullptr)) {
145     return field->Get64(field->GetDeclaringClass());
146   }
147   field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int64_t));
148   if (LIKELY(field != nullptr)) {
149     return field->Get64(field->GetDeclaringClass());
150   }
151   return 0;  // Will throw exception by checking with Thread::Current.
152 }
153 
artGetObjStaticFromCode(uint32_t field_idx,ArtMethod * referrer,Thread * self)154 extern "C" mirror::Object* artGetObjStaticFromCode(uint32_t field_idx,
155                                                    ArtMethod* referrer,
156                                                    Thread* self)
157     SHARED_REQUIRES(Locks::mutator_lock_) {
158   ScopedQuickEntrypointChecks sqec(self);
159   ArtField* field = FindFieldFast(field_idx,
160                                   referrer,
161                                   StaticObjectRead,
162                                   sizeof(mirror::HeapReference<mirror::Object>));
163   if (LIKELY(field != nullptr)) {
164     return field->GetObj(field->GetDeclaringClass());
165   }
166   field = FindFieldFromCode<StaticObjectRead, true>(field_idx,
167                                                     referrer,
168                                                     self,
169                                                     sizeof(mirror::HeapReference<mirror::Object>));
170   if (LIKELY(field != nullptr)) {
171     return field->GetObj(field->GetDeclaringClass());
172   }
173   return nullptr;  // Will throw exception by checking with Thread::Current.
174 }
175 
artGetByteInstanceFromCode(uint32_t field_idx,mirror::Object * obj,ArtMethod * referrer,Thread * self)176 extern "C" int8_t artGetByteInstanceFromCode(uint32_t field_idx,
177                                              mirror::Object* obj,
178                                              ArtMethod* referrer,
179                                              Thread* self)
180     SHARED_REQUIRES(Locks::mutator_lock_) {
181   ScopedQuickEntrypointChecks sqec(self);
182   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int8_t));
183   if (LIKELY(field != nullptr && obj != nullptr)) {
184     return field->GetByte(obj);
185   }
186   field = FindInstanceField<InstancePrimitiveRead, true>(field_idx,
187                                                          referrer,
188                                                          self,
189                                                          sizeof(int8_t),
190                                                          &obj);
191   if (LIKELY(field != nullptr)) {
192     return field->GetByte(obj);
193   }
194   return 0;  // Will throw exception by checking with Thread::Current.
195 }
196 
artGetBooleanInstanceFromCode(uint32_t field_idx,mirror::Object * obj,ArtMethod * referrer,Thread * self)197 extern "C" uint8_t artGetBooleanInstanceFromCode(uint32_t field_idx,
198                                                  mirror::Object* obj,
199                                                  ArtMethod* referrer,
200                                                  Thread* self)
201     SHARED_REQUIRES(Locks::mutator_lock_) {
202   ScopedQuickEntrypointChecks sqec(self);
203   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int8_t));
204   if (LIKELY(field != nullptr && obj != nullptr)) {
205     return field->GetBoolean(obj);
206   }
207   field = FindInstanceField<InstancePrimitiveRead, true>(field_idx,
208                                                          referrer,
209                                                          self,
210                                                          sizeof(int8_t),
211                                                          &obj);
212   if (LIKELY(field != nullptr)) {
213     return field->GetBoolean(obj);
214   }
215   return 0;  // Will throw exception by checking with Thread::Current.
216 }
artGetShortInstanceFromCode(uint32_t field_idx,mirror::Object * obj,ArtMethod * referrer,Thread * self)217 extern "C" int16_t artGetShortInstanceFromCode(uint32_t field_idx,
218                                                mirror::Object* obj,
219                                                ArtMethod* referrer,
220                                                Thread* self)
221     SHARED_REQUIRES(Locks::mutator_lock_) {
222   ScopedQuickEntrypointChecks sqec(self);
223   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int16_t));
224   if (LIKELY(field != nullptr && obj != nullptr)) {
225     return field->GetShort(obj);
226   }
227   field = FindInstanceField<InstancePrimitiveRead, true>(field_idx,
228                                                          referrer,
229                                                          self,
230                                                          sizeof(int16_t),
231                                                          &obj);
232   if (LIKELY(field != nullptr)) {
233     return field->GetShort(obj);
234   }
235   return 0;  // Will throw exception by checking with Thread::Current.
236 }
237 
artGetCharInstanceFromCode(uint32_t field_idx,mirror::Object * obj,ArtMethod * referrer,Thread * self)238 extern "C" uint16_t artGetCharInstanceFromCode(uint32_t field_idx,
239                                                mirror::Object* obj,
240                                                ArtMethod* referrer,
241                                                Thread* self)
242     SHARED_REQUIRES(Locks::mutator_lock_) {
243   ScopedQuickEntrypointChecks sqec(self);
244   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int16_t));
245   if (LIKELY(field != nullptr && obj != nullptr)) {
246     return field->GetChar(obj);
247   }
248   field = FindInstanceField<InstancePrimitiveRead, true>(field_idx,
249                                                          referrer,
250                                                          self,
251                                                          sizeof(int16_t),
252                                                          &obj);
253   if (LIKELY(field != nullptr)) {
254     return field->GetChar(obj);
255   }
256   return 0;  // Will throw exception by checking with Thread::Current.
257 }
258 
artGet32InstanceFromCode(uint32_t field_idx,mirror::Object * obj,ArtMethod * referrer,Thread * self)259 extern "C" uint32_t artGet32InstanceFromCode(uint32_t field_idx,
260                                              mirror::Object* obj,
261                                              ArtMethod* referrer,
262                                              Thread* self)
263     SHARED_REQUIRES(Locks::mutator_lock_) {
264   ScopedQuickEntrypointChecks sqec(self);
265   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int32_t));
266   if (LIKELY(field != nullptr && obj != nullptr)) {
267     return field->Get32(obj);
268   }
269   field = FindInstanceField<InstancePrimitiveRead, true>(field_idx,
270                                                          referrer,
271                                                          self,
272                                                          sizeof(int32_t),
273                                                          &obj);
274   if (LIKELY(field != nullptr)) {
275     return field->Get32(obj);
276   }
277   return 0;  // Will throw exception by checking with Thread::Current.
278 }
279 
artGet64InstanceFromCode(uint32_t field_idx,mirror::Object * obj,ArtMethod * referrer,Thread * self)280 extern "C" uint64_t artGet64InstanceFromCode(uint32_t field_idx,
281                                              mirror::Object* obj,
282                                              ArtMethod* referrer,
283                                              Thread* self)
284     SHARED_REQUIRES(Locks::mutator_lock_) {
285   ScopedQuickEntrypointChecks sqec(self);
286   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int64_t));
287   if (LIKELY(field != nullptr && obj != nullptr)) {
288     return field->Get64(obj);
289   }
290   field = FindInstanceField<InstancePrimitiveRead, true>(field_idx,
291                                                          referrer,
292                                                          self,
293                                                          sizeof(int64_t),
294                                                          &obj);
295   if (LIKELY(field != nullptr)) {
296     return field->Get64(obj);
297   }
298   return 0;  // Will throw exception by checking with Thread::Current.
299 }
300 
artGetObjInstanceFromCode(uint32_t field_idx,mirror::Object * obj,ArtMethod * referrer,Thread * self)301 extern "C" mirror::Object* artGetObjInstanceFromCode(uint32_t field_idx,
302                                                      mirror::Object* obj,
303                                                      ArtMethod* referrer,
304                                                      Thread* self)
305     SHARED_REQUIRES(Locks::mutator_lock_) {
306   ScopedQuickEntrypointChecks sqec(self);
307   ArtField* field = FindFieldFast(field_idx,
308                                   referrer,
309                                   InstanceObjectRead,
310                                   sizeof(mirror::HeapReference<mirror::Object>));
311   if (LIKELY(field != nullptr && obj != nullptr)) {
312     return field->GetObj(obj);
313   }
314   field = FindInstanceField<InstanceObjectRead, true>(field_idx,
315                                                       referrer,
316                                                       self,
317                                                       sizeof(mirror::HeapReference<mirror::Object>),
318                                                       &obj);
319   if (LIKELY(field != nullptr)) {
320     return field->GetObj(obj);
321   }
322   return nullptr;  // Will throw exception by checking with Thread::Current.
323 }
324 
artSet8StaticFromCode(uint32_t field_idx,uint32_t new_value,ArtMethod * referrer,Thread * self)325 extern "C" int artSet8StaticFromCode(uint32_t field_idx,
326                                      uint32_t new_value,
327                                      ArtMethod* referrer,
328                                      Thread* self)
329     SHARED_REQUIRES(Locks::mutator_lock_) {
330   ScopedQuickEntrypointChecks sqec(self);
331   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int8_t));
332   if (LIKELY(field != nullptr)) {
333     Primitive::Type type = field->GetTypeAsPrimitiveType();
334     // Compiled code can't use transactional mode.
335     if (type == Primitive::kPrimBoolean) {
336       field->SetBoolean<false>(field->GetDeclaringClass(), new_value);
337     } else {
338       DCHECK_EQ(Primitive::kPrimByte, type);
339       field->SetByte<false>(field->GetDeclaringClass(), new_value);
340     }
341     return 0;  // success
342   }
343   field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int8_t));
344   if (LIKELY(field != nullptr)) {
345     Primitive::Type type = field->GetTypeAsPrimitiveType();
346     // Compiled code can't use transactional mode.
347     if (type == Primitive::kPrimBoolean) {
348       field->SetBoolean<false>(field->GetDeclaringClass(), new_value);
349     } else {
350       DCHECK_EQ(Primitive::kPrimByte, type);
351       field->SetByte<false>(field->GetDeclaringClass(), new_value);
352     }
353     return 0;  // success
354   }
355   return -1;  // failure
356 }
357 
artSet16StaticFromCode(uint32_t field_idx,uint16_t new_value,ArtMethod * referrer,Thread * self)358 extern "C" int artSet16StaticFromCode(uint32_t field_idx,
359                                       uint16_t new_value,
360                                       ArtMethod* referrer,
361                                       Thread* self)
362     SHARED_REQUIRES(Locks::mutator_lock_) {
363   ScopedQuickEntrypointChecks sqec(self);
364   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int16_t));
365   if (LIKELY(field != nullptr)) {
366     Primitive::Type type = field->GetTypeAsPrimitiveType();
367     // Compiled code can't use transactional mode.
368     if (type == Primitive::kPrimChar) {
369       field->SetChar<false>(field->GetDeclaringClass(), new_value);
370     } else {
371       DCHECK_EQ(Primitive::kPrimShort, type);
372       field->SetShort<false>(field->GetDeclaringClass(), new_value);
373     }
374     return 0;  // success
375   }
376   field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int16_t));
377   if (LIKELY(field != nullptr)) {
378     Primitive::Type type = field->GetTypeAsPrimitiveType();
379     // Compiled code can't use transactional mode.
380     if (type == Primitive::kPrimChar) {
381       field->SetChar<false>(field->GetDeclaringClass(), new_value);
382     } else {
383       DCHECK_EQ(Primitive::kPrimShort, type);
384       field->SetShort<false>(field->GetDeclaringClass(), new_value);
385     }
386     return 0;  // success
387   }
388   return -1;  // failure
389 }
390 
artSet32StaticFromCode(uint32_t field_idx,uint32_t new_value,ArtMethod * referrer,Thread * self)391 extern "C" int artSet32StaticFromCode(uint32_t field_idx,
392                                       uint32_t new_value,
393                                       ArtMethod* referrer,
394                                       Thread* self)
395     SHARED_REQUIRES(Locks::mutator_lock_) {
396   ScopedQuickEntrypointChecks sqec(self);
397   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int32_t));
398   if (LIKELY(field != nullptr)) {
399     // Compiled code can't use transactional mode.
400     field->Set32<false>(field->GetDeclaringClass(), new_value);
401     return 0;  // success
402   }
403   field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int32_t));
404   if (LIKELY(field != nullptr)) {
405     // Compiled code can't use transactional mode.
406     field->Set32<false>(field->GetDeclaringClass(), new_value);
407     return 0;  // success
408   }
409   return -1;  // failure
410 }
411 
artSet64StaticFromCode(uint32_t field_idx,ArtMethod * referrer,uint64_t new_value,Thread * self)412 extern "C" int artSet64StaticFromCode(uint32_t field_idx,
413                                       ArtMethod* referrer,
414                                       uint64_t new_value,
415                                       Thread* self)
416     SHARED_REQUIRES(Locks::mutator_lock_) {
417   ScopedQuickEntrypointChecks sqec(self);
418   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int64_t));
419   if (LIKELY(field != nullptr)) {
420     // Compiled code can't use transactional mode.
421     field->Set64<false>(field->GetDeclaringClass(), new_value);
422     return 0;  // success
423   }
424   field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int64_t));
425   if (LIKELY(field != nullptr)) {
426     // Compiled code can't use transactional mode.
427     field->Set64<false>(field->GetDeclaringClass(), new_value);
428     return 0;  // success
429   }
430   return -1;  // failure
431 }
432 
artSetObjStaticFromCode(uint32_t field_idx,mirror::Object * new_value,ArtMethod * referrer,Thread * self)433 extern "C" int artSetObjStaticFromCode(uint32_t field_idx,
434                                        mirror::Object* new_value,
435                                        ArtMethod* referrer,
436                                        Thread* self)
437     SHARED_REQUIRES(Locks::mutator_lock_) {
438   ScopedQuickEntrypointChecks sqec(self);
439   ArtField* field = FindFieldFast(field_idx,
440                                   referrer,
441                                   StaticObjectWrite,
442                                   sizeof(mirror::HeapReference<mirror::Object>));
443   if (LIKELY(field != nullptr)) {
444     if (LIKELY(!field->IsPrimitiveType())) {
445       // Compiled code can't use transactional mode.
446       field->SetObj<false>(field->GetDeclaringClass(), new_value);
447       return 0;  // success
448     }
449   }
450   {
451     StackHandleScope<1> hs(self);
452     HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&new_value));
453     field = FindFieldFromCode<StaticObjectWrite, true>(
454         field_idx,
455         referrer,
456         self,
457         sizeof(mirror::HeapReference<mirror::Object>));
458   }
459   if (LIKELY(field != nullptr)) {
460     // Compiled code can't use transactional mode.
461     field->SetObj<false>(field->GetDeclaringClass(), new_value);
462     return 0;  // success
463   }
464   return -1;  // failure
465 }
466 
artSet8InstanceFromCode(uint32_t field_idx,mirror::Object * obj,uint8_t new_value,ArtMethod * referrer,Thread * self)467 extern "C" int artSet8InstanceFromCode(uint32_t field_idx,
468                                        mirror::Object* obj,
469                                        uint8_t new_value,
470                                        ArtMethod* referrer,
471                                        Thread* self)
472     SHARED_REQUIRES(Locks::mutator_lock_) {
473   ScopedQuickEntrypointChecks sqec(self);
474   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int8_t));
475   if (LIKELY(field != nullptr && obj != nullptr)) {
476     Primitive::Type type = field->GetTypeAsPrimitiveType();
477     // Compiled code can't use transactional mode.
478     if (type == Primitive::kPrimBoolean) {
479       field->SetBoolean<false>(obj, new_value);
480     } else {
481       DCHECK_EQ(Primitive::kPrimByte, type);
482       field->SetByte<false>(obj, new_value);
483     }
484     return 0;  // success
485   }
486   field = FindInstanceField<InstancePrimitiveWrite, true>(field_idx,
487                                                           referrer,
488                                                           self,
489                                                           sizeof(int8_t),
490                                                           &obj);
491   if (LIKELY(field != nullptr)) {
492     Primitive::Type type = field->GetTypeAsPrimitiveType();
493     // Compiled code can't use transactional mode.
494     if (type == Primitive::kPrimBoolean) {
495       field->SetBoolean<false>(obj, new_value);
496     } else {
497       field->SetByte<false>(obj, new_value);
498     }
499     return 0;  // success
500   }
501   return -1;  // failure
502 }
503 
artSet16InstanceFromCode(uint32_t field_idx,mirror::Object * obj,uint16_t new_value,ArtMethod * referrer,Thread * self)504 extern "C" int artSet16InstanceFromCode(uint32_t field_idx,
505                                         mirror::Object* obj,
506                                         uint16_t new_value,
507                                         ArtMethod* referrer,
508                                         Thread* self)
509     SHARED_REQUIRES(Locks::mutator_lock_) {
510   ScopedQuickEntrypointChecks sqec(self);
511   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int16_t));
512   if (LIKELY(field != nullptr && obj != nullptr)) {
513     Primitive::Type type = field->GetTypeAsPrimitiveType();
514     // Compiled code can't use transactional mode.
515     if (type == Primitive::kPrimChar) {
516       field->SetChar<false>(obj, new_value);
517     } else {
518       DCHECK_EQ(Primitive::kPrimShort, type);
519       field->SetShort<false>(obj, new_value);
520     }
521     return 0;  // success
522   }
523   field = FindInstanceField<InstancePrimitiveWrite, true>(field_idx,
524                                                           referrer,
525                                                           self,
526                                                           sizeof(int16_t),
527                                                           &obj);
528   if (LIKELY(field != nullptr)) {
529     Primitive::Type type = field->GetTypeAsPrimitiveType();
530     // Compiled code can't use transactional mode.
531     if (type == Primitive::kPrimChar) {
532       field->SetChar<false>(obj, new_value);
533     } else {
534       DCHECK_EQ(Primitive::kPrimShort, type);
535       field->SetShort<false>(obj, new_value);
536     }
537     return 0;  // success
538   }
539   return -1;  // failure
540 }
541 
artSet32InstanceFromCode(uint32_t field_idx,mirror::Object * obj,uint32_t new_value,ArtMethod * referrer,Thread * self)542 extern "C" int artSet32InstanceFromCode(uint32_t field_idx,
543                                         mirror::Object* obj,
544                                         uint32_t new_value,
545                                         ArtMethod* referrer,
546                                         Thread* self)
547     SHARED_REQUIRES(Locks::mutator_lock_) {
548   ScopedQuickEntrypointChecks sqec(self);
549   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int32_t));
550   if (LIKELY(field != nullptr && obj != nullptr)) {
551     // Compiled code can't use transactional mode.
552     field->Set32<false>(obj, new_value);
553     return 0;  // success
554   }
555   field = FindInstanceField<InstancePrimitiveWrite, true>(field_idx,
556                                                           referrer,
557                                                           self,
558                                                           sizeof(int32_t),
559                                                           &obj);
560   if (LIKELY(field != nullptr)) {
561     // Compiled code can't use transactional mode.
562     field->Set32<false>(obj, new_value);
563     return 0;  // success
564   }
565   return -1;  // failure
566 }
567 
artSet64InstanceFromCode(uint32_t field_idx,mirror::Object * obj,uint64_t new_value,ArtMethod * referrer,Thread * self)568 extern "C" int artSet64InstanceFromCode(uint32_t field_idx,
569                                         mirror::Object* obj,
570                                         uint64_t new_value,
571                                         ArtMethod* referrer,
572                                         Thread* self)
573     SHARED_REQUIRES(Locks::mutator_lock_) {
574   ScopedQuickEntrypointChecks sqec(self);
575   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int64_t));
576   if (LIKELY(field != nullptr  && obj != nullptr)) {
577     // Compiled code can't use transactional mode.
578     field->Set64<false>(obj, new_value);
579     return 0;  // success
580   }
581   field = FindInstanceField<InstancePrimitiveWrite, true>(field_idx,
582                                                           referrer,
583                                                           self,
584                                                           sizeof(int64_t),
585                                                           &obj);
586   if (LIKELY(field != nullptr)) {
587     // Compiled code can't use transactional mode.
588     field->Set64<false>(obj, new_value);
589     return 0;
590   }
591   return -1;  // failure
592 }
593 
artSetObjInstanceFromCode(uint32_t field_idx,mirror::Object * obj,mirror::Object * new_value,ArtMethod * referrer,Thread * self)594 extern "C" int artSetObjInstanceFromCode(uint32_t field_idx,
595                                          mirror::Object* obj,
596                                          mirror::Object* new_value,
597                                          ArtMethod* referrer,
598                                          Thread* self)
599     SHARED_REQUIRES(Locks::mutator_lock_) {
600   ScopedQuickEntrypointChecks sqec(self);
601   ArtField* field = FindFieldFast(field_idx,
602                                   referrer,
603                                   InstanceObjectWrite,
604                                   sizeof(mirror::HeapReference<mirror::Object>));
605   if (LIKELY(field != nullptr && obj != nullptr)) {
606     // Compiled code can't use transactional mode.
607     field->SetObj<false>(obj, new_value);
608     return 0;  // success
609   }
610   {
611     StackHandleScope<2> hs(self);
612     HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&obj));
613     HandleWrapper<mirror::Object> h_new_value(hs.NewHandleWrapper(&new_value));
614     field = FindFieldFromCode<InstanceObjectWrite, true>(
615         field_idx,
616         referrer,
617         self,
618         sizeof(mirror::HeapReference<mirror::Object>));
619   }
620   if (LIKELY(field != nullptr)) {
621     if (UNLIKELY(obj == nullptr)) {
622       ThrowNullPointerExceptionForFieldAccess(field, false);
623     } else {
624       // Compiled code can't use transactional mode.
625       field->SetObj<false>(obj, new_value);
626       return 0;  // success
627     }
628   }
629   return -1;  // failure
630 }
631 
artReadBarrierMark(mirror::Object * obj)632 extern "C" mirror::Object* artReadBarrierMark(mirror::Object* obj) {
633   DCHECK(kEmitCompilerReadBarrier);
634   return ReadBarrier::Mark(obj);
635 }
636 
artReadBarrierSlow(mirror::Object * ref ATTRIBUTE_UNUSED,mirror::Object * obj,uint32_t offset)637 extern "C" mirror::Object* artReadBarrierSlow(mirror::Object* ref ATTRIBUTE_UNUSED,
638                                               mirror::Object* obj,
639                                               uint32_t offset) {
640   DCHECK(kEmitCompilerReadBarrier);
641   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(obj) + offset;
642   mirror::HeapReference<mirror::Object>* ref_addr =
643      reinterpret_cast<mirror::HeapReference<mirror::Object>*>(raw_addr);
644   constexpr ReadBarrierOption kReadBarrierOption =
645       kUseReadBarrier ? kWithReadBarrier : kWithoutReadBarrier;
646   mirror::Object* result =
647       ReadBarrier::Barrier<mirror::Object, kReadBarrierOption>(obj,
648                                                                MemberOffset(offset),
649                                                                ref_addr);
650   return result;
651 }
652 
artReadBarrierForRootSlow(GcRoot<mirror::Object> * root)653 extern "C" mirror::Object* artReadBarrierForRootSlow(GcRoot<mirror::Object>* root) {
654   DCHECK(kEmitCompilerReadBarrier);
655   return root->Read();
656 }
657 
658 }  // namespace art
659