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 "base/utils.h" 25 #include "class_linker-inl.h" 26 #include "common_throws.h" 27 #include "dex/code_item_accessors-inl.h" 28 #include "dex/dex_file-inl.h" 29 #include "dex/dex_file_annotations.h" 30 #include "dex/dex_file_types.h" 31 #include "dex/invoke_type.h" 32 #include "dex/primitive.h" 33 #include "gc_root-inl.h" 34 #include "intrinsics_enum.h" 35 #include "jit/profiling_info.h" 36 #include "mirror/class-inl.h" 37 #include "mirror/dex_cache-inl.h" 38 #include "mirror/object-inl.h" 39 #include "mirror/object_array.h" 40 #include "mirror/string.h" 41 #include "oat.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 "scoped_thread_state_change-inl.h" 47 #include "thread-current-inl.h" 48 49 namespace art { 50 51 template <ReadBarrierOption kReadBarrierOption> 52 inline mirror::Class* ArtMethod::GetDeclaringClassUnchecked() { 53 GcRootSource gc_root_source(this); 54 return declaring_class_.Read<kReadBarrierOption>(&gc_root_source); 55 } 56 57 template <ReadBarrierOption kReadBarrierOption> 58 inline mirror::Class* ArtMethod::GetDeclaringClass() { 59 mirror::Class* result = GetDeclaringClassUnchecked<kReadBarrierOption>(); 60 if (kIsDebugBuild) { 61 if (!IsRuntimeMethod()) { 62 CHECK(result != nullptr) << this; 63 if (kCheckDeclaringClassState) { 64 if (!(result->IsIdxLoaded() || result->IsErroneous())) { 65 LOG(FATAL_WITHOUT_ABORT) << "Class status: " << result->GetStatus(); 66 LOG(FATAL) << result->PrettyClass(); 67 } 68 } 69 } else { 70 CHECK(result == nullptr) << this; 71 } 72 } 73 return result; 74 } 75 76 inline void ArtMethod::SetDeclaringClass(ObjPtr<mirror::Class> new_declaring_class) { 77 declaring_class_ = GcRoot<mirror::Class>(new_declaring_class); 78 } 79 80 inline bool ArtMethod::CASDeclaringClass(mirror::Class* expected_class, 81 mirror::Class* desired_class) { 82 GcRoot<mirror::Class> expected_root(expected_class); 83 GcRoot<mirror::Class> desired_root(desired_class); 84 auto atomic_root_class = reinterpret_cast<Atomic<GcRoot<mirror::Class>>*>(&declaring_class_); 85 return atomic_root_class->CompareAndSetStrongSequentiallyConsistent(expected_root, desired_root); 86 } 87 88 inline uint16_t ArtMethod::GetMethodIndex() { 89 DCHECK(IsRuntimeMethod() || GetDeclaringClass()->IsResolved()); 90 return method_index_; 91 } 92 93 inline uint16_t ArtMethod::GetMethodIndexDuringLinking() { 94 return method_index_; 95 } 96 97 template <ReadBarrierOption kReadBarrierOption> 98 inline uint32_t ArtMethod::GetDexMethodIndex() { 99 if (kCheckDeclaringClassState) { 100 CHECK(IsRuntimeMethod() || 101 GetDeclaringClass<kReadBarrierOption>()->IsIdxLoaded() || 102 GetDeclaringClass<kReadBarrierOption>()->IsErroneous()); 103 } 104 return GetDexMethodIndexUnchecked(); 105 } 106 107 inline ObjPtr<mirror::Class> ArtMethod::LookupResolvedClassFromTypeIndex(dex::TypeIndex type_idx) { 108 ScopedAssertNoThreadSuspension ants(__FUNCTION__); 109 ObjPtr<mirror::Class> type = 110 Runtime::Current()->GetClassLinker()->LookupResolvedType(type_idx, this); 111 DCHECK(!Thread::Current()->IsExceptionPending()); 112 return type; 113 } 114 115 inline ObjPtr<mirror::Class> ArtMethod::ResolveClassFromTypeIndex(dex::TypeIndex type_idx) { 116 ObjPtr<mirror::Class> type = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, this); 117 DCHECK_EQ(type == nullptr, Thread::Current()->IsExceptionPending()); 118 return type; 119 } 120 121 inline bool ArtMethod::CheckIncompatibleClassChange(InvokeType type) { 122 switch (type) { 123 case kStatic: 124 return !IsStatic(); 125 case kDirect: 126 return !IsDirect() || IsStatic(); 127 case kVirtual: { 128 // We have an error if we are direct or a non-copied (i.e. not part of a real class) interface 129 // method. 130 mirror::Class* methods_class = GetDeclaringClass(); 131 return IsDirect() || (methods_class->IsInterface() && !IsCopied()); 132 } 133 case kSuper: 134 // Constructors and static methods are called with invoke-direct. 135 return IsConstructor() || IsStatic(); 136 case kInterface: { 137 mirror::Class* methods_class = GetDeclaringClass(); 138 return IsDirect() || !(methods_class->IsInterface() || methods_class->IsObjectClass()); 139 } 140 default: 141 LOG(FATAL) << "Unreachable - invocation type: " << type; 142 UNREACHABLE(); 143 } 144 } 145 146 inline bool ArtMethod::IsCalleeSaveMethod() { 147 if (!IsRuntimeMethod()) { 148 return false; 149 } 150 Runtime* runtime = Runtime::Current(); 151 bool result = false; 152 for (uint32_t i = 0; i < static_cast<uint32_t>(CalleeSaveType::kLastCalleeSaveType); i++) { 153 if (this == runtime->GetCalleeSaveMethod(CalleeSaveType(i))) { 154 result = true; 155 break; 156 } 157 } 158 return result; 159 } 160 161 inline bool ArtMethod::IsResolutionMethod() { 162 bool result = this == Runtime::Current()->GetResolutionMethod(); 163 // Check that if we do think it is phony it looks like the resolution method. 164 DCHECK(!result || IsRuntimeMethod()); 165 return result; 166 } 167 168 inline bool ArtMethod::IsImtUnimplementedMethod() { 169 bool result = this == Runtime::Current()->GetImtUnimplementedMethod(); 170 // Check that if we do think it is phony it looks like the imt unimplemented method. 171 DCHECK(!result || IsRuntimeMethod()); 172 return result; 173 } 174 175 inline const DexFile* ArtMethod::GetDexFile() { 176 // It is safe to avoid the read barrier here since the dex file is constant, so if we read the 177 // from-space dex file pointer it will be equal to the to-space copy. 178 return GetDexCache<kWithoutReadBarrier>()->GetDexFile(); 179 } 180 181 inline const char* ArtMethod::GetDeclaringClassDescriptor() { 182 uint32_t dex_method_idx = GetDexMethodIndex(); 183 if (UNLIKELY(dex_method_idx == dex::kDexNoIndex)) { 184 return "<runtime method>"; 185 } 186 DCHECK(!IsProxyMethod()); 187 const DexFile* dex_file = GetDexFile(); 188 return dex_file->GetMethodDeclaringClassDescriptor(dex_file->GetMethodId(dex_method_idx)); 189 } 190 191 inline const char* ArtMethod::GetShorty() { 192 uint32_t unused_length; 193 return GetShorty(&unused_length); 194 } 195 196 inline const char* ArtMethod::GetShorty(uint32_t* out_length) { 197 DCHECK(!IsProxyMethod()); 198 const DexFile* dex_file = GetDexFile(); 199 // Don't do a read barrier in the DCHECK() inside GetDexMethodIndex() as GetShorty() 200 // can be called when the declaring class is about to be unloaded and cannot be added 201 // to the mark stack (subsequent GC assertion would fail). 202 // It is safe to avoid the read barrier as the ArtMethod is constructed with a declaring 203 // Class already satisfying the DCHECK() inside GetDexMethodIndex(), so even if that copy 204 // of declaring class becomes a from-space object, it shall satisfy the DCHECK(). 205 return dex_file->GetMethodShorty(dex_file->GetMethodId(GetDexMethodIndex<kWithoutReadBarrier>()), 206 out_length); 207 } 208 209 inline const Signature ArtMethod::GetSignature() { 210 uint32_t dex_method_idx = GetDexMethodIndex(); 211 if (dex_method_idx != dex::kDexNoIndex) { 212 DCHECK(!IsProxyMethod()); 213 const DexFile* dex_file = GetDexFile(); 214 return dex_file->GetMethodSignature(dex_file->GetMethodId(dex_method_idx)); 215 } 216 return Signature::NoSignature(); 217 } 218 219 inline const char* ArtMethod::GetName() { 220 uint32_t dex_method_idx = GetDexMethodIndex(); 221 if (LIKELY(dex_method_idx != dex::kDexNoIndex)) { 222 DCHECK(!IsProxyMethod()); 223 const DexFile* dex_file = GetDexFile(); 224 return dex_file->GetMethodName(dex_file->GetMethodId(dex_method_idx)); 225 } 226 Runtime* const runtime = Runtime::Current(); 227 if (this == runtime->GetResolutionMethod()) { 228 return "<runtime internal resolution method>"; 229 } else if (this == runtime->GetImtConflictMethod()) { 230 return "<runtime internal imt conflict method>"; 231 } else if (this == runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveAllCalleeSaves)) { 232 return "<runtime internal callee-save all registers method>"; 233 } else if (this == runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsOnly)) { 234 return "<runtime internal callee-save reference registers method>"; 235 } else if (this == runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsAndArgs)) { 236 return "<runtime internal callee-save reference and argument registers method>"; 237 } else if (this == runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveEverything)) { 238 return "<runtime internal save-every-register method>"; 239 } else if (this == runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveEverythingForClinit)) { 240 return "<runtime internal save-every-register method for clinit>"; 241 } else if (this == runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveEverythingForSuspendCheck)) { 242 return "<runtime internal save-every-register method for suspend check>"; 243 } else { 244 return "<unknown runtime internal method>"; 245 } 246 } 247 248 inline const DexFile::CodeItem* ArtMethod::GetCodeItem() { 249 return GetDexFile()->GetCodeItem(GetCodeItemOffset()); 250 } 251 252 inline bool ArtMethod::IsResolvedTypeIdx(dex::TypeIndex type_idx) { 253 DCHECK(!IsProxyMethod()); 254 return LookupResolvedClassFromTypeIndex(type_idx) != nullptr; 255 } 256 257 inline int32_t ArtMethod::GetLineNumFromDexPC(uint32_t dex_pc) { 258 DCHECK(!IsProxyMethod()); 259 if (dex_pc == dex::kDexNoIndex) { 260 return IsNative() ? -2 : -1; 261 } 262 return annotations::GetLineNumFromPC(GetDexFile(), this, dex_pc); 263 } 264 265 inline const DexFile::ProtoId& ArtMethod::GetPrototype() { 266 DCHECK(!IsProxyMethod()); 267 const DexFile* dex_file = GetDexFile(); 268 return dex_file->GetMethodPrototype(dex_file->GetMethodId(GetDexMethodIndex())); 269 } 270 271 inline const DexFile::TypeList* ArtMethod::GetParameterTypeList() { 272 DCHECK(!IsProxyMethod()); 273 const DexFile* dex_file = GetDexFile(); 274 const DexFile::ProtoId& proto = dex_file->GetMethodPrototype( 275 dex_file->GetMethodId(GetDexMethodIndex())); 276 return dex_file->GetProtoParameters(proto); 277 } 278 279 inline const char* ArtMethod::GetDeclaringClassSourceFile() { 280 DCHECK(!IsProxyMethod()); 281 return GetDeclaringClass()->GetSourceFile(); 282 } 283 284 inline uint16_t ArtMethod::GetClassDefIndex() { 285 DCHECK(!IsProxyMethod()); 286 if (LIKELY(!IsObsolete())) { 287 return GetDeclaringClass()->GetDexClassDefIndex(); 288 } else { 289 return FindObsoleteDexClassDefIndex(); 290 } 291 } 292 293 inline const DexFile::ClassDef& ArtMethod::GetClassDef() { 294 DCHECK(!IsProxyMethod()); 295 return GetDexFile()->GetClassDef(GetClassDefIndex()); 296 } 297 298 inline size_t ArtMethod::GetNumberOfParameters() { 299 constexpr size_t return_type_count = 1u; 300 return strlen(GetShorty()) - return_type_count; 301 } 302 303 inline const char* ArtMethod::GetReturnTypeDescriptor() { 304 DCHECK(!IsProxyMethod()); 305 const DexFile* dex_file = GetDexFile(); 306 return dex_file->GetTypeDescriptor(dex_file->GetTypeId(GetReturnTypeIndex())); 307 } 308 309 inline Primitive::Type ArtMethod::GetReturnTypePrimitive() { 310 return Primitive::GetType(GetReturnTypeDescriptor()[0]); 311 } 312 313 inline const char* ArtMethod::GetTypeDescriptorFromTypeIdx(dex::TypeIndex type_idx) { 314 DCHECK(!IsProxyMethod()); 315 const DexFile* dex_file = GetDexFile(); 316 return dex_file->GetTypeDescriptor(dex_file->GetTypeId(type_idx)); 317 } 318 319 inline mirror::ClassLoader* ArtMethod::GetClassLoader() { 320 DCHECK(!IsProxyMethod()); 321 return GetDeclaringClass()->GetClassLoader(); 322 } 323 324 template <ReadBarrierOption kReadBarrierOption> 325 inline mirror::DexCache* ArtMethod::GetDexCache() { 326 if (LIKELY(!IsObsolete<kReadBarrierOption>())) { 327 mirror::Class* klass = GetDeclaringClass<kReadBarrierOption>(); 328 return klass->GetDexCache<kDefaultVerifyFlags, kReadBarrierOption>(); 329 } else { 330 DCHECK(!IsProxyMethod()); 331 return GetObsoleteDexCache(); 332 } 333 } 334 335 inline bool ArtMethod::IsProxyMethod() { 336 DCHECK(!IsRuntimeMethod()) << "ArtMethod::IsProxyMethod called on a runtime method"; 337 // Avoid read barrier since the from-space version of the class will have the correct proxy class 338 // flags since they are constant for the lifetime of the class. 339 return GetDeclaringClass<kWithoutReadBarrier>()->IsProxyClass(); 340 } 341 342 inline ArtMethod* ArtMethod::GetInterfaceMethodForProxyUnchecked(PointerSize pointer_size) { 343 DCHECK(IsProxyMethod()); 344 // Do not check IsAssignableFrom() here as it relies on raw reference comparison 345 // which may give false negatives while visiting references for a non-CC moving GC. 346 return reinterpret_cast<ArtMethod*>(GetDataPtrSize(pointer_size)); 347 } 348 349 inline ArtMethod* ArtMethod::GetInterfaceMethodIfProxy(PointerSize pointer_size) { 350 if (LIKELY(!IsProxyMethod())) { 351 return this; 352 } 353 ArtMethod* interface_method = GetInterfaceMethodForProxyUnchecked(pointer_size); 354 // We can check that the proxy class implements the interface only if the proxy class 355 // is resolved, otherwise the interface table is not yet initialized. 356 DCHECK(!GetDeclaringClass()->IsResolved() || 357 interface_method->GetDeclaringClass()->IsAssignableFrom(GetDeclaringClass())); 358 return interface_method; 359 } 360 361 inline dex::TypeIndex ArtMethod::GetReturnTypeIndex() { 362 DCHECK(!IsProxyMethod()); 363 const DexFile* dex_file = GetDexFile(); 364 const DexFile::MethodId& method_id = dex_file->GetMethodId(GetDexMethodIndex()); 365 const DexFile::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id); 366 return proto_id.return_type_idx_; 367 } 368 369 inline ObjPtr<mirror::Class> ArtMethod::LookupResolvedReturnType() { 370 return LookupResolvedClassFromTypeIndex(GetReturnTypeIndex()); 371 } 372 373 inline ObjPtr<mirror::Class> ArtMethod::ResolveReturnType() { 374 return ResolveClassFromTypeIndex(GetReturnTypeIndex()); 375 } 376 377 template <ReadBarrierOption kReadBarrierOption> 378 inline bool ArtMethod::HasSingleImplementation() { 379 if (IsFinal<kReadBarrierOption>() || GetDeclaringClass<kReadBarrierOption>()->IsFinal()) { 380 // We don't set kAccSingleImplementation for these cases since intrinsic 381 // can use the flag also. 382 return true; 383 } 384 return (GetAccessFlags<kReadBarrierOption>() & kAccSingleImplementation) != 0; 385 } 386 387 inline HiddenApiAccessFlags::ApiList ArtMethod::GetHiddenApiAccessFlags() 388 REQUIRES_SHARED(Locks::mutator_lock_) { 389 if (UNLIKELY(IsIntrinsic())) { 390 switch (static_cast<Intrinsics>(GetIntrinsic())) { 391 case Intrinsics::kSystemArrayCopyChar: 392 case Intrinsics::kStringGetCharsNoCheck: 393 case Intrinsics::kReferenceGetReferent: 394 // These intrinsics are on the light greylist and will fail a DCHECK in 395 // SetIntrinsic() if their flags change on the respective dex methods. 396 // Note that the DCHECK currently won't fail if the dex methods are 397 // whitelisted, e.g. in the core image (b/77733081). As a result, we 398 // might print warnings but we won't change the semantics. 399 return HiddenApiAccessFlags::kLightGreylist; 400 case Intrinsics::kVarHandleFullFence: 401 case Intrinsics::kVarHandleAcquireFence: 402 case Intrinsics::kVarHandleReleaseFence: 403 case Intrinsics::kVarHandleLoadLoadFence: 404 case Intrinsics::kVarHandleStoreStoreFence: 405 case Intrinsics::kVarHandleCompareAndExchange: 406 case Intrinsics::kVarHandleCompareAndExchangeAcquire: 407 case Intrinsics::kVarHandleCompareAndExchangeRelease: 408 case Intrinsics::kVarHandleCompareAndSet: 409 case Intrinsics::kVarHandleGet: 410 case Intrinsics::kVarHandleGetAcquire: 411 case Intrinsics::kVarHandleGetAndAdd: 412 case Intrinsics::kVarHandleGetAndAddAcquire: 413 case Intrinsics::kVarHandleGetAndAddRelease: 414 case Intrinsics::kVarHandleGetAndBitwiseAnd: 415 case Intrinsics::kVarHandleGetAndBitwiseAndAcquire: 416 case Intrinsics::kVarHandleGetAndBitwiseAndRelease: 417 case Intrinsics::kVarHandleGetAndBitwiseOr: 418 case Intrinsics::kVarHandleGetAndBitwiseOrAcquire: 419 case Intrinsics::kVarHandleGetAndBitwiseOrRelease: 420 case Intrinsics::kVarHandleGetAndBitwiseXor: 421 case Intrinsics::kVarHandleGetAndBitwiseXorAcquire: 422 case Intrinsics::kVarHandleGetAndBitwiseXorRelease: 423 case Intrinsics::kVarHandleGetAndSet: 424 case Intrinsics::kVarHandleGetAndSetAcquire: 425 case Intrinsics::kVarHandleGetAndSetRelease: 426 case Intrinsics::kVarHandleGetOpaque: 427 case Intrinsics::kVarHandleGetVolatile: 428 case Intrinsics::kVarHandleSet: 429 case Intrinsics::kVarHandleSetOpaque: 430 case Intrinsics::kVarHandleSetRelease: 431 case Intrinsics::kVarHandleSetVolatile: 432 case Intrinsics::kVarHandleWeakCompareAndSet: 433 case Intrinsics::kVarHandleWeakCompareAndSetAcquire: 434 case Intrinsics::kVarHandleWeakCompareAndSetPlain: 435 case Intrinsics::kVarHandleWeakCompareAndSetRelease: 436 // These intrinsics are on the blacklist and will fail a DCHECK in 437 // SetIntrinsic() if their flags change on the respective dex methods. 438 // Note that the DCHECK currently won't fail if the dex methods are 439 // whitelisted, e.g. in the core image (b/77733081). Given that they are 440 // exclusively VarHandle intrinsics, they should not be used outside 441 // tests that do not enable hidden API checks. 442 return HiddenApiAccessFlags::kBlacklist; 443 default: 444 // Remaining intrinsics are public API. We DCHECK that in SetIntrinsic(). 445 return HiddenApiAccessFlags::kWhitelist; 446 } 447 } else { 448 return HiddenApiAccessFlags::DecodeFromRuntime(GetAccessFlags()); 449 } 450 } 451 452 inline void ArtMethod::SetIntrinsic(uint32_t intrinsic) { 453 // Currently we only do intrinsics for static/final methods or methods of final 454 // classes. We don't set kHasSingleImplementation for those methods. 455 DCHECK(IsStatic() || IsFinal() || GetDeclaringClass()->IsFinal()) << 456 "Potential conflict with kAccSingleImplementation"; 457 static const int kAccFlagsShift = CTZ(kAccIntrinsicBits); 458 DCHECK_LE(intrinsic, kAccIntrinsicBits >> kAccFlagsShift); 459 uint32_t intrinsic_bits = intrinsic << kAccFlagsShift; 460 uint32_t new_value = (GetAccessFlags() & ~kAccIntrinsicBits) | kAccIntrinsic | intrinsic_bits; 461 if (kIsDebugBuild) { 462 uint32_t java_flags = (GetAccessFlags() & kAccJavaFlagsMask); 463 bool is_constructor = IsConstructor(); 464 bool is_synchronized = IsSynchronized(); 465 bool skip_access_checks = SkipAccessChecks(); 466 bool is_fast_native = IsFastNative(); 467 bool is_critical_native = IsCriticalNative(); 468 bool is_copied = IsCopied(); 469 bool is_miranda = IsMiranda(); 470 bool is_default = IsDefault(); 471 bool is_default_conflict = IsDefaultConflicting(); 472 bool is_compilable = IsCompilable(); 473 bool must_count_locks = MustCountLocks(); 474 HiddenApiAccessFlags::ApiList hidden_api_flags = GetHiddenApiAccessFlags(); 475 SetAccessFlags(new_value); 476 DCHECK_EQ(java_flags, (GetAccessFlags() & kAccJavaFlagsMask)); 477 DCHECK_EQ(is_constructor, IsConstructor()); 478 DCHECK_EQ(is_synchronized, IsSynchronized()); 479 DCHECK_EQ(skip_access_checks, SkipAccessChecks()); 480 DCHECK_EQ(is_fast_native, IsFastNative()); 481 DCHECK_EQ(is_critical_native, IsCriticalNative()); 482 DCHECK_EQ(is_copied, IsCopied()); 483 DCHECK_EQ(is_miranda, IsMiranda()); 484 DCHECK_EQ(is_default, IsDefault()); 485 DCHECK_EQ(is_default_conflict, IsDefaultConflicting()); 486 DCHECK_EQ(is_compilable, IsCompilable()); 487 DCHECK_EQ(must_count_locks, MustCountLocks()); 488 // Only DCHECK that we have preserved the hidden API access flags if the 489 // original method was not on the whitelist. This is because the core image 490 // does not have the access flags set (b/77733081). It is fine to hard-code 491 // these because (a) warnings on greylist do not change semantics, and 492 // (b) only VarHandle intrinsics are blacklisted at the moment and they 493 // should not be used outside tests with disabled API checks. 494 if (hidden_api_flags != HiddenApiAccessFlags::kWhitelist) { 495 DCHECK_EQ(hidden_api_flags, GetHiddenApiAccessFlags()); 496 } 497 } else { 498 SetAccessFlags(new_value); 499 } 500 } 501 502 template<ReadBarrierOption kReadBarrierOption, typename RootVisitorType> 503 void ArtMethod::VisitRoots(RootVisitorType& visitor, PointerSize pointer_size) { 504 if (LIKELY(!declaring_class_.IsNull())) { 505 visitor.VisitRoot(declaring_class_.AddressWithoutBarrier()); 506 mirror::Class* klass = declaring_class_.Read<kReadBarrierOption>(); 507 if (UNLIKELY(klass->IsProxyClass())) { 508 // For normal methods, dex cache shortcuts will be visited through the declaring class. 509 // However, for proxies we need to keep the interface method alive, so we visit its roots. 510 ArtMethod* interface_method = GetInterfaceMethodForProxyUnchecked(pointer_size); 511 DCHECK(interface_method != nullptr); 512 interface_method->VisitRoots(visitor, pointer_size); 513 } 514 } 515 } 516 517 template <typename Visitor> 518 inline void ArtMethod::UpdateObjectsForImageRelocation(const Visitor& visitor) { 519 mirror::Class* old_class = GetDeclaringClassUnchecked<kWithoutReadBarrier>(); 520 mirror::Class* new_class = visitor(old_class); 521 if (old_class != new_class) { 522 SetDeclaringClass(new_class); 523 } 524 } 525 526 template <ReadBarrierOption kReadBarrierOption, typename Visitor> 527 inline void ArtMethod::UpdateEntrypoints(const Visitor& visitor, PointerSize pointer_size) { 528 if (IsNative<kReadBarrierOption>()) { 529 const void* old_native_code = GetEntryPointFromJniPtrSize(pointer_size); 530 const void* new_native_code = visitor(old_native_code); 531 if (old_native_code != new_native_code) { 532 SetEntryPointFromJniPtrSize(new_native_code, pointer_size); 533 } 534 } else { 535 DCHECK(GetDataPtrSize(pointer_size) == nullptr); 536 } 537 const void* old_code = GetEntryPointFromQuickCompiledCodePtrSize(pointer_size); 538 const void* new_code = visitor(old_code); 539 if (old_code != new_code) { 540 SetEntryPointFromQuickCompiledCodePtrSize(new_code, pointer_size); 541 } 542 } 543 544 inline CodeItemInstructionAccessor ArtMethod::DexInstructions() { 545 return CodeItemInstructionAccessor(*GetDexFile(), GetCodeItem()); 546 } 547 548 inline CodeItemDataAccessor ArtMethod::DexInstructionData() { 549 return CodeItemDataAccessor(*GetDexFile(), GetCodeItem()); 550 } 551 552 inline CodeItemDebugInfoAccessor ArtMethod::DexInstructionDebugInfo() { 553 return CodeItemDebugInfoAccessor(*GetDexFile(), GetCodeItem(), GetDexMethodIndex()); 554 } 555 556 } // namespace art 557 558 #endif // ART_RUNTIME_ART_METHOD_INL_H_ 559