• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ClassSize()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>
GetJavaLangReflectArtMethod()45 inline Class* ArtMethod::GetJavaLangReflectArtMethod() {
46   DCHECK(!java_lang_reflect_ArtMethod_.IsNull());
47   return java_lang_reflect_ArtMethod_.Read<kReadBarrierOption>();
48 }
49 
GetDeclaringClass()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 
SetDeclaringClass(Class * new_declaring_class)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 
GetAccessFlags()62 inline uint32_t ArtMethod::GetAccessFlags() {
63   DCHECK(GetDeclaringClass()->IsIdxLoaded() || GetDeclaringClass()->IsErroneous());
64   return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, access_flags_));
65 }
66 
GetMethodIndex()67 inline uint16_t ArtMethod::GetMethodIndex() {
68   DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous());
69   return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_));
70 }
71 
GetDexMethodIndex()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 
GetDexCacheStrings()82 inline ObjectArray<String>* ArtMethod::GetDexCacheStrings() {
83   return GetFieldObject<ObjectArray<String>>(
84       OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_strings_));
85 }
86 
GetDexCacheResolvedMethods()87 inline ObjectArray<ArtMethod>* ArtMethod::GetDexCacheResolvedMethods() {
88   return GetFieldObject<ObjectArray<ArtMethod>>(
89       OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_methods_));
90 }
91 
GetDexCacheResolvedMethod(uint16_t method_index)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 
SetDexCacheResolvedMethod(uint16_t method_idx,ArtMethod * new_method)101 inline void ArtMethod::SetDexCacheResolvedMethod(uint16_t method_idx, ArtMethod* new_method) {
102   GetDexCacheResolvedMethods()->Set<false>(method_idx, new_method);
103 }
104 
HasDexCacheResolvedMethods()105 inline bool ArtMethod::HasDexCacheResolvedMethods() {
106   return GetDexCacheResolvedMethods() != nullptr;
107 }
108 
HasSameDexCacheResolvedMethods(ObjectArray<ArtMethod> * other_cache)109 inline bool ArtMethod::HasSameDexCacheResolvedMethods(ObjectArray<ArtMethod>* other_cache) {
110   return GetDexCacheResolvedMethods() == other_cache;
111 }
112 
HasSameDexCacheResolvedMethods(ArtMethod * other)113 inline bool ArtMethod::HasSameDexCacheResolvedMethods(ArtMethod* other) {
114   return GetDexCacheResolvedMethods() == other->GetDexCacheResolvedMethods();
115 }
116 
117 
GetDexCacheResolvedTypes()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>
GetDexCacheResolvedType(uint32_t type_index)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 
HasDexCacheResolvedTypes()134 inline bool ArtMethod::HasDexCacheResolvedTypes() {
135   return GetDexCacheResolvedTypes() != nullptr;
136 }
137 
HasSameDexCacheResolvedTypes(ObjectArray<Class> * other_cache)138 inline bool ArtMethod::HasSameDexCacheResolvedTypes(ObjectArray<Class>* other_cache) {
139   return GetDexCacheResolvedTypes() == other_cache;
140 }
141 
HasSameDexCacheResolvedTypes(ArtMethod * other)142 inline bool ArtMethod::HasSameDexCacheResolvedTypes(ArtMethod* other) {
143   return GetDexCacheResolvedTypes() == other->GetDexCacheResolvedTypes();
144 }
145 
GetCodeSize()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 
CheckIncompatibleClassChange(InvokeType type)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 
AssertPcIsWithinQuickCode(uintptr_t pc)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 
GetQuickOatCodeOffset()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)
GetPortableOatCodeOffset()212 inline uint32_t ArtMethod::GetPortableOatCodeOffset() {
213   DCHECK(!Runtime::Current()->IsStarted());
214   return PointerToLowMemUInt32(GetEntryPointFromPortableCompiledCode());
215 }
216 #endif
217 
SetQuickOatCodeOffset(uint32_t code_offset)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)
SetPortableOatCodeOffset(uint32_t code_offset)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 
GetQuickOatEntryPoint()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 
GetQuickOatCodePointer()247 inline const void* ArtMethod::GetQuickOatCodePointer() {
248   return EntryPointToCodePointer(GetQuickOatEntryPoint());
249 }
250 
GetMappingTable()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 
GetMappingTable(const void * code_pointer)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 
GetVmapTable()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 
GetVmapTable(const void * code_pointer)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 
SetOatNativeGcMapOffset(uint32_t gc_map_offset)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 
GetOatNativeGcMapOffset()294 inline uint32_t ArtMethod::GetOatNativeGcMapOffset() {
295   DCHECK(!Runtime::Current()->IsStarted());
296   return PointerToLowMemUInt32(GetNativeGcMap());
297 }
298 
IsRuntimeMethod()299 inline bool ArtMethod::IsRuntimeMethod() {
300   return GetDexMethodIndex() == DexFile::kDexNoIndex;
301 }
302 
IsCalleeSaveMethod()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 
IsResolutionMethod()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 
IsImtConflictMethod()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 
NativePcOffset(const uintptr_t pc)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 
NativePcOffset(const uintptr_t pc,const void * quick_entry_point)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>
SetNativeMethod(const void * native_method)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 
GetQuickFrameInfo()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 
GetQuickFrameInfo(const void * code_pointer)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 
GetDexFile()401 inline const DexFile* ArtMethod::GetDexFile() {
402   return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexCache()->GetDexFile();
403 }
404 
GetDeclaringClassDescriptor()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 
GetShorty(uint32_t * out_length)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 
GetSignature()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 
GetName()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 
GetCodeItem()454 inline const DexFile::CodeItem* ArtMethod::GetCodeItem() {
455   mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
456   return method->GetDexFile()->GetCodeItem(method->GetCodeItemOffset());
457 }
458 
IsResolvedTypeIdx(uint16_t type_idx)459 inline bool ArtMethod::IsResolvedTypeIdx(uint16_t type_idx) {
460   mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
461   return method->GetDexCacheResolvedType(type_idx) != nullptr;
462 }
463 
GetLineNumFromDexPC(uint32_t dex_pc)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 
GetPrototype()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 
GetParameterTypeList()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 
GetDeclaringClassSourceFile()486 inline const char* ArtMethod::GetDeclaringClassSourceFile() {
487   return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetSourceFile();
488 }
489 
GetClassDefIndex()490 inline uint16_t ArtMethod::GetClassDefIndex() {
491   return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexClassDefIndex();
492 }
493 
GetClassDef()494 inline const DexFile::ClassDef& ArtMethod::GetClassDef() {
495   mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
496   return method->GetDexFile()->GetClassDef(GetClassDefIndex());
497 }
498 
GetReturnTypeDescriptor()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 
GetTypeDescriptorFromTypeIdx(uint16_t type_idx)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 
GetClassLoader()514 inline mirror::ClassLoader* ArtMethod::GetClassLoader() {
515   return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetClassLoader();
516 }
517 
GetDexCache()518 inline mirror::DexCache* ArtMethod::GetDexCache() {
519   return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexCache();
520 }
521 
GetInterfaceMethodIfProxy()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