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