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 "base/callee_save_type.h" 23 #include "class_linker-inl.h" 24 #include "common_throws.h" 25 #include "dex/code_item_accessors-inl.h" 26 #include "dex/dex_file-inl.h" 27 #include "dex/dex_file_annotations.h" 28 #include "dex/dex_file_types.h" 29 #include "dex/invoke_type.h" 30 #include "dex/primitive.h" 31 #include "dex/signature.h" 32 #include "gc_root-inl.h" 33 #include "imtable-inl.h" 34 #include "jit/jit.h" 35 #include "jit/jit_code_cache-inl.h" 36 #include "jit/jit_options.h" 37 #include "mirror/class-inl.h" 38 #include "mirror/dex_cache-inl.h" 39 #include "mirror/object-inl.h" 40 #include "mirror/object_array.h" 41 #include "mirror/string.h" 42 #include "obj_ptr-inl.h" 43 #include "quick/quick_method_frame_info.h" 44 #include "read_barrier-inl.h" 45 #include "runtime-inl.h" 46 #include "thread-current-inl.h" 47 48 namespace art HIDDEN { 49 50 namespace detail { 51 52 template <> struct ShortyTraits<'V'> { 53 using Type = void; 54 static Type Get([[maybe_unused]] const JValue& value) {} 55 // `kVRegCount` and `Set()` are not defined. 56 }; 57 58 template <> struct ShortyTraits<'Z'> { 59 // Despite using `uint8_t` for `boolean` in `JValue`, we shall use `bool` here. 60 using Type = bool; 61 static Type Get(const JValue& value) { return value.GetZ() != 0u; } 62 static constexpr size_t kVRegCount = 1u; 63 static void Set(uint32_t* args, Type value) { args[0] = static_cast<uint32_t>(value ? 1u : 0u); } 64 }; 65 66 template <> struct ShortyTraits<'B'> { 67 using Type = int8_t; 68 static Type Get(const JValue& value) { return value.GetB(); } 69 static constexpr size_t kVRegCount = 1u; 70 static void Set(uint32_t* args, Type value) { args[0] = static_cast<uint32_t>(value); } 71 }; 72 73 template <> struct ShortyTraits<'C'> { 74 using Type = uint16_t; 75 static Type Get(const JValue& value) { return value.GetC(); } 76 static constexpr size_t kVRegCount = 1u; 77 static void Set(uint32_t* args, Type value) { args[0] = static_cast<uint32_t>(value); } 78 }; 79 80 template <> struct ShortyTraits<'S'> { 81 using Type = int16_t; 82 static Type Get(const JValue& value) { return value.GetS(); } 83 static constexpr size_t kVRegCount = 1u; 84 static void Set(uint32_t* args, Type value) { args[0] = static_cast<uint32_t>(value); } 85 }; 86 87 template <> struct ShortyTraits<'I'> { 88 using Type = int32_t; 89 static Type Get(const JValue& value) { return value.GetI(); } 90 static constexpr size_t kVRegCount = 1u; 91 static void Set(uint32_t* args, Type value) { args[0] = static_cast<uint32_t>(value); } 92 }; 93 94 template <> struct ShortyTraits<'J'> { 95 using Type = int64_t; 96 static Type Get(const JValue& value) { return value.GetJ(); } 97 static constexpr size_t kVRegCount = 2u; 98 static void Set(uint32_t* args, Type value) { 99 // Little-endian representation. 100 args[0] = static_cast<uint32_t>(value); 101 args[1] = static_cast<uint32_t>(static_cast<uint64_t>(value) >> 32); 102 } 103 }; 104 105 template <> struct ShortyTraits<'F'> { 106 using Type = float; 107 static Type Get(const JValue& value) { return value.GetF(); } 108 static constexpr size_t kVRegCount = 1u; 109 static void Set(uint32_t* args, Type value) { args[0] = bit_cast<uint32_t>(value); } 110 }; 111 112 template <> struct ShortyTraits<'D'> { 113 using Type = double; 114 static Type Get(const JValue& value) { return value.GetD(); } 115 static constexpr size_t kVRegCount = 2u; 116 static void Set(uint32_t* args, Type value) { 117 // Little-endian representation. 118 uint64_t v = bit_cast<uint64_t>(value); 119 args[0] = static_cast<uint32_t>(v); 120 args[1] = static_cast<uint32_t>(v >> 32); 121 } 122 }; 123 124 template <> struct ShortyTraits<'L'> { 125 using Type = ObjPtr<mirror::Object>; 126 static Type Get(const JValue& value) REQUIRES_SHARED(Locks::mutator_lock_) { 127 return value.GetL(); 128 } 129 static constexpr size_t kVRegCount = 1u; 130 static void Set(uint32_t* args, Type value) REQUIRES_SHARED(Locks::mutator_lock_) { 131 args[0] = StackReference<mirror::Object>::FromMirrorPtr(value.Ptr()).AsVRegValue(); 132 } 133 }; 134 135 template <char... Shorty> 136 constexpr auto MaterializeShorty() { 137 constexpr size_t kSize = std::size({Shorty...}) + 1u; 138 return std::array<char, kSize>{Shorty..., '\0'}; 139 } 140 141 template <char... ArgType> 142 constexpr size_t NumberOfVRegs() { 143 constexpr size_t kArgVRegCount[] = { 144 ShortyTraits<ArgType>::kVRegCount... 145 }; 146 size_t sum = 0u; 147 for (size_t count : kArgVRegCount) { 148 sum += count; 149 } 150 return sum; 151 } 152 153 template <char FirstArgType, char... ArgType> 154 inline ALWAYS_INLINE void FillVRegs(uint32_t* vregs, 155 typename ShortyTraits<FirstArgType>::Type first_arg, 156 typename ShortyTraits<ArgType>::Type... args) 157 REQUIRES_SHARED(Locks::mutator_lock_) { 158 ShortyTraits<FirstArgType>::Set(vregs, first_arg); 159 if constexpr (sizeof...(args) > 0) 160 FillVRegs<ArgType...>(vregs + ShortyTraits<FirstArgType>::kVRegCount, args...); 161 } 162 163 template <char... ArgType> 164 inline ALWAYS_INLINE auto MaterializeVRegs(typename ShortyTraits<ArgType>::Type... args) 165 REQUIRES_SHARED(Locks::mutator_lock_) { 166 constexpr size_t kNumVRegs = NumberOfVRegs<ArgType...>(); 167 std::array<uint32_t, kNumVRegs> vregs; 168 if constexpr (sizeof...(args) > 0) 169 FillVRegs<ArgType...>(vregs.data(), args...); 170 return vregs; 171 } 172 173 } // namespace detail 174 175 template <char ReturnType, char... ArgType> 176 inline typename detail::ShortyTraits<ReturnType>::Type 177 ArtMethod::InvokeStatic(Thread* self, typename detail::ShortyTraits<ArgType>::Type... args) { 178 DCHECK(IsStatic()); 179 DCHECK(GetDeclaringClass()->IsInitialized()); // Used only for initialized well-known classes. 180 JValue result; 181 constexpr auto shorty = detail::MaterializeShorty<ReturnType, ArgType...>(); 182 auto vregs = detail::MaterializeVRegs<ArgType...>(args...); 183 Invoke(self, 184 vregs.empty() ? nullptr : vregs.data(), 185 vregs.size() * sizeof(typename decltype(vregs)::value_type), 186 &result, 187 shorty.data()); 188 return detail::ShortyTraits<ReturnType>::Get(result); 189 } 190 191 template <char ReturnType, char... ArgType> 192 typename detail::ShortyTraits<ReturnType>::Type 193 ArtMethod::InvokeInstance(Thread* self, 194 ObjPtr<mirror::Object> receiver, 195 typename detail::ShortyTraits<ArgType>::Type... args) { 196 DCHECK(!GetDeclaringClass()->IsInterface()); 197 DCHECK(!IsStatic()); 198 JValue result; 199 constexpr auto shorty = detail::MaterializeShorty<ReturnType, ArgType...>(); 200 auto vregs = detail::MaterializeVRegs<'L', ArgType...>(receiver, args...); 201 Invoke(self, 202 vregs.data(), 203 vregs.size() * sizeof(typename decltype(vregs)::value_type), 204 &result, 205 shorty.data()); 206 return detail::ShortyTraits<ReturnType>::Get(result); 207 } 208 209 template <char ReturnType, char... ArgType> 210 typename detail::ShortyTraits<ReturnType>::Type 211 ArtMethod::InvokeFinal(Thread* self, 212 ObjPtr<mirror::Object> receiver, 213 typename detail::ShortyTraits<ArgType>::Type... args) { 214 DCHECK(!GetDeclaringClass()->IsInterface()); 215 DCHECK(!IsStatic()); 216 DCHECK(IsFinal() || GetDeclaringClass()->IsFinal()); 217 DCHECK(receiver != nullptr); 218 return InvokeInstance<ReturnType, ArgType...>(self, receiver, args...); 219 } 220 221 template <char ReturnType, char... ArgType> 222 typename detail::ShortyTraits<ReturnType>::Type 223 ArtMethod::InvokeVirtual(Thread* self, 224 ObjPtr<mirror::Object> receiver, 225 typename detail::ShortyTraits<ArgType>::Type... args) { 226 DCHECK(!GetDeclaringClass()->IsInterface()); 227 DCHECK(!IsStatic()); 228 DCHECK(!IsFinal()); 229 DCHECK(receiver != nullptr); 230 ArtMethod* target_method = 231 receiver->GetClass()->FindVirtualMethodForVirtual(this, kRuntimePointerSize); 232 DCHECK(target_method != nullptr); 233 return target_method->InvokeInstance<ReturnType, ArgType...>(self, receiver, args...); 234 } 235 236 template <char ReturnType, char... ArgType> 237 typename detail::ShortyTraits<ReturnType>::Type 238 ArtMethod::InvokeInterface(Thread* self, 239 ObjPtr<mirror::Object> receiver, 240 typename detail::ShortyTraits<ArgType>::Type... args) { 241 DCHECK(GetDeclaringClass()->IsInterface()); 242 DCHECK(!IsStatic()); 243 DCHECK(receiver != nullptr); 244 ArtMethod* target_method = 245 receiver->GetClass()->FindVirtualMethodForInterface(this, kRuntimePointerSize); 246 DCHECK(target_method != nullptr); 247 return target_method->InvokeInstance<ReturnType, ArgType...>(self, receiver, args...); 248 } 249 250 template <ReadBarrierOption kReadBarrierOption> 251 inline ObjPtr<mirror::Class> ArtMethod::GetDeclaringClassUnchecked() { 252 GcRootSource gc_root_source(this); 253 return declaring_class_.Read<kReadBarrierOption>(&gc_root_source); 254 } 255 256 template <ReadBarrierOption kReadBarrierOption> 257 inline ObjPtr<mirror::Class> ArtMethod::GetDeclaringClass() { 258 ObjPtr<mirror::Class> result = GetDeclaringClassUnchecked<kReadBarrierOption>(); 259 if (kIsDebugBuild) { 260 if (!IsRuntimeMethod()) { 261 CHECK(result != nullptr) << this; 262 } else { 263 CHECK(result == nullptr) << this; 264 } 265 } 266 return result; 267 } 268 269 inline void ArtMethod::SetDeclaringClass(ObjPtr<mirror::Class> new_declaring_class) { 270 declaring_class_ = GcRoot<mirror::Class>(new_declaring_class); 271 } 272 273 inline bool ArtMethod::CASDeclaringClass(ObjPtr<mirror::Class> expected_class, 274 ObjPtr<mirror::Class> desired_class) { 275 GcRoot<mirror::Class> expected_root(expected_class); 276 GcRoot<mirror::Class> desired_root(desired_class); 277 auto atomic_root_class = reinterpret_cast<Atomic<GcRoot<mirror::Class>>*>(&declaring_class_); 278 return atomic_root_class->CompareAndSetStrongSequentiallyConsistent(expected_root, desired_root); 279 } 280 281 inline uint16_t ArtMethod::GetMethodIndex() { 282 DCHECK(IsRuntimeMethod() || GetDeclaringClass()->IsResolved()); 283 return method_index_; 284 } 285 286 inline uint16_t ArtMethod::GetMethodIndexDuringLinking() { 287 return method_index_; 288 } 289 290 inline ObjPtr<mirror::Class> ArtMethod::LookupResolvedClassFromTypeIndex(dex::TypeIndex type_idx) { 291 ScopedAssertNoThreadSuspension ants(__FUNCTION__); 292 ObjPtr<mirror::Class> type = 293 Runtime::Current()->GetClassLinker()->LookupResolvedType(type_idx, this); 294 DCHECK(!Thread::Current()->IsExceptionPending()); 295 return type; 296 } 297 298 inline ObjPtr<mirror::Class> ArtMethod::ResolveClassFromTypeIndex(dex::TypeIndex type_idx) { 299 ObjPtr<mirror::Class> type = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, this); 300 DCHECK_EQ(type == nullptr, Thread::Current()->IsExceptionPending()); 301 return type; 302 } 303 304 inline bool ArtMethod::IsStringConstructor() { 305 uint32_t access_flags = GetAccessFlags(); 306 DCHECK(!IsClassInitializer(access_flags)); 307 return IsConstructor(access_flags) && 308 // No read barrier needed for reading a constant reference only to read 309 // a constant string class flag. See `ReadBarrierOption`. 310 GetDeclaringClass<kWithoutReadBarrier>()->IsStringClass(); 311 } 312 313 inline bool ArtMethod::IsOverridableByDefaultMethod() { 314 // It is safe to avoid the read barrier here since the constant interface flag 315 // in the `Class` object is stored before creating the `ArtMethod` and storing 316 // the declaring class reference. See `ReadBarrierOption`. 317 return GetDeclaringClass<kWithoutReadBarrier>()->IsInterface(); 318 } 319 320 inline bool ArtMethod::CheckIncompatibleClassChange(InvokeType type) { 321 switch (type) { 322 case kStatic: 323 return !IsStatic(); 324 case kDirect: 325 return !IsDirect() || IsStatic(); 326 case kVirtual: { 327 // We have an error if we are direct or a non-copied (i.e. not part of a real class) interface 328 // method. 329 ObjPtr<mirror::Class> methods_class = GetDeclaringClass(); 330 return IsDirect() || (methods_class->IsInterface() && !IsCopied()); 331 } 332 case kSuper: 333 // Constructors and static methods are called with invoke-direct. 334 return IsConstructor() || IsStatic(); 335 case kInterface: { 336 ObjPtr<mirror::Class> methods_class = GetDeclaringClass(); 337 return IsDirect() || !(methods_class->IsInterface() || methods_class->IsObjectClass()); 338 } 339 case kPolymorphic: 340 return !IsSignaturePolymorphic(); 341 default: 342 LOG(FATAL) << "Unreachable - invocation type: " << type; 343 UNREACHABLE(); 344 } 345 } 346 347 inline bool ArtMethod::IsCalleeSaveMethod() { 348 if (!IsRuntimeMethod()) { 349 return false; 350 } 351 Runtime* runtime = Runtime::Current(); 352 bool result = false; 353 for (uint32_t i = 0; i < static_cast<uint32_t>(CalleeSaveType::kLastCalleeSaveType); i++) { 354 if (this == runtime->GetCalleeSaveMethod(CalleeSaveType(i))) { 355 result = true; 356 break; 357 } 358 } 359 return result; 360 } 361 362 inline bool ArtMethod::IsResolutionMethod() { 363 bool result = this == Runtime::Current()->GetResolutionMethod(); 364 // Check that if we do think it is phony it looks like the resolution method. 365 DCHECK_IMPLIES(result, IsRuntimeMethod()); 366 return result; 367 } 368 369 inline bool ArtMethod::IsImtUnimplementedMethod() { 370 bool result = this == Runtime::Current()->GetImtUnimplementedMethod(); 371 // Check that if we do think it is phony it looks like the imt unimplemented method. 372 DCHECK_IMPLIES(result, IsRuntimeMethod()); 373 return result; 374 } 375 376 inline const DexFile* ArtMethod::GetDexFile() { 377 // It is safe to avoid the read barrier here since the dex file is constant, so if we read the 378 // from-space dex file pointer it will be equal to the to-space copy. 379 return GetDexCache<kWithoutReadBarrier>()->GetDexFile(); 380 } 381 382 inline const char* ArtMethod::GetDeclaringClassDescriptor() { 383 DCHECK(!IsRuntimeMethod()); 384 DCHECK(!IsProxyMethod()); 385 return GetDexFile()->GetMethodDeclaringClassDescriptor(GetDexMethodIndex()); 386 } 387 388 inline std::string_view ArtMethod::GetDeclaringClassDescriptorView() { 389 DCHECK(!IsRuntimeMethod()); 390 DCHECK(!IsProxyMethod()); 391 return GetDexFile()->GetMethodDeclaringClassDescriptorView(GetDexMethodIndex()); 392 } 393 394 inline const char* ArtMethod::GetShorty() { 395 uint32_t unused_length; 396 return GetShorty(&unused_length); 397 } 398 399 inline const char* ArtMethod::GetShorty(uint32_t* out_length) { 400 DCHECK(!IsProxyMethod()); 401 const DexFile* dex_file = GetDexFile(); 402 return dex_file->GetMethodShorty(dex_file->GetMethodId(GetDexMethodIndex()), out_length); 403 } 404 405 inline std::string_view ArtMethod::GetShortyView() { 406 DCHECK(!IsProxyMethod()); 407 const DexFile* dex_file = GetDexFile(); 408 return dex_file->GetMethodShortyView(dex_file->GetMethodId(GetDexMethodIndex())); 409 } 410 411 inline const Signature ArtMethod::GetSignature() { 412 uint32_t dex_method_idx = GetDexMethodIndex(); 413 if (dex_method_idx != dex::kDexNoIndex) { 414 DCHECK(!IsProxyMethod()); 415 const DexFile* dex_file = GetDexFile(); 416 return dex_file->GetMethodSignature(dex_file->GetMethodId(dex_method_idx)); 417 } 418 return Signature::NoSignature(); 419 } 420 421 inline const char* ArtMethod::GetName() { 422 uint32_t dex_method_idx = GetDexMethodIndex(); 423 if (LIKELY(dex_method_idx != dex::kDexNoIndex)) { 424 DCHECK(!IsProxyMethod()); 425 const DexFile* dex_file = GetDexFile(); 426 return dex_file->GetMethodName(dex_file->GetMethodId(dex_method_idx)); 427 } 428 return GetRuntimeMethodName(); 429 } 430 431 inline std::string_view ArtMethod::GetNameView() { 432 uint32_t dex_method_idx = GetDexMethodIndex(); 433 if (LIKELY(dex_method_idx != dex::kDexNoIndex)) { 434 DCHECK(!IsProxyMethod()); 435 const DexFile* dex_file = GetDexFile(); 436 return dex_file->GetMethodNameView(dex_method_idx); 437 } 438 return GetRuntimeMethodName(); 439 } 440 441 inline ObjPtr<mirror::String> ArtMethod::ResolveNameString() { 442 DCHECK(!IsProxyMethod()); 443 const dex::MethodId& method_id = GetDexFile()->GetMethodId(GetDexMethodIndex()); 444 return Runtime::Current()->GetClassLinker()->ResolveString(method_id.name_idx_, this); 445 } 446 447 inline bool ArtMethod::NameEquals(ObjPtr<mirror::String> name) { 448 DCHECK(!IsProxyMethod()); 449 const DexFile* dex_file = GetDexFile(); 450 const dex::MethodId& method_id = dex_file->GetMethodId(GetDexMethodIndex()); 451 const dex::StringIndex name_idx = method_id.name_idx_; 452 uint32_t utf16_length; 453 const char* utf8_name = dex_file->GetStringDataAndUtf16Length(name_idx, &utf16_length); 454 return dchecked_integral_cast<uint32_t>(name->GetLength()) == utf16_length && 455 name->Equals(utf8_name); 456 } 457 458 inline const dex::CodeItem* ArtMethod::GetCodeItem() { 459 if (!HasCodeItem()) { 460 return nullptr; 461 } 462 Runtime* runtime = Runtime::Current(); 463 PointerSize pointer_size = runtime->GetClassLinker()->GetImagePointerSize(); 464 return runtime->IsAotCompiler() 465 ? GetDexFile()->GetCodeItem(reinterpret_cast32<uint32_t>(GetDataPtrSize(pointer_size))) 466 : reinterpret_cast<const dex::CodeItem*>( 467 reinterpret_cast<uintptr_t>(GetDataPtrSize(pointer_size)) & ~1); 468 } 469 470 inline int32_t ArtMethod::GetLineNumFromDexPC(uint32_t dex_pc) { 471 DCHECK(!IsProxyMethod()); 472 if (dex_pc == dex::kDexNoIndex) { 473 return IsNative() ? -2 : -1; 474 } 475 return annotations::GetLineNumFromPC(GetDexFile(), this, dex_pc); 476 } 477 478 inline const dex::ProtoId& ArtMethod::GetPrototype() { 479 DCHECK(!IsProxyMethod()); 480 const DexFile* dex_file = GetDexFile(); 481 return dex_file->GetMethodPrototype(dex_file->GetMethodId(GetDexMethodIndex())); 482 } 483 484 inline const dex::TypeList* ArtMethod::GetParameterTypeList() { 485 DCHECK(!IsProxyMethod()); 486 const DexFile* dex_file = GetDexFile(); 487 const dex::ProtoId& proto = dex_file->GetMethodPrototype( 488 dex_file->GetMethodId(GetDexMethodIndex())); 489 return dex_file->GetProtoParameters(proto); 490 } 491 492 inline const char* ArtMethod::GetDeclaringClassSourceFile() { 493 DCHECK(!IsProxyMethod()); 494 return GetDeclaringClass()->GetSourceFile(); 495 } 496 497 inline uint16_t ArtMethod::GetClassDefIndex() { 498 DCHECK(!IsProxyMethod()); 499 if (LIKELY(!IsObsolete())) { 500 return GetDeclaringClass()->GetDexClassDefIndex(); 501 } else { 502 return FindObsoleteDexClassDefIndex(); 503 } 504 } 505 506 inline const dex::ClassDef& ArtMethod::GetClassDef() { 507 DCHECK(!IsProxyMethod()); 508 return GetDexFile()->GetClassDef(GetClassDefIndex()); 509 } 510 511 inline size_t ArtMethod::GetNumberOfParameters() { 512 constexpr size_t return_type_count = 1u; 513 uint32_t shorty_length; 514 GetShorty(&shorty_length); 515 return shorty_length - return_type_count; 516 } 517 518 inline const char* ArtMethod::GetReturnTypeDescriptor() { 519 return GetDexFile()->GetTypeDescriptor(GetReturnTypeIndex()); 520 } 521 522 inline std::string_view ArtMethod::GetReturnTypeDescriptorView() { 523 return GetDexFile()->GetTypeDescriptorView(GetReturnTypeIndex()); 524 } 525 526 inline Primitive::Type ArtMethod::GetReturnTypePrimitive() { 527 return Primitive::GetType(GetReturnTypeDescriptor()[0]); 528 } 529 530 inline const char* ArtMethod::GetTypeDescriptorFromTypeIdx(dex::TypeIndex type_idx) { 531 DCHECK(!IsProxyMethod()); 532 const DexFile* dex_file = GetDexFile(); 533 return dex_file->GetTypeDescriptor(dex_file->GetTypeId(type_idx)); 534 } 535 536 inline ObjPtr<mirror::ClassLoader> ArtMethod::GetClassLoader() { 537 DCHECK(!IsProxyMethod()); 538 return GetDeclaringClass()->GetClassLoader(); 539 } 540 541 template <ReadBarrierOption kReadBarrierOption> 542 inline ObjPtr<mirror::DexCache> ArtMethod::GetDexCache() { 543 if (LIKELY(!IsObsolete())) { 544 ObjPtr<mirror::Class> klass = GetDeclaringClass<kReadBarrierOption>(); 545 return klass->GetDexCache<kDefaultVerifyFlags, kReadBarrierOption>(); 546 } else { 547 DCHECK(!IsProxyMethod()); 548 return GetObsoleteDexCache<kReadBarrierOption>(); 549 } 550 } 551 552 inline bool ArtMethod::IsProxyMethod() { 553 DCHECK(!IsRuntimeMethod()) << "ArtMethod::IsProxyMethod called on a runtime method"; 554 // No read barrier needed, we're reading the constant declaring class only to read 555 // the constant proxy flag. See ReadBarrierOption. 556 return GetDeclaringClass<kWithoutReadBarrier>()->IsProxyClass(); 557 } 558 559 inline ArtMethod* ArtMethod::GetInterfaceMethodForProxyUnchecked(PointerSize pointer_size) { 560 DCHECK(IsProxyMethod()); 561 // Do not check IsAssignableFrom() here as it relies on raw reference comparison 562 // which may give false negatives while visiting references for a non-CC moving GC. 563 return reinterpret_cast<ArtMethod*>(GetDataPtrSize(pointer_size)); 564 } 565 566 inline ArtMethod* ArtMethod::GetInterfaceMethodIfProxy(PointerSize pointer_size) { 567 if (LIKELY(!IsProxyMethod())) { 568 return this; 569 } 570 ArtMethod* interface_method = GetInterfaceMethodForProxyUnchecked(pointer_size); 571 // We can check that the proxy class implements the interface only if the proxy class 572 // is resolved, otherwise the interface table is not yet initialized. 573 DCHECK_IMPLIES(GetDeclaringClass()->IsResolved(), 574 interface_method->GetDeclaringClass()->IsAssignableFrom(GetDeclaringClass())); 575 return interface_method; 576 } 577 578 inline dex::TypeIndex ArtMethod::GetReturnTypeIndex() { 579 DCHECK(!IsRuntimeMethod()); 580 DCHECK(!IsProxyMethod()); 581 const DexFile* dex_file = GetDexFile(); 582 const dex::MethodId& method_id = dex_file->GetMethodId(GetDexMethodIndex()); 583 const dex::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id); 584 return proto_id.return_type_idx_; 585 } 586 587 inline ObjPtr<mirror::Class> ArtMethod::LookupResolvedReturnType() { 588 return LookupResolvedClassFromTypeIndex(GetReturnTypeIndex()); 589 } 590 591 inline ObjPtr<mirror::Class> ArtMethod::ResolveReturnType() { 592 return ResolveClassFromTypeIndex(GetReturnTypeIndex()); 593 } 594 595 inline bool ArtMethod::HasSingleImplementation() { 596 // No read barrier needed for reading a constant reference only to read 597 // a constant final class flag. See `ReadBarrierOption`. 598 if (IsFinal() || GetDeclaringClass<kWithoutReadBarrier>()->IsFinal()) { 599 // We don't set kAccSingleImplementation for these cases since intrinsic 600 // can use the flag also. 601 return true; 602 } 603 return (GetAccessFlags() & kAccSingleImplementation) != 0; 604 } 605 606 template<ReadBarrierOption kReadBarrierOption, bool kVisitProxyMethod, typename RootVisitorType> 607 void ArtMethod::VisitRoots(RootVisitorType& visitor, PointerSize pointer_size) { 608 if (LIKELY(!declaring_class_.IsNull())) { 609 visitor.VisitRoot(declaring_class_.AddressWithoutBarrier()); 610 if (kVisitProxyMethod) { 611 ObjPtr<mirror::Class> klass = declaring_class_.Read<kReadBarrierOption>(); 612 if (UNLIKELY(klass->IsProxyClass())) { 613 // For normal methods, dex cache shortcuts will be visited through the declaring class. 614 // However, for proxies we need to keep the interface method alive, so we visit its roots. 615 ArtMethod* interface_method = GetInterfaceMethodForProxyUnchecked(pointer_size); 616 DCHECK(interface_method != nullptr); 617 interface_method->VisitRoots<kReadBarrierOption, kVisitProxyMethod>(visitor, pointer_size); 618 } 619 } 620 } 621 622 // JIT-ted code can hold references to heap objects like MethodType-s. Visiting them here to 623 // treat them as strongly reachable. 624 Runtime* runtime = Runtime::Current(); 625 if (runtime->GetJit() != nullptr) { 626 runtime->GetJit()->GetCodeCache()->VisitRootTables(this, visitor); 627 } 628 } 629 630 template<typename RootVisitorType> 631 void ArtMethod::VisitRoots(RootVisitorType& visitor, 632 uint8_t* start_boundary, 633 uint8_t* end_boundary, 634 ArtMethod* method) { 635 mirror::CompressedReference<mirror::Object>* cls_ptr = 636 reinterpret_cast<mirror::CompressedReference<mirror::Object>*>( 637 reinterpret_cast<uint8_t*>(method) + DeclaringClassOffset().Int32Value()); 638 if (reinterpret_cast<uint8_t*>(cls_ptr) >= start_boundary 639 && reinterpret_cast<uint8_t*>(cls_ptr) < end_boundary) { 640 visitor.VisitRootIfNonNull(cls_ptr); 641 } 642 } 643 644 template<PointerSize kPointerSize, typename RootVisitorType> 645 void ArtMethod::VisitArrayRoots(RootVisitorType& visitor, 646 uint8_t* start_boundary, 647 uint8_t* end_boundary, 648 LengthPrefixedArray<ArtMethod>* array) { 649 DCHECK_LE(start_boundary, end_boundary); 650 DCHECK_NE(array->size(), 0u); 651 static constexpr size_t kMethodSize = ArtMethod::Size(kPointerSize); 652 ArtMethod* first_method = &array->At(0, kMethodSize, ArtMethod::Alignment(kPointerSize)); 653 DCHECK_LE(static_cast<void*>(end_boundary), 654 static_cast<void*>(reinterpret_cast<uint8_t*>(first_method) 655 + array->size() * kMethodSize)); 656 uint8_t* declaring_class = 657 reinterpret_cast<uint8_t*>(first_method) + DeclaringClassOffset().Int32Value(); 658 // Jump to the first class to visit. 659 if (declaring_class < start_boundary) { 660 size_t remainder = (start_boundary - declaring_class) % kMethodSize; 661 declaring_class = start_boundary; 662 if (remainder > 0) { 663 declaring_class += kMethodSize - remainder; 664 } 665 } 666 while (declaring_class < end_boundary) { 667 visitor.VisitRootIfNonNull( 668 reinterpret_cast<mirror::CompressedReference<mirror::Object>*>(declaring_class)); 669 declaring_class += kMethodSize; 670 } 671 } 672 673 template <ReadBarrierOption kReadBarrierOption> 674 inline bool ArtMethod::StillNeedsClinitCheck() { 675 if (!NeedsClinitCheckBeforeCall()) { 676 return false; 677 } 678 ObjPtr<mirror::Class> klass = GetDeclaringClass<kReadBarrierOption>(); 679 return !klass->IsVisiblyInitialized(); 680 } 681 682 inline bool ArtMethod::StillNeedsClinitCheckMayBeDead() { 683 if (!NeedsClinitCheckBeforeCall()) { 684 return false; 685 } 686 ObjPtr<mirror::Class> klass = GetDeclaringClassMayBeDead(); 687 return !klass->IsVisiblyInitialized(); 688 } 689 690 inline bool ArtMethod::IsDeclaringClassVerifiedMayBeDead() { 691 ObjPtr<mirror::Class> klass = GetDeclaringClassMayBeDead(); 692 return klass->IsVerified(); 693 } 694 695 inline ObjPtr<mirror::Class> ArtMethod::GetDeclaringClassMayBeDead() { 696 // Helper method for checking the status of the declaring class which may be dead. 697 // 698 // To avoid resurrecting an unreachable object, or crashing the GC in some GC phases, 699 // we must not use a full read barrier. Therefore we read the declaring class without 700 // a read barrier and check if it's already marked. If yes, we check the status of the 701 // to-space class object as intended. Otherwise, there is no to-space object and the 702 // from-space class object contains the most recent value of the status field; even if 703 // this races with another thread doing a read barrier and updating the status, that's 704 // no different from a race with a thread that just updates the status. 705 ObjPtr<mirror::Class> klass = GetDeclaringClass<kWithoutReadBarrier>(); 706 ObjPtr<mirror::Class> marked = ReadBarrier::IsMarked(klass.Ptr()); 707 return (marked != nullptr) ? marked : klass; 708 } 709 710 inline CodeItemInstructionAccessor ArtMethod::DexInstructions() { 711 return CodeItemInstructionAccessor(*GetDexFile(), GetCodeItem()); 712 } 713 714 inline CodeItemDataAccessor ArtMethod::DexInstructionData() { 715 return CodeItemDataAccessor(*GetDexFile(), GetCodeItem()); 716 } 717 718 inline CodeItemDebugInfoAccessor ArtMethod::DexInstructionDebugInfo() { 719 return CodeItemDebugInfoAccessor(*GetDexFile(), GetCodeItem(), GetDexMethodIndex()); 720 } 721 722 inline bool ArtMethod::CounterHasChanged(uint16_t threshold) { 723 DCHECK(!IsAbstract()); 724 DCHECK_EQ(threshold, Runtime::Current()->GetJITOptions()->GetWarmupThreshold()); 725 return hotness_count_ != threshold; 726 } 727 728 inline void ArtMethod::ResetCounter(uint16_t new_value) { 729 if (IsAbstract()) { 730 return; 731 } 732 if (IsMemorySharedMethod()) { 733 return; 734 } 735 DCHECK_EQ(new_value, Runtime::Current()->GetJITOptions()->GetWarmupThreshold()); 736 // Avoid dirtying the value if possible. 737 if (hotness_count_ != new_value) { 738 hotness_count_ = new_value; 739 } 740 } 741 742 inline void ArtMethod::SetHotCounter() { 743 DCHECK(!IsAbstract()); 744 // Avoid dirtying the value if possible. 745 if (hotness_count_ != 0) { 746 hotness_count_ = 0; 747 } 748 } 749 750 inline void ArtMethod::UpdateCounter(int32_t new_samples) { 751 DCHECK(!IsAbstract()); 752 DCHECK_GT(new_samples, 0); 753 DCHECK_LE(new_samples, std::numeric_limits<uint16_t>::max()); 754 if (IsMemorySharedMethod()) { 755 return; 756 } 757 uint16_t old_hotness_count = hotness_count_; 758 uint16_t new_count = (old_hotness_count <= new_samples) ? 0u : old_hotness_count - new_samples; 759 // Avoid dirtying the value if possible. 760 if (old_hotness_count != new_count) { 761 hotness_count_ = new_count; 762 } 763 } 764 765 inline bool ArtMethod::CounterIsHot() { 766 DCHECK(!IsAbstract()); 767 return hotness_count_ == 0; 768 } 769 770 inline uint16_t ArtMethod::GetCounter() { 771 DCHECK(!IsAbstract()); 772 return hotness_count_; 773 } 774 775 inline uint32_t ArtMethod::GetImtIndex() { 776 if (LIKELY(IsAbstract())) { 777 return imt_index_; 778 } else { 779 return ImTable::GetImtIndex(this); 780 } 781 } 782 783 inline void ArtMethod::CalculateAndSetImtIndex() { 784 DCHECK(IsAbstract()) << PrettyMethod(); 785 imt_index_ = ImTable::GetImtIndex(this); 786 } 787 788 } // namespace art 789 790 #endif // ART_RUNTIME_ART_METHOD_INL_H_ 791