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_H_
     18 #define ART_RUNTIME_ART_METHOD_H_
     19 
     20 #include "base/bit_utils.h"
     21 #include "base/casts.h"
     22 #include "dex_file.h"
     23 #include "gc_root.h"
     24 #include "invoke_type.h"
     25 #include "method_reference.h"
     26 #include "modifiers.h"
     27 #include "mirror/object.h"
     28 #include "read_barrier_option.h"
     29 #include "stack.h"
     30 #include "utils.h"
     31 
     32 namespace art {
     33 
     34 union JValue;
     35 class OatQuickMethodHeader;
     36 class ProfilingInfo;
     37 class ScopedObjectAccessAlreadyRunnable;
     38 class StringPiece;
     39 class ShadowFrame;
     40 
     41 namespace mirror {
     42 class Array;
     43 class Class;
     44 class IfTable;
     45 class PointerArray;
     46 }  // namespace mirror
     47 
     48 // Table to resolve IMT conflicts at runtime. The table is attached to
     49 // the jni entrypoint of IMT conflict ArtMethods.
     50 // The table contains a list of pairs of { interface_method, implementation_method }
     51 // with the last entry being null to make an assembly implementation of a lookup
     52 // faster.
     53 class ImtConflictTable {
     54   enum MethodIndex {
     55     kMethodInterface,
     56     kMethodImplementation,
     57     kMethodCount,  // Number of elements in enum.
     58   };
     59 
     60  public:
     61   // Build a new table copying `other` and adding the new entry formed of
     62   // the pair { `interface_method`, `implementation_method` }
     63   ImtConflictTable(ImtConflictTable* other,
     64                    ArtMethod* interface_method,
     65                    ArtMethod* implementation_method,
     66                    size_t pointer_size) {
     67     const size_t count = other->NumEntries(pointer_size);
     68     for (size_t i = 0; i < count; ++i) {
     69       SetInterfaceMethod(i, pointer_size, other->GetInterfaceMethod(i, pointer_size));
     70       SetImplementationMethod(i, pointer_size, other->GetImplementationMethod(i, pointer_size));
     71     }
     72     SetInterfaceMethod(count, pointer_size, interface_method);
     73     SetImplementationMethod(count, pointer_size, implementation_method);
     74     // Add the null marker.
     75     SetInterfaceMethod(count + 1, pointer_size, nullptr);
     76     SetImplementationMethod(count + 1, pointer_size, nullptr);
     77   }
     78 
     79   // num_entries excludes the header.
     80   ImtConflictTable(size_t num_entries, size_t pointer_size) {
     81     SetInterfaceMethod(num_entries, pointer_size, nullptr);
     82     SetImplementationMethod(num_entries, pointer_size, nullptr);
     83   }
     84 
     85   // Set an entry at an index.
     86   void SetInterfaceMethod(size_t index, size_t pointer_size, ArtMethod* method) {
     87     SetMethod(index * kMethodCount + kMethodInterface, pointer_size, method);
     88   }
     89 
     90   void SetImplementationMethod(size_t index, size_t pointer_size, ArtMethod* method) {
     91     SetMethod(index * kMethodCount + kMethodImplementation, pointer_size, method);
     92   }
     93 
     94   ArtMethod* GetInterfaceMethod(size_t index, size_t pointer_size) const {
     95     return GetMethod(index * kMethodCount + kMethodInterface, pointer_size);
     96   }
     97 
     98   ArtMethod* GetImplementationMethod(size_t index, size_t pointer_size) const {
     99     return GetMethod(index * kMethodCount + kMethodImplementation, pointer_size);
    100   }
    101 
    102   // Return true if two conflict tables are the same.
    103   bool Equals(ImtConflictTable* other, size_t pointer_size) const {
    104     size_t num = NumEntries(pointer_size);
    105     if (num != other->NumEntries(pointer_size)) {
    106       return false;
    107     }
    108     for (size_t i = 0; i < num; ++i) {
    109       if (GetInterfaceMethod(i, pointer_size) != other->GetInterfaceMethod(i, pointer_size) ||
    110           GetImplementationMethod(i, pointer_size) !=
    111               other->GetImplementationMethod(i, pointer_size)) {
    112         return false;
    113       }
    114     }
    115     return true;
    116   }
    117 
    118   // Visit all of the entries.
    119   // NO_THREAD_SAFETY_ANALYSIS for calling with held locks. Visitor is passed a pair of ArtMethod*
    120   // and also returns one. The order is <interface, implementation>.
    121   template<typename Visitor>
    122   void Visit(const Visitor& visitor, size_t pointer_size) NO_THREAD_SAFETY_ANALYSIS {
    123     uint32_t table_index = 0;
    124     for (;;) {
    125       ArtMethod* interface_method = GetInterfaceMethod(table_index, pointer_size);
    126       if (interface_method == nullptr) {
    127         break;
    128       }
    129       ArtMethod* implementation_method = GetImplementationMethod(table_index, pointer_size);
    130       auto input = std::make_pair(interface_method, implementation_method);
    131       std::pair<ArtMethod*, ArtMethod*> updated = visitor(input);
    132       if (input.first != updated.first) {
    133         SetInterfaceMethod(table_index, pointer_size, updated.first);
    134       }
    135       if (input.second != updated.second) {
    136         SetImplementationMethod(table_index, pointer_size, updated.second);
    137       }
    138       ++table_index;
    139     }
    140   }
    141 
    142   // Lookup the implementation ArtMethod associated to `interface_method`. Return null
    143   // if not found.
    144   ArtMethod* Lookup(ArtMethod* interface_method, size_t pointer_size) const {
    145     uint32_t table_index = 0;
    146     for (;;) {
    147       ArtMethod* current_interface_method = GetInterfaceMethod(table_index, pointer_size);
    148       if (current_interface_method == nullptr) {
    149         break;
    150       }
    151       if (current_interface_method == interface_method) {
    152         return GetImplementationMethod(table_index, pointer_size);
    153       }
    154       ++table_index;
    155     }
    156     return nullptr;
    157   }
    158 
    159   // Compute the number of entries in this table.
    160   size_t NumEntries(size_t pointer_size) const {
    161     uint32_t table_index = 0;
    162     while (GetInterfaceMethod(table_index, pointer_size) != nullptr) {
    163       ++table_index;
    164     }
    165     return table_index;
    166   }
    167 
    168   // Compute the size in bytes taken by this table.
    169   size_t ComputeSize(size_t pointer_size) const {
    170     // Add the end marker.
    171     return ComputeSize(NumEntries(pointer_size), pointer_size);
    172   }
    173 
    174   // Compute the size in bytes needed for copying the given `table` and add
    175   // one more entry.
    176   static size_t ComputeSizeWithOneMoreEntry(ImtConflictTable* table, size_t pointer_size) {
    177     return table->ComputeSize(pointer_size) + EntrySize(pointer_size);
    178   }
    179 
    180   // Compute size with a fixed number of entries.
    181   static size_t ComputeSize(size_t num_entries, size_t pointer_size) {
    182     return (num_entries + 1) * EntrySize(pointer_size);  // Add one for null terminator.
    183   }
    184 
    185   static size_t EntrySize(size_t pointer_size) {
    186     return pointer_size * static_cast<size_t>(kMethodCount);
    187   }
    188 
    189  private:
    190   ArtMethod* GetMethod(size_t index, size_t pointer_size) const {
    191     if (pointer_size == 8) {
    192       return reinterpret_cast<ArtMethod*>(static_cast<uintptr_t>(data64_[index]));
    193     } else {
    194       DCHECK_EQ(pointer_size, 4u);
    195       return reinterpret_cast<ArtMethod*>(static_cast<uintptr_t>(data32_[index]));
    196     }
    197   }
    198 
    199   void SetMethod(size_t index, size_t pointer_size, ArtMethod* method) {
    200     if (pointer_size == 8) {
    201       data64_[index] = dchecked_integral_cast<uint64_t>(reinterpret_cast<uintptr_t>(method));
    202     } else {
    203       DCHECK_EQ(pointer_size, 4u);
    204       data32_[index] = dchecked_integral_cast<uint32_t>(reinterpret_cast<uintptr_t>(method));
    205     }
    206   }
    207 
    208   // Array of entries that the assembly stubs will iterate over. Note that this is
    209   // not fixed size, and we allocate data prior to calling the constructor
    210   // of ImtConflictTable.
    211   union {
    212     uint32_t data32_[0];
    213     uint64_t data64_[0];
    214   };
    215 
    216   DISALLOW_COPY_AND_ASSIGN(ImtConflictTable);
    217 };
    218 
    219 class ArtMethod FINAL {
    220  public:
    221   ArtMethod() : access_flags_(0), dex_code_item_offset_(0), dex_method_index_(0),
    222       method_index_(0) { }
    223 
    224   ArtMethod(ArtMethod* src, size_t image_pointer_size) {
    225     CopyFrom(src, image_pointer_size);
    226   }
    227 
    228   static ArtMethod* FromReflectedMethod(const ScopedObjectAccessAlreadyRunnable& soa,
    229                                         jobject jlr_method)
    230       SHARED_REQUIRES(Locks::mutator_lock_);
    231 
    232   template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
    233   ALWAYS_INLINE mirror::Class* GetDeclaringClass() SHARED_REQUIRES(Locks::mutator_lock_);
    234 
    235   template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
    236   ALWAYS_INLINE mirror::Class* GetDeclaringClassUnchecked()
    237       SHARED_REQUIRES(Locks::mutator_lock_);
    238 
    239   void SetDeclaringClass(mirror::Class *new_declaring_class)
    240       SHARED_REQUIRES(Locks::mutator_lock_);
    241 
    242   bool CASDeclaringClass(mirror::Class* expected_class, mirror::Class* desired_class)
    243       SHARED_REQUIRES(Locks::mutator_lock_);
    244 
    245   static MemberOffset DeclaringClassOffset() {
    246     return MemberOffset(OFFSETOF_MEMBER(ArtMethod, declaring_class_));
    247   }
    248 
    249   // Note: GetAccessFlags acquires the mutator lock in debug mode to check that it is not called for
    250   // a proxy method.
    251   template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
    252   ALWAYS_INLINE uint32_t GetAccessFlags();
    253 
    254   void SetAccessFlags(uint32_t new_access_flags) {
    255     // Not called within a transaction.
    256     access_flags_ = new_access_flags;
    257   }
    258 
    259   // Approximate what kind of method call would be used for this method.
    260   InvokeType GetInvokeType() SHARED_REQUIRES(Locks::mutator_lock_);
    261 
    262   // Returns true if the method is declared public.
    263   bool IsPublic() {
    264     return (GetAccessFlags() & kAccPublic) != 0;
    265   }
    266 
    267   // Returns true if the method is declared private.
    268   bool IsPrivate() {
    269     return (GetAccessFlags() & kAccPrivate) != 0;
    270   }
    271 
    272   // Returns true if the method is declared static.
    273   bool IsStatic() {
    274     return (GetAccessFlags() & kAccStatic) != 0;
    275   }
    276 
    277   // Returns true if the method is a constructor.
    278   bool IsConstructor() {
    279     return (GetAccessFlags() & kAccConstructor) != 0;
    280   }
    281 
    282   // Returns true if the method is a class initializer.
    283   bool IsClassInitializer() {
    284     return IsConstructor() && IsStatic();
    285   }
    286 
    287   // Returns true if the method is static, private, or a constructor.
    288   bool IsDirect() {
    289     return IsDirect(GetAccessFlags());
    290   }
    291 
    292   static bool IsDirect(uint32_t access_flags) {
    293     constexpr uint32_t direct = kAccStatic | kAccPrivate | kAccConstructor;
    294     return (access_flags & direct) != 0;
    295   }
    296 
    297   // Returns true if the method is declared synchronized.
    298   bool IsSynchronized() {
    299     constexpr uint32_t synchonized = kAccSynchronized | kAccDeclaredSynchronized;
    300     return (GetAccessFlags() & synchonized) != 0;
    301   }
    302 
    303   bool IsFinal() {
    304     return (GetAccessFlags() & kAccFinal) != 0;
    305   }
    306 
    307   bool IsCopied() {
    308     const bool copied = (GetAccessFlags() & kAccCopied) != 0;
    309     // (IsMiranda() || IsDefaultConflicting()) implies copied
    310     DCHECK(!(IsMiranda() || IsDefaultConflicting()) || copied)
    311         << "Miranda or default-conflict methods must always be copied.";
    312     return copied;
    313   }
    314 
    315   bool IsMiranda() {
    316     return (GetAccessFlags() & kAccMiranda) != 0;
    317   }
    318 
    319   // Returns true if invoking this method will not throw an AbstractMethodError or
    320   // IncompatibleClassChangeError.
    321   bool IsInvokable() {
    322     return !IsAbstract() && !IsDefaultConflicting();
    323   }
    324 
    325   bool IsCompilable() {
    326     return (GetAccessFlags() & kAccCompileDontBother) == 0;
    327   }
    328 
    329   // A default conflict method is a special sentinel method that stands for a conflict between
    330   // multiple default methods. It cannot be invoked, throwing an IncompatibleClassChangeError if one
    331   // attempts to do so.
    332   bool IsDefaultConflicting() {
    333     return (GetAccessFlags() & kAccDefaultConflict) != 0u;
    334   }
    335 
    336   // This is set by the class linker.
    337   bool IsDefault() {
    338     return (GetAccessFlags() & kAccDefault) != 0;
    339   }
    340 
    341   template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
    342   bool IsNative() {
    343     return (GetAccessFlags<kReadBarrierOption>() & kAccNative) != 0;
    344   }
    345 
    346   bool IsFastNative() {
    347     constexpr uint32_t mask = kAccFastNative | kAccNative;
    348     return (GetAccessFlags() & mask) == mask;
    349   }
    350 
    351   bool IsAbstract() {
    352     return (GetAccessFlags() & kAccAbstract) != 0;
    353   }
    354 
    355   bool IsSynthetic() {
    356     return (GetAccessFlags() & kAccSynthetic) != 0;
    357   }
    358 
    359   bool IsProxyMethod() SHARED_REQUIRES(Locks::mutator_lock_);
    360 
    361   bool SkipAccessChecks() {
    362     return (GetAccessFlags() & kAccSkipAccessChecks) != 0;
    363   }
    364 
    365   void SetSkipAccessChecks() {
    366     DCHECK(!SkipAccessChecks());
    367     SetAccessFlags(GetAccessFlags() | kAccSkipAccessChecks);
    368   }
    369 
    370   // Should this method be run in the interpreter and count locks (e.g., failed structured-
    371   // locking verification)?
    372   bool MustCountLocks() {
    373     return (GetAccessFlags() & kAccMustCountLocks) != 0;
    374   }
    375 
    376   // Returns true if this method could be overridden by a default method.
    377   bool IsOverridableByDefaultMethod() SHARED_REQUIRES(Locks::mutator_lock_);
    378 
    379   bool CheckIncompatibleClassChange(InvokeType type) SHARED_REQUIRES(Locks::mutator_lock_);
    380 
    381   // Throws the error that would result from trying to invoke this method (i.e.
    382   // IncompatibleClassChangeError or AbstractMethodError). Only call if !IsInvokable();
    383   void ThrowInvocationTimeError() SHARED_REQUIRES(Locks::mutator_lock_);
    384 
    385   uint16_t GetMethodIndex() SHARED_REQUIRES(Locks::mutator_lock_);
    386 
    387   // Doesn't do erroneous / unresolved class checks.
    388   uint16_t GetMethodIndexDuringLinking() SHARED_REQUIRES(Locks::mutator_lock_);
    389 
    390   size_t GetVtableIndex() SHARED_REQUIRES(Locks::mutator_lock_) {
    391     return GetMethodIndex();
    392   }
    393 
    394   void SetMethodIndex(uint16_t new_method_index) SHARED_REQUIRES(Locks::mutator_lock_) {
    395     // Not called within a transaction.
    396     method_index_ = new_method_index;
    397   }
    398 
    399   static MemberOffset DexMethodIndexOffset() {
    400     return OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_method_index_);
    401   }
    402 
    403   static MemberOffset MethodIndexOffset() {
    404     return OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_);
    405   }
    406 
    407   uint32_t GetCodeItemOffset() {
    408     return dex_code_item_offset_;
    409   }
    410 
    411   void SetCodeItemOffset(uint32_t new_code_off) {
    412     // Not called within a transaction.
    413     dex_code_item_offset_ = new_code_off;
    414   }
    415 
    416   // Number of 32bit registers that would be required to hold all the arguments
    417   static size_t NumArgRegisters(const StringPiece& shorty);
    418 
    419   ALWAYS_INLINE uint32_t GetDexMethodIndex() SHARED_REQUIRES(Locks::mutator_lock_);
    420 
    421   void SetDexMethodIndex(uint32_t new_idx) {
    422     // Not called within a transaction.
    423     dex_method_index_ = new_idx;
    424   }
    425 
    426   ALWAYS_INLINE ArtMethod** GetDexCacheResolvedMethods(size_t pointer_size)
    427       SHARED_REQUIRES(Locks::mutator_lock_);
    428   ALWAYS_INLINE ArtMethod* GetDexCacheResolvedMethod(uint16_t method_index, size_t ptr_size)
    429       SHARED_REQUIRES(Locks::mutator_lock_);
    430   ALWAYS_INLINE void SetDexCacheResolvedMethod(uint16_t method_index,
    431                                                ArtMethod* new_method,
    432                                                size_t ptr_size)
    433       SHARED_REQUIRES(Locks::mutator_lock_);
    434   ALWAYS_INLINE void SetDexCacheResolvedMethods(ArtMethod** new_dex_cache_methods, size_t ptr_size)
    435       SHARED_REQUIRES(Locks::mutator_lock_);
    436   bool HasDexCacheResolvedMethods(size_t pointer_size) SHARED_REQUIRES(Locks::mutator_lock_);
    437   bool HasSameDexCacheResolvedMethods(ArtMethod* other, size_t pointer_size)
    438       SHARED_REQUIRES(Locks::mutator_lock_);
    439   bool HasSameDexCacheResolvedMethods(ArtMethod** other_cache, size_t pointer_size)
    440       SHARED_REQUIRES(Locks::mutator_lock_);
    441 
    442   template <bool kWithCheck = true>
    443   mirror::Class* GetDexCacheResolvedType(uint32_t type_idx, size_t ptr_size)
    444       SHARED_REQUIRES(Locks::mutator_lock_);
    445   void SetDexCacheResolvedTypes(GcRoot<mirror::Class>* new_dex_cache_types, size_t ptr_size)
    446       SHARED_REQUIRES(Locks::mutator_lock_);
    447   bool HasDexCacheResolvedTypes(size_t pointer_size) SHARED_REQUIRES(Locks::mutator_lock_);
    448   bool HasSameDexCacheResolvedTypes(ArtMethod* other, size_t pointer_size)
    449       SHARED_REQUIRES(Locks::mutator_lock_);
    450   bool HasSameDexCacheResolvedTypes(GcRoot<mirror::Class>* other_cache, size_t pointer_size)
    451       SHARED_REQUIRES(Locks::mutator_lock_);
    452 
    453   // Get the Class* from the type index into this method's dex cache.
    454   mirror::Class* GetClassFromTypeIndex(uint16_t type_idx, bool resolve, size_t ptr_size)
    455       SHARED_REQUIRES(Locks::mutator_lock_);
    456 
    457   // Returns true if this method has the same name and signature of the other method.
    458   bool HasSameNameAndSignature(ArtMethod* other) SHARED_REQUIRES(Locks::mutator_lock_);
    459 
    460   // Find the method that this method overrides.
    461   ArtMethod* FindOverriddenMethod(size_t pointer_size)
    462       SHARED_REQUIRES(Locks::mutator_lock_);
    463 
    464   // Find the method index for this method within other_dexfile. If this method isn't present then
    465   // return DexFile::kDexNoIndex. The name_and_signature_idx MUST refer to a MethodId with the same
    466   // name and signature in the other_dexfile, such as the method index used to resolve this method
    467   // in the other_dexfile.
    468   uint32_t FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile,
    469                                             uint32_t name_and_signature_idx)
    470       SHARED_REQUIRES(Locks::mutator_lock_);
    471 
    472   void Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result, const char* shorty)
    473       SHARED_REQUIRES(Locks::mutator_lock_);
    474 
    475   const void* GetEntryPointFromQuickCompiledCode() {
    476     return GetEntryPointFromQuickCompiledCodePtrSize(sizeof(void*));
    477   }
    478   ALWAYS_INLINE const void* GetEntryPointFromQuickCompiledCodePtrSize(size_t pointer_size) {
    479     return GetNativePointer<const void*>(
    480         EntryPointFromQuickCompiledCodeOffset(pointer_size), pointer_size);
    481   }
    482 
    483   void SetEntryPointFromQuickCompiledCode(const void* entry_point_from_quick_compiled_code) {
    484     SetEntryPointFromQuickCompiledCodePtrSize(entry_point_from_quick_compiled_code,
    485                                               sizeof(void*));
    486   }
    487   ALWAYS_INLINE void SetEntryPointFromQuickCompiledCodePtrSize(
    488       const void* entry_point_from_quick_compiled_code, size_t pointer_size) {
    489     SetNativePointer(EntryPointFromQuickCompiledCodeOffset(pointer_size),
    490                      entry_point_from_quick_compiled_code, pointer_size);
    491   }
    492 
    493   void RegisterNative(const void* native_method, bool is_fast)
    494       SHARED_REQUIRES(Locks::mutator_lock_);
    495 
    496   void UnregisterNative() SHARED_REQUIRES(Locks::mutator_lock_);
    497 
    498   static MemberOffset DexCacheResolvedMethodsOffset(size_t pointer_size) {
    499     return MemberOffset(PtrSizedFieldsOffset(pointer_size) + OFFSETOF_MEMBER(
    500         PtrSizedFields, dex_cache_resolved_methods_) / sizeof(void*) * pointer_size);
    501   }
    502 
    503   static MemberOffset DexCacheResolvedTypesOffset(size_t pointer_size) {
    504     return MemberOffset(PtrSizedFieldsOffset(pointer_size) + OFFSETOF_MEMBER(
    505         PtrSizedFields, dex_cache_resolved_types_) / sizeof(void*) * pointer_size);
    506   }
    507 
    508   static MemberOffset EntryPointFromJniOffset(size_t pointer_size) {
    509     return MemberOffset(PtrSizedFieldsOffset(pointer_size) + OFFSETOF_MEMBER(
    510         PtrSizedFields, entry_point_from_jni_) / sizeof(void*) * pointer_size);
    511   }
    512 
    513   static MemberOffset EntryPointFromQuickCompiledCodeOffset(size_t pointer_size) {
    514     return MemberOffset(PtrSizedFieldsOffset(pointer_size) + OFFSETOF_MEMBER(
    515         PtrSizedFields, entry_point_from_quick_compiled_code_) / sizeof(void*) * pointer_size);
    516   }
    517 
    518   ProfilingInfo* GetProfilingInfo(size_t pointer_size) {
    519     return reinterpret_cast<ProfilingInfo*>(GetEntryPointFromJniPtrSize(pointer_size));
    520   }
    521 
    522   ImtConflictTable* GetImtConflictTable(size_t pointer_size) {
    523     DCHECK(IsRuntimeMethod());
    524     return reinterpret_cast<ImtConflictTable*>(GetEntryPointFromJniPtrSize(pointer_size));
    525   }
    526 
    527   ALWAYS_INLINE void SetImtConflictTable(ImtConflictTable* table, size_t pointer_size) {
    528     SetEntryPointFromJniPtrSize(table, pointer_size);
    529   }
    530 
    531   ALWAYS_INLINE void SetProfilingInfo(ProfilingInfo* info) {
    532     SetEntryPointFromJniPtrSize(info, sizeof(void*));
    533   }
    534 
    535   ALWAYS_INLINE void SetProfilingInfoPtrSize(ProfilingInfo* info, size_t pointer_size) {
    536     SetEntryPointFromJniPtrSize(info, pointer_size);
    537   }
    538 
    539   static MemberOffset ProfilingInfoOffset() {
    540     return EntryPointFromJniOffset(sizeof(void*));
    541   }
    542 
    543   void* GetEntryPointFromJni() {
    544     return GetEntryPointFromJniPtrSize(sizeof(void*));
    545   }
    546 
    547   ALWAYS_INLINE void* GetEntryPointFromJniPtrSize(size_t pointer_size) {
    548     return GetNativePointer<void*>(EntryPointFromJniOffset(pointer_size), pointer_size);
    549   }
    550 
    551   void SetEntryPointFromJni(const void* entrypoint) {
    552     DCHECK(IsNative());
    553     SetEntryPointFromJniPtrSize(entrypoint, sizeof(void*));
    554   }
    555 
    556   ALWAYS_INLINE void SetEntryPointFromJniPtrSize(const void* entrypoint, size_t pointer_size) {
    557     SetNativePointer(EntryPointFromJniOffset(pointer_size), entrypoint, pointer_size);
    558   }
    559 
    560   // Is this a CalleSaveMethod or ResolutionMethod and therefore doesn't adhere to normal
    561   // conventions for a method of managed code. Returns false for Proxy methods.
    562   ALWAYS_INLINE bool IsRuntimeMethod();
    563 
    564   // Is this a hand crafted method used for something like describing callee saves?
    565   bool IsCalleeSaveMethod() SHARED_REQUIRES(Locks::mutator_lock_);
    566 
    567   bool IsResolutionMethod() SHARED_REQUIRES(Locks::mutator_lock_);
    568 
    569   bool IsImtUnimplementedMethod() SHARED_REQUIRES(Locks::mutator_lock_);
    570 
    571   MethodReference ToMethodReference() SHARED_REQUIRES(Locks::mutator_lock_) {
    572     return MethodReference(GetDexFile(), GetDexMethodIndex());
    573   }
    574 
    575   // Find the catch block for the given exception type and dex_pc. When a catch block is found,
    576   // indicates whether the found catch block is responsible for clearing the exception or whether
    577   // a move-exception instruction is present.
    578   uint32_t FindCatchBlock(Handle<mirror::Class> exception_type, uint32_t dex_pc,
    579                           bool* has_no_move_exception)
    580       SHARED_REQUIRES(Locks::mutator_lock_);
    581 
    582   // NO_THREAD_SAFETY_ANALYSIS since we don't know what the callback requires.
    583   template<typename RootVisitorType>
    584   void VisitRoots(RootVisitorType& visitor, size_t pointer_size) NO_THREAD_SAFETY_ANALYSIS;
    585 
    586   const DexFile* GetDexFile() SHARED_REQUIRES(Locks::mutator_lock_);
    587 
    588   const char* GetDeclaringClassDescriptor() SHARED_REQUIRES(Locks::mutator_lock_);
    589 
    590   const char* GetShorty() SHARED_REQUIRES(Locks::mutator_lock_) {
    591     uint32_t unused_length;
    592     return GetShorty(&unused_length);
    593   }
    594 
    595   const char* GetShorty(uint32_t* out_length) SHARED_REQUIRES(Locks::mutator_lock_);
    596 
    597   const Signature GetSignature() SHARED_REQUIRES(Locks::mutator_lock_);
    598 
    599   ALWAYS_INLINE const char* GetName() SHARED_REQUIRES(Locks::mutator_lock_);
    600 
    601   mirror::String* GetNameAsString(Thread* self) SHARED_REQUIRES(Locks::mutator_lock_);
    602 
    603   const DexFile::CodeItem* GetCodeItem() SHARED_REQUIRES(Locks::mutator_lock_);
    604 
    605   bool IsResolvedTypeIdx(uint16_t type_idx, size_t ptr_size) SHARED_REQUIRES(Locks::mutator_lock_);
    606 
    607   int32_t GetLineNumFromDexPC(uint32_t dex_pc) SHARED_REQUIRES(Locks::mutator_lock_);
    608 
    609   const DexFile::ProtoId& GetPrototype() SHARED_REQUIRES(Locks::mutator_lock_);
    610 
    611   const DexFile::TypeList* GetParameterTypeList() SHARED_REQUIRES(Locks::mutator_lock_);
    612 
    613   const char* GetDeclaringClassSourceFile() SHARED_REQUIRES(Locks::mutator_lock_);
    614 
    615   uint16_t GetClassDefIndex() SHARED_REQUIRES(Locks::mutator_lock_);
    616 
    617   const DexFile::ClassDef& GetClassDef() SHARED_REQUIRES(Locks::mutator_lock_);
    618 
    619   const char* GetReturnTypeDescriptor() SHARED_REQUIRES(Locks::mutator_lock_);
    620 
    621   const char* GetTypeDescriptorFromTypeIdx(uint16_t type_idx)
    622       SHARED_REQUIRES(Locks::mutator_lock_);
    623 
    624   // May cause thread suspension due to GetClassFromTypeIdx calling ResolveType this caused a large
    625   // number of bugs at call sites.
    626   mirror::Class* GetReturnType(bool resolve, size_t ptr_size)
    627       SHARED_REQUIRES(Locks::mutator_lock_);
    628 
    629   mirror::ClassLoader* GetClassLoader() SHARED_REQUIRES(Locks::mutator_lock_);
    630 
    631   mirror::DexCache* GetDexCache() SHARED_REQUIRES(Locks::mutator_lock_);
    632 
    633   ALWAYS_INLINE ArtMethod* GetInterfaceMethodIfProxy(size_t pointer_size)
    634       SHARED_REQUIRES(Locks::mutator_lock_);
    635 
    636   // May cause thread suspension due to class resolution.
    637   bool EqualParameters(Handle<mirror::ObjectArray<mirror::Class>> params)
    638       SHARED_REQUIRES(Locks::mutator_lock_);
    639 
    640   // Size of an instance of this native class.
    641   static size_t Size(size_t pointer_size) {
    642     return RoundUp(OFFSETOF_MEMBER(ArtMethod, ptr_sized_fields_), pointer_size) +
    643         (sizeof(PtrSizedFields) / sizeof(void*)) * pointer_size;
    644   }
    645 
    646   // Alignment of an instance of this native class.
    647   static size_t Alignment(size_t pointer_size) {
    648     // The ArtMethod alignment is the same as image pointer size. This differs from
    649     // alignof(ArtMethod) if cross-compiling with pointer_size != sizeof(void*).
    650     return pointer_size;
    651   }
    652 
    653   void CopyFrom(ArtMethod* src, size_t image_pointer_size)
    654       SHARED_REQUIRES(Locks::mutator_lock_);
    655 
    656   ALWAYS_INLINE GcRoot<mirror::Class>* GetDexCacheResolvedTypes(size_t pointer_size)
    657       SHARED_REQUIRES(Locks::mutator_lock_);
    658 
    659   // Note, hotness_counter_ updates are non-atomic but it doesn't need to be precise.  Also,
    660   // given that the counter is only 16 bits wide we can expect wrap-around in some
    661   // situations.  Consumers of hotness_count_ must be able to deal with that.
    662   uint16_t IncrementCounter() {
    663     return ++hotness_count_;
    664   }
    665 
    666   void ClearCounter() {
    667     hotness_count_ = 0;
    668   }
    669 
    670   void SetCounter(int16_t hotness_count) {
    671     hotness_count_ = hotness_count;
    672   }
    673 
    674   uint16_t GetCounter() const {
    675     return hotness_count_;
    676   }
    677 
    678   const uint8_t* GetQuickenedInfo() SHARED_REQUIRES(Locks::mutator_lock_);
    679 
    680   // Returns the method header for the compiled code containing 'pc'. Note that runtime
    681   // methods will return null for this method, as they are not oat based.
    682   const OatQuickMethodHeader* GetOatQuickMethodHeader(uintptr_t pc)
    683       SHARED_REQUIRES(Locks::mutator_lock_);
    684 
    685   // Returns whether the method has any compiled code, JIT or AOT.
    686   bool HasAnyCompiledCode() SHARED_REQUIRES(Locks::mutator_lock_);
    687 
    688 
    689   // Update heap objects and non-entrypoint pointers by the passed in visitor for image relocation.
    690   // Does not use read barrier.
    691   template <typename Visitor>
    692   ALWAYS_INLINE void UpdateObjectsForImageRelocation(const Visitor& visitor, size_t pointer_size)
    693       SHARED_REQUIRES(Locks::mutator_lock_);
    694 
    695   // Update entry points by passing them through the visitor.
    696   template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename Visitor>
    697   ALWAYS_INLINE void UpdateEntrypoints(const Visitor& visitor, size_t pointer_size);
    698 
    699  protected:
    700   // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
    701   // The class we are a part of.
    702   GcRoot<mirror::Class> declaring_class_;
    703 
    704   // Access flags; low 16 bits are defined by spec.
    705   uint32_t access_flags_;
    706 
    707   /* Dex file fields. The defining dex file is available via declaring_class_->dex_cache_ */
    708 
    709   // Offset to the CodeItem.
    710   uint32_t dex_code_item_offset_;
    711 
    712   // Index into method_ids of the dex file associated with this method.
    713   uint32_t dex_method_index_;
    714 
    715   /* End of dex file fields. */
    716 
    717   // Entry within a dispatch table for this method. For static/direct methods the index is into
    718   // the declaringClass.directMethods, for virtual methods the vtable and for interface methods the
    719   // ifTable.
    720   uint16_t method_index_;
    721 
    722   // The hotness we measure for this method. Managed by the interpreter. Not atomic, as we allow
    723   // missing increments: if the method is hot, we will see it eventually.
    724   uint16_t hotness_count_;
    725 
    726   // Fake padding field gets inserted here.
    727 
    728   // Must be the last fields in the method.
    729   // PACKED(4) is necessary for the correctness of
    730   // RoundUp(OFFSETOF_MEMBER(ArtMethod, ptr_sized_fields_), pointer_size).
    731   struct PACKED(4) PtrSizedFields {
    732     // Short cuts to declaring_class_->dex_cache_ member for fast compiled code access.
    733     ArtMethod** dex_cache_resolved_methods_;
    734 
    735     // Short cuts to declaring_class_->dex_cache_ member for fast compiled code access.
    736     GcRoot<mirror::Class>* dex_cache_resolved_types_;
    737 
    738     // Pointer to JNI function registered to this method, or a function to resolve the JNI function,
    739     // or the profiling data for non-native methods, or an ImtConflictTable.
    740     void* entry_point_from_jni_;
    741 
    742     // Method dispatch from quick compiled code invokes this pointer which may cause bridging into
    743     // the interpreter.
    744     void* entry_point_from_quick_compiled_code_;
    745   } ptr_sized_fields_;
    746 
    747  private:
    748   static size_t PtrSizedFieldsOffset(size_t pointer_size) {
    749     // Round up to pointer size for padding field.
    750     return RoundUp(OFFSETOF_MEMBER(ArtMethod, ptr_sized_fields_), pointer_size);
    751   }
    752 
    753   template<typename T>
    754   ALWAYS_INLINE T GetNativePointer(MemberOffset offset, size_t pointer_size) const {
    755     static_assert(std::is_pointer<T>::value, "T must be a pointer type");
    756     DCHECK(ValidPointerSize(pointer_size)) << pointer_size;
    757     const auto addr = reinterpret_cast<uintptr_t>(this) + offset.Uint32Value();
    758     if (pointer_size == sizeof(uint32_t)) {
    759       return reinterpret_cast<T>(*reinterpret_cast<const uint32_t*>(addr));
    760     } else {
    761       auto v = *reinterpret_cast<const uint64_t*>(addr);
    762       return reinterpret_cast<T>(dchecked_integral_cast<uintptr_t>(v));
    763     }
    764   }
    765 
    766   template<typename T>
    767   ALWAYS_INLINE void SetNativePointer(MemberOffset offset, T new_value, size_t pointer_size) {
    768     static_assert(std::is_pointer<T>::value, "T must be a pointer type");
    769     DCHECK(ValidPointerSize(pointer_size)) << pointer_size;
    770     const auto addr = reinterpret_cast<uintptr_t>(this) + offset.Uint32Value();
    771     if (pointer_size == sizeof(uint32_t)) {
    772       uintptr_t ptr = reinterpret_cast<uintptr_t>(new_value);
    773       *reinterpret_cast<uint32_t*>(addr) = dchecked_integral_cast<uint32_t>(ptr);
    774     } else {
    775       *reinterpret_cast<uint64_t*>(addr) = reinterpret_cast<uintptr_t>(new_value);
    776     }
    777   }
    778 
    779   DISALLOW_COPY_AND_ASSIGN(ArtMethod);  // Need to use CopyFrom to deal with 32 vs 64 bits.
    780 };
    781 
    782 }  // namespace art
    783 
    784 #endif  // ART_RUNTIME_ART_METHOD_H_
    785