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