8227054: ServiceThread needs to know about all OopStorage objects
authorkbarrett
Wed, 21 Aug 2019 18:42:30 -0400
changeset 57828 35db8fba55f9
parent 57827 425412369353
child 57829 58891103f9cc
8227054: ServiceThread needs to know about all OopStorage objects 8227053: ServiceThread cleanup of OopStorage is missing some Summary: OopStorages provides named access and iteration. Reviewed-by: eosterlund, pliden, coleenp
src/hotspot/share/classfile/stringTable.cpp
src/hotspot/share/classfile/stringTable.hpp
src/hotspot/share/classfile/systemDictionary.cpp
src/hotspot/share/classfile/systemDictionary.hpp
src/hotspot/share/gc/shared/oopStorageParState.hpp
src/hotspot/share/gc/shared/oopStorageSet.cpp
src/hotspot/share/gc/shared/oopStorageSet.hpp
src/hotspot/share/gc/shared/weakProcessor.cpp
src/hotspot/share/gc/shared/weakProcessor.inline.hpp
src/hotspot/share/gc/shared/weakProcessorPhaseTimes.cpp
src/hotspot/share/gc/shared/weakProcessorPhaseTimes.hpp
src/hotspot/share/gc/shared/weakProcessorPhases.cpp
src/hotspot/share/gc/shared/weakProcessorPhases.hpp
src/hotspot/share/gc/z/zRootsIterator.cpp
src/hotspot/share/jvmci/jvmci.cpp
src/hotspot/share/jvmci/jvmci.hpp
src/hotspot/share/memory/universe.cpp
src/hotspot/share/oops/weakHandle.cpp
src/hotspot/share/prims/resolvedMethodTable.cpp
src/hotspot/share/prims/resolvedMethodTable.hpp
src/hotspot/share/runtime/init.cpp
src/hotspot/share/runtime/jniHandles.cpp
src/hotspot/share/runtime/jniHandles.hpp
src/hotspot/share/runtime/mutexLocker.cpp
src/hotspot/share/runtime/mutexLocker.hpp
src/hotspot/share/runtime/serviceThread.cpp
test/hotspot/gtest/gc/shared/test_oopStorageSet.cpp
test/hotspot/jtreg/gc/g1/TestGCLogMessages.java
--- a/src/hotspot/share/classfile/stringTable.cpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/classfile/stringTable.cpp	Wed Aug 21 18:42:30 2019 -0400
@@ -30,6 +30,7 @@
 #include "classfile/systemDictionary.hpp"
 #include "gc/shared/collectedHeap.hpp"
 #include "gc/shared/oopStorage.inline.hpp"
+#include "gc/shared/oopStorageSet.hpp"
 #include "logging/log.hpp"
 #include "logging/logStream.hpp"
 #include "memory/allocation.inline.hpp"
@@ -86,7 +87,6 @@
 volatile bool StringTable::_needs_rehashing = false;
 
 volatile size_t StringTable::_uncleaned_items_count = 0;
-OopStorage* StringTable::_weak_handles = NULL;
 
 static size_t _current_size = 0;
 static volatile size_t _items_count = 0;
@@ -206,9 +206,6 @@
 }
 
 void StringTable::create_table() {
-  _weak_handles = new OopStorage("StringTable weak",
-                                 StringTableWeakAlloc_lock,
-                                 StringTableWeakActive_lock);
   size_t start_size_log_2 = ceil_log2(StringTableSize);
   _current_size = ((size_t)1) << start_size_log_2;
   log_trace(stringtable)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")",
@@ -388,7 +385,7 @@
 
 void StringTable::oops_do(OopClosure* f) {
   assert(f != NULL, "No closure");
-  _weak_handles->oops_do(f);
+  OopStorageSet::string_table_weak()->oops_do(f);
 }
 
 // Concurrent work
--- a/src/hotspot/share/classfile/stringTable.hpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/classfile/stringTable.hpp	Wed Aug 21 18:42:30 2019 -0400
@@ -25,7 +25,6 @@
 #ifndef SHARE_CLASSFILE_STRINGTABLE_HPP
 #define SHARE_CLASSFILE_STRINGTABLE_HPP
 
-#include "gc/shared/oopStorage.hpp"
 #include "memory/allocation.hpp"
 #include "memory/padded.hpp"
 #include "oops/oop.hpp"
@@ -33,6 +32,7 @@
 #include "utilities/tableStatistics.hpp"
 
 class CompactHashtableWriter;
+class JavaThread;
 class SerializeClosure;
 
 class StringTable;
@@ -51,8 +51,6 @@
   // Set if one bucket is out of balance due to hash algorithm deficiency
   static volatile bool _needs_rehashing;
 
-  static OopStorage* _weak_handles;
-
   static void grow(JavaThread* jt);
   static void clean_dead_entries(JavaThread* jt);
 
@@ -78,8 +76,6 @@
   static size_t table_size();
   static TableStatistics get_table_statistics();
 
-  static OopStorage* weak_storage() { return _weak_handles; }
-
   static void create_table();
 
   static void do_concurrent_work(JavaThread* jt);
--- a/src/hotspot/share/classfile/systemDictionary.cpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/classfile/systemDictionary.cpp	Wed Aug 21 18:42:30 2019 -0400
@@ -47,6 +47,7 @@
 #include "compiler/compileBroker.hpp"
 #include "gc/shared/gcTraceTime.inline.hpp"
 #include "gc/shared/oopStorage.inline.hpp"
+#include "gc/shared/oopStorageSet.hpp"
 #include "interpreter/bytecodeStream.hpp"
 #include "interpreter/interpreter.hpp"
 #include "jfr/jfrEvents.hpp"
@@ -114,10 +115,6 @@
 
 const int defaultProtectionDomainCacheSize = 1009;
 
-OopStorage* SystemDictionary::_vm_global_oop_storage = NULL;
-OopStorage* SystemDictionary::_vm_weak_oop_storage = NULL;
-
-
 // ----------------------------------------------------------------------------
 // Java-level SystemLoader and PlatformLoader
 
@@ -1855,7 +1852,7 @@
   invoke_method_table()->oops_do(f);
 
   if (include_handles) {
-    vm_global_oop_storage()->oops_do(f);
+    OopStorageSet::vm_global()->oops_do(f);
   }
 }
 
@@ -2896,25 +2893,3 @@
     return 0;
   }
 }
-
-void SystemDictionary::initialize_oop_storage() {
-  _vm_global_oop_storage =
-    new OopStorage("VM Global Oop Handles",
-                   VMGlobalAlloc_lock,
-                   VMGlobalActive_lock);
-
-  _vm_weak_oop_storage =
-    new OopStorage("VM Weak Oop Handles",
-                   VMWeakAlloc_lock,
-                   VMWeakActive_lock);
-}
-
-OopStorage* SystemDictionary::vm_global_oop_storage() {
-  assert(_vm_global_oop_storage != NULL, "Uninitialized");
-  return _vm_global_oop_storage;
-}
-
-OopStorage* SystemDictionary::vm_weak_oop_storage() {
-  assert(_vm_weak_oop_storage != NULL, "Uninitialized");
-  return _vm_weak_oop_storage;
-}
--- a/src/hotspot/share/classfile/systemDictionary.hpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/classfile/systemDictionary.hpp	Wed Aug 21 18:42:30 2019 -0400
@@ -84,7 +84,6 @@
 class ProtectionDomainCacheTable;
 class ProtectionDomainCacheEntry;
 class GCTimer;
-class OopStorage;
 
 #define WK_KLASS_ENUM_NAME(kname)    kname##_knum
 
@@ -349,7 +348,7 @@
 
   // Applies "f->do_oop" to all root oops in the system dictionary.
   // If include_handles is true (the default), then the handles in the
-  // storage object returned by vm_global_oop_storage() are included.
+  // vm_global OopStorage object are included.
   static void oops_do(OopClosure* f, bool include_handles = true);
 
   // System loader lock
@@ -565,10 +564,6 @@
   // ProtectionDomain cache
   static ProtectionDomainCacheTable*   _pd_cache_table;
 
-  // VM OopStorage objects.
-  static OopStorage*             _vm_global_oop_storage;
-  static OopStorage*             _vm_weak_oop_storage;
-
 protected:
   static void validate_protection_domain(InstanceKlass* klass,
                                          Handle class_loader,
@@ -623,10 +618,6 @@
     return !m->is_public() && m->method_holder() == SystemDictionary::Object_klass();
   }
 
-  static void initialize_oop_storage();
-  static OopStorage* vm_global_oop_storage();
-  static OopStorage* vm_weak_oop_storage();
-
 protected:
   // Setup link to hierarchy
   static void add_to_hierarchy(InstanceKlass* k, TRAPS);
--- a/src/hotspot/share/gc/shared/oopStorageParState.hpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/gc/shared/oopStorageParState.hpp	Wed Aug 21 18:42:30 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -153,6 +153,8 @@
                 bool concurrent);
   ~BasicParState();
 
+  const OopStorage* storage() const { return _storage; }
+
   template<bool is_const, typename F> void iterate(F f);
 
   static uint default_estimated_thread_count(bool concurrent);
@@ -172,6 +174,7 @@
     _basic_state(storage, estimated_thread_count, concurrent)
   {}
 
+  const OopStorage* storage() const { return _basic_state.storage(); }
   template<typename F> void iterate(F f);
   template<typename Closure> void oops_do(Closure* cl);
 };
@@ -186,6 +189,7 @@
     _basic_state(storage, estimated_thread_count, false)
   {}
 
+  const OopStorage* storage() const { return _basic_state.storage(); }
   template<typename F> void iterate(F f);
   template<typename Closure> void oops_do(Closure* cl);
   template<typename Closure> void weak_oops_do(Closure* cl);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/oopStorageSet.cpp	Wed Aug 21 18:42:30 2019 -0400
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/shared/oopStorage.hpp"
+#include "gc/shared/oopStorageSet.hpp"
+#include "runtime/mutex.hpp"
+#include "runtime/os.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/macros.hpp"
+
+// +1 for NULL singular entry.
+OopStorage* OopStorageSet::storages[all_count + 1] = {};
+
+static Mutex* make_oopstorage_mutex(const char* storage_name,
+                                    const char* kind,
+                                    int rank) {
+  char name[256];
+  os::snprintf(name, sizeof(name), "%s %s lock", storage_name, kind);
+  return new PaddedMutex(rank, name, true, Mutex::_safepoint_check_never);
+}
+
+static OopStorage* make_oopstorage(const char* name) {
+  Mutex* alloc = make_oopstorage_mutex(name, "alloc", Mutex::oopstorage);
+  Mutex* active = make_oopstorage_mutex(name, "active", Mutex::oopstorage - 1);
+  return new OopStorage(name, alloc, active);
+}
+
+void OopStorageSet::initialize() {
+  storages[jni_global_index]        = make_oopstorage("JNI global");
+  storages[vm_global_index]         = make_oopstorage("VM global");
+  storages[jni_weak_index]          = make_oopstorage("JNI weak");
+  storages[vm_weak_index]           = make_oopstorage("VM weak");
+  storages[string_table_weak_index] = make_oopstorage("StringTable weak");
+  storages[resolved_method_table_weak_index] =
+    make_oopstorage("ResolvedMethodTable weak");
+
+  // Ensure we have all of them.
+  STATIC_ASSERT(all_count == 6);
+  assert(storages[singular_index] == NULL, "postcondition");
+#ifdef ASSERT
+  for (uint i = all_start; i < all_end; ++i) {
+    assert(storages[i] != NULL, "postcondition");
+  }
+#endif // ASSERT
+}
+
+void oopstorage_init() {
+  OopStorageSet::initialize();
+}
+
+#ifdef ASSERT
+
+void OopStorageSet::verify_initialized(uint index) {
+  assert(storages[index] != NULL, "oopstorage_init not yet called");
+}
+
+void OopStorageSet::Iterator::verify_nonsingular() const {
+  assert(_category != singular, "precondition");
+}
+
+void OopStorageSet::Iterator::verify_category_match(const Iterator& other) const {
+  verify_nonsingular();
+  assert(_category == other._category, "precondition");
+}
+
+void OopStorageSet::Iterator::verify_dereferenceable() const {
+  verify_nonsingular();
+  assert(!is_end(), "precondition");
+}
+
+#endif // ASSERT
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/oopStorageSet.hpp	Wed Aug 21 18:42:30 2019 -0400
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_GC_SHARED_OOPSTORAGESET_HPP
+#define SHARE_GC_SHARED_OOPSTORAGESET_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/macros.hpp"
+
+class OopStorage;
+
+class OopStorageSet : public AllStatic {
+private:
+  friend void oopstorage_init();
+
+  enum {
+    singular_index,             // For singular iterator.
+
+    all_start,
+
+    // Strong
+    strong_start = all_start,
+    jni_global_index = strong_start,
+    vm_global_index,
+    strong_end,
+
+    // Weak
+    weak_start = strong_end,
+    jni_weak_index = weak_start,
+    vm_weak_index,
+    string_table_weak_index,
+    resolved_method_table_weak_index,
+    weak_end,
+
+    all_end = weak_end
+  };
+
+  static OopStorage* storages[all_end];
+
+  static void verify_initialized(uint index) NOT_DEBUG_RETURN;
+
+  static OopStorage* storage(uint index) {
+    verify_initialized(index);
+    return storages[index];
+  }
+
+  static void initialize();
+
+public:
+  class Iterator;
+
+  static const uint strong_count = (strong_end - strong_start);
+  static const uint weak_count = (weak_end - weak_start);
+  static const uint all_count = (all_end - all_start);
+
+  static Iterator strong_iterator();
+  static Iterator weak_iterator();
+  static Iterator all_iterator();
+
+  // Strong
+  static OopStorage* jni_global() { return storage(jni_global_index); }
+  static OopStorage* vm_global()  { return storage(vm_global_index); }
+
+  // Weak
+  static OopStorage* jni_weak()   { return storage(jni_weak_index); }
+  static OopStorage* vm_weak()    { return storage(vm_weak_index); }
+
+  static OopStorage* string_table_weak() {
+    return storage(string_table_weak_index);
+  }
+
+  static OopStorage* resolved_method_table_weak() {
+    return storage(resolved_method_table_weak_index);
+  }
+};
+
+class OopStorageSet::Iterator {
+  friend class OopStorageSet;
+
+  enum Category { singular, strong, weak, all };
+
+  uint _index;
+  uint _limit;
+  DEBUG_ONLY(Category _category;)
+
+  Iterator(uint index, uint limit, Category category) :
+    _index(index), _limit(limit) DEBUG_ONLY(COMMA _category(category)) {}
+
+  void verify_nonsingular() const NOT_DEBUG_RETURN;
+  void verify_category_match(const Iterator& other) const NOT_DEBUG_RETURN;
+  void verify_dereferenceable() const NOT_DEBUG_RETURN;
+
+public:
+  // Construct a singular iterator for later assignment.  The only valid
+  // operations are destruction and assignment.
+  Iterator() :
+    _index(singular_index),
+    _limit(singular_index)
+    DEBUG_ONLY(COMMA _category(singular)) {}
+
+  bool is_end() const {
+    verify_nonsingular();
+    return _index == _limit;
+  }
+
+  bool operator==(const Iterator& other) const {
+    verify_category_match(other);
+    return _index == other._index;
+  }
+
+  bool operator!=(const Iterator& other) const {
+    return !operator==(other);
+  }
+
+  OopStorage* operator*() const {
+    verify_dereferenceable();
+    return storage(_index);
+  }
+
+  OopStorage* operator->() const {
+    return operator*();
+  }
+
+  Iterator& operator++() {
+    verify_dereferenceable();
+    ++_index;
+    return *this;
+  }
+
+  Iterator operator++(int) {
+    Iterator result = *this;
+    operator++();
+    return result;
+  }
+
+  Iterator begin() const {
+    verify_nonsingular();
+    return *this;
+  }
+
+  Iterator end() const {
+    verify_nonsingular();
+    Iterator result = *this;
+    result._index = _limit;
+    return result;
+  }
+};
+
+inline OopStorageSet::Iterator OopStorageSet::strong_iterator() {
+  return Iterator(strong_start, strong_end, Iterator::strong);
+}
+
+inline OopStorageSet::Iterator OopStorageSet::weak_iterator() {
+  return Iterator(weak_start, weak_end, Iterator::weak);
+}
+
+inline OopStorageSet::Iterator OopStorageSet::all_iterator() {
+  return Iterator(all_start, all_end, Iterator::all);
+}
+
+#endif // SHARE_GC_SHARED_OOPSTORAGESET_HPP
--- a/src/hotspot/share/gc/shared/weakProcessor.cpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/gc/shared/weakProcessor.cpp	Wed Aug 21 18:42:30 2019 -0400
@@ -26,6 +26,7 @@
 #include "classfile/stringTable.hpp"
 #include "gc/shared/oopStorage.inline.hpp"
 #include "gc/shared/oopStorageParState.inline.hpp"
+#include "gc/shared/oopStorageSet.hpp"
 #include "gc/shared/weakProcessor.inline.hpp"
 #include "gc/shared/weakProcessorPhases.hpp"
 #include "gc/shared/weakProcessorPhaseTimes.hpp"
@@ -38,11 +39,11 @@
 template <typename Container>
 class OopsDoAndReportCounts {
 public:
-  void operator()(BoolObjectClosure* is_alive, OopClosure* keep_alive, WeakProcessorPhase phase) {
+  void operator()(BoolObjectClosure* is_alive, OopClosure* keep_alive, OopStorage* storage) {
     Container::reset_dead_counter();
 
     CountingSkippedIsAliveClosure<BoolObjectClosure, OopClosure> cl(is_alive, keep_alive);
-    WeakProcessorPhases::oop_storage(phase)->oops_do(&cl);
+    storage->oops_do(&cl);
 
     Container::inc_dead_counter(cl.num_dead() + cl.num_skipped());
     Container::finish_dead_counter();
@@ -50,17 +51,19 @@
 };
 
 void WeakProcessor::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive) {
-  FOR_EACH_WEAK_PROCESSOR_PHASE(phase) {
-    if (WeakProcessorPhases::is_serial(phase)) {
-      WeakProcessorPhases::processor(phase)(is_alive, keep_alive);
+  WeakProcessorPhases::Iterator pit = WeakProcessorPhases::serial_iterator();
+  for ( ; !pit.is_end(); ++pit) {
+    WeakProcessorPhases::processor(*pit)(is_alive, keep_alive);
+  }
+
+  OopStorageSet::Iterator it = OopStorageSet::weak_iterator();
+  for ( ; !it.is_end(); ++it) {
+    if (OopStorageSet::string_table_weak() == *it) {
+      OopsDoAndReportCounts<StringTable>()(is_alive, keep_alive, *it);
+    } else if (OopStorageSet::resolved_method_table_weak() == *it) {
+      OopsDoAndReportCounts<ResolvedMethodTable>()(is_alive, keep_alive, *it);
     } else {
-      if (WeakProcessorPhases::is_stringtable(phase)) {
-        OopsDoAndReportCounts<StringTable>()(is_alive, keep_alive, phase);
-      } else if (WeakProcessorPhases::is_resolved_method_table(phase)){
-        OopsDoAndReportCounts<ResolvedMethodTable>()(is_alive, keep_alive, phase);
-      } else {
-        WeakProcessorPhases::oop_storage(phase)->weak_oops_do(is_alive, keep_alive);
-      }
+      it->weak_oops_do(is_alive, keep_alive);
     }
   }
 }
@@ -86,8 +89,9 @@
   // and development oriented, so not allocating any threads
   // specifically for them is okay.
   size_t ref_count = 0;
-  FOR_EACH_WEAK_PROCESSOR_OOP_STORAGE_PHASE(phase) {
-    ref_count += WeakProcessorPhases::oop_storage(phase)->allocation_count();
+  OopStorageSet::Iterator it = OopStorageSet::weak_iterator();
+  for ( ; !it.is_end(); ++it) {
+    ref_count += it->allocation_count();
   }
 
   // +1 to (approx) round up the ref per thread division.
@@ -106,14 +110,16 @@
     _phase_times->set_active_workers(_nworkers);
   }
 
-  uint storage_count = WeakProcessorPhases::oop_storage_phase_count;
+  uint storage_count = WeakProcessorPhases::oopstorage_phase_count;
   _storage_states = NEW_C_HEAP_ARRAY(StorageState, storage_count, mtGC);
 
-  StorageState* states = _storage_states;
-  FOR_EACH_WEAK_PROCESSOR_OOP_STORAGE_PHASE(phase) {
-    OopStorage* storage = WeakProcessorPhases::oop_storage(phase);
-    new (states++) StorageState(storage, _nworkers);
+  StorageState* cur_state = _storage_states;
+  OopStorageSet::Iterator it = OopStorageSet::weak_iterator();
+  for ( ; !it.is_end(); ++it, ++cur_state) {
+    assert((cur_state - _storage_states) < storage_count, "invariant");
+    new (cur_state) StorageState(*it, _nworkers);
   }
+  assert((cur_state - _storage_states) == storage_count, "invariant");
   StringTable::reset_dead_counter();
   ResolvedMethodTable::reset_dead_counter();
 }
@@ -139,7 +145,7 @@
 WeakProcessor::Task::~Task() {
   if (_storage_states != NULL) {
     StorageState* states = _storage_states;
-    FOR_EACH_WEAK_PROCESSOR_OOP_STORAGE_PHASE(phase) {
+    for (uint i = 0; i < WeakProcessorPhases::oopstorage_phase_count; ++i) {
       states->StorageState::~StorageState();
       ++states;
     }
--- a/src/hotspot/share/gc/shared/weakProcessor.inline.hpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/gc/shared/weakProcessor.inline.hpp	Wed Aug 21 18:42:30 2019 -0400
@@ -28,6 +28,7 @@
 #include "classfile/stringTable.hpp"
 #include "gc/shared/oopStorage.inline.hpp"
 #include "gc/shared/oopStorageParState.inline.hpp"
+#include "gc/shared/oopStorageSet.hpp"
 #include "gc/shared/weakProcessor.hpp"
 #include "gc/shared/weakProcessorPhases.hpp"
 #include "gc/shared/weakProcessorPhaseTimes.hpp"
@@ -94,31 +95,36 @@
          "worker_id (%u) exceeds task's configured workers (%u)",
          worker_id, _nworkers);
 
-  FOR_EACH_WEAK_PROCESSOR_PHASE(phase) {
-    if (WeakProcessorPhases::is_serial(phase)) {
-      CountingIsAliveClosure<IsAlive> cl(is_alive);
-      uint serial_index = WeakProcessorPhases::serial_index(phase);
-      if (_serial_phases_done.try_claim_task(serial_index)) {
-        WeakProcessorPhaseTimeTracker pt(_phase_times, phase);
-        WeakProcessorPhases::processor(phase)(&cl, keep_alive);
-        if (_phase_times != NULL) {
-          _phase_times->record_phase_items(phase, cl.num_dead(), cl.num_total());
-        }
+  typedef WeakProcessorPhases::Iterator Iterator;
+
+  for (Iterator it = WeakProcessorPhases::serial_iterator(); !it.is_end(); ++it) {
+    WeakProcessorPhase phase = *it;
+    CountingIsAliveClosure<IsAlive> cl(is_alive);
+    uint serial_index = WeakProcessorPhases::serial_index(phase);
+    if (_serial_phases_done.try_claim_task(serial_index)) {
+      WeakProcessorPhaseTimeTracker pt(_phase_times, phase);
+      WeakProcessorPhases::processor(phase)(&cl, keep_alive);
+      if (_phase_times != NULL) {
+        _phase_times->record_phase_items(phase, cl.num_dead(), cl.num_total());
       }
-    } else {
-      CountingSkippedIsAliveClosure<IsAlive, KeepAlive> cl(is_alive, keep_alive);
-      WeakProcessorPhaseTimeTracker pt(_phase_times, phase, worker_id);
-      uint storage_index = WeakProcessorPhases::oop_storage_index(phase);
-      _storage_states[storage_index].oops_do(&cl);
-      if (_phase_times != NULL) {
-        _phase_times->record_worker_items(worker_id, phase, cl.num_dead(), cl.num_total());
-      }
-      if (WeakProcessorPhases::is_stringtable(phase)) {
-        StringTable::inc_dead_counter(cl.num_dead() + cl.num_skipped());
-      }
-      if (WeakProcessorPhases::is_resolved_method_table(phase)) {
-        ResolvedMethodTable::inc_dead_counter(cl.num_dead() + cl.num_skipped());
-      }
+    }
+  }
+
+  for (Iterator it = WeakProcessorPhases::oopstorage_iterator(); !it.is_end(); ++it) {
+    WeakProcessorPhase phase = *it;
+    CountingSkippedIsAliveClosure<IsAlive, KeepAlive> cl(is_alive, keep_alive);
+    WeakProcessorPhaseTimeTracker pt(_phase_times, phase, worker_id);
+    uint oopstorage_index = WeakProcessorPhases::oopstorage_index(phase);
+    StorageState& cur_state = _storage_states[oopstorage_index];
+    cur_state.oops_do(&cl);
+    if (_phase_times != NULL) {
+      _phase_times->record_worker_items(worker_id, phase, cl.num_dead(), cl.num_total());
+    }
+    const OopStorage* cur_storage = cur_state.storage();
+    if (cur_storage == OopStorageSet::string_table_weak()) {
+      StringTable::inc_dead_counter(cl.num_dead() + cl.num_skipped());
+    } else if (cur_storage == OopStorageSet::resolved_method_table_weak()) {
+      ResolvedMethodTable::inc_dead_counter(cl.num_dead() + cl.num_skipped());
     }
   }
 
--- a/src/hotspot/share/gc/shared/weakProcessorPhaseTimes.cpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/gc/shared/weakProcessorPhaseTimes.cpp	Wed Aug 21 18:42:30 2019 -0400
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/shared/oopStorage.hpp"
 #include "gc/shared/weakProcessorPhases.hpp"
 #include "gc/shared/weakProcessorPhaseTimes.hpp"
 #include "gc/shared/workerDataArray.inline.hpp"
@@ -32,17 +33,22 @@
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/ticks.hpp"
 
-static uint phase_index(WeakProcessorPhase phase) {
-  return WeakProcessorPhases::index(phase);
+static uint serial_phase_index(WeakProcessorPhase phase) {
+  return WeakProcessorPhases::serial_index(phase);
 }
 
 static bool is_serial_phase(WeakProcessorPhase phase) {
   return WeakProcessorPhases::is_serial(phase);
 }
 
-static void assert_oop_storage_phase(WeakProcessorPhase phase) {
-  assert(WeakProcessorPhases::is_oop_storage(phase),
-         "Not an oop_storage phase %u", phase_index(phase));
+static void assert_serial_phase(WeakProcessorPhase phase) {
+  assert(is_serial_phase(phase),
+         "Not a serial phase %u", static_cast<uint>(phase));
+}
+
+static void assert_oopstorage_phase(WeakProcessorPhase phase) {
+  assert(WeakProcessorPhases::is_oopstorage(phase),
+         "Not an oopstorage phase %u", static_cast<uint>(phase));
 }
 
 const double uninitialized_time = -1.0;
@@ -64,6 +70,12 @@
   }
 }
 
+void WeakProcessorPhaseTimes::reset_phase_data() {
+  reset_times(_phase_times_sec, ARRAY_SIZE(_phase_times_sec));
+  reset_items(_phase_dead_items, ARRAY_SIZE(_phase_dead_items));
+  reset_items(_phase_total_items, ARRAY_SIZE(_phase_total_items));
+}
+
 WeakProcessorPhaseTimes::WeakProcessorPhaseTimes(uint max_threads) :
   _max_threads(max_threads),
   _active_workers(0),
@@ -74,20 +86,19 @@
 {
   assert(_max_threads > 0, "max_threads must not be zero");
 
-  reset_times(_phase_times_sec, ARRAY_SIZE(_phase_times_sec));
-  reset_items(_phase_dead_items, ARRAY_SIZE(_phase_dead_items));
-  reset_items(_phase_total_items, ARRAY_SIZE(_phase_total_items));
+  reset_phase_data();
 
-  if (_max_threads > 1) {
-    WorkerDataArray<double>** wpt = _worker_data;
-    FOR_EACH_WEAK_PROCESSOR_OOP_STORAGE_PHASE(phase) {
-      const char* description = WeakProcessorPhases::description(phase);
-      *wpt = new WorkerDataArray<double>(_max_threads, description);
-      (*wpt)->link_thread_work_items(new WorkerDataArray<size_t>(_max_threads, "Dead"), DeadItems);
-      (*wpt)->link_thread_work_items(new WorkerDataArray<size_t>(_max_threads, "Total"), TotalItems);
-      wpt++;
-    }
+  WorkerDataArray<double>** wpt = _worker_data;
+  OopStorageSet::Iterator it = OopStorageSet::weak_iterator();
+  for ( ; !it.is_end(); ++it) {
+    assert(size_t(wpt - _worker_data) < ARRAY_SIZE(_worker_data), "invariant");
+    const char* description = it->name();
+    *wpt = new WorkerDataArray<double>(_max_threads, description);
+    (*wpt)->link_thread_work_items(new WorkerDataArray<size_t>(_max_threads, "Dead"), DeadItems);
+    (*wpt)->link_thread_work_items(new WorkerDataArray<size_t>(_max_threads, "Total"), TotalItems);
+    wpt++;
   }
+  assert(size_t(wpt - _worker_data) == ARRAY_SIZE(_worker_data), "invariant");
 }
 
 WeakProcessorPhaseTimes::~WeakProcessorPhaseTimes() {
@@ -115,13 +126,9 @@
 void WeakProcessorPhaseTimes::reset() {
   _active_workers = 0;
   _total_time_sec = uninitialized_time;
-  reset_times(_phase_times_sec, ARRAY_SIZE(_phase_times_sec));
-  reset_items(_phase_dead_items, ARRAY_SIZE(_phase_dead_items));
-  reset_items(_phase_total_items, ARRAY_SIZE(_phase_total_items));
-  if (_max_threads > 1) {
-    for (size_t i = 0; i < ARRAY_SIZE(_worker_data); ++i) {
-      _worker_data[i]->reset();
-    }
+  reset_phase_data();
+  for (size_t i = 0; i < ARRAY_SIZE(_worker_data); ++i) {
+    _worker_data[i]->reset();
   }
 }
 
@@ -136,19 +143,22 @@
 }
 
 double WeakProcessorPhaseTimes::phase_time_sec(WeakProcessorPhase phase) const {
-  assert(is_initialized_time(_phase_times_sec[phase_index(phase)]),
-         "phase time not set %u", phase_index(phase));
-  return _phase_times_sec[phase_index(phase)];
+  assert_serial_phase(phase);
+  assert(is_initialized_time(_phase_times_sec[serial_phase_index(phase)]),
+         "phase time not set %u", serial_phase_index(phase));
+  return _phase_times_sec[serial_phase_index(phase)];
 }
 
 void WeakProcessorPhaseTimes::record_phase_time_sec(WeakProcessorPhase phase, double time_sec) {
-  assert(!is_initialized_time(_phase_times_sec[phase_index(phase)]),
-         "Already set time for phase %u", phase_index(phase));
-  _phase_times_sec[phase_index(phase)] = time_sec;
+  assert_serial_phase(phase);
+  assert(!is_initialized_time(_phase_times_sec[serial_phase_index(phase)]),
+         "Already set time for phase %u", serial_phase_index(phase));
+  _phase_times_sec[serial_phase_index(phase)] = time_sec;
 }
 
 void WeakProcessorPhaseTimes::record_phase_items(WeakProcessorPhase phase, size_t num_dead, size_t num_total) {
-  uint p = phase_index(phase);
+  assert_serial_phase(phase);
+  uint p = serial_phase_index(phase);
   assert(!is_initialized_items(_phase_dead_items[p]),
          "Already set dead items for phase %u", p);
   assert(!is_initialized_items(_phase_total_items[p]),
@@ -158,41 +168,29 @@
 }
 
 WorkerDataArray<double>* WeakProcessorPhaseTimes::worker_data(WeakProcessorPhase phase) const {
-  assert_oop_storage_phase(phase);
-  assert(active_workers() > 1, "No worker data when single-threaded");
-  return _worker_data[WeakProcessorPhases::oop_storage_index(phase)];
+  assert_oopstorage_phase(phase);
+  return _worker_data[WeakProcessorPhases::oopstorage_index(phase)];
 }
 
 double WeakProcessorPhaseTimes::worker_time_sec(uint worker_id, WeakProcessorPhase phase) const {
   assert(worker_id < active_workers(),
          "invalid worker id %u for %u", worker_id, active_workers());
-  if (active_workers() == 1) {
-    return phase_time_sec(phase);
-  } else {
-    return worker_data(phase)->get(worker_id);
-  }
+  return worker_data(phase)->get(worker_id);
 }
 
 void WeakProcessorPhaseTimes::record_worker_time_sec(uint worker_id,
                                                      WeakProcessorPhase phase,
                                                      double time_sec) {
-  if (active_workers() == 1) {
-    record_phase_time_sec(phase, time_sec);
-  } else {
-    worker_data(phase)->set(worker_id, time_sec);
-  }
+  worker_data(phase)->set(worker_id, time_sec);
 }
 
 void WeakProcessorPhaseTimes::record_worker_items(uint worker_id,
                                                   WeakProcessorPhase phase,
                                                   size_t num_dead,
                                                   size_t num_total) {
-  if (active_workers() == 1) {
-    record_phase_items(phase, num_dead, num_total);
-  } else {
-    worker_data(phase)->set_or_add_thread_work_item(worker_id, num_dead, DeadItems);
-    worker_data(phase)->set_or_add_thread_work_item(worker_id, num_total, TotalItems);
-  }
+  WorkerDataArray<double>* phase_data = worker_data(phase);
+  phase_data->set_or_add_thread_work_item(worker_id, num_dead, DeadItems);
+  phase_data->set_or_add_thread_work_item(worker_id, num_total, TotalItems);
 }
 
 static double elapsed_time_sec(Ticks start_time, Ticks end_time) {
@@ -219,7 +217,7 @@
   _worker_id(worker_id),
   _start_time(Ticks::now())
 {
-  assert_oop_storage_phase(_phase);
+  assert_oopstorage_phase(_phase);
   assert(_times == NULL || worker_id < _times->active_workers(),
          "Invalid worker_id %u", worker_id);
 }
@@ -231,7 +229,7 @@
   _worker_id(0),
   _start_time(Ticks::now())
 {
-  assert(is_serial_phase(phase), "Not a serial phase %u", phase_index(phase));
+  assert_serial_phase(phase);
 }
 
 WeakProcessorPhaseTimeTracker::~WeakProcessorPhaseTimeTracker() {
@@ -259,6 +257,7 @@
 
 void WeakProcessorPhaseTimes::log_st_phase(WeakProcessorPhase phase,
                                            uint indent) const {
+  assert_serial_phase(phase);
   log_debug(gc, phases)("%s%s: " TIME_FORMAT,
                         indent_str(indent),
                         WeakProcessorPhases::description(phase),
@@ -267,12 +266,12 @@
   log_debug(gc, phases)("%s%s: " SIZE_FORMAT,
                         indent_str(indent + 1),
                         "Dead",
-                        _phase_dead_items[phase_index(phase)]);
+                        _phase_dead_items[serial_phase_index(phase)]);
 
   log_debug(gc, phases)("%s%s: " SIZE_FORMAT,
                         indent_str(indent + 1),
                         "Total",
-                        _phase_total_items[phase_index(phase)]);
+                        _phase_total_items[serial_phase_index(phase)]);
 }
 
 void WeakProcessorPhaseTimes::log_mt_phase_summary(WeakProcessorPhase phase,
@@ -306,12 +305,12 @@
 
 void WeakProcessorPhaseTimes::log_print_phases(uint indent) const {
   if (log_is_enabled(Debug, gc, phases)) {
-    FOR_EACH_WEAK_PROCESSOR_PHASE(phase) {
-      if (is_serial_phase(phase) || (active_workers() == 1)) {
-        log_st_phase(phase, indent);
-      } else {
-        log_mt_phase_summary(phase, indent);
-      }
+    typedef WeakProcessorPhases::Iterator Iterator;
+    for (Iterator it = WeakProcessorPhases::serial_iterator(); !it.is_end(); ++it) {
+      log_st_phase(*it, indent);
+    }
+    for (Iterator it = WeakProcessorPhases::oopstorage_iterator(); !it.is_end(); ++it) {
+      log_mt_phase_summary(*it, indent);
     }
   }
 }
--- a/src/hotspot/share/gc/shared/weakProcessorPhaseTimes.hpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/gc/shared/weakProcessorPhaseTimes.hpp	Wed Aug 21 18:42:30 2019 -0400
@@ -25,6 +25,7 @@
 #ifndef SHARE_GC_SHARED_WEAKPROCESSORPHASETIMES_HPP
 #define SHARE_GC_SHARED_WEAKPROCESSORPHASETIMES_HPP
 
+#include "gc/shared/oopStorageSet.hpp"
 #include "gc/shared/weakProcessorPhases.hpp"
 #include "memory/allocation.hpp"
 #include "utilities/globalDefinitions.hpp"
@@ -43,17 +44,20 @@
   // Total time for weak processor.
   double _total_time_sec;
 
-  // Total time for each serially processed phase.  Entries for phases
-  // processed by multiple threads are unused, as are entries for
-  // unexecuted phases.
-  double _phase_times_sec[WeakProcessorPhases::phase_count];
-  size_t _phase_dead_items[WeakProcessorPhases::phase_count];
-  size_t _phase_total_items[WeakProcessorPhases::phase_count];
+  // Total time and associated items for each serially processed phase.
+  static const uint phase_data_count = WeakProcessorPhases::serial_phase_count;
+  // +1 because serial_phase_count == 0 in some build configurations.
+  // Simpler to always allocate extra space than conditionalize.
+  double _phase_times_sec[phase_data_count + 1];
+  size_t _phase_dead_items[phase_data_count + 1];
+  size_t _phase_total_items[phase_data_count + 1];
+  void reset_phase_data();
 
-  // Per-worker times and linked items, if multiple threads used and the phase was executed.
-  WorkerDataArray<double>* _worker_data[WeakProcessorPhases::oop_storage_phase_count];
-  WorkerDataArray<size_t>* _worker_dead_items[WeakProcessorPhases::oop_storage_phase_count];
-  WorkerDataArray<size_t>* _worker_total_items[WeakProcessorPhases::oop_storage_phase_count];
+  // Per-worker times and linked items.
+  static const uint worker_data_count = WeakProcessorPhases::oopstorage_phase_count;
+  WorkerDataArray<double>* _worker_data[worker_data_count];
+  WorkerDataArray<size_t>* _worker_dead_items[worker_data_count];
+  WorkerDataArray<size_t>* _worker_total_items[worker_data_count];
 
   WorkerDataArray<double>* worker_data(WeakProcessorPhase phase) const;
 
@@ -114,7 +118,7 @@
 
   // For tracking possibly parallel phase times (even if processed by
   // only one thread).
-  // Precondition: WeakProcessorPhases::is_oop_storage(phase)
+  // Precondition: WeakProcessorPhases::is_oopstorage(phase)
   // Precondition: worker_id < times->max_threads().
   WeakProcessorPhaseTimeTracker(WeakProcessorPhaseTimes* times,
                                 WeakProcessorPhase phase,
--- a/src/hotspot/share/gc/shared/weakProcessorPhases.cpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/gc/shared/weakProcessorPhases.cpp	Wed Aug 21 18:42:30 2019 -0400
@@ -23,11 +23,8 @@
  */
 
 #include "precompiled.hpp"
-#include "classfile/stringTable.hpp"
-#include "classfile/systemDictionary.hpp"
+#include "gc/shared/oopStorageSet.hpp"
 #include "gc/shared/weakProcessorPhases.hpp"
-#include "prims/resolvedMethodTable.hpp"
-#include "runtime/jniHandles.hpp"
 #include "utilities/debug.hpp"
 #include "utilities/macros.hpp"
 
@@ -39,53 +36,84 @@
 #include "prims/jvmtiExport.hpp"
 #endif // INCLUDE_JVMTI
 
-WeakProcessorPhases::Phase WeakProcessorPhases::phase(uint value) {
-  assert(value < phase_count, "Invalid phase value %u", value);
-  return static_cast<Phase>(value);
+// serial_phase_count is 0 if JFR and JVMTI are both not built,
+// requiring some code to be careful to avoid tautological checks
+// that some compilers warn about.
+
+#define HAVE_SERIAL_PHASES (INCLUDE_JVMTI || INCLUDE_JFR)
+
+WeakProcessorPhases::Phase WeakProcessorPhases::serial_phase(uint value) {
+#if HAVE_SERIAL_PHASES
+  assert(value < serial_phase_count, "Invalid serial phase value %u", value);
+  return static_cast<Phase>(value + serial_phase_start);
+#else
+  STATIC_ASSERT(serial_phase_count == 0);
+  fatal("invalid serial phase value %u", value);
+  return static_cast<Phase>(serial_phase_start);
+#endif // HAVE_SERIAL_PHASES
 }
 
-uint WeakProcessorPhases::index(Phase phase) {
-  uint value = static_cast<uint>(phase);
-  assert(value < phase_count, "Invalid phase %u", value);
-  return value;
+WeakProcessorPhases::Phase WeakProcessorPhases::oopstorage_phase(uint value) {
+  assert(value < oopstorage_phase_count, "Invalid oopstorage phase value %u", value);
+  return static_cast<Phase>(value + oopstorage_phase_start);
+}
+
+static uint raw_phase_index(WeakProcessorPhases::Phase phase) {
+  return static_cast<uint>(phase);
 }
 
 uint WeakProcessorPhases::serial_index(Phase phase) {
-  assert(is_serial(phase), "not serial phase %u", index(phase));
-  return index(phase) - serial_phase_start;
+  assert(is_serial(phase), "not serial phase %u", raw_phase_index(phase));
+  return raw_phase_index(phase) - serial_phase_start;
 }
 
-uint WeakProcessorPhases::oop_storage_index(Phase phase) {
-  assert(is_oop_storage(phase), "not oop storage phase %u", index(phase));
-  return index(phase) - oop_storage_phase_start;
+uint WeakProcessorPhases::oopstorage_index(Phase phase) {
+  assert(is_oopstorage(phase), "not oopstorage phase %u", raw_phase_index(phase));
+  return raw_phase_index(phase) - oopstorage_phase_start;
+}
+
+static bool is_phase(WeakProcessorPhases::Phase phase, uint start, uint count) {
+  return (raw_phase_index(phase) - start) < count;
 }
 
 bool WeakProcessorPhases::is_serial(Phase phase) {
-  // serial_phase_count is 0 if JFR and JVMTI are both not built,
-  // making this check with unsigned lhs redundant
-#if INCLUDE_JVMTI || INCLUDE_JFR
-  return (index(phase) - serial_phase_start) < serial_phase_count;
+#if HAVE_SERIAL_PHASES
+  return is_phase(phase, serial_phase_start, serial_phase_count);
 #else
   STATIC_ASSERT(serial_phase_count == 0);
   return false;
-#endif
+#endif // HAVE_SERIAL_PHASES
+}
+
+bool WeakProcessorPhases::is_oopstorage(Phase phase) {
+  return is_phase(phase, oopstorage_phase_start, oopstorage_phase_count);
 }
 
-bool WeakProcessorPhases::is_oop_storage(Phase phase) {
-  return (index(phase) - oop_storage_phase_start) < oop_storage_phase_count;
+#ifdef ASSERT
+
+void WeakProcessorPhases::Iterator::verify_nonsingular() const {
+  assert(_limit != singular_value, "precondition");
 }
 
+void WeakProcessorPhases::Iterator::verify_category_match(const Iterator& other) const {
+  verify_nonsingular();
+  assert(_limit == other._limit, "precondition");
+}
+
+void WeakProcessorPhases::Iterator::verify_dereferenceable() const {
+  verify_nonsingular();
+  assert(_index < _limit, "precondition");
+}
+
+#endif // ASSERT
+
 const char* WeakProcessorPhases::description(Phase phase) {
   switch (phase) {
   JVMTI_ONLY(case jvmti: return "JVMTI weak processing";)
   JFR_ONLY(case jfr: return "JFR weak processing";)
-  case jni: return "JNI weak processing";
-  case stringtable: return "StringTable weak processing";
-  case resolved_method_table: return "ResolvedMethodTable weak processing";
-  case vm: return "VM weak processing";
   default:
     ShouldNotReachHere();
-    return "Invalid weak processing phase";
+    return "Invalid serial weak processing phase";
   }
 }
 
@@ -98,23 +126,3 @@
     return NULL;
   }
 }
-
-OopStorage* WeakProcessorPhases::oop_storage(Phase phase) {
-  switch (phase) {
-  case jni: return JNIHandles::weak_global_handles();
-  case stringtable: return StringTable::weak_storage();
-  case resolved_method_table: return ResolvedMethodTable::weak_storage();
-  case vm: return SystemDictionary::vm_weak_oop_storage();
-  default:
-    ShouldNotReachHere();
-    return NULL;
-  }
-}
-
-bool WeakProcessorPhases::is_stringtable(Phase phase) {
-  return phase == stringtable;
-}
-
-bool WeakProcessorPhases::is_resolved_method_table(Phase phase) {
-  return phase == resolved_method_table;
-}
--- a/src/hotspot/share/gc/shared/weakProcessorPhases.hpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/gc/shared/weakProcessorPhases.hpp	Wed Aug 21 18:42:30 2019 -0400
@@ -25,6 +25,7 @@
 #ifndef SHARE_GC_SHARED_WEAKPROCESSORPHASES_HPP
 #define SHARE_GC_SHARED_WEAKPROCESSORPHASES_HPP
 
+#include "gc/shared/oopStorageSet.hpp"
 #include "memory/allocation.hpp"
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/macros.hpp"
@@ -35,54 +36,117 @@
 
 class WeakProcessorPhases : AllStatic {
 public:
+  class Iterator;
+
   typedef void (*Processor)(BoolObjectClosure*, OopClosure*);
 
   enum Phase {
     // Serial phases.
-    JVMTI_ONLY(jvmti COMMA)
-    JFR_ONLY(jfr COMMA)
+    JVMTI_ONLY(jvmti JFR_ONLY(COMMA))
+    JFR_ONLY(jfr)
 
-    // OopStorage phases.
-    jni,
-    stringtable,
-    resolved_method_table,
-    vm
+    // Additional implicit phase values follow for oopstorages.
   };
 
   static const uint serial_phase_start = 0;
-  static const uint serial_phase_count = jni;
-  static const uint oop_storage_phase_start = serial_phase_count;
-  static const uint oop_storage_phase_count = (vm + 1) - oop_storage_phase_start;
-  static const uint phase_count = serial_phase_count + oop_storage_phase_count;
+  static const uint serial_phase_count = 0 JVMTI_ONLY(+ 1) JFR_ONLY(+ 1);
+  static const uint oopstorage_phase_start = serial_phase_count;
+  static const uint oopstorage_phase_count = OopStorageSet::weak_count;
+  static const uint phase_count = serial_phase_count + oopstorage_phase_count;
+
+  // Precondition: value < serial_phase_count
+  static Phase serial_phase(uint value);
 
-  static Phase phase(uint value);
-  static uint index(Phase phase);
+  // Precondition: value < oopstorage_phase_count
+  static Phase oopstorage_phase(uint value);
+
   // Indexes relative to the corresponding phase_start constant.
+  // Precondition: is_serial(phase) or is_oopstorage(phase) accordingly
   static uint serial_index(Phase phase);
-  static uint oop_storage_index(Phase phase);
+  static uint oopstorage_index(Phase phase);
 
   static bool is_serial(Phase phase);
-  static bool is_oop_storage(Phase phase);
+  static bool is_oopstorage(Phase phase);
 
+  static Iterator serial_iterator();
+  static Iterator oopstorage_iterator();
+
+  // Precondition: is_serial(phase)
   static const char* description(Phase phase);
-  static Processor processor(Phase phase); // Precondition: is_serial(phase)
-  static OopStorage* oop_storage(Phase phase); // Precondition: is_oop_storage(phase)
 
-  static bool is_stringtable(Phase phase);
-  static bool is_resolved_method_table(Phase phase);
+  // Precondition: is_serial(phase)
+  static Processor processor(Phase phase);
 };
 
 typedef WeakProcessorPhases::Phase WeakProcessorPhase;
 
-#define FOR_EACH_WEAK_PROCESSOR_PHASE(P)                                \
-  for (WeakProcessorPhase P = static_cast<WeakProcessorPhase>(0);       \
-       static_cast<uint>(P) <  WeakProcessorPhases::phase_count;        \
-       P = static_cast<WeakProcessorPhase>(static_cast<uint>(P) + 1))
+class WeakProcessorPhases::Iterator {
+  friend class WeakProcessorPhases;
+
+  uint _index;
+  uint _limit;
+
+  Iterator(uint index, uint limit) : _index(index), _limit(limit) {}
+
+  static const uint singular_value = UINT_MAX;
+  void verify_nonsingular() const NOT_DEBUG_RETURN;
+  void verify_category_match(const Iterator& other) const NOT_DEBUG_RETURN;
+  void verify_dereferenceable() const NOT_DEBUG_RETURN;
+
+public:
+  // Construct a singular iterator for later assignment.  The only valid
+  // operations are destruction and assignment.
+  Iterator() : _index(singular_value), _limit(singular_value) {}
+
+  bool is_end() const {
+    verify_nonsingular();
+    return _index == _limit;
+  }
+
+  bool operator==(const Iterator& other) const {
+    verify_category_match(other);
+    return _index == other._index;
+  }
+
+  bool operator!=(const Iterator& other) const {
+    return !operator==(other);
+  }
 
-#define FOR_EACH_WEAK_PROCESSOR_OOP_STORAGE_PHASE(P)                    \
-  for (WeakProcessorPhase P = static_cast<WeakProcessorPhase>(WeakProcessorPhases::oop_storage_phase_start); \
-       static_cast<uint>(P) < (WeakProcessorPhases::oop_storage_phase_start + \
-                               WeakProcessorPhases::oop_storage_phase_count); \
-       P = static_cast<WeakProcessorPhase>(static_cast<uint>(P) + 1))
+  Phase operator*() const {
+    verify_dereferenceable();
+    return static_cast<Phase>(_index);
+  }
+
+  // Phase doesn't have members, so no operator->().
+
+  Iterator& operator++() {
+    verify_dereferenceable();
+    ++_index;
+    return *this;
+  }
+
+  Iterator operator++(int) {
+    verify_dereferenceable();
+    return Iterator(_index++, _limit);
+  }
+
+  Iterator begin() const {
+    verify_nonsingular();
+    return *this;
+  }
+
+  Iterator end() const {
+    verify_nonsingular();
+    return Iterator(_limit, _limit);
+  }
+};
+
+inline WeakProcessorPhases::Iterator WeakProcessorPhases::serial_iterator() {
+  return Iterator(serial_phase_start, serial_phase_start + serial_phase_count);
+}
+
+inline WeakProcessorPhases::Iterator WeakProcessorPhases::oopstorage_iterator() {
+  return Iterator(oopstorage_phase_start, oopstorage_phase_start + oopstorage_phase_count);
+}
 
 #endif // SHARE_GC_SHARED_WEAKPROCESSORPHASES_HPP
--- a/src/hotspot/share/gc/z/zRootsIterator.cpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/gc/z/zRootsIterator.cpp	Wed Aug 21 18:42:30 2019 -0400
@@ -30,6 +30,7 @@
 #include "gc/shared/barrierSet.hpp"
 #include "gc/shared/barrierSetNMethod.hpp"
 #include "gc/shared/oopStorageParState.inline.hpp"
+#include "gc/shared/oopStorageSet.hpp"
 #include "gc/shared/suspendibleThreadSet.hpp"
 #include "gc/z/zBarrierSetNMethod.hpp"
 #include "gc/z/zGlobals.hpp"
@@ -43,7 +44,6 @@
 #include "prims/jvmtiExport.hpp"
 #include "prims/resolvedMethodTable.hpp"
 #include "runtime/atomic.hpp"
-#include "runtime/jniHandles.hpp"
 #include "runtime/thread.hpp"
 #include "runtime/safepoint.hpp"
 #include "runtime/synchronizer.hpp"
@@ -265,8 +265,8 @@
 }
 
 ZConcurrentRootsIterator::ZConcurrentRootsIterator(int cld_claim) :
-    _jni_handles_iter(JNIHandles::global_handles()),
-    _vm_handles_iter(SystemDictionary::vm_global_oop_storage()),
+    _jni_handles_iter(OopStorageSet::jni_global()),
+    _vm_handles_iter(OopStorageSet::vm_global()),
     _cld_claim(cld_claim),
     _jni_handles(this),
     _vm_handles(this),
@@ -337,10 +337,10 @@
 }
 
 ZConcurrentWeakRootsIterator::ZConcurrentWeakRootsIterator() :
-    _vm_weak_handles_iter(SystemDictionary::vm_weak_oop_storage()),
-    _jni_weak_handles_iter(JNIHandles::weak_global_handles()),
-    _string_table_iter(StringTable::weak_storage()),
-    _resolved_method_table_iter(ResolvedMethodTable::weak_storage()),
+    _vm_weak_handles_iter(OopStorageSet::vm_weak()),
+    _jni_weak_handles_iter(OopStorageSet::jni_weak()),
+    _string_table_iter(OopStorageSet::string_table_weak()),
+    _resolved_method_table_iter(OopStorageSet::resolved_method_table_weak()),
     _vm_weak_handles(this),
     _jni_weak_handles(this),
     _string_table(this),
--- a/src/hotspot/share/jvmci/jvmci.cpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/jvmci/jvmci.cpp	Wed Aug 21 18:42:30 2019 -0400
@@ -25,13 +25,13 @@
 #include "classfile/systemDictionary.hpp"
 #include "gc/shared/collectedHeap.hpp"
 #include "gc/shared/oopStorage.hpp"
+#include "gc/shared/oopStorageSet.hpp"
 #include "jvmci/jvmci.hpp"
 #include "jvmci/jvmciJavaClasses.hpp"
 #include "jvmci/jvmciRuntime.hpp"
 #include "jvmci/metadataHandleBlock.hpp"
 #include "memory/universe.hpp"
 
-OopStorage* JVMCI::_object_handles = NULL;
 MetadataHandleBlock* JVMCI::_metadata_handles = NULL;
 JVMCIRuntime* JVMCI::_compiler_runtime = NULL;
 JVMCIRuntime* JVMCI::_java_runtime = NULL;
@@ -58,7 +58,6 @@
 }
 
 void JVMCI::initialize_globals() {
-  _object_handles = SystemDictionary::vm_global_oop_storage();
   _metadata_handles = MetadataHandleBlock::allocate_block();
   if (UseJVMCINativeLibrary) {
     // There are two runtimes.
@@ -70,9 +69,9 @@
   }
 }
 
-OopStorage* JVMCI::object_handles() {
-  assert(_object_handles != NULL, "Uninitialized");
-  return _object_handles;
+// Handles to objects in the Hotspot heap.
+static OopStorage* object_handles() {
+  return OopStorageSet::vm_global();
 }
 
 jobject JVMCI::make_global(const Handle& obj) {
--- a/src/hotspot/share/jvmci/jvmci.hpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/jvmci/jvmci.hpp	Wed Aug 21 18:42:30 2019 -0400
@@ -45,11 +45,6 @@
   friend class JVMCIEnv;
 
  private:
-  // Handles to objects in the HotSpot heap.
-  static OopStorage* _object_handles;
-
-  static OopStorage* object_handles();
-
   // Handles to Metadata objects.
   static MetadataHandleBlock* _metadata_handles;
 
--- a/src/hotspot/share/memory/universe.cpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/memory/universe.cpp	Wed Aug 21 18:42:30 2019 -0400
@@ -670,8 +670,6 @@
 
   Universe::initialize_tlab();
 
-  SystemDictionary::initialize_oop_storage();
-
   Metaspace::global_initialize();
 
   // Initialize performance counters for metaspaces
--- a/src/hotspot/share/oops/weakHandle.cpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/oops/weakHandle.cpp	Wed Aug 21 18:42:30 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,26 +23,24 @@
  */
 
 #include "precompiled.hpp"
-#include "classfile/systemDictionary.hpp"
-#include "classfile/stringTable.hpp"
 #include "gc/shared/oopStorage.hpp"
+#include "gc/shared/oopStorageSet.hpp"
 #include "oops/access.inline.hpp"
 #include "oops/oop.hpp"
 #include "oops/weakHandle.inline.hpp"
-#include "prims/resolvedMethodTable.hpp"
 #include "utilities/debug.hpp"
 #include "utilities/ostream.hpp"
 
 template <> OopStorage* WeakHandle<vm_class_loader_data>::get_storage() {
-  return SystemDictionary::vm_weak_oop_storage();
+  return OopStorageSet::vm_weak();
 }
 
 template <> OopStorage* WeakHandle<vm_string_table_data>::get_storage() {
-  return StringTable::weak_storage();
+  return OopStorageSet::string_table_weak();
 }
 
 template <> OopStorage* WeakHandle<vm_resolved_method_table_data>::get_storage() {
-  return ResolvedMethodTable::weak_storage();
+  return OopStorageSet::resolved_method_table_weak();
 }
 
 template <WeakHandleType T>
@@ -50,7 +48,9 @@
   assert(obj() != NULL, "no need to create weak null oop");
   oop* oop_addr = get_storage()->allocate();
   if (oop_addr == NULL) {
-    vm_exit_out_of_memory(sizeof(oop*), OOM_MALLOC_ERROR, "Unable to create new weak oop handle in OopStorage");
+    vm_exit_out_of_memory(sizeof(oop*), OOM_MALLOC_ERROR,
+                          "Unable to create new weak oop handle in OopStorage %s",
+                          get_storage()->name());
   }
   // Create WeakHandle with address returned and store oop into it.
   NativeAccess<ON_PHANTOM_OOP_REF>::oop_store(oop_addr, obj());
--- a/src/hotspot/share/prims/resolvedMethodTable.cpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp	Wed Aug 21 18:42:30 2019 -0400
@@ -25,13 +25,14 @@
 #include "precompiled.hpp"
 #include "classfile/javaClasses.hpp"
 #include "gc/shared/oopStorage.inline.hpp"
+#include "gc/shared/oopStorageSet.hpp"
 #include "logging/log.hpp"
 #include "memory/allocation.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.hpp"
 #include "oops/access.inline.hpp"
+#include "oops/method.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/method.hpp"
 #include "oops/weakHandle.inline.hpp"
 #include "prims/resolvedMethodTable.hpp"
 #include "runtime/handles.inline.hpp"
@@ -90,7 +91,6 @@
 static ResolvedMethodTableHash* _local_table           = NULL;
 static size_t                   _current_size          = (size_t)1 << ResolvedMethodTableSizeLog;
 
-OopStorage*              ResolvedMethodTable::_weak_handles          = NULL;
 volatile bool            ResolvedMethodTable::_has_work              = false;
 
 volatile size_t          _items_count           = 0;
@@ -98,9 +98,6 @@
 
 void ResolvedMethodTable::create_table() {
   _local_table  = new ResolvedMethodTableHash(ResolvedMethodTableSizeLog, END_SIZE, GROW_HINT);
-  _weak_handles = new OopStorage("ResolvedMethodTable weak",
-                                 ResolvedMethodTableWeakAlloc_lock,
-                                 ResolvedMethodTableWeakActive_lock);
   log_trace(membername, table)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")",
                                _current_size, ResolvedMethodTableSizeLog);
 }
--- a/src/hotspot/share/prims/resolvedMethodTable.hpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/prims/resolvedMethodTable.hpp	Wed Aug 21 18:42:30 2019 -0400
@@ -25,7 +25,6 @@
 #ifndef SHARE_PRIMS_RESOLVEDMETHODTABLE_HPP
 #define SHARE_PRIMS_RESOLVEDMETHODTABLE_HPP
 
-#include "gc/shared/oopStorage.hpp"
 #include "memory/allocation.hpp"
 #include "oops/symbol.hpp"
 #include "oops/weakHandle.hpp"
@@ -34,9 +33,8 @@
 class ResolvedMethodTableConfig;
 
 class ResolvedMethodTable : public AllStatic {
-  static OopStorage*              _weak_handles;
+  static volatile bool            _has_work;
 
-  static volatile bool            _has_work;
 public:
   // Initialization
   static void create_table();
@@ -54,9 +52,6 @@
   // Cleaning
   static bool has_work() { return _has_work; }
 
-  // GC Support - Backing storage for the oop*s
-  static OopStorage* weak_storage() { return _weak_handles; }
-
   // Cleaning and table management
 
   static double get_load_factor();
--- a/src/hotspot/share/runtime/init.cpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/runtime/init.cpp	Wed Aug 21 18:42:30 2019 -0400
@@ -50,6 +50,7 @@
 void check_ThreadShadow();
 void eventlog_init();
 void mutex_init();
+void oopstorage_init();
 void chunkpool_init();
 void perfMemory_init();
 void SuspendibleThreadSet_init();
@@ -98,6 +99,7 @@
   basic_types_init();
   eventlog_init();
   mutex_init();
+  oopstorage_init();
   chunkpool_init();
   perfMemory_init();
   SuspendibleThreadSet_init();
--- a/src/hotspot/share/runtime/jniHandles.cpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/runtime/jniHandles.cpp	Wed Aug 21 18:42:30 2019 -0400
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc/shared/oopStorage.inline.hpp"
+#include "gc/shared/oopStorageSet.hpp"
 #include "logging/log.hpp"
 #include "memory/iterator.hpp"
 #include "memory/universe.hpp"
@@ -36,17 +37,21 @@
 #include "utilities/align.hpp"
 #include "utilities/debug.hpp"
 
+static OopStorage* global_handles() {
+  return OopStorageSet::jni_global();
+}
+
+static OopStorage* weak_global_handles() {
+  return OopStorageSet::jni_weak();
+}
+
+// Serviceability agent support.
 OopStorage* JNIHandles::_global_handles = NULL;
 OopStorage* JNIHandles::_weak_global_handles = NULL;
 
-OopStorage* JNIHandles::global_handles() {
-  assert(_global_handles != NULL, "Uninitialized JNI global handles");
-  return _global_handles;
-}
-
-OopStorage* JNIHandles::weak_global_handles() {
-  assert(_weak_global_handles != NULL, "Uninitialized JNI weak global handles");
-  return _weak_global_handles;
+void jni_handles_init() {
+  JNIHandles::_global_handles = global_handles();
+  JNIHandles::_weak_global_handles = weak_global_handles();
 }
 
 
@@ -197,16 +202,6 @@
 }
 
 
-void JNIHandles::initialize() {
-  _global_handles = new OopStorage("JNI Global",
-                                   JNIGlobalAlloc_lock,
-                                   JNIGlobalActive_lock);
-  _weak_global_handles = new OopStorage("JNI Weak",
-                                        JNIWeakAlloc_lock,
-                                        JNIWeakActive_lock);
-}
-
-
 inline bool is_storage_handle(const OopStorage* storage, const oop* ptr) {
   return storage->allocation_status(ptr) == OopStorage::ALLOCATED_ENTRY;
 }
@@ -332,11 +327,6 @@
 }
 
 
-void jni_handles_init() {
-  JNIHandles::initialize();
-}
-
-
 int             JNIHandleBlock::_blocks_allocated     = 0;
 JNIHandleBlock* JNIHandleBlock::_block_free_list      = NULL;
 #ifndef PRODUCT
--- a/src/hotspot/share/runtime/jniHandles.hpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/runtime/jniHandles.hpp	Wed Aug 21 18:42:30 2019 -0400
@@ -37,8 +37,10 @@
 class JNIHandles : AllStatic {
   friend class VMStructs;
  private:
+  // These are used by the serviceability agent.
   static OopStorage* _global_handles;
   static OopStorage* _weak_global_handles;
+  friend void jni_handles_init();
 
   inline static bool is_jweak(jobject handle);
   inline static oop* jobject_ptr(jobject handle); // NOT jweak!
@@ -122,9 +124,6 @@
   static void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f);
   // Traversal of weak global handles.
   static void weak_oops_do(OopClosure* f);
-
-  static OopStorage* global_handles();
-  static OopStorage* weak_global_handles();
 };
 
 
--- a/src/hotspot/share/runtime/mutexLocker.cpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/runtime/mutexLocker.cpp	Wed Aug 21 18:42:30 2019 -0400
@@ -46,19 +46,7 @@
 Mutex*   CompiledIC_lock              = NULL;
 Mutex*   InlineCacheBuffer_lock       = NULL;
 Mutex*   VMStatistic_lock             = NULL;
-Mutex*   JNIGlobalAlloc_lock          = NULL;
-Mutex*   JNIGlobalActive_lock         = NULL;
-Mutex*   JNIWeakAlloc_lock            = NULL;
-Mutex*   JNIWeakActive_lock           = NULL;
-Mutex*   StringTableWeakAlloc_lock    = NULL;
-Mutex*   StringTableWeakActive_lock   = NULL;
 Mutex*   JNIHandleBlockFreeList_lock  = NULL;
-Mutex*   VMGlobalAlloc_lock           = NULL;
-Mutex*   VMGlobalActive_lock          = NULL;
-Mutex*   VMWeakAlloc_lock             = NULL;
-Mutex*   VMWeakActive_lock            = NULL;
-Mutex*   ResolvedMethodTableWeakAlloc_lock  = NULL;
-Mutex*   ResolvedMethodTableWeakActive_lock = NULL;
 Mutex*   JmethodIdCreation_lock       = NULL;
 Mutex*   JfieldIdCreation_lock        = NULL;
 Monitor* JNICritical_lock             = NULL;
@@ -214,18 +202,6 @@
   def(CGC_lock                     , PaddedMonitor, special,     true,  Monitor::_safepoint_check_never);      // coordinate between fore- and background GC
   def(STS_lock                     , PaddedMonitor, leaf,        true,  Monitor::_safepoint_check_never);
 
-  def(VMGlobalAlloc_lock           , PaddedMutex  , oopstorage,  true,  Monitor::_safepoint_check_never);
-  def(VMGlobalActive_lock          , PaddedMutex  , oopstorage-1,true,  Monitor::_safepoint_check_never);
-
-  def(VMWeakAlloc_lock             , PaddedMutex  , oopstorage,  true,  Monitor::_safepoint_check_never);
-  def(VMWeakActive_lock            , PaddedMutex  , oopstorage-1,true,  Monitor::_safepoint_check_never);
-
-  def(StringTableWeakAlloc_lock    , PaddedMutex  , oopstorage,  true,  Monitor::_safepoint_check_never);
-  def(StringTableWeakActive_lock   , PaddedMutex  , oopstorage-1,true,  Monitor::_safepoint_check_never);
-
-  def(ResolvedMethodTableWeakAlloc_lock    , PaddedMutex  , oopstorage,   true,  Monitor::_safepoint_check_never);
-  def(ResolvedMethodTableWeakActive_lock   , PaddedMutex  , oopstorage-1, true,  Monitor::_safepoint_check_never);
-
   def(FullGCCount_lock             , PaddedMonitor, leaf,        true,  Monitor::_safepoint_check_never);      // in support of ExplicitGCInvokesConcurrent
   if (UseG1GC) {
     def(DirtyCardQ_CBL_mon         , PaddedMonitor, access,      true,  Monitor::_safepoint_check_never);
@@ -296,10 +272,6 @@
   def(InitCompleted_lock           , PaddedMonitor, leaf,        true,  Monitor::_safepoint_check_never);
   def(VtableStubs_lock             , PaddedMutex  , nonleaf,     true,  Monitor::_safepoint_check_never);
   def(Notify_lock                  , PaddedMonitor, nonleaf,     true,  Monitor::_safepoint_check_always);
-  def(JNIGlobalAlloc_lock          , PaddedMutex  , nonleaf,     true,  Monitor::_safepoint_check_never);
-  def(JNIGlobalActive_lock         , PaddedMutex  , nonleaf-1,   true,  Monitor::_safepoint_check_never);
-  def(JNIWeakAlloc_lock            , PaddedMutex  , nonleaf,     true,  Monitor::_safepoint_check_never);
-  def(JNIWeakActive_lock           , PaddedMutex  , nonleaf-1,   true,  Monitor::_safepoint_check_never);
   def(JNICritical_lock             , PaddedMonitor, nonleaf,     true,  Monitor::_safepoint_check_always); // used for JNI critical regions
   def(AdapterHandlerLibrary_lock   , PaddedMutex  , nonleaf,     true,  Monitor::_safepoint_check_always);
 
--- a/src/hotspot/share/runtime/mutexLocker.hpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/runtime/mutexLocker.hpp	Wed Aug 21 18:42:30 2019 -0400
@@ -39,19 +39,7 @@
 extern Mutex*   CompiledIC_lock;                 // a lock used to guard compiled IC patching and access
 extern Mutex*   InlineCacheBuffer_lock;          // a lock used to guard the InlineCacheBuffer
 extern Mutex*   VMStatistic_lock;                // a lock used to guard statistics count increment
-extern Mutex*   JNIGlobalAlloc_lock;             // JNI global storage allocate list lock
-extern Mutex*   JNIGlobalActive_lock;            // JNI global storage active list lock
-extern Mutex*   JNIWeakAlloc_lock;               // JNI weak storage allocate list lock
-extern Mutex*   JNIWeakActive_lock;              // JNI weak storage active list lock
-extern Mutex*   StringTableWeakAlloc_lock;       // StringTable weak storage allocate list lock
-extern Mutex*   StringTableWeakActive_lock;      // STringTable weak storage active list lock
 extern Mutex*   JNIHandleBlockFreeList_lock;     // a lock on the JNI handle block free list
-extern Mutex*   VMGlobalAlloc_lock;              // VM Global Handles storage allocate list lock
-extern Mutex*   VMGlobalActive_lock;             // VM Global Handles storage active list lock
-extern Mutex*   VMWeakAlloc_lock;                // VM Weak Handles storage allocate list lock
-extern Mutex*   VMWeakActive_lock;               // VM Weak Handles storage active list lock
-extern Mutex*   ResolvedMethodTableWeakAlloc_lock;  // ResolvedMethodTable weak storage allocate list
-extern Mutex*   ResolvedMethodTableWeakActive_lock; // ResolvedMethodTable weak storage active list
 extern Mutex*   JmethodIdCreation_lock;          // a lock on creating JNI method identifiers
 extern Mutex*   JfieldIdCreation_lock;           // a lock on creating JNI static field identifiers
 extern Monitor* JNICritical_lock;                // a lock used while entering and exiting JNI critical regions, allows GC to sometimes get in
--- a/src/hotspot/share/runtime/serviceThread.cpp	Wed Aug 21 16:19:17 2019 -0400
+++ b/src/hotspot/share/runtime/serviceThread.cpp	Wed Aug 21 18:42:30 2019 -0400
@@ -27,6 +27,8 @@
 #include "classfile/stringTable.hpp"
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
+#include "gc/shared/oopStorage.hpp"
+#include "gc/shared/oopStorageSet.hpp"
 #include "memory/universe.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/interfaceSupport.inline.hpp"
@@ -83,22 +85,14 @@
   }
 }
 
-static void cleanup_oopstorages(OopStorage* const* storages, size_t size) {
-  for (size_t i = 0; i < size; ++i) {
-    storages[i]->delete_empty_blocks();
+static void cleanup_oopstorages() {
+  OopStorageSet::Iterator it = OopStorageSet::all_iterator();
+  for ( ; !it.is_end(); ++it) {
+    it->delete_empty_blocks();
   }
 }
 
 void ServiceThread::service_thread_entry(JavaThread* jt, TRAPS) {
-  OopStorage* const oopstorages[] = {
-    JNIHandles::global_handles(),
-    JNIHandles::weak_global_handles(),
-    StringTable::weak_storage(),
-    SystemDictionary::vm_global_oop_storage(),
-    SystemDictionary::vm_weak_oop_storage()
-  };
-  const size_t oopstorage_count = ARRAY_SIZE(oopstorages);
-
   while (true) {
     bool sensors_changed = false;
     bool has_jvmti_events = false;
@@ -178,7 +172,7 @@
     }
 
     if (oopstorage_work) {
-      cleanup_oopstorages(oopstorages, oopstorage_count);
+      cleanup_oopstorages();
     }
   }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/gtest/gc/shared/test_oopStorageSet.cpp	Wed Aug 21 18:42:30 2019 -0400
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/shared/oopStorage.hpp"
+#include "gc/shared/oopStorageSet.hpp"
+#include "memory/allocation.inline.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/macros.hpp"
+#include "unittest.hpp"
+
+// GTEST assertions may introduce ODR-uses.  Dodge them.
+template<typename T> static T no_odr(T x) { return x; }
+
+static void fill_strong(OopStorage** storages, size_t size) {
+  ASSERT_EQ(size, no_odr(OopStorageSet::strong_count));
+  STATIC_ASSERT(2 == OopStorageSet::strong_count);
+  storages[0] = OopStorageSet::jni_global();
+  storages[1] = OopStorageSet::vm_global();
+}
+
+static void fill_weak(OopStorage** storages, size_t size) {
+  ASSERT_EQ(size, no_odr(OopStorageSet::weak_count));
+  STATIC_ASSERT(4 == OopStorageSet::weak_count);
+  storages[0] = OopStorageSet::jni_weak();
+  storages[1] = OopStorageSet::vm_weak();
+  storages[2] = OopStorageSet::string_table_weak();
+  storages[3] = OopStorageSet::resolved_method_table_weak();
+}
+
+static void fill_all(OopStorage** storages, size_t size) {
+  ASSERT_EQ(size, no_odr(OopStorageSet::all_count));
+  const uint strong_count = OopStorageSet::strong_count;
+  fill_strong(storages, strong_count);
+  fill_weak(storages + strong_count, size - strong_count);
+}
+
+// Returns index of s in storages, or size if not found.
+static size_t find_storage(OopStorage* s, OopStorage** storages, size_t size) {
+  for (uint i = 0; i < size; ++i) {
+    if (s == storages[i]) {
+      return i;
+    }
+  }
+  return size;
+}
+
+static void check_iterator(OopStorageSet::Iterator it,
+                           OopStorage** storages,
+                           size_t size) {
+  OopStorageSet::Iterator start = it;
+  ASSERT_EQ(start, it);
+  for ( ; !it.is_end(); ++it) {
+    size_t index = find_storage(*it, storages, size);
+    ASSERT_LT(index, size);
+    storages[index] = NULL;
+  }
+  ASSERT_NE(start, it);
+  const OopStorage* null_storage = NULL;
+  for (uint i = 0; i < size; ++i) {
+    ASSERT_EQ(null_storage, storages[i]);
+  }
+}
+
+static void test_iterator(uint count,
+                          OopStorageSet::Iterator iterator,
+                          void (*fill)(OopStorage**, size_t)) {
+  OopStorage** storages = NEW_C_HEAP_ARRAY(OopStorage*, count, mtGC);
+  fill(storages, count);
+  check_iterator(iterator, storages, count);
+  FREE_C_HEAP_ARRAY(OopStorage*, storages);
+}
+
+#define TEST_ITERATOR(kind)                                             \
+  TEST_VM(OopStorageSetTest, PASTE_TOKENS(kind, _iterator)) {           \
+    test_iterator(OopStorageSet::PASTE_TOKENS(kind, _count),            \
+                  OopStorageSet::PASTE_TOKENS(kind, _iterator)(),       \
+                  &PASTE_TOKENS(fill_, kind));                          \
+  }
+
+TEST_ITERATOR(strong);
+TEST_ITERATOR(weak)
+TEST_ITERATOR(all)
--- a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java	Wed Aug 21 16:19:17 2019 -0400
+++ b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java	Wed Aug 21 18:42:30 2019 -0400
@@ -159,9 +159,10 @@
         new LogMessageWithLevel("Reference Processing", Level.DEBUG),
         // VM internal reference processing
         new LogMessageWithLevel("Weak Processing", Level.DEBUG),
-        new LogMessageWithLevel("JNI weak processing", Level.DEBUG),
-        new LogMessageWithLevel("StringTable weak processing", Level.DEBUG),
-        new LogMessageWithLevel("VM weak processing", Level.DEBUG),
+        new LogMessageWithLevel("JNI weak", Level.DEBUG),
+        new LogMessageWithLevel("StringTable weak", Level.DEBUG),
+        new LogMessageWithLevel("ResolvedMethodTable weak", Level.DEBUG),
+        new LogMessageWithLevel("VM weak", Level.DEBUG),
 
         new LogMessageWithLevelC2OrJVMCIOnly("DerivedPointerTable Update", Level.DEBUG),
         new LogMessageWithLevel("Start New Collection Set", Level.DEBUG),