Home | History | Annotate | Download | only in mirror
      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_MIRROR_ART_METHOD_INL_H_
     18 #define ART_RUNTIME_MIRROR_ART_METHOD_INL_H_
     19 
     20 #include "art_method.h"
     21 
     22 #include "art_field.h"
     23 #include "class.h"
     24 #include "class_linker.h"
     25 #include "dex_cache.h"
     26 #include "dex_file.h"
     27 #include "entrypoints/entrypoint_utils.h"
     28 #include "method_helper.h"
     29 #include "object-inl.h"
     30 #include "object_array.h"
     31 #include "oat.h"
     32 #include "quick/quick_method_frame_info.h"
     33 #include "read_barrier-inl.h"
     34 #include "runtime-inl.h"
     35 
     36 namespace art {
     37 namespace mirror {
     38 
     39 inline uint32_t ArtMethod::ClassSize() {
     40   uint32_t vtable_entries = Object::kVTableLength + 8;
     41   return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0);
     42 }
     43 
     44 template<ReadBarrierOption kReadBarrierOption>
     45 inline Class* ArtMethod::GetJavaLangReflectArtMethod() {
     46   DCHECK(!java_lang_reflect_ArtMethod_.IsNull());
     47   return java_lang_reflect_ArtMethod_.Read<kReadBarrierOption>();
     48 }
     49 
     50 inline Class* ArtMethod::GetDeclaringClass() {
     51   Class* result = GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, declaring_class_));
     52   DCHECK(result != NULL) << this;
     53   DCHECK(result->IsIdxLoaded() || result->IsErroneous()) << this;
     54   return result;
     55 }
     56 
     57 inline void ArtMethod::SetDeclaringClass(Class *new_declaring_class) {
     58   SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, declaring_class_),
     59                         new_declaring_class);
     60 }
     61 
     62 inline uint32_t ArtMethod::GetAccessFlags() {
     63   DCHECK(GetDeclaringClass()->IsIdxLoaded() || GetDeclaringClass()->IsErroneous());
     64   return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, access_flags_));
     65 }
     66 
     67 inline uint16_t ArtMethod::GetMethodIndex() {
     68   DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous());
     69   return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_));
     70 }
     71 
     72 inline uint32_t ArtMethod::GetDexMethodIndex() {
     73 #ifdef ART_SEA_IR_MODE
     74   // TODO: Re-add this check for (PORTABLE + SMALL + ) SEA IR when PORTABLE IS fixed!
     75   // DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
     76 #else
     77   DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
     78 #endif
     79   return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_method_index_));
     80 }
     81 
     82 inline ObjectArray<String>* ArtMethod::GetDexCacheStrings() {
     83   return GetFieldObject<ObjectArray<String>>(
     84       OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_strings_));
     85 }
     86 
     87 inline ObjectArray<ArtMethod>* ArtMethod::GetDexCacheResolvedMethods() {
     88   return GetFieldObject<ObjectArray<ArtMethod>>(
     89       OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_methods_));
     90 }
     91 
     92 inline ArtMethod* ArtMethod::GetDexCacheResolvedMethod(uint16_t method_index) {
     93   ArtMethod* method = GetDexCacheResolvedMethods()->Get(method_index);
     94   if (method != nullptr && !method->GetDeclaringClass()->IsErroneous()) {
     95     return method;
     96   } else {
     97     return nullptr;
     98   }
     99 }
    100 
    101 inline void ArtMethod::SetDexCacheResolvedMethod(uint16_t method_idx, ArtMethod* new_method) {
    102   GetDexCacheResolvedMethods()->Set<false>(method_idx, new_method);
    103 }
    104 
    105 inline bool ArtMethod::HasDexCacheResolvedMethods() {
    106   return GetDexCacheResolvedMethods() != nullptr;
    107 }
    108 
    109 inline bool ArtMethod::HasSameDexCacheResolvedMethods(ObjectArray<ArtMethod>* other_cache) {
    110   return GetDexCacheResolvedMethods() == other_cache;
    111 }
    112 
    113 inline bool ArtMethod::HasSameDexCacheResolvedMethods(ArtMethod* other) {
    114   return GetDexCacheResolvedMethods() == other->GetDexCacheResolvedMethods();
    115 }
    116 
    117 
    118 inline ObjectArray<Class>* ArtMethod::GetDexCacheResolvedTypes() {
    119   return GetFieldObject<ObjectArray<Class>>(
    120       OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_types_));
    121 }
    122 
    123 template <bool kWithCheck>
    124 inline Class* ArtMethod::GetDexCacheResolvedType(uint32_t type_index) {
    125   Class* klass;
    126   if (kWithCheck) {
    127     klass = GetDexCacheResolvedTypes()->Get(type_index);
    128   } else {
    129     klass = GetDexCacheResolvedTypes()->GetWithoutChecks(type_index);
    130   }
    131   return (klass != nullptr && !klass->IsErroneous()) ? klass : nullptr;
    132 }
    133 
    134 inline bool ArtMethod::HasDexCacheResolvedTypes() {
    135   return GetDexCacheResolvedTypes() != nullptr;
    136 }
    137 
    138 inline bool ArtMethod::HasSameDexCacheResolvedTypes(ObjectArray<Class>* other_cache) {
    139   return GetDexCacheResolvedTypes() == other_cache;
    140 }
    141 
    142 inline bool ArtMethod::HasSameDexCacheResolvedTypes(ArtMethod* other) {
    143   return GetDexCacheResolvedTypes() == other->GetDexCacheResolvedTypes();
    144 }
    145 
    146 inline uint32_t ArtMethod::GetCodeSize() {
    147   DCHECK(!IsRuntimeMethod() && !IsProxyMethod()) << PrettyMethod(this);
    148   const void* code = EntryPointToCodePointer(GetEntryPointFromQuickCompiledCode());
    149   if (code == nullptr) {
    150     return 0u;
    151   }
    152   return reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].code_size_;
    153 }
    154 
    155 inline bool ArtMethod::CheckIncompatibleClassChange(InvokeType type) {
    156   switch (type) {
    157     case kStatic:
    158       return !IsStatic();
    159     case kDirect:
    160       return !IsDirect() || IsStatic();
    161     case kVirtual: {
    162       Class* methods_class = GetDeclaringClass();
    163       return IsDirect() || (methods_class->IsInterface() && !IsMiranda());
    164     }
    165     case kSuper:
    166       // Constructors and static methods are called with invoke-direct.
    167       // Interface methods cannot be invoked with invoke-super.
    168       return IsConstructor() || IsStatic() || GetDeclaringClass()->IsInterface();
    169     case kInterface: {
    170       Class* methods_class = GetDeclaringClass();
    171       return IsDirect() || !(methods_class->IsInterface() || methods_class->IsObjectClass());
    172     }
    173     default:
    174       LOG(FATAL) << "Unreachable - invocation type: " << type;
    175       return true;
    176   }
    177 }
    178 
    179 inline void ArtMethod::AssertPcIsWithinQuickCode(uintptr_t pc) {
    180   if (!kIsDebugBuild) {
    181     return;
    182   }
    183   if (IsNative() || IsRuntimeMethod() || IsProxyMethod()) {
    184     return;
    185   }
    186   if (pc == GetQuickInstrumentationExitPc()) {
    187     return;
    188   }
    189   const void* code = GetEntryPointFromQuickCompiledCode();
    190   if (code == GetQuickToInterpreterBridge() || code == GetQuickInstrumentationEntryPoint()) {
    191     return;
    192   }
    193   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    194   if (code == class_linker->GetQuickResolutionTrampoline() ||
    195       code == class_linker->GetQuickToInterpreterBridgeTrampoline()) {
    196     return;
    197   }
    198   DCHECK(IsWithinQuickCode(pc))
    199       << PrettyMethod(this)
    200       << " pc=" << std::hex << pc
    201       << " code=" << code
    202       << " size=" << GetCodeSize();
    203 }
    204 
    205 inline uint32_t ArtMethod::GetQuickOatCodeOffset() {
    206   DCHECK(!Runtime::Current()->IsStarted());
    207   return PointerToLowMemUInt32(GetEntryPointFromQuickCompiledCode());
    208 }
    209 
    210 
    211 #if defined(ART_USE_PORTABLE_COMPILER)
    212 inline uint32_t ArtMethod::GetPortableOatCodeOffset() {
    213   DCHECK(!Runtime::Current()->IsStarted());
    214   return PointerToLowMemUInt32(GetEntryPointFromPortableCompiledCode());
    215 }
    216 #endif
    217 
    218 inline void ArtMethod::SetQuickOatCodeOffset(uint32_t code_offset) {
    219   DCHECK(!Runtime::Current()->IsStarted());
    220   SetEntryPointFromQuickCompiledCode(reinterpret_cast<void*>(code_offset));
    221 }
    222 
    223 #if defined(ART_USE_PORTABLE_COMPILER)
    224 inline void ArtMethod::SetPortableOatCodeOffset(uint32_t code_offset) {
    225   DCHECK(!Runtime::Current()->IsStarted());
    226   SetEntryPointFromPortableCompiledCode(reinterpret_cast<void*>(code_offset));
    227 }
    228 #endif
    229 
    230 inline const void* ArtMethod::GetQuickOatEntryPoint() {
    231   if (IsPortableCompiled() || IsAbstract() || IsRuntimeMethod() || IsProxyMethod()) {
    232     return nullptr;
    233   }
    234   Runtime* runtime = Runtime::Current();
    235   const void* entry_point = runtime->GetInstrumentation()->GetQuickCodeFor(this);
    236   // On failure, instead of nullptr we get the quick-generic-jni-trampoline for native method
    237   // indicating the generic JNI, or the quick-to-interpreter-bridge (but not the trampoline)
    238   // for non-native methods.
    239   DCHECK(entry_point != runtime->GetClassLinker()->GetQuickToInterpreterBridgeTrampoline());
    240   if (UNLIKELY(entry_point == GetQuickToInterpreterBridge()) ||
    241       UNLIKELY(entry_point == runtime->GetClassLinker()->GetQuickGenericJniTrampoline())) {
    242     return nullptr;
    243   }
    244   return entry_point;
    245 }
    246 
    247 inline const void* ArtMethod::GetQuickOatCodePointer() {
    248   return EntryPointToCodePointer(GetQuickOatEntryPoint());
    249 }
    250 
    251 inline const uint8_t* ArtMethod::GetMappingTable() {
    252   const void* code_pointer = GetQuickOatCodePointer();
    253   if (code_pointer == nullptr) {
    254     return nullptr;
    255   }
    256   return GetMappingTable(code_pointer);
    257 }
    258 
    259 inline const uint8_t* ArtMethod::GetMappingTable(const void* code_pointer) {
    260   DCHECK(code_pointer != nullptr);
    261   DCHECK(code_pointer == GetQuickOatCodePointer());
    262   uint32_t offset =
    263       reinterpret_cast<const OatQuickMethodHeader*>(code_pointer)[-1].mapping_table_offset_;
    264   if (UNLIKELY(offset == 0u)) {
    265     return nullptr;
    266   }
    267   return reinterpret_cast<const uint8_t*>(code_pointer) - offset;
    268 }
    269 
    270 inline const uint8_t* ArtMethod::GetVmapTable() {
    271   const void* code_pointer = GetQuickOatCodePointer();
    272   if (code_pointer == nullptr) {
    273     return nullptr;
    274   }
    275   return GetVmapTable(code_pointer);
    276 }
    277 
    278 inline const uint8_t* ArtMethod::GetVmapTable(const void* code_pointer) {
    279   DCHECK(code_pointer != nullptr);
    280   DCHECK(code_pointer == GetQuickOatCodePointer());
    281   uint32_t offset =
    282       reinterpret_cast<const OatQuickMethodHeader*>(code_pointer)[-1].vmap_table_offset_;
    283   if (UNLIKELY(offset == 0u)) {
    284     return nullptr;
    285   }
    286   return reinterpret_cast<const uint8_t*>(code_pointer) - offset;
    287 }
    288 
    289 inline void ArtMethod::SetOatNativeGcMapOffset(uint32_t gc_map_offset) {
    290   DCHECK(!Runtime::Current()->IsStarted());
    291   SetNativeGcMap(reinterpret_cast<uint8_t*>(gc_map_offset));
    292 }
    293 
    294 inline uint32_t ArtMethod::GetOatNativeGcMapOffset() {
    295   DCHECK(!Runtime::Current()->IsStarted());
    296   return PointerToLowMemUInt32(GetNativeGcMap());
    297 }
    298 
    299 inline bool ArtMethod::IsRuntimeMethod() {
    300   return GetDexMethodIndex() == DexFile::kDexNoIndex;
    301 }
    302 
    303 inline bool ArtMethod::IsCalleeSaveMethod() {
    304   if (!IsRuntimeMethod()) {
    305     return false;
    306   }
    307   Runtime* runtime = Runtime::Current();
    308   bool result = false;
    309   for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
    310     if (this == runtime->GetCalleeSaveMethod(Runtime::CalleeSaveType(i))) {
    311       result = true;
    312       break;
    313     }
    314   }
    315   return result;
    316 }
    317 
    318 inline bool ArtMethod::IsResolutionMethod() {
    319   bool result = this == Runtime::Current()->GetResolutionMethod();
    320   // Check that if we do think it is phony it looks like the resolution method.
    321   DCHECK(!result || IsRuntimeMethod());
    322   return result;
    323 }
    324 
    325 inline bool ArtMethod::IsImtConflictMethod() {
    326   bool result = this == Runtime::Current()->GetImtConflictMethod();
    327   // Check that if we do think it is phony it looks like the imt conflict method.
    328   DCHECK(!result || IsRuntimeMethod());
    329   return result;
    330 }
    331 
    332 inline uintptr_t ArtMethod::NativePcOffset(const uintptr_t pc) {
    333   const void* code = Runtime::Current()->GetInstrumentation()->GetQuickCodeFor(this);
    334   return pc - reinterpret_cast<uintptr_t>(code);
    335 }
    336 
    337 inline uintptr_t ArtMethod::NativePcOffset(const uintptr_t pc, const void* quick_entry_point) {
    338   DCHECK(quick_entry_point != GetQuickToInterpreterBridge());
    339   DCHECK(quick_entry_point == Runtime::Current()->GetInstrumentation()->GetQuickCodeFor(this));
    340   return pc - reinterpret_cast<uintptr_t>(quick_entry_point);
    341 }
    342 
    343 template<VerifyObjectFlags kVerifyFlags>
    344 inline void ArtMethod::SetNativeMethod(const void* native_method) {
    345   SetFieldPtr<false, true, kVerifyFlags>(
    346       OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_jni_), native_method);
    347 }
    348 
    349 inline QuickMethodFrameInfo ArtMethod::GetQuickFrameInfo() {
    350   if (UNLIKELY(IsPortableCompiled())) {
    351     // Portable compiled dex bytecode or jni stub.
    352     return QuickMethodFrameInfo(kStackAlignment, 0u, 0u);
    353   }
    354   Runtime* runtime = Runtime::Current();
    355   // For Proxy method we exclude direct method (there is only one direct method - constructor).
    356   // Direct method is cloned from original java.lang.reflect.Proxy class together with code
    357   // and as a result it is executed as usual quick compiled method without any stubs.
    358   // So the frame info should be returned as it is a quick method not a stub.
    359   if (UNLIKELY(IsAbstract()) || UNLIKELY(IsProxyMethod() && !IsDirect())) {
    360     return runtime->GetCalleeSaveMethodFrameInfo(Runtime::kRefsAndArgs);
    361   }
    362   if (UNLIKELY(IsRuntimeMethod())) {
    363     return runtime->GetRuntimeMethodFrameInfo(this);
    364   }
    365 
    366   const void* entry_point = runtime->GetInstrumentation()->GetQuickCodeFor(this);
    367   // On failure, instead of nullptr we get the quick-generic-jni-trampoline for native method
    368   // indicating the generic JNI, or the quick-to-interpreter-bridge (but not the trampoline)
    369   // for non-native methods. And we really shouldn't see a failure for non-native methods here.
    370   DCHECK(entry_point != runtime->GetClassLinker()->GetQuickToInterpreterBridgeTrampoline());
    371   CHECK(entry_point != GetQuickToInterpreterBridge());
    372 
    373   if (UNLIKELY(entry_point == runtime->GetClassLinker()->GetQuickGenericJniTrampoline())) {
    374     // Generic JNI frame.
    375     DCHECK(IsNative());
    376     StackHandleScope<1> hs(Thread::Current());
    377     uint32_t handle_refs =
    378         MethodHelper(hs.NewHandle(this)).GetNumberOfReferenceArgsWithoutReceiver() + 1;
    379     size_t scope_size = HandleScope::SizeOf(handle_refs);
    380     QuickMethodFrameInfo callee_info = runtime->GetCalleeSaveMethodFrameInfo(Runtime::kRefsAndArgs);
    381 
    382     // Callee saves + handle scope + method ref + alignment
    383     size_t frame_size = RoundUp(callee_info.FrameSizeInBytes() + scope_size
    384                                 - kPointerSize  // callee-save frame stores a whole method pointer
    385                                 + sizeof(StackReference<mirror::ArtMethod>),
    386                                 kStackAlignment);
    387 
    388     return QuickMethodFrameInfo(frame_size, callee_info.CoreSpillMask(), callee_info.FpSpillMask());
    389   }
    390 
    391   const void* code_pointer = EntryPointToCodePointer(entry_point);
    392   return GetQuickFrameInfo(code_pointer);
    393 }
    394 
    395 inline QuickMethodFrameInfo ArtMethod::GetQuickFrameInfo(const void* code_pointer) {
    396   DCHECK(code_pointer != nullptr);
    397   DCHECK_EQ(code_pointer, GetQuickOatCodePointer());
    398   return reinterpret_cast<const OatQuickMethodHeader*>(code_pointer)[-1].frame_info_;
    399 }
    400 
    401 inline const DexFile* ArtMethod::GetDexFile() {
    402   return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexCache()->GetDexFile();
    403 }
    404 
    405 inline const char* ArtMethod::GetDeclaringClassDescriptor() {
    406   mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
    407   uint32_t dex_method_idx = method->GetDexMethodIndex();
    408   if (UNLIKELY(dex_method_idx == DexFile::kDexNoIndex)) {
    409     return "<runtime method>";
    410   }
    411   const DexFile* dex_file = method->GetDexFile();
    412   return dex_file->GetMethodDeclaringClassDescriptor(dex_file->GetMethodId(dex_method_idx));
    413 }
    414 
    415 inline const char* ArtMethod::GetShorty(uint32_t* out_length) {
    416   mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
    417   const DexFile* dex_file = method->GetDexFile();
    418   return dex_file->GetMethodShorty(dex_file->GetMethodId(method->GetDexMethodIndex()), out_length);
    419 }
    420 
    421 inline const Signature ArtMethod::GetSignature() {
    422   mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
    423   uint32_t dex_method_idx = method->GetDexMethodIndex();
    424   if (dex_method_idx != DexFile::kDexNoIndex) {
    425     const DexFile* dex_file = method->GetDexFile();
    426     return dex_file->GetMethodSignature(dex_file->GetMethodId(dex_method_idx));
    427   }
    428   return Signature::NoSignature();
    429 }
    430 
    431 inline const char* ArtMethod::GetName() {
    432   mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
    433   uint32_t dex_method_idx = method->GetDexMethodIndex();
    434   if (LIKELY(dex_method_idx != DexFile::kDexNoIndex)) {
    435     const DexFile* dex_file = method->GetDexFile();
    436     return dex_file->GetMethodName(dex_file->GetMethodId(dex_method_idx));
    437   }
    438   Runtime* runtime = Runtime::Current();
    439   if (method == runtime->GetResolutionMethod()) {
    440     return "<runtime internal resolution method>";
    441   } else if (method == runtime->GetImtConflictMethod()) {
    442     return "<runtime internal imt conflict method>";
    443   } else if (method == runtime->GetCalleeSaveMethod(Runtime::kSaveAll)) {
    444     return "<runtime internal callee-save all registers method>";
    445   } else if (method == runtime->GetCalleeSaveMethod(Runtime::kRefsOnly)) {
    446     return "<runtime internal callee-save reference registers method>";
    447   } else if (method == runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs)) {
    448     return "<runtime internal callee-save reference and argument registers method>";
    449   } else {
    450     return "<unknown runtime internal method>";
    451   }
    452 }
    453 
    454 inline const DexFile::CodeItem* ArtMethod::GetCodeItem() {
    455   mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
    456   return method->GetDexFile()->GetCodeItem(method->GetCodeItemOffset());
    457 }
    458 
    459 inline bool ArtMethod::IsResolvedTypeIdx(uint16_t type_idx) {
    460   mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
    461   return method->GetDexCacheResolvedType(type_idx) != nullptr;
    462 }
    463 
    464 inline int32_t ArtMethod::GetLineNumFromDexPC(uint32_t dex_pc) {
    465   mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
    466   if (dex_pc == DexFile::kDexNoIndex) {
    467     return method->IsNative() ? -2 : -1;
    468   }
    469   return method->GetDexFile()->GetLineNumFromPC(method, dex_pc);
    470 }
    471 
    472 inline const DexFile::ProtoId& ArtMethod::GetPrototype() {
    473   mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
    474   const DexFile* dex_file = method->GetDexFile();
    475   return dex_file->GetMethodPrototype(dex_file->GetMethodId(method->GetDexMethodIndex()));
    476 }
    477 
    478 inline const DexFile::TypeList* ArtMethod::GetParameterTypeList() {
    479   mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
    480   const DexFile* dex_file = method->GetDexFile();
    481   const DexFile::ProtoId& proto = dex_file->GetMethodPrototype(
    482       dex_file->GetMethodId(method->GetDexMethodIndex()));
    483   return dex_file->GetProtoParameters(proto);
    484 }
    485 
    486 inline const char* ArtMethod::GetDeclaringClassSourceFile() {
    487   return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetSourceFile();
    488 }
    489 
    490 inline uint16_t ArtMethod::GetClassDefIndex() {
    491   return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexClassDefIndex();
    492 }
    493 
    494 inline const DexFile::ClassDef& ArtMethod::GetClassDef() {
    495   mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
    496   return method->GetDexFile()->GetClassDef(GetClassDefIndex());
    497 }
    498 
    499 inline const char* ArtMethod::GetReturnTypeDescriptor() {
    500   mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
    501   const DexFile* dex_file = method->GetDexFile();
    502   const DexFile::MethodId& method_id = dex_file->GetMethodId(method->GetDexMethodIndex());
    503   const DexFile::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id);
    504   uint16_t return_type_idx = proto_id.return_type_idx_;
    505   return dex_file->GetTypeDescriptor(dex_file->GetTypeId(return_type_idx));
    506 }
    507 
    508 inline const char* ArtMethod::GetTypeDescriptorFromTypeIdx(uint16_t type_idx) {
    509   mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
    510   const DexFile* dex_file = method->GetDexFile();
    511   return dex_file->GetTypeDescriptor(dex_file->GetTypeId(type_idx));
    512 }
    513 
    514 inline mirror::ClassLoader* ArtMethod::GetClassLoader() {
    515   return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetClassLoader();
    516 }
    517 
    518 inline mirror::DexCache* ArtMethod::GetDexCache() {
    519   return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexCache();
    520 }
    521 
    522 inline ArtMethod* ArtMethod::GetInterfaceMethodIfProxy() {
    523   mirror::Class* klass = GetDeclaringClass();
    524   if (LIKELY(!klass->IsProxyClass())) {
    525     return this;
    526   }
    527   mirror::ArtMethod* interface_method = GetDexCacheResolvedMethods()->Get(GetDexMethodIndex());
    528   DCHECK(interface_method != nullptr);
    529   DCHECK_EQ(interface_method,
    530             Runtime::Current()->GetClassLinker()->FindMethodForProxy(klass, this));
    531   return interface_method;
    532 }
    533 
    534 }  // namespace mirror
    535 }  // namespace art
    536 
    537 #endif  // ART_RUNTIME_MIRROR_ART_METHOD_INL_H_
    538