art_method-inl.h revision 63bc11efaac0c041e849ab401f9fc368631a00f5
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 36namespace art { 37namespace mirror { 38 39inline uint32_t ArtMethod::ClassSize() { 40 uint32_t vtable_entries = Object::kVTableLength + 8; 41 return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0); 42} 43 44template<ReadBarrierOption kReadBarrierOption> 45inline Class* ArtMethod::GetJavaLangReflectArtMethod() { 46 DCHECK(!java_lang_reflect_ArtMethod_.IsNull()); 47 return java_lang_reflect_ArtMethod_.Read<kReadBarrierOption>(); 48} 49 50inline 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 57inline void ArtMethod::SetDeclaringClass(Class *new_declaring_class) { 58 SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, declaring_class_), 59 new_declaring_class); 60} 61 62inline uint32_t ArtMethod::GetAccessFlags() { 63 DCHECK(GetDeclaringClass()->IsIdxLoaded() || GetDeclaringClass()->IsErroneous()); 64 return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, access_flags_)); 65} 66 67inline uint16_t ArtMethod::GetMethodIndex() { 68 DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous()); 69 return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_)); 70} 71 72inline 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 82inline ObjectArray<String>* ArtMethod::GetDexCacheStrings() { 83 return GetFieldObject<ObjectArray<String>>( 84 OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_strings_)); 85} 86 87inline ObjectArray<ArtMethod>* ArtMethod::GetDexCacheResolvedMethods() { 88 return GetFieldObject<ObjectArray<ArtMethod>>( 89 OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_methods_)); 90} 91 92inline 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 101inline void ArtMethod::SetDexCacheResolvedMethod(uint16_t method_idx, ArtMethod* new_method) { 102 GetDexCacheResolvedMethods()->Set<false>(method_idx, new_method); 103} 104 105inline bool ArtMethod::HasDexCacheResolvedMethods() { 106 return GetDexCacheResolvedMethods() != nullptr; 107} 108 109inline bool ArtMethod::HasSameDexCacheResolvedMethods(ObjectArray<ArtMethod>* other_cache) { 110 return GetDexCacheResolvedMethods() == other_cache; 111} 112 113inline bool ArtMethod::HasSameDexCacheResolvedMethods(ArtMethod* other) { 114 return GetDexCacheResolvedMethods() == other->GetDexCacheResolvedMethods(); 115} 116 117 118inline ObjectArray<Class>* ArtMethod::GetDexCacheResolvedTypes() { 119 return GetFieldObject<ObjectArray<Class>>( 120 OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_types_)); 121} 122 123template <bool kWithCheck> 124inline 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 134inline bool ArtMethod::HasDexCacheResolvedTypes() { 135 return GetDexCacheResolvedTypes() != nullptr; 136} 137 138inline bool ArtMethod::HasSameDexCacheResolvedTypes(ObjectArray<Class>* other_cache) { 139 return GetDexCacheResolvedTypes() == other_cache; 140} 141 142inline bool ArtMethod::HasSameDexCacheResolvedTypes(ArtMethod* other) { 143 return GetDexCacheResolvedTypes() == other->GetDexCacheResolvedTypes(); 144} 145 146inline 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 155inline 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 179inline 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 205inline uint32_t ArtMethod::GetQuickOatCodeOffset() { 206 DCHECK(!Runtime::Current()->IsStarted()); 207 return PointerToLowMemUInt32(GetEntryPointFromQuickCompiledCode()); 208} 209 210 211#if defined(ART_USE_PORTABLE_COMPILER) 212inline uint32_t ArtMethod::GetPortableOatCodeOffset() { 213 DCHECK(!Runtime::Current()->IsStarted()); 214 return PointerToLowMemUInt32(GetEntryPointFromPortableCompiledCode()); 215} 216#endif 217 218inline 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) 224inline void ArtMethod::SetPortableOatCodeOffset(uint32_t code_offset) { 225 DCHECK(!Runtime::Current()->IsStarted()); 226 SetEntryPointFromPortableCompiledCode(reinterpret_cast<void*>(code_offset)); 227} 228#endif 229 230inline 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 247inline const void* ArtMethod::GetQuickOatCodePointer() { 248 return EntryPointToCodePointer(GetQuickOatEntryPoint()); 249} 250 251inline 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 259inline 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 270inline 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 278inline 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 289inline void ArtMethod::SetOatNativeGcMapOffset(uint32_t gc_map_offset) { 290 DCHECK(!Runtime::Current()->IsStarted()); 291 SetNativeGcMap(reinterpret_cast<uint8_t*>(gc_map_offset)); 292} 293 294inline uint32_t ArtMethod::GetOatNativeGcMapOffset() { 295 DCHECK(!Runtime::Current()->IsStarted()); 296 return PointerToLowMemUInt32(GetNativeGcMap()); 297} 298 299inline bool ArtMethod::IsRuntimeMethod() { 300 return GetDexMethodIndex() == DexFile::kDexNoIndex; 301} 302 303inline 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 318inline 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 325inline 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 332inline 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 337inline 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 343template<VerifyObjectFlags kVerifyFlags> 344inline 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 349inline 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 395inline 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 401inline const DexFile* ArtMethod::GetDexFile() { 402 return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexCache()->GetDexFile(); 403} 404 405inline 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 415inline 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 421inline 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 431inline 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 454inline const DexFile::CodeItem* ArtMethod::GetCodeItem() { 455 mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); 456 return method->GetDexFile()->GetCodeItem(method->GetCodeItemOffset()); 457} 458 459inline bool ArtMethod::IsResolvedTypeIdx(uint16_t type_idx) { 460 mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); 461 return method->GetDexCacheResolvedType(type_idx) != nullptr; 462} 463 464inline 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 472inline 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 478inline 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 486inline const char* ArtMethod::GetDeclaringClassSourceFile() { 487 return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetSourceFile(); 488} 489 490inline uint16_t ArtMethod::GetClassDefIndex() { 491 return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexClassDefIndex(); 492} 493 494inline const DexFile::ClassDef& ArtMethod::GetClassDef() { 495 mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); 496 return method->GetDexFile()->GetClassDef(GetClassDefIndex()); 497} 498 499inline 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 508inline 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 514inline mirror::ClassLoader* ArtMethod::GetClassLoader() { 515 return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetClassLoader(); 516} 517 518inline mirror::DexCache* ArtMethod::GetDexCache() { 519 return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexCache(); 520} 521 522inline 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