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