Revert "Revert "Make JVMTI DisposeEnvironment and GetEnv thread safe.""

This reverts commit af9341087aab0146b8323ece156bde8130948465.

We needed to allow TopLockLevel locks to be acquired when the
mutator_lock_ is exclusive held. This is required for spec
conformance. To ensure there are no deadlocks the mutator_lock_ is the
only lock level with this exception and one cannot acquire the
mutator_lock_ when one holds any kTopLockLevel locks.

Reason for revert: Fixed issue causing test 913 failure in art-gc-gss-tlab
Test: ART_DEFAULT_GC_TYPE=GSS \
      ART_USE_TLAB=true \
      ART_USE_READ_BARRIER=false
      ./test.py --host -j50
Bug: 69465262

Change-Id: Ic1a4d9bb3ff64382ba7ae22ba27a4f44628ed095
diff --git a/openjdkjvmti/events.h b/openjdkjvmti/events.h
index a99ed7b..c73215f 100644
--- a/openjdkjvmti/events.h
+++ b/openjdkjvmti/events.h
@@ -158,6 +158,10 @@
   void HandleChangedCapabilities(const jvmtiCapabilities& caps, bool caps_added);
 };
 
+namespace impl {
+template <ArtJvmtiEvent kEvent> struct EventHandlerFunc { };
+}  // namespace impl
+
 // Helper class for event handling.
 class EventHandler {
  public:
@@ -169,10 +173,10 @@
 
   // Register an env. It is assumed that this happens on env creation, that is, no events are
   // enabled, yet.
-  void RegisterArtJvmTiEnv(ArtJvmTiEnv* env);
+  void RegisterArtJvmTiEnv(ArtJvmTiEnv* env) REQUIRES(!envs_lock_);
 
   // Remove an env.
-  void RemoveArtJvmTiEnv(ArtJvmTiEnv* env);
+  void RemoveArtJvmTiEnv(ArtJvmTiEnv* env) REQUIRES(!envs_lock_);
 
   bool IsEventEnabledAnywhere(ArtJvmtiEvent event) const {
     if (!EventMask::EventIsInRange(event)) {
@@ -184,13 +188,15 @@
   jvmtiError SetEvent(ArtJvmTiEnv* env,
                       art::Thread* thread,
                       ArtJvmtiEvent event,
-                      jvmtiEventMode mode);
+                      jvmtiEventMode mode)
+      REQUIRES(!envs_lock_);
 
   // Dispatch event to all registered environments. Since this one doesn't have a JNIEnv* it doesn't
   // matter if it has the mutator_lock.
   template <ArtJvmtiEvent kEvent, typename ...Args>
   ALWAYS_INLINE
-  inline void DispatchEvent(art::Thread* thread, Args... args) const;
+  inline void DispatchEvent(art::Thread* thread, Args... args) const
+      REQUIRES(!envs_lock_);
 
   // Dispatch event to all registered environments stashing exceptions as needed. This works since
   // JNIEnv* is always the second argument if it is passed to an event. Needed since C++ does not
@@ -200,7 +206,8 @@
   // the event to allocate local references.
   template <ArtJvmtiEvent kEvent, typename ...Args>
   ALWAYS_INLINE
-  inline void DispatchEvent(art::Thread* thread, JNIEnv* jnienv, Args... args) const;
+  inline void DispatchEvent(art::Thread* thread, JNIEnv* jnienv, Args... args) const
+      REQUIRES(!envs_lock_);
 
   // Tell the event handler capabilities were added/lost so it can adjust the sent events.If
   // caps_added is true then caps is all the newly set capabilities of the jvmtiEnv. If it is false
@@ -208,30 +215,50 @@
   ALWAYS_INLINE
   inline void HandleChangedCapabilities(ArtJvmTiEnv* env,
                                         const jvmtiCapabilities& caps,
-                                        bool added);
+                                        bool added)
+      REQUIRES(!envs_lock_);
 
   // Dispatch event to the given environment, only.
   template <ArtJvmtiEvent kEvent, typename ...Args>
   ALWAYS_INLINE
-  inline void DispatchEventOnEnv(
-      ArtJvmTiEnv* env, art::Thread* thread, JNIEnv* jnienv, Args... args) const;
+  inline void DispatchEventOnEnv(ArtJvmTiEnv* env,
+                                 art::Thread* thread,
+                                 JNIEnv* jnienv,
+                                 Args... args) const
+      REQUIRES(!envs_lock_);
 
   // Dispatch event to the given environment, only.
   template <ArtJvmtiEvent kEvent, typename ...Args>
   ALWAYS_INLINE
-  inline void DispatchEventOnEnv(ArtJvmTiEnv* env, art::Thread* thread, Args... args) const;
+  inline void DispatchEventOnEnv(ArtJvmTiEnv* env, art::Thread* thread, Args... args) const
+      REQUIRES(!envs_lock_);
 
  private:
+  template <ArtJvmtiEvent kEvent, typename ...Args>
+  ALWAYS_INLINE
+  inline std::vector<impl::EventHandlerFunc<kEvent>> CollectEvents(art::Thread* thread,
+                                                                   Args... args) const
+      REQUIRES(!envs_lock_);
+
   template <ArtJvmtiEvent kEvent>
   ALWAYS_INLINE
-  static inline bool ShouldDispatchOnThread(ArtJvmTiEnv* env, art::Thread* thread);
+  inline bool ShouldDispatchOnThread(ArtJvmTiEnv* env, art::Thread* thread) const;
 
   template <ArtJvmtiEvent kEvent, typename ...Args>
   ALWAYS_INLINE
-  static inline void ExecuteCallback(ArtJvmTiEnv* env, Args... args);
+  static inline void ExecuteCallback(impl::EventHandlerFunc<kEvent> handler,
+                                     JNIEnv* env,
+                                     Args... args)
+      REQUIRES(!envs_lock_);
 
   template <ArtJvmtiEvent kEvent, typename ...Args>
   ALWAYS_INLINE
+  static inline void ExecuteCallback(impl::EventHandlerFunc<kEvent> handler, Args... args)
+      REQUIRES(!envs_lock_);
+
+  // Public for use to collect dispatches
+  template <ArtJvmtiEvent kEvent, typename ...Args>
+  ALWAYS_INLINE
   inline bool ShouldDispatch(ArtJvmTiEnv* env, art::Thread* thread, Args... args) const;
 
   ALWAYS_INLINE
@@ -241,7 +268,9 @@
 
   // Recalculates the event mask for the given event.
   ALWAYS_INLINE
-  inline void RecalculateGlobalEventMask(ArtJvmtiEvent event);
+  inline void RecalculateGlobalEventMask(ArtJvmtiEvent event) REQUIRES(!envs_lock_);
+  ALWAYS_INLINE
+  inline void RecalculateGlobalEventMaskLocked(ArtJvmtiEvent event) REQUIRES(envs_lock_);
 
   template <ArtJvmtiEvent kEvent>
   ALWAYS_INLINE inline void DispatchClassFileLoadHookEvent(art::Thread* thread,
@@ -253,7 +282,8 @@
                                                            jint class_data_len,
                                                            const unsigned char* class_data,
                                                            jint* new_class_data_len,
-                                                           unsigned char** new_class_data) const;
+                                                           unsigned char** new_class_data) const
+      REQUIRES(!envs_lock_);
 
   void HandleEventType(ArtJvmtiEvent event, bool enable);
   void HandleLocalAccessCapabilityAdded();
@@ -261,10 +291,13 @@
 
   bool OtherMonitorEventsEnabledAnywhere(ArtJvmtiEvent event);
 
-  // List of all JvmTiEnv objects that have been created, in their creation order.
-  // NB Some elements might be null representing envs that have been deleted. They should be skipped
-  // anytime this list is used.
-  std::vector<ArtJvmTiEnv*> envs;
+  // List of all JvmTiEnv objects that have been created, in their creation order. It is a std::list
+  // since we mostly access it by iterating over the entire thing, only ever append to the end, and
+  // need to be able to remove arbitrary elements from it.
+  std::list<ArtJvmTiEnv*> envs GUARDED_BY(envs_lock_);
+
+  // Top level lock. Nothing at all should be held when we lock this.
+  mutable art::Mutex envs_lock_ ACQUIRED_BEFORE(art::Locks::instrument_entrypoints_lock_);
 
   // A union of all enabled events, anywhere.
   EventMask global_mask;