diff --git a/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 7df7b7fee8dbec5f0dfa1949b9def6084299e867..e138e8cceed7f06d33d251b50a8f872e49279ddd 100644 --- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -4736,7 +4736,7 @@ void G1PrintRegionLivenessInfoClosure::get_hum_bytes(size_t* used_bytes, } bool G1PrintRegionLivenessInfoClosure::doHeapRegion(HeapRegion* r) { - const char* type = ""; + const char* type = r->get_type_str(); HeapWord* bottom = r->bottom(); HeapWord* end = r->end(); size_t capacity_bytes = r->capacity(); @@ -4747,15 +4747,7 @@ bool G1PrintRegionLivenessInfoClosure::doHeapRegion(HeapRegion* r) { size_t remset_bytes = r->rem_set()->mem_size(); size_t strong_code_roots_bytes = r->rem_set()->strong_code_roots_mem_size(); - if (r->used() == 0) { - type = "FREE"; - } else if (r->is_survivor()) { - type = "SURV"; - } else if (r->is_young()) { - type = "EDEN"; - } else if (r->startsHumongous()) { - type = "HUMS"; - + if (r->startsHumongous()) { assert(_hum_used_bytes == 0 && _hum_capacity_bytes == 0 && _hum_prev_live_bytes == 0 && _hum_next_live_bytes == 0, "they should have been zeroed after the last time we used them"); @@ -4768,12 +4760,9 @@ bool G1PrintRegionLivenessInfoClosure::doHeapRegion(HeapRegion* r) { &prev_live_bytes, &next_live_bytes); end = bottom + HeapRegion::GrainWords; } else if (r->continuesHumongous()) { - type = "HUMC"; get_hum_bytes(&used_bytes, &capacity_bytes, &prev_live_bytes, &next_live_bytes); assert(end == bottom + HeapRegion::GrainWords, "invariant"); - } else { - type = "OLD"; } _total_used_bytes += used_bytes; diff --git a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index a05e0a4f310b2ebad983c4f494ec272e8c3344ee..9bd99122e9f3a49b27a9ba91f720c84e58e8ca61 100644 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -207,7 +207,10 @@ void YoungList::empty_list(HeapRegion* list) { HeapRegion* next = list->get_next_young_region(); list->set_next_young_region(NULL); list->uninstall_surv_rate_group(); - list->set_not_young(); + // This is called before a Full GC and all the non-empty / + // non-humongous regions at the end of the Full GC will end up as + // old anyway. + list->set_old(); list = next; } } @@ -366,7 +369,7 @@ void YoungList::print() { if (curr == NULL) gclog_or_tty->print_cr(" empty"); while (curr != NULL) { - gclog_or_tty->print_cr(" "HR_FORMAT", P: "PTR_FORMAT "N: "PTR_FORMAT", age: %4d", + gclog_or_tty->print_cr(" "HR_FORMAT", P: "PTR_FORMAT ", N: "PTR_FORMAT", age: %4d", HR_FORMAT_PARAMS(curr), curr->prev_top_at_mark_start(), curr->next_top_at_mark_start(), @@ -800,6 +803,7 @@ HeapWord* G1CollectedHeap::humongous_obj_allocate(size_t word_size, AllocationCo #ifdef ASSERT for (uint i = first; i < first + obj_regions; ++i) { HeapRegion* hr = region_at(i); + assert(hr->is_free(), "sanity"); assert(hr->is_empty(), "sanity"); assert(is_on_master_free_list(hr), "sanity"); } @@ -1227,21 +1231,21 @@ private: public: bool doHeapRegion(HeapRegion* hr) { assert(!hr->is_young(), "not expecting to find young regions"); - // We only generate output for non-empty regions. - if (!hr->is_empty()) { - if (!hr->isHumongous()) { - _hr_printer->post_compaction(hr, G1HRPrinter::Old); - } else if (hr->startsHumongous()) { - if (hr->region_num() == 1) { - // single humongous region - _hr_printer->post_compaction(hr, G1HRPrinter::SingleHumongous); - } else { - _hr_printer->post_compaction(hr, G1HRPrinter::StartsHumongous); - } + if (hr->is_free()) { + // We only generate output for non-empty regions. + } else if (hr->startsHumongous()) { + if (hr->region_num() == 1) { + // single humongous region + _hr_printer->post_compaction(hr, G1HRPrinter::SingleHumongous); } else { - assert(hr->continuesHumongous(), "only way to get here"); - _hr_printer->post_compaction(hr, G1HRPrinter::ContinuesHumongous); + _hr_printer->post_compaction(hr, G1HRPrinter::StartsHumongous); } + } else if (hr->continuesHumongous()) { + _hr_printer->post_compaction(hr, G1HRPrinter::ContinuesHumongous); + } else if (hr->is_old()) { + _hr_printer->post_compaction(hr, G1HRPrinter::Old); + } else { + ShouldNotReachHere(); } return false; } @@ -2127,8 +2131,8 @@ jint G1CollectedHeap::initialize() { // We'll re-use the same region whether the alloc region will // require BOT updates or not and, if it doesn't, then a non-young // region will complain that it cannot support allocations without - // BOT updates. So we'll tag the dummy region as young to avoid that. - dummy_region->set_young(); + // BOT updates. So we'll tag the dummy region as eden to avoid that. + dummy_region->set_eden(); // Make sure it's full. dummy_region->set_top(dummy_region->end()); G1AllocRegion::setup(this, dummy_region); @@ -4021,14 +4025,6 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { if (_hr_printer.is_active()) { HeapRegion* hr = g1_policy()->collection_set(); while (hr != NULL) { - G1HRPrinter::RegionType type; - if (!hr->is_young()) { - type = G1HRPrinter::Old; - } else if (hr->is_survivor()) { - type = G1HRPrinter::Survivor; - } else { - type = G1HRPrinter::Eden; - } _hr_printer.cset(hr); hr = hr->next_in_collection_set(); } @@ -5948,7 +5944,7 @@ void G1CollectedHeap::free_region(HeapRegion* hr, FreeRegionList* free_list, bool par, bool locked) { - assert(!hr->isHumongous(), "this is only for non-humongous regions"); + assert(!hr->is_free(), "the region should not be free"); assert(!hr->is_empty(), "the region should not be empty"); assert(_hrm.is_available(hr->hrm_index()), "region should be committed"); assert(free_list != NULL, "pre-condition"); @@ -5978,14 +5974,14 @@ void G1CollectedHeap::free_humongous_region(HeapRegion* hr, // We need to read this before we make the region non-humongous, // otherwise the information will be gone. uint last_index = hr->last_hc_index(); - hr->set_notHumongous(); + hr->clear_humongous(); free_region(hr, free_list, par); uint i = hr->hrm_index() + 1; while (i < last_index) { HeapRegion* curr_hr = region_at(i); assert(curr_hr->continuesHumongous(), "invariant"); - curr_hr->set_notHumongous(); + curr_hr->clear_humongous(); free_region(curr_hr, free_list, par); i += 1; } @@ -6290,9 +6286,9 @@ void G1CollectedHeap::free_collection_set(HeapRegion* cs_head, EvacuationInfo& e if (cur->is_young()) { cur->set_young_index_in_cset(-1); } - cur->set_not_young(); cur->set_evacuation_failed(false); // The region is now considered to be old. + cur->set_old(); _old_set.add(cur); evacuation_info.increment_collectionset_used_after(cur->used()); } @@ -6579,16 +6575,15 @@ public: TearDownRegionSetsClosure(HeapRegionSet* old_set) : _old_set(old_set) { } bool doHeapRegion(HeapRegion* r) { - if (r->is_empty()) { - // We ignore empty regions, we'll empty the free list afterwards - } else if (r->is_young()) { - // We ignore young regions, we'll empty the young list afterwards - } else if (r->isHumongous()) { - // We ignore humongous regions, we're not tearing down the - // humongous region set - } else { - // The rest should be old + if (r->is_old()) { _old_set->remove(r); + } else { + // We ignore free regions, we'll empty the free list afterwards. + // We ignore young regions, we'll empty the young list afterwards. + // We ignore humongous regions, we're not tearing down the + // humongous regions set. + assert(r->is_free() || r->is_young() || r->isHumongous(), + "it cannot be another type"); } return false; } @@ -6638,6 +6633,7 @@ public: if (r->is_empty()) { // Add free regions to the free list + r->set_free(); r->set_allocation_context(AllocationContext::system()); _hrm->insert_into_free_list(r); } else if (!_free_list_only) { @@ -6646,7 +6642,11 @@ public: if (r->isHumongous()) { // We ignore humongous regions, we left the humongous set unchanged } else { - // The rest should be old, add them to the old set + // Objects that were compacted would have ended up on regions + // that were previously old or free. + assert(r->is_free() || r->is_old(), "invariant"); + // We now consider them old, so register as such. + r->set_old(); _old_set->add(r); } _total_used += r->used(); @@ -6713,7 +6713,7 @@ HeapRegion* G1CollectedHeap::new_mutator_alloc_region(size_t word_size, void G1CollectedHeap::retire_mutator_alloc_region(HeapRegion* alloc_region, size_t allocated_bytes) { assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */); - assert(alloc_region->is_young(), "all mutator alloc regions should be young"); + assert(alloc_region->is_eden(), "all mutator alloc regions should be eden"); g1_policy()->add_region_to_incremental_cset_lhs(alloc_region); _allocator->increase_used(allocated_bytes); @@ -6762,6 +6762,7 @@ HeapRegion* G1CollectedHeap::new_gc_alloc_region(size_t word_size, _hr_printer.alloc(new_alloc_region, G1HRPrinter::Survivor); check_bitmaps("Survivor Region Allocation", new_alloc_region); } else { + new_alloc_region->set_old(); _hr_printer.alloc(new_alloc_region, G1HRPrinter::Old); check_bitmaps("Old Region Allocation", new_alloc_region); } @@ -6821,9 +6822,11 @@ public: } else if (hr->is_empty()) { assert(_hrm->is_free(hr), err_msg("Heap region %u is empty but not on the free list.", hr->hrm_index())); _free_count.increment(1u, hr->capacity()); - } else { + } else if (hr->is_old()) { assert(hr->containing_set() == _old_set, err_msg("Heap region %u is old but not in the old set.", hr->hrm_index())); _old_count.increment(1u, hr->capacity()); + } else { + ShouldNotReachHere(); } return false; } diff --git a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index bd3bbe905ef4768a650e8b613b83693ddaa0e073..aa8695747658f0e78652d2317eeaa93096a30eb7 100644 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -1664,7 +1664,7 @@ G1CollectorPolicy::record_concurrent_mark_cleanup_end(int no_of_gc_threads) { // Add the heap region at the head of the non-incremental collection set void G1CollectorPolicy::add_old_region_to_cset(HeapRegion* hr) { assert(_inc_cset_build_state == Active, "Precondition"); - assert(!hr->is_young(), "non-incremental add of young region"); + assert(hr->is_old(), "the region should be old"); assert(!hr->in_collection_set(), "should not already be in the CSet"); hr->set_in_collection_set(true); @@ -1810,7 +1810,7 @@ void G1CollectorPolicy::add_region_to_incremental_cset_common(HeapRegion* hr) { // Add the region at the RHS of the incremental cset void G1CollectorPolicy::add_region_to_incremental_cset_rhs(HeapRegion* hr) { // We should only ever be appending survivors at the end of a pause - assert( hr->is_survivor(), "Logic"); + assert(hr->is_survivor(), "Logic"); // Do the 'common' stuff add_region_to_incremental_cset_common(hr); @@ -1828,7 +1828,7 @@ void G1CollectorPolicy::add_region_to_incremental_cset_rhs(HeapRegion* hr) { // Add the region to the LHS of the incremental cset void G1CollectorPolicy::add_region_to_incremental_cset_lhs(HeapRegion* hr) { // Survivors should be added to the RHS at the end of a pause - assert(!hr->is_survivor(), "Logic"); + assert(hr->is_eden(), "Logic"); // Do the 'common' stuff add_region_to_incremental_cset_common(hr); @@ -1988,7 +1988,11 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms, EvacuationInf HeapRegion* hr = young_list->first_survivor_region(); while (hr != NULL) { assert(hr->is_survivor(), "badly formed young list"); - hr->set_young(); + // There is a convention that all the young regions in the CSet + // are tagged as "eden", so we do this for the survivors here. We + // use the special set_eden_pre_gc() as it doesn't check that the + // region is free (which is not the case here). + hr->set_eden_pre_gc(); hr = hr->get_next_young_region(); } diff --git a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp index 29f7446cbf19c36ede794a746f01a4fbc16a0510..b95824fef1da8bcec0a8890cfe1822c9b935f96e 100644 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp @@ -299,13 +299,13 @@ public: // Accessors void set_region_eden(HeapRegion* hr, int young_index_in_cset) { - hr->set_young(); + hr->set_eden(); hr->install_surv_rate_group(_short_lived_surv_rate_group); hr->set_young_index_in_cset(young_index_in_cset); } void set_region_survivor(HeapRegion* hr, int young_index_in_cset) { - assert(hr->is_young() && hr->is_survivor(), "pre-condition"); + assert(hr->is_survivor(), "pre-condition"); hr->install_surv_rate_group(_survivor_surv_rate_group); hr->set_young_index_in_cset(young_index_in_cset); } diff --git a/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp b/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp index 07da90808356731b3df02e4b149b4e20e4e1700c..0c51c318f2e6ce6e4bb294f468101bc31df38b2b 100644 --- a/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp +++ b/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp @@ -27,7 +27,6 @@ #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1HotCardCache.hpp" #include "gc_implementation/g1/g1RemSet.hpp" -#include "gc_implementation/g1/heapRegion.hpp" #include "runtime/atomic.hpp" G1HotCardCache::G1HotCardCache(G1CollectedHeap *g1h): @@ -136,7 +135,6 @@ void G1HotCardCache::drain(uint worker_i, } void G1HotCardCache::reset_card_counts(HeapRegion* hr) { - assert(!hr->isHumongous(), "Should have been cleared"); _card_counts.clear_region(hr); } diff --git a/src/share/vm/gc_implementation/g1/g1RemSetSummary.cpp b/src/share/vm/gc_implementation/g1/g1RemSetSummary.cpp index cdc13041a5d20a062a0e6fcfe39132510cc60a43..062d7abe2c58dc46f37365743dab18a6fb07e5eb 100644 --- a/src/share/vm/gc_implementation/g1/g1RemSetSummary.cpp +++ b/src/share/vm/gc_implementation/g1/g1RemSetSummary.cpp @@ -258,14 +258,16 @@ public: size_t code_root_elems = hrrs->strong_code_roots_list_length(); RegionTypeCounter* current = NULL; - if (r->is_young()) { + if (r->is_free()) { + current = &_free; + } else if (r->is_young()) { current = &_young; } else if (r->isHumongous()) { current = &_humonguous; - } else if (r->is_empty()) { - current = &_free; - } else { + } else if (r->is_old()) { current = &_old; + } else { + ShouldNotReachHere(); } current->add(rs_mem_sz, occupied_cards, code_root_mem_sz, code_root_elems); _all.add(rs_mem_sz, occupied_cards, code_root_mem_sz, code_root_elems); diff --git a/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp b/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp index f02c28c227b5fb291bca1be135a7d62d8af5d858..80c402e995415dce682914d508383a7789e4c6b3 100644 --- a/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp +++ b/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp @@ -31,8 +31,6 @@ #include "oops/oop.inline.hpp" #include "utilities/macros.hpp" -#if INCLUDE_ALL_GCS - class DirtyCardQueueSet; class G1SATBCardTableLoggingModRefBS; @@ -180,7 +178,4 @@ class G1SATBCardTableLoggingModRefBS: public G1SATBCardTableModRefBS { void write_ref_array_work(MemRegion mr) { invalidate(mr); } }; - -#endif // INCLUDE_ALL_GCS - #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1SATBCARDTABLEMODREFBS_HPP diff --git a/src/share/vm/gc_implementation/g1/heapRegion.cpp b/src/share/vm/gc_implementation/g1/heapRegion.cpp index 17f902aa185d0bbf4c741c6a1e0474e89c13686f..a98d687309e269e544c2476dc834a124e2645d60 100644 --- a/src/share/vm/gc_implementation/g1/heapRegion.cpp +++ b/src/share/vm/gc_implementation/g1/heapRegion.cpp @@ -195,8 +195,6 @@ void HeapRegion::reset_after_compaction() { } void HeapRegion::hr_clear(bool par, bool clear_space, bool locked) { - assert(_humongous_type == NotHumongous, - "we should have already filtered out humongous regions"); assert(_humongous_start_region == NULL, "we should have already filtered out humongous regions"); assert(_end == _orig_end, @@ -207,7 +205,7 @@ void HeapRegion::hr_clear(bool par, bool clear_space, bool locked) { set_allocation_context(AllocationContext::system()); set_young_index_in_cset(-1); uninstall_surv_rate_group(); - set_young_type(NotYoung); + set_free(); reset_pre_dummy_top(); if (!par) { @@ -258,7 +256,7 @@ void HeapRegion::set_startsHumongous(HeapWord* new_top, HeapWord* new_end) { assert(top() == bottom(), "should be empty"); assert(bottom() <= new_top && new_top <= new_end, "pre-condition"); - _humongous_type = StartsHumongous; + _type.set_starts_humongous(); _humongous_start_region = this; set_end(new_end); @@ -272,11 +270,11 @@ void HeapRegion::set_continuesHumongous(HeapRegion* first_hr) { assert(top() == bottom(), "should be empty"); assert(first_hr->startsHumongous(), "pre-condition"); - _humongous_type = ContinuesHumongous; + _type.set_continues_humongous(); _humongous_start_region = first_hr; } -void HeapRegion::set_notHumongous() { +void HeapRegion::clear_humongous() { assert(isHumongous(), "pre-condition"); if (startsHumongous()) { @@ -292,7 +290,6 @@ void HeapRegion::set_notHumongous() { } assert(capacity() == HeapRegion::GrainBytes, "pre-condition"); - _humongous_type = NotHumongous; _humongous_start_region = NULL; } @@ -336,12 +333,12 @@ HeapRegion::HeapRegion(uint hrm_index, G1OffsetTableContigSpace(sharedOffsetArray, mr), _hrm_index(hrm_index), _allocation_context(AllocationContext::system()), - _humongous_type(NotHumongous), _humongous_start_region(NULL), + _humongous_start_region(NULL), _in_collection_set(false), _next_in_special_set(NULL), _orig_end(NULL), _claimed(InitialClaimValue), _evacuation_failed(false), _prev_marked_bytes(0), _next_marked_bytes(0), _gc_efficiency(0.0), - _young_type(NotYoung), _next_young_region(NULL), + _next_young_region(NULL), _next_dirty_cards_region(NULL), _next(NULL), _prev(NULL), #ifdef ASSERT _containing_set(NULL), @@ -703,27 +700,11 @@ void HeapRegion::verify_strong_code_roots(VerifyOption vo, bool* failures) const void HeapRegion::print() const { print_on(gclog_or_tty); } void HeapRegion::print_on(outputStream* st) const { st->print("AC%4u", allocation_context()); - - if (isHumongous()) { - if (startsHumongous()) - st->print(" HS"); - else - st->print(" HC"); - } else { - st->print(" "); - } + st->print(" %2s", get_short_type_str()); if (in_collection_set()) st->print(" CS"); else st->print(" "); - if (is_young()) - st->print(is_survivor() ? " SU" : " Y "); - else - st->print(" "); - if (is_empty()) - st->print(" F"); - else - st->print(" "); st->print(" TS %5d", _gc_time_stamp); st->print(" PTAMS "PTR_FORMAT" NTAMS "PTR_FORMAT, prev_top_at_mark_start(), next_top_at_mark_start()); diff --git a/src/share/vm/gc_implementation/g1/heapRegion.hpp b/src/share/vm/gc_implementation/g1/heapRegion.hpp index 11d2f6d1e2c8db6996196a6375bbd2bd64456cdb..8f19eb0b5be0d71189c7b977a09969c85a801a30 100644 --- a/src/share/vm/gc_implementation/g1/heapRegion.hpp +++ b/src/share/vm/gc_implementation/g1/heapRegion.hpp @@ -28,6 +28,7 @@ #include "gc_implementation/g1/g1AllocationContext.hpp" #include "gc_implementation/g1/g1BlockOffsetTable.hpp" #include "gc_implementation/g1/g1_specialized_oop_closures.hpp" +#include "gc_implementation/g1/heapRegionType.hpp" #include "gc_implementation/g1/survRateGroup.hpp" #include "gc_implementation/shared/ageTable.hpp" #include "gc_implementation/shared/spaceDecorator.hpp" @@ -35,8 +36,6 @@ #include "memory/watermark.hpp" #include "utilities/macros.hpp" -#if INCLUDE_ALL_GCS - // A HeapRegion is the smallest piece of a G1CollectedHeap that // can be collected independently. @@ -56,10 +55,7 @@ class nmethod; #define HR_FORMAT "%u:(%s)["PTR_FORMAT","PTR_FORMAT","PTR_FORMAT"]" #define HR_FORMAT_PARAMS(_hr_) \ (_hr_)->hrm_index(), \ - (_hr_)->is_survivor() ? "S" : (_hr_)->is_young() ? "E" : \ - (_hr_)->startsHumongous() ? "HS" : \ - (_hr_)->continuesHumongous() ? "HC" : \ - !(_hr_)->is_empty() ? "O" : "F", \ + (_hr_)->get_short_type_str(), \ p2i((_hr_)->bottom()), p2i((_hr_)->top()), p2i((_hr_)->end()) // sentinel value for hrm_index @@ -220,12 +216,6 @@ class HeapRegion: public G1OffsetTableContigSpace { friend class VMStructs; private: - enum HumongousType { - NotHumongous = 0, - StartsHumongous, - ContinuesHumongous - }; - // The remembered set for this region. // (Might want to make this "inline" later, to avoid some alloc failure // issues.) @@ -239,7 +229,8 @@ class HeapRegion: public G1OffsetTableContigSpace { AllocationContext_t _allocation_context; - HumongousType _humongous_type; + HeapRegionType _type; + // For a humongous region, region in which it starts. HeapRegion* _humongous_start_region; // For the start region of a humongous sequence, it's original end(). @@ -281,13 +272,6 @@ class HeapRegion: public G1OffsetTableContigSpace { // The calculated GC efficiency of the region. double _gc_efficiency; - enum YoungType { - NotYoung, // a region is not young - Young, // a region is young - Survivor // a region is young and it contains survivors - }; - - volatile YoungType _young_type; int _young_index_in_cset; SurvRateGroup* _surv_rate_group; int _age_index; @@ -312,12 +296,6 @@ class HeapRegion: public G1OffsetTableContigSpace { _next_top_at_mark_start = bot; } - void set_young_type(YoungType new_type) { - //assert(_young_type != new_type, "setting the same type" ); - // TODO: add more assertions here - _young_type = new_type; - } - // Cached attributes used in the collection set policy information // The RSet length that was added to the total value @@ -437,9 +415,21 @@ class HeapRegion: public G1OffsetTableContigSpace { _prev_marked_bytes = _next_marked_bytes = 0; } - bool isHumongous() const { return _humongous_type != NotHumongous; } - bool startsHumongous() const { return _humongous_type == StartsHumongous; } - bool continuesHumongous() const { return _humongous_type == ContinuesHumongous; } + const char* get_type_str() const { return _type.get_str(); } + const char* get_short_type_str() const { return _type.get_short_str(); } + + bool is_free() const { return _type.is_free(); } + + bool is_young() const { return _type.is_young(); } + bool is_eden() const { return _type.is_eden(); } + bool is_survivor() const { return _type.is_survivor(); } + + bool isHumongous() const { return _type.is_humongous(); } + bool startsHumongous() const { return _type.is_starts_humongous(); } + bool continuesHumongous() const { return _type.is_continues_humongous(); } + + bool is_old() const { return _type.is_old(); } + // For a humongous region, region in which it starts. HeapRegion* humongous_start_region() const { return _humongous_start_region; @@ -503,7 +493,7 @@ class HeapRegion: public G1OffsetTableContigSpace { void set_continuesHumongous(HeapRegion* first_hr); // Unsets the humongous-related fields on the region. - void set_notHumongous(); + void clear_humongous(); // If the region has a remembered set, return a pointer to it. HeapRegionRemSet* rem_set() const { @@ -638,9 +628,6 @@ class HeapRegion: public G1OffsetTableContigSpace { void calc_gc_efficiency(void); double gc_efficiency() { return _gc_efficiency;} - bool is_young() const { return _young_type != NotYoung; } - bool is_survivor() const { return _young_type == Survivor; } - int young_index_in_cset() const { return _young_index_in_cset; } void set_young_index_in_cset(int index) { assert( (index == -1) || is_young(), "pre-condition" ); @@ -692,11 +679,13 @@ class HeapRegion: public G1OffsetTableContigSpace { } } - void set_young() { set_young_type(Young); } + void set_free() { _type.set_free(); } - void set_survivor() { set_young_type(Survivor); } + void set_eden() { _type.set_eden(); } + void set_eden_pre_gc() { _type.set_eden_pre_gc(); } + void set_survivor() { _type.set_survivor(); } - void set_not_young() { set_young_type(NotYoung); } + void set_old() { _type.set_old(); } // Determine if an object has been allocated since the last // mark performed by the collector. This returns true iff the object @@ -841,6 +830,4 @@ class HeapRegionClosure : public StackObj { bool complete() { return _complete; } }; -#endif // INCLUDE_ALL_GCS - #endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGION_HPP diff --git a/src/share/vm/gc_implementation/g1/heapRegionSet.cpp b/src/share/vm/gc_implementation/g1/heapRegionSet.cpp index 7f3e76ad15cc192ea087e18f0b22cf0886352388..8fde2455f1d5e940fbb397a0b6d99594c050d4c8 100644 --- a/src/share/vm/gc_implementation/g1/heapRegionSet.cpp +++ b/src/share/vm/gc_implementation/g1/heapRegionSet.cpp @@ -42,7 +42,9 @@ void HeapRegionSetBase::verify_region(HeapRegion* hr) { assert(hr->containing_set() == this, err_msg("Inconsistent containing set for %u", hr->hrm_index())); assert(!hr->is_young(), err_msg("Adding young region %u", hr->hrm_index())); // currently we don't use these sets for young regions assert(hr->isHumongous() == regions_humongous(), err_msg("Wrong humongous state for region %u and set %s", hr->hrm_index(), name())); - assert(hr->is_empty() == regions_empty(), err_msg("Wrong empty state for region %u and set %s", hr->hrm_index(), name())); + assert(hr->is_free() == regions_free(), err_msg("Wrong free state for region %u and set %s", hr->hrm_index(), name())); + assert(!hr->is_free() || hr->is_empty(), err_msg("Free region %u is not empty for set %s", hr->hrm_index(), name())); + assert(!hr->is_empty() || hr->is_free(), err_msg("Empty region %u is not free for set %s", hr->hrm_index(), name())); assert(hr->rem_set()->verify_ready_for_par_iteration(), err_msg("Wrong iteration state %u", hr->hrm_index())); } #endif @@ -85,16 +87,16 @@ void HeapRegionSetBase::print_on(outputStream* out, bool print_contents) { out->print_cr("Set: %s ("PTR_FORMAT")", name(), this); out->print_cr(" Region Assumptions"); out->print_cr(" humongous : %s", BOOL_TO_STR(regions_humongous())); - out->print_cr(" empty : %s", BOOL_TO_STR(regions_empty())); + out->print_cr(" free : %s", BOOL_TO_STR(regions_free())); out->print_cr(" Attributes"); out->print_cr(" length : %14u", length()); out->print_cr(" total capacity : "SIZE_FORMAT_W(14)" bytes", total_capacity_bytes()); } -HeapRegionSetBase::HeapRegionSetBase(const char* name, bool humongous, bool empty, HRSMtSafeChecker* mt_safety_checker) +HeapRegionSetBase::HeapRegionSetBase(const char* name, bool humongous, bool free, HRSMtSafeChecker* mt_safety_checker) : _name(name), _verify_in_progress(false), - _is_humongous(humongous), _is_empty(empty), _mt_safety_checker(mt_safety_checker), + _is_humongous(humongous), _is_free(free), _mt_safety_checker(mt_safety_checker), _count() { } diff --git a/src/share/vm/gc_implementation/g1/heapRegionSet.hpp b/src/share/vm/gc_implementation/g1/heapRegionSet.hpp index db501993685c0e1ce1130ae06f1b863cf2bf01f9..9a9267c4b9b9d062e8430841e86e6e448f1b70da 100644 --- a/src/share/vm/gc_implementation/g1/heapRegionSet.hpp +++ b/src/share/vm/gc_implementation/g1/heapRegionSet.hpp @@ -81,7 +81,7 @@ class HeapRegionSetBase VALUE_OBJ_CLASS_SPEC { friend class VMStructs; private: bool _is_humongous; - bool _is_empty; + bool _is_free; HRSMtSafeChecker* _mt_safety_checker; protected: @@ -102,9 +102,9 @@ protected: // not. Only used during verification. bool regions_humongous() { return _is_humongous; } - // Indicates whether all regions in the set should be empty or + // Indicates whether all regions in the set should be free or // not. Only used during verification. - bool regions_empty() { return _is_empty; } + bool regions_free() { return _is_free; } void check_mt_safety() { if (_mt_safety_checker != NULL) { @@ -114,7 +114,7 @@ protected: virtual void fill_in_ext_msg_extra(hrs_ext_msg* msg) { } - HeapRegionSetBase(const char* name, bool humongous, bool empty, HRSMtSafeChecker* mt_safety_checker); + HeapRegionSetBase(const char* name, bool humongous, bool free, HRSMtSafeChecker* mt_safety_checker); public: const char* name() { return _name; } @@ -171,7 +171,7 @@ public: do { \ assert(((_set1_)->regions_humongous() == \ (_set2_)->regions_humongous()) && \ - ((_set1_)->regions_empty() == (_set2_)->regions_empty()), \ + ((_set1_)->regions_free() == (_set2_)->regions_free()), \ hrs_err_msg("the contents of set %s and set %s should match", \ (_set1_)->name(), (_set2_)->name())); \ } while (0) @@ -184,7 +184,7 @@ public: class HeapRegionSet : public HeapRegionSetBase { public: HeapRegionSet(const char* name, bool humongous, HRSMtSafeChecker* mt_safety_checker): - HeapRegionSetBase(name, humongous, false /* empty */, mt_safety_checker) { } + HeapRegionSetBase(name, humongous, false /* free */, mt_safety_checker) { } void bulk_remove(const HeapRegionSetCount& removed) { _count.decrement(removed.length(), removed.capacity()); diff --git a/src/share/vm/gc_implementation/g1/heapRegionType.cpp b/src/share/vm/gc_implementation/g1/heapRegionType.cpp new file mode 100644 index 0000000000000000000000000000000000000000..347b58d79960c5f5b45ce6af9aef716c0a1f012b --- /dev/null +++ b/src/share/vm/gc_implementation/g1/heapRegionType.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014, 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_implementation/g1/heapRegionType.hpp" + +bool HeapRegionType::is_valid(Tag tag) { + switch (tag) { + case FreeTag: + case EdenTag: + case SurvTag: + case HumStartsTag: + case HumContTag: + case OldTag: + return true; + } + return false; +} + +const char* HeapRegionType::get_str() const { + hrt_assert_is_valid(_tag); + switch (_tag) { + case FreeTag: return "FREE"; + case EdenTag: return "EDEN"; + case SurvTag: return "SURV"; + case HumStartsTag: return "HUMS"; + case HumContTag: return "HUMC"; + case OldTag: return "OLD"; + } + ShouldNotReachHere(); + // keep some compilers happy + return NULL; +} + +const char* HeapRegionType::get_short_str() const { + hrt_assert_is_valid(_tag); + switch (_tag) { + case FreeTag: return "F"; + case EdenTag: return "E"; + case SurvTag: return "S"; + case HumStartsTag: return "HS"; + case HumContTag: return "HC"; + case OldTag: return "O"; + } + ShouldNotReachHere(); + // keep some compilers happy + return NULL; +} diff --git a/src/share/vm/gc_implementation/g1/heapRegionType.hpp b/src/share/vm/gc_implementation/g1/heapRegionType.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b00590a6b78101d44caa59edf547f66318c29f8b --- /dev/null +++ b/src/share/vm/gc_implementation/g1/heapRegionType.hpp @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2014, 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_VM_GC_IMPLEMENTATION_G1_HEAPREGIONTYPE_HPP +#define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONTYPE_HPP + +#include "memory/allocation.hpp" + +#define hrt_assert_is_valid(tag) \ + assert(is_valid((tag)), err_msg("invalid HR type: %u", (uint) (tag))) + +class HeapRegionType VALUE_OBJ_CLASS_SPEC { +private: + // We encode the value of the heap region type so the generation can be + // determined quickly. The tag is split into two parts: + // + // major type (young, humongous) : top N-1 bits + // minor type (eden / survivor, starts / cont hum, etc.) : bottom 1 bit + // + // If there's need to increase the number of minor types in the + // future, we'll have to increase the size of the latter and hence + // decrease the size of the former. + // + // 0000 0 [ 0] Free + // + // 0001 0 Young Mask + // 0001 0 [ 2] Eden + // 0001 1 [ 3] Survivor + // + // 0010 0 Humongous Mask + // 0010 0 [ 4] Humongous Starts + // 0010 1 [ 5] Humongous Continues + // + // 01000 [ 8] Old + typedef enum { + FreeTag = 0, + + YoungMask = 2, + EdenTag = YoungMask, + SurvTag = YoungMask + 1, + + HumMask = 4, + HumStartsTag = HumMask, + HumContTag = HumMask + 1, + + OldTag = 8 + } Tag; + + volatile Tag _tag; + + static bool is_valid(Tag tag); + + Tag get() const { + hrt_assert_is_valid(_tag); + return _tag; + } + + // Sets the type to 'tag'. + void set(Tag tag) { + hrt_assert_is_valid(tag); + hrt_assert_is_valid(_tag); + _tag = tag; + } + + // Sets the type to 'tag', expecting the type to be 'before'. This + // is available for when we want to add sanity checking to the type + // transition. + void set_from(Tag tag, Tag before) { + hrt_assert_is_valid(tag); + hrt_assert_is_valid(before); + hrt_assert_is_valid(_tag); + assert(_tag == before, + err_msg("HR tag: %u, expected: %u new tag; %u", _tag, before, tag)); + _tag = tag; + } + +public: + // Queries + + bool is_free() const { return get() == FreeTag; } + + bool is_young() const { return (get() & YoungMask) != 0; } + bool is_eden() const { return get() == EdenTag; } + bool is_survivor() const { return get() == SurvTag; } + + bool is_humongous() const { return (get() & HumMask) != 0; } + bool is_starts_humongous() const { return get() == HumStartsTag; } + bool is_continues_humongous() const { return get() == HumContTag; } + + bool is_old() const { return get() == OldTag; } + + // Setters + + void set_free() { set(FreeTag); } + + void set_eden() { set_from(EdenTag, FreeTag); } + void set_eden_pre_gc() { set_from(EdenTag, SurvTag); } + void set_survivor() { set_from(SurvTag, FreeTag); } + + void set_starts_humongous() { set_from(HumStartsTag, FreeTag); } + void set_continues_humongous() { set_from(HumContTag, FreeTag); } + + void set_old() { set(OldTag); } + + // Misc + + const char* get_str() const; + const char* get_short_str() const; + + HeapRegionType() : _tag(FreeTag) { hrt_assert_is_valid(_tag); } +}; + +#endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONTYPE_HPP