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