Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2016 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 #ifndef ART_RUNTIME_COMMON_DEX_OPERATIONS_H_
     18 #define ART_RUNTIME_COMMON_DEX_OPERATIONS_H_
     19 
     20 #include "android-base/logging.h"
     21 #include "art_field.h"
     22 #include "art_method.h"
     23 #include "base/macros.h"
     24 #include "base/mutex.h"
     25 #include "class_linker.h"
     26 #include "dex/code_item_accessors.h"
     27 #include "dex/primitive.h"
     28 #include "handle_scope-inl.h"
     29 #include "instrumentation.h"
     30 #include "interpreter/shadow_frame.h"
     31 #include "interpreter/unstarted_runtime.h"
     32 #include "mirror/class.h"
     33 #include "mirror/object.h"
     34 #include "obj_ptr-inl.h"
     35 #include "runtime.h"
     36 #include "stack.h"
     37 #include "thread.h"
     38 
     39 namespace art {
     40 
     41 namespace interpreter {
     42   void ArtInterpreterToInterpreterBridge(Thread* self,
     43                                         const DexFile::CodeItem* code_item,
     44                                         ShadowFrame* shadow_frame,
     45                                         JValue* result)
     46      REQUIRES_SHARED(Locks::mutator_lock_);
     47 
     48   void ArtInterpreterToCompiledCodeBridge(Thread* self,
     49                                           ArtMethod* caller,
     50                                           ShadowFrame* shadow_frame,
     51                                           uint16_t arg_offset,
     52                                           JValue* result);
     53 }  // namespace interpreter
     54 
     55 inline void PerformCall(Thread* self,
     56                         const CodeItemDataAccessor& accessor,
     57                         ArtMethod* caller_method,
     58                         const size_t first_dest_reg,
     59                         ShadowFrame* callee_frame,
     60                         JValue* result,
     61                         bool use_interpreter_entrypoint)
     62     REQUIRES_SHARED(Locks::mutator_lock_) {
     63   if (LIKELY(Runtime::Current()->IsStarted())) {
     64     if (use_interpreter_entrypoint) {
     65       interpreter::ArtInterpreterToInterpreterBridge(self, accessor, callee_frame, result);
     66     } else {
     67       interpreter::ArtInterpreterToCompiledCodeBridge(
     68           self, caller_method, callee_frame, first_dest_reg, result);
     69     }
     70   } else {
     71     interpreter::UnstartedRuntime::Invoke(self, accessor, callee_frame, result, first_dest_reg);
     72   }
     73 }
     74 
     75 template <typename T>
     76 inline void DCheckStaticState(Thread* self, T* entity) REQUIRES_SHARED(Locks::mutator_lock_) {
     77   if (kIsDebugBuild) {
     78     ObjPtr<mirror::Class> klass = entity->GetDeclaringClass();
     79     if (entity->IsStatic()) {
     80       klass->AssertInitializedOrInitializingInThread(self);
     81     } else {
     82       CHECK(klass->IsInitializing() || klass->IsErroneousResolved());
     83     }
     84   }
     85 }
     86 
     87 template<Primitive::Type field_type>
     88 static ALWAYS_INLINE bool DoFieldGetCommon(Thread* self,
     89                                            const ShadowFrame& shadow_frame,
     90                                            ObjPtr<mirror::Object> obj,
     91                                            ArtField* field,
     92                                            JValue* result)
     93     REQUIRES_SHARED(Locks::mutator_lock_) {
     94   DCheckStaticState(self, field);
     95 
     96   // Report this field access to instrumentation if needed.
     97   instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
     98   if (UNLIKELY(instrumentation->HasFieldReadListeners())) {
     99     StackHandleScope<1> hs(self);
    100     // Wrap in handle wrapper in case the listener does thread suspension.
    101     HandleWrapperObjPtr<mirror::Object> h(hs.NewHandleWrapper(&obj));
    102     ObjPtr<mirror::Object> this_object;
    103     if (!field->IsStatic()) {
    104       this_object = obj;
    105     }
    106     instrumentation->FieldReadEvent(self,
    107                                     this_object.Ptr(),
    108                                     shadow_frame.GetMethod(),
    109                                     shadow_frame.GetDexPC(),
    110                                     field);
    111     if (UNLIKELY(self->IsExceptionPending())) {
    112       return false;
    113     }
    114   }
    115 
    116   switch (field_type) {
    117     case Primitive::kPrimBoolean:
    118       result->SetZ(field->GetBoolean(obj));
    119       break;
    120     case Primitive::kPrimByte:
    121       result->SetB(field->GetByte(obj));
    122       break;
    123     case Primitive::kPrimChar:
    124       result->SetC(field->GetChar(obj));
    125       break;
    126     case Primitive::kPrimShort:
    127       result->SetS(field->GetShort(obj));
    128       break;
    129     case Primitive::kPrimInt:
    130       result->SetI(field->GetInt(obj));
    131       break;
    132     case Primitive::kPrimLong:
    133       result->SetJ(field->GetLong(obj));
    134       break;
    135     case Primitive::kPrimNot:
    136       result->SetL(field->GetObject(obj));
    137       break;
    138     case Primitive::kPrimVoid:
    139       LOG(FATAL) << "Unreachable " << field_type;
    140       break;
    141   }
    142   return true;
    143 }
    144 
    145 template<Primitive::Type field_type, bool do_assignability_check, bool transaction_active>
    146 ALWAYS_INLINE bool DoFieldPutCommon(Thread* self,
    147                                     const ShadowFrame& shadow_frame,
    148                                     ObjPtr<mirror::Object> obj,
    149                                     ArtField* field,
    150                                     JValue& value)
    151     REQUIRES_SHARED(Locks::mutator_lock_) {
    152   DCheckStaticState(self, field);
    153 
    154   // Report this field access to instrumentation if needed. Since we only have the offset of
    155   // the field from the base of the object, we need to look for it first.
    156   instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
    157   if (UNLIKELY(instrumentation->HasFieldWriteListeners())) {
    158     StackHandleScope<2> hs(self);
    159     // Save this and return value (if needed) in case the instrumentation causes a suspend.
    160     HandleWrapperObjPtr<mirror::Object> h(hs.NewHandleWrapper(&obj));
    161     ObjPtr<mirror::Object> this_object = field->IsStatic() ? nullptr : obj;
    162     mirror::Object* fake_root = nullptr;
    163     HandleWrapper<mirror::Object> ret(hs.NewHandleWrapper<mirror::Object>(
    164         field_type == Primitive::kPrimNot ? value.GetGCRoot() : &fake_root));
    165     instrumentation->FieldWriteEvent(self,
    166                                      this_object.Ptr(),
    167                                      shadow_frame.GetMethod(),
    168                                      shadow_frame.GetDexPC(),
    169                                      field,
    170                                      value);
    171     if (UNLIKELY(self->IsExceptionPending())) {
    172       return false;
    173     }
    174   }
    175 
    176   switch (field_type) {
    177     case Primitive::kPrimBoolean:
    178       field->SetBoolean<transaction_active>(obj, value.GetZ());
    179       break;
    180     case Primitive::kPrimByte:
    181       field->SetByte<transaction_active>(obj, value.GetB());
    182       break;
    183     case Primitive::kPrimChar:
    184       field->SetChar<transaction_active>(obj, value.GetC());
    185       break;
    186     case Primitive::kPrimShort:
    187       field->SetShort<transaction_active>(obj, value.GetS());
    188       break;
    189     case Primitive::kPrimInt:
    190       field->SetInt<transaction_active>(obj, value.GetI());
    191       break;
    192     case Primitive::kPrimLong:
    193       field->SetLong<transaction_active>(obj, value.GetJ());
    194       break;
    195     case Primitive::kPrimNot: {
    196       ObjPtr<mirror::Object> reg = value.GetL();
    197       if (do_assignability_check && reg != nullptr) {
    198         // FieldHelper::GetType can resolve classes, use a handle wrapper which will restore the
    199         // object in the destructor.
    200         ObjPtr<mirror::Class> field_class;
    201         {
    202           StackHandleScope<2> hs(self);
    203           HandleWrapperObjPtr<mirror::Object> h_reg(hs.NewHandleWrapper(&reg));
    204           HandleWrapperObjPtr<mirror::Object> h_obj(hs.NewHandleWrapper(&obj));
    205           field_class = field->ResolveType();
    206         }
    207         if (!reg->VerifierInstanceOf(field_class.Ptr())) {
    208           // This should never happen.
    209           std::string temp1, temp2, temp3;
    210           self->ThrowNewExceptionF("Ljava/lang/InternalError;",
    211                                    "Put '%s' that is not instance of field '%s' in '%s'",
    212                                    reg->GetClass()->GetDescriptor(&temp1),
    213                                    field_class->GetDescriptor(&temp2),
    214                                    field->GetDeclaringClass()->GetDescriptor(&temp3));
    215           return false;
    216         }
    217       }
    218       field->SetObj<transaction_active>(obj, reg);
    219       break;
    220     }
    221     case Primitive::kPrimVoid: {
    222       LOG(FATAL) << "Unreachable " << field_type;
    223       break;
    224     }
    225   }
    226   if (transaction_active) {
    227     if (UNLIKELY(self->IsExceptionPending())) {
    228       return false;
    229     }
    230   }
    231   return true;
    232 }
    233 
    234 }  // namespace art
    235 
    236 #endif  // ART_RUNTIME_COMMON_DEX_OPERATIONS_H_
    237