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