art_method-inl.h revision 94f7b49578b6aaa80de8ffed230648d601393905
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 "class_linker.h" 23#include "dex_cache.h" 24#include "dex_file.h" 25#include "entrypoints/entrypoint_utils.h" 26#include "method_helper.h" 27#include "object-inl.h" 28#include "object_array.h" 29#include "oat.h" 30#include "quick/quick_method_frame_info.h" 31#include "read_barrier-inl.h" 32#include "runtime-inl.h" 33 34namespace art { 35namespace mirror { 36 37inline uint32_t ArtMethod::ClassSize() { 38 uint32_t vtable_entries = Object::kVTableLength + 8; 39 return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0); 40} 41 42template<ReadBarrierOption kReadBarrierOption> 43inline Class* ArtMethod::GetJavaLangReflectArtMethod() { 44 DCHECK(!java_lang_reflect_ArtMethod_.IsNull()); 45 return java_lang_reflect_ArtMethod_.Read<kReadBarrierOption>(); 46} 47 48inline Class* ArtMethod::GetDeclaringClass() { 49 Class* result = GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, declaring_class_)); 50 DCHECK(result != NULL) << this; 51 DCHECK(result->IsIdxLoaded() || result->IsErroneous()) << this; 52 return result; 53} 54 55inline void ArtMethod::SetDeclaringClass(Class *new_declaring_class) { 56 SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, declaring_class_), 57 new_declaring_class); 58} 59 60inline uint32_t ArtMethod::GetAccessFlags() { 61 DCHECK(GetDeclaringClass()->IsIdxLoaded() || GetDeclaringClass()->IsErroneous()); 62 return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, access_flags_)); 63} 64 65inline uint16_t ArtMethod::GetMethodIndex() { 66 DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous()); 67 return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_)); 68} 69 70inline uint32_t ArtMethod::GetDexMethodIndex() { 71#ifdef ART_SEA_IR_MODE 72 // TODO: Re-add this check for (PORTABLE + SMALL + ) SEA IR when PORTABLE IS fixed! 73 // DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous()); 74#else 75 DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous()); 76#endif 77 return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_method_index_)); 78} 79 80inline ObjectArray<String>* ArtMethod::GetDexCacheStrings() { 81 return GetFieldObject<ObjectArray<String>>( 82 OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_strings_)); 83} 84 85inline ObjectArray<ArtMethod>* ArtMethod::GetDexCacheResolvedMethods() { 86 return GetFieldObject<ObjectArray<ArtMethod>>( 87 OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_methods_)); 88} 89 90inline ObjectArray<Class>* ArtMethod::GetDexCacheResolvedTypes() { 91 return GetFieldObject<ObjectArray<Class>>( 92 OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_types_)); 93} 94 95inline uint32_t ArtMethod::GetCodeSize() { 96 DCHECK(!IsRuntimeMethod() && !IsProxyMethod()) << PrettyMethod(this); 97 const void* code = EntryPointToCodePointer(GetEntryPointFromQuickCompiledCode()); 98 if (code == nullptr) { 99 return 0u; 100 } 101 return reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].code_size_; 102} 103 104inline bool ArtMethod::CheckIncompatibleClassChange(InvokeType type) { 105 switch (type) { 106 case kStatic: 107 return !IsStatic(); 108 case kDirect: 109 return !IsDirect() || IsStatic(); 110 case kVirtual: { 111 Class* methods_class = GetDeclaringClass(); 112 return IsDirect() || (methods_class->IsInterface() && !IsMiranda()); 113 } 114 case kSuper: 115 return false; // TODO: appropriate checks for call to super class. 116 case kInterface: { 117 Class* methods_class = GetDeclaringClass(); 118 return IsDirect() || !(methods_class->IsInterface() || methods_class->IsObjectClass()); 119 } 120 default: 121 LOG(FATAL) << "Unreachable - invocation type: " << type; 122 return true; 123 } 124} 125 126inline void ArtMethod::AssertPcIsWithinQuickCode(uintptr_t pc) { 127 if (!kIsDebugBuild) { 128 return; 129 } 130 if (IsNative() || IsRuntimeMethod() || IsProxyMethod()) { 131 return; 132 } 133 if (pc == GetQuickInstrumentationExitPc()) { 134 return; 135 } 136 const void* code = GetEntryPointFromQuickCompiledCode(); 137 if (code == GetQuickToInterpreterBridge() || code == GetQuickInstrumentationEntryPoint()) { 138 return; 139 } 140 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 141 if (code == class_linker->GetQuickResolutionTrampoline() || 142 code == class_linker->GetQuickToInterpreterBridgeTrampoline()) { 143 return; 144 } 145 DCHECK(IsWithinQuickCode(pc)) 146 << PrettyMethod(this) 147 << " pc=" << std::hex << pc 148 << " code=" << code 149 << " size=" << GetCodeSize(); 150} 151 152inline uint32_t ArtMethod::GetQuickOatCodeOffset() { 153 DCHECK(!Runtime::Current()->IsStarted()); 154 return PointerToLowMemUInt32(GetEntryPointFromQuickCompiledCode()); 155} 156 157inline uint32_t ArtMethod::GetPortableOatCodeOffset() { 158 DCHECK(!Runtime::Current()->IsStarted()); 159 return PointerToLowMemUInt32(GetEntryPointFromPortableCompiledCode()); 160} 161 162inline void ArtMethod::SetQuickOatCodeOffset(uint32_t code_offset) { 163 DCHECK(!Runtime::Current()->IsStarted()); 164 SetEntryPointFromQuickCompiledCode(reinterpret_cast<void*>(code_offset)); 165} 166 167inline void ArtMethod::SetPortableOatCodeOffset(uint32_t code_offset) { 168 DCHECK(!Runtime::Current()->IsStarted()); 169 SetEntryPointFromPortableCompiledCode(reinterpret_cast<void*>(code_offset)); 170} 171 172inline const void* ArtMethod::GetQuickOatEntryPoint() { 173 if (IsPortableCompiled() || IsAbstract() || IsRuntimeMethod() || IsProxyMethod()) { 174 return nullptr; 175 } 176 Runtime* runtime = Runtime::Current(); 177 const void* entry_point = runtime->GetInstrumentation()->GetQuickCodeFor(this); 178 // On failure, instead of nullptr we get the quick-generic-jni-trampoline for native method 179 // indicating the generic JNI, or the quick-to-interpreter-bridge (but not the trampoline) 180 // for non-native methods. 181 DCHECK(entry_point != runtime->GetClassLinker()->GetQuickToInterpreterBridgeTrampoline()); 182 if (UNLIKELY(entry_point == GetQuickToInterpreterBridge()) || 183 UNLIKELY(entry_point == runtime->GetClassLinker()->GetQuickGenericJniTrampoline())) { 184 return nullptr; 185 } 186 return entry_point; 187} 188 189inline const void* ArtMethod::GetQuickOatCodePointer() { 190 return EntryPointToCodePointer(GetQuickOatEntryPoint()); 191} 192 193inline const uint8_t* ArtMethod::GetMappingTable() { 194 const void* code_pointer = GetQuickOatCodePointer(); 195 if (code_pointer == nullptr) { 196 return nullptr; 197 } 198 return GetMappingTable(code_pointer); 199} 200 201inline const uint8_t* ArtMethod::GetMappingTable(const void* code_pointer) { 202 DCHECK(code_pointer != nullptr); 203 DCHECK(code_pointer == GetQuickOatCodePointer()); 204 uint32_t offset = 205 reinterpret_cast<const OatQuickMethodHeader*>(code_pointer)[-1].mapping_table_offset_; 206 if (UNLIKELY(offset == 0u)) { 207 return nullptr; 208 } 209 return reinterpret_cast<const uint8_t*>(code_pointer) - offset; 210} 211 212inline const uint8_t* ArtMethod::GetVmapTable() { 213 const void* code_pointer = GetQuickOatCodePointer(); 214 if (code_pointer == nullptr) { 215 return nullptr; 216 } 217 return GetVmapTable(code_pointer); 218} 219 220inline const uint8_t* ArtMethod::GetVmapTable(const void* code_pointer) { 221 DCHECK(code_pointer != nullptr); 222 DCHECK(code_pointer == GetQuickOatCodePointer()); 223 uint32_t offset = 224 reinterpret_cast<const OatQuickMethodHeader*>(code_pointer)[-1].vmap_table_offset_; 225 if (UNLIKELY(offset == 0u)) { 226 return nullptr; 227 } 228 return reinterpret_cast<const uint8_t*>(code_pointer) - offset; 229} 230 231inline void ArtMethod::SetOatNativeGcMapOffset(uint32_t gc_map_offset) { 232 DCHECK(!Runtime::Current()->IsStarted()); 233 SetNativeGcMap(reinterpret_cast<uint8_t*>(gc_map_offset)); 234} 235 236inline uint32_t ArtMethod::GetOatNativeGcMapOffset() { 237 DCHECK(!Runtime::Current()->IsStarted()); 238 return PointerToLowMemUInt32(GetNativeGcMap()); 239} 240 241inline bool ArtMethod::IsRuntimeMethod() { 242 return GetDexMethodIndex() == DexFile::kDexNoIndex; 243} 244 245inline bool ArtMethod::IsCalleeSaveMethod() { 246 if (!IsRuntimeMethod()) { 247 return false; 248 } 249 Runtime* runtime = Runtime::Current(); 250 bool result = false; 251 for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) { 252 if (this == runtime->GetCalleeSaveMethod(Runtime::CalleeSaveType(i))) { 253 result = true; 254 break; 255 } 256 } 257 return result; 258} 259 260inline bool ArtMethod::IsResolutionMethod() { 261 bool result = this == Runtime::Current()->GetResolutionMethod(); 262 // Check that if we do think it is phony it looks like the resolution method. 263 DCHECK(!result || IsRuntimeMethod()); 264 return result; 265} 266 267inline bool ArtMethod::IsImtConflictMethod() { 268 bool result = this == Runtime::Current()->GetImtConflictMethod(); 269 // Check that if we do think it is phony it looks like the imt conflict method. 270 DCHECK(!result || IsRuntimeMethod()); 271 return result; 272} 273 274inline uintptr_t ArtMethod::NativePcOffset(const uintptr_t pc) { 275 const void* code = Runtime::Current()->GetInstrumentation()->GetQuickCodeFor(this); 276 return pc - reinterpret_cast<uintptr_t>(code); 277} 278 279inline uintptr_t ArtMethod::NativePcOffset(const uintptr_t pc, const void* quick_entry_point) { 280 DCHECK(quick_entry_point != GetQuickToInterpreterBridge()); 281 DCHECK(quick_entry_point == Runtime::Current()->GetInstrumentation()->GetQuickCodeFor(this)); 282 return pc - reinterpret_cast<uintptr_t>(quick_entry_point); 283} 284 285template<VerifyObjectFlags kVerifyFlags> 286inline void ArtMethod::SetNativeMethod(const void* native_method) { 287 SetFieldPtr<false, true, kVerifyFlags>( 288 OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_jni_), native_method); 289} 290 291inline QuickMethodFrameInfo ArtMethod::GetQuickFrameInfo() { 292 if (UNLIKELY(IsPortableCompiled())) { 293 // Portable compiled dex bytecode or jni stub. 294 return QuickMethodFrameInfo(kStackAlignment, 0u, 0u); 295 } 296 Runtime* runtime = Runtime::Current(); 297 if (UNLIKELY(IsAbstract()) || UNLIKELY(IsProxyMethod())) { 298 return runtime->GetCalleeSaveMethodFrameInfo(Runtime::kRefsAndArgs); 299 } 300 if (UNLIKELY(IsRuntimeMethod())) { 301 return runtime->GetRuntimeMethodFrameInfo(this); 302 } 303 304 const void* entry_point = runtime->GetInstrumentation()->GetQuickCodeFor(this); 305 // On failure, instead of nullptr we get the quick-generic-jni-trampoline for native method 306 // indicating the generic JNI, or the quick-to-interpreter-bridge (but not the trampoline) 307 // for non-native methods. And we really shouldn't see a failure for non-native methods here. 308 DCHECK(entry_point != runtime->GetClassLinker()->GetQuickToInterpreterBridgeTrampoline()); 309 CHECK(entry_point != GetQuickToInterpreterBridge()); 310 311 if (UNLIKELY(entry_point == runtime->GetClassLinker()->GetQuickGenericJniTrampoline())) { 312 // Generic JNI frame. 313 DCHECK(IsNative()); 314 StackHandleScope<1> hs(Thread::Current()); 315 uint32_t handle_refs = 316 MethodHelper(hs.NewHandle(this)).GetNumberOfReferenceArgsWithoutReceiver() + 1; 317 size_t scope_size = HandleScope::SizeOf(handle_refs); 318 QuickMethodFrameInfo callee_info = runtime->GetCalleeSaveMethodFrameInfo(Runtime::kRefsAndArgs); 319 320 // Callee saves + handle scope + method ref + alignment 321 size_t frame_size = RoundUp(callee_info.FrameSizeInBytes() + scope_size 322 - kPointerSize // callee-save frame stores a whole method pointer 323 + sizeof(StackReference<mirror::ArtMethod>), 324 kStackAlignment); 325 326 return QuickMethodFrameInfo(frame_size, callee_info.CoreSpillMask(), callee_info.FpSpillMask()); 327 } 328 329 const void* code_pointer = EntryPointToCodePointer(entry_point); 330 return GetQuickFrameInfo(code_pointer); 331} 332 333inline QuickMethodFrameInfo ArtMethod::GetQuickFrameInfo(const void* code_pointer) { 334 DCHECK(code_pointer != nullptr); 335 DCHECK_EQ(code_pointer, GetQuickOatCodePointer()); 336 return reinterpret_cast<const OatQuickMethodHeader*>(code_pointer)[-1].frame_info_; 337} 338 339inline const DexFile* ArtMethod::GetDexFile() { 340 return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexCache()->GetDexFile(); 341} 342 343inline const char* ArtMethod::GetDeclaringClassDescriptor() { 344 mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); 345 uint32_t dex_method_idx = method->GetDexMethodIndex(); 346 if (UNLIKELY(dex_method_idx == DexFile::kDexNoIndex)) { 347 return "<runtime method>"; 348 } 349 const DexFile* dex_file = method->GetDexFile(); 350 return dex_file->GetMethodDeclaringClassDescriptor(dex_file->GetMethodId(dex_method_idx)); 351} 352 353inline const char* ArtMethod::GetShorty(uint32_t* out_length) { 354 mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); 355 const DexFile* dex_file = method->GetDexFile(); 356 return dex_file->GetMethodShorty(dex_file->GetMethodId(method->GetDexMethodIndex()), out_length); 357} 358 359inline const Signature ArtMethod::GetSignature() { 360 mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); 361 uint32_t dex_method_idx = method->GetDexMethodIndex(); 362 if (dex_method_idx != DexFile::kDexNoIndex) { 363 const DexFile* dex_file = method->GetDexFile(); 364 return dex_file->GetMethodSignature(dex_file->GetMethodId(dex_method_idx)); 365 } 366 return Signature::NoSignature(); 367} 368 369inline const char* ArtMethod::GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 370 mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); 371 uint32_t dex_method_idx = method->GetDexMethodIndex(); 372 if (LIKELY(dex_method_idx != DexFile::kDexNoIndex)) { 373 const DexFile* dex_file = method->GetDexFile(); 374 return dex_file->GetMethodName(dex_file->GetMethodId(dex_method_idx)); 375 } 376 Runtime* runtime = Runtime::Current(); 377 if (method == runtime->GetResolutionMethod()) { 378 return "<runtime internal resolution method>"; 379 } else if (method == runtime->GetImtConflictMethod()) { 380 return "<runtime internal imt conflict method>"; 381 } else if (method == runtime->GetCalleeSaveMethod(Runtime::kSaveAll)) { 382 return "<runtime internal callee-save all registers method>"; 383 } else if (method == runtime->GetCalleeSaveMethod(Runtime::kRefsOnly)) { 384 return "<runtime internal callee-save reference registers method>"; 385 } else if (method == runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs)) { 386 return "<runtime internal callee-save reference and argument registers method>"; 387 } else { 388 return "<unknown runtime internal method>"; 389 } 390} 391 392inline const DexFile::CodeItem* ArtMethod::GetCodeItem() { 393 mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); 394 return method->GetDexFile()->GetCodeItem(method->GetCodeItemOffset()); 395} 396 397inline bool ArtMethod::IsResolvedTypeIdx(uint16_t type_idx) { 398 mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); 399 return method->GetDexCacheResolvedTypes()->Get(type_idx) != nullptr; 400} 401 402inline int32_t ArtMethod::GetLineNumFromDexPC(uint32_t dex_pc) { 403 mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); 404 if (dex_pc == DexFile::kDexNoIndex) { 405 return method->IsNative() ? -2 : -1; 406 } 407 return method->GetDexFile()->GetLineNumFromPC(method, dex_pc); 408} 409 410inline const DexFile::ProtoId& ArtMethod::GetPrototype() { 411 mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); 412 const DexFile* dex_file = method->GetDexFile(); 413 return dex_file->GetMethodPrototype(dex_file->GetMethodId(method->GetDexMethodIndex())); 414} 415 416inline const DexFile::TypeList* ArtMethod::GetParameterTypeList() { 417 mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); 418 const DexFile* dex_file = method->GetDexFile(); 419 const DexFile::ProtoId& proto = dex_file->GetMethodPrototype( 420 dex_file->GetMethodId(method->GetDexMethodIndex())); 421 return dex_file->GetProtoParameters(proto); 422} 423 424inline const char* ArtMethod::GetDeclaringClassSourceFile() { 425 return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetSourceFile(); 426} 427 428inline uint16_t ArtMethod::GetClassDefIndex() { 429 return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexClassDefIndex(); 430} 431 432inline const DexFile::ClassDef& ArtMethod::GetClassDef() { 433 mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); 434 return method->GetDexFile()->GetClassDef(GetClassDefIndex()); 435} 436 437inline const char* ArtMethod::GetReturnTypeDescriptor() { 438 mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); 439 const DexFile* dex_file = method->GetDexFile(); 440 const DexFile::MethodId& method_id = dex_file->GetMethodId(method->GetDexMethodIndex()); 441 const DexFile::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id); 442 uint16_t return_type_idx = proto_id.return_type_idx_; 443 return dex_file->GetTypeDescriptor(dex_file->GetTypeId(return_type_idx)); 444} 445 446inline const char* ArtMethod::GetTypeDescriptorFromTypeIdx(uint16_t type_idx) { 447 mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); 448 const DexFile* dex_file = method->GetDexFile(); 449 return dex_file->GetTypeDescriptor(dex_file->GetTypeId(type_idx)); 450} 451 452inline mirror::ClassLoader* ArtMethod::GetClassLoader() { 453 return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetClassLoader(); 454} 455 456inline mirror::DexCache* ArtMethod::GetDexCache() { 457 return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexCache(); 458} 459 460inline ArtMethod* ArtMethod::GetInterfaceMethodIfProxy() { 461 mirror::Class* klass = GetDeclaringClass(); 462 if (LIKELY(!klass->IsProxyClass())) { 463 return this; 464 } 465 mirror::ArtMethod* interface_method = GetDexCacheResolvedMethods()->Get(GetDexMethodIndex()); 466 DCHECK(interface_method != nullptr); 467 DCHECK_EQ(interface_method, 468 Runtime::Current()->GetClassLinker()->FindMethodForProxy(klass, this)); 469 return interface_method; 470} 471 472} // namespace mirror 473} // namespace art 474 475#endif // ART_RUNTIME_MIRROR_ART_METHOD_INL_H_ 476