8251302: Create dedicated OopStorages for Management and Jvmti

Reviewed-by: sspitsyn, dholmes
diff --git a/src/hotspot/share/gc/shared/oopStorageSet.hpp b/src/hotspot/share/gc/shared/oopStorageSet.hpp
index 66c3941..9fd8a3c 100644
--- a/src/hotspot/share/gc/shared/oopStorageSet.hpp
+++ b/src/hotspot/share/gc/shared/oopStorageSet.hpp
@@ -37,7 +37,7 @@
 
 public:
   // Must be updated when new OopStorages are introduced
-  static const uint strong_count = 3;
+  static const uint strong_count = 4 JVMTI_ONLY(+ 1);
   static const uint weak_count = 4 JFR_ONLY(+ 1);
   static const uint all_count = strong_count + weak_count;
 
diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp
index 32c30d3..6ed7079 100644
--- a/src/hotspot/share/prims/jvmtiExport.cpp
+++ b/src/hotspot/share/prims/jvmtiExport.cpp
@@ -29,6 +29,7 @@
 #include "code/nmethod.hpp"
 #include "code/pcDesc.hpp"
 #include "code/scopeDesc.hpp"
+#include "gc/shared/oopStorageSet.hpp"
 #include "interpreter/interpreter.hpp"
 #include "jvmtifiles/jvmtiEnv.hpp"
 #include "logging/log.hpp"
@@ -678,6 +679,18 @@
   }
 }
 
+static OopStorage* _jvmti_oop_storage = NULL;
+
+OopStorage* JvmtiExport::jvmti_oop_storage() {
+  assert(_jvmti_oop_storage != NULL, "not yet initialized");
+  return _jvmti_oop_storage;
+}
+
+void JvmtiExport::initialize_oop_storage() {
+  // OopStorage needs to be created early in startup and unconditionally
+  // because of OopStorageSet static array indices.
+  _jvmti_oop_storage = OopStorageSet::create_strong("JVMTI OopStorage");
+}
 
 void JvmtiExport::post_vm_initialized() {
   EVT_TRIG_TRACE(JVMTI_EVENT_VM_INIT, ("Trg VM init event triggered" ));
@@ -2828,7 +2841,7 @@
       oop obj = _allocated->at(i).resolve();
       _post_callback(JavaThread::current(), obj);
       // Release OopHandle
-      _allocated->at(i).release(Universe::vm_global());
+      _allocated->at(i).release(JvmtiExport::jvmti_oop_storage());
 
     }
     delete _allocated, _allocated = NULL;
@@ -2840,7 +2853,7 @@
   if (_allocated == NULL) {
     _allocated = new (ResourceObj::C_HEAP, mtServiceability) GrowableArray<OopHandle>(1, mtServiceability);
   }
-  _allocated->push(OopHandle(Universe::vm_global(), obj));
+  _allocated->push(OopHandle(JvmtiExport::jvmti_oop_storage(), obj));
 }
 
 // Disable collection of VMObjectAlloc events
diff --git a/src/hotspot/share/prims/jvmtiExport.hpp b/src/hotspot/share/prims/jvmtiExport.hpp
index 6d1a7b6..ce7f410 100644
--- a/src/hotspot/share/prims/jvmtiExport.hpp
+++ b/src/hotspot/share/prims/jvmtiExport.hpp
@@ -47,6 +47,8 @@
 class JvmtiEnv;
 class JvmtiThreadState;
 
+class OopStorage;
+
 #define JVMTI_SUPPORT_FLAG(key)                                           \
   private:                                                                \
   static bool  _##key;                                                    \
@@ -162,6 +164,9 @@
   static void post_dynamic_code_generated_internal(const char *name, const void *code_begin, const void *code_end) NOT_JVMTI_RETURN;
 
   static void post_class_unload_internal(const char *name) NOT_JVMTI_RETURN;
+
+  static void initialize_oop_storage() NOT_JVMTI_RETURN;
+  static OopStorage* jvmti_oop_storage();
  private:
 
   // GenerateEvents support to allow posting of CompiledMethodLoad and
diff --git a/src/hotspot/share/prims/jvmtiImpl.cpp b/src/hotspot/share/prims/jvmtiImpl.cpp
index e377a17..7962fc6 100644
--- a/src/hotspot/share/prims/jvmtiImpl.cpp
+++ b/src/hotspot/share/prims/jvmtiImpl.cpp
@@ -200,19 +200,19 @@
   assert(_method != NULL, "No method for breakpoint.");
   assert(_bci >= 0, "Negative bci for breakpoint.");
   oop class_holder_oop  = _method->method_holder()->klass_holder();
-  _class_holder = OopHandle(Universe::vm_global(), class_holder_oop);
+  _class_holder = OopHandle(JvmtiExport::jvmti_oop_storage(), class_holder_oop);
 }
 
 JvmtiBreakpoint::~JvmtiBreakpoint() {
   if (_class_holder.peek() != NULL) {
-    _class_holder.release(Universe::vm_global());
+    _class_holder.release(JvmtiExport::jvmti_oop_storage());
   }
 }
 
 void JvmtiBreakpoint::copy(JvmtiBreakpoint& bp) {
   _method   = bp._method;
   _bci      = bp._bci;
-  _class_holder = OopHandle(Universe::vm_global(), bp._class_holder.resolve());
+  _class_holder = OopHandle(JvmtiExport::jvmti_oop_storage(), bp._class_holder.resolve());
 }
 
 bool JvmtiBreakpoint::equals(JvmtiBreakpoint& bp) {
diff --git a/src/hotspot/share/runtime/init.cpp b/src/hotspot/share/runtime/init.cpp
index 8b35bfc..9d70147 100644
--- a/src/hotspot/share/runtime/init.cpp
+++ b/src/hotspot/share/runtime/init.cpp
@@ -34,6 +34,7 @@
 #include "logging/log.hpp"
 #include "logging/logTag.hpp"
 #include "memory/universe.hpp"
+#include "prims/jvmtiExport.hpp"
 #include "prims/methodHandles.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/flags/jvmFlag.hpp"
@@ -106,6 +107,7 @@
 
 jint init_globals() {
   management_init();
+  JvmtiExport::initialize_oop_storage();
   bytecodes_init();
   classLoader_init1();
   compilationPolicy_init();
diff --git a/src/hotspot/share/services/threadService.cpp b/src/hotspot/share/services/threadService.cpp
index 53382e2..28e054c 100644
--- a/src/hotspot/share/services/threadService.cpp
+++ b/src/hotspot/share/services/threadService.cpp
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "classfile/systemDictionary.hpp"
+#include "gc/shared/oopStorageSet.hpp"
 #include "memory/allocation.hpp"
 #include "memory/heapInspection.hpp"
 #include "memory/oopFactory.hpp"
@@ -67,6 +68,9 @@
 
 static const int INITIAL_ARRAY_SIZE = 10;
 
+// OopStorage for thread stack sampling
+static OopStorage* _thread_service_storage = NULL;
+
 void ThreadService::init() {
   EXCEPTION_MARK;
 
@@ -95,6 +99,9 @@
   }
 
   _thread_allocated_memory_enabled = true; // Always on, so enable it
+
+  // Initialize OopStorage for thread stack sampling walking
+  _thread_service_storage = OopStorageSet::create_strong("ThreadService OopStorage");
 }
 
 void ThreadService::reset_peak_thread_count() {
@@ -563,7 +570,7 @@
 StackFrameInfo::StackFrameInfo(javaVFrame* jvf, bool with_lock_info) {
   _method = jvf->method();
   _bci = jvf->bci();
-  _class_holder = OopHandle(Universe::vm_global(), _method->method_holder()->klass_holder());
+  _class_holder = OopHandle(_thread_service_storage, _method->method_holder()->klass_holder());
   _locked_monitors = NULL;
   if (with_lock_info) {
     Thread* current_thread = Thread::current();
@@ -576,7 +583,7 @@
       for (int i = 0; i < length; i++) {
         MonitorInfo* monitor = list->at(i);
         assert(monitor->owner() != NULL, "This monitor must have an owning object");
-        _locked_monitors->append(OopHandle(Universe::vm_global(), monitor->owner()));
+        _locked_monitors->append(OopHandle(_thread_service_storage, monitor->owner()));
       }
     }
   }
@@ -585,11 +592,11 @@
 StackFrameInfo::~StackFrameInfo() {
   if (_locked_monitors != NULL) {
     for (int i = 0; i < _locked_monitors->length(); i++) {
-      _locked_monitors->at(i).release(Universe::vm_global());
+      _locked_monitors->at(i).release(_thread_service_storage);
     }
     delete _locked_monitors;
   }
-  _class_holder.release(Universe::vm_global());
+  _class_holder.release(_thread_service_storage);
 }
 
 void StackFrameInfo::metadata_do(void f(Metadata*)) {
@@ -640,7 +647,7 @@
 }
 
 void ThreadStackTrace::add_jni_locked_monitor(oop object) {
-  _jni_locked_monitors->append(OopHandle(Universe::vm_global(), object));
+  _jni_locked_monitors->append(OopHandle(_thread_service_storage, object));
 }
 
 ThreadStackTrace::~ThreadStackTrace() {
@@ -650,7 +657,7 @@
   delete _frames;
   if (_jni_locked_monitors != NULL) {
     for (int i = 0; i < _jni_locked_monitors->length(); i++) {
-      _jni_locked_monitors->at(i).release(Universe::vm_global());
+      _jni_locked_monitors->at(i).release(_thread_service_storage);
     }
     delete _jni_locked_monitors;
   }
@@ -834,13 +841,13 @@
 
 ThreadConcurrentLocks::~ThreadConcurrentLocks() {
   for (int i = 0; i < _owned_locks->length(); i++) {
-    _owned_locks->at(i).release(Universe::vm_global());
+    _owned_locks->at(i).release(_thread_service_storage);
   }
   delete _owned_locks;
 }
 
 void ThreadConcurrentLocks::add_lock(instanceOop o) {
-  _owned_locks->append(OopHandle(Universe::vm_global(), o));
+  _owned_locks->append(OopHandle(_thread_service_storage, o));
 }
 
 ThreadStatistics::ThreadStatistics() {
@@ -857,7 +864,7 @@
 void ThreadSnapshot::initialize(ThreadsList * t_list, JavaThread* thread) {
   _thread = thread;
   oop threadObj = thread->threadObj();
-  _threadObj = OopHandle(Universe::vm_global(), threadObj);
+  _threadObj = OopHandle(_thread_service_storage, threadObj);
 
   ThreadStatistics* stat = thread->get_thread_stat();
   _contended_enter_ticks = stat->contended_enter_ticks();
@@ -910,10 +917,10 @@
   }
 
   if (blocker_object != NULL) {
-    _blocker_object = OopHandle(Universe::vm_global(), blocker_object);
+    _blocker_object = OopHandle(_thread_service_storage, blocker_object);
   }
   if (blocker_object_owner != NULL) {
-    _blocker_object_owner = OopHandle(Universe::vm_global(), blocker_object_owner);
+    _blocker_object_owner = OopHandle(_thread_service_storage, blocker_object_owner);
   }
 }
 
@@ -921,9 +928,9 @@
 oop ThreadSnapshot::blocker_object_owner() const     { return _blocker_object_owner.resolve(); }
 
 ThreadSnapshot::~ThreadSnapshot() {
-  _blocker_object.release(Universe::vm_global());
-  _blocker_object_owner.release(Universe::vm_global());
-  _threadObj.release(Universe::vm_global());
+  _blocker_object.release(_thread_service_storage);
+  _blocker_object_owner.release(_thread_service_storage);
+  _threadObj.release(_thread_service_storage);
 
   delete _stack_trace;
   delete _concurrent_locks;
diff --git a/test/jdk/jdk/jfr/event/gc/collection/TestG1ParallelPhases.java b/test/jdk/jdk/jfr/event/gc/collection/TestG1ParallelPhases.java
index 90667c9..06837a0 100644
--- a/test/jdk/jdk/jfr/event/gc/collection/TestG1ParallelPhases.java
+++ b/test/jdk/jdk/jfr/event/gc/collection/TestG1ParallelPhases.java
@@ -95,6 +95,8 @@
             "VM Global",
             "JNI Global",
             "Thread OopStorage",
+            "ThreadService OopStorage",
+            "JVMTI OopStorage",
             "CLDGRoots",
             "CMRefRoots",
             "MergeER",