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