Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2011 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_OBJECT_UTILS_H_
     18 #define ART_RUNTIME_OBJECT_UTILS_H_
     19 
     20 #include "class_linker-inl.h"
     21 #include "dex_file.h"
     22 #include "monitor.h"
     23 #include "mirror/art_field.h"
     24 #include "mirror/art_method.h"
     25 #include "mirror/class.h"
     26 #include "mirror/dex_cache.h"
     27 #include "mirror/iftable.h"
     28 #include "mirror/string.h"
     29 
     30 #include "runtime.h"
     31 #include "sirt_ref.h"
     32 
     33 #include <string>
     34 
     35 namespace art {
     36 
     37 class ObjectLock {
     38  public:
     39   explicit ObjectLock(Thread* self, mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
     40       : self_(self), obj_(object) {
     41     CHECK(object != NULL);
     42     obj_->MonitorEnter(self_);
     43   }
     44 
     45   ~ObjectLock() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     46     obj_->MonitorExit(self_);
     47   }
     48 
     49   void WaitIgnoringInterrupts() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     50     Monitor::Wait(self_, obj_, 0, 0, false, kWaiting);
     51   }
     52 
     53   void Notify() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     54     obj_->Notify(self_);
     55   }
     56 
     57   void NotifyAll() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     58     obj_->NotifyAll(self_);
     59   }
     60 
     61  private:
     62   Thread* const self_;
     63   mirror::Object* obj_;
     64   DISALLOW_COPY_AND_ASSIGN(ObjectLock);
     65 };
     66 
     67 class ClassHelper {
     68  public:
     69   ClassHelper(const mirror::Class* c = NULL, ClassLinker* l = NULL)
     70       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
     71       : class_linker_(l),
     72         dex_cache_(NULL),
     73         dex_file_(NULL),
     74         interface_type_list_(NULL),
     75         klass_(NULL) {
     76     if (c != NULL) {
     77       ChangeClass(c);
     78     }
     79   }
     80 
     81   void ChangeClass(const mirror::Class* new_c)
     82       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     83     CHECK(new_c != NULL) << "klass_=" << klass_;  // Log what we were changing from if any
     84     CHECK(new_c->IsClass()) << "new_c=" << new_c;
     85     if (dex_cache_ != NULL) {
     86       mirror::DexCache* new_c_dex_cache = new_c->GetDexCache();
     87       if (new_c_dex_cache != dex_cache_) {
     88         dex_cache_ = new_c_dex_cache;
     89         dex_file_ = NULL;
     90       }
     91     }
     92     klass_ = new_c;
     93     interface_type_list_ = NULL;
     94   }
     95 
     96   // The returned const char* is only guaranteed to be valid for the lifetime of the ClassHelper.
     97   // If you need it longer, copy it into a std::string.
     98   const char* GetDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     99     CHECK(klass_ != NULL);
    100     if (UNLIKELY(klass_->IsArrayClass())) {
    101       return GetArrayDescriptor();
    102     } else if (UNLIKELY(klass_->IsPrimitive())) {
    103       return Primitive::Descriptor(klass_->GetPrimitiveType());
    104     } else if (UNLIKELY(klass_->IsProxyClass())) {
    105       descriptor_ = GetClassLinker()->GetDescriptorForProxy(klass_);
    106       return descriptor_.c_str();
    107     } else {
    108       const DexFile& dex_file = GetDexFile();
    109       const DexFile::TypeId& type_id = dex_file.GetTypeId(GetClassDef()->class_idx_);
    110       return dex_file.GetTypeDescriptor(type_id);
    111     }
    112   }
    113 
    114   const char* GetArrayDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    115     std::string result("[");
    116     const mirror::Class* saved_klass = klass_;
    117     CHECK(saved_klass != NULL);
    118     ChangeClass(klass_->GetComponentType());
    119     result += GetDescriptor();
    120     ChangeClass(saved_klass);
    121     descriptor_ = result;
    122     return descriptor_.c_str();
    123   }
    124 
    125   const DexFile::ClassDef* GetClassDef() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    126     DCHECK(klass_ != nullptr);
    127     uint16_t class_def_idx = klass_->GetDexClassDefIndex();
    128     if (class_def_idx == DexFile::kDexNoIndex16) {
    129       return nullptr;
    130     }
    131     return &GetDexFile().GetClassDef(class_def_idx);
    132   }
    133 
    134   uint32_t NumDirectInterfaces() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    135     DCHECK(klass_ != NULL);
    136     if (klass_->IsPrimitive()) {
    137       return 0;
    138     } else if (klass_->IsArrayClass()) {
    139       return 2;
    140     } else if (klass_->IsProxyClass()) {
    141       return klass_->GetIfTable()->GetLength();
    142     } else {
    143       const DexFile::TypeList* interfaces = GetInterfaceTypeList();
    144       if (interfaces == NULL) {
    145         return 0;
    146       } else {
    147         return interfaces->Size();
    148       }
    149     }
    150   }
    151 
    152   uint16_t GetDirectInterfaceTypeIdx(uint32_t idx)
    153       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    154     DCHECK(klass_ != NULL);
    155     DCHECK(!klass_->IsPrimitive());
    156     DCHECK(!klass_->IsArrayClass());
    157     return GetInterfaceTypeList()->GetTypeItem(idx).type_idx_;
    158   }
    159 
    160   mirror::Class* GetDirectInterface(uint32_t idx)
    161       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    162     DCHECK(klass_ != NULL);
    163     DCHECK(!klass_->IsPrimitive());
    164     if (klass_->IsArrayClass()) {
    165       if (idx == 0) {
    166         return GetClassLinker()->FindSystemClass("Ljava/lang/Cloneable;");
    167       } else {
    168         DCHECK_EQ(1U, idx);
    169         return GetClassLinker()->FindSystemClass("Ljava/io/Serializable;");
    170       }
    171     } else if (klass_->IsProxyClass()) {
    172       return klass_->GetIfTable()->GetInterface(idx);
    173     } else {
    174       uint16_t type_idx = GetDirectInterfaceTypeIdx(idx);
    175       mirror::Class* interface = GetDexCache()->GetResolvedType(type_idx);
    176       if (interface == NULL) {
    177         interface = GetClassLinker()->ResolveType(GetDexFile(), type_idx, klass_);
    178         CHECK(interface != NULL || Thread::Current()->IsExceptionPending());
    179       }
    180       return interface;
    181     }
    182   }
    183 
    184   const char* GetSourceFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    185     std::string descriptor(GetDescriptor());
    186     const DexFile& dex_file = GetDexFile();
    187     const DexFile::ClassDef* dex_class_def = GetClassDef();
    188     CHECK(dex_class_def != NULL);
    189     return dex_file.GetSourceFile(*dex_class_def);
    190   }
    191 
    192   std::string GetLocation() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    193     mirror::DexCache* dex_cache = GetDexCache();
    194     if (dex_cache != NULL && !klass_->IsProxyClass()) {
    195       return dex_cache->GetLocation()->ToModifiedUtf8();
    196     } else {
    197       // Arrays and proxies are generated and have no corresponding dex file location.
    198       return "generated class";
    199     }
    200   }
    201 
    202   const DexFile& GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    203     if (dex_file_ == NULL) {
    204       dex_file_ = GetDexCache()->GetDexFile();
    205     }
    206     return *dex_file_;
    207   }
    208 
    209   mirror::DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    210     mirror::DexCache* result = dex_cache_;
    211     if (result == NULL) {
    212       DCHECK(klass_ != NULL);
    213       result = klass_->GetDexCache();
    214       dex_cache_ = result;
    215     }
    216     return result;
    217   }
    218 
    219  private:
    220   const DexFile::TypeList* GetInterfaceTypeList()
    221       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    222     const DexFile::TypeList* result = interface_type_list_;
    223     if (result == NULL) {
    224       const DexFile::ClassDef* class_def = GetClassDef();
    225       if (class_def != NULL) {
    226         result =  GetDexFile().GetInterfacesList(*class_def);
    227         interface_type_list_ = result;
    228       }
    229     }
    230     return result;
    231   }
    232 
    233   ClassLinker* GetClassLinker() {
    234     ClassLinker* result = class_linker_;
    235     if (result == NULL) {
    236       result = Runtime::Current()->GetClassLinker();
    237       class_linker_ = result;
    238     }
    239     return result;
    240   }
    241 
    242   ClassLinker* class_linker_;
    243   mirror::DexCache* dex_cache_;
    244   const DexFile* dex_file_;
    245   const DexFile::TypeList* interface_type_list_;
    246   const mirror::Class* klass_;
    247   std::string descriptor_;
    248 
    249   DISALLOW_COPY_AND_ASSIGN(ClassHelper);
    250 };
    251 
    252 class FieldHelper {
    253  public:
    254   FieldHelper() : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), field_(NULL) {}
    255   explicit FieldHelper(const mirror::ArtField* f) : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), field_(f) {}
    256   FieldHelper(const mirror::ArtField* f, ClassLinker* l)
    257       : class_linker_(l), dex_cache_(NULL), dex_file_(NULL), field_(f) {}
    258 
    259   void ChangeField(const mirror::ArtField* new_f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    260     DCHECK(new_f != NULL);
    261     if (dex_cache_ != NULL) {
    262       mirror::DexCache* new_f_dex_cache = new_f->GetDeclaringClass()->GetDexCache();
    263       if (new_f_dex_cache != dex_cache_) {
    264         dex_cache_ = new_f_dex_cache;
    265         dex_file_ = NULL;
    266       }
    267     }
    268     field_ = new_f;
    269   }
    270   const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    271     uint32_t field_index = field_->GetDexFieldIndex();
    272     if (!field_->GetDeclaringClass()->IsProxyClass()) {
    273       const DexFile& dex_file = GetDexFile();
    274       return dex_file.GetFieldName(dex_file.GetFieldId(field_index));
    275     } else {
    276       DCHECK(field_->IsStatic());
    277       DCHECK_LT(field_index, 2U);
    278       return field_index == 0 ? "interfaces" : "throws";
    279     }
    280   }
    281   mirror::Class* GetType(bool resolve = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    282     uint32_t field_index = field_->GetDexFieldIndex();
    283     if (!field_->GetDeclaringClass()->IsProxyClass()) {
    284       const DexFile& dex_file = GetDexFile();
    285       const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
    286       mirror::Class* type = GetDexCache()->GetResolvedType(field_id.type_idx_);
    287       if (resolve && (type == NULL)) {
    288         type = GetClassLinker()->ResolveType(field_id.type_idx_, field_);
    289         CHECK(type != NULL || Thread::Current()->IsExceptionPending());
    290       }
    291       return type;
    292     } else {
    293       return GetClassLinker()->FindSystemClass(GetTypeDescriptor());
    294     }
    295   }
    296   const char* GetTypeDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    297     uint32_t field_index = field_->GetDexFieldIndex();
    298     if (!field_->GetDeclaringClass()->IsProxyClass()) {
    299       const DexFile& dex_file = GetDexFile();
    300       const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
    301       return dex_file.GetFieldTypeDescriptor(field_id);
    302     } else {
    303       DCHECK(field_->IsStatic());
    304       DCHECK_LT(field_index, 2U);
    305       // 0 == Class[] interfaces; 1 == Class[][] throws;
    306       return field_index == 0 ? "[Ljava/lang/Class;" : "[[Ljava/lang/Class;";
    307     }
    308   }
    309   Primitive::Type GetTypeAsPrimitiveType()
    310       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    311     return Primitive::GetType(GetTypeDescriptor()[0]);
    312   }
    313   bool IsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    314     Primitive::Type type = GetTypeAsPrimitiveType();
    315     return type != Primitive::kPrimNot;
    316   }
    317   size_t FieldSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    318     Primitive::Type type = GetTypeAsPrimitiveType();
    319     return Primitive::FieldSize(type);
    320   }
    321 
    322   // The returned const char* is only guaranteed to be valid for the lifetime of the FieldHelper.
    323   // If you need it longer, copy it into a std::string.
    324   const char* GetDeclaringClassDescriptor()
    325       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    326     uint32_t field_index = field_->GetDexFieldIndex();
    327     if (!field_->GetDeclaringClass()->IsProxyClass()) {
    328       const DexFile& dex_file = GetDexFile();
    329       const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
    330       return dex_file.GetFieldDeclaringClassDescriptor(field_id);
    331     } else {
    332       DCHECK(field_->IsStatic());
    333       DCHECK_LT(field_index, 2U);
    334       // 0 == Class[] interfaces; 1 == Class[][] throws;
    335       ClassHelper kh(field_->GetDeclaringClass());
    336       declaring_class_descriptor_ = kh.GetDescriptor();
    337       return declaring_class_descriptor_.c_str();
    338     }
    339   }
    340 
    341  private:
    342   mirror::DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    343     mirror::DexCache* result = dex_cache_;
    344     if (result == NULL) {
    345       result = field_->GetDeclaringClass()->GetDexCache();
    346       dex_cache_ = result;
    347     }
    348     return result;
    349   }
    350   ClassLinker* GetClassLinker() {
    351     ClassLinker* result = class_linker_;
    352     if (result == NULL) {
    353       result = Runtime::Current()->GetClassLinker();
    354       class_linker_ = result;
    355     }
    356     return result;
    357   }
    358   const DexFile& GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    359     if (dex_file_ == NULL) {
    360       dex_file_ = GetDexCache()->GetDexFile();
    361     }
    362     return *dex_file_;
    363   }
    364 
    365   ClassLinker* class_linker_;
    366   mirror::DexCache* dex_cache_;
    367   const DexFile* dex_file_;
    368   const mirror::ArtField* field_;
    369   std::string declaring_class_descriptor_;
    370 
    371   DISALLOW_COPY_AND_ASSIGN(FieldHelper);
    372 };
    373 
    374 class MethodHelper {
    375  public:
    376   MethodHelper()
    377      : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), method_(NULL), shorty_(NULL),
    378        shorty_len_(0) {}
    379 
    380   explicit MethodHelper(const mirror::ArtMethod* m)
    381       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    382       : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), method_(NULL), shorty_(NULL),
    383         shorty_len_(0) {
    384     SetMethod(m);
    385   }
    386 
    387   MethodHelper(const mirror::ArtMethod* m, ClassLinker* l)
    388       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    389       : class_linker_(l), dex_cache_(NULL), dex_file_(NULL), method_(NULL), shorty_(NULL),
    390         shorty_len_(0) {
    391     SetMethod(m);
    392   }
    393 
    394   void ChangeMethod(mirror::ArtMethod* new_m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    395     DCHECK(new_m != NULL);
    396     if (dex_cache_ != NULL) {
    397       mirror::Class* klass = new_m->GetDeclaringClass();
    398       if (klass->IsProxyClass()) {
    399         dex_cache_ = NULL;
    400         dex_file_ = NULL;
    401       } else {
    402         mirror::DexCache* new_m_dex_cache = klass->GetDexCache();
    403         if (new_m_dex_cache != dex_cache_) {
    404           dex_cache_ = new_m_dex_cache;
    405           dex_file_ = NULL;
    406         }
    407       }
    408     }
    409     SetMethod(new_m);
    410     shorty_ = NULL;
    411   }
    412 
    413   const mirror::ArtMethod* GetMethod() const {
    414     return method_;
    415   }
    416 
    417   const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    418     const DexFile& dex_file = GetDexFile();
    419     uint32_t dex_method_idx = method_->GetDexMethodIndex();
    420     if (dex_method_idx != DexFile::kDexNoIndex) {
    421       return dex_file.GetMethodName(dex_file.GetMethodId(dex_method_idx));
    422     } else {
    423       Runtime* runtime = Runtime::Current();
    424       if (method_ == runtime->GetResolutionMethod()) {
    425         return "<runtime internal resolution method>";
    426       } else if (method_ == runtime->GetCalleeSaveMethod(Runtime::kSaveAll)) {
    427         return "<runtime internal callee-save all registers method>";
    428       } else if (method_ == runtime->GetCalleeSaveMethod(Runtime::kRefsOnly)) {
    429         return "<runtime internal callee-save reference registers method>";
    430       } else if (method_ == runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs)) {
    431         return "<runtime internal callee-save reference and argument registers method>";
    432       } else {
    433         return "<unknown runtime internal method>";
    434       }
    435     }
    436   }
    437 
    438   mirror::String* GetNameAsString() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    439     const DexFile& dex_file = GetDexFile();
    440     uint32_t dex_method_idx = method_->GetDexMethodIndex();
    441     const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
    442     return GetClassLinker()->ResolveString(dex_file, method_id.name_idx_, GetDexCache());
    443   }
    444 
    445   const char* GetShorty() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    446     const char* result = shorty_;
    447     if (result == NULL) {
    448       const DexFile& dex_file = GetDexFile();
    449       result = dex_file.GetMethodShorty(dex_file.GetMethodId(method_->GetDexMethodIndex()),
    450                                         &shorty_len_);
    451       shorty_ = result;
    452     }
    453     return result;
    454   }
    455 
    456   uint32_t GetShortyLength() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    457     if (shorty_ == NULL) {
    458       GetShorty();
    459     }
    460     return shorty_len_;
    461   }
    462 
    463   const std::string GetSignature() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    464     const DexFile& dex_file = GetDexFile();
    465     uint32_t dex_method_idx = method_->GetDexMethodIndex();
    466     if (dex_method_idx != DexFile::kDexNoIndex) {
    467       return dex_file.GetMethodSignature(dex_file.GetMethodId(dex_method_idx));
    468     } else {
    469       return "<no signature>";
    470     }
    471   }
    472 
    473   const DexFile::ProtoId& GetPrototype() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    474     const DexFile& dex_file = GetDexFile();
    475     return dex_file.GetMethodPrototype(dex_file.GetMethodId(method_->GetDexMethodIndex()));
    476   }
    477 
    478   const DexFile::TypeList* GetParameterTypeList() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    479     const DexFile::ProtoId& proto = GetPrototype();
    480     return GetDexFile().GetProtoParameters(proto);
    481   }
    482 
    483   mirror::Class* GetReturnType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    484     const DexFile& dex_file = GetDexFile();
    485     const DexFile::MethodId& method_id = dex_file.GetMethodId(method_->GetDexMethodIndex());
    486     const DexFile::ProtoId& proto_id = dex_file.GetMethodPrototype(method_id);
    487     uint16_t return_type_idx = proto_id.return_type_idx_;
    488     return GetClassFromTypeIdx(return_type_idx);
    489   }
    490 
    491   const char* GetReturnTypeDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    492     const DexFile& dex_file = GetDexFile();
    493     const DexFile::MethodId& method_id = dex_file.GetMethodId(method_->GetDexMethodIndex());
    494     const DexFile::ProtoId& proto_id = dex_file.GetMethodPrototype(method_id);
    495     uint16_t return_type_idx = proto_id.return_type_idx_;
    496     return dex_file.GetTypeDescriptor(dex_file.GetTypeId(return_type_idx));
    497   }
    498 
    499   int32_t GetLineNumFromDexPC(uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    500     if (dex_pc == DexFile::kDexNoIndex) {
    501       return method_->IsNative() ? -2 : -1;
    502     } else {
    503       const DexFile& dex_file = GetDexFile();
    504       return dex_file.GetLineNumFromPC(method_, dex_pc);
    505     }
    506   }
    507 
    508   const char* GetDeclaringClassDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    509     const DexFile& dex_file = GetDexFile();
    510     uint32_t dex_method_idx = method_->GetDexMethodIndex();
    511     if (dex_method_idx != DexFile::kDexNoIndex) {
    512       return dex_file.GetMethodDeclaringClassDescriptor(dex_file.GetMethodId(dex_method_idx));
    513     } else {
    514       return "<runtime method>";
    515     }
    516   }
    517 
    518   const char* GetDeclaringClassSourceFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    519     return ClassHelper(method_->GetDeclaringClass()).GetSourceFile();
    520   }
    521 
    522   uint16_t GetClassDefIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    523     return method_->GetDeclaringClass()->GetDexClassDefIndex();
    524   }
    525 
    526   const DexFile::ClassDef& GetClassDef() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    527     return GetDexFile().GetClassDef(GetClassDefIndex());
    528   }
    529 
    530   mirror::ClassLoader* GetClassLoader() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    531     return method_->GetDeclaringClass()->GetClassLoader();
    532   }
    533 
    534   bool IsStatic() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    535     return method_->IsStatic();
    536   }
    537 
    538   bool IsClassInitializer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    539     return IsStatic() && StringPiece(GetName()) == "<clinit>";
    540   }
    541 
    542   size_t NumArgs() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    543     // "1 +" because the first in Args is the receiver.
    544     // "- 1" because we don't count the return type.
    545     return (IsStatic() ? 0 : 1) + GetShortyLength() - 1;
    546   }
    547 
    548   // Get the primitive type associated with the given parameter.
    549   Primitive::Type GetParamPrimitiveType(size_t param) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    550     CHECK_LT(param, NumArgs());
    551     if (IsStatic()) {
    552       param++;  // 0th argument must skip return value at start of the shorty
    553     } else if (param == 0) {
    554       return Primitive::kPrimNot;
    555     }
    556     return Primitive::GetType(GetShorty()[param]);
    557   }
    558 
    559   // Is the specified parameter a long or double, where parameter 0 is 'this' for instance methods.
    560   bool IsParamALongOrDouble(size_t param) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    561     Primitive::Type type = GetParamPrimitiveType(param);
    562     return type == Primitive::kPrimLong || type == Primitive::kPrimDouble;
    563   }
    564 
    565   // Is the specified parameter a reference, where parameter 0 is 'this' for instance methods.
    566   bool IsParamAReference(size_t param) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    567     return GetParamPrimitiveType(param) == Primitive::kPrimNot;
    568   }
    569 
    570   bool HasSameNameAndSignature(MethodHelper* other)
    571       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    572     if (GetDexCache() == other->GetDexCache()) {
    573       const DexFile& dex_file = GetDexFile();
    574       const DexFile::MethodId& mid = dex_file.GetMethodId(method_->GetDexMethodIndex());
    575       const DexFile::MethodId& other_mid =
    576           dex_file.GetMethodId(other->method_->GetDexMethodIndex());
    577       return mid.name_idx_ == other_mid.name_idx_ && mid.proto_idx_ == other_mid.proto_idx_;
    578     }
    579     StringPiece name(GetName());
    580     StringPiece other_name(other->GetName());
    581     return name == other_name && GetSignature() == other->GetSignature();
    582   }
    583 
    584   const DexFile::CodeItem* GetCodeItem()
    585       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    586     return GetDexFile().GetCodeItem(method_->GetCodeItemOffset());
    587   }
    588 
    589   bool IsResolvedTypeIdx(uint16_t type_idx) const
    590       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    591     return method_->GetDexCacheResolvedTypes()->Get(type_idx) != NULL;
    592   }
    593 
    594   mirror::Class* GetClassFromTypeIdx(uint16_t type_idx)
    595       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    596     mirror::Class* type = method_->GetDexCacheResolvedTypes()->Get(type_idx);
    597     if (type == NULL) {
    598       type = GetClassLinker()->ResolveType(type_idx, method_);
    599       CHECK(type != NULL || Thread::Current()->IsExceptionPending());
    600     }
    601     return type;
    602   }
    603 
    604   const char* GetTypeDescriptorFromTypeIdx(uint16_t type_idx)
    605       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    606     const DexFile& dex_file = GetDexFile();
    607     return dex_file.GetTypeDescriptor(dex_file.GetTypeId(type_idx));
    608   }
    609 
    610   mirror::Class* GetDexCacheResolvedType(uint16_t type_idx)
    611       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    612     return method_->GetDexCacheResolvedTypes()->Get(type_idx);
    613   }
    614 
    615   const DexFile& GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    616     const DexFile* result = dex_file_;
    617     if (result == NULL) {
    618       const mirror::DexCache* dex_cache = GetDexCache();
    619       result = dex_file_ = dex_cache->GetDexFile();
    620     }
    621     return *result;
    622   }
    623 
    624   mirror::DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    625     mirror::DexCache* result = dex_cache_;
    626     if (result == NULL) {
    627       mirror::Class* klass = method_->GetDeclaringClass();
    628       result = klass->GetDexCache();
    629       dex_cache_ = result;
    630     }
    631     return result;
    632   }
    633 
    634   mirror::String* ResolveString(uint32_t string_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    635     mirror::String* s = method_->GetDexCacheStrings()->Get(string_idx);
    636     if (UNLIKELY(s == NULL)) {
    637       s = GetClassLinker()->ResolveString(GetDexFile(), string_idx, GetDexCache());
    638     }
    639     return s;
    640   }
    641 
    642  private:
    643   // Set the method_ field, for proxy methods looking up the interface method via the resolved
    644   // methods table.
    645   void SetMethod(const mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    646     if (method != NULL) {
    647       mirror::Class* klass = method->GetDeclaringClass();
    648       if (UNLIKELY(klass->IsProxyClass())) {
    649         mirror::ArtMethod* interface_method =
    650             method->GetDexCacheResolvedMethods()->Get(method->GetDexMethodIndex());
    651         DCHECK(interface_method != NULL);
    652         DCHECK(interface_method == GetClassLinker()->FindMethodForProxy(klass, method));
    653         method = interface_method;
    654       }
    655     }
    656     method_ = method;
    657   }
    658 
    659   ClassLinker* GetClassLinker() {
    660     ClassLinker* result = class_linker_;
    661     if (result == NULL) {
    662       result = Runtime::Current()->GetClassLinker();
    663       class_linker_ = result;
    664     }
    665     return result;
    666   }
    667 
    668   ClassLinker* class_linker_;
    669   mirror::DexCache* dex_cache_;
    670   const DexFile* dex_file_;
    671   const mirror::ArtMethod* method_;
    672   const char* shorty_;
    673   uint32_t shorty_len_;
    674 
    675   DISALLOW_COPY_AND_ASSIGN(MethodHelper);
    676 };
    677 
    678 }  // namespace art
    679 
    680 #endif  // ART_RUNTIME_OBJECT_UTILS_H_
    681