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_ART_METHOD_INL_H_ 18 #define ART_RUNTIME_ART_METHOD_INL_H_ 19 20 #include "art_method.h" 21 22 #include "art_field.h" 23 #include "base/logging.h" 24 #include "dex_file.h" 25 #include "dex_file-inl.h" 26 #include "gc_root-inl.h" 27 #include "mirror/class-inl.h" 28 #include "mirror/dex_cache.h" 29 #include "mirror/object-inl.h" 30 #include "mirror/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 #include "utils.h" 36 37 namespace art { 38 39 inline mirror::Class* ArtMethod::GetDeclaringClassUnchecked() { 40 return declaring_class_.Read(); 41 } 42 43 inline mirror::Class* ArtMethod::GetDeclaringClassNoBarrier() { 44 return declaring_class_.Read<kWithoutReadBarrier>(); 45 } 46 47 inline mirror::Class* ArtMethod::GetDeclaringClass() { 48 mirror::Class* result = GetDeclaringClassUnchecked(); 49 if (kIsDebugBuild) { 50 if (!IsRuntimeMethod()) { 51 CHECK(result != nullptr) << this; 52 CHECK(result->IsIdxLoaded() || result->IsErroneous()) 53 << result->GetStatus() << " " << PrettyClass(result); 54 } else { 55 CHECK(result == nullptr) << this; 56 } 57 } 58 return result; 59 } 60 61 inline void ArtMethod::SetDeclaringClass(mirror::Class* new_declaring_class) { 62 declaring_class_ = GcRoot<mirror::Class>(new_declaring_class); 63 } 64 65 inline uint32_t ArtMethod::GetAccessFlags() { 66 DCHECK(IsRuntimeMethod() || GetDeclaringClass()->IsIdxLoaded() || 67 GetDeclaringClass()->IsErroneous()); 68 return access_flags_; 69 } 70 71 inline uint16_t ArtMethod::GetMethodIndex() { 72 DCHECK(IsRuntimeMethod() || GetDeclaringClass()->IsResolved() || 73 GetDeclaringClass()->IsErroneous()); 74 return method_index_; 75 } 76 77 inline uint16_t ArtMethod::GetMethodIndexDuringLinking() { 78 return method_index_; 79 } 80 81 inline uint32_t ArtMethod::GetDexMethodIndex() { 82 DCHECK(IsRuntimeMethod() || GetDeclaringClass()->IsIdxLoaded() || 83 GetDeclaringClass()->IsErroneous()); 84 return dex_method_index_; 85 } 86 87 inline mirror::PointerArray* ArtMethod::GetDexCacheResolvedMethods() { 88 return dex_cache_resolved_methods_.Read(); 89 } 90 91 inline ArtMethod* ArtMethod::GetDexCacheResolvedMethod(uint16_t method_index, size_t ptr_size) { 92 auto* method = GetDexCacheResolvedMethods()->GetElementPtrSize<ArtMethod*>( 93 method_index, ptr_size); 94 if (LIKELY(method != nullptr)) { 95 auto* declaring_class = method->GetDeclaringClass(); 96 if (LIKELY(declaring_class == nullptr || !declaring_class->IsErroneous())) { 97 return method; 98 } 99 } 100 return nullptr; 101 } 102 103 inline void ArtMethod::SetDexCacheResolvedMethod(uint16_t method_idx, ArtMethod* new_method, 104 size_t ptr_size) { 105 DCHECK(new_method == nullptr || new_method->GetDeclaringClass() != nullptr); 106 GetDexCacheResolvedMethods()->SetElementPtrSize(method_idx, new_method, ptr_size); 107 } 108 109 inline bool ArtMethod::HasDexCacheResolvedMethods() { 110 return GetDexCacheResolvedMethods() != nullptr; 111 } 112 113 inline bool ArtMethod::HasSameDexCacheResolvedMethods(mirror::PointerArray* other_cache) { 114 return GetDexCacheResolvedMethods() == other_cache; 115 } 116 117 inline bool ArtMethod::HasSameDexCacheResolvedMethods(ArtMethod* other) { 118 return GetDexCacheResolvedMethods() == other->GetDexCacheResolvedMethods(); 119 } 120 121 inline mirror::ObjectArray<mirror::Class>* ArtMethod::GetDexCacheResolvedTypes() { 122 return dex_cache_resolved_types_.Read(); 123 } 124 125 template <bool kWithCheck> 126 inline mirror::Class* ArtMethod::GetDexCacheResolvedType(uint32_t type_index) { 127 mirror::Class* klass = kWithCheck ? 128 GetDexCacheResolvedTypes()->Get(type_index) : 129 GetDexCacheResolvedTypes()->GetWithoutChecks(type_index); 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( 138 mirror::ObjectArray<mirror::Class>* other_cache) { 139 return GetDexCacheResolvedTypes() == other_cache; 140 } 141 142 inline bool ArtMethod::HasSameDexCacheResolvedTypes(ArtMethod* other) { 143 return GetDexCacheResolvedTypes() == other->GetDexCacheResolvedTypes(); 144 } 145 146 inline mirror::Class* ArtMethod::GetClassFromTypeIndex(uint16_t type_idx, bool resolve) { 147 mirror::Class* type = GetDexCacheResolvedType(type_idx); 148 if (type == nullptr && resolve) { 149 type = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, this); 150 CHECK(type != nullptr || Thread::Current()->IsExceptionPending()); 151 } 152 return type; 153 } 154 155 inline uint32_t ArtMethod::GetCodeSize() { 156 DCHECK(!IsRuntimeMethod() && !IsProxyMethod()) << PrettyMethod(this); 157 return GetCodeSize(EntryPointToCodePointer(GetEntryPointFromQuickCompiledCode())); 158 } 159 160 inline uint32_t ArtMethod::GetCodeSize(const void* code) { 161 if (code == nullptr) { 162 return 0u; 163 } 164 return reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].code_size_; 165 } 166 167 inline bool ArtMethod::CheckIncompatibleClassChange(InvokeType type) { 168 switch (type) { 169 case kStatic: 170 return !IsStatic(); 171 case kDirect: 172 return !IsDirect() || IsStatic(); 173 case kVirtual: { 174 mirror::Class* methods_class = GetDeclaringClass(); 175 return IsDirect() || (methods_class->IsInterface() && !IsMiranda()); 176 } 177 case kSuper: 178 // Constructors and static methods are called with invoke-direct. 179 // Interface methods cannot be invoked with invoke-super. 180 return IsConstructor() || IsStatic() || GetDeclaringClass()->IsInterface(); 181 case kInterface: { 182 mirror::Class* methods_class = GetDeclaringClass(); 183 return IsDirect() || !(methods_class->IsInterface() || methods_class->IsObjectClass()); 184 } 185 default: 186 LOG(FATAL) << "Unreachable - invocation type: " << type; 187 UNREACHABLE(); 188 } 189 } 190 191 inline uint32_t ArtMethod::GetQuickOatCodeOffset() { 192 DCHECK(!Runtime::Current()->IsStarted()); 193 return PointerToLowMemUInt32(GetEntryPointFromQuickCompiledCode()); 194 } 195 196 inline void ArtMethod::SetQuickOatCodeOffset(uint32_t code_offset) { 197 DCHECK(!Runtime::Current()->IsStarted()); 198 SetEntryPointFromQuickCompiledCode(reinterpret_cast<void*>(code_offset)); 199 } 200 201 inline const uint8_t* ArtMethod::GetMappingTable(size_t pointer_size) { 202 const void* code_pointer = GetQuickOatCodePointer(pointer_size); 203 if (code_pointer == nullptr) { 204 return nullptr; 205 } 206 return GetMappingTable(code_pointer, pointer_size); 207 } 208 209 inline const uint8_t* ArtMethod::GetMappingTable(const void* code_pointer, size_t pointer_size) { 210 DCHECK(code_pointer != nullptr); 211 DCHECK_EQ(code_pointer, GetQuickOatCodePointer(pointer_size)); 212 uint32_t offset = 213 reinterpret_cast<const OatQuickMethodHeader*>(code_pointer)[-1].mapping_table_offset_; 214 if (UNLIKELY(offset == 0u)) { 215 return nullptr; 216 } 217 return reinterpret_cast<const uint8_t*>(code_pointer) - offset; 218 } 219 220 inline const uint8_t* ArtMethod::GetVmapTable(size_t pointer_size) { 221 const void* code_pointer = GetQuickOatCodePointer(pointer_size); 222 if (code_pointer == nullptr) { 223 return nullptr; 224 } 225 return GetVmapTable(code_pointer, pointer_size); 226 } 227 228 inline const uint8_t* ArtMethod::GetVmapTable(const void* code_pointer, size_t pointer_size) { 229 CHECK(!IsOptimized(pointer_size)) << "Unimplemented vmap table for optimized compiler"; 230 DCHECK(code_pointer != nullptr); 231 DCHECK_EQ(code_pointer, GetQuickOatCodePointer(pointer_size)); 232 uint32_t offset = 233 reinterpret_cast<const OatQuickMethodHeader*>(code_pointer)[-1].vmap_table_offset_; 234 if (UNLIKELY(offset == 0u)) { 235 return nullptr; 236 } 237 return reinterpret_cast<const uint8_t*>(code_pointer) - offset; 238 } 239 240 inline CodeInfo ArtMethod::GetOptimizedCodeInfo() { 241 DCHECK(IsOptimized(sizeof(void*))); 242 const void* code_pointer = GetQuickOatCodePointer(sizeof(void*)); 243 DCHECK(code_pointer != nullptr); 244 uint32_t offset = 245 reinterpret_cast<const OatQuickMethodHeader*>(code_pointer)[-1].vmap_table_offset_; 246 const void* data = 247 reinterpret_cast<const void*>(reinterpret_cast<const uint8_t*>(code_pointer) - offset); 248 return CodeInfo(data); 249 } 250 251 inline const uint8_t* ArtMethod::GetNativeGcMap(size_t pointer_size) { 252 const void* code_pointer = GetQuickOatCodePointer(pointer_size); 253 if (code_pointer == nullptr) { 254 return nullptr; 255 } 256 return GetNativeGcMap(code_pointer, pointer_size); 257 } 258 259 inline const uint8_t* ArtMethod::GetNativeGcMap(const void* code_pointer, size_t pointer_size) { 260 DCHECK(code_pointer != nullptr); 261 DCHECK_EQ(code_pointer, GetQuickOatCodePointer(pointer_size)); 262 uint32_t offset = 263 reinterpret_cast<const OatQuickMethodHeader*>(code_pointer)[-1].gc_map_offset_; 264 if (UNLIKELY(offset == 0u)) { 265 return nullptr; 266 } 267 return reinterpret_cast<const uint8_t*>(code_pointer) - offset; 268 } 269 270 inline bool ArtMethod::IsRuntimeMethod() { 271 return dex_method_index_ == DexFile::kDexNoIndex; 272 } 273 274 inline bool ArtMethod::IsCalleeSaveMethod() { 275 if (!IsRuntimeMethod()) { 276 return false; 277 } 278 Runtime* runtime = Runtime::Current(); 279 bool result = false; 280 for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) { 281 if (this == runtime->GetCalleeSaveMethod(Runtime::CalleeSaveType(i))) { 282 result = true; 283 break; 284 } 285 } 286 return result; 287 } 288 289 inline bool ArtMethod::IsResolutionMethod() { 290 bool result = this == Runtime::Current()->GetResolutionMethod(); 291 // Check that if we do think it is phony it looks like the resolution method. 292 DCHECK(!result || IsRuntimeMethod()); 293 return result; 294 } 295 296 inline bool ArtMethod::IsImtConflictMethod() { 297 bool result = this == Runtime::Current()->GetImtConflictMethod(); 298 // Check that if we do think it is phony it looks like the imt conflict method. 299 DCHECK(!result || IsRuntimeMethod()); 300 return result; 301 } 302 303 inline bool ArtMethod::IsImtUnimplementedMethod() { 304 bool result = this == Runtime::Current()->GetImtUnimplementedMethod(); 305 // Check that if we do think it is phony it looks like the imt unimplemented method. 306 DCHECK(!result || IsRuntimeMethod()); 307 return result; 308 } 309 310 inline uintptr_t ArtMethod::NativeQuickPcOffset(const uintptr_t pc) { 311 const void* code = Runtime::Current()->GetInstrumentation()->GetQuickCodeFor( 312 this, sizeof(void*)); 313 return pc - reinterpret_cast<uintptr_t>(code); 314 } 315 316 inline QuickMethodFrameInfo ArtMethod::GetQuickFrameInfo(const void* code_pointer) { 317 DCHECK(code_pointer != nullptr); 318 if (kIsDebugBuild && !IsProxyMethod()) { 319 CHECK_EQ(code_pointer, GetQuickOatCodePointer(sizeof(void*))); 320 } 321 return reinterpret_cast<const OatQuickMethodHeader*>(code_pointer)[-1].frame_info_; 322 } 323 324 inline const DexFile* ArtMethod::GetDexFile() { 325 return GetDexCache()->GetDexFile(); 326 } 327 328 inline const char* ArtMethod::GetDeclaringClassDescriptor() { 329 uint32_t dex_method_idx = GetDexMethodIndex(); 330 if (UNLIKELY(dex_method_idx == DexFile::kDexNoIndex)) { 331 return "<runtime method>"; 332 } 333 DCHECK(!IsProxyMethod()); 334 const DexFile* dex_file = GetDexFile(); 335 return dex_file->GetMethodDeclaringClassDescriptor(dex_file->GetMethodId(dex_method_idx)); 336 } 337 338 inline const char* ArtMethod::GetShorty(uint32_t* out_length) { 339 DCHECK(!IsProxyMethod()); 340 const DexFile* dex_file = GetDexFile(); 341 return dex_file->GetMethodShorty(dex_file->GetMethodId(GetDexMethodIndex()), out_length); 342 } 343 344 inline const Signature ArtMethod::GetSignature() { 345 uint32_t dex_method_idx = GetDexMethodIndex(); 346 if (dex_method_idx != DexFile::kDexNoIndex) { 347 DCHECK(!IsProxyMethod()); 348 const DexFile* dex_file = GetDexFile(); 349 return dex_file->GetMethodSignature(dex_file->GetMethodId(dex_method_idx)); 350 } 351 return Signature::NoSignature(); 352 } 353 354 inline const char* ArtMethod::GetName() { 355 uint32_t dex_method_idx = GetDexMethodIndex(); 356 if (LIKELY(dex_method_idx != DexFile::kDexNoIndex)) { 357 DCHECK(!IsProxyMethod()); 358 const DexFile* dex_file = GetDexFile(); 359 return dex_file->GetMethodName(dex_file->GetMethodId(dex_method_idx)); 360 } 361 Runtime* const runtime = Runtime::Current(); 362 if (this == runtime->GetResolutionMethod()) { 363 return "<runtime internal resolution method>"; 364 } else if (this == runtime->GetImtConflictMethod()) { 365 return "<runtime internal imt conflict method>"; 366 } else if (this == runtime->GetCalleeSaveMethod(Runtime::kSaveAll)) { 367 return "<runtime internal callee-save all registers method>"; 368 } else if (this == runtime->GetCalleeSaveMethod(Runtime::kRefsOnly)) { 369 return "<runtime internal callee-save reference registers method>"; 370 } else if (this == runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs)) { 371 return "<runtime internal callee-save reference and argument registers method>"; 372 } else { 373 return "<unknown runtime internal method>"; 374 } 375 } 376 377 inline const DexFile::CodeItem* ArtMethod::GetCodeItem() { 378 return GetDeclaringClass()->GetDexFile().GetCodeItem(GetCodeItemOffset()); 379 } 380 381 inline bool ArtMethod::IsResolvedTypeIdx(uint16_t type_idx) { 382 DCHECK(!IsProxyMethod()); 383 return GetDexCacheResolvedType(type_idx) != nullptr; 384 } 385 386 inline int32_t ArtMethod::GetLineNumFromDexPC(uint32_t dex_pc) { 387 DCHECK(!IsProxyMethod()); 388 if (dex_pc == DexFile::kDexNoIndex) { 389 return IsNative() ? -2 : -1; 390 } 391 return GetDexFile()->GetLineNumFromPC(this, dex_pc); 392 } 393 394 inline const DexFile::ProtoId& ArtMethod::GetPrototype() { 395 DCHECK(!IsProxyMethod()); 396 const DexFile* dex_file = GetDexFile(); 397 return dex_file->GetMethodPrototype(dex_file->GetMethodId(GetDexMethodIndex())); 398 } 399 400 inline const DexFile::TypeList* ArtMethod::GetParameterTypeList() { 401 DCHECK(!IsProxyMethod()); 402 const DexFile* dex_file = GetDexFile(); 403 const DexFile::ProtoId& proto = dex_file->GetMethodPrototype( 404 dex_file->GetMethodId(GetDexMethodIndex())); 405 return dex_file->GetProtoParameters(proto); 406 } 407 408 inline const char* ArtMethod::GetDeclaringClassSourceFile() { 409 DCHECK(!IsProxyMethod()); 410 return GetDeclaringClass()->GetSourceFile(); 411 } 412 413 inline uint16_t ArtMethod::GetClassDefIndex() { 414 DCHECK(!IsProxyMethod()); 415 return GetDeclaringClass()->GetDexClassDefIndex(); 416 } 417 418 inline const DexFile::ClassDef& ArtMethod::GetClassDef() { 419 DCHECK(!IsProxyMethod()); 420 return GetDexFile()->GetClassDef(GetClassDefIndex()); 421 } 422 423 inline const char* ArtMethod::GetReturnTypeDescriptor() { 424 DCHECK(!IsProxyMethod()); 425 const DexFile* dex_file = GetDexFile(); 426 const DexFile::MethodId& method_id = dex_file->GetMethodId(GetDexMethodIndex()); 427 const DexFile::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id); 428 uint16_t return_type_idx = proto_id.return_type_idx_; 429 return dex_file->GetTypeDescriptor(dex_file->GetTypeId(return_type_idx)); 430 } 431 432 inline const char* ArtMethod::GetTypeDescriptorFromTypeIdx(uint16_t type_idx) { 433 DCHECK(!IsProxyMethod()); 434 const DexFile* dex_file = GetDexFile(); 435 return dex_file->GetTypeDescriptor(dex_file->GetTypeId(type_idx)); 436 } 437 438 inline mirror::ClassLoader* ArtMethod::GetClassLoader() { 439 DCHECK(!IsProxyMethod()); 440 return GetDeclaringClass()->GetClassLoader(); 441 } 442 443 inline mirror::DexCache* ArtMethod::GetDexCache() { 444 DCHECK(!IsProxyMethod()); 445 return GetDeclaringClass()->GetDexCache(); 446 } 447 448 inline bool ArtMethod::IsProxyMethod() { 449 return GetDeclaringClass()->IsProxyClass(); 450 } 451 452 inline ArtMethod* ArtMethod::GetInterfaceMethodIfProxy(size_t pointer_size) { 453 if (LIKELY(!IsProxyMethod())) { 454 return this; 455 } 456 mirror::Class* klass = GetDeclaringClass(); 457 auto interface_method = GetDexCacheResolvedMethods()->GetElementPtrSize<ArtMethod*>( 458 GetDexMethodIndex(), pointer_size); 459 DCHECK(interface_method != nullptr); 460 DCHECK_EQ(interface_method, 461 Runtime::Current()->GetClassLinker()->FindMethodForProxy(klass, this)); 462 return interface_method; 463 } 464 465 inline void ArtMethod::SetDexCacheResolvedMethods(mirror::PointerArray* new_dex_cache_methods) { 466 dex_cache_resolved_methods_ = GcRoot<mirror::PointerArray>(new_dex_cache_methods); 467 } 468 469 inline void ArtMethod::SetDexCacheResolvedTypes( 470 mirror::ObjectArray<mirror::Class>* new_dex_cache_types) { 471 dex_cache_resolved_types_ = GcRoot<mirror::ObjectArray<mirror::Class>>(new_dex_cache_types); 472 } 473 474 inline mirror::Class* ArtMethod::GetReturnType(bool resolve) { 475 DCHECK(!IsProxyMethod()); 476 const DexFile* dex_file = GetDexFile(); 477 const DexFile::MethodId& method_id = dex_file->GetMethodId(GetDexMethodIndex()); 478 const DexFile::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id); 479 uint16_t return_type_idx = proto_id.return_type_idx_; 480 mirror::Class* type = GetDexCacheResolvedType(return_type_idx); 481 if (type == nullptr && resolve) { 482 type = Runtime::Current()->GetClassLinker()->ResolveType(return_type_idx, this); 483 CHECK(type != nullptr || Thread::Current()->IsExceptionPending()); 484 } 485 return type; 486 } 487 488 template<typename RootVisitorType> 489 void ArtMethod::VisitRoots(RootVisitorType& visitor) { 490 visitor.VisitRootIfNonNull(declaring_class_.AddressWithoutBarrier()); 491 visitor.VisitRootIfNonNull(dex_cache_resolved_methods_.AddressWithoutBarrier()); 492 visitor.VisitRootIfNonNull(dex_cache_resolved_types_.AddressWithoutBarrier()); 493 } 494 495 inline void ArtMethod::CopyFrom(const ArtMethod* src, size_t image_pointer_size) { 496 memcpy(reinterpret_cast<void*>(this), reinterpret_cast<const void*>(src), 497 ObjectSize(image_pointer_size)); 498 declaring_class_ = GcRoot<mirror::Class>(const_cast<ArtMethod*>(src)->GetDeclaringClass()); 499 dex_cache_resolved_methods_ = GcRoot<mirror::PointerArray>( 500 const_cast<ArtMethod*>(src)->GetDexCacheResolvedMethods()); 501 dex_cache_resolved_types_ = GcRoot<mirror::ObjectArray<mirror::Class>>( 502 const_cast<ArtMethod*>(src)->GetDexCacheResolvedTypes()); 503 } 504 505 } // namespace art 506 507 #endif // ART_RUNTIME_ART_METHOD_INL_H_ 508