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