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