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 "dex_file.h"
25 #include "dex_file-inl.h"
26 #include "gc_root-inl.h"
27 #include "mirror/class-inl.h"
28 #include "mirror/dex_cache.h"
29 #include "mirror/object-inl.h"
30 #include "mirror/object_array.h"
31 #include "oat.h"
32 #include "quick/quick_method_frame_info.h"
33 #include "read_barrier-inl.h"
34 #include "runtime-inl.h"
35 #include "utils.h"
36
37 namespace art {
38
GetDeclaringClassUnchecked()39 inline mirror::Class* ArtMethod::GetDeclaringClassUnchecked() {
40 return declaring_class_.Read();
41 }
42
GetDeclaringClassNoBarrier()43 inline mirror::Class* ArtMethod::GetDeclaringClassNoBarrier() {
44 return declaring_class_.Read<kWithoutReadBarrier>();
45 }
46
GetDeclaringClass()47 inline mirror::Class* ArtMethod::GetDeclaringClass() {
48 mirror::Class* result = GetDeclaringClassUnchecked();
49 if (kIsDebugBuild) {
50 if (!IsRuntimeMethod()) {
51 CHECK(result != nullptr) << this;
52 CHECK(result->IsIdxLoaded() || result->IsErroneous())
53 << result->GetStatus() << " " << PrettyClass(result);
54 } else {
55 CHECK(result == nullptr) << this;
56 }
57 }
58 return result;
59 }
60
SetDeclaringClass(mirror::Class * new_declaring_class)61 inline void ArtMethod::SetDeclaringClass(mirror::Class* new_declaring_class) {
62 declaring_class_ = GcRoot<mirror::Class>(new_declaring_class);
63 }
64
GetAccessFlags()65 inline uint32_t ArtMethod::GetAccessFlags() {
66 DCHECK(IsRuntimeMethod() || GetDeclaringClass()->IsIdxLoaded() ||
67 GetDeclaringClass()->IsErroneous());
68 return access_flags_;
69 }
70
GetMethodIndex()71 inline uint16_t ArtMethod::GetMethodIndex() {
72 DCHECK(IsRuntimeMethod() || GetDeclaringClass()->IsResolved() ||
73 GetDeclaringClass()->IsErroneous());
74 return method_index_;
75 }
76
GetMethodIndexDuringLinking()77 inline uint16_t ArtMethod::GetMethodIndexDuringLinking() {
78 return method_index_;
79 }
80
GetDexMethodIndex()81 inline uint32_t ArtMethod::GetDexMethodIndex() {
82 DCHECK(IsRuntimeMethod() || GetDeclaringClass()->IsIdxLoaded() ||
83 GetDeclaringClass()->IsErroneous());
84 return dex_method_index_;
85 }
86
GetDexCacheResolvedMethods()87 inline mirror::PointerArray* ArtMethod::GetDexCacheResolvedMethods() {
88 return dex_cache_resolved_methods_.Read();
89 }
90
GetDexCacheResolvedMethod(uint16_t method_index,size_t ptr_size)91 inline ArtMethod* ArtMethod::GetDexCacheResolvedMethod(uint16_t method_index, size_t ptr_size) {
92 auto* method = GetDexCacheResolvedMethods()->GetElementPtrSize<ArtMethod*>(
93 method_index, ptr_size);
94 if (LIKELY(method != nullptr)) {
95 auto* declaring_class = method->GetDeclaringClass();
96 if (LIKELY(declaring_class == nullptr || !declaring_class->IsErroneous())) {
97 return method;
98 }
99 }
100 return nullptr;
101 }
102
SetDexCacheResolvedMethod(uint16_t method_idx,ArtMethod * new_method,size_t ptr_size)103 inline void ArtMethod::SetDexCacheResolvedMethod(uint16_t method_idx, ArtMethod* new_method,
104 size_t ptr_size) {
105 DCHECK(new_method == nullptr || new_method->GetDeclaringClass() != nullptr);
106 GetDexCacheResolvedMethods()->SetElementPtrSize(method_idx, new_method, ptr_size);
107 }
108
HasDexCacheResolvedMethods()109 inline bool ArtMethod::HasDexCacheResolvedMethods() {
110 return GetDexCacheResolvedMethods() != nullptr;
111 }
112
HasSameDexCacheResolvedMethods(mirror::PointerArray * other_cache)113 inline bool ArtMethod::HasSameDexCacheResolvedMethods(mirror::PointerArray* other_cache) {
114 return GetDexCacheResolvedMethods() == other_cache;
115 }
116
HasSameDexCacheResolvedMethods(ArtMethod * other)117 inline bool ArtMethod::HasSameDexCacheResolvedMethods(ArtMethod* other) {
118 return GetDexCacheResolvedMethods() == other->GetDexCacheResolvedMethods();
119 }
120
GetDexCacheResolvedTypes()121 inline mirror::ObjectArray<mirror::Class>* ArtMethod::GetDexCacheResolvedTypes() {
122 return dex_cache_resolved_types_.Read();
123 }
124
125 template <bool kWithCheck>
GetDexCacheResolvedType(uint32_t type_index)126 inline mirror::Class* ArtMethod::GetDexCacheResolvedType(uint32_t type_index) {
127 mirror::Class* klass = kWithCheck ?
128 GetDexCacheResolvedTypes()->Get(type_index) :
129 GetDexCacheResolvedTypes()->GetWithoutChecks(type_index);
130 return (klass != nullptr && !klass->IsErroneous()) ? klass : nullptr;
131 }
132
HasDexCacheResolvedTypes()133 inline bool ArtMethod::HasDexCacheResolvedTypes() {
134 return GetDexCacheResolvedTypes() != nullptr;
135 }
136
HasSameDexCacheResolvedTypes(mirror::ObjectArray<mirror::Class> * other_cache)137 inline bool ArtMethod::HasSameDexCacheResolvedTypes(
138 mirror::ObjectArray<mirror::Class>* other_cache) {
139 return GetDexCacheResolvedTypes() == other_cache;
140 }
141
HasSameDexCacheResolvedTypes(ArtMethod * other)142 inline bool ArtMethod::HasSameDexCacheResolvedTypes(ArtMethod* other) {
143 return GetDexCacheResolvedTypes() == other->GetDexCacheResolvedTypes();
144 }
145
GetClassFromTypeIndex(uint16_t type_idx,bool resolve)146 inline mirror::Class* ArtMethod::GetClassFromTypeIndex(uint16_t type_idx, bool resolve) {
147 mirror::Class* type = GetDexCacheResolvedType(type_idx);
148 if (type == nullptr && resolve) {
149 type = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, this);
150 CHECK(type != nullptr || Thread::Current()->IsExceptionPending());
151 }
152 return type;
153 }
154
GetCodeSize()155 inline uint32_t ArtMethod::GetCodeSize() {
156 DCHECK(!IsRuntimeMethod() && !IsProxyMethod()) << PrettyMethod(this);
157 return GetCodeSize(EntryPointToCodePointer(GetEntryPointFromQuickCompiledCode()));
158 }
159
GetCodeSize(const void * code)160 inline uint32_t ArtMethod::GetCodeSize(const void* code) {
161 if (code == nullptr) {
162 return 0u;
163 }
164 return reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].code_size_;
165 }
166
CheckIncompatibleClassChange(InvokeType type)167 inline bool ArtMethod::CheckIncompatibleClassChange(InvokeType type) {
168 switch (type) {
169 case kStatic:
170 return !IsStatic();
171 case kDirect:
172 return !IsDirect() || IsStatic();
173 case kVirtual: {
174 mirror::Class* methods_class = GetDeclaringClass();
175 return IsDirect() || (methods_class->IsInterface() && !IsMiranda());
176 }
177 case kSuper:
178 // Constructors and static methods are called with invoke-direct.
179 // Interface methods cannot be invoked with invoke-super.
180 return IsConstructor() || IsStatic() || GetDeclaringClass()->IsInterface();
181 case kInterface: {
182 mirror::Class* methods_class = GetDeclaringClass();
183 return IsDirect() || !(methods_class->IsInterface() || methods_class->IsObjectClass());
184 }
185 default:
186 LOG(FATAL) << "Unreachable - invocation type: " << type;
187 UNREACHABLE();
188 }
189 }
190
GetQuickOatCodeOffset()191 inline uint32_t ArtMethod::GetQuickOatCodeOffset() {
192 DCHECK(!Runtime::Current()->IsStarted());
193 return PointerToLowMemUInt32(GetEntryPointFromQuickCompiledCode());
194 }
195
SetQuickOatCodeOffset(uint32_t code_offset)196 inline void ArtMethod::SetQuickOatCodeOffset(uint32_t code_offset) {
197 DCHECK(!Runtime::Current()->IsStarted());
198 SetEntryPointFromQuickCompiledCode(reinterpret_cast<void*>(code_offset));
199 }
200
GetMappingTable(size_t pointer_size)201 inline const uint8_t* ArtMethod::GetMappingTable(size_t pointer_size) {
202 const void* code_pointer = GetQuickOatCodePointer(pointer_size);
203 if (code_pointer == nullptr) {
204 return nullptr;
205 }
206 return GetMappingTable(code_pointer, pointer_size);
207 }
208
GetMappingTable(const void * code_pointer,size_t pointer_size)209 inline const uint8_t* ArtMethod::GetMappingTable(const void* code_pointer, size_t pointer_size) {
210 DCHECK(code_pointer != nullptr);
211 DCHECK_EQ(code_pointer, GetQuickOatCodePointer(pointer_size));
212 uint32_t offset =
213 reinterpret_cast<const OatQuickMethodHeader*>(code_pointer)[-1].mapping_table_offset_;
214 if (UNLIKELY(offset == 0u)) {
215 return nullptr;
216 }
217 return reinterpret_cast<const uint8_t*>(code_pointer) - offset;
218 }
219
GetVmapTable(size_t pointer_size)220 inline const uint8_t* ArtMethod::GetVmapTable(size_t pointer_size) {
221 const void* code_pointer = GetQuickOatCodePointer(pointer_size);
222 if (code_pointer == nullptr) {
223 return nullptr;
224 }
225 return GetVmapTable(code_pointer, pointer_size);
226 }
227
GetVmapTable(const void * code_pointer,size_t pointer_size)228 inline const uint8_t* ArtMethod::GetVmapTable(const void* code_pointer, size_t pointer_size) {
229 CHECK(!IsOptimized(pointer_size)) << "Unimplemented vmap table for optimized compiler";
230 DCHECK(code_pointer != nullptr);
231 DCHECK_EQ(code_pointer, GetQuickOatCodePointer(pointer_size));
232 uint32_t offset =
233 reinterpret_cast<const OatQuickMethodHeader*>(code_pointer)[-1].vmap_table_offset_;
234 if (UNLIKELY(offset == 0u)) {
235 return nullptr;
236 }
237 return reinterpret_cast<const uint8_t*>(code_pointer) - offset;
238 }
239
GetOptimizedCodeInfo()240 inline CodeInfo ArtMethod::GetOptimizedCodeInfo() {
241 DCHECK(IsOptimized(sizeof(void*)));
242 const void* code_pointer = GetQuickOatCodePointer(sizeof(void*));
243 DCHECK(code_pointer != nullptr);
244 uint32_t offset =
245 reinterpret_cast<const OatQuickMethodHeader*>(code_pointer)[-1].vmap_table_offset_;
246 const void* data =
247 reinterpret_cast<const void*>(reinterpret_cast<const uint8_t*>(code_pointer) - offset);
248 return CodeInfo(data);
249 }
250
GetNativeGcMap(size_t pointer_size)251 inline const uint8_t* ArtMethod::GetNativeGcMap(size_t pointer_size) {
252 const void* code_pointer = GetQuickOatCodePointer(pointer_size);
253 if (code_pointer == nullptr) {
254 return nullptr;
255 }
256 return GetNativeGcMap(code_pointer, pointer_size);
257 }
258
GetNativeGcMap(const void * code_pointer,size_t pointer_size)259 inline const uint8_t* ArtMethod::GetNativeGcMap(const void* code_pointer, size_t pointer_size) {
260 DCHECK(code_pointer != nullptr);
261 DCHECK_EQ(code_pointer, GetQuickOatCodePointer(pointer_size));
262 uint32_t offset =
263 reinterpret_cast<const OatQuickMethodHeader*>(code_pointer)[-1].gc_map_offset_;
264 if (UNLIKELY(offset == 0u)) {
265 return nullptr;
266 }
267 return reinterpret_cast<const uint8_t*>(code_pointer) - offset;
268 }
269
IsRuntimeMethod()270 inline bool ArtMethod::IsRuntimeMethod() {
271 return dex_method_index_ == DexFile::kDexNoIndex;
272 }
273
IsCalleeSaveMethod()274 inline bool ArtMethod::IsCalleeSaveMethod() {
275 if (!IsRuntimeMethod()) {
276 return false;
277 }
278 Runtime* runtime = Runtime::Current();
279 bool result = false;
280 for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
281 if (this == runtime->GetCalleeSaveMethod(Runtime::CalleeSaveType(i))) {
282 result = true;
283 break;
284 }
285 }
286 return result;
287 }
288
IsResolutionMethod()289 inline bool ArtMethod::IsResolutionMethod() {
290 bool result = this == Runtime::Current()->GetResolutionMethod();
291 // Check that if we do think it is phony it looks like the resolution method.
292 DCHECK(!result || IsRuntimeMethod());
293 return result;
294 }
295
IsImtConflictMethod()296 inline bool ArtMethod::IsImtConflictMethod() {
297 bool result = this == Runtime::Current()->GetImtConflictMethod();
298 // Check that if we do think it is phony it looks like the imt conflict method.
299 DCHECK(!result || IsRuntimeMethod());
300 return result;
301 }
302
IsImtUnimplementedMethod()303 inline bool ArtMethod::IsImtUnimplementedMethod() {
304 bool result = this == Runtime::Current()->GetImtUnimplementedMethod();
305 // Check that if we do think it is phony it looks like the imt unimplemented method.
306 DCHECK(!result || IsRuntimeMethod());
307 return result;
308 }
309
NativeQuickPcOffset(const uintptr_t pc)310 inline uintptr_t ArtMethod::NativeQuickPcOffset(const uintptr_t pc) {
311 const void* code = Runtime::Current()->GetInstrumentation()->GetQuickCodeFor(
312 this, sizeof(void*));
313 return pc - reinterpret_cast<uintptr_t>(code);
314 }
315
GetQuickFrameInfo(const void * code_pointer)316 inline QuickMethodFrameInfo ArtMethod::GetQuickFrameInfo(const void* code_pointer) {
317 DCHECK(code_pointer != nullptr);
318 if (kIsDebugBuild && !IsProxyMethod()) {
319 CHECK_EQ(code_pointer, GetQuickOatCodePointer(sizeof(void*)));
320 }
321 return reinterpret_cast<const OatQuickMethodHeader*>(code_pointer)[-1].frame_info_;
322 }
323
GetDexFile()324 inline const DexFile* ArtMethod::GetDexFile() {
325 return GetDexCache()->GetDexFile();
326 }
327
GetDeclaringClassDescriptor()328 inline const char* ArtMethod::GetDeclaringClassDescriptor() {
329 uint32_t dex_method_idx = GetDexMethodIndex();
330 if (UNLIKELY(dex_method_idx == DexFile::kDexNoIndex)) {
331 return "<runtime method>";
332 }
333 DCHECK(!IsProxyMethod());
334 const DexFile* dex_file = GetDexFile();
335 return dex_file->GetMethodDeclaringClassDescriptor(dex_file->GetMethodId(dex_method_idx));
336 }
337
GetShorty(uint32_t * out_length)338 inline const char* ArtMethod::GetShorty(uint32_t* out_length) {
339 DCHECK(!IsProxyMethod());
340 const DexFile* dex_file = GetDexFile();
341 return dex_file->GetMethodShorty(dex_file->GetMethodId(GetDexMethodIndex()), out_length);
342 }
343
GetSignature()344 inline const Signature ArtMethod::GetSignature() {
345 uint32_t dex_method_idx = GetDexMethodIndex();
346 if (dex_method_idx != DexFile::kDexNoIndex) {
347 DCHECK(!IsProxyMethod());
348 const DexFile* dex_file = GetDexFile();
349 return dex_file->GetMethodSignature(dex_file->GetMethodId(dex_method_idx));
350 }
351 return Signature::NoSignature();
352 }
353
GetName()354 inline const char* ArtMethod::GetName() {
355 uint32_t dex_method_idx = GetDexMethodIndex();
356 if (LIKELY(dex_method_idx != DexFile::kDexNoIndex)) {
357 DCHECK(!IsProxyMethod());
358 const DexFile* dex_file = GetDexFile();
359 return dex_file->GetMethodName(dex_file->GetMethodId(dex_method_idx));
360 }
361 Runtime* const runtime = Runtime::Current();
362 if (this == runtime->GetResolutionMethod()) {
363 return "<runtime internal resolution method>";
364 } else if (this == runtime->GetImtConflictMethod()) {
365 return "<runtime internal imt conflict method>";
366 } else if (this == runtime->GetCalleeSaveMethod(Runtime::kSaveAll)) {
367 return "<runtime internal callee-save all registers method>";
368 } else if (this == runtime->GetCalleeSaveMethod(Runtime::kRefsOnly)) {
369 return "<runtime internal callee-save reference registers method>";
370 } else if (this == runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs)) {
371 return "<runtime internal callee-save reference and argument registers method>";
372 } else {
373 return "<unknown runtime internal method>";
374 }
375 }
376
GetCodeItem()377 inline const DexFile::CodeItem* ArtMethod::GetCodeItem() {
378 return GetDeclaringClass()->GetDexFile().GetCodeItem(GetCodeItemOffset());
379 }
380
IsResolvedTypeIdx(uint16_t type_idx)381 inline bool ArtMethod::IsResolvedTypeIdx(uint16_t type_idx) {
382 DCHECK(!IsProxyMethod());
383 return GetDexCacheResolvedType(type_idx) != nullptr;
384 }
385
GetLineNumFromDexPC(uint32_t dex_pc)386 inline int32_t ArtMethod::GetLineNumFromDexPC(uint32_t dex_pc) {
387 DCHECK(!IsProxyMethod());
388 if (dex_pc == DexFile::kDexNoIndex) {
389 return IsNative() ? -2 : -1;
390 }
391 return GetDexFile()->GetLineNumFromPC(this, dex_pc);
392 }
393
GetPrototype()394 inline const DexFile::ProtoId& ArtMethod::GetPrototype() {
395 DCHECK(!IsProxyMethod());
396 const DexFile* dex_file = GetDexFile();
397 return dex_file->GetMethodPrototype(dex_file->GetMethodId(GetDexMethodIndex()));
398 }
399
GetParameterTypeList()400 inline const DexFile::TypeList* ArtMethod::GetParameterTypeList() {
401 DCHECK(!IsProxyMethod());
402 const DexFile* dex_file = GetDexFile();
403 const DexFile::ProtoId& proto = dex_file->GetMethodPrototype(
404 dex_file->GetMethodId(GetDexMethodIndex()));
405 return dex_file->GetProtoParameters(proto);
406 }
407
GetDeclaringClassSourceFile()408 inline const char* ArtMethod::GetDeclaringClassSourceFile() {
409 DCHECK(!IsProxyMethod());
410 return GetDeclaringClass()->GetSourceFile();
411 }
412
GetClassDefIndex()413 inline uint16_t ArtMethod::GetClassDefIndex() {
414 DCHECK(!IsProxyMethod());
415 return GetDeclaringClass()->GetDexClassDefIndex();
416 }
417
GetClassDef()418 inline const DexFile::ClassDef& ArtMethod::GetClassDef() {
419 DCHECK(!IsProxyMethod());
420 return GetDexFile()->GetClassDef(GetClassDefIndex());
421 }
422
GetReturnTypeDescriptor()423 inline const char* ArtMethod::GetReturnTypeDescriptor() {
424 DCHECK(!IsProxyMethod());
425 const DexFile* dex_file = GetDexFile();
426 const DexFile::MethodId& method_id = dex_file->GetMethodId(GetDexMethodIndex());
427 const DexFile::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id);
428 uint16_t return_type_idx = proto_id.return_type_idx_;
429 return dex_file->GetTypeDescriptor(dex_file->GetTypeId(return_type_idx));
430 }
431
GetTypeDescriptorFromTypeIdx(uint16_t type_idx)432 inline const char* ArtMethod::GetTypeDescriptorFromTypeIdx(uint16_t type_idx) {
433 DCHECK(!IsProxyMethod());
434 const DexFile* dex_file = GetDexFile();
435 return dex_file->GetTypeDescriptor(dex_file->GetTypeId(type_idx));
436 }
437
GetClassLoader()438 inline mirror::ClassLoader* ArtMethod::GetClassLoader() {
439 DCHECK(!IsProxyMethod());
440 return GetDeclaringClass()->GetClassLoader();
441 }
442
GetDexCache()443 inline mirror::DexCache* ArtMethod::GetDexCache() {
444 DCHECK(!IsProxyMethod());
445 return GetDeclaringClass()->GetDexCache();
446 }
447
IsProxyMethod()448 inline bool ArtMethod::IsProxyMethod() {
449 return GetDeclaringClass()->IsProxyClass();
450 }
451
GetInterfaceMethodIfProxy(size_t pointer_size)452 inline ArtMethod* ArtMethod::GetInterfaceMethodIfProxy(size_t pointer_size) {
453 if (LIKELY(!IsProxyMethod())) {
454 return this;
455 }
456 mirror::Class* klass = GetDeclaringClass();
457 auto interface_method = GetDexCacheResolvedMethods()->GetElementPtrSize<ArtMethod*>(
458 GetDexMethodIndex(), pointer_size);
459 DCHECK(interface_method != nullptr);
460 DCHECK_EQ(interface_method,
461 Runtime::Current()->GetClassLinker()->FindMethodForProxy(klass, this));
462 return interface_method;
463 }
464
SetDexCacheResolvedMethods(mirror::PointerArray * new_dex_cache_methods)465 inline void ArtMethod::SetDexCacheResolvedMethods(mirror::PointerArray* new_dex_cache_methods) {
466 dex_cache_resolved_methods_ = GcRoot<mirror::PointerArray>(new_dex_cache_methods);
467 }
468
SetDexCacheResolvedTypes(mirror::ObjectArray<mirror::Class> * new_dex_cache_types)469 inline void ArtMethod::SetDexCacheResolvedTypes(
470 mirror::ObjectArray<mirror::Class>* new_dex_cache_types) {
471 dex_cache_resolved_types_ = GcRoot<mirror::ObjectArray<mirror::Class>>(new_dex_cache_types);
472 }
473
GetReturnType(bool resolve)474 inline mirror::Class* ArtMethod::GetReturnType(bool resolve) {
475 DCHECK(!IsProxyMethod());
476 const DexFile* dex_file = GetDexFile();
477 const DexFile::MethodId& method_id = dex_file->GetMethodId(GetDexMethodIndex());
478 const DexFile::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id);
479 uint16_t return_type_idx = proto_id.return_type_idx_;
480 mirror::Class* type = GetDexCacheResolvedType(return_type_idx);
481 if (type == nullptr && resolve) {
482 type = Runtime::Current()->GetClassLinker()->ResolveType(return_type_idx, this);
483 CHECK(type != nullptr || Thread::Current()->IsExceptionPending());
484 }
485 return type;
486 }
487
488 template<typename RootVisitorType>
VisitRoots(RootVisitorType & visitor)489 void ArtMethod::VisitRoots(RootVisitorType& visitor) {
490 visitor.VisitRootIfNonNull(declaring_class_.AddressWithoutBarrier());
491 visitor.VisitRootIfNonNull(dex_cache_resolved_methods_.AddressWithoutBarrier());
492 visitor.VisitRootIfNonNull(dex_cache_resolved_types_.AddressWithoutBarrier());
493 }
494
CopyFrom(const ArtMethod * src,size_t image_pointer_size)495 inline void ArtMethod::CopyFrom(const ArtMethod* src, size_t image_pointer_size) {
496 memcpy(reinterpret_cast<void*>(this), reinterpret_cast<const void*>(src),
497 ObjectSize(image_pointer_size));
498 declaring_class_ = GcRoot<mirror::Class>(const_cast<ArtMethod*>(src)->GetDeclaringClass());
499 dex_cache_resolved_methods_ = GcRoot<mirror::PointerArray>(
500 const_cast<ArtMethod*>(src)->GetDexCacheResolvedMethods());
501 dex_cache_resolved_types_ = GcRoot<mirror::ObjectArray<mirror::Class>>(
502 const_cast<ArtMethod*>(src)->GetDexCacheResolvedTypes());
503 }
504
505 } // namespace art
506
507 #endif // ART_RUNTIME_ART_METHOD_INL_H_
508