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