Use r/w Mutex to control access to jvmtiEnv event information.
We were previously relying on the mutator_lock_ to provide
synchronization when accessing control information for some jvmti
events. This was not fully thread safe. To fix this problem we
instead use a ReaderWriterMutex to control access to this data.
Refactorings to allow all methods to have appropriate lock annotations
will follow in later CL (see bug).
Performance Impact:
Tested performance by running main piece of test 993 10 times.
Printing redirected to /dev/null.
Total of ~270 breakpoints are executed.
Before: 2.62 seconds / run
After: 2.72 seconds / run
Test: ./test.py --host -j50
Test: ./art/tools/run-prebuilt-libjdwp-tests.sh --debug
Bug: 62821960
Bug: 67958496
Bug: 67962439
Change-Id: Ib2935c2e10bc2113e8430b49a9a7b76144e4235e
diff --git a/openjdkjvmti/events-inl.h b/openjdkjvmti/events-inl.h
index ab8e6de..3973e94 100644
--- a/openjdkjvmti/events-inl.h
+++ b/openjdkjvmti/events-inl.h
@@ -21,6 +21,7 @@
#include <type_traits>
#include <tuple>
+#include "base/mutex-inl.h"
#include "events.h"
#include "jni_internal.h"
#include "nativehelper/ScopedLocalRef.h"
@@ -276,6 +277,7 @@
jthread jni_thread ATTRIBUTE_UNUSED,
jmethodID jmethod,
jlocation location) const {
+ art::ReaderMutexLock lk(art::Thread::Current(), env->event_info_mutex_);
art::ArtMethod* method = art::jni::DecodeArtMethod(jmethod);
return ShouldDispatchOnThread<ArtJvmtiEvent::kBreakpoint>(env, thread) &&
env->breakpoints.find({method, location}) != env->breakpoints.end();
@@ -292,6 +294,7 @@
const art::ShadowFrame* frame) const {
// Search for the frame. Do this before checking if we need to send the event so that we don't
// have to deal with use-after-free or the frames being reallocated later.
+ art::WriterMutexLock lk(art::Thread::Current(), env->event_info_mutex_);
return env->notify_frames.erase(frame) != 0 &&
ShouldDispatchOnThread<ArtJvmtiEvent::kFramePop>(env, thread);
}
@@ -313,6 +316,7 @@
jfieldID field,
char type_char ATTRIBUTE_UNUSED,
jvalue val ATTRIBUTE_UNUSED) const {
+ art::ReaderMutexLock lk(art::Thread::Current(), env->event_info_mutex_);
return ShouldDispatchOnThread<ArtJvmtiEvent::kFieldModification>(env, thread) &&
env->modify_watched_fields.find(
art::jni::DecodeArtField(field)) != env->modify_watched_fields.end();
@@ -329,6 +333,7 @@
jclass field_klass ATTRIBUTE_UNUSED,
jobject object ATTRIBUTE_UNUSED,
jfieldID field) const {
+ art::ReaderMutexLock lk(art::Thread::Current(), env->event_info_mutex_);
return ShouldDispatchOnThread<ArtJvmtiEvent::kFieldAccess>(env, thread) &&
env->access_watched_fields.find(
art::jni::DecodeArtField(field)) != env->access_watched_fields.end();