art_method.h revision 7ead0c009c64f1e10aa39e44ea10383dd859d332
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
32namespace art {
33
34union JValue;
35class OatQuickMethodHeader;
36class ProfilingInfo;
37class ScopedObjectAccessAlreadyRunnable;
38class StringPiece;
39class ShadowFrame;
40
41namespace mirror {
42class Array;
43class Class;
44class PointerArray;
45}  // namespace mirror
46
47class ArtMethod FINAL {
48 public:
49  ArtMethod() : access_flags_(0), dex_code_item_offset_(0), dex_method_index_(0),
50      method_index_(0) { }
51
52  ArtMethod(ArtMethod* src, size_t image_pointer_size) {
53    CopyFrom(src, image_pointer_size);
54  }
55
56  static ArtMethod* FromReflectedMethod(const ScopedObjectAccessAlreadyRunnable& soa,
57                                        jobject jlr_method)
58      SHARED_REQUIRES(Locks::mutator_lock_);
59
60  template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
61  ALWAYS_INLINE mirror::Class* GetDeclaringClass() SHARED_REQUIRES(Locks::mutator_lock_);
62
63  template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
64  ALWAYS_INLINE mirror::Class* GetDeclaringClassUnchecked()
65      SHARED_REQUIRES(Locks::mutator_lock_);
66
67  void SetDeclaringClass(mirror::Class *new_declaring_class)
68      SHARED_REQUIRES(Locks::mutator_lock_);
69
70  bool CASDeclaringClass(mirror::Class* expected_class, mirror::Class* desired_class)
71      SHARED_REQUIRES(Locks::mutator_lock_);
72
73  static MemberOffset DeclaringClassOffset() {
74    return MemberOffset(OFFSETOF_MEMBER(ArtMethod, declaring_class_));
75  }
76
77  // Note: GetAccessFlags acquires the mutator lock in debug mode to check that it is not called for
78  // a proxy method.
79  template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
80  ALWAYS_INLINE uint32_t GetAccessFlags();
81
82  void SetAccessFlags(uint32_t new_access_flags) {
83    // Not called within a transaction.
84    access_flags_ = new_access_flags;
85  }
86
87  // Approximate what kind of method call would be used for this method.
88  InvokeType GetInvokeType() SHARED_REQUIRES(Locks::mutator_lock_);
89
90  // Returns true if the method is declared public.
91  bool IsPublic() {
92    return (GetAccessFlags() & kAccPublic) != 0;
93  }
94
95  // Returns true if the method is declared private.
96  bool IsPrivate() {
97    return (GetAccessFlags() & kAccPrivate) != 0;
98  }
99
100  // Returns true if the method is declared static.
101  bool IsStatic() {
102    return (GetAccessFlags() & kAccStatic) != 0;
103  }
104
105  // Returns true if the method is a constructor.
106  bool IsConstructor() {
107    return (GetAccessFlags() & kAccConstructor) != 0;
108  }
109
110  // Returns true if the method is a class initializer.
111  bool IsClassInitializer() {
112    return IsConstructor() && IsStatic();
113  }
114
115  // Returns true if the method is static, private, or a constructor.
116  bool IsDirect() {
117    return IsDirect(GetAccessFlags());
118  }
119
120  static bool IsDirect(uint32_t access_flags) {
121    constexpr uint32_t direct = kAccStatic | kAccPrivate | kAccConstructor;
122    return (access_flags & direct) != 0;
123  }
124
125  // Returns true if the method is declared synchronized.
126  bool IsSynchronized() {
127    constexpr uint32_t synchonized = kAccSynchronized | kAccDeclaredSynchronized;
128    return (GetAccessFlags() & synchonized) != 0;
129  }
130
131  bool IsFinal() {
132    return (GetAccessFlags() & kAccFinal) != 0;
133  }
134
135  bool IsCopied() {
136    const bool copied = (GetAccessFlags() & kAccCopied) != 0;
137    // (IsMiranda() || IsDefaultConflicting()) implies copied
138    DCHECK(!(IsMiranda() || IsDefaultConflicting()) || copied)
139        << "Miranda or default-conflict methods must always be copied.";
140    return copied;
141  }
142
143  bool IsMiranda() {
144    return (GetAccessFlags() & kAccMiranda) != 0;
145  }
146
147  // Returns true if invoking this method will not throw an AbstractMethodError or
148  // IncompatibleClassChangeError.
149  bool IsInvokable() {
150    return !IsAbstract() && !IsDefaultConflicting();
151  }
152
153  // A default conflict method is a special sentinel method that stands for a conflict between
154  // multiple default methods. It cannot be invoked, throwing an IncompatibleClassChangeError if one
155  // attempts to do so.
156  bool IsDefaultConflicting() {
157    return (GetAccessFlags() & kAccDefaultConflict) != 0u;
158  }
159
160  // This is set by the class linker.
161  bool IsDefault() {
162    return (GetAccessFlags() & kAccDefault) != 0;
163  }
164
165  template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
166  bool IsNative() {
167    return (GetAccessFlags<kReadBarrierOption>() & kAccNative) != 0;
168  }
169
170  bool IsFastNative() {
171    constexpr uint32_t mask = kAccFastNative | kAccNative;
172    return (GetAccessFlags() & mask) == mask;
173  }
174
175  bool IsAbstract() {
176    return (GetAccessFlags() & kAccAbstract) != 0;
177  }
178
179  bool IsSynthetic() {
180    return (GetAccessFlags() & kAccSynthetic) != 0;
181  }
182
183  bool IsProxyMethod() SHARED_REQUIRES(Locks::mutator_lock_);
184
185  bool SkipAccessChecks() {
186    return (GetAccessFlags() & kAccSkipAccessChecks) != 0;
187  }
188
189  void SetSkipAccessChecks() {
190    DCHECK(!SkipAccessChecks());
191    SetAccessFlags(GetAccessFlags() | kAccSkipAccessChecks);
192  }
193
194  // Returns true if this method could be overridden by a default method.
195  bool IsOverridableByDefaultMethod() SHARED_REQUIRES(Locks::mutator_lock_);
196
197  bool CheckIncompatibleClassChange(InvokeType type) SHARED_REQUIRES(Locks::mutator_lock_);
198
199  // Throws the error that would result from trying to invoke this method (i.e.
200  // IncompatibleClassChangeError or AbstractMethodError). Only call if !IsInvokable();
201  void ThrowInvocationTimeError() SHARED_REQUIRES(Locks::mutator_lock_);
202
203  uint16_t GetMethodIndex() SHARED_REQUIRES(Locks::mutator_lock_);
204
205  // Doesn't do erroneous / unresolved class checks.
206  uint16_t GetMethodIndexDuringLinking() SHARED_REQUIRES(Locks::mutator_lock_);
207
208  size_t GetVtableIndex() SHARED_REQUIRES(Locks::mutator_lock_) {
209    return GetMethodIndex();
210  }
211
212  void SetMethodIndex(uint16_t new_method_index) SHARED_REQUIRES(Locks::mutator_lock_) {
213    // Not called within a transaction.
214    method_index_ = new_method_index;
215  }
216
217  static MemberOffset DexMethodIndexOffset() {
218    return OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_method_index_);
219  }
220
221  static MemberOffset MethodIndexOffset() {
222    return OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_);
223  }
224
225  uint32_t GetCodeItemOffset() {
226    return dex_code_item_offset_;
227  }
228
229  void SetCodeItemOffset(uint32_t new_code_off) {
230    // Not called within a transaction.
231    dex_code_item_offset_ = new_code_off;
232  }
233
234  // Number of 32bit registers that would be required to hold all the arguments
235  static size_t NumArgRegisters(const StringPiece& shorty);
236
237  ALWAYS_INLINE uint32_t GetDexMethodIndex() SHARED_REQUIRES(Locks::mutator_lock_);
238
239  void SetDexMethodIndex(uint32_t new_idx) {
240    // Not called within a transaction.
241    dex_method_index_ = new_idx;
242  }
243
244  ALWAYS_INLINE ArtMethod** GetDexCacheResolvedMethods(size_t pointer_size)
245      SHARED_REQUIRES(Locks::mutator_lock_);
246  ALWAYS_INLINE ArtMethod* GetDexCacheResolvedMethod(uint16_t method_index, size_t ptr_size)
247      SHARED_REQUIRES(Locks::mutator_lock_);
248  ALWAYS_INLINE void SetDexCacheResolvedMethod(uint16_t method_index,
249                                               ArtMethod* new_method,
250                                               size_t ptr_size)
251      SHARED_REQUIRES(Locks::mutator_lock_);
252  ALWAYS_INLINE void SetDexCacheResolvedMethods(ArtMethod** new_dex_cache_methods, size_t ptr_size)
253      SHARED_REQUIRES(Locks::mutator_lock_);
254  bool HasDexCacheResolvedMethods(size_t pointer_size) SHARED_REQUIRES(Locks::mutator_lock_);
255  bool HasSameDexCacheResolvedMethods(ArtMethod* other, size_t pointer_size)
256      SHARED_REQUIRES(Locks::mutator_lock_);
257  bool HasSameDexCacheResolvedMethods(ArtMethod** other_cache, size_t pointer_size)
258      SHARED_REQUIRES(Locks::mutator_lock_);
259
260  template <bool kWithCheck = true>
261  mirror::Class* GetDexCacheResolvedType(uint32_t type_idx, size_t ptr_size)
262      SHARED_REQUIRES(Locks::mutator_lock_);
263  void SetDexCacheResolvedTypes(GcRoot<mirror::Class>* new_dex_cache_types, size_t ptr_size)
264      SHARED_REQUIRES(Locks::mutator_lock_);
265  bool HasDexCacheResolvedTypes(size_t pointer_size) SHARED_REQUIRES(Locks::mutator_lock_);
266  bool HasSameDexCacheResolvedTypes(ArtMethod* other, size_t pointer_size)
267      SHARED_REQUIRES(Locks::mutator_lock_);
268  bool HasSameDexCacheResolvedTypes(GcRoot<mirror::Class>* other_cache, size_t pointer_size)
269      SHARED_REQUIRES(Locks::mutator_lock_);
270
271  // Get the Class* from the type index into this method's dex cache.
272  mirror::Class* GetClassFromTypeIndex(uint16_t type_idx, bool resolve, size_t ptr_size)
273      SHARED_REQUIRES(Locks::mutator_lock_);
274
275  // Returns true if this method has the same name and signature of the other method.
276  bool HasSameNameAndSignature(ArtMethod* other) SHARED_REQUIRES(Locks::mutator_lock_);
277
278  // Find the method that this method overrides.
279  ArtMethod* FindOverriddenMethod(size_t pointer_size)
280      REQUIRES(Roles::uninterruptible_)
281      SHARED_REQUIRES(Locks::mutator_lock_);
282
283  // Find the method index for this method within other_dexfile. If this method isn't present then
284  // return DexFile::kDexNoIndex. The name_and_signature_idx MUST refer to a MethodId with the same
285  // name and signature in the other_dexfile, such as the method index used to resolve this method
286  // in the other_dexfile.
287  uint32_t FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile,
288                                            uint32_t name_and_signature_idx)
289      SHARED_REQUIRES(Locks::mutator_lock_);
290
291  void Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result, const char* shorty)
292      SHARED_REQUIRES(Locks::mutator_lock_);
293
294  const void* GetEntryPointFromQuickCompiledCode() {
295    return GetEntryPointFromQuickCompiledCodePtrSize(sizeof(void*));
296  }
297  ALWAYS_INLINE const void* GetEntryPointFromQuickCompiledCodePtrSize(size_t pointer_size) {
298    return GetNativePointer<const void*>(
299        EntryPointFromQuickCompiledCodeOffset(pointer_size), pointer_size);
300  }
301
302  void SetEntryPointFromQuickCompiledCode(const void* entry_point_from_quick_compiled_code) {
303    SetEntryPointFromQuickCompiledCodePtrSize(entry_point_from_quick_compiled_code,
304                                              sizeof(void*));
305  }
306  ALWAYS_INLINE void SetEntryPointFromQuickCompiledCodePtrSize(
307      const void* entry_point_from_quick_compiled_code, size_t pointer_size) {
308    SetNativePointer(EntryPointFromQuickCompiledCodeOffset(pointer_size),
309                     entry_point_from_quick_compiled_code, pointer_size);
310  }
311
312  void RegisterNative(const void* native_method, bool is_fast)
313      SHARED_REQUIRES(Locks::mutator_lock_);
314
315  void UnregisterNative() SHARED_REQUIRES(Locks::mutator_lock_);
316
317  static MemberOffset DexCacheResolvedMethodsOffset(size_t pointer_size) {
318    return MemberOffset(PtrSizedFieldsOffset(pointer_size) + OFFSETOF_MEMBER(
319        PtrSizedFields, dex_cache_resolved_methods_) / sizeof(void*) * pointer_size);
320  }
321
322  static MemberOffset DexCacheResolvedTypesOffset(size_t pointer_size) {
323    return MemberOffset(PtrSizedFieldsOffset(pointer_size) + OFFSETOF_MEMBER(
324        PtrSizedFields, dex_cache_resolved_types_) / sizeof(void*) * pointer_size);
325  }
326
327  static MemberOffset EntryPointFromJniOffset(size_t pointer_size) {
328    return MemberOffset(PtrSizedFieldsOffset(pointer_size) + OFFSETOF_MEMBER(
329        PtrSizedFields, entry_point_from_jni_) / sizeof(void*) * pointer_size);
330  }
331
332  static MemberOffset EntryPointFromQuickCompiledCodeOffset(size_t pointer_size) {
333    return MemberOffset(PtrSizedFieldsOffset(pointer_size) + OFFSETOF_MEMBER(
334        PtrSizedFields, entry_point_from_quick_compiled_code_) / sizeof(void*) * pointer_size);
335  }
336
337  ProfilingInfo* GetProfilingInfo(size_t pointer_size) {
338    return reinterpret_cast<ProfilingInfo*>(GetEntryPointFromJniPtrSize(pointer_size));
339  }
340
341  ALWAYS_INLINE void SetProfilingInfo(ProfilingInfo* info) {
342    SetEntryPointFromJniPtrSize(info, sizeof(void*));
343  }
344
345  ALWAYS_INLINE void SetProfilingInfoPtrSize(ProfilingInfo* info, size_t pointer_size) {
346    SetEntryPointFromJniPtrSize(info, pointer_size);
347  }
348
349  static MemberOffset ProfilingInfoOffset() {
350    return EntryPointFromJniOffset(sizeof(void*));
351  }
352
353  void* GetEntryPointFromJni() {
354    return GetEntryPointFromJniPtrSize(sizeof(void*));
355  }
356
357  ALWAYS_INLINE void* GetEntryPointFromJniPtrSize(size_t pointer_size) {
358    return GetNativePointer<void*>(EntryPointFromJniOffset(pointer_size), pointer_size);
359  }
360
361  void SetEntryPointFromJni(const void* entrypoint) {
362    DCHECK(IsNative());
363    SetEntryPointFromJniPtrSize(entrypoint, sizeof(void*));
364  }
365
366  ALWAYS_INLINE void SetEntryPointFromJniPtrSize(const void* entrypoint, size_t pointer_size) {
367    SetNativePointer(EntryPointFromJniOffset(pointer_size), entrypoint, pointer_size);
368  }
369
370  // Is this a CalleSaveMethod or ResolutionMethod and therefore doesn't adhere to normal
371  // conventions for a method of managed code. Returns false for Proxy methods.
372  ALWAYS_INLINE bool IsRuntimeMethod();
373
374  // Is this a hand crafted method used for something like describing callee saves?
375  bool IsCalleeSaveMethod() SHARED_REQUIRES(Locks::mutator_lock_);
376
377  bool IsResolutionMethod() SHARED_REQUIRES(Locks::mutator_lock_);
378
379  bool IsImtConflictMethod() SHARED_REQUIRES(Locks::mutator_lock_);
380
381  bool IsImtUnimplementedMethod() SHARED_REQUIRES(Locks::mutator_lock_);
382
383  MethodReference ToMethodReference() SHARED_REQUIRES(Locks::mutator_lock_) {
384    return MethodReference(GetDexFile(), GetDexMethodIndex());
385  }
386
387  // Find the catch block for the given exception type and dex_pc. When a catch block is found,
388  // indicates whether the found catch block is responsible for clearing the exception or whether
389  // a move-exception instruction is present.
390  uint32_t FindCatchBlock(Handle<mirror::Class> exception_type, uint32_t dex_pc,
391                          bool* has_no_move_exception)
392      SHARED_REQUIRES(Locks::mutator_lock_);
393
394  // NO_THREAD_SAFETY_ANALYSIS since we don't know what the callback requires.
395  template<typename RootVisitorType>
396  void VisitRoots(RootVisitorType& visitor, size_t pointer_size) NO_THREAD_SAFETY_ANALYSIS;
397
398  const DexFile* GetDexFile() SHARED_REQUIRES(Locks::mutator_lock_);
399
400  const char* GetDeclaringClassDescriptor() SHARED_REQUIRES(Locks::mutator_lock_);
401
402  const char* GetShorty() SHARED_REQUIRES(Locks::mutator_lock_) {
403    uint32_t unused_length;
404    return GetShorty(&unused_length);
405  }
406
407  const char* GetShorty(uint32_t* out_length) SHARED_REQUIRES(Locks::mutator_lock_);
408
409  const Signature GetSignature() SHARED_REQUIRES(Locks::mutator_lock_);
410
411  ALWAYS_INLINE const char* GetName() SHARED_REQUIRES(Locks::mutator_lock_);
412
413  mirror::String* GetNameAsString(Thread* self) SHARED_REQUIRES(Locks::mutator_lock_);
414
415  const DexFile::CodeItem* GetCodeItem() SHARED_REQUIRES(Locks::mutator_lock_);
416
417  bool IsResolvedTypeIdx(uint16_t type_idx, size_t ptr_size) SHARED_REQUIRES(Locks::mutator_lock_);
418
419  int32_t GetLineNumFromDexPC(uint32_t dex_pc) SHARED_REQUIRES(Locks::mutator_lock_);
420
421  const DexFile::ProtoId& GetPrototype() SHARED_REQUIRES(Locks::mutator_lock_);
422
423  const DexFile::TypeList* GetParameterTypeList() SHARED_REQUIRES(Locks::mutator_lock_);
424
425  const char* GetDeclaringClassSourceFile() SHARED_REQUIRES(Locks::mutator_lock_);
426
427  uint16_t GetClassDefIndex() SHARED_REQUIRES(Locks::mutator_lock_);
428
429  const DexFile::ClassDef& GetClassDef() SHARED_REQUIRES(Locks::mutator_lock_);
430
431  const char* GetReturnTypeDescriptor() SHARED_REQUIRES(Locks::mutator_lock_);
432
433  const char* GetTypeDescriptorFromTypeIdx(uint16_t type_idx)
434      SHARED_REQUIRES(Locks::mutator_lock_);
435
436  // May cause thread suspension due to GetClassFromTypeIdx calling ResolveType this caused a large
437  // number of bugs at call sites.
438  mirror::Class* GetReturnType(bool resolve, size_t ptr_size)
439      SHARED_REQUIRES(Locks::mutator_lock_);
440
441  mirror::ClassLoader* GetClassLoader() SHARED_REQUIRES(Locks::mutator_lock_);
442
443  mirror::DexCache* GetDexCache() SHARED_REQUIRES(Locks::mutator_lock_);
444
445  ALWAYS_INLINE ArtMethod* GetInterfaceMethodIfProxy(size_t pointer_size)
446      SHARED_REQUIRES(Locks::mutator_lock_);
447
448  // May cause thread suspension due to class resolution.
449  bool EqualParameters(Handle<mirror::ObjectArray<mirror::Class>> params)
450      SHARED_REQUIRES(Locks::mutator_lock_);
451
452  // Size of an instance of this native class.
453  static size_t Size(size_t pointer_size) {
454    return RoundUp(OFFSETOF_MEMBER(ArtMethod, ptr_sized_fields_), pointer_size) +
455        (sizeof(PtrSizedFields) / sizeof(void*)) * pointer_size;
456  }
457
458  // Alignment of an instance of this native class.
459  static size_t Alignment(size_t pointer_size) {
460    // The ArtMethod alignment is the same as image pointer size. This differs from
461    // alignof(ArtMethod) if cross-compiling with pointer_size != sizeof(void*).
462    return pointer_size;
463  }
464
465  void CopyFrom(ArtMethod* src, size_t image_pointer_size)
466      SHARED_REQUIRES(Locks::mutator_lock_);
467
468  ALWAYS_INLINE GcRoot<mirror::Class>* GetDexCacheResolvedTypes(size_t pointer_size)
469      SHARED_REQUIRES(Locks::mutator_lock_);
470
471  uint16_t IncrementCounter() {
472    return ++hotness_count_;
473  }
474
475  void ClearCounter() {
476    hotness_count_ = 0;
477  }
478
479  const uint8_t* GetQuickenedInfo() SHARED_REQUIRES(Locks::mutator_lock_);
480
481  // Returns the method header for the compiled code containing 'pc'. Note that runtime
482  // methods will return null for this method, as they are not oat based.
483  const OatQuickMethodHeader* GetOatQuickMethodHeader(uintptr_t pc)
484      SHARED_REQUIRES(Locks::mutator_lock_);
485
486  // Returns whether the method has any compiled code, JIT or AOT.
487  bool HasAnyCompiledCode() SHARED_REQUIRES(Locks::mutator_lock_);
488
489
490  // Update heap objects and non-entrypoint pointers by the passed in visitor for image relocation.
491  // Does not use read barrier.
492  template <typename Visitor>
493  ALWAYS_INLINE void UpdateObjectsForImageRelocation(const Visitor& visitor)
494      SHARED_REQUIRES(Locks::mutator_lock_);
495
496  // Update entry points by passing them through the visitor.
497  template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename Visitor>
498  ALWAYS_INLINE void UpdateEntrypoints(const Visitor& visitor);
499
500 protected:
501  // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
502  // The class we are a part of.
503  GcRoot<mirror::Class> declaring_class_;
504
505  // Access flags; low 16 bits are defined by spec.
506  uint32_t access_flags_;
507
508  /* Dex file fields. The defining dex file is available via declaring_class_->dex_cache_ */
509
510  // Offset to the CodeItem.
511  uint32_t dex_code_item_offset_;
512
513  // Index into method_ids of the dex file associated with this method.
514  uint32_t dex_method_index_;
515
516  /* End of dex file fields. */
517
518  // Entry within a dispatch table for this method. For static/direct methods the index is into
519  // the declaringClass.directMethods, for virtual methods the vtable and for interface methods the
520  // ifTable.
521  uint16_t method_index_;
522
523  // The hotness we measure for this method. Incremented by the interpreter. Not atomic, as we allow
524  // missing increments: if the method is hot, we will see it eventually.
525  uint16_t hotness_count_;
526
527  // Fake padding field gets inserted here.
528
529  // Must be the last fields in the method.
530  // PACKED(4) is necessary for the correctness of
531  // RoundUp(OFFSETOF_MEMBER(ArtMethod, ptr_sized_fields_), pointer_size).
532  struct PACKED(4) PtrSizedFields {
533    // Short cuts to declaring_class_->dex_cache_ member for fast compiled code access.
534    ArtMethod** dex_cache_resolved_methods_;
535
536    // Short cuts to declaring_class_->dex_cache_ member for fast compiled code access.
537    GcRoot<mirror::Class>* dex_cache_resolved_types_;
538
539    // Pointer to JNI function registered to this method, or a function to resolve the JNI function,
540    // or the profiling data for non-native methods.
541    void* entry_point_from_jni_;
542
543    // Method dispatch from quick compiled code invokes this pointer which may cause bridging into
544    // the interpreter.
545    void* entry_point_from_quick_compiled_code_;
546  } ptr_sized_fields_;
547
548 private:
549  static size_t PtrSizedFieldsOffset(size_t pointer_size) {
550    // Round up to pointer size for padding field.
551    return RoundUp(OFFSETOF_MEMBER(ArtMethod, ptr_sized_fields_), pointer_size);
552  }
553
554  template<typename T>
555  ALWAYS_INLINE T GetNativePointer(MemberOffset offset, size_t pointer_size) const {
556    static_assert(std::is_pointer<T>::value, "T must be a pointer type");
557    DCHECK(ValidPointerSize(pointer_size)) << pointer_size;
558    const auto addr = reinterpret_cast<uintptr_t>(this) + offset.Uint32Value();
559    if (pointer_size == sizeof(uint32_t)) {
560      return reinterpret_cast<T>(*reinterpret_cast<const uint32_t*>(addr));
561    } else {
562      auto v = *reinterpret_cast<const uint64_t*>(addr);
563      return reinterpret_cast<T>(dchecked_integral_cast<uintptr_t>(v));
564    }
565  }
566
567  template<typename T>
568  ALWAYS_INLINE void SetNativePointer(MemberOffset offset, T new_value, size_t pointer_size) {
569    static_assert(std::is_pointer<T>::value, "T must be a pointer type");
570    DCHECK(ValidPointerSize(pointer_size)) << pointer_size;
571    const auto addr = reinterpret_cast<uintptr_t>(this) + offset.Uint32Value();
572    if (pointer_size == sizeof(uint32_t)) {
573      uintptr_t ptr = reinterpret_cast<uintptr_t>(new_value);
574      *reinterpret_cast<uint32_t*>(addr) = dchecked_integral_cast<uint32_t>(ptr);
575    } else {
576      *reinterpret_cast<uint64_t*>(addr) = reinterpret_cast<uintptr_t>(new_value);
577    }
578  }
579
580  DISALLOW_COPY_AND_ASSIGN(ArtMethod);  // Need to use CopyFrom to deal with 32 vs 64 bits.
581};
582
583}  // namespace art
584
585#endif  // ART_RUNTIME_ART_METHOD_H_
586