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