Home | History | Annotate | Download | only in quick
      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 
     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>
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 }
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    632 extern "C" mirror::Object* artReadBarrierMark(mirror::Object* obj) {
    633   DCHECK(kEmitCompilerReadBarrier);
    634   return ReadBarrier::Mark(obj);
    635 }
    636 
    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 
    653 extern "C" mirror::Object* artReadBarrierForRootSlow(GcRoot<mirror::Object>* root) {
    654   DCHECK(kEmitCompilerReadBarrier);
    655   return root->Read();
    656 }
    657 
    658 }  // namespace art
    659