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 
GetMethodIndexDuringLinking()72 inline uint16_t ArtMethod::GetMethodIndexDuringLinking() {
73   return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_));
74 }
75 
GetDexMethodIndex()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 
GetDexCacheResolvedMethods()86 inline ObjectArray<ArtMethod>* ArtMethod::GetDexCacheResolvedMethods() {
87   return GetFieldObject<ObjectArray<ArtMethod>>(
88       OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_methods_));
89 }
90 
GetDexCacheResolvedMethod(uint16_t method_index)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 
SetDexCacheResolvedMethod(uint16_t method_idx,ArtMethod * new_method)100 inline void ArtMethod::SetDexCacheResolvedMethod(uint16_t method_idx, ArtMethod* new_method) {
101   GetDexCacheResolvedMethods()->Set<false>(method_idx, new_method);
102 }
103 
HasDexCacheResolvedMethods()104 inline bool ArtMethod::HasDexCacheResolvedMethods() {
105   return GetDexCacheResolvedMethods() != nullptr;
106 }
107 
HasSameDexCacheResolvedMethods(ObjectArray<ArtMethod> * other_cache)108 inline bool ArtMethod::HasSameDexCacheResolvedMethods(ObjectArray<ArtMethod>* other_cache) {
109   return GetDexCacheResolvedMethods() == other_cache;
110 }
111 
HasSameDexCacheResolvedMethods(ArtMethod * other)112 inline bool ArtMethod::HasSameDexCacheResolvedMethods(ArtMethod* other) {
113   return GetDexCacheResolvedMethods() == other->GetDexCacheResolvedMethods();
114 }
115 
116 
GetDexCacheResolvedTypes()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>
GetDexCacheResolvedType(uint32_t type_index)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 
HasDexCacheResolvedTypes()133 inline bool ArtMethod::HasDexCacheResolvedTypes() {
134   return GetDexCacheResolvedTypes() != nullptr;
135 }
136 
HasSameDexCacheResolvedTypes(ObjectArray<Class> * other_cache)137 inline bool ArtMethod::HasSameDexCacheResolvedTypes(ObjectArray<Class>* other_cache) {
138   return GetDexCacheResolvedTypes() == other_cache;
139 }
140 
HasSameDexCacheResolvedTypes(ArtMethod * other)141 inline bool ArtMethod::HasSameDexCacheResolvedTypes(ArtMethod* other) {
142   return GetDexCacheResolvedTypes() == other->GetDexCacheResolvedTypes();
143 }
144 
GetCodeSize()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 
CheckIncompatibleClassChange(InvokeType type)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 
AssertPcIsWithinQuickCode(uintptr_t pc)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 
GetQuickOatCodeOffset()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)
GetPortableOatCodeOffset()211 inline uint32_t ArtMethod::GetPortableOatCodeOffset() {
212   DCHECK(!Runtime::Current()->IsStarted());
213   return PointerToLowMemUInt32(GetEntryPointFromPortableCompiledCode());
214 }
215 #endif
216 
SetQuickOatCodeOffset(uint32_t code_offset)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)
SetPortableOatCodeOffset(uint32_t code_offset)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 
GetQuickOatEntryPoint(size_t pointer_size)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 
GetQuickOatCodePointer(size_t pointer_size)246 inline const void* ArtMethod::GetQuickOatCodePointer(size_t pointer_size) {
247   return EntryPointToCodePointer(GetQuickOatEntryPoint(pointer_size));
248 }
249 
GetMappingTable(size_t pointer_size)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 
GetMappingTable(const void * code_pointer,size_t pointer_size)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 
GetVmapTable(size_t pointer_size)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 
GetVmapTable(const void * code_pointer,size_t pointer_size)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 
GetNativeGcMap(size_t pointer_size)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 
GetNativeGcMap(const void * code_pointer,size_t pointer_size)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 
IsRuntimeMethod()307 inline bool ArtMethod::IsRuntimeMethod() {
308   return GetDexMethodIndex() == DexFile::kDexNoIndex;
309 }
310 
IsCalleeSaveMethod()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 
IsResolutionMethod()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 
IsImtConflictMethod()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 
IsImtUnimplementedMethod()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 
NativePcOffset(const uintptr_t pc)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 
NativePcOffset(const uintptr_t pc,const void * quick_entry_point)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 
GetQuickFrameInfo()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 
GetQuickFrameInfo(const void * code_pointer)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 
GetDexFile()412 inline const DexFile* ArtMethod::GetDexFile() {
413   return GetDexCache()->GetDexFile();
414 }
415 
GetDeclaringClassDescriptor()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 
GetShorty(uint32_t * out_length)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 
GetSignature()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 
GetName()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 
GetCodeItem()465 inline const DexFile::CodeItem* ArtMethod::GetCodeItem() {
466   mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
467   return method->GetDexFile()->GetCodeItem(method->GetCodeItemOffset());
468 }
469 
IsResolvedTypeIdx(uint16_t type_idx)470 inline bool ArtMethod::IsResolvedTypeIdx(uint16_t type_idx) {
471   mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
472   return method->GetDexCacheResolvedType(type_idx) != nullptr;
473 }
474 
GetLineNumFromDexPC(uint32_t dex_pc)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 
GetPrototype()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 
GetParameterTypeList()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 
GetDeclaringClassSourceFile()497 inline const char* ArtMethod::GetDeclaringClassSourceFile() {
498   return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetSourceFile();
499 }
500 
GetClassDefIndex()501 inline uint16_t ArtMethod::GetClassDefIndex() {
502   return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexClassDefIndex();
503 }
504 
GetClassDef()505 inline const DexFile::ClassDef& ArtMethod::GetClassDef() {
506   mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
507   return method->GetDexFile()->GetClassDef(GetClassDefIndex());
508 }
509 
GetReturnTypeDescriptor()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 
GetTypeDescriptorFromTypeIdx(uint16_t type_idx)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 
GetClassLoader()525 inline mirror::ClassLoader* ArtMethod::GetClassLoader() {
526   return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetClassLoader();
527 }
528 
GetDexCache()529 inline mirror::DexCache* ArtMethod::GetDexCache() {
530   return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexCache();
531 }
532 
IsProxyMethod()533 inline bool ArtMethod::IsProxyMethod() {
534   return GetDeclaringClass()->IsProxyClass();
535 }
536 
GetInterfaceMethodIfProxy()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 
SetDexCacheResolvedMethods(ObjectArray<ArtMethod> * new_dex_cache_methods)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 
SetDexCacheResolvedTypes(ObjectArray<Class> * new_dex_cache_classes)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 
CheckObjectSizeEqualsMirrorSize()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