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