# HG changeset patch # User tschatzl # Date 1534963027 -7200 # Node ID 1906adbef2dc9fbe35adda0cdc2718454c57f66c # Parent 6b5f3f5fd63c156339b369bd8c4d1e2a497d5e69 8208498: Put archive regions into a first-class HeapRegionSet Summary: Maintain archive regions in a HeapRegionSet like other region types. Reviewed-by: phh, sangheki diff -r 6b5f3f5fd63c -r 1906adbef2dc src/hotspot/share/gc/g1/collectionSetChooser.cpp --- 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()); } diff -r 6b5f3f5fd63c -r 1906adbef2dc src/hotspot/share/gc/g1/g1Allocator.cpp --- 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; diff -r 6b5f3f5fd63c -r 1906adbef2dc src/hotspot/share/gc/g1/g1CollectedHeap.cpp --- 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); } diff -r 6b5f3f5fd63c -r 1906adbef2dc src/hotspot/share/gc/g1/g1CollectedHeap.hpp --- 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 diff -r 6b5f3f5fd63c -r 1906adbef2dc src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp --- 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 diff -r 6b5f3f5fd63c -r 1906adbef2dc src/hotspot/share/gc/g1/g1ConcurrentMark.inline.hpp --- 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) { diff -r 6b5f3f5fd63c -r 1906adbef2dc src/hotspot/share/gc/g1/g1HeapTransition.cpp --- 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", diff -r 6b5f3f5fd63c -r 1906adbef2dc src/hotspot/share/gc/g1/g1HeapTransition.hpp --- 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; diff -r 6b5f3f5fd63c -r 1906adbef2dc src/hotspot/share/gc/g1/g1HeapVerifier.cpp --- 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); diff -r 6b5f3f5fd63c -r 1906adbef2dc src/hotspot/share/gc/g1/g1RemSet.cpp --- 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. diff -r 6b5f3f5fd63c -r 1906adbef2dc src/hotspot/share/gc/g1/g1RemSetSummary.cpp --- 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." diff -r 6b5f3f5fd63c -r 1906adbef2dc src/hotspot/share/gc/g1/g1RemSetTrackingPolicy.cpp --- 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(); diff -r 6b5f3f5fd63c -r 1906adbef2dc src/hotspot/share/gc/g1/heapRegion.hpp --- 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(); } diff -r 6b5f3f5fd63c -r 1906adbef2dc src/hotspot/share/gc/g1/heapRegion.inline.hpp --- 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(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 diff -r 6b5f3f5fd63c -r 1906adbef2dc src/hotspot/share/gc/g1/heapRegionSet.cpp --- 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."); +} diff -r 6b5f3f5fd63c -r 1906adbef2dc src/hotspot/share/gc/g1/heapRegionSet.hpp --- 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(); } diff -r 6b5f3f5fd63c -r 1906adbef2dc src/hotspot/share/gc/g1/heapRegionType.hpp --- 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; } diff -r 6b5f3f5fd63c -r 1906adbef2dc src/hotspot/share/gc/g1/vmStructs_g1.hpp --- 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) \ diff -r 6b5f3f5fd63c -r 1906adbef2dc src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/g1/G1CollectedHeap.java --- 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, diff -r 6b5f3f5fd63c -r 1906adbef2dc src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java --- 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:");