diff --git a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 36d5cbd89d37cc41ce7da7a3d9905f3d8af1efb8..360bd9e0ce6534499bbd9b073bedcedaf77d0aa6 100644 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -25,6 +25,8 @@ #include "incls/_precompiled.incl" #include "incls/_g1CollectedHeap.cpp.incl" +size_t G1CollectedHeap::_humongous_object_threshold_in_words = 0; + // turn it on so that the contents of the young list (scan-only / // to-be-collected) are printed at "strategic" points before / during // / after the collection --- this is useful for debugging @@ -1394,6 +1396,9 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) : if (_process_strong_tasks == NULL || !_process_strong_tasks->valid()) { vm_exit_during_initialization("Failed necessary allocation."); } + + _humongous_object_threshold_in_words = HeapRegion::GrainWords / 2; + int n_queues = MAX2((int)ParallelGCThreads, 1); _task_queues = new RefToScanQueueSet(n_queues); @@ -1546,9 +1551,10 @@ jint G1CollectedHeap::initialize() { const size_t max_region_idx = ((size_t)1 << (sizeof(RegionIdx_t)*BitsPerByte-1)) - 1; guarantee((max_regions() - 1) <= max_region_idx, "too many regions"); - const size_t cards_per_region = HeapRegion::GrainBytes >> CardTableModRefBS::card_shift; size_t max_cards_per_region = ((size_t)1 << (sizeof(CardIdx_t)*BitsPerByte-1)) - 1; - guarantee(cards_per_region < max_cards_per_region, "too many cards per region"); + guarantee(HeapRegion::CardsPerRegion > 0, "make sure it's initialized"); + guarantee((size_t) HeapRegion::CardsPerRegion < max_cards_per_region, + "too many cards per region"); _bot_shared = new G1BlockOffsetSharedArray(_reserved, heap_word_size(init_byte_size)); diff --git a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 04a69fef3ed1a18902ca26944067c43e180f299d..4ce7bdcfee8b0064160fe5b0e2e684acc575ddd1 100644 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -167,16 +167,11 @@ class G1CollectedHeap : public SharedHeap { friend class G1MarkSweep; private: - enum SomePrivateConstants { - VeryLargeInBytes = HeapRegion::GrainBytes/2, - VeryLargeInWords = VeryLargeInBytes/HeapWordSize, - MinHeapDeltaBytes = 10 * HeapRegion::GrainBytes, // FIXME - NumAPIs = HeapRegion::MaxAge - }; - // The one and only G1CollectedHeap, so static functions can find it. static G1CollectedHeap* _g1h; + static size_t _humongous_object_threshold_in_words; + // Storage for the G1 heap (excludes the permanent generation). VirtualSpace _g1_storage; MemRegion _g1_reserved; @@ -1021,7 +1016,7 @@ public: // Returns "true" iff the given word_size is "very large". static bool isHumongous(size_t word_size) { - return word_size >= VeryLargeInWords; + return word_size >= _humongous_object_threshold_in_words; } // Update mod union table with the set of dirty cards. diff --git a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index 6e457eeb96f1d626d91218454c0cd7ff8b28f880..ecbddba4404ea0e7023575969704378e86a12a64 100644 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -201,6 +201,11 @@ G1CollectorPolicy::G1CollectorPolicy() : _survivors_age_table(true) { + // Set up the region size and associated fields. Given that the + // policy is created before the heap, we have to set this up here, + // so it's done as soon as possible. + HeapRegion::setup_heap_region_size(Arguments::min_heap_size()); + _recent_prev_end_times_for_all_gcs_sec->add(os::elapsedTime()); _prev_collection_pause_end_ms = os::elapsedTime() * 1000.0; diff --git a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp index 09d839eeb1060ffa58051b48a9c007d5e86c3c39..0dff91a0b509c30408ce2fc95eb5e8636202cea8 100644 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp @@ -92,9 +92,7 @@ protected: int _parallel_gc_threads; enum SomePrivateConstants { - NumPrevPausesForHeuristics = 10, - NumPrevGCsForHeuristics = 10, - NumAPIs = HeapRegion::MaxAge + NumPrevPausesForHeuristics = 10 }; G1MMUTracker* _mmu_tracker; diff --git a/src/share/vm/gc_implementation/g1/g1_globals.hpp b/src/share/vm/gc_implementation/g1/g1_globals.hpp index 9c5a82090b586816713756b5c342d1a346992ede..b56a02813138142d40bb69ddfadecd4da5b2b440 100644 --- a/src/share/vm/gc_implementation/g1/g1_globals.hpp +++ b/src/share/vm/gc_implementation/g1/g1_globals.hpp @@ -37,7 +37,7 @@ develop(intx, G1MarkingOverheadPercent, 0, \ "Overhead of concurrent marking") \ \ - product(intx, G1YoungGenSize, 0, \ + product(uintx, G1YoungGenSize, 0, \ "Size of the G1 young generation, 0 is the adaptive policy") \ \ develop(bool, G1Gen, true, \ @@ -246,6 +246,9 @@ "If non-0 is the size of the G1 survivor space, " \ "otherwise SurvivorRatio is used to determine the size") \ \ + product(uintx, G1HeapRegionSize, 0, \ + "Size of the G1 regions.") \ + \ experimental(bool, G1ParallelRSetUpdatingEnabled, false, \ "Enables the parallelization of remembered set updating " \ "during evacuation pauses") \ diff --git a/src/share/vm/gc_implementation/g1/heapRegion.cpp b/src/share/vm/gc_implementation/g1/heapRegion.cpp index 55a0d023c34a30fbf90c9ac0ee3ab7f44a25deb5..6cbdf87583bf709a78a507be3172b4bc38fdc85e 100644 --- a/src/share/vm/gc_implementation/g1/heapRegion.cpp +++ b/src/share/vm/gc_implementation/g1/heapRegion.cpp @@ -25,6 +25,12 @@ #include "incls/_precompiled.incl" #include "incls/_heapRegion.cpp.incl" +int HeapRegion::LogOfHRGrainBytes = 0; +int HeapRegion::LogOfHRGrainWords = 0; +int HeapRegion::GrainBytes = 0; +int HeapRegion::GrainWords = 0; +int HeapRegion::CardsPerRegion = 0; + HeapRegionDCTOC::HeapRegionDCTOC(G1CollectedHeap* g1, HeapRegion* hr, OopClosure* cl, CardTableModRefBS::PrecisionStyle precision, @@ -231,6 +237,73 @@ void HeapRegionDCTOC::walk_mem_region_with_cl(MemRegion mr, } } +// Minimum region size; we won't go lower than that. +// We might want to decrease this in the future, to deal with small +// heaps a bit more efficiently. +#define MIN_REGION_SIZE ( 1024 * 1024 ) + +// Maximum region size; we don't go higher than that. There's a good +// reason for having an upper bound. We don't want regions to get too +// large, otherwise cleanup's effectiveness would decrease as there +// will be fewer opportunities to find totally empty regions after +// marking. +#define MAX_REGION_SIZE ( 32 * 1024 * 1024 ) + +// The automatic region size calculation will try to have around this +// many regions in the heap (based on the min heap size). +#define TARGET_REGION_NUMBER 2048 + +void HeapRegion::setup_heap_region_size(uintx min_heap_size) { + // region_size in bytes + uintx region_size = G1HeapRegionSize; + if (FLAG_IS_DEFAULT(G1HeapRegionSize)) { + // We base the automatic calculation on the min heap size. This + // can be problematic if the spread between min and max is quite + // wide, imagine -Xms128m -Xmx32g. But, if we decided it based on + // the max size, the region size might be way too large for the + // min size. Either way, some users might have to set the region + // size manually for some -Xms / -Xmx combos. + + region_size = MAX2(min_heap_size / TARGET_REGION_NUMBER, + (uintx) MIN_REGION_SIZE); + } + + int region_size_log = log2_long((jlong) region_size); + // Recalculate the region size to make sure it's a power of + // 2. This means that region_size is the largest power of 2 that's + // <= what we've calculated so far. + region_size = 1 << region_size_log; + + // Now make sure that we don't go over or under our limits. + if (region_size < MIN_REGION_SIZE) { + region_size = MIN_REGION_SIZE; + } else if (region_size > MAX_REGION_SIZE) { + region_size = MAX_REGION_SIZE; + } + + // And recalculate the log. + region_size_log = log2_long((jlong) region_size); + + // Now, set up the globals. + guarantee(LogOfHRGrainBytes == 0, "we should only set it once"); + LogOfHRGrainBytes = region_size_log; + + guarantee(LogOfHRGrainWords == 0, "we should only set it once"); + LogOfHRGrainWords = LogOfHRGrainBytes - LogHeapWordSize; + + guarantee(GrainBytes == 0, "we should only set it once"); + // The cast to int is safe, given that we've bounded region_size by + // MIN_REGION_SIZE and MAX_REGION_SIZE. + GrainBytes = (int) region_size; + + guarantee(GrainWords == 0, "we should only set it once"); + GrainWords = GrainBytes >> LogHeapWordSize; + guarantee(1 << LogOfHRGrainWords == GrainWords, "sanity"); + + guarantee(CardsPerRegion == 0, "we should only set it once"); + CardsPerRegion = GrainBytes >> CardTableModRefBS::card_shift; +} + void HeapRegion::reset_after_compaction() { G1OffsetTableContigSpace::reset_after_compaction(); // After a compaction the mark bitmap is invalid, so we must diff --git a/src/share/vm/gc_implementation/g1/heapRegion.hpp b/src/share/vm/gc_implementation/g1/heapRegion.hpp index 663ed5c44bf568cac49f34e3b1bb71c3b1070363..9a96a84da5513249f51d7487699cacfa8c684394 100644 --- a/src/share/vm/gc_implementation/g1/heapRegion.hpp +++ b/src/share/vm/gc_implementation/g1/heapRegion.hpp @@ -297,15 +297,24 @@ class HeapRegion: public G1OffsetTableContigSpace { HeapRegion(G1BlockOffsetSharedArray* sharedOffsetArray, MemRegion mr, bool is_zeroed); - enum SomePublicConstants { - // HeapRegions are GrainBytes-aligned - // and have sizes that are multiples of GrainBytes. - LogOfHRGrainBytes = 20, - LogOfHRGrainWords = LogOfHRGrainBytes - LogHeapWordSize, - GrainBytes = 1 << LogOfHRGrainBytes, - GrainWords = 1 <> CardTableModRefBS::card_shift - }; - protected: // We need access in order to union things into the base table. BitMap* bm() { return &_bm; } @@ -76,7 +72,7 @@ protected: #if PRT_COUNT_OCCUPIED _occupied(0), #endif - _bm(CardsPerRegion, false /* in-resource-area */) + _bm(HeapRegion::CardsPerRegion, false /* in-resource-area */) {} static void free(PerRegionTable* prt) { @@ -144,7 +140,8 @@ protected: CardIdx_t from_card = (CardIdx_t) hw_offset >> (CardTableModRefBS::card_shift - LogHeapWordSize); - assert(0 <= from_card && from_card < CardsPerRegion, "Must be in range."); + assert(0 <= from_card && from_card < HeapRegion::CardsPerRegion, + "Must be in range."); add_card_work(from_card, par); } } @@ -631,7 +628,7 @@ void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, int tid) { uintptr_t(from_hr->bottom()) >> CardTableModRefBS::card_shift; CardIdx_t card_index = from_card - from_hr_bot_card_index; - assert(0 <= card_index && card_index < PosParPRT::CardsPerRegion, + assert(0 <= card_index && card_index < HeapRegion::CardsPerRegion, "Must be in range."); if (G1HRRSUseSparseTable && _sparse_table.add_card(from_hrs_ind, card_index)) { @@ -922,7 +919,7 @@ size_t OtherRegionsTable::occ_fine() const { } size_t OtherRegionsTable::occ_coarse() const { - return (_n_coarse_entries * PosParPRT::CardsPerRegion); + return (_n_coarse_entries * HeapRegion::CardsPerRegion); } size_t OtherRegionsTable::occ_sparse() const { @@ -1049,7 +1046,8 @@ bool OtherRegionsTable::contains_reference_locked(OopOrNarrowOopStar from) const uintptr_t(hr->bottom()) >> CardTableModRefBS::card_shift; assert(from_card >= hr_bot_card_index, "Inv"); CardIdx_t card_index = from_card - hr_bot_card_index; - assert(0 <= card_index && card_index < PosParPRT::CardsPerRegion, "Must be in range."); + assert(0 <= card_index && card_index < HeapRegion::CardsPerRegion, + "Must be in range."); return _sparse_table.contains_card(hr_ind, card_index); } @@ -1176,7 +1174,7 @@ void HeapRegionRemSetIterator::initialize(const HeapRegionRemSet* hrrs) { _is = Sparse; // Set these values so that we increment to the first region. _coarse_cur_region_index = -1; - _coarse_cur_region_cur_card = (PosParPRT::CardsPerRegion-1);; + _coarse_cur_region_cur_card = (HeapRegion::CardsPerRegion-1);; _cur_region_cur_card = 0; @@ -1195,7 +1193,7 @@ bool HeapRegionRemSetIterator::coarse_has_next(size_t& card_index) { // Go to the next card. _coarse_cur_region_cur_card++; // Was the last the last card in the current region? - if (_coarse_cur_region_cur_card == PosParPRT::CardsPerRegion) { + if (_coarse_cur_region_cur_card == HeapRegion::CardsPerRegion) { // Yes: find the next region. This may leave _coarse_cur_region_index // Set to the last index, in which case there are no more coarse // regions. @@ -1232,7 +1230,7 @@ bool HeapRegionRemSetIterator::fine_has_next(size_t& card_index) { _fine_cur_prt->_bm.get_next_one_offset(_cur_region_cur_card + 1); } while (!fine_has_next()) { - if (_cur_region_cur_card == PosParPRT::CardsPerRegion) { + if (_cur_region_cur_card == (size_t) HeapRegion::CardsPerRegion) { _cur_region_cur_card = 0; _fine_cur_prt = _fine_cur_prt->next(); } @@ -1255,7 +1253,7 @@ bool HeapRegionRemSetIterator::fine_has_next(size_t& card_index) { bool HeapRegionRemSetIterator::fine_has_next() { return _fine_cur_prt != NULL && - _cur_region_cur_card < PosParPRT::CardsPerRegion; + _cur_region_cur_card < (size_t) HeapRegion::CardsPerRegion; } bool HeapRegionRemSetIterator::has_next(size_t& card_index) { diff --git a/src/share/vm/gc_implementation/g1/sparsePRT.cpp b/src/share/vm/gc_implementation/g1/sparsePRT.cpp index 5baa550566242582a26022821aaab0dd18db151a..e57953b03e0fef91c007645820284450bc3c4599 100644 --- a/src/share/vm/gc_implementation/g1/sparsePRT.cpp +++ b/src/share/vm/gc_implementation/g1/sparsePRT.cpp @@ -347,7 +347,7 @@ CardIdx_t /* RSHashTable:: */ RSHashTableIter::find_first_card_in_list() { size_t /* RSHashTable:: */ RSHashTableIter::compute_card_ind(CardIdx_t ci) { return _heap_bot_card_ind - + (_rsht->entry(_bl_ind)->r_ind() * CardsPerRegion) + + (_rsht->entry(_bl_ind)->r_ind() * HeapRegion::CardsPerRegion) + ci; } diff --git a/src/share/vm/gc_implementation/g1/sparsePRT.hpp b/src/share/vm/gc_implementation/g1/sparsePRT.hpp index d5ab0d5181e9b93ff0b7051f3f9b4bb4b56eb35d..b67126ae80ff44ccdb8849f97aa86a4915029e60 100644 --- a/src/share/vm/gc_implementation/g1/sparsePRT.hpp +++ b/src/share/vm/gc_implementation/g1/sparsePRT.hpp @@ -172,10 +172,6 @@ class RSHashTableIter VALUE_OBJ_CLASS_SPEC { RSHashTable* _rsht; size_t _heap_bot_card_ind; - enum SomePrivateConstants { - CardsPerRegion = HeapRegion::GrainBytes >> CardTableModRefBS::card_shift - }; - // If the bucket list pointed to by _bl_ind contains a card, sets // _bl_ind to the index of that entry, and returns the card. // Otherwise, returns SparseEntry::NullEntry. diff --git a/src/share/vm/gc_implementation/includeDB_gc_g1 b/src/share/vm/gc_implementation/includeDB_gc_g1 index b788aea3bf96c1ac988f3a98e622fb1d95cb1e4e..63bfbce76f9dba50cda36d21052f4d4068e8ee65 100644 --- a/src/share/vm/gc_implementation/includeDB_gc_g1 +++ b/src/share/vm/gc_implementation/includeDB_gc_g1 @@ -165,6 +165,7 @@ g1CollectedHeap.inline.hpp g1CollectedHeap.hpp g1CollectedHeap.inline.hpp heapRegionSeq.hpp g1CollectedHeap.inline.hpp taskqueue.hpp +g1CollectorPolicy.cpp arguments.hpp g1CollectorPolicy.cpp concurrentG1Refine.hpp g1CollectorPolicy.cpp concurrentMark.hpp g1CollectorPolicy.cpp concurrentMarkThread.inline.hpp