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 "dex_file.h"
     21 #include "gc_root.h"
     22 #include "invoke_type.h"
     23 #include "method_reference.h"
     24 #include "modifiers.h"
     25 #include "mirror/object.h"
     26 #include "object_callbacks.h"
     27 #include "quick/quick_method_frame_info.h"
     28 #include "read_barrier_option.h"
     29 #include "stack.h"
     30 #include "stack_map.h"
     31 #include "utils.h"
     32 
     33 namespace art {
     34 
     35 union JValue;
     36 class ScopedObjectAccessAlreadyRunnable;
     37 class StringPiece;
     38 class ShadowFrame;
     39 
     40 namespace mirror {
     41 class Array;
     42 class Class;
     43 class PointerArray;
     44 }  // namespace mirror
     45 
     46 typedef void (EntryPointFromInterpreter)(Thread* self, const DexFile::CodeItem* code_item,
     47                                          ShadowFrame* shadow_frame, JValue* result);
     48 
     49 class ArtMethod FINAL {
     50  public:
     51   ArtMethod() : access_flags_(0), dex_code_item_offset_(0), dex_method_index_(0),
     52       method_index_(0) { }
     53 
     54   ArtMethod(const ArtMethod& src, size_t image_pointer_size) {
     55     CopyFrom(&src, image_pointer_size);
     56   }
     57 
     58   static ArtMethod* FromReflectedMethod(const ScopedObjectAccessAlreadyRunnable& soa,
     59                                         jobject jlr_method)
     60       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     61 
     62   ALWAYS_INLINE mirror::Class* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     63 
     64   ALWAYS_INLINE mirror::Class* GetDeclaringClassNoBarrier()
     65       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     66 
     67   ALWAYS_INLINE mirror::Class* GetDeclaringClassUnchecked()
     68       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     69 
     70   void SetDeclaringClass(mirror::Class *new_declaring_class)
     71       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     72 
     73   static MemberOffset DeclaringClassOffset() {
     74     return MemberOffset(OFFSETOF_MEMBER(ArtMethod, declaring_class_));
     75   }
     76 
     77   ALWAYS_INLINE uint32_t GetAccessFlags() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     78 
     79   void SetAccessFlags(uint32_t new_access_flags) {
     80     // Not called within a transaction.
     81     access_flags_ = new_access_flags;
     82   }
     83 
     84   // Approximate what kind of method call would be used for this method.
     85   InvokeType GetInvokeType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     86 
     87   // Returns true if the method is declared public.
     88   bool IsPublic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     89     return (GetAccessFlags() & kAccPublic) != 0;
     90   }
     91 
     92   // Returns true if the method is declared private.
     93   bool IsPrivate() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     94     return (GetAccessFlags() & kAccPrivate) != 0;
     95   }
     96 
     97   // Returns true if the method is declared static.
     98   bool IsStatic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     99     return (GetAccessFlags() & kAccStatic) != 0;
    100   }
    101 
    102   // Returns true if the method is a constructor.
    103   bool IsConstructor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    104     return (GetAccessFlags() & kAccConstructor) != 0;
    105   }
    106 
    107   // Returns true if the method is a class initializer.
    108   bool IsClassInitializer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    109     return IsConstructor() && IsStatic();
    110   }
    111 
    112   // Returns true if the method is static, private, or a constructor.
    113   bool IsDirect() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    114     return IsDirect(GetAccessFlags());
    115   }
    116 
    117   static bool IsDirect(uint32_t access_flags) {
    118     return (access_flags & (kAccStatic | kAccPrivate | kAccConstructor)) != 0;
    119   }
    120 
    121   // Returns true if the method is declared synchronized.
    122   bool IsSynchronized() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    123     uint32_t synchonized = kAccSynchronized | kAccDeclaredSynchronized;
    124     return (GetAccessFlags() & synchonized) != 0;
    125   }
    126 
    127   bool IsFinal() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    128     return (GetAccessFlags() & kAccFinal) != 0;
    129   }
    130 
    131   bool IsMiranda() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    132     return (GetAccessFlags() & kAccMiranda) != 0;
    133   }
    134 
    135   bool IsNative() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    136     return (GetAccessFlags() & kAccNative) != 0;
    137   }
    138 
    139   bool ShouldNotInline() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    140     return (GetAccessFlags() & kAccDontInline) != 0;
    141   }
    142 
    143   void SetShouldNotInline() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    144     SetAccessFlags(GetAccessFlags() | kAccDontInline);
    145   }
    146 
    147   bool IsFastNative() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    148     uint32_t mask = kAccFastNative | kAccNative;
    149     return (GetAccessFlags() & mask) == mask;
    150   }
    151 
    152   bool IsAbstract() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    153     return (GetAccessFlags() & kAccAbstract) != 0;
    154   }
    155 
    156   bool IsSynthetic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    157     return (GetAccessFlags() & kAccSynthetic) != 0;
    158   }
    159 
    160   bool IsProxyMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    161 
    162   bool IsPreverified() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    163     return (GetAccessFlags() & kAccPreverified) != 0;
    164   }
    165 
    166   void SetPreverified() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    167     DCHECK(!IsPreverified());
    168     SetAccessFlags(GetAccessFlags() | kAccPreverified);
    169   }
    170 
    171   bool IsOptimized(size_t pointer_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    172     // Temporary solution for detecting if a method has been optimized: the compiler
    173     // does not create a GC map. Instead, the vmap table contains the stack map
    174     // (as in stack_map.h).
    175     return !IsNative()
    176         && GetEntryPointFromQuickCompiledCodePtrSize(pointer_size) != nullptr
    177         && GetQuickOatCodePointer(pointer_size) != nullptr
    178         && GetNativeGcMap(pointer_size) == nullptr;
    179   }
    180 
    181   bool CheckIncompatibleClassChange(InvokeType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    182 
    183   uint16_t GetMethodIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    184 
    185   // Doesn't do erroneous / unresolved class checks.
    186   uint16_t GetMethodIndexDuringLinking() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    187 
    188   size_t GetVtableIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    189     return GetMethodIndex();
    190   }
    191 
    192   void SetMethodIndex(uint16_t new_method_index) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    193     // Not called within a transaction.
    194     method_index_ = new_method_index;
    195   }
    196 
    197   static MemberOffset DexMethodIndexOffset() {
    198     return OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_method_index_);
    199   }
    200 
    201   static MemberOffset MethodIndexOffset() {
    202     return OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_);
    203   }
    204 
    205   uint32_t GetCodeItemOffset() {
    206     return dex_code_item_offset_;
    207   }
    208 
    209   void SetCodeItemOffset(uint32_t new_code_off) {
    210     // Not called within a transaction.
    211     dex_code_item_offset_ = new_code_off;
    212   }
    213 
    214   // Number of 32bit registers that would be required to hold all the arguments
    215   static size_t NumArgRegisters(const StringPiece& shorty);
    216 
    217   ALWAYS_INLINE uint32_t GetDexMethodIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    218 
    219   void SetDexMethodIndex(uint32_t new_idx) {
    220     // Not called within a transaction.
    221     dex_method_index_ = new_idx;
    222   }
    223 
    224   static MemberOffset DexCacheResolvedMethodsOffset() {
    225     return OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_methods_);
    226   }
    227 
    228   static MemberOffset DexCacheResolvedTypesOffset() {
    229     return OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_types_);
    230   }
    231 
    232   ALWAYS_INLINE mirror::PointerArray* GetDexCacheResolvedMethods()
    233       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    234   ALWAYS_INLINE ArtMethod* GetDexCacheResolvedMethod(uint16_t method_idx, size_t ptr_size)
    235       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    236   ALWAYS_INLINE void SetDexCacheResolvedMethod(uint16_t method_idx, ArtMethod* new_method,
    237                                                size_t ptr_size)
    238       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    239   ALWAYS_INLINE void SetDexCacheResolvedMethods(mirror::PointerArray* new_dex_cache_methods)
    240       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    241   bool HasDexCacheResolvedMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    242   bool HasSameDexCacheResolvedMethods(ArtMethod* other)
    243       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    244   bool HasSameDexCacheResolvedMethods(mirror::PointerArray* other_cache)
    245       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    246 
    247   template <bool kWithCheck = true>
    248   mirror::Class* GetDexCacheResolvedType(uint32_t type_idx)
    249       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    250   void SetDexCacheResolvedTypes(mirror::ObjectArray<mirror::Class>* new_dex_cache_types)
    251       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    252   bool HasDexCacheResolvedTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    253   bool HasSameDexCacheResolvedTypes(ArtMethod* other) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    254   bool HasSameDexCacheResolvedTypes(mirror::ObjectArray<mirror::Class>* other_cache)
    255       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    256 
    257   // Get the Class* from the type index into this method's dex cache.
    258   mirror::Class* GetClassFromTypeIndex(uint16_t type_idx, bool resolve)
    259       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    260 
    261   // Find the method that this method overrides.
    262   ArtMethod* FindOverriddenMethod(size_t pointer_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    263 
    264   // Find the method index for this method within other_dexfile. If this method isn't present then
    265   // return DexFile::kDexNoIndex. The name_and_signature_idx MUST refer to a MethodId with the same
    266   // name and signature in the other_dexfile, such as the method index used to resolve this method
    267   // in the other_dexfile.
    268   uint32_t FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile,
    269                                             uint32_t name_and_signature_idx)
    270       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    271 
    272   void Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result, const char* shorty)
    273       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    274 
    275   EntryPointFromInterpreter* GetEntryPointFromInterpreter() {
    276     return GetEntryPointFromInterpreterPtrSize(sizeof(void*));
    277   }
    278   EntryPointFromInterpreter* GetEntryPointFromInterpreterPtrSize(size_t pointer_size) {
    279     return GetEntryPoint<EntryPointFromInterpreter*>(
    280         EntryPointFromInterpreterOffset(pointer_size), pointer_size);
    281   }
    282 
    283   void SetEntryPointFromInterpreter(EntryPointFromInterpreter* entry_point_from_interpreter) {
    284     SetEntryPointFromInterpreterPtrSize(entry_point_from_interpreter, sizeof(void*));
    285   }
    286   void SetEntryPointFromInterpreterPtrSize(EntryPointFromInterpreter* entry_point_from_interpreter,
    287                                            size_t pointer_size) {
    288     SetEntryPoint(EntryPointFromInterpreterOffset(pointer_size), entry_point_from_interpreter,
    289                   pointer_size);
    290   }
    291 
    292   const void* GetEntryPointFromQuickCompiledCode() {
    293     return GetEntryPointFromQuickCompiledCodePtrSize(sizeof(void*));
    294   }
    295   ALWAYS_INLINE const void* GetEntryPointFromQuickCompiledCodePtrSize(size_t pointer_size) {
    296     return GetEntryPoint<const void*>(
    297         EntryPointFromQuickCompiledCodeOffset(pointer_size), pointer_size);
    298   }
    299 
    300   void SetEntryPointFromQuickCompiledCode(const void* entry_point_from_quick_compiled_code) {
    301     SetEntryPointFromQuickCompiledCodePtrSize(entry_point_from_quick_compiled_code,
    302                                               sizeof(void*));
    303   }
    304   ALWAYS_INLINE void SetEntryPointFromQuickCompiledCodePtrSize(
    305       const void* entry_point_from_quick_compiled_code, size_t pointer_size) {
    306     SetEntryPoint(EntryPointFromQuickCompiledCodeOffset(pointer_size),
    307                   entry_point_from_quick_compiled_code, pointer_size);
    308   }
    309 
    310   uint32_t GetCodeSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    311 
    312   // Check whether the given PC is within the quick compiled code associated with this method's
    313   // quick entrypoint. This code isn't robust for instrumentation, etc. and is only used for
    314   // debug purposes.
    315   bool PcIsWithinQuickCode(uintptr_t pc) {
    316     return PcIsWithinQuickCode(
    317         reinterpret_cast<uintptr_t>(GetEntryPointFromQuickCompiledCode()), pc);
    318   }
    319 
    320   void AssertPcIsWithinQuickCode(uintptr_t pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    321 
    322   // Returns true if the entrypoint points to the interpreter, as
    323   // opposed to the compiled code, that is, this method will be
    324   // interpretered on invocation.
    325   bool IsEntrypointInterpreter() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    326 
    327   uint32_t GetQuickOatCodeOffset();
    328   void SetQuickOatCodeOffset(uint32_t code_offset);
    329 
    330   ALWAYS_INLINE static const void* EntryPointToCodePointer(const void* entry_point) {
    331     uintptr_t code = reinterpret_cast<uintptr_t>(entry_point);
    332     // TODO: Make this Thumb2 specific. It is benign on other architectures as code is always at
    333     //       least 2 byte aligned.
    334     code &= ~0x1;
    335     return reinterpret_cast<const void*>(code);
    336   }
    337 
    338   // Actual entry point pointer to compiled oat code or null.
    339   const void* GetQuickOatEntryPoint(size_t pointer_size)
    340       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    341   // Actual pointer to compiled oat code or null.
    342   const void* GetQuickOatCodePointer(size_t pointer_size)
    343       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    344     return EntryPointToCodePointer(GetQuickOatEntryPoint(pointer_size));
    345   }
    346 
    347   // Callers should wrap the uint8_t* in a MappingTable instance for convenient access.
    348   const uint8_t* GetMappingTable(size_t pointer_size)
    349       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    350   const uint8_t* GetMappingTable(const void* code_pointer, size_t pointer_size)
    351       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    352 
    353   // Callers should wrap the uint8_t* in a VmapTable instance for convenient access.
    354   const uint8_t* GetVmapTable(size_t pointer_size)
    355       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    356   const uint8_t* GetVmapTable(const void* code_pointer, size_t pointer_size)
    357       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    358 
    359   CodeInfo GetOptimizedCodeInfo() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    360 
    361   // Callers should wrap the uint8_t* in a GcMap instance for convenient access.
    362   const uint8_t* GetNativeGcMap(size_t pointer_size)
    363       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    364   const uint8_t* GetNativeGcMap(const void* code_pointer, size_t pointer_size)
    365       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    366 
    367   template <bool kCheckFrameSize = true>
    368   uint32_t GetFrameSizeInBytes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    369     uint32_t result = GetQuickFrameInfo().FrameSizeInBytes();
    370     if (kCheckFrameSize) {
    371       DCHECK_LE(static_cast<size_t>(kStackAlignment), result);
    372     }
    373     return result;
    374   }
    375 
    376   QuickMethodFrameInfo GetQuickFrameInfo() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    377   QuickMethodFrameInfo GetQuickFrameInfo(const void* code_pointer)
    378       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    379 
    380   FrameOffset GetReturnPcOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    381     return GetReturnPcOffset(GetFrameSizeInBytes());
    382   }
    383 
    384   FrameOffset GetReturnPcOffset(uint32_t frame_size_in_bytes)
    385       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    386     DCHECK_EQ(frame_size_in_bytes, GetFrameSizeInBytes());
    387     return FrameOffset(frame_size_in_bytes - sizeof(void*));
    388   }
    389 
    390   FrameOffset GetHandleScopeOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    391     constexpr size_t handle_scope_offset = sizeof(ArtMethod*);
    392     DCHECK_LT(handle_scope_offset, GetFrameSizeInBytes());
    393     return FrameOffset(handle_scope_offset);
    394   }
    395 
    396   void RegisterNative(const void* native_method, bool is_fast)
    397       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    398 
    399   void UnregisterNative() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    400 
    401   static MemberOffset EntryPointFromInterpreterOffset(size_t pointer_size) {
    402     return MemberOffset(PtrSizedFieldsOffset(pointer_size) + OFFSETOF_MEMBER(
    403         PtrSizedFields, entry_point_from_interpreter_) / sizeof(void*) * pointer_size);
    404   }
    405 
    406   static MemberOffset EntryPointFromJniOffset(size_t pointer_size) {
    407     return MemberOffset(PtrSizedFieldsOffset(pointer_size) + OFFSETOF_MEMBER(
    408         PtrSizedFields, entry_point_from_jni_) / sizeof(void*) * pointer_size);
    409   }
    410 
    411   static MemberOffset EntryPointFromQuickCompiledCodeOffset(size_t pointer_size) {
    412     return MemberOffset(PtrSizedFieldsOffset(pointer_size) + OFFSETOF_MEMBER(
    413         PtrSizedFields, entry_point_from_quick_compiled_code_) / sizeof(void*) * pointer_size);
    414   }
    415 
    416   void* GetEntryPointFromJni() {
    417     return GetEntryPointFromJniPtrSize(sizeof(void*));
    418   }
    419   ALWAYS_INLINE void* GetEntryPointFromJniPtrSize(size_t pointer_size) {
    420     return GetEntryPoint<void*>(EntryPointFromJniOffset(pointer_size), pointer_size);
    421   }
    422 
    423   void SetEntryPointFromJni(const void* entrypoint) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    424     SetEntryPointFromJniPtrSize(entrypoint, sizeof(void*));
    425   }
    426   ALWAYS_INLINE void SetEntryPointFromJniPtrSize(const void* entrypoint, size_t pointer_size) {
    427     SetEntryPoint(EntryPointFromJniOffset(pointer_size), entrypoint, pointer_size);
    428   }
    429 
    430   // Is this a CalleSaveMethod or ResolutionMethod and therefore doesn't adhere to normal
    431   // conventions for a method of managed code. Returns false for Proxy methods.
    432   ALWAYS_INLINE bool IsRuntimeMethod();
    433 
    434   // Is this a hand crafted method used for something like describing callee saves?
    435   bool IsCalleeSaveMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    436 
    437   bool IsResolutionMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    438 
    439   bool IsImtConflictMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    440 
    441   bool IsImtUnimplementedMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    442 
    443   uintptr_t NativeQuickPcOffset(const uintptr_t pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    444 #ifdef NDEBUG
    445   uintptr_t NativeQuickPcOffset(const uintptr_t pc, const void* quick_entry_point)
    446       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    447     return pc - reinterpret_cast<uintptr_t>(quick_entry_point);
    448   }
    449 #else
    450   uintptr_t NativeQuickPcOffset(const uintptr_t pc, const void* quick_entry_point)
    451       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    452 #endif
    453 
    454   // Converts a native PC to a dex PC.
    455   uint32_t ToDexPc(const uintptr_t pc, bool abort_on_failure = true)
    456       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    457 
    458   // Converts a dex PC to a native PC.
    459   uintptr_t ToNativeQuickPc(const uint32_t dex_pc, bool abort_on_failure = true)
    460       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    461 
    462   MethodReference ToMethodReference() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    463     return MethodReference(GetDexFile(), GetDexMethodIndex());
    464   }
    465 
    466   // Find the catch block for the given exception type and dex_pc. When a catch block is found,
    467   // indicates whether the found catch block is responsible for clearing the exception or whether
    468   // a move-exception instruction is present.
    469   uint32_t FindCatchBlock(Handle<mirror::Class> exception_type, uint32_t dex_pc,
    470                           bool* has_no_move_exception)
    471       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    472 
    473   template<typename RootVisitorType>
    474   void VisitRoots(RootVisitorType& visitor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    475 
    476   const DexFile* GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    477 
    478   const char* GetDeclaringClassDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    479 
    480   const char* GetShorty() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    481     uint32_t unused_length;
    482     return GetShorty(&unused_length);
    483   }
    484 
    485   const char* GetShorty(uint32_t* out_length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    486 
    487   const Signature GetSignature() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    488 
    489   ALWAYS_INLINE const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    490 
    491   mirror::String* GetNameAsString(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    492 
    493   const DexFile::CodeItem* GetCodeItem() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    494 
    495   bool IsResolvedTypeIdx(uint16_t type_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    496 
    497   int32_t GetLineNumFromDexPC(uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    498 
    499   const DexFile::ProtoId& GetPrototype() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    500 
    501   const DexFile::TypeList* GetParameterTypeList() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    502 
    503   const char* GetDeclaringClassSourceFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    504 
    505   uint16_t GetClassDefIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    506 
    507   const DexFile::ClassDef& GetClassDef() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    508 
    509   const char* GetReturnTypeDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    510 
    511   const char* GetTypeDescriptorFromTypeIdx(uint16_t type_idx)
    512       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    513 
    514   // May cause thread suspension due to GetClassFromTypeIdx calling ResolveType this caused a large
    515   // number of bugs at call sites.
    516   mirror::Class* GetReturnType(bool resolve = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    517 
    518   mirror::ClassLoader* GetClassLoader() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    519 
    520   mirror::DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    521 
    522   ALWAYS_INLINE ArtMethod* GetInterfaceMethodIfProxy(size_t pointer_size)
    523       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    524 
    525   // May cause thread suspension due to class resolution.
    526   bool EqualParameters(Handle<mirror::ObjectArray<mirror::Class>> params)
    527       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    528 
    529   // Size of an instance of this object.
    530   static size_t ObjectSize(size_t pointer_size) {
    531     return RoundUp(OFFSETOF_MEMBER(ArtMethod, ptr_sized_fields_), pointer_size) +
    532         (sizeof(PtrSizedFields) / sizeof(void*)) * pointer_size;
    533   }
    534 
    535   void CopyFrom(const ArtMethod* src, size_t image_pointer_size)
    536       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    537 
    538   ALWAYS_INLINE mirror::ObjectArray<mirror::Class>* GetDexCacheResolvedTypes()
    539       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    540 
    541  protected:
    542   // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
    543   // The class we are a part of.
    544   GcRoot<mirror::Class> declaring_class_;
    545 
    546   // Short cuts to declaring_class_->dex_cache_ member for fast compiled code access.
    547   GcRoot<mirror::PointerArray> dex_cache_resolved_methods_;
    548 
    549   // Short cuts to declaring_class_->dex_cache_ member for fast compiled code access.
    550   GcRoot<mirror::ObjectArray<mirror::Class>> dex_cache_resolved_types_;
    551 
    552   // Access flags; low 16 bits are defined by spec.
    553   uint32_t access_flags_;
    554 
    555   /* Dex file fields. The defining dex file is available via declaring_class_->dex_cache_ */
    556 
    557   // Offset to the CodeItem.
    558   uint32_t dex_code_item_offset_;
    559 
    560   // Index into method_ids of the dex file associated with this method.
    561   uint32_t dex_method_index_;
    562 
    563   /* End of dex file fields. */
    564 
    565   // Entry within a dispatch table for this method. For static/direct methods the index is into
    566   // the declaringClass.directMethods, for virtual methods the vtable and for interface methods the
    567   // ifTable.
    568   uint32_t method_index_;
    569 
    570   // Fake padding field gets inserted here.
    571 
    572   // Must be the last fields in the method.
    573   // PACKED(4) is necessary for the correctness of
    574   // RoundUp(OFFSETOF_MEMBER(ArtMethod, ptr_sized_fields_), pointer_size).
    575   struct PACKED(4) PtrSizedFields {
    576     // Method dispatch from the interpreter invokes this pointer which may cause a bridge into
    577     // compiled code.
    578     void* entry_point_from_interpreter_;
    579 
    580     // Pointer to JNI function registered to this method, or a function to resolve the JNI function.
    581     void* entry_point_from_jni_;
    582 
    583     // Method dispatch from quick compiled code invokes this pointer which may cause bridging into
    584     // the interpreter.
    585     void* entry_point_from_quick_compiled_code_;
    586   } ptr_sized_fields_;
    587 
    588  private:
    589   static size_t PtrSizedFieldsOffset(size_t pointer_size) {
    590     // Round up to pointer size for padding field.
    591     return RoundUp(OFFSETOF_MEMBER(ArtMethod, ptr_sized_fields_), pointer_size);
    592   }
    593 
    594   template<typename T>
    595   ALWAYS_INLINE T GetEntryPoint(MemberOffset offset, size_t pointer_size) const {
    596     DCHECK(ValidPointerSize(pointer_size)) << pointer_size;
    597     const auto addr = reinterpret_cast<uintptr_t>(this) + offset.Uint32Value();
    598     if (pointer_size == sizeof(uint32_t)) {
    599       return reinterpret_cast<T>(*reinterpret_cast<const uint32_t*>(addr));
    600     } else {
    601       auto v = *reinterpret_cast<const uint64_t*>(addr);
    602       DCHECK_EQ(reinterpret_cast<uint64_t>(reinterpret_cast<T>(v)), v) << "Conversion lost bits";
    603       return reinterpret_cast<T>(v);
    604     }
    605   }
    606 
    607   template<typename T>
    608   ALWAYS_INLINE void SetEntryPoint(MemberOffset offset, T new_value, size_t pointer_size) {
    609     DCHECK(ValidPointerSize(pointer_size)) << pointer_size;
    610     const auto addr = reinterpret_cast<uintptr_t>(this) + offset.Uint32Value();
    611     if (pointer_size == sizeof(uint32_t)) {
    612       uintptr_t ptr = reinterpret_cast<uintptr_t>(new_value);
    613       DCHECK_EQ(static_cast<uint32_t>(ptr), ptr) << "Conversion lost bits";
    614       *reinterpret_cast<uint32_t*>(addr) = static_cast<uint32_t>(ptr);
    615     } else {
    616       *reinterpret_cast<uint64_t*>(addr) = reinterpret_cast<uintptr_t>(new_value);
    617     }
    618   }
    619 
    620   // Code points to the start of the quick code.
    621   static uint32_t GetCodeSize(const void* code);
    622 
    623   static bool PcIsWithinQuickCode(uintptr_t code, uintptr_t pc) {
    624     if (code == 0) {
    625       return pc == 0;
    626     }
    627     /*
    628      * During a stack walk, a return PC may point past-the-end of the code
    629      * in the case that the last instruction is a call that isn't expected to
    630      * return.  Thus, we check <= code + GetCodeSize().
    631      *
    632      * NOTE: For Thumb both pc and code are offset by 1 indicating the Thumb state.
    633      */
    634     return code <= pc && pc <= code + GetCodeSize(
    635         EntryPointToCodePointer(reinterpret_cast<const void*>(code)));
    636   }
    637 
    638   DISALLOW_COPY_AND_ASSIGN(ArtMethod);  // Need to use CopyFrom to deal with 32 vs 64 bits.
    639 };
    640 
    641 }  // namespace art
    642 
    643 #endif  // ART_RUNTIME_ART_METHOD_H_
    644