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