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