• 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 "base/callee_save_type.h"
23 #include "class_linker-inl.h"
24 #include "common_throws.h"
25 #include "dex/code_item_accessors-inl.h"
26 #include "dex/dex_file-inl.h"
27 #include "dex/dex_file_annotations.h"
28 #include "dex/dex_file_types.h"
29 #include "dex/invoke_type.h"
30 #include "dex/primitive.h"
31 #include "dex/signature.h"
32 #include "gc_root-inl.h"
33 #include "imtable-inl.h"
34 #include "jit/jit.h"
35 #include "jit/jit_code_cache-inl.h"
36 #include "jit/jit_options.h"
37 #include "mirror/class-inl.h"
38 #include "mirror/dex_cache-inl.h"
39 #include "mirror/object-inl.h"
40 #include "mirror/object_array.h"
41 #include "mirror/string.h"
42 #include "obj_ptr-inl.h"
43 #include "quick/quick_method_frame_info.h"
44 #include "read_barrier-inl.h"
45 #include "runtime-inl.h"
46 #include "thread-current-inl.h"
47 
48 namespace art HIDDEN {
49 
50 namespace detail {
51 
52 template <> struct ShortyTraits<'V'> {
53   using Type = void;
54   static Type Get([[maybe_unused]] const JValue& value) {}
55   // `kVRegCount` and `Set()` are not defined.
56 };
57 
58 template <> struct ShortyTraits<'Z'> {
59   // Despite using `uint8_t` for `boolean` in `JValue`, we shall use `bool` here.
60   using Type = bool;
61   static Type Get(const JValue& value) { return value.GetZ() != 0u; }
62   static constexpr size_t kVRegCount = 1u;
63   static void Set(uint32_t* args, Type value) { args[0] = static_cast<uint32_t>(value ? 1u : 0u); }
64 };
65 
66 template <> struct ShortyTraits<'B'> {
67   using Type = int8_t;
68   static Type Get(const JValue& value) { return value.GetB(); }
69   static constexpr size_t kVRegCount = 1u;
70   static void Set(uint32_t* args, Type value) { args[0] = static_cast<uint32_t>(value); }
71 };
72 
73 template <> struct ShortyTraits<'C'> {
74   using Type = uint16_t;
75   static Type Get(const JValue& value) { return value.GetC(); }
76   static constexpr size_t kVRegCount = 1u;
77   static void Set(uint32_t* args, Type value) { args[0] = static_cast<uint32_t>(value); }
78 };
79 
80 template <> struct ShortyTraits<'S'> {
81   using Type = int16_t;
82   static Type Get(const JValue& value) { return value.GetS(); }
83   static constexpr size_t kVRegCount = 1u;
84   static void Set(uint32_t* args, Type value) { args[0] = static_cast<uint32_t>(value); }
85 };
86 
87 template <> struct ShortyTraits<'I'> {
88   using Type = int32_t;
89   static Type Get(const JValue& value) { return value.GetI(); }
90   static constexpr size_t kVRegCount = 1u;
91   static void Set(uint32_t* args, Type value) { args[0] = static_cast<uint32_t>(value); }
92 };
93 
94 template <> struct ShortyTraits<'J'> {
95   using Type = int64_t;
96   static Type Get(const JValue& value) { return value.GetJ(); }
97   static constexpr size_t kVRegCount = 2u;
98   static void Set(uint32_t* args, Type value) {
99     // Little-endian representation.
100     args[0] = static_cast<uint32_t>(value);
101     args[1] = static_cast<uint32_t>(static_cast<uint64_t>(value) >> 32);
102   }
103 };
104 
105 template <> struct ShortyTraits<'F'> {
106   using Type = float;
107   static Type Get(const JValue& value) { return value.GetF(); }
108   static constexpr size_t kVRegCount = 1u;
109   static void Set(uint32_t* args, Type value) { args[0] = bit_cast<uint32_t>(value); }
110 };
111 
112 template <> struct ShortyTraits<'D'> {
113   using Type = double;
114   static Type Get(const JValue& value) { return value.GetD(); }
115   static constexpr size_t kVRegCount = 2u;
116   static void Set(uint32_t* args, Type value) {
117     // Little-endian representation.
118     uint64_t v = bit_cast<uint64_t>(value);
119     args[0] = static_cast<uint32_t>(v);
120     args[1] = static_cast<uint32_t>(v >> 32);
121   }
122 };
123 
124 template <> struct ShortyTraits<'L'> {
125   using Type = ObjPtr<mirror::Object>;
126   static Type Get(const JValue& value) REQUIRES_SHARED(Locks::mutator_lock_) {
127       return value.GetL();
128   }
129   static constexpr size_t kVRegCount = 1u;
130   static void Set(uint32_t* args, Type value) REQUIRES_SHARED(Locks::mutator_lock_) {
131     args[0] = StackReference<mirror::Object>::FromMirrorPtr(value.Ptr()).AsVRegValue();
132   }
133 };
134 
135 template <char... Shorty>
136 constexpr auto MaterializeShorty() {
137   constexpr size_t kSize = std::size({Shorty...}) + 1u;
138   return std::array<char, kSize>{Shorty..., '\0'};
139 }
140 
141 template <char... ArgType>
142 constexpr size_t NumberOfVRegs() {
143   constexpr size_t kArgVRegCount[] = {
144     ShortyTraits<ArgType>::kVRegCount...
145   };
146   size_t sum = 0u;
147   for (size_t count : kArgVRegCount) {
148     sum += count;
149   }
150   return sum;
151 }
152 
153 template <char FirstArgType, char... ArgType>
154 inline ALWAYS_INLINE void FillVRegs(uint32_t* vregs,
155                                     typename ShortyTraits<FirstArgType>::Type first_arg,
156                                     typename ShortyTraits<ArgType>::Type... args)
157     REQUIRES_SHARED(Locks::mutator_lock_) {
158   ShortyTraits<FirstArgType>::Set(vregs, first_arg);
159   if constexpr (sizeof...(args) > 0)
160     FillVRegs<ArgType...>(vregs + ShortyTraits<FirstArgType>::kVRegCount, args...);
161 }
162 
163 template <char... ArgType>
164 inline ALWAYS_INLINE auto MaterializeVRegs(typename ShortyTraits<ArgType>::Type... args)
165     REQUIRES_SHARED(Locks::mutator_lock_) {
166   constexpr size_t kNumVRegs = NumberOfVRegs<ArgType...>();
167   std::array<uint32_t, kNumVRegs> vregs;
168   if constexpr (sizeof...(args) > 0)
169     FillVRegs<ArgType...>(vregs.data(), args...);
170   return vregs;
171 }
172 
173 }  // namespace detail
174 
175 template <char ReturnType, char... ArgType>
176 inline typename detail::ShortyTraits<ReturnType>::Type
177 ArtMethod::InvokeStatic(Thread* self, typename detail::ShortyTraits<ArgType>::Type... args) {
178   DCHECK(IsStatic());
179   DCHECK(GetDeclaringClass()->IsInitialized());  // Used only for initialized well-known classes.
180   JValue result;
181   constexpr auto shorty = detail::MaterializeShorty<ReturnType, ArgType...>();
182   auto vregs = detail::MaterializeVRegs<ArgType...>(args...);
183   Invoke(self,
184          vregs.empty() ? nullptr : vregs.data(),
185          vregs.size() * sizeof(typename decltype(vregs)::value_type),
186          &result,
187          shorty.data());
188   return detail::ShortyTraits<ReturnType>::Get(result);
189 }
190 
191 template <char ReturnType, char... ArgType>
192 typename detail::ShortyTraits<ReturnType>::Type
193 ArtMethod::InvokeInstance(Thread* self,
194                           ObjPtr<mirror::Object> receiver,
195                           typename detail::ShortyTraits<ArgType>::Type... args) {
196   DCHECK(!GetDeclaringClass()->IsInterface());
197   DCHECK(!IsStatic());
198   JValue result;
199   constexpr auto shorty = detail::MaterializeShorty<ReturnType, ArgType...>();
200   auto vregs = detail::MaterializeVRegs<'L', ArgType...>(receiver, args...);
201   Invoke(self,
202          vregs.data(),
203          vregs.size() * sizeof(typename decltype(vregs)::value_type),
204          &result,
205          shorty.data());
206   return detail::ShortyTraits<ReturnType>::Get(result);
207 }
208 
209 template <char ReturnType, char... ArgType>
210 typename detail::ShortyTraits<ReturnType>::Type
211 ArtMethod::InvokeFinal(Thread* self,
212                        ObjPtr<mirror::Object> receiver,
213                        typename detail::ShortyTraits<ArgType>::Type... args) {
214   DCHECK(!GetDeclaringClass()->IsInterface());
215   DCHECK(!IsStatic());
216   DCHECK(IsFinal() || GetDeclaringClass()->IsFinal());
217   DCHECK(receiver != nullptr);
218   return InvokeInstance<ReturnType, ArgType...>(self, receiver, args...);
219 }
220 
221 template <char ReturnType, char... ArgType>
222 typename detail::ShortyTraits<ReturnType>::Type
223 ArtMethod::InvokeVirtual(Thread* self,
224                          ObjPtr<mirror::Object> receiver,
225                          typename detail::ShortyTraits<ArgType>::Type... args) {
226   DCHECK(!GetDeclaringClass()->IsInterface());
227   DCHECK(!IsStatic());
228   DCHECK(!IsFinal());
229   DCHECK(receiver != nullptr);
230   ArtMethod* target_method =
231       receiver->GetClass()->FindVirtualMethodForVirtual(this, kRuntimePointerSize);
232   DCHECK(target_method != nullptr);
233   return target_method->InvokeInstance<ReturnType, ArgType...>(self, receiver, args...);
234 }
235 
236 template <char ReturnType, char... ArgType>
237 typename detail::ShortyTraits<ReturnType>::Type
238 ArtMethod::InvokeInterface(Thread* self,
239                            ObjPtr<mirror::Object> receiver,
240                            typename detail::ShortyTraits<ArgType>::Type... args) {
241   DCHECK(GetDeclaringClass()->IsInterface());
242   DCHECK(!IsStatic());
243   DCHECK(receiver != nullptr);
244   ArtMethod* target_method =
245       receiver->GetClass()->FindVirtualMethodForInterface(this, kRuntimePointerSize);
246   DCHECK(target_method != nullptr);
247   return target_method->InvokeInstance<ReturnType, ArgType...>(self, receiver, args...);
248 }
249 
250 template <ReadBarrierOption kReadBarrierOption>
251 inline ObjPtr<mirror::Class> ArtMethod::GetDeclaringClassUnchecked() {
252   GcRootSource gc_root_source(this);
253   return declaring_class_.Read<kReadBarrierOption>(&gc_root_source);
254 }
255 
256 template <ReadBarrierOption kReadBarrierOption>
257 inline ObjPtr<mirror::Class> ArtMethod::GetDeclaringClass() {
258   ObjPtr<mirror::Class> result = GetDeclaringClassUnchecked<kReadBarrierOption>();
259   if (kIsDebugBuild) {
260     if (!IsRuntimeMethod()) {
261       CHECK(result != nullptr) << this;
262     } else {
263       CHECK(result == nullptr) << this;
264     }
265   }
266   return result;
267 }
268 
269 inline void ArtMethod::SetDeclaringClass(ObjPtr<mirror::Class> new_declaring_class) {
270   declaring_class_ = GcRoot<mirror::Class>(new_declaring_class);
271 }
272 
273 inline bool ArtMethod::CASDeclaringClass(ObjPtr<mirror::Class> expected_class,
274                                          ObjPtr<mirror::Class> desired_class) {
275   GcRoot<mirror::Class> expected_root(expected_class);
276   GcRoot<mirror::Class> desired_root(desired_class);
277   auto atomic_root_class = reinterpret_cast<Atomic<GcRoot<mirror::Class>>*>(&declaring_class_);
278   return atomic_root_class->CompareAndSetStrongSequentiallyConsistent(expected_root, desired_root);
279 }
280 
281 inline uint16_t ArtMethod::GetMethodIndex() {
282   DCHECK(IsRuntimeMethod() || GetDeclaringClass()->IsResolved());
283   return method_index_;
284 }
285 
286 inline uint16_t ArtMethod::GetMethodIndexDuringLinking() {
287   return method_index_;
288 }
289 
290 inline ObjPtr<mirror::Class> ArtMethod::LookupResolvedClassFromTypeIndex(dex::TypeIndex type_idx) {
291   ScopedAssertNoThreadSuspension ants(__FUNCTION__);
292   ObjPtr<mirror::Class> type =
293       Runtime::Current()->GetClassLinker()->LookupResolvedType(type_idx, this);
294   DCHECK(!Thread::Current()->IsExceptionPending());
295   return type;
296 }
297 
298 inline ObjPtr<mirror::Class> ArtMethod::ResolveClassFromTypeIndex(dex::TypeIndex type_idx) {
299   ObjPtr<mirror::Class> type = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, this);
300   DCHECK_EQ(type == nullptr, Thread::Current()->IsExceptionPending());
301   return type;
302 }
303 
304 inline bool ArtMethod::IsStringConstructor() {
305   uint32_t access_flags = GetAccessFlags();
306   DCHECK(!IsClassInitializer(access_flags));
307   return IsConstructor(access_flags) &&
308          // No read barrier needed for reading a constant reference only to read
309          // a constant string class flag. See `ReadBarrierOption`.
310          GetDeclaringClass<kWithoutReadBarrier>()->IsStringClass();
311 }
312 
313 inline bool ArtMethod::IsOverridableByDefaultMethod() {
314   // It is safe to avoid the read barrier here since the constant interface flag
315   // in the `Class` object is stored before creating the `ArtMethod` and storing
316   // the declaring class reference. See `ReadBarrierOption`.
317   return GetDeclaringClass<kWithoutReadBarrier>()->IsInterface();
318 }
319 
320 inline bool ArtMethod::CheckIncompatibleClassChange(InvokeType type) {
321   switch (type) {
322     case kStatic:
323       return !IsStatic();
324     case kDirect:
325       return !IsDirect() || IsStatic();
326     case kVirtual: {
327       // We have an error if we are direct or a non-copied (i.e. not part of a real class) interface
328       // method.
329       ObjPtr<mirror::Class> methods_class = GetDeclaringClass();
330       return IsDirect() || (methods_class->IsInterface() && !IsCopied());
331     }
332     case kSuper:
333       // Constructors and static methods are called with invoke-direct.
334       return IsConstructor() || IsStatic();
335     case kInterface: {
336       ObjPtr<mirror::Class> methods_class = GetDeclaringClass();
337       return IsDirect() || !(methods_class->IsInterface() || methods_class->IsObjectClass());
338     }
339     case kPolymorphic:
340       return !IsSignaturePolymorphic();
341     default:
342       LOG(FATAL) << "Unreachable - invocation type: " << type;
343       UNREACHABLE();
344   }
345 }
346 
347 inline bool ArtMethod::IsCalleeSaveMethod() {
348   if (!IsRuntimeMethod()) {
349     return false;
350   }
351   Runtime* runtime = Runtime::Current();
352   bool result = false;
353   for (uint32_t i = 0; i < static_cast<uint32_t>(CalleeSaveType::kLastCalleeSaveType); i++) {
354     if (this == runtime->GetCalleeSaveMethod(CalleeSaveType(i))) {
355       result = true;
356       break;
357     }
358   }
359   return result;
360 }
361 
362 inline bool ArtMethod::IsResolutionMethod() {
363   bool result = this == Runtime::Current()->GetResolutionMethod();
364   // Check that if we do think it is phony it looks like the resolution method.
365   DCHECK_IMPLIES(result, IsRuntimeMethod());
366   return result;
367 }
368 
369 inline bool ArtMethod::IsImtUnimplementedMethod() {
370   bool result = this == Runtime::Current()->GetImtUnimplementedMethod();
371   // Check that if we do think it is phony it looks like the imt unimplemented method.
372   DCHECK_IMPLIES(result, IsRuntimeMethod());
373   return result;
374 }
375 
376 inline const DexFile* ArtMethod::GetDexFile() {
377   // It is safe to avoid the read barrier here since the dex file is constant, so if we read the
378   // from-space dex file pointer it will be equal to the to-space copy.
379   return GetDexCache<kWithoutReadBarrier>()->GetDexFile();
380 }
381 
382 inline const char* ArtMethod::GetDeclaringClassDescriptor() {
383   DCHECK(!IsRuntimeMethod());
384   DCHECK(!IsProxyMethod());
385   return GetDexFile()->GetMethodDeclaringClassDescriptor(GetDexMethodIndex());
386 }
387 
388 inline std::string_view ArtMethod::GetDeclaringClassDescriptorView() {
389   DCHECK(!IsRuntimeMethod());
390   DCHECK(!IsProxyMethod());
391   return GetDexFile()->GetMethodDeclaringClassDescriptorView(GetDexMethodIndex());
392 }
393 
394 inline const char* ArtMethod::GetShorty() {
395   uint32_t unused_length;
396   return GetShorty(&unused_length);
397 }
398 
399 inline const char* ArtMethod::GetShorty(uint32_t* out_length) {
400   DCHECK(!IsProxyMethod());
401   const DexFile* dex_file = GetDexFile();
402   return dex_file->GetMethodShorty(dex_file->GetMethodId(GetDexMethodIndex()), out_length);
403 }
404 
405 inline std::string_view ArtMethod::GetShortyView() {
406   DCHECK(!IsProxyMethod());
407   const DexFile* dex_file = GetDexFile();
408   return dex_file->GetMethodShortyView(dex_file->GetMethodId(GetDexMethodIndex()));
409 }
410 
411 inline const Signature ArtMethod::GetSignature() {
412   uint32_t dex_method_idx = GetDexMethodIndex();
413   if (dex_method_idx != dex::kDexNoIndex) {
414     DCHECK(!IsProxyMethod());
415     const DexFile* dex_file = GetDexFile();
416     return dex_file->GetMethodSignature(dex_file->GetMethodId(dex_method_idx));
417   }
418   return Signature::NoSignature();
419 }
420 
421 inline const char* ArtMethod::GetName() {
422   uint32_t dex_method_idx = GetDexMethodIndex();
423   if (LIKELY(dex_method_idx != dex::kDexNoIndex)) {
424     DCHECK(!IsProxyMethod());
425     const DexFile* dex_file = GetDexFile();
426     return dex_file->GetMethodName(dex_file->GetMethodId(dex_method_idx));
427   }
428   return GetRuntimeMethodName();
429 }
430 
431 inline std::string_view ArtMethod::GetNameView() {
432   uint32_t dex_method_idx = GetDexMethodIndex();
433   if (LIKELY(dex_method_idx != dex::kDexNoIndex)) {
434     DCHECK(!IsProxyMethod());
435     const DexFile* dex_file = GetDexFile();
436     return dex_file->GetMethodNameView(dex_method_idx);
437   }
438   return GetRuntimeMethodName();
439 }
440 
441 inline ObjPtr<mirror::String> ArtMethod::ResolveNameString() {
442   DCHECK(!IsProxyMethod());
443   const dex::MethodId& method_id = GetDexFile()->GetMethodId(GetDexMethodIndex());
444   return Runtime::Current()->GetClassLinker()->ResolveString(method_id.name_idx_, this);
445 }
446 
447 inline bool ArtMethod::NameEquals(ObjPtr<mirror::String> name) {
448   DCHECK(!IsProxyMethod());
449   const DexFile* dex_file = GetDexFile();
450   const dex::MethodId& method_id = dex_file->GetMethodId(GetDexMethodIndex());
451   const dex::StringIndex name_idx = method_id.name_idx_;
452   uint32_t utf16_length;
453   const char* utf8_name = dex_file->GetStringDataAndUtf16Length(name_idx, &utf16_length);
454   return dchecked_integral_cast<uint32_t>(name->GetLength()) == utf16_length &&
455          name->Equals(utf8_name);
456 }
457 
458 inline const dex::CodeItem* ArtMethod::GetCodeItem() {
459   if (!HasCodeItem()) {
460     return nullptr;
461   }
462   Runtime* runtime = Runtime::Current();
463   PointerSize pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
464   return runtime->IsAotCompiler()
465       ? GetDexFile()->GetCodeItem(reinterpret_cast32<uint32_t>(GetDataPtrSize(pointer_size)))
466       : reinterpret_cast<const dex::CodeItem*>(
467           reinterpret_cast<uintptr_t>(GetDataPtrSize(pointer_size)) & ~1);
468 }
469 
470 inline int32_t ArtMethod::GetLineNumFromDexPC(uint32_t dex_pc) {
471   DCHECK(!IsProxyMethod());
472   if (dex_pc == dex::kDexNoIndex) {
473     return IsNative() ? -2 : -1;
474   }
475   return annotations::GetLineNumFromPC(GetDexFile(), this, dex_pc);
476 }
477 
478 inline const dex::ProtoId& ArtMethod::GetPrototype() {
479   DCHECK(!IsProxyMethod());
480   const DexFile* dex_file = GetDexFile();
481   return dex_file->GetMethodPrototype(dex_file->GetMethodId(GetDexMethodIndex()));
482 }
483 
484 inline const dex::ProtoIndex ArtMethod::GetProtoIndex() {
485   return GetDexFile()->GetIndexForProtoId(GetPrototype());
486 }
487 
488 inline const dex::TypeList* ArtMethod::GetParameterTypeList() {
489   DCHECK(!IsProxyMethod());
490   const DexFile* dex_file = GetDexFile();
491   const dex::ProtoId& proto = dex_file->GetMethodPrototype(
492       dex_file->GetMethodId(GetDexMethodIndex()));
493   return dex_file->GetProtoParameters(proto);
494 }
495 
496 inline const char* ArtMethod::GetDeclaringClassSourceFile() {
497   DCHECK(!IsProxyMethod());
498   return GetDeclaringClass()->GetSourceFile();
499 }
500 
501 inline uint16_t ArtMethod::GetClassDefIndex() {
502   DCHECK(!IsProxyMethod());
503   if (LIKELY(!IsObsolete())) {
504     return GetDeclaringClass()->GetDexClassDefIndex();
505   } else {
506     return FindObsoleteDexClassDefIndex();
507   }
508 }
509 
510 inline const dex::ClassDef& ArtMethod::GetClassDef() {
511   DCHECK(!IsProxyMethod());
512   return GetDexFile()->GetClassDef(GetClassDefIndex());
513 }
514 
515 inline size_t ArtMethod::GetNumberOfParameters() {
516   constexpr size_t return_type_count = 1u;
517   uint32_t shorty_length;
518   GetShorty(&shorty_length);
519   return shorty_length - return_type_count;
520 }
521 
522 inline const char* ArtMethod::GetReturnTypeDescriptor() {
523   return GetDexFile()->GetTypeDescriptor(GetReturnTypeIndex());
524 }
525 
526 inline std::string_view ArtMethod::GetReturnTypeDescriptorView() {
527   return GetDexFile()->GetTypeDescriptorView(GetReturnTypeIndex());
528 }
529 
530 inline Primitive::Type ArtMethod::GetReturnTypePrimitive() {
531   return Primitive::GetType(GetReturnTypeDescriptor()[0]);
532 }
533 
534 inline const char* ArtMethod::GetTypeDescriptorFromTypeIdx(dex::TypeIndex type_idx) {
535   DCHECK(!IsProxyMethod());
536   const DexFile* dex_file = GetDexFile();
537   return dex_file->GetTypeDescriptor(dex_file->GetTypeId(type_idx));
538 }
539 
540 inline ObjPtr<mirror::ClassLoader> ArtMethod::GetClassLoader() {
541   DCHECK(!IsProxyMethod());
542   return GetDeclaringClass()->GetClassLoader();
543 }
544 
545 template <ReadBarrierOption kReadBarrierOption>
546 inline ObjPtr<mirror::DexCache> ArtMethod::GetDexCache() {
547   if (LIKELY(!IsObsolete())) {
548     ObjPtr<mirror::Class> klass = GetDeclaringClass<kReadBarrierOption>();
549     return klass->GetDexCache<kDefaultVerifyFlags, kReadBarrierOption>();
550   } else {
551     DCHECK(!IsProxyMethod());
552     return GetObsoleteDexCache<kReadBarrierOption>();
553   }
554 }
555 
556 inline bool ArtMethod::IsProxyMethod() {
557   DCHECK(!IsRuntimeMethod()) << "ArtMethod::IsProxyMethod called on a runtime method";
558   // No read barrier needed, we're reading the constant declaring class only to read
559   // the constant proxy flag. See ReadBarrierOption.
560   return GetDeclaringClass<kWithoutReadBarrier>()->IsProxyClass();
561 }
562 
563 inline ArtMethod* ArtMethod::GetInterfaceMethodForProxyUnchecked(PointerSize pointer_size) {
564   DCHECK(IsProxyMethod());
565   // Do not check IsAssignableFrom() here as it relies on raw reference comparison
566   // which may give false negatives while visiting references for a non-CC moving GC.
567   return reinterpret_cast<ArtMethod*>(GetDataPtrSize(pointer_size));
568 }
569 
570 inline ArtMethod* ArtMethod::GetInterfaceMethodIfProxy(PointerSize pointer_size) {
571   if (LIKELY(!IsProxyMethod())) {
572     return this;
573   }
574   ArtMethod* interface_method = GetInterfaceMethodForProxyUnchecked(pointer_size);
575   // We can check that the proxy class implements the interface only if the proxy class
576   // is resolved, otherwise the interface table is not yet initialized.
577   DCHECK_IMPLIES(GetDeclaringClass()->IsResolved(),
578                  interface_method->GetDeclaringClass()->IsAssignableFrom(GetDeclaringClass()));
579   return interface_method;
580 }
581 
582 inline dex::TypeIndex ArtMethod::GetReturnTypeIndex() {
583   DCHECK(!IsRuntimeMethod());
584   DCHECK(!IsProxyMethod());
585   const DexFile* dex_file = GetDexFile();
586   const dex::MethodId& method_id = dex_file->GetMethodId(GetDexMethodIndex());
587   const dex::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id);
588   return proto_id.return_type_idx_;
589 }
590 
591 inline ObjPtr<mirror::Class> ArtMethod::LookupResolvedReturnType() {
592   return LookupResolvedClassFromTypeIndex(GetReturnTypeIndex());
593 }
594 
595 inline ObjPtr<mirror::Class> ArtMethod::ResolveReturnType() {
596   return ResolveClassFromTypeIndex(GetReturnTypeIndex());
597 }
598 
599 inline bool ArtMethod::HasSingleImplementation() {
600   // No read barrier needed for reading a constant reference only to read
601   // a constant final class flag. See `ReadBarrierOption`.
602   if (IsFinal() || GetDeclaringClass<kWithoutReadBarrier>()->IsFinal()) {
603     // We don't set kAccSingleImplementation for these cases since intrinsic
604     // can use the flag also.
605     return true;
606   }
607   return (GetAccessFlags() & kAccSingleImplementation) != 0;
608 }
609 
610 template<ReadBarrierOption kReadBarrierOption, bool kVisitProxyMethod, typename RootVisitorType>
611 void ArtMethod::VisitRoots(RootVisitorType& visitor, PointerSize pointer_size) {
612   if (LIKELY(!declaring_class_.IsNull())) {
613     visitor.VisitRoot(declaring_class_.AddressWithoutBarrier());
614     if (kVisitProxyMethod) {
615       ObjPtr<mirror::Class> klass = declaring_class_.Read<kReadBarrierOption>();
616       if (UNLIKELY(klass->IsProxyClass())) {
617         // For normal methods, dex cache shortcuts will be visited through the declaring class.
618         // However, for proxies we need to keep the interface method alive, so we visit its roots.
619         ArtMethod* interface_method = GetInterfaceMethodForProxyUnchecked(pointer_size);
620         DCHECK(interface_method != nullptr);
621         interface_method->VisitRoots<kReadBarrierOption, kVisitProxyMethod>(visitor, pointer_size);
622       }
623     }
624   }
625 
626   // JIT-ted code can hold references to heap objects like MethodType-s. Visiting them here to
627   // treat them as strongly reachable.
628   Runtime* runtime = Runtime::Current();
629   if (runtime->GetJit() != nullptr) {
630     runtime->GetJit()->GetCodeCache()->VisitRootTables(this, visitor);
631   }
632 }
633 
634 template<typename RootVisitorType>
635 void ArtMethod::VisitRoots(RootVisitorType& visitor,
636                            uint8_t* start_boundary,
637                            uint8_t* end_boundary,
638                            ArtMethod* method) {
639   mirror::CompressedReference<mirror::Object>* cls_ptr =
640       reinterpret_cast<mirror::CompressedReference<mirror::Object>*>(
641           reinterpret_cast<uint8_t*>(method) + DeclaringClassOffset().Int32Value());
642   if (reinterpret_cast<uint8_t*>(cls_ptr) >= start_boundary
643       && reinterpret_cast<uint8_t*>(cls_ptr) < end_boundary) {
644     visitor.VisitRootIfNonNull(cls_ptr);
645   }
646 }
647 
648 template<PointerSize kPointerSize, typename RootVisitorType>
649 void ArtMethod::VisitArrayRoots(RootVisitorType& visitor,
650                                 uint8_t* start_boundary,
651                                 uint8_t* end_boundary,
652                                 LengthPrefixedArray<ArtMethod>* array) {
653   DCHECK_LE(start_boundary, end_boundary);
654   DCHECK_NE(array->size(), 0u);
655   static constexpr size_t kMethodSize = ArtMethod::Size(kPointerSize);
656   ArtMethod* first_method = &array->At(0, kMethodSize, ArtMethod::Alignment(kPointerSize));
657   DCHECK_LE(static_cast<void*>(end_boundary),
658             static_cast<void*>(reinterpret_cast<uint8_t*>(first_method)
659                                + array->size() * kMethodSize));
660   uint8_t* declaring_class =
661       reinterpret_cast<uint8_t*>(first_method) + DeclaringClassOffset().Int32Value();
662   // Jump to the first class to visit.
663   if (declaring_class < start_boundary) {
664     size_t remainder = (start_boundary - declaring_class) % kMethodSize;
665     declaring_class = start_boundary;
666     if (remainder > 0) {
667       declaring_class += kMethodSize - remainder;
668     }
669   }
670   while (declaring_class < end_boundary) {
671     visitor.VisitRootIfNonNull(
672         reinterpret_cast<mirror::CompressedReference<mirror::Object>*>(declaring_class));
673     declaring_class += kMethodSize;
674   }
675 }
676 
677 template <ReadBarrierOption kReadBarrierOption>
678 inline bool ArtMethod::StillNeedsClinitCheck() {
679   if (!NeedsClinitCheckBeforeCall()) {
680     return false;
681   }
682   ObjPtr<mirror::Class> klass = GetDeclaringClass<kReadBarrierOption>();
683   return !klass->IsVisiblyInitialized();
684 }
685 
686 inline bool ArtMethod::StillNeedsClinitCheckMayBeDead() {
687   if (!NeedsClinitCheckBeforeCall()) {
688     return false;
689   }
690   ObjPtr<mirror::Class> klass = GetDeclaringClassMayBeDead();
691   return !klass->IsVisiblyInitialized();
692 }
693 
694 inline bool ArtMethod::IsDeclaringClassVerifiedMayBeDead() {
695   ObjPtr<mirror::Class> klass = GetDeclaringClassMayBeDead();
696   return klass->IsVerified();
697 }
698 
699 inline ObjPtr<mirror::Class> ArtMethod::GetDeclaringClassMayBeDead() {
700   // Helper method for checking the status of the declaring class which may be dead.
701   //
702   // To avoid resurrecting an unreachable object, or crashing the GC in some GC phases,
703   // we must not use a full read barrier. Therefore we read the declaring class without
704   // a read barrier and check if it's already marked. If yes, we check the status of the
705   // to-space class object as intended. Otherwise, there is no to-space object and the
706   // from-space class object contains the most recent value of the status field; even if
707   // this races with another thread doing a read barrier and updating the status, that's
708   // no different from a race with a thread that just updates the status.
709   ObjPtr<mirror::Class> klass = GetDeclaringClass<kWithoutReadBarrier>();
710   ObjPtr<mirror::Class> marked = ReadBarrier::IsMarked(klass.Ptr());
711   return (marked != nullptr) ? marked : klass;
712 }
713 
714 inline CodeItemInstructionAccessor ArtMethod::DexInstructions() {
715   return CodeItemInstructionAccessor(*GetDexFile(), GetCodeItem());
716 }
717 
718 inline CodeItemDataAccessor ArtMethod::DexInstructionData() {
719   return CodeItemDataAccessor(*GetDexFile(), GetCodeItem());
720 }
721 
722 inline CodeItemDebugInfoAccessor ArtMethod::DexInstructionDebugInfo() {
723   return CodeItemDebugInfoAccessor(*GetDexFile(), GetCodeItem(), GetDexMethodIndex());
724 }
725 
726 inline bool ArtMethod::CounterHasChanged(uint16_t threshold) {
727   DCHECK(!IsAbstract());
728   DCHECK_EQ(threshold, Runtime::Current()->GetJITOptions()->GetWarmupThreshold());
729   return hotness_count_ != threshold;
730 }
731 
732 inline void ArtMethod::ResetCounter(uint16_t new_value) {
733   if (IsAbstract()) {
734     return;
735   }
736   if (IsMemorySharedMethod()) {
737     return;
738   }
739   DCHECK_EQ(new_value, Runtime::Current()->GetJITOptions()->GetWarmupThreshold());
740   // Avoid dirtying the value if possible.
741   if (hotness_count_ != new_value) {
742     hotness_count_ = new_value;
743   }
744 }
745 
746 inline void ArtMethod::SetHotCounter() {
747   DCHECK(!IsAbstract());
748   // Avoid dirtying the value if possible.
749   if (hotness_count_ != 0) {
750     hotness_count_ = 0;
751   }
752 }
753 
754 inline void ArtMethod::UpdateCounter(int32_t new_samples) {
755   DCHECK(!IsAbstract());
756   DCHECK_GT(new_samples, 0);
757   DCHECK_LE(new_samples, std::numeric_limits<uint16_t>::max());
758   if (IsMemorySharedMethod()) {
759     return;
760   }
761   uint16_t old_hotness_count = hotness_count_;
762   uint16_t new_count = (old_hotness_count <= new_samples) ? 0u : old_hotness_count - new_samples;
763   // Avoid dirtying the value if possible.
764   if (old_hotness_count != new_count) {
765     hotness_count_ = new_count;
766   }
767 }
768 
769 inline bool ArtMethod::CounterIsHot() {
770   DCHECK(!IsAbstract());
771   return hotness_count_ == 0;
772 }
773 
774 inline uint16_t ArtMethod::GetCounter() {
775   DCHECK(!IsAbstract());
776   return hotness_count_;
777 }
778 
779 inline uint32_t ArtMethod::GetImtIndex() {
780   if (LIKELY(IsAbstract())) {
781     return imt_index_;
782   } else {
783     return ImTable::GetImtIndex(this);
784   }
785 }
786 
787 }  // namespace art
788 
789 #endif  // ART_RUNTIME_ART_METHOD_INL_H_
790