ART: Hide mutex in Instrumentation
Ensure that instrumentation.h does not pull in mutex.h.
Bug: 119869270
Test: m test-art-host
Change-Id: I0cb993ac3ddef3ce7efab8c624aa92905c888a0d
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 12f1522..42f940e 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -164,7 +164,8 @@
have_watched_frame_pop_listeners_(false),
have_branch_listeners_(false),
have_exception_handled_listeners_(false),
- deoptimized_methods_lock_("deoptimized methods lock", kGenericBottomLock),
+ deoptimized_methods_lock_(new ReaderWriterMutex("deoptimized methods lock",
+ kGenericBottomLock)),
deoptimization_enabled_(false),
interpreter_handler_table_(kMainHandlerTable),
quick_alloc_entry_points_instrumentation_counter_(0),
@@ -743,7 +744,7 @@
// Restore stack only if there is no method currently deoptimized.
bool empty;
{
- ReaderMutexLock mu(self, deoptimized_methods_lock_);
+ ReaderMutexLock mu(self, *GetDeoptimizedMethodsLock());
empty = IsDeoptimizedMethodsEmpty(); // Avoid lock violation.
}
if (empty) {
@@ -931,7 +932,7 @@
Thread* self = Thread::Current();
{
- WriterMutexLock mu(self, deoptimized_methods_lock_);
+ WriterMutexLock mu(self, *GetDeoptimizedMethodsLock());
bool has_not_been_deoptimized = AddDeoptimizedMethod(method);
CHECK(has_not_been_deoptimized) << "Method " << ArtMethod::PrettyMethod(method)
<< " is already deoptimized";
@@ -955,7 +956,7 @@
Thread* self = Thread::Current();
bool empty;
{
- WriterMutexLock mu(self, deoptimized_methods_lock_);
+ WriterMutexLock mu(self, *GetDeoptimizedMethodsLock());
bool found_and_erased = RemoveDeoptimizedMethod(method);
CHECK(found_and_erased) << "Method " << ArtMethod::PrettyMethod(method)
<< " is not deoptimized";
@@ -987,12 +988,12 @@
bool Instrumentation::IsDeoptimized(ArtMethod* method) {
DCHECK(method != nullptr);
- ReaderMutexLock mu(Thread::Current(), deoptimized_methods_lock_);
+ ReaderMutexLock mu(Thread::Current(), *GetDeoptimizedMethodsLock());
return IsDeoptimizedMethod(method);
}
void Instrumentation::EnableDeoptimization() {
- ReaderMutexLock mu(Thread::Current(), deoptimized_methods_lock_);
+ ReaderMutexLock mu(Thread::Current(), *GetDeoptimizedMethodsLock());
CHECK(IsDeoptimizedMethodsEmpty());
CHECK_EQ(deoptimization_enabled_, false);
deoptimization_enabled_ = true;
@@ -1009,7 +1010,7 @@
while (true) {
ArtMethod* method;
{
- ReaderMutexLock mu(Thread::Current(), deoptimized_methods_lock_);
+ ReaderMutexLock mu(Thread::Current(), *GetDeoptimizedMethodsLock());
if (IsDeoptimizedMethodsEmpty()) {
break;
}
diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h
index 3bd4fb5..d4c3c29 100644
--- a/runtime/instrumentation.h
+++ b/runtime/instrumentation.h
@@ -19,12 +19,13 @@
#include <stdint.h>
#include <list>
+#include <memory>
#include <unordered_set>
#include "arch/instruction_set.h"
#include "base/enums.h"
+#include "base/locks.h"
#include "base/macros.h"
-#include "base/mutex.h"
#include "base/safe_map.h"
#include "gc_root.h"
@@ -39,6 +40,7 @@
template <typename T> class Handle;
template <typename T> class MutableHandle;
union JValue;
+class SHARED_LOCKABLE ReaderWriterMutex;
class ShadowFrame;
class Thread;
enum class DeoptimizationMethodType;
@@ -211,11 +213,11 @@
// Deoptimization.
void EnableDeoptimization()
REQUIRES(Locks::mutator_lock_)
- REQUIRES(!deoptimized_methods_lock_);
+ REQUIRES(!GetDeoptimizedMethodsLock());
// Calls UndeoptimizeEverything which may visit class linker classes through ConfigureStubs.
void DisableDeoptimization(const char* key)
REQUIRES(Locks::mutator_lock_, Roles::uninterruptible_)
- REQUIRES(!deoptimized_methods_lock_);
+ REQUIRES(!GetDeoptimizedMethodsLock());
bool AreAllMethodsDeoptimized() const {
return interpreter_stubs_installed_;
@@ -231,7 +233,7 @@
REQUIRES(Locks::mutator_lock_, Roles::uninterruptible_)
REQUIRES(!Locks::thread_list_lock_,
!Locks::classlinker_classes_lock_,
- !deoptimized_methods_lock_);
+ !GetDeoptimizedMethodsLock());
// Executes everything with compiled code (or interpreter if there is no code). May visit class
// linker classes through ConfigureStubs.
@@ -239,23 +241,23 @@
REQUIRES(Locks::mutator_lock_, Roles::uninterruptible_)
REQUIRES(!Locks::thread_list_lock_,
!Locks::classlinker_classes_lock_,
- !deoptimized_methods_lock_);
+ !GetDeoptimizedMethodsLock());
// Deoptimize a method by forcing its execution with the interpreter. Nevertheless, a static
// method (except a class initializer) set to the resolution trampoline will be deoptimized only
// once its declaring class is initialized.
void Deoptimize(ArtMethod* method)
- REQUIRES(Locks::mutator_lock_, !Locks::thread_list_lock_, !deoptimized_methods_lock_);
+ REQUIRES(Locks::mutator_lock_, !Locks::thread_list_lock_, !GetDeoptimizedMethodsLock());
// Undeoptimze the method by restoring its entrypoints. Nevertheless, a static method
// (except a class initializer) set to the resolution trampoline will be updated only once its
// declaring class is initialized.
void Undeoptimize(ArtMethod* method)
- REQUIRES(Locks::mutator_lock_, !Locks::thread_list_lock_, !deoptimized_methods_lock_);
+ REQUIRES(Locks::mutator_lock_, !Locks::thread_list_lock_, !GetDeoptimizedMethodsLock());
// Indicates whether the method has been deoptimized so it is executed with the interpreter.
bool IsDeoptimized(ArtMethod* method)
- REQUIRES(!deoptimized_methods_lock_) REQUIRES_SHARED(Locks::mutator_lock_);
+ REQUIRES(!GetDeoptimizedMethodsLock()) REQUIRES_SHARED(Locks::mutator_lock_);
// Enable method tracing by installing instrumentation entry/exit stubs or interpreter.
void EnableMethodTracing(const char* key,
@@ -263,14 +265,14 @@
REQUIRES(Locks::mutator_lock_, Roles::uninterruptible_)
REQUIRES(!Locks::thread_list_lock_,
!Locks::classlinker_classes_lock_,
- !deoptimized_methods_lock_);
+ !GetDeoptimizedMethodsLock());
// Disable method tracing by uninstalling instrumentation entry/exit stubs or interpreter.
void DisableMethodTracing(const char* key)
REQUIRES(Locks::mutator_lock_, Roles::uninterruptible_)
REQUIRES(!Locks::thread_list_lock_,
!Locks::classlinker_classes_lock_,
- !deoptimized_methods_lock_);
+ !GetDeoptimizedMethodsLock());
InterpreterHandlerTable GetInterpreterHandlerTable() const
REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -289,19 +291,19 @@
// Update the code of a method respecting any installed stubs.
void UpdateMethodsCode(ArtMethod* method, const void* quick_code)
- REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!deoptimized_methods_lock_);
+ REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!GetDeoptimizedMethodsLock());
// Update the code of a native method to a JITed stub.
void UpdateNativeMethodsCodeToJitCode(ArtMethod* method, const void* quick_code)
- REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!deoptimized_methods_lock_);
+ REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!GetDeoptimizedMethodsLock());
// Update the code of a method to the interpreter respecting any installed stubs from debugger.
void UpdateMethodsCodeToInterpreterEntryPoint(ArtMethod* method)
- REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!deoptimized_methods_lock_);
+ REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!GetDeoptimizedMethodsLock());
// Update the code of a method respecting any installed stubs from debugger.
void UpdateMethodsCodeForJavaDebuggable(ArtMethod* method, const void* quick_code)
- REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!deoptimized_methods_lock_);
+ REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!GetDeoptimizedMethodsLock());
// Return the code that we can execute for an invoke including from the JIT.
const void* GetCodeForInvoke(ArtMethod* method) const
@@ -483,7 +485,7 @@
// being returned from.
TwoWordReturn PopInstrumentationStackFrame(Thread* self, uintptr_t* return_pc,
uint64_t* gpr_result, uint64_t* fpr_result)
- REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!deoptimized_methods_lock_);
+ REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!GetDeoptimizedMethodsLock());
// Pops nframes instrumentation frames from the current thread. Returns the return pc for the last
// instrumentation frame that's popped.
@@ -492,10 +494,10 @@
// Call back for configure stubs.
void InstallStubsForClass(mirror::Class* klass) REQUIRES_SHARED(Locks::mutator_lock_)
- REQUIRES(!deoptimized_methods_lock_);
+ REQUIRES(!GetDeoptimizedMethodsLock());
void InstallStubsForMethod(ArtMethod* method)
- REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!deoptimized_methods_lock_);
+ REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!GetDeoptimizedMethodsLock());
// Install instrumentation exit stub on every method of the stack of the given thread.
// This is used by the debugger to cause a deoptimization of the thread's stack after updating
@@ -528,7 +530,7 @@
// becomes the highest instrumentation level required by a client.
void ConfigureStubs(const char* key, InstrumentationLevel desired_instrumentation_level)
REQUIRES(Locks::mutator_lock_, Roles::uninterruptible_)
- REQUIRES(!deoptimized_methods_lock_,
+ REQUIRES(!GetDeoptimizedMethodsLock(),
!Locks::thread_list_lock_,
!Locks::classlinker_classes_lock_);
@@ -583,18 +585,21 @@
// Read barrier-aware utility functions for accessing deoptimized_methods_
bool AddDeoptimizedMethod(ArtMethod* method)
- REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(deoptimized_methods_lock_);
+ REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(GetDeoptimizedMethodsLock());
bool IsDeoptimizedMethod(ArtMethod* method)
- REQUIRES_SHARED(Locks::mutator_lock_, deoptimized_methods_lock_);
+ REQUIRES_SHARED(Locks::mutator_lock_, GetDeoptimizedMethodsLock());
bool RemoveDeoptimizedMethod(ArtMethod* method)
- REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(deoptimized_methods_lock_);
+ REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(GetDeoptimizedMethodsLock());
ArtMethod* BeginDeoptimizedMethod()
- REQUIRES_SHARED(Locks::mutator_lock_, deoptimized_methods_lock_);
+ REQUIRES_SHARED(Locks::mutator_lock_, GetDeoptimizedMethodsLock());
bool IsDeoptimizedMethodsEmpty() const
- REQUIRES_SHARED(Locks::mutator_lock_, deoptimized_methods_lock_);
+ REQUIRES_SHARED(Locks::mutator_lock_, GetDeoptimizedMethodsLock());
void UpdateMethodsCodeImpl(ArtMethod* method, const void* quick_code)
- REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!deoptimized_methods_lock_);
+ REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!GetDeoptimizedMethodsLock());
+ ReaderWriterMutex* GetDeoptimizedMethodsLock() const {
+ return deoptimized_methods_lock_.get();
+ }
// Have we hijacked ArtMethod::code_ so that it calls instrumentation/interpreter code?
bool instrumentation_stubs_installed_;
@@ -676,8 +681,8 @@
// The set of methods being deoptimized (by the debugger) which must be executed with interpreter
// only.
- mutable ReaderWriterMutex deoptimized_methods_lock_ BOTTOM_MUTEX_ACQUIRED_AFTER;
- std::unordered_set<ArtMethod*> deoptimized_methods_ GUARDED_BY(deoptimized_methods_lock_);
+ mutable std::unique_ptr<ReaderWriterMutex> deoptimized_methods_lock_ BOTTOM_MUTEX_ACQUIRED_AFTER;
+ std::unordered_set<ArtMethod*> deoptimized_methods_ GUARDED_BY(GetDeoptimizedMethodsLock());
bool deoptimization_enabled_;
// Current interpreter handler table. This is updated each time the thread state flags are