• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/logging.h"
25 #include "class_linker-inl.h"
26 #include "common_throws.h"
27 #include "dex_file.h"
28 #include "dex_file_annotations.h"
29 #include "dex_file-inl.h"
30 #include "gc_root-inl.h"
31 #include "invoke_type.h"
32 #include "jit/profiling_info.h"
33 #include "mirror/class-inl.h"
34 #include "mirror/dex_cache-inl.h"
35 #include "mirror/object-inl.h"
36 #include "mirror/object_array.h"
37 #include "mirror/string.h"
38 #include "oat.h"
39 #include "obj_ptr-inl.h"
40 #include "primitive.h"
41 #include "quick/quick_method_frame_info.h"
42 #include "read_barrier-inl.h"
43 #include "runtime-inl.h"
44 #include "scoped_thread_state_change-inl.h"
45 #include "thread-current-inl.h"
46 #include "utils.h"
47 
48 namespace art {
49 
50 template <ReadBarrierOption kReadBarrierOption>
GetDeclaringClassUnchecked()51 inline mirror::Class* ArtMethod::GetDeclaringClassUnchecked() {
52   GcRootSource gc_root_source(this);
53   return declaring_class_.Read<kReadBarrierOption>(&gc_root_source);
54 }
55 
56 template <ReadBarrierOption kReadBarrierOption>
GetDeclaringClass()57 inline mirror::Class* ArtMethod::GetDeclaringClass() {
58   mirror::Class* result = GetDeclaringClassUnchecked<kReadBarrierOption>();
59   if (kIsDebugBuild) {
60     if (!IsRuntimeMethod()) {
61       CHECK(result != nullptr) << this;
62       if (kCheckDeclaringClassState) {
63         if (!(result->IsIdxLoaded() || result->IsErroneous())) {
64           LOG(FATAL_WITHOUT_ABORT) << "Class status: " << result->GetStatus();
65           LOG(FATAL) << result->PrettyClass();
66         }
67       }
68     } else {
69       CHECK(result == nullptr) << this;
70     }
71   }
72   return result;
73 }
74 
SetDeclaringClass(ObjPtr<mirror::Class> new_declaring_class)75 inline void ArtMethod::SetDeclaringClass(ObjPtr<mirror::Class> new_declaring_class) {
76   declaring_class_ = GcRoot<mirror::Class>(new_declaring_class);
77 }
78 
CASDeclaringClass(mirror::Class * expected_class,mirror::Class * desired_class)79 inline bool ArtMethod::CASDeclaringClass(mirror::Class* expected_class,
80                                          mirror::Class* desired_class) {
81   GcRoot<mirror::Class> expected_root(expected_class);
82   GcRoot<mirror::Class> desired_root(desired_class);
83   return reinterpret_cast<Atomic<GcRoot<mirror::Class>>*>(&declaring_class_)->
84       CompareExchangeStrongSequentiallyConsistent(
85           expected_root, desired_root);
86 }
87 
GetMethodIndex()88 inline uint16_t ArtMethod::GetMethodIndex() {
89   DCHECK(IsRuntimeMethod() || GetDeclaringClass()->IsResolved());
90   return method_index_;
91 }
92 
GetMethodIndexDuringLinking()93 inline uint16_t ArtMethod::GetMethodIndexDuringLinking() {
94   return method_index_;
95 }
96 
GetDexMethodIndex()97 inline uint32_t ArtMethod::GetDexMethodIndex() {
98   if (kCheckDeclaringClassState) {
99     CHECK(IsRuntimeMethod() || GetDeclaringClass()->IsIdxLoaded() ||
100           GetDeclaringClass()->IsErroneous());
101   }
102   return GetDexMethodIndexUnchecked();
103 }
104 
GetDexCacheResolvedMethods(PointerSize pointer_size)105 inline mirror::MethodDexCacheType* ArtMethod::GetDexCacheResolvedMethods(PointerSize pointer_size) {
106   return GetNativePointer<mirror::MethodDexCacheType*>(DexCacheResolvedMethodsOffset(pointer_size),
107                                                        pointer_size);
108 }
109 
GetDexCacheResolvedMethod(uint16_t method_index,PointerSize pointer_size)110 inline ArtMethod* ArtMethod::GetDexCacheResolvedMethod(uint16_t method_index,
111                                                        PointerSize pointer_size) {
112   // NOTE: Unchecked, i.e. not throwing AIOOB. We don't even know the length here
113   // without accessing the DexCache and we don't want to do that in release build.
114   DCHECK_LT(method_index, GetInterfaceMethodIfProxy(pointer_size)->GetDexFile()->NumMethodIds());
115   uint32_t slot_idx = method_index % mirror::DexCache::kDexCacheMethodCacheSize;
116   DCHECK_LT(slot_idx, GetInterfaceMethodIfProxy(pointer_size)->GetDexCache()->NumResolvedMethods());
117   mirror::MethodDexCachePair pair = mirror::DexCache::GetNativePairPtrSize(
118       GetDexCacheResolvedMethods(pointer_size), slot_idx, pointer_size);
119   ArtMethod* method = pair.GetObjectForIndex(method_index);
120   if (LIKELY(method != nullptr)) {
121     auto* declaring_class = method->GetDeclaringClass();
122     if (LIKELY(declaring_class == nullptr || !declaring_class->IsErroneous())) {
123       return method;
124     }
125   }
126   return nullptr;
127 }
128 
SetDexCacheResolvedMethod(uint16_t method_index,ArtMethod * new_method,PointerSize pointer_size)129 inline void ArtMethod::SetDexCacheResolvedMethod(uint16_t method_index,
130                                                  ArtMethod* new_method,
131                                                  PointerSize pointer_size) {
132   // NOTE: Unchecked, i.e. not throwing AIOOB. We don't even know the length here
133   // without accessing the DexCache and we don't want to do that in release build.
134   DCHECK_LT(method_index, GetInterfaceMethodIfProxy(pointer_size)->GetDexFile()->NumMethodIds());
135   DCHECK(new_method == nullptr || new_method->GetDeclaringClass() != nullptr);
136   uint32_t slot_idx = method_index % mirror::DexCache::kDexCacheMethodCacheSize;
137   DCHECK_LT(slot_idx, GetInterfaceMethodIfProxy(pointer_size)->GetDexCache()->NumResolvedMethods());
138   mirror::MethodDexCachePair pair(new_method, method_index);
139   mirror::DexCache::SetNativePairPtrSize(
140       GetDexCacheResolvedMethods(pointer_size), slot_idx, pair, pointer_size);
141 }
142 
HasDexCacheResolvedMethods(PointerSize pointer_size)143 inline bool ArtMethod::HasDexCacheResolvedMethods(PointerSize pointer_size) {
144   return GetDexCacheResolvedMethods(pointer_size) != nullptr;
145 }
146 
HasSameDexCacheResolvedMethods(ArtMethod * other,PointerSize pointer_size)147 inline bool ArtMethod::HasSameDexCacheResolvedMethods(ArtMethod* other, PointerSize pointer_size) {
148   return GetDexCacheResolvedMethods(pointer_size) ==
149       other->GetDexCacheResolvedMethods(pointer_size);
150 }
151 
HasSameDexCacheResolvedMethods(mirror::MethodDexCacheType * other_cache,PointerSize pointer_size)152 inline bool ArtMethod::HasSameDexCacheResolvedMethods(mirror::MethodDexCacheType* other_cache,
153                                                       PointerSize pointer_size) {
154   return GetDexCacheResolvedMethods(pointer_size) == other_cache;
155 }
156 
GetClassFromTypeIndex(dex::TypeIndex type_idx,bool resolve)157 inline mirror::Class* ArtMethod::GetClassFromTypeIndex(dex::TypeIndex type_idx, bool resolve) {
158   // TODO: Refactor this function into two functions, Resolve...() and Lookup...()
159   // so that we can properly annotate it with no-suspension possible / suspension possible.
160   ObjPtr<mirror::DexCache> dex_cache = GetDexCache();
161   ObjPtr<mirror::Class> type = dex_cache->GetResolvedType(type_idx);
162   if (UNLIKELY(type == nullptr)) {
163     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
164     if (resolve) {
165       type = class_linker->ResolveType(type_idx, this);
166       CHECK(type != nullptr || Thread::Current()->IsExceptionPending());
167     } else {
168       type = class_linker->LookupResolvedType(
169           *dex_cache->GetDexFile(), type_idx, dex_cache, GetClassLoader());
170     }
171   }
172   return type.Ptr();
173 }
174 
CheckIncompatibleClassChange(InvokeType type)175 inline bool ArtMethod::CheckIncompatibleClassChange(InvokeType type) {
176   switch (type) {
177     case kStatic:
178       return !IsStatic();
179     case kDirect:
180       return !IsDirect() || IsStatic();
181     case kVirtual: {
182       // We have an error if we are direct or a non-copied (i.e. not part of a real class) interface
183       // method.
184       mirror::Class* methods_class = GetDeclaringClass();
185       return IsDirect() || (methods_class->IsInterface() && !IsCopied());
186     }
187     case kSuper:
188       // Constructors and static methods are called with invoke-direct.
189       return IsConstructor() || IsStatic();
190     case kInterface: {
191       mirror::Class* methods_class = GetDeclaringClass();
192       return IsDirect() || !(methods_class->IsInterface() || methods_class->IsObjectClass());
193     }
194     default:
195       LOG(FATAL) << "Unreachable - invocation type: " << type;
196       UNREACHABLE();
197   }
198 }
199 
IsCalleeSaveMethod()200 inline bool ArtMethod::IsCalleeSaveMethod() {
201   if (!IsRuntimeMethod()) {
202     return false;
203   }
204   Runtime* runtime = Runtime::Current();
205   bool result = false;
206   for (uint32_t i = 0; i < static_cast<uint32_t>(CalleeSaveType::kLastCalleeSaveType); i++) {
207     if (this == runtime->GetCalleeSaveMethod(CalleeSaveType(i))) {
208       result = true;
209       break;
210     }
211   }
212   return result;
213 }
214 
IsResolutionMethod()215 inline bool ArtMethod::IsResolutionMethod() {
216   bool result = this == Runtime::Current()->GetResolutionMethod();
217   // Check that if we do think it is phony it looks like the resolution method.
218   DCHECK(!result || IsRuntimeMethod());
219   return result;
220 }
221 
IsImtUnimplementedMethod()222 inline bool ArtMethod::IsImtUnimplementedMethod() {
223   bool result = this == Runtime::Current()->GetImtUnimplementedMethod();
224   // Check that if we do think it is phony it looks like the imt unimplemented method.
225   DCHECK(!result || IsRuntimeMethod());
226   return result;
227 }
228 
GetDexFile()229 inline const DexFile* ArtMethod::GetDexFile() {
230   // It is safe to avoid the read barrier here since the dex file is constant, so if we read the
231   // from-space dex file pointer it will be equal to the to-space copy.
232   return GetDexCache<kWithoutReadBarrier>()->GetDexFile();
233 }
234 
GetDeclaringClassDescriptor()235 inline const char* ArtMethod::GetDeclaringClassDescriptor() {
236   uint32_t dex_method_idx = GetDexMethodIndex();
237   if (UNLIKELY(dex_method_idx == DexFile::kDexNoIndex)) {
238     return "<runtime method>";
239   }
240   DCHECK(!IsProxyMethod());
241   const DexFile* dex_file = GetDexFile();
242   return dex_file->GetMethodDeclaringClassDescriptor(dex_file->GetMethodId(dex_method_idx));
243 }
244 
GetShorty()245 inline const char* ArtMethod::GetShorty() {
246   uint32_t unused_length;
247   return GetShorty(&unused_length);
248 }
249 
GetShorty(uint32_t * out_length)250 inline const char* ArtMethod::GetShorty(uint32_t* out_length) {
251   DCHECK(!IsProxyMethod());
252   const DexFile* dex_file = GetDexFile();
253   return dex_file->GetMethodShorty(dex_file->GetMethodId(GetDexMethodIndex()), out_length);
254 }
255 
GetSignature()256 inline const Signature ArtMethod::GetSignature() {
257   uint32_t dex_method_idx = GetDexMethodIndex();
258   if (dex_method_idx != DexFile::kDexNoIndex) {
259     DCHECK(!IsProxyMethod());
260     const DexFile* dex_file = GetDexFile();
261     return dex_file->GetMethodSignature(dex_file->GetMethodId(dex_method_idx));
262   }
263   return Signature::NoSignature();
264 }
265 
GetName()266 inline const char* ArtMethod::GetName() {
267   uint32_t dex_method_idx = GetDexMethodIndex();
268   if (LIKELY(dex_method_idx != DexFile::kDexNoIndex)) {
269     DCHECK(!IsProxyMethod());
270     const DexFile* dex_file = GetDexFile();
271     return dex_file->GetMethodName(dex_file->GetMethodId(dex_method_idx));
272   }
273   Runtime* const runtime = Runtime::Current();
274   if (this == runtime->GetResolutionMethod()) {
275     return "<runtime internal resolution method>";
276   } else if (this == runtime->GetImtConflictMethod()) {
277     return "<runtime internal imt conflict method>";
278   } else if (this == runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveAllCalleeSaves)) {
279     return "<runtime internal callee-save all registers method>";
280   } else if (this == runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsOnly)) {
281     return "<runtime internal callee-save reference registers method>";
282   } else if (this == runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsAndArgs)) {
283     return "<runtime internal callee-save reference and argument registers method>";
284   } else if (this == runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveEverything)) {
285     return "<runtime internal save-every-register method>";
286   } else {
287     return "<unknown runtime internal method>";
288   }
289 }
290 
GetCodeItem()291 inline const DexFile::CodeItem* ArtMethod::GetCodeItem() {
292   return GetDexFile()->GetCodeItem(GetCodeItemOffset());
293 }
294 
IsResolvedTypeIdx(dex::TypeIndex type_idx)295 inline bool ArtMethod::IsResolvedTypeIdx(dex::TypeIndex type_idx) {
296   DCHECK(!IsProxyMethod());
297   return GetClassFromTypeIndex(type_idx, /* resolve */ false) != nullptr;
298 }
299 
GetLineNumFromDexPC(uint32_t dex_pc)300 inline int32_t ArtMethod::GetLineNumFromDexPC(uint32_t dex_pc) {
301   DCHECK(!IsProxyMethod());
302   if (dex_pc == DexFile::kDexNoIndex) {
303     return IsNative() ? -2 : -1;
304   }
305   return annotations::GetLineNumFromPC(GetDexFile(), this, dex_pc);
306 }
307 
GetPrototype()308 inline const DexFile::ProtoId& ArtMethod::GetPrototype() {
309   DCHECK(!IsProxyMethod());
310   const DexFile* dex_file = GetDexFile();
311   return dex_file->GetMethodPrototype(dex_file->GetMethodId(GetDexMethodIndex()));
312 }
313 
GetParameterTypeList()314 inline const DexFile::TypeList* ArtMethod::GetParameterTypeList() {
315   DCHECK(!IsProxyMethod());
316   const DexFile* dex_file = GetDexFile();
317   const DexFile::ProtoId& proto = dex_file->GetMethodPrototype(
318       dex_file->GetMethodId(GetDexMethodIndex()));
319   return dex_file->GetProtoParameters(proto);
320 }
321 
GetDeclaringClassSourceFile()322 inline const char* ArtMethod::GetDeclaringClassSourceFile() {
323   DCHECK(!IsProxyMethod());
324   return GetDeclaringClass()->GetSourceFile();
325 }
326 
GetClassDefIndex()327 inline uint16_t ArtMethod::GetClassDefIndex() {
328   DCHECK(!IsProxyMethod());
329   if (LIKELY(!IsObsolete())) {
330     return GetDeclaringClass()->GetDexClassDefIndex();
331   } else {
332     return FindObsoleteDexClassDefIndex();
333   }
334 }
335 
GetClassDef()336 inline const DexFile::ClassDef& ArtMethod::GetClassDef() {
337   DCHECK(!IsProxyMethod());
338   return GetDexFile()->GetClassDef(GetClassDefIndex());
339 }
340 
GetReturnTypeDescriptor()341 inline const char* ArtMethod::GetReturnTypeDescriptor() {
342   DCHECK(!IsProxyMethod());
343   const DexFile* dex_file = GetDexFile();
344   const DexFile::MethodId& method_id = dex_file->GetMethodId(GetDexMethodIndex());
345   const DexFile::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id);
346   return dex_file->GetTypeDescriptor(dex_file->GetTypeId(proto_id.return_type_idx_));
347 }
348 
GetReturnTypePrimitive()349 inline Primitive::Type ArtMethod::GetReturnTypePrimitive() {
350   return Primitive::GetType(GetReturnTypeDescriptor()[0]);
351 }
352 
GetTypeDescriptorFromTypeIdx(dex::TypeIndex type_idx)353 inline const char* ArtMethod::GetTypeDescriptorFromTypeIdx(dex::TypeIndex type_idx) {
354   DCHECK(!IsProxyMethod());
355   const DexFile* dex_file = GetDexFile();
356   return dex_file->GetTypeDescriptor(dex_file->GetTypeId(type_idx));
357 }
358 
GetClassLoader()359 inline mirror::ClassLoader* ArtMethod::GetClassLoader() {
360   DCHECK(!IsProxyMethod());
361   return GetDeclaringClass()->GetClassLoader();
362 }
363 
364 template <ReadBarrierOption kReadBarrierOption>
GetDexCache()365 inline mirror::DexCache* ArtMethod::GetDexCache() {
366   if (LIKELY(!IsObsolete())) {
367     mirror::Class* klass = GetDeclaringClass<kReadBarrierOption>();
368     return klass->GetDexCache<kDefaultVerifyFlags, kReadBarrierOption>();
369   } else {
370     DCHECK(!IsProxyMethod());
371     return GetObsoleteDexCache();
372   }
373 }
374 
IsProxyMethod()375 inline bool ArtMethod::IsProxyMethod() {
376   // Avoid read barrier since the from-space version of the class will have the correct proxy class
377   // flags since they are constant for the lifetime of the class.
378   return GetDeclaringClass<kWithoutReadBarrier>()->IsProxyClass();
379 }
380 
GetInterfaceMethodIfProxy(PointerSize pointer_size)381 inline ArtMethod* ArtMethod::GetInterfaceMethodIfProxy(PointerSize pointer_size) {
382   if (LIKELY(!IsProxyMethod())) {
383     return this;
384   }
385   uint32_t method_index = GetDexMethodIndex();
386   uint32_t slot_idx = method_index % mirror::DexCache::kDexCacheMethodCacheSize;
387   mirror::MethodDexCachePair pair = mirror::DexCache::GetNativePairPtrSize(
388       GetDexCacheResolvedMethods(pointer_size), slot_idx, pointer_size);
389   ArtMethod* interface_method = pair.GetObjectForIndex(method_index);
390   if (LIKELY(interface_method != nullptr)) {
391     DCHECK_EQ(interface_method, Runtime::Current()->GetClassLinker()->FindMethodForProxy(this));
392   } else {
393     interface_method = Runtime::Current()->GetClassLinker()->FindMethodForProxy(this);
394     DCHECK(interface_method != nullptr);
395   }
396   return interface_method;
397 }
398 
SetDexCacheResolvedMethods(mirror::MethodDexCacheType * new_dex_cache_methods,PointerSize pointer_size)399 inline void ArtMethod::SetDexCacheResolvedMethods(mirror::MethodDexCacheType* new_dex_cache_methods,
400                                                   PointerSize pointer_size) {
401   SetNativePointer(DexCacheResolvedMethodsOffset(pointer_size),
402                    new_dex_cache_methods,
403                    pointer_size);
404 }
405 
GetReturnType(bool resolve)406 inline mirror::Class* ArtMethod::GetReturnType(bool resolve) {
407   DCHECK(!IsProxyMethod());
408   const DexFile* dex_file = GetDexFile();
409   const DexFile::MethodId& method_id = dex_file->GetMethodId(GetDexMethodIndex());
410   const DexFile::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id);
411   dex::TypeIndex return_type_idx = proto_id.return_type_idx_;
412   return GetClassFromTypeIndex(return_type_idx, resolve);
413 }
414 
HasSingleImplementation()415 inline bool ArtMethod::HasSingleImplementation() {
416   if (IsFinal() || GetDeclaringClass()->IsFinal()) {
417     // We don't set kAccSingleImplementation for these cases since intrinsic
418     // can use the flag also.
419     return true;
420   }
421   return (GetAccessFlags() & kAccSingleImplementation) != 0;
422 }
423 
SetIntrinsic(uint32_t intrinsic)424 inline void ArtMethod::SetIntrinsic(uint32_t intrinsic) {
425   DCHECK(IsUint<8>(intrinsic));
426   // Currently we only do intrinsics for static/final methods or methods of final
427   // classes. We don't set kHasSingleImplementation for those methods.
428   DCHECK(IsStatic() || IsFinal() || GetDeclaringClass()->IsFinal()) <<
429       "Potential conflict with kAccSingleImplementation";
430   uint32_t new_value = (GetAccessFlags() & kAccFlagsNotUsedByIntrinsic) |
431       kAccIntrinsic |
432       (intrinsic << POPCOUNT(kAccFlagsNotUsedByIntrinsic));
433   if (kIsDebugBuild) {
434     uint32_t java_flags = (GetAccessFlags() & kAccJavaFlagsMask);
435     bool is_constructor = IsConstructor();
436     bool is_synchronized = IsSynchronized();
437     bool skip_access_checks = SkipAccessChecks();
438     bool is_fast_native = IsFastNative();
439     bool is_copied = IsCopied();
440     bool is_miranda = IsMiranda();
441     bool is_default = IsDefault();
442     bool is_default_conflict = IsDefaultConflicting();
443     bool is_compilable = IsCompilable();
444     bool must_count_locks = MustCountLocks();
445     SetAccessFlags(new_value);
446     DCHECK_EQ(java_flags, (GetAccessFlags() & kAccJavaFlagsMask));
447     DCHECK_EQ(is_constructor, IsConstructor());
448     DCHECK_EQ(is_synchronized, IsSynchronized());
449     DCHECK_EQ(skip_access_checks, SkipAccessChecks());
450     DCHECK_EQ(is_fast_native, IsFastNative());
451     DCHECK_EQ(is_copied, IsCopied());
452     DCHECK_EQ(is_miranda, IsMiranda());
453     DCHECK_EQ(is_default, IsDefault());
454     DCHECK_EQ(is_default_conflict, IsDefaultConflicting());
455     DCHECK_EQ(is_compilable, IsCompilable());
456     DCHECK_EQ(must_count_locks, MustCountLocks());
457   } else {
458     SetAccessFlags(new_value);
459   }
460 }
461 
462 template<ReadBarrierOption kReadBarrierOption, typename RootVisitorType>
VisitRoots(RootVisitorType & visitor,PointerSize pointer_size)463 void ArtMethod::VisitRoots(RootVisitorType& visitor, PointerSize pointer_size) {
464   if (LIKELY(!declaring_class_.IsNull())) {
465     visitor.VisitRoot(declaring_class_.AddressWithoutBarrier());
466     mirror::Class* klass = declaring_class_.Read<kReadBarrierOption>();
467     if (UNLIKELY(klass->IsProxyClass())) {
468       // For normal methods, dex cache shortcuts will be visited through the declaring class.
469       // However, for proxies we need to keep the interface method alive, so we visit its roots.
470       ArtMethod* interface_method = GetInterfaceMethodIfProxy(pointer_size);
471       DCHECK(interface_method != nullptr);
472       interface_method->VisitRoots(visitor, pointer_size);
473     }
474   }
475 }
476 
477 template <typename Visitor>
UpdateObjectsForImageRelocation(const Visitor & visitor,PointerSize pointer_size)478 inline void ArtMethod::UpdateObjectsForImageRelocation(const Visitor& visitor,
479                                                        PointerSize pointer_size) {
480   mirror::Class* old_class = GetDeclaringClassUnchecked<kWithoutReadBarrier>();
481   mirror::Class* new_class = visitor(old_class);
482   if (old_class != new_class) {
483     SetDeclaringClass(new_class);
484   }
485   mirror::MethodDexCacheType* old_methods = GetDexCacheResolvedMethods(pointer_size);
486   mirror::MethodDexCacheType* new_methods = visitor(old_methods);
487   if (old_methods != new_methods) {
488     SetDexCacheResolvedMethods(new_methods, pointer_size);
489   }
490 }
491 
492 template <ReadBarrierOption kReadBarrierOption, typename Visitor>
UpdateEntrypoints(const Visitor & visitor,PointerSize pointer_size)493 inline void ArtMethod::UpdateEntrypoints(const Visitor& visitor, PointerSize pointer_size) {
494   if (IsNative<kReadBarrierOption>()) {
495     const void* old_native_code = GetEntryPointFromJniPtrSize(pointer_size);
496     const void* new_native_code = visitor(old_native_code);
497     if (old_native_code != new_native_code) {
498       SetEntryPointFromJniPtrSize(new_native_code, pointer_size);
499     }
500   } else {
501     DCHECK(GetDataPtrSize(pointer_size) == nullptr);
502   }
503   const void* old_code = GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
504   const void* new_code = visitor(old_code);
505   if (old_code != new_code) {
506     SetEntryPointFromQuickCompiledCodePtrSize(new_code, pointer_size);
507   }
508 }
509 
510 }  // namespace art
511 
512 #endif  // ART_RUNTIME_ART_METHOD_INL_H_
513