• 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 "class_linker-inl.h"
25 #include "common_throws.h"
26 #include "dex/code_item_accessors-inl.h"
27 #include "dex/dex_file-inl.h"
28 #include "dex/dex_file_annotations.h"
29 #include "dex/dex_file_types.h"
30 #include "dex/invoke_type.h"
31 #include "dex/primitive.h"
32 #include "dex/signature.h"
33 #include "gc_root-inl.h"
34 #include "imtable-inl.h"
35 #include "intrinsics_enum.h"
36 #include "jit/jit.h"
37 #include "jit/profiling_info.h"
38 #include "mirror/class-inl.h"
39 #include "mirror/dex_cache-inl.h"
40 #include "mirror/object-inl.h"
41 #include "mirror/object_array.h"
42 #include "mirror/string.h"
43 #include "obj_ptr-inl.h"
44 #include "quick/quick_method_frame_info.h"
45 #include "read_barrier-inl.h"
46 #include "runtime-inl.h"
47 #include "thread-current-inl.h"
48 
49 namespace art {
50 
51 template <ReadBarrierOption kReadBarrierOption>
GetDeclaringClassUnchecked()52 inline ObjPtr<mirror::Class> ArtMethod::GetDeclaringClassUnchecked() {
53   GcRootSource gc_root_source(this);
54   return declaring_class_.Read<kReadBarrierOption>(&gc_root_source);
55 }
56 
57 template <ReadBarrierOption kReadBarrierOption>
GetDeclaringClass()58 inline ObjPtr<mirror::Class> ArtMethod::GetDeclaringClass() {
59   ObjPtr<mirror::Class> result = GetDeclaringClassUnchecked<kReadBarrierOption>();
60   if (kIsDebugBuild) {
61     if (!IsRuntimeMethod()) {
62       CHECK(result != nullptr) << this;
63     } else {
64       CHECK(result == nullptr) << this;
65     }
66   }
67   return result;
68 }
69 
SetDeclaringClass(ObjPtr<mirror::Class> new_declaring_class)70 inline void ArtMethod::SetDeclaringClass(ObjPtr<mirror::Class> new_declaring_class) {
71   declaring_class_ = GcRoot<mirror::Class>(new_declaring_class);
72 }
73 
CASDeclaringClass(ObjPtr<mirror::Class> expected_class,ObjPtr<mirror::Class> desired_class)74 inline bool ArtMethod::CASDeclaringClass(ObjPtr<mirror::Class> expected_class,
75                                          ObjPtr<mirror::Class> desired_class) {
76   GcRoot<mirror::Class> expected_root(expected_class);
77   GcRoot<mirror::Class> desired_root(desired_class);
78   auto atomic_root_class = reinterpret_cast<Atomic<GcRoot<mirror::Class>>*>(&declaring_class_);
79   return atomic_root_class->CompareAndSetStrongSequentiallyConsistent(expected_root, desired_root);
80 }
81 
GetMethodIndex()82 inline uint16_t ArtMethod::GetMethodIndex() {
83   DCHECK(IsRuntimeMethod() || GetDeclaringClass()->IsResolved());
84   return method_index_;
85 }
86 
GetMethodIndexDuringLinking()87 inline uint16_t ArtMethod::GetMethodIndexDuringLinking() {
88   return method_index_;
89 }
90 
LookupResolvedClassFromTypeIndex(dex::TypeIndex type_idx)91 inline ObjPtr<mirror::Class> ArtMethod::LookupResolvedClassFromTypeIndex(dex::TypeIndex type_idx) {
92   ScopedAssertNoThreadSuspension ants(__FUNCTION__);
93   ObjPtr<mirror::Class> type =
94       Runtime::Current()->GetClassLinker()->LookupResolvedType(type_idx, this);
95   DCHECK(!Thread::Current()->IsExceptionPending());
96   return type;
97 }
98 
ResolveClassFromTypeIndex(dex::TypeIndex type_idx)99 inline ObjPtr<mirror::Class> ArtMethod::ResolveClassFromTypeIndex(dex::TypeIndex type_idx) {
100   ObjPtr<mirror::Class> type = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, this);
101   DCHECK_EQ(type == nullptr, Thread::Current()->IsExceptionPending());
102   return type;
103 }
104 
IsOverridableByDefaultMethod()105 inline bool ArtMethod::IsOverridableByDefaultMethod() {
106   // It is safe to avoid the read barrier here since the constant interface flag
107   // in the `Class` object is stored before creating the `ArtMethod` and storing
108   // the declaring class reference. See `ReadBarrierOption`.
109   return GetDeclaringClass<kWithoutReadBarrier>()->IsInterface();
110 }
111 
CheckIncompatibleClassChange(InvokeType type)112 inline bool ArtMethod::CheckIncompatibleClassChange(InvokeType type) {
113   switch (type) {
114     case kStatic:
115       return !IsStatic();
116     case kDirect:
117       return !IsDirect() || IsStatic();
118     case kVirtual: {
119       // We have an error if we are direct or a non-copied (i.e. not part of a real class) interface
120       // method.
121       ObjPtr<mirror::Class> methods_class = GetDeclaringClass();
122       return IsDirect() || (methods_class->IsInterface() && !IsCopied());
123     }
124     case kSuper:
125       // Constructors and static methods are called with invoke-direct.
126       return IsConstructor() || IsStatic();
127     case kInterface: {
128       ObjPtr<mirror::Class> methods_class = GetDeclaringClass();
129       return IsDirect() || !(methods_class->IsInterface() || methods_class->IsObjectClass());
130     }
131     case kPolymorphic:
132       return !IsSignaturePolymorphic();
133     default:
134       LOG(FATAL) << "Unreachable - invocation type: " << type;
135       UNREACHABLE();
136   }
137 }
138 
IsCalleeSaveMethod()139 inline bool ArtMethod::IsCalleeSaveMethod() {
140   if (!IsRuntimeMethod()) {
141     return false;
142   }
143   Runtime* runtime = Runtime::Current();
144   bool result = false;
145   for (uint32_t i = 0; i < static_cast<uint32_t>(CalleeSaveType::kLastCalleeSaveType); i++) {
146     if (this == runtime->GetCalleeSaveMethod(CalleeSaveType(i))) {
147       result = true;
148       break;
149     }
150   }
151   return result;
152 }
153 
IsResolutionMethod()154 inline bool ArtMethod::IsResolutionMethod() {
155   bool result = this == Runtime::Current()->GetResolutionMethod();
156   // Check that if we do think it is phony it looks like the resolution method.
157   DCHECK_IMPLIES(result, IsRuntimeMethod());
158   return result;
159 }
160 
IsImtUnimplementedMethod()161 inline bool ArtMethod::IsImtUnimplementedMethod() {
162   bool result = this == Runtime::Current()->GetImtUnimplementedMethod();
163   // Check that if we do think it is phony it looks like the imt unimplemented method.
164   DCHECK_IMPLIES(result, IsRuntimeMethod());
165   return result;
166 }
167 
GetDexFile()168 inline const DexFile* ArtMethod::GetDexFile() {
169   // It is safe to avoid the read barrier here since the dex file is constant, so if we read the
170   // from-space dex file pointer it will be equal to the to-space copy.
171   return GetDexCache<kWithoutReadBarrier>()->GetDexFile();
172 }
173 
GetDeclaringClassDescriptor()174 inline const char* ArtMethod::GetDeclaringClassDescriptor() {
175   uint32_t dex_method_idx = GetDexMethodIndex();
176   if (UNLIKELY(dex_method_idx == dex::kDexNoIndex)) {
177     return "<runtime method>";
178   }
179   DCHECK(!IsProxyMethod());
180   const DexFile* dex_file = GetDexFile();
181   return dex_file->GetMethodDeclaringClassDescriptor(dex_file->GetMethodId(dex_method_idx));
182 }
183 
GetShorty()184 inline const char* ArtMethod::GetShorty() {
185   uint32_t unused_length;
186   return GetShorty(&unused_length);
187 }
188 
GetShorty(uint32_t * out_length)189 inline const char* ArtMethod::GetShorty(uint32_t* out_length) {
190   DCHECK(!IsProxyMethod());
191   const DexFile* dex_file = GetDexFile();
192   return dex_file->GetMethodShorty(dex_file->GetMethodId(GetDexMethodIndex()), out_length);
193 }
194 
GetSignature()195 inline const Signature ArtMethod::GetSignature() {
196   uint32_t dex_method_idx = GetDexMethodIndex();
197   if (dex_method_idx != dex::kDexNoIndex) {
198     DCHECK(!IsProxyMethod());
199     const DexFile* dex_file = GetDexFile();
200     return dex_file->GetMethodSignature(dex_file->GetMethodId(dex_method_idx));
201   }
202   return Signature::NoSignature();
203 }
204 
GetName()205 inline const char* ArtMethod::GetName() {
206   uint32_t dex_method_idx = GetDexMethodIndex();
207   if (LIKELY(dex_method_idx != dex::kDexNoIndex)) {
208     DCHECK(!IsProxyMethod());
209     const DexFile* dex_file = GetDexFile();
210     return dex_file->GetMethodName(dex_file->GetMethodId(dex_method_idx));
211   }
212   return GetRuntimeMethodName();
213 }
214 
GetNameView()215 inline std::string_view ArtMethod::GetNameView() {
216   uint32_t dex_method_idx = GetDexMethodIndex();
217   if (LIKELY(dex_method_idx != dex::kDexNoIndex)) {
218     DCHECK(!IsProxyMethod());
219     const DexFile* dex_file = GetDexFile();
220     return dex_file->GetMethodNameView(dex_method_idx);
221   }
222   return GetRuntimeMethodName();
223 }
224 
ResolveNameString()225 inline ObjPtr<mirror::String> ArtMethod::ResolveNameString() {
226   DCHECK(!IsProxyMethod());
227   const dex::MethodId& method_id = GetDexFile()->GetMethodId(GetDexMethodIndex());
228   return Runtime::Current()->GetClassLinker()->ResolveString(method_id.name_idx_, this);
229 }
230 
NameEquals(ObjPtr<mirror::String> name)231 inline bool ArtMethod::NameEquals(ObjPtr<mirror::String> name) {
232   DCHECK(!IsProxyMethod());
233   const DexFile* dex_file = GetDexFile();
234   const dex::MethodId& method_id = dex_file->GetMethodId(GetDexMethodIndex());
235   const dex::StringIndex name_idx = method_id.name_idx_;
236   uint32_t utf16_length;
237   const char* utf8_name = dex_file->StringDataAndUtf16LengthByIdx(name_idx, &utf16_length);
238   return dchecked_integral_cast<uint32_t>(name->GetLength()) == utf16_length &&
239          name->Equals(utf8_name);
240 }
241 
GetCodeItem()242 inline const dex::CodeItem* ArtMethod::GetCodeItem() {
243   if (!HasCodeItem()) {
244     return nullptr;
245   }
246   Runtime* runtime = Runtime::Current();
247   PointerSize pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
248   return runtime->IsAotCompiler()
249       ? GetDexFile()->GetCodeItem(reinterpret_cast32<uint32_t>(GetDataPtrSize(pointer_size)))
250       : reinterpret_cast<const dex::CodeItem*>(
251           reinterpret_cast<uintptr_t>(GetDataPtrSize(pointer_size)) & ~1);
252 }
253 
IsResolvedTypeIdx(dex::TypeIndex type_idx)254 inline bool ArtMethod::IsResolvedTypeIdx(dex::TypeIndex type_idx) {
255   DCHECK(!IsProxyMethod());
256   return LookupResolvedClassFromTypeIndex(type_idx) != nullptr;
257 }
258 
GetLineNumFromDexPC(uint32_t dex_pc)259 inline int32_t ArtMethod::GetLineNumFromDexPC(uint32_t dex_pc) {
260   DCHECK(!IsProxyMethod());
261   if (dex_pc == dex::kDexNoIndex) {
262     return IsNative() ? -2 : -1;
263   }
264   return annotations::GetLineNumFromPC(GetDexFile(), this, dex_pc);
265 }
266 
GetPrototype()267 inline const dex::ProtoId& ArtMethod::GetPrototype() {
268   DCHECK(!IsProxyMethod());
269   const DexFile* dex_file = GetDexFile();
270   return dex_file->GetMethodPrototype(dex_file->GetMethodId(GetDexMethodIndex()));
271 }
272 
GetParameterTypeList()273 inline const dex::TypeList* ArtMethod::GetParameterTypeList() {
274   DCHECK(!IsProxyMethod());
275   const DexFile* dex_file = GetDexFile();
276   const dex::ProtoId& proto = dex_file->GetMethodPrototype(
277       dex_file->GetMethodId(GetDexMethodIndex()));
278   return dex_file->GetProtoParameters(proto);
279 }
280 
GetDeclaringClassSourceFile()281 inline const char* ArtMethod::GetDeclaringClassSourceFile() {
282   DCHECK(!IsProxyMethod());
283   return GetDeclaringClass()->GetSourceFile();
284 }
285 
GetClassDefIndex()286 inline uint16_t ArtMethod::GetClassDefIndex() {
287   DCHECK(!IsProxyMethod());
288   if (LIKELY(!IsObsolete())) {
289     return GetDeclaringClass()->GetDexClassDefIndex();
290   } else {
291     return FindObsoleteDexClassDefIndex();
292   }
293 }
294 
GetClassDef()295 inline const dex::ClassDef& ArtMethod::GetClassDef() {
296   DCHECK(!IsProxyMethod());
297   return GetDexFile()->GetClassDef(GetClassDefIndex());
298 }
299 
GetNumberOfParameters()300 inline size_t ArtMethod::GetNumberOfParameters() {
301   constexpr size_t return_type_count = 1u;
302   uint32_t shorty_length;
303   GetShorty(&shorty_length);
304   return shorty_length - return_type_count;
305 }
306 
GetReturnTypeDescriptor()307 inline const char* ArtMethod::GetReturnTypeDescriptor() {
308   DCHECK(!IsProxyMethod());
309   const DexFile* dex_file = GetDexFile();
310   return dex_file->GetTypeDescriptor(dex_file->GetTypeId(GetReturnTypeIndex()));
311 }
312 
GetReturnTypePrimitive()313 inline Primitive::Type ArtMethod::GetReturnTypePrimitive() {
314   return Primitive::GetType(GetReturnTypeDescriptor()[0]);
315 }
316 
GetTypeDescriptorFromTypeIdx(dex::TypeIndex type_idx)317 inline const char* ArtMethod::GetTypeDescriptorFromTypeIdx(dex::TypeIndex type_idx) {
318   DCHECK(!IsProxyMethod());
319   const DexFile* dex_file = GetDexFile();
320   return dex_file->GetTypeDescriptor(dex_file->GetTypeId(type_idx));
321 }
322 
GetClassLoader()323 inline ObjPtr<mirror::ClassLoader> ArtMethod::GetClassLoader() {
324   DCHECK(!IsProxyMethod());
325   return GetDeclaringClass()->GetClassLoader();
326 }
327 
328 template <ReadBarrierOption kReadBarrierOption>
GetDexCache()329 inline ObjPtr<mirror::DexCache> ArtMethod::GetDexCache() {
330   if (LIKELY(!IsObsolete())) {
331     ObjPtr<mirror::Class> klass = GetDeclaringClass<kReadBarrierOption>();
332     return klass->GetDexCache<kDefaultVerifyFlags, kReadBarrierOption>();
333   } else {
334     DCHECK(!IsProxyMethod());
335     return GetObsoleteDexCache();
336   }
337 }
338 
IsProxyMethod()339 inline bool ArtMethod::IsProxyMethod() {
340   DCHECK(!IsRuntimeMethod()) << "ArtMethod::IsProxyMethod called on a runtime method";
341   // No read barrier needed, we're reading the constant declaring class only to read
342   // the constant proxy flag. See ReadBarrierOption.
343   return GetDeclaringClass<kWithoutReadBarrier>()->IsProxyClass();
344 }
345 
GetInterfaceMethodForProxyUnchecked(PointerSize pointer_size)346 inline ArtMethod* ArtMethod::GetInterfaceMethodForProxyUnchecked(PointerSize pointer_size) {
347   DCHECK(IsProxyMethod());
348   // Do not check IsAssignableFrom() here as it relies on raw reference comparison
349   // which may give false negatives while visiting references for a non-CC moving GC.
350   return reinterpret_cast<ArtMethod*>(GetDataPtrSize(pointer_size));
351 }
352 
GetInterfaceMethodIfProxy(PointerSize pointer_size)353 inline ArtMethod* ArtMethod::GetInterfaceMethodIfProxy(PointerSize pointer_size) {
354   if (LIKELY(!IsProxyMethod())) {
355     return this;
356   }
357   ArtMethod* interface_method = GetInterfaceMethodForProxyUnchecked(pointer_size);
358   // We can check that the proxy class implements the interface only if the proxy class
359   // is resolved, otherwise the interface table is not yet initialized.
360   DCHECK_IMPLIES(GetDeclaringClass()->IsResolved(),
361                  interface_method->GetDeclaringClass()->IsAssignableFrom(GetDeclaringClass()));
362   return interface_method;
363 }
364 
GetReturnTypeIndex()365 inline dex::TypeIndex ArtMethod::GetReturnTypeIndex() {
366   DCHECK(!IsProxyMethod());
367   const DexFile* dex_file = GetDexFile();
368   const dex::MethodId& method_id = dex_file->GetMethodId(GetDexMethodIndex());
369   const dex::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id);
370   return proto_id.return_type_idx_;
371 }
372 
LookupResolvedReturnType()373 inline ObjPtr<mirror::Class> ArtMethod::LookupResolvedReturnType() {
374   return LookupResolvedClassFromTypeIndex(GetReturnTypeIndex());
375 }
376 
ResolveReturnType()377 inline ObjPtr<mirror::Class> ArtMethod::ResolveReturnType() {
378   return ResolveClassFromTypeIndex(GetReturnTypeIndex());
379 }
380 
381 template <ReadBarrierOption kReadBarrierOption>
HasSingleImplementation()382 inline bool ArtMethod::HasSingleImplementation() {
383   if (IsFinal() || GetDeclaringClass<kReadBarrierOption>()->IsFinal()) {
384     // We don't set kAccSingleImplementation for these cases since intrinsic
385     // can use the flag also.
386     return true;
387   }
388   return (GetAccessFlags() & kAccSingleImplementation) != 0;
389 }
390 
391 template<ReadBarrierOption kReadBarrierOption, typename RootVisitorType>
VisitRoots(RootVisitorType & visitor,PointerSize pointer_size)392 void ArtMethod::VisitRoots(RootVisitorType& visitor, PointerSize pointer_size) {
393   if (LIKELY(!declaring_class_.IsNull())) {
394     visitor.VisitRoot(declaring_class_.AddressWithoutBarrier());
395     ObjPtr<mirror::Class> klass = declaring_class_.Read<kReadBarrierOption>();
396     if (UNLIKELY(klass->IsProxyClass())) {
397       // For normal methods, dex cache shortcuts will be visited through the declaring class.
398       // However, for proxies we need to keep the interface method alive, so we visit its roots.
399       ArtMethod* interface_method = GetInterfaceMethodForProxyUnchecked(pointer_size);
400       DCHECK(interface_method != nullptr);
401       interface_method->VisitRoots<kReadBarrierOption>(visitor, pointer_size);
402     }
403   }
404 }
405 
406 template <typename Visitor>
UpdateEntrypoints(const Visitor & visitor,PointerSize pointer_size)407 inline void ArtMethod::UpdateEntrypoints(const Visitor& visitor, PointerSize pointer_size) {
408   if (IsNative()) {
409     const void* old_native_code = GetEntryPointFromJniPtrSize(pointer_size);
410     const void* new_native_code = visitor(old_native_code);
411     if (old_native_code != new_native_code) {
412       SetEntryPointFromJniPtrSize(new_native_code, pointer_size);
413     }
414   }
415   const void* old_code = GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
416   const void* new_code = visitor(old_code);
417   if (old_code != new_code) {
418     SetEntryPointFromQuickCompiledCodePtrSize(new_code, pointer_size);
419   }
420 }
421 
DexInstructions()422 inline CodeItemInstructionAccessor ArtMethod::DexInstructions() {
423   return CodeItemInstructionAccessor(*GetDexFile(), GetCodeItem());
424 }
425 
DexInstructionData()426 inline CodeItemDataAccessor ArtMethod::DexInstructionData() {
427   return CodeItemDataAccessor(*GetDexFile(), GetCodeItem());
428 }
429 
DexInstructionDebugInfo()430 inline CodeItemDebugInfoAccessor ArtMethod::DexInstructionDebugInfo() {
431   return CodeItemDebugInfoAccessor(*GetDexFile(), GetCodeItem(), GetDexMethodIndex());
432 }
433 
CounterHasChanged(uint16_t threshold)434 inline bool ArtMethod::CounterHasChanged(uint16_t threshold) {
435   DCHECK(!IsAbstract());
436   DCHECK_EQ(threshold, Runtime::Current()->GetJITOptions()->GetWarmupThreshold());
437   return hotness_count_ != threshold;
438 }
439 
ResetCounter(uint16_t new_value)440 inline void ArtMethod::ResetCounter(uint16_t new_value) {
441   if (IsAbstract()) {
442     return;
443   }
444   if (IsMemorySharedMethod()) {
445     return;
446   }
447   DCHECK_EQ(new_value, Runtime::Current()->GetJITOptions()->GetWarmupThreshold());
448   // Avoid dirtying the value if possible.
449   if (hotness_count_ != new_value) {
450     hotness_count_ = new_value;
451   }
452 }
453 
SetHotCounter()454 inline void ArtMethod::SetHotCounter() {
455   DCHECK(!IsAbstract());
456   // Avoid dirtying the value if possible.
457   if (hotness_count_ != 0) {
458     hotness_count_ = 0;
459   }
460 }
461 
UpdateCounter(int32_t new_samples)462 inline void ArtMethod::UpdateCounter(int32_t new_samples) {
463   DCHECK(!IsAbstract());
464   DCHECK_GT(new_samples, 0);
465   DCHECK_LE(new_samples, std::numeric_limits<uint16_t>::max());
466   if (IsMemorySharedMethod()) {
467     return;
468   }
469   uint16_t old_hotness_count = hotness_count_;
470   uint16_t new_count = (old_hotness_count <= new_samples) ? 0u : old_hotness_count - new_samples;
471   // Avoid dirtying the value if possible.
472   if (old_hotness_count != new_count) {
473     hotness_count_ = new_count;
474   }
475 }
476 
CounterIsHot()477 inline bool ArtMethod::CounterIsHot() {
478   DCHECK(!IsAbstract());
479   return hotness_count_ == 0;
480 }
481 
CounterHasReached(uint16_t samples,uint16_t threshold)482 inline bool ArtMethod::CounterHasReached(uint16_t samples, uint16_t threshold) {
483   DCHECK(!IsAbstract());
484   DCHECK_EQ(threshold, Runtime::Current()->GetJITOptions()->GetWarmupThreshold());
485   DCHECK_LE(samples, threshold);
486   return hotness_count_ <= (threshold - samples);
487 }
488 
GetCounter()489 inline uint16_t ArtMethod::GetCounter() {
490   DCHECK(!IsAbstract());
491   return hotness_count_;
492 }
493 
GetImtIndex()494 inline uint32_t ArtMethod::GetImtIndex() {
495   if (LIKELY(IsAbstract())) {
496     return imt_index_;
497   } else {
498     return ImTable::GetImtIndex(this);
499   }
500 }
501 
CalculateAndSetImtIndex()502 inline void ArtMethod::CalculateAndSetImtIndex() {
503   DCHECK(IsAbstract()) << PrettyMethod();
504   imt_index_ = ImTable::GetImtIndex(this);
505 }
506 
507 }  // namespace art
508 
509 #endif  // ART_RUNTIME_ART_METHOD_INL_H_
510