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: ArtMethod()51 ArtMethod() : access_flags_(0), dex_code_item_offset_(0), dex_method_index_(0), 52 method_index_(0) { } 53 ArtMethod(const ArtMethod & src,size_t image_pointer_size)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 DeclaringClassOffset()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 SetAccessFlags(uint32_t new_access_flags)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. IsPublic()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. IsPrivate()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. IsStatic()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. IsConstructor()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. IsClassInitializer()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. IsDirect()113 bool IsDirect() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 114 return IsDirect(GetAccessFlags()); 115 } 116 IsDirect(uint32_t access_flags)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. IsSynchronized()122 bool IsSynchronized() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 123 uint32_t synchonized = kAccSynchronized | kAccDeclaredSynchronized; 124 return (GetAccessFlags() & synchonized) != 0; 125 } 126 IsFinal()127 bool IsFinal() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 128 return (GetAccessFlags() & kAccFinal) != 0; 129 } 130 IsMiranda()131 bool IsMiranda() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 132 return (GetAccessFlags() & kAccMiranda) != 0; 133 } 134 IsNative()135 bool IsNative() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 136 return (GetAccessFlags() & kAccNative) != 0; 137 } 138 ShouldNotInline()139 bool ShouldNotInline() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 140 return (GetAccessFlags() & kAccDontInline) != 0; 141 } 142 SetShouldNotInline()143 void SetShouldNotInline() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 144 SetAccessFlags(GetAccessFlags() | kAccDontInline); 145 } 146 IsFastNative()147 bool IsFastNative() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 148 uint32_t mask = kAccFastNative | kAccNative; 149 return (GetAccessFlags() & mask) == mask; 150 } 151 IsAbstract()152 bool IsAbstract() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 153 return (GetAccessFlags() & kAccAbstract) != 0; 154 } 155 IsSynthetic()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 IsPreverified()162 bool IsPreverified() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 163 return (GetAccessFlags() & kAccPreverified) != 0; 164 } 165 SetPreverified()166 void SetPreverified() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 167 DCHECK(!IsPreverified()); 168 SetAccessFlags(GetAccessFlags() | kAccPreverified); 169 } 170 IsOptimized(size_t pointer_size)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 GetVtableIndex()188 size_t GetVtableIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 189 return GetMethodIndex(); 190 } 191 SetMethodIndex(uint16_t new_method_index)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 DexMethodIndexOffset()197 static MemberOffset DexMethodIndexOffset() { 198 return OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_method_index_); 199 } 200 MethodIndexOffset()201 static MemberOffset MethodIndexOffset() { 202 return OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_); 203 } 204 GetCodeItemOffset()205 uint32_t GetCodeItemOffset() { 206 return dex_code_item_offset_; 207 } 208 SetCodeItemOffset(uint32_t new_code_off)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 SetDexMethodIndex(uint32_t new_idx)219 void SetDexMethodIndex(uint32_t new_idx) { 220 // Not called within a transaction. 221 dex_method_index_ = new_idx; 222 } 223 DexCacheResolvedMethodsOffset()224 static MemberOffset DexCacheResolvedMethodsOffset() { 225 return OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_methods_); 226 } 227 DexCacheResolvedTypesOffset()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 GetEntryPointFromInterpreter()275 EntryPointFromInterpreter* GetEntryPointFromInterpreter() { 276 return GetEntryPointFromInterpreterPtrSize(sizeof(void*)); 277 } GetEntryPointFromInterpreterPtrSize(size_t pointer_size)278 EntryPointFromInterpreter* GetEntryPointFromInterpreterPtrSize(size_t pointer_size) { 279 return GetEntryPoint<EntryPointFromInterpreter*>( 280 EntryPointFromInterpreterOffset(pointer_size), pointer_size); 281 } 282 SetEntryPointFromInterpreter(EntryPointFromInterpreter * entry_point_from_interpreter)283 void SetEntryPointFromInterpreter(EntryPointFromInterpreter* entry_point_from_interpreter) { 284 SetEntryPointFromInterpreterPtrSize(entry_point_from_interpreter, sizeof(void*)); 285 } SetEntryPointFromInterpreterPtrSize(EntryPointFromInterpreter * entry_point_from_interpreter,size_t pointer_size)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 GetEntryPointFromQuickCompiledCode()292 const void* GetEntryPointFromQuickCompiledCode() { 293 return GetEntryPointFromQuickCompiledCodePtrSize(sizeof(void*)); 294 } GetEntryPointFromQuickCompiledCodePtrSize(size_t pointer_size)295 ALWAYS_INLINE const void* GetEntryPointFromQuickCompiledCodePtrSize(size_t pointer_size) { 296 return GetEntryPoint<const void*>( 297 EntryPointFromQuickCompiledCodeOffset(pointer_size), pointer_size); 298 } 299 SetEntryPointFromQuickCompiledCode(const void * entry_point_from_quick_compiled_code)300 void SetEntryPointFromQuickCompiledCode(const void* entry_point_from_quick_compiled_code) { 301 SetEntryPointFromQuickCompiledCodePtrSize(entry_point_from_quick_compiled_code, 302 sizeof(void*)); 303 } SetEntryPointFromQuickCompiledCodePtrSize(const void * entry_point_from_quick_compiled_code,size_t pointer_size)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. PcIsWithinQuickCode(uintptr_t pc)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 EntryPointToCodePointer(const void * entry_point)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. GetQuickOatCodePointer(size_t pointer_size)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> GetFrameSizeInBytes()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 GetReturnPcOffset()380 FrameOffset GetReturnPcOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 381 return GetReturnPcOffset(GetFrameSizeInBytes()); 382 } 383 GetReturnPcOffset(uint32_t frame_size_in_bytes)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 GetHandleScopeOffset()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 EntryPointFromInterpreterOffset(size_t pointer_size)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 EntryPointFromJniOffset(size_t pointer_size)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 EntryPointFromQuickCompiledCodeOffset(size_t pointer_size)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 GetEntryPointFromJni()416 void* GetEntryPointFromJni() { 417 return GetEntryPointFromJniPtrSize(sizeof(void*)); 418 } GetEntryPointFromJniPtrSize(size_t pointer_size)419 ALWAYS_INLINE void* GetEntryPointFromJniPtrSize(size_t pointer_size) { 420 return GetEntryPoint<void*>(EntryPointFromJniOffset(pointer_size), pointer_size); 421 } 422 SetEntryPointFromJni(const void * entrypoint)423 void SetEntryPointFromJni(const void* entrypoint) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 424 SetEntryPointFromJniPtrSize(entrypoint, sizeof(void*)); 425 } SetEntryPointFromJniPtrSize(const void * entrypoint,size_t pointer_size)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 NativeQuickPcOffset(const uintptr_t pc,const void * quick_entry_point)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 ToMethodReference()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 GetShorty()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. ObjectSize(size_t pointer_size)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: PtrSizedFieldsOffset(size_t pointer_size)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> GetEntryPoint(MemberOffset offset,size_t pointer_size)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> SetEntryPoint(MemberOffset offset,T new_value,size_t pointer_size)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 PcIsWithinQuickCode(uintptr_t code,uintptr_t pc)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