Home | History | Annotate | Download | only in runtime
      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