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 "callee_save_frame.h"
     18 #include "dex_file-inl.h"
     19 #include "entrypoints/entrypoint_utils-inl.h"
     20 #include "mirror/art_field-inl.h"
     21 #include "mirror/art_method-inl.h"
     22 #include "mirror/class-inl.h"
     23 
     24 #include <stdint.h>
     25 
     26 namespace art {
     27 
     28 extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx,
     29                                            mirror::ArtMethod* referrer,
     30                                            Thread* self, StackReference<mirror::ArtMethod>* sp)
     31     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     32   mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead,
     33                                           sizeof(int32_t));
     34   if (LIKELY(field != NULL)) {
     35     return field->Get32(field->GetDeclaringClass());
     36   }
     37   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
     38   field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int32_t));
     39   if (LIKELY(field != NULL)) {
     40     return field->Get32(field->GetDeclaringClass());
     41   }
     42   return 0;  // Will throw exception by checking with Thread::Current
     43 }
     44 
     45 extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx,
     46                                            mirror::ArtMethod* referrer,
     47                                            Thread* self, StackReference<mirror::ArtMethod>* sp)
     48     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     49   mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead,
     50                                           sizeof(int64_t));
     51   if (LIKELY(field != NULL)) {
     52     return field->Get64(field->GetDeclaringClass());
     53   }
     54   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
     55   field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int64_t));
     56   if (LIKELY(field != NULL)) {
     57     return field->Get64(field->GetDeclaringClass());
     58   }
     59   return 0;  // Will throw exception by checking with Thread::Current
     60 }
     61 
     62 extern "C" mirror::Object* artGetObjStaticFromCode(uint32_t field_idx,
     63                                                    mirror::ArtMethod* referrer,
     64                                                    Thread* self,
     65                                                    StackReference<mirror::ArtMethod>* sp)
     66     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     67   mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectRead,
     68                                           sizeof(mirror::HeapReference<mirror::Object>));
     69   if (LIKELY(field != NULL)) {
     70     return field->GetObj(field->GetDeclaringClass());
     71   }
     72   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
     73   field = FindFieldFromCode<StaticObjectRead, true>(field_idx, referrer, self,
     74                                                     sizeof(mirror::HeapReference<mirror::Object>));
     75   if (LIKELY(field != NULL)) {
     76     return field->GetObj(field->GetDeclaringClass());
     77   }
     78   return NULL;  // Will throw exception by checking with Thread::Current
     79 }
     80 
     81 extern "C" uint32_t artGet32InstanceFromCode(uint32_t field_idx, mirror::Object* obj,
     82                                              mirror::ArtMethod* referrer, Thread* self,
     83                                              StackReference<mirror::ArtMethod>* sp)
     84     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     85   mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead,
     86                                           sizeof(int32_t));
     87   if (LIKELY(field != NULL && obj != NULL)) {
     88     return field->Get32(obj);
     89   }
     90   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
     91   field = FindFieldFromCode<InstancePrimitiveRead, true>(field_idx, referrer, self,
     92                                                          sizeof(int32_t));
     93   if (LIKELY(field != NULL)) {
     94     if (UNLIKELY(obj == NULL)) {
     95       ThrowLocation throw_location = self->GetCurrentLocationForThrow();
     96       ThrowNullPointerExceptionForFieldAccess(throw_location, field, true);
     97     } else {
     98       return field->Get32(obj);
     99     }
    100   }
    101   return 0;  // Will throw exception by checking with Thread::Current
    102 }
    103 
    104 extern "C" uint64_t artGet64InstanceFromCode(uint32_t field_idx, mirror::Object* obj,
    105                                              mirror::ArtMethod* referrer, Thread* self,
    106                                              StackReference<mirror::ArtMethod>* sp)
    107     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    108   mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead,
    109                                           sizeof(int64_t));
    110   if (LIKELY(field != NULL && obj != NULL)) {
    111     return field->Get64(obj);
    112   }
    113   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
    114   field = FindFieldFromCode<InstancePrimitiveRead, true>(field_idx, referrer, self,
    115                                                          sizeof(int64_t));
    116   if (LIKELY(field != NULL)) {
    117     if (UNLIKELY(obj == NULL)) {
    118       ThrowLocation throw_location = self->GetCurrentLocationForThrow();
    119       ThrowNullPointerExceptionForFieldAccess(throw_location, field, true);
    120     } else {
    121       return field->Get64(obj);
    122     }
    123   }
    124   return 0;  // Will throw exception by checking with Thread::Current
    125 }
    126 
    127 extern "C" mirror::Object* artGetObjInstanceFromCode(uint32_t field_idx, mirror::Object* obj,
    128                                                      mirror::ArtMethod* referrer,
    129                                                      Thread* self,
    130                                                      StackReference<mirror::ArtMethod>* sp)
    131     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    132   mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectRead,
    133                                           sizeof(mirror::HeapReference<mirror::Object>));
    134   if (LIKELY(field != NULL && obj != NULL)) {
    135     return field->GetObj(obj);
    136   }
    137   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
    138   field = FindFieldFromCode<InstanceObjectRead, true>(field_idx, referrer, self,
    139                                                       sizeof(mirror::HeapReference<mirror::Object>));
    140   if (LIKELY(field != NULL)) {
    141     if (UNLIKELY(obj == NULL)) {
    142       ThrowLocation throw_location = self->GetCurrentLocationForThrow();
    143       ThrowNullPointerExceptionForFieldAccess(throw_location, field, true);
    144     } else {
    145       return field->GetObj(obj);
    146     }
    147   }
    148   return NULL;  // Will throw exception by checking with Thread::Current
    149 }
    150 
    151 extern "C" int artSet32StaticFromCode(uint32_t field_idx, uint32_t new_value,
    152                                       mirror::ArtMethod* referrer, Thread* self,
    153                                       StackReference<mirror::ArtMethod>* sp)
    154     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    155   mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite,
    156                                           sizeof(int32_t));
    157   if (LIKELY(field != NULL)) {
    158     // Compiled code can't use transactional mode.
    159     field->Set32<false>(field->GetDeclaringClass(), new_value);
    160     return 0;  // success
    161   }
    162   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
    163   field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int32_t));
    164   if (LIKELY(field != NULL)) {
    165     // Compiled code can't use transactional mode.
    166     field->Set32<false>(field->GetDeclaringClass(), new_value);
    167     return 0;  // success
    168   }
    169   return -1;  // failure
    170 }
    171 
    172 extern "C" int artSet64StaticFromCode(uint32_t field_idx, mirror::ArtMethod* referrer,
    173                                       uint64_t new_value, Thread* self,
    174                                       StackReference<mirror::ArtMethod>* sp)
    175     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    176   mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite,
    177                                           sizeof(int64_t));
    178   if (LIKELY(field != NULL)) {
    179     // Compiled code can't use transactional mode.
    180     field->Set64<false>(field->GetDeclaringClass(), new_value);
    181     return 0;  // success
    182   }
    183   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
    184   field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int64_t));
    185   if (LIKELY(field != NULL)) {
    186     // Compiled code can't use transactional mode.
    187     field->Set64<false>(field->GetDeclaringClass(), new_value);
    188     return 0;  // success
    189   }
    190   return -1;  // failure
    191 }
    192 
    193 extern "C" int artSetObjStaticFromCode(uint32_t field_idx, mirror::Object* new_value,
    194                                        mirror::ArtMethod* referrer, Thread* self,
    195                                        StackReference<mirror::ArtMethod>* sp)
    196     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    197   mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectWrite,
    198                                           sizeof(mirror::HeapReference<mirror::Object>));
    199   if (LIKELY(field != NULL)) {
    200     if (LIKELY(!field->IsPrimitiveType())) {
    201       // Compiled code can't use transactional mode.
    202       field->SetObj<false>(field->GetDeclaringClass(), new_value);
    203       return 0;  // success
    204     }
    205   }
    206   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
    207   field = FindFieldFromCode<StaticObjectWrite, true>(field_idx, referrer, self,
    208                                                      sizeof(mirror::HeapReference<mirror::Object>));
    209   if (LIKELY(field != NULL)) {
    210     // Compiled code can't use transactional mode.
    211     field->SetObj<false>(field->GetDeclaringClass(), new_value);
    212     return 0;  // success
    213   }
    214   return -1;  // failure
    215 }
    216 
    217 extern "C" int artSet32InstanceFromCode(uint32_t field_idx, mirror::Object* obj, uint32_t new_value,
    218                                         mirror::ArtMethod* referrer, Thread* self,
    219                                         StackReference<mirror::ArtMethod>* sp)
    220     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    221   mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite,
    222                                           sizeof(int32_t));
    223   if (LIKELY(field != NULL && obj != NULL)) {
    224     // Compiled code can't use transactional mode.
    225     field->Set32<false>(obj, new_value);
    226     return 0;  // success
    227   }
    228   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
    229   {
    230     StackHandleScope<1> hs(self);
    231     HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&obj));
    232     field = FindFieldFromCode<InstancePrimitiveWrite, true>(field_idx, referrer, self,
    233                                                             sizeof(int32_t));
    234   }
    235   if (LIKELY(field != NULL)) {
    236     if (UNLIKELY(obj == NULL)) {
    237       ThrowLocation throw_location = self->GetCurrentLocationForThrow();
    238       ThrowNullPointerExceptionForFieldAccess(throw_location, field, false);
    239     } else {
    240       // Compiled code can't use transactional mode.
    241       field->Set32<false>(obj, new_value);
    242       return 0;  // success
    243     }
    244   }
    245   return -1;  // failure
    246 }
    247 
    248 extern "C" int artSet64InstanceFromCode(uint32_t field_idx, mirror::Object* obj, uint64_t new_value,
    249                                         Thread* self, StackReference<mirror::ArtMethod>* sp)
    250     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    251   constexpr size_t frame_size = GetCalleeSaveFrameSize(kRuntimeISA, Runtime::kRefsOnly);
    252   mirror::ArtMethod* referrer =
    253       reinterpret_cast<StackReference<mirror::ArtMethod>*>(
    254           reinterpret_cast<uint8_t*>(sp) + frame_size)->AsMirrorPtr();
    255   mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite,
    256                                           sizeof(int64_t));
    257   if (LIKELY(field != NULL  && obj != NULL)) {
    258     // Compiled code can't use transactional mode.
    259     field->Set64<false>(obj, new_value);
    260     return 0;  // success
    261   }
    262   sp->Assign(Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsOnly));
    263   self->SetTopOfStack(sp, 0);
    264   field = FindFieldFromCode<InstancePrimitiveWrite, true>(field_idx, referrer, self,
    265                                                           sizeof(int64_t));
    266   if (LIKELY(field != NULL)) {
    267     if (UNLIKELY(obj == NULL)) {
    268       ThrowLocation throw_location = self->GetCurrentLocationForThrow();
    269       ThrowNullPointerExceptionForFieldAccess(throw_location, field, false);
    270     } else {
    271       // Compiled code can't use transactional mode.
    272       field->Set64<false>(obj, new_value);
    273       return 0;  // success
    274     }
    275   }
    276   return -1;  // failure
    277 }
    278 
    279 extern "C" int artSetObjInstanceFromCode(uint32_t field_idx, mirror::Object* obj,
    280                                          mirror::Object* new_value,
    281                                          mirror::ArtMethod* referrer, Thread* self,
    282                                          StackReference<mirror::ArtMethod>* sp)
    283     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    284   mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite,
    285                                           sizeof(mirror::HeapReference<mirror::Object>));
    286   if (LIKELY(field != NULL && obj != NULL)) {
    287     // Compiled code can't use transactional mode.
    288     field->SetObj<false>(obj, new_value);
    289     return 0;  // success
    290   }
    291   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
    292   field = FindFieldFromCode<InstanceObjectWrite, true>(field_idx, referrer, self,
    293                                                        sizeof(mirror::HeapReference<mirror::Object>));
    294   if (LIKELY(field != NULL)) {
    295     if (UNLIKELY(obj == NULL)) {
    296       ThrowLocation throw_location = self->GetCurrentLocationForThrow();
    297       ThrowNullPointerExceptionForFieldAccess(throw_location, field, false);
    298     } else {
    299       // Compiled code can't use transactional mode.
    300       field->SetObj<false>(obj, new_value);
    301       return 0;  // success
    302     }
    303   }
    304   return -1;  // failure
    305 }
    306 
    307 }  // namespace art
    308