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
28namespace art {
29
30inline 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.
40template<FindFieldType type, bool kAccessCheck>
41ALWAYS_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
58extern "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
74extern "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
90extern "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
106extern "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
122extern "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
138extern "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
154extern "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
176extern "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
197extern "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}
217extern "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
238extern "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
259extern "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
280extern "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
301extern "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
325extern "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
358extern "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
391extern "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
412extern "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
433extern "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
467extern "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
504extern "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
542extern "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
568extern "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
594extern "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
632extern "C" mirror::Object* artReadBarrierMark(mirror::Object* obj) {
633  DCHECK(kEmitCompilerReadBarrier);
634  return ReadBarrier::Mark(obj);
635}
636
637extern "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
653extern "C" mirror::Object* artReadBarrierForRootSlow(GcRoot<mirror::Object>* root) {
654  DCHECK(kEmitCompilerReadBarrier);
655  return root->Read();
656}
657
658}  // namespace art
659