diff options
Diffstat (limited to 'runtime/art_method.h')
-rw-r--r-- | runtime/art_method.h | 89 |
1 files changed, 52 insertions, 37 deletions
diff --git a/runtime/art_method.h b/runtime/art_method.h index 00fab65241..3bc6f5d4fd 100644 --- a/runtime/art_method.h +++ b/runtime/art_method.h @@ -85,9 +85,29 @@ class ArtMethod FINAL { template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier> ALWAYS_INLINE uint32_t GetAccessFlags(); + // This version should only be called when it's certain there is no + // concurrency so there is no need to guarantee atomicity. For example, + // before the method is linked. void SetAccessFlags(uint32_t new_access_flags) { - // Not called within a transaction. - access_flags_ = new_access_flags; + access_flags_.store(new_access_flags, std::memory_order_relaxed); + } + + // This setter guarantees atomicity. + void AddAccessFlags(uint32_t flag) { + uint32_t old_access_flags = access_flags_.load(std::memory_order_relaxed); + uint32_t new_access_flags; + do { + new_access_flags = old_access_flags | flag; + } while (!access_flags_.compare_exchange_weak(old_access_flags, new_access_flags)); + } + + // This setter guarantees atomicity. + void ClearAccessFlags(uint32_t flag) { + uint32_t old_access_flags = access_flags_.load(std::memory_order_relaxed); + uint32_t new_access_flags; + do { + new_access_flags = old_access_flags & ~flag; + } while (!access_flags_.compare_exchange_weak(old_access_flags, new_access_flags)); } // Approximate what kind of method call would be used for this method. @@ -142,39 +162,7 @@ class ArtMethod FINAL { return (GetAccessFlags() & kAccIntrinsic) != 0; } - void SetIntrinsic(uint32_t intrinsic) { - DCHECK(IsUint<8>(intrinsic)); - uint32_t new_value = (GetAccessFlags() & kAccFlagsNotUsedByIntrinsic) | - kAccIntrinsic | - (intrinsic << POPCOUNT(kAccFlagsNotUsedByIntrinsic)); - if (kIsDebugBuild) { - uint32_t java_flags = (GetAccessFlags() & kAccJavaFlagsMask); - bool is_constructor = IsConstructor(); - bool is_synchronized = IsSynchronized(); - bool skip_access_checks = SkipAccessChecks(); - bool is_fast_native = IsFastNative(); - bool is_copied = IsCopied(); - bool is_miranda = IsMiranda(); - bool is_default = IsDefault(); - bool is_default_conflict = IsDefaultConflicting(); - bool is_compilable = IsCompilable(); - bool must_count_locks = MustCountLocks(); - SetAccessFlags(new_value); - DCHECK_EQ(java_flags, (GetAccessFlags() & kAccJavaFlagsMask)); - DCHECK_EQ(is_constructor, IsConstructor()); - DCHECK_EQ(is_synchronized, IsSynchronized()); - DCHECK_EQ(skip_access_checks, SkipAccessChecks()); - DCHECK_EQ(is_fast_native, IsFastNative()); - DCHECK_EQ(is_copied, IsCopied()); - DCHECK_EQ(is_miranda, IsMiranda()); - DCHECK_EQ(is_default, IsDefault()); - DCHECK_EQ(is_default_conflict, IsDefaultConflicting()); - DCHECK_EQ(is_compilable, IsCompilable()); - DCHECK_EQ(must_count_locks, MustCountLocks()); - } else { - SetAccessFlags(new_value); - } - } + ALWAYS_INLINE void SetIntrinsic(uint32_t intrinsic) REQUIRES_SHARED(Locks::mutator_lock_); uint32_t GetIntrinsic() { DCHECK(IsIntrinsic()); @@ -250,6 +238,10 @@ class ArtMethod FINAL { return (GetAccessFlags() & kAccSynthetic) != 0; } + bool IsVarargs() { + return (GetAccessFlags() & kAccVarargs) != 0; + } + template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier> bool IsProxyMethod() REQUIRES_SHARED(Locks::mutator_lock_); @@ -259,7 +251,7 @@ class ArtMethod FINAL { void SetSkipAccessChecks() { DCHECK(!SkipAccessChecks()); - SetAccessFlags(GetAccessFlags() | kAccSkipAccessChecks); + AddAccessFlags(kAccSkipAccessChecks); } // Should this method be run in the interpreter and count locks (e.g., failed structured- @@ -461,6 +453,26 @@ class ArtMethod FINAL { return DataOffset(kRuntimePointerSize); } + ALWAYS_INLINE bool HasSingleImplementation() REQUIRES_SHARED(Locks::mutator_lock_); + + ALWAYS_INLINE void SetHasSingleImplementation(bool single_impl) { + DCHECK(!IsIntrinsic()) << "conflict with intrinsic bits"; + if (single_impl) { + AddAccessFlags(kAccSingleImplementation); + } else { + ClearAccessFlags(kAccSingleImplementation); + } + } + + ArtMethod* GetSingleImplementation() + REQUIRES_SHARED(Locks::mutator_lock_); + + ALWAYS_INLINE void SetSingleImplementation(ArtMethod* method, PointerSize pointer_size) { + DCHECK(!IsNative()); + DCHECK(IsAbstract()); // Non-abstract method's single implementation is just itself. + SetDataPtrSize(method, pointer_size); + } + void* GetEntryPointFromJni() { DCHECK(IsNative()); return GetEntryPointFromJniPtrSize(kRuntimePointerSize); @@ -655,7 +667,10 @@ class ArtMethod FINAL { GcRoot<mirror::Class> declaring_class_; // Access flags; low 16 bits are defined by spec. - uint32_t access_flags_; + // Getting and setting this flag needs to be atomic when concurrency is + // possible, e.g. after this method's class is linked. Such as when setting + // verifier flags and single-implementation flag. + std::atomic<std::uint32_t> access_flags_; /* Dex file fields. The defining dex file is available via declaring_class_->dex_cache_ */ |