summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/art_method-inl.h25
-rw-r--r--runtime/art_method.h43
2 files changed, 46 insertions, 22 deletions
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index d6b2b7e04d..632a50f15c 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -35,6 +35,8 @@
#include "quick/quick_method_frame_info.h"
#include "read_barrier-inl.h"
#include "runtime-inl.h"
+#include "scoped_thread_state_change.h"
+#include "thread-inl.h"
#include "utils.h"
namespace art {
@@ -75,9 +77,28 @@ inline bool ArtMethod::CASDeclaringClass(mirror::Class* expected_class,
expected_root, desired_root);
}
+// AssertSharedHeld doesn't work in GetAccessFlags, so use a NO_THREAD_SAFETY_ANALYSIS helper.
+// TODO: Figure out why ASSERT_SHARED_CAPABILITY doesn't work.
+ALWAYS_INLINE
+static inline void DoGetAccessFlagsHelper(ArtMethod* method) NO_THREAD_SAFETY_ANALYSIS {
+ CHECK(method->IsRuntimeMethod() || method->GetDeclaringClass()->IsIdxLoaded() ||
+ method->GetDeclaringClass()->IsErroneous());
+}
+
inline uint32_t ArtMethod::GetAccessFlags() {
- DCHECK(IsRuntimeMethod() || GetDeclaringClass()->IsIdxLoaded() ||
- GetDeclaringClass()->IsErroneous());
+ if (kIsDebugBuild) {
+ Thread* self = Thread::Current();
+ if (!Locks::mutator_lock_->IsSharedHeld(self)) {
+ ScopedObjectAccess soa(self);
+ CHECK(IsRuntimeMethod() || GetDeclaringClass()->IsIdxLoaded() ||
+ GetDeclaringClass()->IsErroneous());
+ } else {
+ // We cannot use SOA in this case. We might be holding the lock, but may not be in the
+ // runnable state (e.g., during GC).
+ Locks::mutator_lock_->AssertSharedHeld(self);
+ DoGetAccessFlagsHelper(this);
+ }
+ }
return access_flags_;
}
diff --git a/runtime/art_method.h b/runtime/art_method.h
index f78c8274b0..0315c3a953 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -75,7 +75,9 @@ class ArtMethod FINAL {
return MemberOffset(OFFSETOF_MEMBER(ArtMethod, declaring_class_));
}
- ALWAYS_INLINE uint32_t GetAccessFlags() SHARED_REQUIRES(Locks::mutator_lock_);
+ // Note: GetAccessFlags acquires the mutator lock in debug mode to check that it is not called for
+ // a proxy method.
+ ALWAYS_INLINE uint32_t GetAccessFlags();
void SetAccessFlags(uint32_t new_access_flags) {
// Not called within a transaction.
@@ -86,77 +88,78 @@ class ArtMethod FINAL {
InvokeType GetInvokeType() SHARED_REQUIRES(Locks::mutator_lock_);
// Returns true if the method is declared public.
- bool IsPublic() SHARED_REQUIRES(Locks::mutator_lock_) {
+ bool IsPublic() {
return (GetAccessFlags() & kAccPublic) != 0;
}
// Returns true if the method is declared private.
- bool IsPrivate() SHARED_REQUIRES(Locks::mutator_lock_) {
+ bool IsPrivate() {
return (GetAccessFlags() & kAccPrivate) != 0;
}
// Returns true if the method is declared static.
- bool IsStatic() SHARED_REQUIRES(Locks::mutator_lock_) {
+ bool IsStatic() {
return (GetAccessFlags() & kAccStatic) != 0;
}
// Returns true if the method is a constructor.
- bool IsConstructor() SHARED_REQUIRES(Locks::mutator_lock_) {
+ bool IsConstructor() {
return (GetAccessFlags() & kAccConstructor) != 0;
}
// Returns true if the method is a class initializer.
- bool IsClassInitializer() SHARED_REQUIRES(Locks::mutator_lock_) {
+ bool IsClassInitializer() {
return IsConstructor() && IsStatic();
}
// Returns true if the method is static, private, or a constructor.
- bool IsDirect() SHARED_REQUIRES(Locks::mutator_lock_) {
+ bool IsDirect() {
return IsDirect(GetAccessFlags());
}
static bool IsDirect(uint32_t access_flags) {
- return (access_flags & (kAccStatic | kAccPrivate | kAccConstructor)) != 0;
+ constexpr uint32_t direct = kAccStatic | kAccPrivate | kAccConstructor;
+ return (access_flags & direct) != 0;
}
// Returns true if the method is declared synchronized.
- bool IsSynchronized() SHARED_REQUIRES(Locks::mutator_lock_) {
- uint32_t synchonized = kAccSynchronized | kAccDeclaredSynchronized;
+ bool IsSynchronized() {
+ constexpr uint32_t synchonized = kAccSynchronized | kAccDeclaredSynchronized;
return (GetAccessFlags() & synchonized) != 0;
}
- bool IsFinal() SHARED_REQUIRES(Locks::mutator_lock_) {
+ bool IsFinal() {
return (GetAccessFlags() & kAccFinal) != 0;
}
- bool IsMiranda() SHARED_REQUIRES(Locks::mutator_lock_) {
+ bool IsMiranda() {
return (GetAccessFlags() & kAccMiranda) != 0;
}
- bool IsNative() SHARED_REQUIRES(Locks::mutator_lock_) {
+ bool IsNative() {
return (GetAccessFlags() & kAccNative) != 0;
}
- bool IsFastNative() SHARED_REQUIRES(Locks::mutator_lock_) {
- uint32_t mask = kAccFastNative | kAccNative;
+ bool IsFastNative() {
+ constexpr uint32_t mask = kAccFastNative | kAccNative;
return (GetAccessFlags() & mask) == mask;
}
- bool IsAbstract() SHARED_REQUIRES(Locks::mutator_lock_) {
+ bool IsAbstract() {
return (GetAccessFlags() & kAccAbstract) != 0;
}
- bool IsSynthetic() SHARED_REQUIRES(Locks::mutator_lock_) {
+ bool IsSynthetic() {
return (GetAccessFlags() & kAccSynthetic) != 0;
}
bool IsProxyMethod() SHARED_REQUIRES(Locks::mutator_lock_);
- bool IsPreverified() SHARED_REQUIRES(Locks::mutator_lock_) {
+ bool IsPreverified() {
return (GetAccessFlags() & kAccPreverified) != 0;
}
- void SetPreverified() SHARED_REQUIRES(Locks::mutator_lock_) {
+ void SetPreverified() {
DCHECK(!IsPreverified());
SetAccessFlags(GetAccessFlags() | kAccPreverified);
}
@@ -404,7 +407,7 @@ class ArtMethod FINAL {
return GetNativePointer<void*>(EntryPointFromJniOffset(pointer_size), pointer_size);
}
- void SetEntryPointFromJni(const void* entrypoint) SHARED_REQUIRES(Locks::mutator_lock_) {
+ void SetEntryPointFromJni(const void* entrypoint) {
DCHECK(IsNative());
SetEntryPointFromJniPtrSize(entrypoint, sizeof(void*));
}