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