Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ART_RUNTIME_ART_METHOD_INL_H_
     18 #define ART_RUNTIME_ART_METHOD_INL_H_
     19 
     20 #include "art_method.h"
     21 
     22 #include "art_field.h"
     23 #include "base/callee_save_type.h"
     24 #include "class_linker-inl.h"
     25 #include "common_throws.h"
     26 #include "dex/code_item_accessors-inl.h"
     27 #include "dex/dex_file-inl.h"
     28 #include "dex/dex_file_annotations.h"
     29 #include "dex/dex_file_types.h"
     30 #include "dex/invoke_type.h"
     31 #include "dex/primitive.h"
     32 #include "gc_root-inl.h"
     33 #include "imtable-inl.h"
     34 #include "intrinsics_enum.h"
     35 #include "jit/profiling_info.h"
     36 #include "mirror/class-inl.h"
     37 #include "mirror/dex_cache-inl.h"
     38 #include "mirror/object-inl.h"
     39 #include "mirror/object_array.h"
     40 #include "mirror/string.h"
     41 #include "oat.h"
     42 #include "obj_ptr-inl.h"
     43 #include "quick/quick_method_frame_info.h"
     44 #include "read_barrier-inl.h"
     45 #include "runtime-inl.h"
     46 #include "thread-current-inl.h"
     47 
     48 namespace art {
     49 
     50 template <ReadBarrierOption kReadBarrierOption>
     51 inline ObjPtr<mirror::Class> ArtMethod::GetDeclaringClassUnchecked() {
     52   GcRootSource gc_root_source(this);
     53   return declaring_class_.Read<kReadBarrierOption>(&gc_root_source);
     54 }
     55 
     56 template <ReadBarrierOption kReadBarrierOption>
     57 inline ObjPtr<mirror::Class> ArtMethod::GetDeclaringClass() {
     58   ObjPtr<mirror::Class> result = GetDeclaringClassUnchecked<kReadBarrierOption>();
     59   if (kIsDebugBuild) {
     60     if (!IsRuntimeMethod()) {
     61       CHECK(result != nullptr) << this;
     62     } else {
     63       CHECK(result == nullptr) << this;
     64     }
     65   }
     66   return result;
     67 }
     68 
     69 inline void ArtMethod::SetDeclaringClass(ObjPtr<mirror::Class> new_declaring_class) {
     70   declaring_class_ = GcRoot<mirror::Class>(new_declaring_class);
     71 }
     72 
     73 inline bool ArtMethod::CASDeclaringClass(ObjPtr<mirror::Class> expected_class,
     74                                          ObjPtr<mirror::Class> desired_class) {
     75   GcRoot<mirror::Class> expected_root(expected_class);
     76   GcRoot<mirror::Class> desired_root(desired_class);
     77   auto atomic_root_class = reinterpret_cast<Atomic<GcRoot<mirror::Class>>*>(&declaring_class_);
     78   return atomic_root_class->CompareAndSetStrongSequentiallyConsistent(expected_root, desired_root);
     79 }
     80 
     81 inline uint16_t ArtMethod::GetMethodIndex() {
     82   DCHECK(IsRuntimeMethod() || GetDeclaringClass()->IsResolved());
     83   return method_index_;
     84 }
     85 
     86 inline uint16_t ArtMethod::GetMethodIndexDuringLinking() {
     87   return method_index_;
     88 }
     89 
     90 inline ObjPtr<mirror::Class> ArtMethod::LookupResolvedClassFromTypeIndex(dex::TypeIndex type_idx) {
     91   ScopedAssertNoThreadSuspension ants(__FUNCTION__);
     92   ObjPtr<mirror::Class> type =
     93       Runtime::Current()->GetClassLinker()->LookupResolvedType(type_idx, this);
     94   DCHECK(!Thread::Current()->IsExceptionPending());
     95   return type;
     96 }
     97 
     98 inline ObjPtr<mirror::Class> ArtMethod::ResolveClassFromTypeIndex(dex::TypeIndex type_idx) {
     99   ObjPtr<mirror::Class> type = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, this);
    100   DCHECK_EQ(type == nullptr, Thread::Current()->IsExceptionPending());
    101   return type;
    102 }
    103 
    104 inline bool ArtMethod::CheckIncompatibleClassChange(InvokeType type) {
    105   switch (type) {
    106     case kStatic:
    107       return !IsStatic();
    108     case kDirect:
    109       return !IsDirect() || IsStatic();
    110     case kVirtual: {
    111       // We have an error if we are direct or a non-copied (i.e. not part of a real class) interface
    112       // method.
    113       ObjPtr<mirror::Class> methods_class = GetDeclaringClass();
    114       return IsDirect() || (methods_class->IsInterface() && !IsCopied());
    115     }
    116     case kSuper:
    117       // Constructors and static methods are called with invoke-direct.
    118       return IsConstructor() || IsStatic();
    119     case kInterface: {
    120       ObjPtr<mirror::Class> methods_class = GetDeclaringClass();
    121       return IsDirect() || !(methods_class->IsInterface() || methods_class->IsObjectClass());
    122     }
    123     default:
    124       LOG(FATAL) << "Unreachable - invocation type: " << type;
    125       UNREACHABLE();
    126   }
    127 }
    128 
    129 inline bool ArtMethod::IsCalleeSaveMethod() {
    130   if (!IsRuntimeMethod()) {
    131     return false;
    132   }
    133   Runtime* runtime = Runtime::Current();
    134   bool result = false;
    135   for (uint32_t i = 0; i < static_cast<uint32_t>(CalleeSaveType::kLastCalleeSaveType); i++) {
    136     if (this == runtime->GetCalleeSaveMethod(CalleeSaveType(i))) {
    137       result = true;
    138       break;
    139     }
    140   }
    141   return result;
    142 }
    143 
    144 inline bool ArtMethod::IsResolutionMethod() {
    145   bool result = this == Runtime::Current()->GetResolutionMethod();
    146   // Check that if we do think it is phony it looks like the resolution method.
    147   DCHECK(!result || IsRuntimeMethod());
    148   return result;
    149 }
    150 
    151 inline bool ArtMethod::IsImtUnimplementedMethod() {
    152   bool result = this == Runtime::Current()->GetImtUnimplementedMethod();
    153   // Check that if we do think it is phony it looks like the imt unimplemented method.
    154   DCHECK(!result || IsRuntimeMethod());
    155   return result;
    156 }
    157 
    158 inline const DexFile* ArtMethod::GetDexFile() {
    159   // It is safe to avoid the read barrier here since the dex file is constant, so if we read the
    160   // from-space dex file pointer it will be equal to the to-space copy.
    161   return GetDexCache<kWithoutReadBarrier>()->GetDexFile();
    162 }
    163 
    164 inline const char* ArtMethod::GetDeclaringClassDescriptor() {
    165   uint32_t dex_method_idx = GetDexMethodIndex();
    166   if (UNLIKELY(dex_method_idx == dex::kDexNoIndex)) {
    167     return "<runtime method>";
    168   }
    169   DCHECK(!IsProxyMethod());
    170   const DexFile* dex_file = GetDexFile();
    171   return dex_file->GetMethodDeclaringClassDescriptor(dex_file->GetMethodId(dex_method_idx));
    172 }
    173 
    174 inline const char* ArtMethod::GetShorty() {
    175   uint32_t unused_length;
    176   return GetShorty(&unused_length);
    177 }
    178 
    179 inline const char* ArtMethod::GetShorty(uint32_t* out_length) {
    180   DCHECK(!IsProxyMethod());
    181   const DexFile* dex_file = GetDexFile();
    182   return dex_file->GetMethodShorty(dex_file->GetMethodId(GetDexMethodIndex()), out_length);
    183 }
    184 
    185 inline const Signature ArtMethod::GetSignature() {
    186   uint32_t dex_method_idx = GetDexMethodIndex();
    187   if (dex_method_idx != dex::kDexNoIndex) {
    188     DCHECK(!IsProxyMethod());
    189     const DexFile* dex_file = GetDexFile();
    190     return dex_file->GetMethodSignature(dex_file->GetMethodId(dex_method_idx));
    191   }
    192   return Signature::NoSignature();
    193 }
    194 
    195 inline const char* ArtMethod::GetName() {
    196   uint32_t dex_method_idx = GetDexMethodIndex();
    197   if (LIKELY(dex_method_idx != dex::kDexNoIndex)) {
    198     DCHECK(!IsProxyMethod());
    199     const DexFile* dex_file = GetDexFile();
    200     return dex_file->GetMethodName(dex_file->GetMethodId(dex_method_idx));
    201   }
    202   return GetRuntimeMethodName();
    203 }
    204 
    205 inline std::string_view ArtMethod::GetNameView() {
    206   uint32_t dex_method_idx = GetDexMethodIndex();
    207   if (LIKELY(dex_method_idx != dex::kDexNoIndex)) {
    208     DCHECK(!IsProxyMethod());
    209     const DexFile* dex_file = GetDexFile();
    210     uint32_t length = 0;
    211     const char* name = dex_file->GetMethodName(dex_file->GetMethodId(dex_method_idx), &length);
    212     return StringViewFromUtf16Length(name, length);
    213   }
    214   return GetRuntimeMethodName();
    215 }
    216 
    217 inline ObjPtr<mirror::String> ArtMethod::ResolveNameString() {
    218   DCHECK(!IsProxyMethod());
    219   const dex::MethodId& method_id = GetDexFile()->GetMethodId(GetDexMethodIndex());
    220   return Runtime::Current()->GetClassLinker()->ResolveString(method_id.name_idx_, this);
    221 }
    222 
    223 inline const dex::CodeItem* ArtMethod::GetCodeItem() {
    224   return GetDexFile()->GetCodeItem(GetCodeItemOffset());
    225 }
    226 
    227 inline bool ArtMethod::IsResolvedTypeIdx(dex::TypeIndex type_idx) {
    228   DCHECK(!IsProxyMethod());
    229   return LookupResolvedClassFromTypeIndex(type_idx) != nullptr;
    230 }
    231 
    232 inline int32_t ArtMethod::GetLineNumFromDexPC(uint32_t dex_pc) {
    233   DCHECK(!IsProxyMethod());
    234   if (dex_pc == dex::kDexNoIndex) {
    235     return IsNative() ? -2 : -1;
    236   }
    237   return annotations::GetLineNumFromPC(GetDexFile(), this, dex_pc);
    238 }
    239 
    240 inline const dex::ProtoId& ArtMethod::GetPrototype() {
    241   DCHECK(!IsProxyMethod());
    242   const DexFile* dex_file = GetDexFile();
    243   return dex_file->GetMethodPrototype(dex_file->GetMethodId(GetDexMethodIndex()));
    244 }
    245 
    246 inline const dex::TypeList* ArtMethod::GetParameterTypeList() {
    247   DCHECK(!IsProxyMethod());
    248   const DexFile* dex_file = GetDexFile();
    249   const dex::ProtoId& proto = dex_file->GetMethodPrototype(
    250       dex_file->GetMethodId(GetDexMethodIndex()));
    251   return dex_file->GetProtoParameters(proto);
    252 }
    253 
    254 inline const char* ArtMethod::GetDeclaringClassSourceFile() {
    255   DCHECK(!IsProxyMethod());
    256   return GetDeclaringClass()->GetSourceFile();
    257 }
    258 
    259 inline uint16_t ArtMethod::GetClassDefIndex() {
    260   DCHECK(!IsProxyMethod());
    261   if (LIKELY(!IsObsolete())) {
    262     return GetDeclaringClass()->GetDexClassDefIndex();
    263   } else {
    264     return FindObsoleteDexClassDefIndex();
    265   }
    266 }
    267 
    268 inline const dex::ClassDef& ArtMethod::GetClassDef() {
    269   DCHECK(!IsProxyMethod());
    270   return GetDexFile()->GetClassDef(GetClassDefIndex());
    271 }
    272 
    273 inline size_t ArtMethod::GetNumberOfParameters() {
    274   constexpr size_t return_type_count = 1u;
    275   return strlen(GetShorty()) - return_type_count;
    276 }
    277 
    278 inline const char* ArtMethod::GetReturnTypeDescriptor() {
    279   DCHECK(!IsProxyMethod());
    280   const DexFile* dex_file = GetDexFile();
    281   return dex_file->GetTypeDescriptor(dex_file->GetTypeId(GetReturnTypeIndex()));
    282 }
    283 
    284 inline Primitive::Type ArtMethod::GetReturnTypePrimitive() {
    285   return Primitive::GetType(GetReturnTypeDescriptor()[0]);
    286 }
    287 
    288 inline const char* ArtMethod::GetTypeDescriptorFromTypeIdx(dex::TypeIndex type_idx) {
    289   DCHECK(!IsProxyMethod());
    290   const DexFile* dex_file = GetDexFile();
    291   return dex_file->GetTypeDescriptor(dex_file->GetTypeId(type_idx));
    292 }
    293 
    294 inline ObjPtr<mirror::ClassLoader> ArtMethod::GetClassLoader() {
    295   DCHECK(!IsProxyMethod());
    296   return GetDeclaringClass()->GetClassLoader();
    297 }
    298 
    299 template <ReadBarrierOption kReadBarrierOption>
    300 inline ObjPtr<mirror::DexCache> ArtMethod::GetDexCache() {
    301   if (LIKELY(!IsObsolete())) {
    302     ObjPtr<mirror::Class> klass = GetDeclaringClass<kReadBarrierOption>();
    303     return klass->GetDexCache<kDefaultVerifyFlags, kReadBarrierOption>();
    304   } else {
    305     DCHECK(!IsProxyMethod());
    306     return GetObsoleteDexCache();
    307   }
    308 }
    309 
    310 inline bool ArtMethod::IsProxyMethod() {
    311   DCHECK(!IsRuntimeMethod()) << "ArtMethod::IsProxyMethod called on a runtime method";
    312   // No read barrier needed, we're reading the constant declaring class only to read
    313   // the constant proxy flag. See ReadBarrierOption.
    314   return GetDeclaringClass<kWithoutReadBarrier>()->IsProxyClass();
    315 }
    316 
    317 inline ArtMethod* ArtMethod::GetInterfaceMethodForProxyUnchecked(PointerSize pointer_size) {
    318   DCHECK(IsProxyMethod());
    319   // Do not check IsAssignableFrom() here as it relies on raw reference comparison
    320   // which may give false negatives while visiting references for a non-CC moving GC.
    321   return reinterpret_cast<ArtMethod*>(GetDataPtrSize(pointer_size));
    322 }
    323 
    324 inline ArtMethod* ArtMethod::GetInterfaceMethodIfProxy(PointerSize pointer_size) {
    325   if (LIKELY(!IsProxyMethod())) {
    326     return this;
    327   }
    328   ArtMethod* interface_method = GetInterfaceMethodForProxyUnchecked(pointer_size);
    329   // We can check that the proxy class implements the interface only if the proxy class
    330   // is resolved, otherwise the interface table is not yet initialized.
    331   DCHECK(!GetDeclaringClass()->IsResolved() ||
    332          interface_method->GetDeclaringClass()->IsAssignableFrom(GetDeclaringClass()));
    333   return interface_method;
    334 }
    335 
    336 inline dex::TypeIndex ArtMethod::GetReturnTypeIndex() {
    337   DCHECK(!IsProxyMethod());
    338   const DexFile* dex_file = GetDexFile();
    339   const dex::MethodId& method_id = dex_file->GetMethodId(GetDexMethodIndex());
    340   const dex::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id);
    341   return proto_id.return_type_idx_;
    342 }
    343 
    344 inline ObjPtr<mirror::Class> ArtMethod::LookupResolvedReturnType() {
    345   return LookupResolvedClassFromTypeIndex(GetReturnTypeIndex());
    346 }
    347 
    348 inline ObjPtr<mirror::Class> ArtMethod::ResolveReturnType() {
    349   return ResolveClassFromTypeIndex(GetReturnTypeIndex());
    350 }
    351 
    352 template <ReadBarrierOption kReadBarrierOption>
    353 inline bool ArtMethod::HasSingleImplementation() {
    354   if (IsFinal() || GetDeclaringClass<kReadBarrierOption>()->IsFinal()) {
    355     // We don't set kAccSingleImplementation for these cases since intrinsic
    356     // can use the flag also.
    357     return true;
    358   }
    359   return (GetAccessFlags() & kAccSingleImplementation) != 0;
    360 }
    361 
    362 template<ReadBarrierOption kReadBarrierOption, typename RootVisitorType>
    363 void ArtMethod::VisitRoots(RootVisitorType& visitor, PointerSize pointer_size) {
    364   if (LIKELY(!declaring_class_.IsNull())) {
    365     visitor.VisitRoot(declaring_class_.AddressWithoutBarrier());
    366     ObjPtr<mirror::Class> klass = declaring_class_.Read<kReadBarrierOption>();
    367     if (UNLIKELY(klass->IsProxyClass())) {
    368       // For normal methods, dex cache shortcuts will be visited through the declaring class.
    369       // However, for proxies we need to keep the interface method alive, so we visit its roots.
    370       ArtMethod* interface_method = GetInterfaceMethodForProxyUnchecked(pointer_size);
    371       DCHECK(interface_method != nullptr);
    372       interface_method->VisitRoots(visitor, pointer_size);
    373     }
    374   }
    375 }
    376 
    377 template <typename Visitor>
    378 inline void ArtMethod::UpdateObjectsForImageRelocation(const Visitor& visitor) {
    379   ObjPtr<mirror::Class> old_class = GetDeclaringClassUnchecked<kWithoutReadBarrier>();
    380   ObjPtr<mirror::Class> new_class = visitor(old_class.Ptr());
    381   if (old_class != new_class) {
    382     SetDeclaringClass(new_class);
    383   }
    384 }
    385 
    386 template <typename Visitor>
    387 inline void ArtMethod::UpdateEntrypoints(const Visitor& visitor, PointerSize pointer_size) {
    388   if (IsNative()) {
    389     const void* old_native_code = GetEntryPointFromJniPtrSize(pointer_size);
    390     const void* new_native_code = visitor(old_native_code);
    391     if (old_native_code != new_native_code) {
    392       SetEntryPointFromJniPtrSize(new_native_code, pointer_size);
    393     }
    394   } else {
    395     DCHECK(GetDataPtrSize(pointer_size) == nullptr);
    396   }
    397   const void* old_code = GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
    398   const void* new_code = visitor(old_code);
    399   if (old_code != new_code) {
    400     SetEntryPointFromQuickCompiledCodePtrSize(new_code, pointer_size);
    401   }
    402 }
    403 
    404 inline CodeItemInstructionAccessor ArtMethod::DexInstructions() {
    405   return CodeItemInstructionAccessor(*GetDexFile(), GetCodeItem());
    406 }
    407 
    408 inline CodeItemDataAccessor ArtMethod::DexInstructionData() {
    409   return CodeItemDataAccessor(*GetDexFile(), GetCodeItem());
    410 }
    411 
    412 inline CodeItemDebugInfoAccessor ArtMethod::DexInstructionDebugInfo() {
    413   return CodeItemDebugInfoAccessor(*GetDexFile(), GetCodeItem(), GetDexMethodIndex());
    414 }
    415 
    416 inline void ArtMethod::SetCounter(int16_t hotness_count) {
    417   DCHECK(!IsAbstract()) << PrettyMethod();
    418   hotness_count_ = hotness_count;
    419 }
    420 
    421 inline uint16_t ArtMethod::GetCounter() {
    422   DCHECK(!IsAbstract()) << PrettyMethod();
    423   return hotness_count_;
    424 }
    425 
    426 inline uint32_t ArtMethod::GetImtIndex() {
    427   if (LIKELY(IsAbstract() && imt_index_ != 0)) {
    428     uint16_t imt_index = ~imt_index_;
    429     DCHECK_EQ(imt_index, ImTable::GetImtIndex(this)) << PrettyMethod();
    430     return imt_index;
    431   } else {
    432     return ImTable::GetImtIndex(this);
    433   }
    434 }
    435 
    436 inline void ArtMethod::CalculateAndSetImtIndex() {
    437   DCHECK(IsAbstract()) << PrettyMethod();
    438   imt_index_ = ~ImTable::GetImtIndex(this);
    439 }
    440 
    441 }  // namespace art
    442 
    443 #endif  // ART_RUNTIME_ART_METHOD_INL_H_
    444