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