8208498: Put archive regions into a first-class HeapRegionSet
authortschatzl
Wed, 22 Aug 2018 20:37:07 +0200
changeset 51494 1906adbef2dc
parent 51493 6b5f3f5fd63c
child 51495 89d2f870e92c
8208498: Put archive regions into a first-class HeapRegionSet Summary: Maintain archive regions in a HeapRegionSet like other region types. Reviewed-by: phh, sangheki
src/hotspot/share/gc/g1/collectionSetChooser.cpp
src/hotspot/share/gc/g1/g1Allocator.cpp
src/hotspot/share/gc/g1/g1CollectedHeap.cpp
src/hotspot/share/gc/g1/g1CollectedHeap.hpp
src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp
src/hotspot/share/gc/g1/g1ConcurrentMark.inline.hpp
src/hotspot/share/gc/g1/g1HeapTransition.cpp
src/hotspot/share/gc/g1/g1HeapTransition.hpp
src/hotspot/share/gc/g1/g1HeapVerifier.cpp
src/hotspot/share/gc/g1/g1RemSet.cpp
src/hotspot/share/gc/g1/g1RemSetSummary.cpp
src/hotspot/share/gc/g1/g1RemSetTrackingPolicy.cpp
src/hotspot/share/gc/g1/heapRegion.hpp
src/hotspot/share/gc/g1/heapRegion.inline.hpp
src/hotspot/share/gc/g1/heapRegionSet.cpp
src/hotspot/share/gc/g1/heapRegionSet.hpp
src/hotspot/share/gc/g1/heapRegionType.hpp
src/hotspot/share/gc/g1/vmStructs_g1.hpp
src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/g1/G1CollectedHeap.java
src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java
--- a/src/hotspot/share/gc/g1/collectionSetChooser.cpp	Wed Aug 22 10:28:34 2018 -0700
+++ b/src/hotspot/share/gc/g1/collectionSetChooser.cpp	Wed Aug 22 20:37:07 2018 +0200
@@ -243,7 +243,7 @@
       // sets for old regions.
       r->rem_set()->clear(true /* only_cardset */);
     } else {
-      assert(!r->is_old() || !r->rem_set()->is_tracked(),
+      assert(r->is_archive() || !r->is_old() || !r->rem_set()->is_tracked(),
              "Missed to clear unused remembered set of region %u (%s) that is %s",
              r->hrm_index(), r->get_type_str(), r->rem_set()->get_state_str());
     }
--- a/src/hotspot/share/gc/g1/g1Allocator.cpp	Wed Aug 22 10:28:34 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1Allocator.cpp	Wed Aug 22 20:37:07 2018 +0200
@@ -361,7 +361,7 @@
     hr->set_closed_archive();
   }
   _g1h->g1_policy()->remset_tracker()->update_at_allocate(hr);
-  _g1h->old_set_add(hr);
+  _g1h->archive_set_add(hr);
   _g1h->hr_printer()->alloc(hr);
   _allocated_regions.append(hr);
   _allocation_region = hr;
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Wed Aug 22 10:28:34 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Wed Aug 22 20:37:07 2018 +0200
@@ -643,7 +643,7 @@
         curr_region->set_closed_archive();
       }
       _hr_printer.alloc(curr_region);
-      _old_set.add(curr_region);
+      _archive_set.add(curr_region);
       HeapWord* top;
       HeapRegion* next_region;
       if (curr_region != last_region) {
@@ -800,7 +800,7 @@
       guarantee(curr_region->is_archive(),
                 "Expected archive region at index %u", curr_region->hrm_index());
       uint curr_index = curr_region->hrm_index();
-      _old_set.remove(curr_region);
+      _archive_set.remove(curr_region);
       curr_region->set_free();
       curr_region->set_top(curr_region->bottom());
       if (curr_region != last_region) {
@@ -1417,8 +1417,9 @@
   _eden_pool(NULL),
   _survivor_pool(NULL),
   _old_pool(NULL),
-  _old_set("Old Set", false /* humongous */, new OldRegionSetMtSafeChecker()),
-  _humongous_set("Master Humongous Set", true /* humongous */, new HumongousRegionSetMtSafeChecker()),
+  _old_set("Old Region Set", HeapRegionSetBase::ForOldRegions, new OldRegionSetMtSafeChecker()),
+  _archive_set("Archive Region Set", HeapRegionSetBase::ForArchiveRegions, new ArchiveRegionSetMtSafeChecker()),
+  _humongous_set("Humongous Region Set", HeapRegionSetBase::ForHumongousRegions, new HumongousRegionSetMtSafeChecker()),
   _bot(NULL),
   _listener(),
   _hrm(),
@@ -4593,7 +4594,6 @@
 #endif // ASSERT
 
 class TearDownRegionSetsClosure : public HeapRegionClosure {
-private:
   HeapRegionSet *_old_set;
 
 public:
@@ -4606,9 +4606,9 @@
       r->uninstall_surv_rate_group();
     } else {
       // We ignore free regions, we'll empty the free list afterwards.
-      // We ignore humongous regions, we're not tearing down the
-      // humongous regions set.
-      assert(r->is_free() || r->is_humongous(),
+      // We ignore humongous and archive regions, we're not tearing down these
+      // sets.
+      assert(r->is_archive() || r->is_free() || r->is_humongous(),
              "it cannot be another type");
     }
     return false;
@@ -4651,14 +4651,17 @@
 
 class RebuildRegionSetsClosure : public HeapRegionClosure {
 private:
-  bool            _free_list_only;
-  HeapRegionSet*   _old_set;
-  HeapRegionManager*   _hrm;
-  size_t          _total_used;
+  bool _free_list_only;
+
+  HeapRegionSet* _old_set;
+  HeapRegionManager* _hrm;
+
+  size_t _total_used;
 
 public:
   RebuildRegionSetsClosure(bool free_list_only,
-                           HeapRegionSet* old_set, HeapRegionManager* hrm) :
+                           HeapRegionSet* old_set,
+                           HeapRegionManager* hrm) :
     _free_list_only(free_list_only),
     _old_set(old_set), _hrm(hrm), _total_used(0) {
     assert(_hrm->num_free_regions() == 0, "pre-condition");
@@ -4676,11 +4679,11 @@
       _hrm->insert_into_free_list(r);
     } else if (!_free_list_only) {
 
-      if (r->is_humongous()) {
-        // We ignore humongous regions. We left the humongous set unchanged.
+      if (r->is_archive() || r->is_humongous()) {
+        // We ignore archive and humongous regions. We left these sets unchanged.
       } else {
         assert(r->is_young() || r->is_free() || r->is_old(), "invariant");
-        // We now move all (non-humongous, non-old) regions to old gen, and register them as such.
+        // We now move all (non-humongous, non-old, non-archive) regions to old gen, and register them as such.
         r->move_to_old();
         _old_set->add(r);
       }
@@ -4805,7 +4808,7 @@
   alloc_region->note_end_of_copying(during_im);
   g1_policy()->record_bytes_copied_during_gc(allocated_bytes);
   if (dest.is_old()) {
-    _old_set.add(alloc_region);
+    old_set_add(alloc_region);
   }
   _hr_printer.retire(alloc_region);
 }
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	Wed Aug 22 10:28:34 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	Wed Aug 22 20:37:07 2018 +0200
@@ -169,10 +169,9 @@
 
   static size_t _humongous_object_threshold_in_words;
 
-  // It keeps track of the old regions.
+  // These sets keep track of old, archive and humongous regions respectively.
   HeapRegionSet _old_set;
-
-  // It keeps track of the humongous regions.
+  HeapRegionSet _archive_set;
   HeapRegionSet _humongous_set;
 
   virtual void initialize_serviceability();
@@ -1046,8 +1045,10 @@
   inline void old_set_add(HeapRegion* hr);
   inline void old_set_remove(HeapRegion* hr);
 
+  inline void archive_set_add(HeapRegion* hr);
+
   size_t non_young_capacity_bytes() {
-    return (_old_set.length() + _humongous_set.length()) * HeapRegion::GrainBytes;
+    return (old_regions_count() + _archive_set.length() + humongous_regions_count()) * HeapRegion::GrainBytes;
   }
 
   // Determine whether the given region is one that we are using as an
@@ -1232,20 +1233,11 @@
 
   const G1SurvivorRegions* survivor() const { return &_survivor; }
 
-  uint survivor_regions_count() const {
-    return _survivor.length();
-  }
-
-  uint eden_regions_count() const {
-    return _eden.length();
-  }
-
-  uint young_regions_count() const {
-    return _eden.length() + _survivor.length();
-  }
-
+  uint eden_regions_count() const { return _eden.length(); }
+  uint survivor_regions_count() const { return _survivor.length(); }
+  uint young_regions_count() const { return _eden.length() + _survivor.length(); }
   uint old_regions_count() const { return _old_set.length(); }
-
+  uint archive_regions_count() const { return _archive_set.length(); }
   uint humongous_regions_count() const { return _humongous_set.length(); }
 
 #ifdef ASSERT
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp	Wed Aug 22 10:28:34 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp	Wed Aug 22 20:37:07 2018 +0200
@@ -92,6 +92,10 @@
   _old_set.remove(hr);
 }
 
+inline void G1CollectedHeap::archive_set_add(HeapRegion* hr) {
+  _archive_set.add(hr);
+}
+
 // It dirties the cards that cover the block so that the post
 // write barrier never queues anything when updating objects on this
 // block. It is assumed (and in fact we assert) that the block
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.inline.hpp	Wed Aug 22 10:28:34 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.inline.hpp	Wed Aug 22 20:37:07 2018 +0200
@@ -52,7 +52,7 @@
     return false;
   }
   assert(_g1h->is_in_reserved(obj), "Trying to discover obj " PTR_FORMAT " not in heap", p2i(obj));
-  return _g1h->heap_region_containing(obj)->is_old_or_humongous();
+  return _g1h->heap_region_containing(obj)->is_old_or_humongous_or_archive();
 }
 
 inline bool G1ConcurrentMark::mark_in_next_bitmap(uint const worker_id, oop const obj, size_t const obj_size) {
--- a/src/hotspot/share/gc/g1/g1HeapTransition.cpp	Wed Aug 22 10:28:34 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1HeapTransition.cpp	Wed Aug 22 20:37:07 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -33,6 +33,7 @@
   _eden_length = g1_heap->eden_regions_count();
   _survivor_length = g1_heap->survivor_regions_count();
   _old_length = g1_heap->old_regions_count();
+  _archive_length = g1_heap->archive_regions_count();
   _humongous_length = g1_heap->humongous_regions_count();
   _metaspace_used_bytes = MetaspaceUtils::used_bytes();
 }
@@ -43,16 +44,19 @@
   size_t _eden_used;
   size_t _survivor_used;
   size_t _old_used;
+  size_t _archive_used;
   size_t _humongous_used;
 
   size_t _eden_region_count;
   size_t _survivor_region_count;
   size_t _old_region_count;
+  size_t _archive_region_count;
   size_t _humongous_region_count;
 
   DetailedUsage() :
-    _eden_used(0), _survivor_used(0), _old_used(0), _humongous_used(0),
-    _eden_region_count(0), _survivor_region_count(0), _old_region_count(0), _humongous_region_count(0) {}
+    _eden_used(0), _survivor_used(0), _old_used(0), _archive_used(0), _humongous_used(0),
+    _eden_region_count(0), _survivor_region_count(0), _old_region_count(0),
+    _archive_region_count(0), _humongous_region_count(0) {}
 };
 
 class DetailedUsageClosure: public HeapRegionClosure {
@@ -62,6 +66,9 @@
     if (r->is_old()) {
       _usage._old_used += r->used();
       _usage._old_region_count++;
+    } else if (r->is_archive()) {
+      _usage._archive_used += r->used();
+      _usage._archive_region_count++;
     } else if (r->is_survivor()) {
       _usage._survivor_used += r->used();
       _usage._survivor_region_count++;
@@ -94,6 +101,8 @@
         after._survivor_length, usage._survivor_region_count);
     assert(usage._old_region_count == after._old_length, "Expected old to be " SIZE_FORMAT " but was " SIZE_FORMAT,
         after._old_length, usage._old_region_count);
+    assert(usage._archive_region_count == after._archive_length, "Expected archive to be " SIZE_FORMAT " but was " SIZE_FORMAT,
+        after._archive_length, usage._archive_region_count);
     assert(usage._humongous_region_count == after._humongous_length, "Expected humongous to be " SIZE_FORMAT " but was " SIZE_FORMAT,
         after._humongous_length, usage._humongous_region_count);
   }
@@ -112,6 +121,11 @@
   log_trace(gc, heap)(" Used: " SIZE_FORMAT "K, Waste: " SIZE_FORMAT "K",
       usage._old_used / K, ((after._old_length * HeapRegion::GrainBytes) - usage._old_used) / K);
 
+  log_info(gc, heap)("Archive regions: " SIZE_FORMAT "->" SIZE_FORMAT,
+                     _before._archive_length, after._archive_length);
+  log_trace(gc, heap)(" Used: " SIZE_FORMAT "K, Waste: " SIZE_FORMAT "K",
+      usage._archive_used / K, ((after._archive_length * HeapRegion::GrainBytes) - usage._archive_used) / K);
+
   log_info(gc, heap)("Humongous regions: " SIZE_FORMAT "->" SIZE_FORMAT,
                      _before._humongous_length, after._humongous_length);
   log_trace(gc, heap)(" Used: " SIZE_FORMAT "K, Waste: " SIZE_FORMAT "K",
--- a/src/hotspot/share/gc/g1/g1HeapTransition.hpp	Wed Aug 22 10:28:34 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1HeapTransition.hpp	Wed Aug 22 20:37:07 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -34,6 +34,7 @@
     size_t _eden_length;
     size_t _survivor_length;
     size_t _old_length;
+    size_t _archive_length;
     size_t _humongous_length;
     size_t _metaspace_used_bytes;
 
--- a/src/hotspot/share/gc/g1/g1HeapVerifier.cpp	Wed Aug 22 10:28:34 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1HeapVerifier.cpp	Wed Aug 22 20:37:07 2018 +0200
@@ -488,19 +488,22 @@
 class VerifyRegionListsClosure : public HeapRegionClosure {
 private:
   HeapRegionSet*   _old_set;
+  HeapRegionSet*   _archive_set;
   HeapRegionSet*   _humongous_set;
-  HeapRegionManager*   _hrm;
+  HeapRegionManager* _hrm;
 
 public:
   uint _old_count;
+  uint _archive_count;
   uint _humongous_count;
   uint _free_count;
 
   VerifyRegionListsClosure(HeapRegionSet* old_set,
+                           HeapRegionSet* archive_set,
                            HeapRegionSet* humongous_set,
                            HeapRegionManager* hrm) :
-    _old_set(old_set), _humongous_set(humongous_set), _hrm(hrm),
-    _old_count(), _humongous_count(), _free_count(){ }
+    _old_set(old_set), _archive_set(archive_set), _humongous_set(humongous_set), _hrm(hrm),
+    _old_count(), _archive_count(), _humongous_count(), _free_count(){ }
 
   bool do_heap_region(HeapRegion* hr) {
     if (hr->is_young()) {
@@ -511,6 +514,9 @@
     } else if (hr->is_empty()) {
       assert(_hrm->is_free(hr), "Heap region %u is empty but not on the free list.", hr->hrm_index());
       _free_count++;
+    } else if (hr->is_archive()) {
+      assert(hr->containing_set() == _archive_set, "Heap region %u is archive but not in the archive set.", hr->hrm_index());
+      _archive_count++;
     } else if (hr->is_old()) {
       assert(hr->containing_set() == _old_set, "Heap region %u is old but not in the old set.", hr->hrm_index());
       _old_count++;
@@ -523,8 +529,9 @@
     return false;
   }
 
-  void verify_counts(HeapRegionSet* old_set, HeapRegionSet* humongous_set, HeapRegionManager* free_list) {
+  void verify_counts(HeapRegionSet* old_set, HeapRegionSet* archive_set, HeapRegionSet* humongous_set, HeapRegionManager* free_list) {
     guarantee(old_set->length() == _old_count, "Old set count mismatch. Expected %u, actual %u.", old_set->length(), _old_count);
+    guarantee(archive_set->length() == _archive_count, "Archive set count mismatch. Expected %u, actual %u.", archive_set->length(), _archive_count);
     guarantee(humongous_set->length() == _humongous_count, "Hum set count mismatch. Expected %u, actual %u.", humongous_set->length(), _humongous_count);
     guarantee(free_list->num_free_regions() == _free_count, "Free list count mismatch. Expected %u, actual %u.", free_list->num_free_regions(), _free_count);
   }
@@ -539,9 +546,9 @@
   // Finally, make sure that the region accounting in the lists is
   // consistent with what we see in the heap.
 
-  VerifyRegionListsClosure cl(&_g1h->_old_set, &_g1h->_humongous_set, &_g1h->_hrm);
+  VerifyRegionListsClosure cl(&_g1h->_old_set, &_g1h->_archive_set, &_g1h->_humongous_set, &_g1h->_hrm);
   _g1h->heap_region_iterate(&cl);
-  cl.verify_counts(&_g1h->_old_set, &_g1h->_humongous_set, &_g1h->_hrm);
+  cl.verify_counts(&_g1h->_old_set, &_g1h->_archive_set, &_g1h->_humongous_set, &_g1h->_hrm);
 }
 
 void G1HeapVerifier::prepare_for_verify() {
@@ -755,6 +762,11 @@
         return true;
       }
       if (cset_state.is_in_cset()) {
+        if (hr->is_archive()) {
+          log_error(gc, verify)("## is_archive in collection set for region %u", i);
+          _failures = true;
+          return true;
+        }
         if (hr->is_young() != (cset_state.is_young())) {
           log_error(gc, verify)("## is_young %d / cset state " CSETSTATE_FORMAT " inconsistency for region %u",
                                hr->is_young(), cset_state.value(), i);
--- a/src/hotspot/share/gc/g1/g1RemSet.cpp	Wed Aug 22 10:28:34 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1RemSet.cpp	Wed Aug 22 20:37:07 2018 +0200
@@ -132,7 +132,7 @@
 
     virtual bool do_heap_region(HeapRegion* r) {
       uint hrm_index = r->hrm_index();
-      if (!r->in_collection_set() && r->is_old_or_humongous()) {
+      if (!r->in_collection_set() && r->is_old_or_humongous_or_archive()) {
         _scan_top[hrm_index] = r->top();
       } else {
         _scan_top[hrm_index] = r->bottom();
@@ -571,7 +571,7 @@
   // In the normal (non-stale) case, the synchronization between the
   // enqueueing of the card and processing it here will have ensured
   // we see the up-to-date region type here.
-  if (!r->is_old_or_humongous()) {
+  if (!r->is_old_or_humongous_or_archive()) {
     return;
   }
 
@@ -600,7 +600,7 @@
       // Check whether the region formerly in the cache should be
       // ignored, as discussed earlier for the original card.  The
       // region could have been freed while in the cache.
-      if (!r->is_old_or_humongous()) {
+      if (!r->is_old_or_humongous_or_archive()) {
         return;
       }
     } // Else we still have the original card.
--- a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp	Wed Aug 22 10:28:34 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp	Wed Aug 22 20:37:07 2018 +0200
@@ -226,6 +226,7 @@
   RegionTypeCounter _humongous;
   RegionTypeCounter _free;
   RegionTypeCounter _old;
+  RegionTypeCounter _archive;
   RegionTypeCounter _all;
 
   size_t _max_rs_mem_sz;
@@ -248,7 +249,7 @@
 
 public:
   HRRSStatsIter() : _young("Young"), _humongous("Humongous"),
-    _free("Free"), _old("Old"), _all("All"),
+    _free("Free"), _old("Old"), _archive("Archive"), _all("All"),
     _max_rs_mem_sz(0), _max_rs_mem_sz_region(NULL),
     _max_code_root_mem_sz(0), _max_code_root_mem_sz_region(NULL)
   {}
@@ -280,6 +281,8 @@
       current = &_humongous;
     } else if (r->is_old()) {
       current = &_old;
+    } else if (r->is_archive()) {
+      current = &_archive;
     } else {
       ShouldNotReachHere();
     }
@@ -290,7 +293,7 @@
   }
 
   void print_summary_on(outputStream* out) {
-    RegionTypeCounter* counters[] = { &_young, &_humongous, &_free, &_old, NULL };
+    RegionTypeCounter* counters[] = { &_young, &_humongous, &_free, &_old, &_archive, NULL };
 
     out->print_cr(" Current rem set statistics");
     out->print_cr("  Total per region rem sets sizes = " SIZE_FORMAT "%s."
--- a/src/hotspot/share/gc/g1/g1RemSetTrackingPolicy.cpp	Wed Aug 22 10:28:34 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1RemSetTrackingPolicy.cpp	Wed Aug 22 20:37:07 2018 +0200
@@ -141,8 +141,9 @@
 void G1RemSetTrackingPolicy::update_after_rebuild(HeapRegion* r) {
   assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");
 
-  if (r->is_old_or_humongous()) {
+  if (r->is_old_or_humongous_or_archive()) {
     if (r->rem_set()->is_updating()) {
+      assert(!r->is_archive(), "Archive region %u with remembered set", r->hrm_index());
       r->rem_set()->set_state_complete();
     }
     G1CollectedHeap* g1h = G1CollectedHeap::heap();
--- a/src/hotspot/share/gc/g1/heapRegion.hpp	Wed Aug 22 10:28:34 2018 -0700
+++ b/src/hotspot/share/gc/g1/heapRegion.hpp	Wed Aug 22 20:37:07 2018 +0200
@@ -426,6 +426,8 @@
 
   bool is_old_or_humongous() const { return _type.is_old_or_humongous(); }
 
+  bool is_old_or_humongous_or_archive() const { return _type.is_old_or_humongous_or_archive(); }
+
   // A pinned region contains objects which are not moved by garbage collections.
   // Humongous regions and archive regions are pinned.
   bool is_pinned() const { return _type.is_pinned(); }
--- a/src/hotspot/share/gc/g1/heapRegion.inline.hpp	Wed Aug 22 10:28:34 2018 -0700
+++ b/src/hotspot/share/gc/g1/heapRegion.inline.hpp	Wed Aug 22 20:37:07 2018 +0200
@@ -350,7 +350,7 @@
   if (is_humongous()) {
     return do_oops_on_card_in_humongous<Closure, is_gc_active>(mr, cl, g1h);
   }
-  assert(is_old(), "precondition");
+  assert(is_old() || is_archive(), "Wrongly trying to iterate over region %u type %s", _hrm_index, get_type_str());
 
   // Because mr has been trimmed to what's been allocated in this
   // region, the parts of the heap that are examined here are always
--- a/src/hotspot/share/gc/g1/heapRegionSet.cpp	Wed Aug 22 10:28:34 2018 -0700
+++ b/src/hotspot/share/gc/g1/heapRegionSet.cpp	Wed Aug 22 20:37:07 2018 +0200
@@ -77,19 +77,17 @@
   out->print_cr("Set: %s (" PTR_FORMAT ")", name(), p2i(this));
   out->print_cr("  Region Assumptions");
   out->print_cr("    humongous         : %s", BOOL_TO_STR(regions_humongous()));
+  out->print_cr("    archive           : %s", BOOL_TO_STR(regions_archive()));
   out->print_cr("    free              : %s", BOOL_TO_STR(regions_free()));
   out->print_cr("  Attributes");
   out->print_cr("    length            : %14u", length());
 }
 
-HeapRegionSetBase::HeapRegionSetBase(const char* name, bool humongous, bool free, HRSMtSafeChecker* mt_safety_checker)
-  : _is_humongous(humongous),
-    _is_free(free),
-    _mt_safety_checker(mt_safety_checker),
-    _length(0),
-    _name(name),
-    _verify_in_progress(false)
-{ }
+HeapRegionSetBase::HeapRegionSetBase(const char* name, RegionSetKind kind, HRSMtSafeChecker* mt_safety_checker)
+  : _region_kind(kind), _mt_safety_checker(mt_safety_checker), _length(0), _name(name), _verify_in_progress(false)
+{
+  assert(kind >= ForOldRegions && kind <= ForFreeRegions, "Invalid heap region set kind %d.", kind);
+}
 
 void FreeRegionList::set_unrealistically_long_length(uint len) {
   guarantee(_unrealistically_long_length == 0, "should only be set once");
@@ -365,3 +363,8 @@
               "master humongous set MT safety protocol outside a safepoint");
   }
 }
+
+void ArchiveRegionSetMtSafeChecker::check() {
+  guarantee(!Universe::is_fully_initialized() || SafepointSynchronize::is_at_safepoint(),
+            "May only change archive regions during initialization or safepoint.");
+}
--- a/src/hotspot/share/gc/g1/heapRegionSet.hpp	Wed Aug 22 10:28:34 2018 -0700
+++ b/src/hotspot/share/gc/g1/heapRegionSet.hpp	Wed Aug 22 20:37:07 2018 +0200
@@ -55,6 +55,7 @@
 class MasterFreeRegionListMtSafeChecker    : public HRSMtSafeChecker { public: void check(); };
 class HumongousRegionSetMtSafeChecker      : public HRSMtSafeChecker { public: void check(); };
 class OldRegionSetMtSafeChecker            : public HRSMtSafeChecker { public: void check(); };
+class ArchiveRegionSetMtSafeChecker        : public HRSMtSafeChecker { public: void check(); };
 
 // Base class for all the classes that represent heap region sets. It
 // contains the basic attributes that each set needs to maintain
@@ -63,9 +64,16 @@
 
 class HeapRegionSetBase {
   friend class VMStructs;
+public:
+  enum RegionSetKind {
+    ForOldRegions,
+    ForHumongousRegions,
+    ForArchiveRegions,
+    ForFreeRegions
+  };
+
 private:
-  bool _is_humongous;
-  bool _is_free;
+  RegionSetKind _region_kind;
   HRSMtSafeChecker* _mt_safety_checker;
 
 protected:
@@ -80,13 +88,11 @@
   // added to / removed from a set are consistent.
   void verify_region(HeapRegion* hr) PRODUCT_RETURN;
 
-  // Indicates whether all regions in the set should be humongous or
-  // not. Only used during verification.
-  bool regions_humongous() { return _is_humongous; }
-
-  // Indicates whether all regions in the set should be free or
-  // not. Only used during verification.
-  bool regions_free() { return _is_free; }
+  // Indicates whether all regions in the set should be of a given particular type.
+  // Only used for verification.
+  bool regions_humongous() const { return _region_kind == ForHumongousRegions; }
+  bool regions_archive() const { return _region_kind == ForArchiveRegions; }
+  bool regions_free() const { return _region_kind == ForFreeRegions; }
 
   void check_mt_safety() {
     if (_mt_safety_checker != NULL) {
@@ -94,7 +100,7 @@
     }
   }
 
-  HeapRegionSetBase(const char* name, bool humongous, bool free, HRSMtSafeChecker* mt_safety_checker);
+  HeapRegionSetBase(const char* name, RegionSetKind kind, HRSMtSafeChecker* mt_safety_checker);
 
 public:
   const char* name() { return _name; }
@@ -121,15 +127,6 @@
   virtual void print_on(outputStream* out, bool print_contents = false);
 };
 
-#define hrs_assert_sets_match(_set1_, _set2_)                                  \
-  do {                                                                         \
-    assert(((_set1_)->regions_humongous() == (_set2_)->regions_humongous()) && \
-           ((_set1_)->regions_free() == (_set2_)->regions_free()),             \
-           "the contents of set %s and set %s should match",                   \
-           (_set1_)->name(),                                                   \
-           (_set2_)->name());                                                  \
-  } while (0)
-
 // This class represents heap region sets whose members are not
 // explicitly tracked. It's helpful to group regions using such sets
 // so that we can reason about all the region groups in the heap using
@@ -137,8 +134,10 @@
 
 class HeapRegionSet : public HeapRegionSetBase {
 public:
-  HeapRegionSet(const char* name, bool humongous, HRSMtSafeChecker* mt_safety_checker):
-    HeapRegionSetBase(name, humongous, false /* free */, mt_safety_checker) { }
+  HeapRegionSet(const char* name, RegionSetKind kind, HRSMtSafeChecker* mt_safety_checker):
+    HeapRegionSetBase(name, kind, mt_safety_checker) {
+    assert(kind != ForFreeRegions, "Must not call this constructor for Free regions.");
+  }
 
   void bulk_remove(const uint removed) {
     _length -= removed;
@@ -174,7 +173,7 @@
 
 public:
   FreeRegionList(const char* name, HRSMtSafeChecker* mt_safety_checker = NULL):
-    HeapRegionSetBase(name, false /* humongous */, true /* empty */, mt_safety_checker) {
+    HeapRegionSetBase(name, ForFreeRegions, mt_safety_checker) {
     clear();
   }
 
--- a/src/hotspot/share/gc/g1/heapRegionType.hpp	Wed Aug 22 10:28:34 2018 -0700
+++ b/src/hotspot/share/gc/g1/heapRegionType.hpp	Wed Aug 22 20:37:07 2018 +0200
@@ -86,8 +86,8 @@
     // Objects within these regions are allowed to have references to objects
     // contained in any other kind of regions.
     ArchiveMask           = 32,
-    OpenArchiveTag        = ArchiveMask | PinnedMask | OldMask,
-    ClosedArchiveTag      = ArchiveMask | PinnedMask | OldMask + 1
+    OpenArchiveTag        = ArchiveMask | PinnedMask,
+    ClosedArchiveTag      = ArchiveMask | PinnedMask + 1
   } Tag;
 
   volatile Tag _tag;
@@ -139,6 +139,8 @@
 
   bool is_old_or_humongous() const { return (get() & (OldMask | HumongousMask)) != 0; }
 
+  bool is_old_or_humongous_or_archive() const { return (get() & (OldMask | HumongousMask | ArchiveMask)) != 0; }
+
   // is_pinned regions may be archive or humongous
   bool is_pinned() const { return (get() & PinnedMask) != 0; }
 
--- a/src/hotspot/share/gc/g1/vmStructs_g1.hpp	Wed Aug 22 10:28:34 2018 -0700
+++ b/src/hotspot/share/gc/g1/vmStructs_g1.hpp	Wed Aug 22 20:37:07 2018 +0200
@@ -56,6 +56,7 @@
   nonstatic_field(G1CollectedHeap, _hrm,                HeapRegionManager)    \
   nonstatic_field(G1CollectedHeap, _g1mm,               G1MonitoringSupport*) \
   nonstatic_field(G1CollectedHeap, _old_set,            HeapRegionSetBase)    \
+  nonstatic_field(G1CollectedHeap, _archive_set,        HeapRegionSetBase)    \
   nonstatic_field(G1CollectedHeap, _humongous_set,      HeapRegionSetBase)    \
                                                                               \
   nonstatic_field(G1MonitoringSupport, _eden_committed,     size_t)           \
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/g1/G1CollectedHeap.java	Wed Aug 22 10:28:34 2018 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/g1/G1CollectedHeap.java	Wed Aug 22 20:37:07 2018 +0200
@@ -56,6 +56,8 @@
     static private AddressField g1mmField;
     // HeapRegionSet _old_set;
     static private long oldSetFieldOffset;
+    // HeapRegionSet _archive_set;
+    static private long archiveSetFieldOffset;
     // HeapRegionSet _humongous_set;
     static private long humongousSetFieldOffset;
 
@@ -74,6 +76,7 @@
         summaryBytesUsedField = type.getCIntegerField("_summary_bytes_used");
         g1mmField = type.getAddressField("_g1mm");
         oldSetFieldOffset = type.getField("_old_set").getOffset();
+        archiveSetFieldOffset = type.getField("_archive_set").getOffset();
         humongousSetFieldOffset = type.getField("_humongous_set").getOffset();
     }
 
@@ -106,6 +109,12 @@
                                                              oldSetAddr);
     }
 
+    public HeapRegionSetBase archiveSet() {
+        Address archiveSetAddr = addr.addOffsetTo(archiveSetFieldOffset);
+        return (HeapRegionSetBase) VMObjectFactory.newObject(HeapRegionSetBase.class,
+                                                             archiveSetAddr);
+    }
+
     public HeapRegionSetBase humongousSet() {
         Address humongousSetAddr = addr.addOffsetTo(humongousSetFieldOffset);
         return (HeapRegionSetBase) VMObjectFactory.newObject(HeapRegionSetBase.class,
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java	Wed Aug 22 10:28:34 2018 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java	Wed Aug 22 20:37:07 2018 +0200
@@ -228,8 +228,9 @@
       long edenRegionNum = g1mm.edenRegionNum();
       long survivorRegionNum = g1mm.survivorRegionNum();
       HeapRegionSetBase oldSet = g1h.oldSet();
+      HeapRegionSetBase archiveSet = g1h.archiveSet();
       HeapRegionSetBase humongousSet = g1h.humongousSet();
-      long oldRegionNum = oldSet.length() + humongousSet.length();
+      long oldRegionNum = oldSet.length() + archiveSet.length() + humongousSet.length();
       printG1Space("G1 Heap:", g1h.n_regions(),
                    g1h.used(), g1h.capacity());
       System.out.println("G1 Young Generation:");