Fri, 06 Feb 2009 01:38:50 +0300
6484959: G1: introduce survivor spaces
6797754: G1: combined bugfix
Summary: Implemented a policy to control G1 survivor space parameters.
Reviewed-by: tonyp, iveresov
1.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Feb 05 11:42:10 2009 -0800 1.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Feb 06 01:38:50 2009 +0300 1.3 @@ -141,7 +141,7 @@ 1.4 _scan_only_head(NULL), _scan_only_tail(NULL), _curr_scan_only(NULL), 1.5 _length(0), _scan_only_length(0), 1.6 _last_sampled_rs_lengths(0), 1.7 - _survivor_head(NULL), _survivors_tail(NULL), _survivor_length(0) 1.8 + _survivor_head(NULL), _survivor_tail(NULL), _survivor_length(0) 1.9 { 1.10 guarantee( check_list_empty(false), "just making sure..." ); 1.11 } 1.12 @@ -159,16 +159,15 @@ 1.13 } 1.14 1.15 void YoungList::add_survivor_region(HeapRegion* hr) { 1.16 - assert(!hr->is_survivor(), "should not already be for survived"); 1.17 + assert(hr->is_survivor(), "should be flagged as survivor region"); 1.18 assert(hr->get_next_young_region() == NULL, "cause it should!"); 1.19 1.20 hr->set_next_young_region(_survivor_head); 1.21 if (_survivor_head == NULL) { 1.22 - _survivors_tail = hr; 1.23 + _survivor_tail = hr; 1.24 } 1.25 _survivor_head = hr; 1.26 1.27 - hr->set_survivor(); 1.28 ++_survivor_length; 1.29 } 1.30 1.31 @@ -239,7 +238,7 @@ 1.32 1.33 empty_list(_survivor_head); 1.34 _survivor_head = NULL; 1.35 - _survivors_tail = NULL; 1.36 + _survivor_tail = NULL; 1.37 _survivor_length = 0; 1.38 1.39 _last_sampled_rs_lengths = 0; 1.40 @@ -391,6 +390,7 @@ 1.41 1.42 // Add survivor regions to SurvRateGroup. 1.43 _g1h->g1_policy()->note_start_adding_survivor_regions(); 1.44 + _g1h->g1_policy()->finished_recalculating_age_indexes(true /* is_survivors */); 1.45 for (HeapRegion* curr = _survivor_head; 1.46 curr != NULL; 1.47 curr = curr->get_next_young_region()) { 1.48 @@ -401,7 +401,7 @@ 1.49 if (_survivor_head != NULL) { 1.50 _head = _survivor_head; 1.51 _length = _survivor_length + _scan_only_length; 1.52 - _survivors_tail->set_next_young_region(_scan_only_head); 1.53 + _survivor_tail->set_next_young_region(_scan_only_head); 1.54 } else { 1.55 _head = _scan_only_head; 1.56 _length = _scan_only_length; 1.57 @@ -418,9 +418,9 @@ 1.58 _curr_scan_only = NULL; 1.59 1.60 _survivor_head = NULL; 1.61 - _survivors_tail = NULL; 1.62 + _survivor_tail = NULL; 1.63 _survivor_length = 0; 1.64 - _g1h->g1_policy()->finished_recalculating_age_indexes(); 1.65 + _g1h->g1_policy()->finished_recalculating_age_indexes(false /* is_survivors */); 1.66 1.67 assert(check_list_well_formed(), "young list should be well formed"); 1.68 } 1.69 @@ -553,7 +553,7 @@ 1.70 if (_gc_alloc_region_counts[purpose] < g1_policy()->max_regions(purpose)) { 1.71 alloc_region = newAllocRegion_work(word_size, true, zero_filled); 1.72 if (purpose == GCAllocForSurvived && alloc_region != NULL) { 1.73 - _young_list->add_survivor_region(alloc_region); 1.74 + alloc_region->set_survivor(); 1.75 } 1.76 ++_gc_alloc_region_counts[purpose]; 1.77 } else { 1.78 @@ -2593,6 +2593,9 @@ 1.79 _young_list->print(); 1.80 #endif // SCAN_ONLY_VERBOSE 1.81 1.82 + g1_policy()->record_survivor_regions(_young_list->survivor_length(), 1.83 + _young_list->first_survivor_region(), 1.84 + _young_list->last_survivor_region()); 1.85 _young_list->reset_auxilary_lists(); 1.86 } 1.87 } else { 1.88 @@ -2619,7 +2622,9 @@ 1.89 #endif // SCAN_ONLY_VERBOSE 1.90 1.91 double end_time_sec = os::elapsedTime(); 1.92 - g1_policy()->record_pause_time((end_time_sec - start_time_sec)*1000.0); 1.93 + if (!evacuation_failed()) { 1.94 + g1_policy()->record_pause_time((end_time_sec - start_time_sec)*1000.0); 1.95 + } 1.96 GCOverheadReporter::recordSTWEnd(end_time_sec); 1.97 g1_policy()->record_collection_pause_end(popular_region != NULL, 1.98 abandoned); 1.99 @@ -2754,6 +2759,13 @@ 1.100 _gc_alloc_region_list = r->next_gc_alloc_region(); 1.101 r->set_next_gc_alloc_region(NULL); 1.102 r->set_is_gc_alloc_region(false); 1.103 + if (r->is_survivor()) { 1.104 + if (r->is_empty()) { 1.105 + r->set_not_young(); 1.106 + } else { 1.107 + _young_list->add_survivor_region(r); 1.108 + } 1.109 + } 1.110 if (r->is_empty()) { 1.111 ++_free_regions; 1.112 } 1.113 @@ -3150,6 +3162,20 @@ 1.114 return block; 1.115 } 1.116 1.117 +void G1CollectedHeap::retire_alloc_region(HeapRegion* alloc_region, 1.118 + bool par) { 1.119 + // Another thread might have obtained alloc_region for the given 1.120 + // purpose, and might be attempting to allocate in it, and might 1.121 + // succeed. Therefore, we can't do the "finalization" stuff on the 1.122 + // region below until we're sure the last allocation has happened. 1.123 + // We ensure this by allocating the remaining space with a garbage 1.124 + // object. 1.125 + if (par) par_allocate_remaining_space(alloc_region); 1.126 + // Now we can do the post-GC stuff on the region. 1.127 + alloc_region->note_end_of_copying(); 1.128 + g1_policy()->record_after_bytes(alloc_region->used()); 1.129 +} 1.130 + 1.131 HeapWord* 1.132 G1CollectedHeap::allocate_during_gc_slow(GCAllocPurpose purpose, 1.133 HeapRegion* alloc_region, 1.134 @@ -3167,16 +3193,7 @@ 1.135 // Otherwise, continue; this new region is empty, too. 1.136 } 1.137 assert(alloc_region != NULL, "We better have an allocation region"); 1.138 - // Another thread might have obtained alloc_region for the given 1.139 - // purpose, and might be attempting to allocate in it, and might 1.140 - // succeed. Therefore, we can't do the "finalization" stuff on the 1.141 - // region below until we're sure the last allocation has happened. 1.142 - // We ensure this by allocating the remaining space with a garbage 1.143 - // object. 1.144 - if (par) par_allocate_remaining_space(alloc_region); 1.145 - // Now we can do the post-GC stuff on the region. 1.146 - alloc_region->note_end_of_copying(); 1.147 - g1_policy()->record_after_bytes(alloc_region->used()); 1.148 + retire_alloc_region(alloc_region, par); 1.149 1.150 if (_gc_alloc_region_counts[purpose] >= g1_policy()->max_regions(purpose)) { 1.151 // Cannot allocate more regions for the given purpose. 1.152 @@ -3185,7 +3202,7 @@ 1.153 if (purpose != alt_purpose) { 1.154 HeapRegion* alt_region = _gc_alloc_regions[alt_purpose]; 1.155 // Has not the alternative region been aliased? 1.156 - if (alloc_region != alt_region) { 1.157 + if (alloc_region != alt_region && alt_region != NULL) { 1.158 // Try to allocate in the alternative region. 1.159 if (par) { 1.160 block = alt_region->par_allocate(word_size); 1.161 @@ -3194,9 +3211,10 @@ 1.162 } 1.163 // Make an alias. 1.164 _gc_alloc_regions[purpose] = _gc_alloc_regions[alt_purpose]; 1.165 - } 1.166 - if (block != NULL) { 1.167 - return block; 1.168 + if (block != NULL) { 1.169 + return block; 1.170 + } 1.171 + retire_alloc_region(alt_region, par); 1.172 } 1.173 // Both the allocation region and the alternative one are full 1.174 // and aliased, replace them with a new allocation region. 1.175 @@ -3497,6 +3515,7 @@ 1.176 OverflowQueue* _overflowed_refs; 1.177 1.178 G1ParGCAllocBuffer _alloc_buffers[GCAllocPurposeCount]; 1.179 + ageTable _age_table; 1.180 1.181 size_t _alloc_buffer_waste; 1.182 size_t _undo_waste; 1.183 @@ -3538,6 +3557,7 @@ 1.184 _refs(g1h->task_queue(queue_num)), 1.185 _hash_seed(17), _queue_num(queue_num), 1.186 _term_attempts(0), 1.187 + _age_table(false), 1.188 #if G1_DETAILED_STATS 1.189 _pushes(0), _pops(0), _steals(0), 1.190 _steal_attempts(0), _overflow_pushes(0), 1.191 @@ -3572,8 +3592,9 @@ 1.192 1.193 RefToScanQueue* refs() { return _refs; } 1.194 OverflowQueue* overflowed_refs() { return _overflowed_refs; } 1.195 - 1.196 - inline G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) { 1.197 + ageTable* age_table() { return &_age_table; } 1.198 + 1.199 + G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) { 1.200 return &_alloc_buffers[purpose]; 1.201 } 1.202 1.203 @@ -3834,7 +3855,9 @@ 1.204 (!from_region->is_young() && young_index == 0), "invariant" ); 1.205 G1CollectorPolicy* g1p = _g1->g1_policy(); 1.206 markOop m = old->mark(); 1.207 - GCAllocPurpose alloc_purpose = g1p->evacuation_destination(from_region, m->age(), 1.208 + int age = m->has_displaced_mark_helper() ? m->displaced_mark_helper()->age() 1.209 + : m->age(); 1.210 + GCAllocPurpose alloc_purpose = g1p->evacuation_destination(from_region, age, 1.211 word_sz); 1.212 HeapWord* obj_ptr = _par_scan_state->allocate(alloc_purpose, word_sz); 1.213 oop obj = oop(obj_ptr); 1.214 @@ -3872,9 +3895,12 @@ 1.215 obj->incr_age(); 1.216 } else { 1.217 m = m->incr_age(); 1.218 + obj->set_mark(m); 1.219 } 1.220 + _par_scan_state->age_table()->add(obj, word_sz); 1.221 + } else { 1.222 + obj->set_mark(m); 1.223 } 1.224 - obj->set_mark(m); 1.225 1.226 // preserve "next" mark bit 1.227 if (_g1->mark_in_progress() && !_g1->is_obj_ill(old)) { 1.228 @@ -4129,6 +4155,9 @@ 1.229 _g1h->g1_policy()->record_obj_copy_time(i, elapsed_ms-term_ms); 1.230 _g1h->g1_policy()->record_termination_time(i, term_ms); 1.231 } 1.232 + if (G1UseSurvivorSpace) { 1.233 + _g1h->g1_policy()->record_thread_age_table(pss.age_table()); 1.234 + } 1.235 _g1h->update_surviving_young_words(pss.surviving_young_words()+1); 1.236 1.237 // Clean up any par-expanded rem sets. 1.238 @@ -4368,7 +4397,7 @@ 1.239 // Is this the right thing to do here? We don't save marks 1.240 // on individual heap regions when we allocate from 1.241 // them in parallel, so this seems like the correct place for this. 1.242 - all_alloc_regions_note_end_of_copying(); 1.243 + retire_all_alloc_regions(); 1.244 { 1.245 G1IsAliveClosure is_alive(this); 1.246 G1KeepAliveClosure keep_alive(this); 1.247 @@ -5008,7 +5037,7 @@ 1.248 return no_allocs; 1.249 } 1.250 1.251 -void G1CollectedHeap::all_alloc_regions_note_end_of_copying() { 1.252 +void G1CollectedHeap::retire_all_alloc_regions() { 1.253 for (int ap = 0; ap < GCAllocPurposeCount; ++ap) { 1.254 HeapRegion* r = _gc_alloc_regions[ap]; 1.255 if (r != NULL) { 1.256 @@ -5021,8 +5050,7 @@ 1.257 } 1.258 } 1.259 if (!has_processed_alias) { 1.260 - r->note_end_of_copying(); 1.261 - g1_policy()->record_after_bytes(r->used()); 1.262 + retire_alloc_region(r, false /* par */); 1.263 } 1.264 } 1.265 }
2.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Feb 05 11:42:10 2009 -0800 2.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Feb 06 01:38:50 2009 +0300 2.3 @@ -90,7 +90,7 @@ 2.4 HeapRegion* _curr_scan_only; 2.5 2.6 HeapRegion* _survivor_head; 2.7 - HeapRegion* _survivors_tail; 2.8 + HeapRegion* _survivor_tail; 2.9 size_t _survivor_length; 2.10 2.11 void empty_list(HeapRegion* list); 2.12 @@ -105,6 +105,7 @@ 2.13 bool is_empty() { return _length == 0; } 2.14 size_t length() { return _length; } 2.15 size_t scan_only_length() { return _scan_only_length; } 2.16 + size_t survivor_length() { return _survivor_length; } 2.17 2.18 void rs_length_sampling_init(); 2.19 bool rs_length_sampling_more(); 2.20 @@ -120,6 +121,7 @@ 2.21 HeapRegion* first_region() { return _head; } 2.22 HeapRegion* first_scan_only_region() { return _scan_only_head; } 2.23 HeapRegion* first_survivor_region() { return _survivor_head; } 2.24 + HeapRegion* last_survivor_region() { return _survivor_tail; } 2.25 HeapRegion* par_get_next_scan_only_region() { 2.26 MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag); 2.27 HeapRegion* ret = _curr_scan_only; 2.28 @@ -219,7 +221,7 @@ 2.29 // The to-space memory regions into which objects are being copied during 2.30 // a GC. 2.31 HeapRegion* _gc_alloc_regions[GCAllocPurposeCount]; 2.32 - uint _gc_alloc_region_counts[GCAllocPurposeCount]; 2.33 + size_t _gc_alloc_region_counts[GCAllocPurposeCount]; 2.34 2.35 // A list of the regions that have been set to be alloc regions in the 2.36 // current collection. 2.37 @@ -281,8 +283,8 @@ 2.38 // Returns "true" iff none of the gc alloc regions have any allocations 2.39 // since the last call to "save_marks". 2.40 bool all_alloc_regions_no_allocs_since_save_marks(); 2.41 - // Calls "note_end_of_copying on all gc alloc_regions. 2.42 - void all_alloc_regions_note_end_of_copying(); 2.43 + // Perform finalization stuff on all allocation regions. 2.44 + void retire_all_alloc_regions(); 2.45 2.46 // The number of regions allocated to hold humongous objects. 2.47 int _num_humongous_regions; 2.48 @@ -351,6 +353,10 @@ 2.49 // that parallel threads might be attempting allocations. 2.50 void par_allocate_remaining_space(HeapRegion* r); 2.51 2.52 + // Retires an allocation region when it is full or at the end of a 2.53 + // GC pause. 2.54 + void retire_alloc_region(HeapRegion* alloc_region, bool par); 2.55 + 2.56 // Helper function for two callbacks below. 2.57 // "full", if true, indicates that the GC is for a System.gc() request, 2.58 // and should collect the entire heap. If "clear_all_soft_refs" is true,
3.1 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu Feb 05 11:42:10 2009 -0800 3.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Fri Feb 06 01:38:50 2009 +0300 3.3 @@ -196,8 +196,13 @@ 3.4 _short_lived_surv_rate_group(new SurvRateGroup(this, "Short Lived", 3.5 G1YoungSurvRateNumRegionsSummary)), 3.6 _survivor_surv_rate_group(new SurvRateGroup(this, "Survivor", 3.7 - G1YoungSurvRateNumRegionsSummary)) 3.8 + G1YoungSurvRateNumRegionsSummary)), 3.9 // add here any more surv rate groups 3.10 + _recorded_survivor_regions(0), 3.11 + _recorded_survivor_head(NULL), 3.12 + _recorded_survivor_tail(NULL), 3.13 + _survivors_age_table(true) 3.14 + 3.15 { 3.16 _recent_prev_end_times_for_all_gcs_sec->add(os::elapsedTime()); 3.17 _prev_collection_pause_end_ms = os::elapsedTime() * 1000.0; 3.18 @@ -272,6 +277,15 @@ 3.19 _concurrent_mark_cleanup_times_ms->add(0.20); 3.20 _tenuring_threshold = MaxTenuringThreshold; 3.21 3.22 + if (G1UseSurvivorSpace) { 3.23 + // if G1FixedSurvivorSpaceSize is 0 which means the size is not 3.24 + // fixed, then _max_survivor_regions will be calculated at 3.25 + // calculate_young_list_target_config diring initialization 3.26 + _max_survivor_regions = G1FixedSurvivorSpaceSize / HeapRegion::GrainBytes; 3.27 + } else { 3.28 + _max_survivor_regions = 0; 3.29 + } 3.30 + 3.31 initialize_all(); 3.32 } 3.33 3.34 @@ -301,6 +315,8 @@ 3.35 "-XX:+UseConcMarkSweepGC."); 3.36 } 3.37 3.38 + initialize_gc_policy_counters(); 3.39 + 3.40 if (G1Gen) { 3.41 _in_young_gc_mode = true; 3.42 3.43 @@ -322,6 +338,12 @@ 3.44 } 3.45 } 3.46 3.47 +// Create the jstat counters for the policy. 3.48 +void G1CollectorPolicy::initialize_gc_policy_counters() 3.49 +{ 3.50 + _gc_policy_counters = new GCPolicyCounters("GarbageFirst", 1, 2 + G1Gen); 3.51 +} 3.52 + 3.53 void G1CollectorPolicy::calculate_young_list_min_length() { 3.54 _young_list_min_length = 0; 3.55 3.56 @@ -352,6 +374,7 @@ 3.57 guarantee( so_length < _young_list_target_length, "invariant" ); 3.58 _young_list_so_prefix_length = so_length; 3.59 } 3.60 + calculate_survivors_policy(); 3.61 } 3.62 3.63 // This method calculate the optimal scan-only set for a fixed young 3.64 @@ -448,6 +471,9 @@ 3.65 if (full_young_gcs() && _free_regions_at_end_of_collection > 0) { 3.66 // we are in fully-young mode and there are free regions in the heap 3.67 3.68 + double survivor_regions_evac_time = 3.69 + predict_survivor_regions_evac_time(); 3.70 + 3.71 size_t min_so_length = 0; 3.72 size_t max_so_length = 0; 3.73 3.74 @@ -497,9 +523,8 @@ 3.75 scanned_cards = predict_non_young_card_num(adj_rs_lengths); 3.76 // calculate this once, so that we don't have to recalculate it in 3.77 // the innermost loop 3.78 - double base_time_ms = predict_base_elapsed_time_ms(pending_cards, 3.79 - scanned_cards); 3.80 - 3.81 + double base_time_ms = predict_base_elapsed_time_ms(pending_cards, scanned_cards) 3.82 + + survivor_regions_evac_time; 3.83 // the result 3.84 size_t final_young_length = 0; 3.85 size_t final_so_length = 0; 3.86 @@ -548,14 +573,14 @@ 3.87 bool done = false; 3.88 // this is the outermost loop 3.89 while (!done) { 3.90 -#if 0 3.91 +#ifdef TRACE_CALC_YOUNG_CONFIG 3.92 // leave this in for debugging, just in case 3.93 gclog_or_tty->print_cr("searching between " SIZE_FORMAT " and " SIZE_FORMAT 3.94 ", incr " SIZE_FORMAT ", pass %s", 3.95 from_so_length, to_so_length, so_length_incr, 3.96 (pass == pass_type_coarse) ? "coarse" : 3.97 (pass == pass_type_fine) ? "fine" : "final"); 3.98 -#endif // 0 3.99 +#endif // TRACE_CALC_YOUNG_CONFIG 3.100 3.101 size_t so_length = from_so_length; 3.102 size_t init_free_regions = 3.103 @@ -651,11 +676,11 @@ 3.104 guarantee( so_length_incr == so_coarse_increments, "invariant" ); 3.105 guarantee( final_so_length >= min_so_length, "invariant" ); 3.106 3.107 -#if 0 3.108 +#ifdef TRACE_CALC_YOUNG_CONFIG 3.109 // leave this in for debugging, just in case 3.110 gclog_or_tty->print_cr(" coarse pass: SO length " SIZE_FORMAT, 3.111 final_so_length); 3.112 -#endif // 0 3.113 +#endif // TRACE_CALC_YOUNG_CONFIG 3.114 3.115 from_so_length = 3.116 (final_so_length - min_so_length > so_coarse_increments) ? 3.117 @@ -687,12 +712,12 @@ 3.118 // of the optimal 3.119 size_t new_so_length = 950 * final_so_length / 1000; 3.120 3.121 -#if 0 3.122 +#ifdef TRACE_CALC_YOUNG_CONFIG 3.123 // leave this in for debugging, just in case 3.124 gclog_or_tty->print_cr(" fine pass: SO length " SIZE_FORMAT 3.125 ", setting it to " SIZE_FORMAT, 3.126 final_so_length, new_so_length); 3.127 -#endif // 0 3.128 +#endif // TRACE_CALC_YOUNG_CONFIG 3.129 3.130 from_so_length = new_so_length; 3.131 to_so_length = new_so_length; 3.132 @@ -719,7 +744,8 @@ 3.133 } 3.134 3.135 // we should have at least one region in the target young length 3.136 - _young_list_target_length = MAX2((size_t) 1, final_young_length); 3.137 + _young_list_target_length = 3.138 + MAX2((size_t) 1, final_young_length + _recorded_survivor_regions); 3.139 if (final_so_length >= final_young_length) 3.140 // and we need to ensure that the S-O length is not greater than 3.141 // the target young length (this is being a bit careful) 3.142 @@ -734,7 +760,7 @@ 3.143 double end_time_sec = os::elapsedTime(); 3.144 double elapsed_time_ms = (end_time_sec - start_time_sec) * 1000.0; 3.145 3.146 -#if 0 3.147 +#ifdef TRACE_CALC_YOUNG_CONFIG 3.148 // leave this in for debugging, just in case 3.149 gclog_or_tty->print_cr("target = %1.1lf ms, young = " SIZE_FORMAT 3.150 ", SO = " SIZE_FORMAT ", " 3.151 @@ -747,9 +773,9 @@ 3.152 calculations, 3.153 full_young_gcs() ? "full" : "partial", 3.154 should_initiate_conc_mark() ? " i-m" : "", 3.155 - in_marking_window(), 3.156 - in_marking_window_im()); 3.157 -#endif // 0 3.158 + _in_marking_window, 3.159 + _in_marking_window_im); 3.160 +#endif // TRACE_CALC_YOUNG_CONFIG 3.161 3.162 if (_young_list_target_length < _young_list_min_length) { 3.163 // bummer; this means that, if we do a pause when the optimal 3.164 @@ -768,14 +794,14 @@ 3.165 // S-O length 3.166 so_length = calculate_optimal_so_length(_young_list_min_length); 3.167 3.168 -#if 0 3.169 +#ifdef TRACE_CALC_YOUNG_CONFIG 3.170 // leave this in for debugging, just in case 3.171 gclog_or_tty->print_cr("adjusted target length from " 3.172 SIZE_FORMAT " to " SIZE_FORMAT 3.173 ", SO " SIZE_FORMAT, 3.174 _young_list_target_length, _young_list_min_length, 3.175 so_length); 3.176 -#endif // 0 3.177 +#endif // TRACE_CALC_YOUNG_CONFIG 3.178 3.179 _young_list_target_length = 3.180 MAX2(_young_list_min_length, (size_t)1); 3.181 @@ -785,12 +811,12 @@ 3.182 // we are in a partially-young mode or we've run out of regions (due 3.183 // to evacuation failure) 3.184 3.185 -#if 0 3.186 +#ifdef TRACE_CALC_YOUNG_CONFIG 3.187 // leave this in for debugging, just in case 3.188 gclog_or_tty->print_cr("(partial) setting target to " SIZE_FORMAT 3.189 ", SO " SIZE_FORMAT, 3.190 _young_list_min_length, 0); 3.191 -#endif // 0 3.192 +#endif // TRACE_CALC_YOUNG_CONFIG 3.193 3.194 // we'll do the pause as soon as possible and with no S-O prefix 3.195 // (see above for the reasons behind the latter) 3.196 @@ -884,6 +910,16 @@ 3.197 return true; 3.198 } 3.199 3.200 +double G1CollectorPolicy::predict_survivor_regions_evac_time() { 3.201 + double survivor_regions_evac_time = 0.0; 3.202 + for (HeapRegion * r = _recorded_survivor_head; 3.203 + r != NULL && r != _recorded_survivor_tail->get_next_young_region(); 3.204 + r = r->get_next_young_region()) { 3.205 + survivor_regions_evac_time += predict_region_elapsed_time_ms(r, true); 3.206 + } 3.207 + return survivor_regions_evac_time; 3.208 +} 3.209 + 3.210 void G1CollectorPolicy::check_prediction_validity() { 3.211 guarantee( adaptive_young_list_length(), "should not call this otherwise" ); 3.212 3.213 @@ -995,11 +1031,15 @@ 3.214 _short_lived_surv_rate_group->start_adding_regions(); 3.215 // also call this on any additional surv rate groups 3.216 3.217 + record_survivor_regions(0, NULL, NULL); 3.218 + 3.219 _prev_region_num_young = _region_num_young; 3.220 _prev_region_num_tenured = _region_num_tenured; 3.221 3.222 _free_regions_at_end_of_collection = _g1->free_regions(); 3.223 _scan_only_regions_at_end_of_collection = 0; 3.224 + // Reset survivors SurvRateGroup. 3.225 + _survivor_surv_rate_group->reset(); 3.226 calculate_young_list_min_length(); 3.227 calculate_young_list_target_config(); 3.228 } 3.229 @@ -1104,6 +1144,10 @@ 3.230 _short_lived_surv_rate_group->record_scan_only_prefix(short_lived_so_length); 3.231 tag_scan_only(short_lived_so_length); 3.232 3.233 + if (G1UseSurvivorSpace) { 3.234 + _survivors_age_table.clear(); 3.235 + } 3.236 + 3.237 assert( verify_young_ages(), "region age verification" ); 3.238 } 3.239 3.240 @@ -1965,9 +2009,6 @@ 3.241 // </NEW PREDICTION> 3.242 3.243 _target_pause_time_ms = -1.0; 3.244 - 3.245 - // TODO: calculate tenuring threshold 3.246 - _tenuring_threshold = MaxTenuringThreshold; 3.247 } 3.248 3.249 // <NEW PREDICTION> 3.250 @@ -2058,7 +2099,7 @@ 3.251 guarantee( hr->is_young() && hr->age_in_surv_rate_group() != -1, 3.252 "invariant" ); 3.253 int age = hr->age_in_surv_rate_group(); 3.254 - double yg_surv_rate = predict_yg_surv_rate(age); 3.255 + double yg_surv_rate = predict_yg_surv_rate(age, hr->surv_rate_group()); 3.256 bytes_to_copy = (size_t) ((double) hr->used() * yg_surv_rate); 3.257 } 3.258 3.259 @@ -2091,7 +2132,7 @@ 3.260 } 3.261 #if PREDICTIONS_VERBOSE 3.262 if (young) { 3.263 - _recorded_young_bytes += hr->asSpace()->used(); 3.264 + _recorded_young_bytes += hr->used(); 3.265 } else { 3.266 _recorded_marked_bytes += hr->max_live_bytes(); 3.267 } 3.268 @@ -2119,11 +2160,6 @@ 3.269 predict_non_young_card_num(_predicted_rs_lengths); 3.270 _recorded_region_num = _recorded_young_regions + _recorded_non_young_regions; 3.271 3.272 - _predicted_young_survival_ratio = 0.0; 3.273 - for (int i = 0; i < _recorded_young_regions; ++i) 3.274 - _predicted_young_survival_ratio += predict_yg_surv_rate(i); 3.275 - _predicted_young_survival_ratio /= (double) _recorded_young_regions; 3.276 - 3.277 _predicted_scan_only_scan_time_ms = 3.278 predict_scan_only_time_ms(_recorded_scan_only_regions); 3.279 _predicted_rs_update_time_ms = 3.280 @@ -2673,8 +2709,11 @@ 3.281 assert(in_young_gc_mode(), "should be in young GC mode"); 3.282 bool ret; 3.283 size_t young_list_length = _g1->young_list_length(); 3.284 - 3.285 - if (young_list_length < _young_list_target_length) { 3.286 + size_t young_list_max_length = _young_list_target_length; 3.287 + if (G1FixedEdenSize) { 3.288 + young_list_max_length -= _max_survivor_regions; 3.289 + } 3.290 + if (young_list_length < young_list_max_length) { 3.291 ret = true; 3.292 ++_region_num_young; 3.293 } else { 3.294 @@ -2710,17 +2749,39 @@ 3.295 } 3.296 3.297 3.298 -uint G1CollectorPolicy::max_regions(int purpose) { 3.299 +size_t G1CollectorPolicy::max_regions(int purpose) { 3.300 switch (purpose) { 3.301 case GCAllocForSurvived: 3.302 - return G1MaxSurvivorRegions; 3.303 + return _max_survivor_regions; 3.304 case GCAllocForTenured: 3.305 - return UINT_MAX; 3.306 + return REGIONS_UNLIMITED; 3.307 default: 3.308 - return UINT_MAX; 3.309 + ShouldNotReachHere(); 3.310 + return REGIONS_UNLIMITED; 3.311 }; 3.312 } 3.313 3.314 +// Calculates survivor space parameters. 3.315 +void G1CollectorPolicy::calculate_survivors_policy() 3.316 +{ 3.317 + if (!G1UseSurvivorSpace) { 3.318 + return; 3.319 + } 3.320 + if (G1FixedSurvivorSpaceSize == 0) { 3.321 + _max_survivor_regions = _young_list_target_length / SurvivorRatio; 3.322 + } else { 3.323 + _max_survivor_regions = G1FixedSurvivorSpaceSize; 3.324 + } 3.325 + 3.326 + if (G1FixedTenuringThreshold) { 3.327 + _tenuring_threshold = MaxTenuringThreshold; 3.328 + } else { 3.329 + _tenuring_threshold = _survivors_age_table.compute_tenuring_threshold( 3.330 + HeapRegion::GrainWords * _max_survivor_regions); 3.331 + } 3.332 +} 3.333 + 3.334 + 3.335 void 3.336 G1CollectorPolicy_BestRegionsFirst:: 3.337 set_single_region_collection_set(HeapRegion* hr) { 3.338 @@ -2743,7 +2804,11 @@ 3.339 double max_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0; 3.340 3.341 size_t young_list_length = _g1->young_list_length(); 3.342 - bool reached_target_length = young_list_length >= _young_list_target_length; 3.343 + size_t young_list_max_length = _young_list_target_length; 3.344 + if (G1FixedEdenSize) { 3.345 + young_list_max_length -= _max_survivor_regions; 3.346 + } 3.347 + bool reached_target_length = young_list_length >= young_list_max_length; 3.348 3.349 if (in_young_gc_mode()) { 3.350 if (reached_target_length) {
4.1 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Thu Feb 05 11:42:10 2009 -0800 4.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Fri Feb 06 01:38:50 2009 +0300 4.3 @@ -557,6 +557,8 @@ 4.4 return get_new_neg_prediction(_young_gc_eff_seq); 4.5 } 4.6 4.7 + double predict_survivor_regions_evac_time(); 4.8 + 4.9 // </NEW PREDICTION> 4.10 4.11 public: 4.12 @@ -599,8 +601,8 @@ 4.13 4.14 // Returns an estimate of the survival rate of the region at yg-age 4.15 // "yg_age". 4.16 - double predict_yg_surv_rate(int age) { 4.17 - TruncatedSeq* seq = _short_lived_surv_rate_group->get_seq(age); 4.18 + double predict_yg_surv_rate(int age, SurvRateGroup* surv_rate_group) { 4.19 + TruncatedSeq* seq = surv_rate_group->get_seq(age); 4.20 if (seq->num() == 0) 4.21 gclog_or_tty->print("BARF! age is %d", age); 4.22 guarantee( seq->num() > 0, "invariant" ); 4.23 @@ -610,6 +612,10 @@ 4.24 return pred; 4.25 } 4.26 4.27 + double predict_yg_surv_rate(int age) { 4.28 + return predict_yg_surv_rate(age, _short_lived_surv_rate_group); 4.29 + } 4.30 + 4.31 double accum_yg_surv_rate_pred(int age) { 4.32 return _short_lived_surv_rate_group->accum_surv_rate_pred(age); 4.33 } 4.34 @@ -822,6 +828,9 @@ 4.35 4.36 virtual void init(); 4.37 4.38 + // Create jstat counters for the policy. 4.39 + virtual void initialize_gc_policy_counters(); 4.40 + 4.41 virtual HeapWord* mem_allocate_work(size_t size, 4.42 bool is_tlab, 4.43 bool* gc_overhead_limit_was_exceeded); 4.44 @@ -1047,8 +1056,12 @@ 4.45 // Print stats on young survival ratio 4.46 void print_yg_surv_rate_info() const; 4.47 4.48 - void finished_recalculating_age_indexes() { 4.49 - _short_lived_surv_rate_group->finished_recalculating_age_indexes(); 4.50 + void finished_recalculating_age_indexes(bool is_survivors) { 4.51 + if (is_survivors) { 4.52 + _survivor_surv_rate_group->finished_recalculating_age_indexes(); 4.53 + } else { 4.54 + _short_lived_surv_rate_group->finished_recalculating_age_indexes(); 4.55 + } 4.56 // do that for any other surv rate groups 4.57 } 4.58 4.59 @@ -1097,6 +1110,17 @@ 4.60 // maximum amount of suvivors regions. 4.61 int _tenuring_threshold; 4.62 4.63 + // The limit on the number of regions allocated for survivors. 4.64 + size_t _max_survivor_regions; 4.65 + 4.66 + // The amount of survor regions after a collection. 4.67 + size_t _recorded_survivor_regions; 4.68 + // List of survivor regions. 4.69 + HeapRegion* _recorded_survivor_head; 4.70 + HeapRegion* _recorded_survivor_tail; 4.71 + 4.72 + ageTable _survivors_age_table; 4.73 + 4.74 public: 4.75 4.76 inline GCAllocPurpose 4.77 @@ -1116,7 +1140,9 @@ 4.78 return GCAllocForTenured; 4.79 } 4.80 4.81 - uint max_regions(int purpose); 4.82 + static const size_t REGIONS_UNLIMITED = ~(size_t)0; 4.83 + 4.84 + size_t max_regions(int purpose); 4.85 4.86 // The limit on regions for a particular purpose is reached. 4.87 void note_alloc_region_limit_reached(int purpose) { 4.88 @@ -1132,6 +1158,23 @@ 4.89 void note_stop_adding_survivor_regions() { 4.90 _survivor_surv_rate_group->stop_adding_regions(); 4.91 } 4.92 + 4.93 + void record_survivor_regions(size_t regions, 4.94 + HeapRegion* head, 4.95 + HeapRegion* tail) { 4.96 + _recorded_survivor_regions = regions; 4.97 + _recorded_survivor_head = head; 4.98 + _recorded_survivor_tail = tail; 4.99 + } 4.100 + 4.101 + void record_thread_age_table(ageTable* age_table) 4.102 + { 4.103 + _survivors_age_table.merge_par(age_table); 4.104 + } 4.105 + 4.106 + // Calculates survivor space parameters. 4.107 + void calculate_survivors_policy(); 4.108 + 4.109 }; 4.110 4.111 // This encapsulates a particular strategy for a g1 Collector.
5.1 --- a/src/share/vm/gc_implementation/g1/g1RemSet.cpp Thu Feb 05 11:42:10 2009 -0800 5.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.cpp Fri Feb 06 01:38:50 2009 +0300 5.3 @@ -572,6 +572,9 @@ 5.4 } 5.5 guarantee( _cards_scanned == NULL, "invariant" ); 5.6 _cards_scanned = NEW_C_HEAP_ARRAY(size_t, n_workers()); 5.7 + for (uint i = 0; i < n_workers(); ++i) { 5.8 + _cards_scanned[i] = 0; 5.9 + } 5.10 _total_cards_scanned = 0; 5.11 } 5.12
6.1 --- a/src/share/vm/gc_implementation/g1/g1_globals.hpp Thu Feb 05 11:42:10 2009 -0800 6.2 +++ b/src/share/vm/gc_implementation/g1/g1_globals.hpp Fri Feb 06 01:38:50 2009 +0300 6.3 @@ -281,7 +281,17 @@ 6.4 develop(bool, G1HRRSFlushLogBuffersOnVerify, false, \ 6.5 "Forces flushing of log buffers before verification.") \ 6.6 \ 6.7 - product(intx, G1MaxSurvivorRegions, 0, \ 6.8 - "The maximum number of survivor regions") 6.9 + product(bool, G1UseSurvivorSpace, true, \ 6.10 + "When true, use survivor space.") \ 6.11 + \ 6.12 + product(bool, G1FixedTenuringThreshold, false, \ 6.13 + "When set, G1 will not adjust the tenuring threshold") \ 6.14 + \ 6.15 + product(bool, G1FixedEdenSize, false, \ 6.16 + "When set, G1 will not allocate unused survivor space regions") \ 6.17 + \ 6.18 + product(uintx, G1FixedSurvivorSpaceSize, 0, \ 6.19 + "If non-0 is the size of the G1 survivor space, " \ 6.20 + "otherwise SurvivorRatio is used to determine the size") 6.21 6.22 G1_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG, DECLARE_MANAGEABLE_FLAG, DECLARE_PRODUCT_RW_FLAG)
7.1 --- a/src/share/vm/gc_implementation/g1/heapRegion.hpp Thu Feb 05 11:42:10 2009 -0800 7.2 +++ b/src/share/vm/gc_implementation/g1/heapRegion.hpp Fri Feb 06 01:38:50 2009 +0300 7.3 @@ -566,7 +566,11 @@ 7.4 void note_end_of_copying() { 7.5 assert(top() >= _next_top_at_mark_start, 7.6 "Increase only"); 7.7 - _next_top_at_mark_start = top(); 7.8 + // Survivor regions will be scanned on the start of concurrent 7.9 + // marking. 7.10 + if (!is_survivor()) { 7.11 + _next_top_at_mark_start = top(); 7.12 + } 7.13 } 7.14 7.15 // Returns "false" iff no object in the region was allocated when the
8.1 --- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Thu Feb 05 11:42:10 2009 -0800 8.2 +++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Fri Feb 06 01:38:50 2009 +0300 8.3 @@ -65,9 +65,11 @@ 8.4 // We need access in order to union things into the base table. 8.5 BitMap* bm() { return &_bm; } 8.6 8.7 +#if PRT_COUNT_OCCUPIED 8.8 void recount_occupied() { 8.9 _occupied = (jint) bm()->count_one_bits(); 8.10 } 8.11 +#endif 8.12 8.13 PerRegionTable(HeapRegion* hr) : 8.14 _hr(hr), 8.15 @@ -1144,7 +1146,9 @@ 8.16 size_t i = _outgoing_region_map.get_next_one_offset(0); 8.17 while (i < _outgoing_region_map.size()) { 8.18 HeapRegion* to_region = g1h->region_at(i); 8.19 - to_region->rem_set()->clear_incoming_entry(hr()); 8.20 + if (!to_region->in_collection_set()) { 8.21 + to_region->rem_set()->clear_incoming_entry(hr()); 8.22 + } 8.23 i = _outgoing_region_map.get_next_one_offset(i+1); 8.24 } 8.25 }
9.1 --- a/src/share/vm/gc_implementation/g1/survRateGroup.cpp Thu Feb 05 11:42:10 2009 -0800 9.2 +++ b/src/share/vm/gc_implementation/g1/survRateGroup.cpp Fri Feb 06 01:38:50 2009 +0300 9.3 @@ -29,23 +29,14 @@ 9.4 const char* name, 9.5 size_t summary_surv_rates_len) : 9.6 _g1p(g1p), _name(name), 9.7 - _all_regions_allocated(0), 9.8 - _curr_length(0), _scan_only_prefix(0), _setup_seq_num(0), 9.9 - _array_length(0), _surv_rate(NULL), _accum_surv_rate_pred(NULL), 9.10 - _accum_surv_rate(0.0), _surv_rate_pred(NULL), _last_pred(0.0), 9.11 _summary_surv_rates_len(summary_surv_rates_len), 9.12 _summary_surv_rates_max_len(0), 9.13 - _summary_surv_rates(NULL) { 9.14 - 9.15 - // the following will set up the arrays with length 1 9.16 - _curr_length = 1; 9.17 - stop_adding_regions(); 9.18 - guarantee( _array_length == 1, "invariant" ); 9.19 - guarantee( _surv_rate_pred[0] != NULL, "invariant" ); 9.20 - _surv_rate_pred[0]->add(0.4); 9.21 - all_surviving_words_recorded(false); 9.22 - _curr_length = 0; 9.23 - 9.24 + _summary_surv_rates(NULL), 9.25 + _surv_rate(NULL), 9.26 + _accum_surv_rate_pred(NULL), 9.27 + _surv_rate_pred(NULL) 9.28 +{ 9.29 + reset(); 9.30 if (summary_surv_rates_len > 0) { 9.31 size_t length = summary_surv_rates_len; 9.32 _summary_surv_rates = NEW_C_HEAP_ARRAY(NumberSeq*, length); 9.33 @@ -60,61 +51,80 @@ 9.34 start_adding_regions(); 9.35 } 9.36 9.37 + 9.38 +void SurvRateGroup::reset() 9.39 +{ 9.40 + _all_regions_allocated = 0; 9.41 + _scan_only_prefix = 0; 9.42 + _setup_seq_num = 0; 9.43 + _stats_arrays_length = 0; 9.44 + _accum_surv_rate = 0.0; 9.45 + _last_pred = 0.0; 9.46 + // the following will set up the arrays with length 1 9.47 + _region_num = 1; 9.48 + stop_adding_regions(); 9.49 + guarantee( _stats_arrays_length == 1, "invariant" ); 9.50 + guarantee( _surv_rate_pred[0] != NULL, "invariant" ); 9.51 + _surv_rate_pred[0]->add(0.4); 9.52 + all_surviving_words_recorded(false); 9.53 + _region_num = 0; 9.54 +} 9.55 + 9.56 + 9.57 void 9.58 SurvRateGroup::start_adding_regions() { 9.59 - _setup_seq_num = _array_length; 9.60 - _curr_length = _scan_only_prefix; 9.61 + _setup_seq_num = _stats_arrays_length; 9.62 + _region_num = _scan_only_prefix; 9.63 _accum_surv_rate = 0.0; 9.64 9.65 #if 0 9.66 - gclog_or_tty->print_cr("start adding regions, seq num %d, length %d", 9.67 - _setup_seq_num, _curr_length); 9.68 + gclog_or_tty->print_cr("[%s] start adding regions, seq num %d, length %d", 9.69 + _name, _setup_seq_num, _region_num); 9.70 #endif // 0 9.71 } 9.72 9.73 void 9.74 SurvRateGroup::stop_adding_regions() { 9.75 - size_t length = _curr_length; 9.76 9.77 #if 0 9.78 - gclog_or_tty->print_cr("stop adding regions, length %d", length); 9.79 + gclog_or_tty->print_cr("[%s] stop adding regions, length %d", _name, _region_num); 9.80 #endif // 0 9.81 9.82 - if (length > _array_length) { 9.83 + if (_region_num > _stats_arrays_length) { 9.84 double* old_surv_rate = _surv_rate; 9.85 double* old_accum_surv_rate_pred = _accum_surv_rate_pred; 9.86 TruncatedSeq** old_surv_rate_pred = _surv_rate_pred; 9.87 9.88 - _surv_rate = NEW_C_HEAP_ARRAY(double, length); 9.89 + _surv_rate = NEW_C_HEAP_ARRAY(double, _region_num); 9.90 if (_surv_rate == NULL) { 9.91 - vm_exit_out_of_memory(sizeof(double) * length, 9.92 + vm_exit_out_of_memory(sizeof(double) * _region_num, 9.93 "Not enough space for surv rate array."); 9.94 } 9.95 - _accum_surv_rate_pred = NEW_C_HEAP_ARRAY(double, length); 9.96 + _accum_surv_rate_pred = NEW_C_HEAP_ARRAY(double, _region_num); 9.97 if (_accum_surv_rate_pred == NULL) { 9.98 - vm_exit_out_of_memory(sizeof(double) * length, 9.99 + vm_exit_out_of_memory(sizeof(double) * _region_num, 9.100 "Not enough space for accum surv rate pred array."); 9.101 } 9.102 - _surv_rate_pred = NEW_C_HEAP_ARRAY(TruncatedSeq*, length); 9.103 + _surv_rate_pred = NEW_C_HEAP_ARRAY(TruncatedSeq*, _region_num); 9.104 if (_surv_rate == NULL) { 9.105 - vm_exit_out_of_memory(sizeof(TruncatedSeq*) * length, 9.106 + vm_exit_out_of_memory(sizeof(TruncatedSeq*) * _region_num, 9.107 "Not enough space for surv rate pred array."); 9.108 } 9.109 9.110 - for (size_t i = 0; i < _array_length; ++i) 9.111 + for (size_t i = 0; i < _stats_arrays_length; ++i) 9.112 _surv_rate_pred[i] = old_surv_rate_pred[i]; 9.113 9.114 #if 0 9.115 - gclog_or_tty->print_cr("stop adding regions, new seqs %d to %d", 9.116 - _array_length, length - 1); 9.117 + gclog_or_tty->print_cr("[%s] stop adding regions, new seqs %d to %d", 9.118 + _name, _array_length, _region_num - 1); 9.119 #endif // 0 9.120 9.121 - for (size_t i = _array_length; i < length; ++i) { 9.122 + for (size_t i = _stats_arrays_length; i < _region_num; ++i) { 9.123 _surv_rate_pred[i] = new TruncatedSeq(10); 9.124 // _surv_rate_pred[i]->add(last_pred); 9.125 } 9.126 9.127 - _array_length = length; 9.128 + _stats_arrays_length = _region_num; 9.129 9.130 if (old_surv_rate != NULL) 9.131 FREE_C_HEAP_ARRAY(double, old_surv_rate); 9.132 @@ -124,7 +134,7 @@ 9.133 FREE_C_HEAP_ARRAY(NumberSeq*, old_surv_rate_pred); 9.134 } 9.135 9.136 - for (size_t i = 0; i < _array_length; ++i) 9.137 + for (size_t i = 0; i < _stats_arrays_length; ++i) 9.138 _surv_rate[i] = 0.0; 9.139 } 9.140 9.141 @@ -135,7 +145,7 @@ 9.142 9.143 double ret = _accum_surv_rate; 9.144 if (adjustment > 0) { 9.145 - TruncatedSeq* seq = get_seq(_curr_length+1); 9.146 + TruncatedSeq* seq = get_seq(_region_num+1); 9.147 double surv_rate = _g1p->get_new_prediction(seq); 9.148 ret += surv_rate; 9.149 } 9.150 @@ -145,23 +155,23 @@ 9.151 9.152 int 9.153 SurvRateGroup::next_age_index() { 9.154 - TruncatedSeq* seq = get_seq(_curr_length); 9.155 + TruncatedSeq* seq = get_seq(_region_num); 9.156 double surv_rate = _g1p->get_new_prediction(seq); 9.157 _accum_surv_rate += surv_rate; 9.158 9.159 - ++_curr_length; 9.160 + ++_region_num; 9.161 return (int) ++_all_regions_allocated; 9.162 } 9.163 9.164 void 9.165 SurvRateGroup::record_scan_only_prefix(size_t scan_only_prefix) { 9.166 - guarantee( scan_only_prefix <= _curr_length, "pre-condition" ); 9.167 + guarantee( scan_only_prefix <= _region_num, "pre-condition" ); 9.168 _scan_only_prefix = scan_only_prefix; 9.169 } 9.170 9.171 void 9.172 SurvRateGroup::record_surviving_words(int age_in_group, size_t surv_words) { 9.173 - guarantee( 0 <= age_in_group && (size_t) age_in_group < _curr_length, 9.174 + guarantee( 0 <= age_in_group && (size_t) age_in_group < _region_num, 9.175 "pre-condition" ); 9.176 guarantee( _surv_rate[age_in_group] <= 0.00001, 9.177 "should only update each slot once" ); 9.178 @@ -178,15 +188,15 @@ 9.179 9.180 void 9.181 SurvRateGroup::all_surviving_words_recorded(bool propagate) { 9.182 - if (propagate && _curr_length > 0) { // conservative 9.183 - double surv_rate = _surv_rate_pred[_curr_length-1]->last(); 9.184 + if (propagate && _region_num > 0) { // conservative 9.185 + double surv_rate = _surv_rate_pred[_region_num-1]->last(); 9.186 9.187 #if 0 9.188 gclog_or_tty->print_cr("propagating %1.2lf from %d to %d", 9.189 surv_rate, _curr_length, _array_length - 1); 9.190 #endif // 0 9.191 9.192 - for (size_t i = _curr_length; i < _array_length; ++i) { 9.193 + for (size_t i = _region_num; i < _stats_arrays_length; ++i) { 9.194 guarantee( _surv_rate[i] <= 0.00001, 9.195 "the slot should not have been updated" ); 9.196 _surv_rate_pred[i]->add(surv_rate); 9.197 @@ -195,7 +205,7 @@ 9.198 9.199 double accum = 0.0; 9.200 double pred = 0.0; 9.201 - for (size_t i = 0; i < _array_length; ++i) { 9.202 + for (size_t i = 0; i < _stats_arrays_length; ++i) { 9.203 pred = _g1p->get_new_prediction(_surv_rate_pred[i]); 9.204 if (pred > 1.0) pred = 1.0; 9.205 accum += pred; 9.206 @@ -209,8 +219,8 @@ 9.207 void 9.208 SurvRateGroup::print() { 9.209 gclog_or_tty->print_cr("Surv Rate Group: %s (%d entries, %d scan-only)", 9.210 - _name, _curr_length, _scan_only_prefix); 9.211 - for (size_t i = 0; i < _curr_length; ++i) { 9.212 + _name, _region_num, _scan_only_prefix); 9.213 + for (size_t i = 0; i < _region_num; ++i) { 9.214 gclog_or_tty->print_cr(" age %4d surv rate %6.2lf %% pred %6.2lf %%%s", 9.215 i, _surv_rate[i] * 100.0, 9.216 _g1p->get_new_prediction(_surv_rate_pred[i]) * 100.0,
10.1 --- a/src/share/vm/gc_implementation/g1/survRateGroup.hpp Thu Feb 05 11:42:10 2009 -0800 10.2 +++ b/src/share/vm/gc_implementation/g1/survRateGroup.hpp Fri Feb 06 01:38:50 2009 +0300 10.3 @@ -29,7 +29,7 @@ 10.4 G1CollectorPolicy* _g1p; 10.5 const char* _name; 10.6 10.7 - size_t _array_length; 10.8 + size_t _stats_arrays_length; 10.9 double* _surv_rate; 10.10 double* _accum_surv_rate_pred; 10.11 double _last_pred; 10.12 @@ -40,7 +40,7 @@ 10.13 size_t _summary_surv_rates_max_len; 10.14 10.15 int _all_regions_allocated; 10.16 - size_t _curr_length; 10.17 + size_t _region_num; 10.18 size_t _scan_only_prefix; 10.19 size_t _setup_seq_num; 10.20 10.21 @@ -48,6 +48,7 @@ 10.22 SurvRateGroup(G1CollectorPolicy* g1p, 10.23 const char* name, 10.24 size_t summary_surv_rates_len); 10.25 + void reset(); 10.26 void start_adding_regions(); 10.27 void stop_adding_regions(); 10.28 void record_scan_only_prefix(size_t scan_only_prefix); 10.29 @@ -55,22 +56,21 @@ 10.30 void all_surviving_words_recorded(bool propagate); 10.31 const char* name() { return _name; } 10.32 10.33 - size_t region_num() { return _curr_length; } 10.34 + size_t region_num() { return _region_num; } 10.35 size_t scan_only_length() { return _scan_only_prefix; } 10.36 double accum_surv_rate_pred(int age) { 10.37 assert(age >= 0, "must be"); 10.38 - if ((size_t)age < _array_length) 10.39 + if ((size_t)age < _stats_arrays_length) 10.40 return _accum_surv_rate_pred[age]; 10.41 else { 10.42 - double diff = (double) (age - _array_length + 1); 10.43 - return _accum_surv_rate_pred[_array_length-1] + diff * _last_pred; 10.44 + double diff = (double) (age - _stats_arrays_length + 1); 10.45 + return _accum_surv_rate_pred[_stats_arrays_length-1] + diff * _last_pred; 10.46 } 10.47 } 10.48 10.49 double accum_surv_rate(size_t adjustment); 10.50 10.51 TruncatedSeq* get_seq(size_t age) { 10.52 - guarantee( 0 <= age, "pre-condition" ); 10.53 if (age >= _setup_seq_num) { 10.54 guarantee( _setup_seq_num > 0, "invariant" ); 10.55 age = _setup_seq_num-1;
11.1 --- a/src/share/vm/gc_implementation/includeDB_gc_g1 Thu Feb 05 11:42:10 2009 -0800 11.2 +++ b/src/share/vm/gc_implementation/includeDB_gc_g1 Fri Feb 06 01:38:50 2009 +0300 11.3 @@ -172,6 +172,7 @@ 11.4 g1CollectorPolicy.cpp g1CollectorPolicy.hpp 11.5 g1CollectorPolicy.cpp heapRegionRemSet.hpp 11.6 g1CollectorPolicy.cpp mutexLocker.hpp 11.7 +g1CollectorPolicy.cpp gcPolicyCounters.hpp 11.8 11.9 g1CollectorPolicy.hpp collectorPolicy.hpp 11.10 g1CollectorPolicy.hpp collectionSetChooser.hpp 11.11 @@ -272,6 +273,7 @@ 11.12 heapRegion.hpp watermark.hpp 11.13 heapRegion.hpp g1_specialized_oop_closures.hpp 11.14 heapRegion.hpp survRateGroup.hpp 11.15 +heapRegion.hpp ageTable.hpp 11.16 11.17 heapRegionRemSet.hpp sparsePRT.hpp 11.18
12.1 --- a/src/share/vm/gc_implementation/shared/ageTable.cpp Thu Feb 05 11:42:10 2009 -0800 12.2 +++ b/src/share/vm/gc_implementation/shared/ageTable.cpp Fri Feb 06 01:38:50 2009 +0300 12.3 @@ -67,6 +67,12 @@ 12.4 } 12.5 } 12.6 12.7 +void ageTable::merge_par(ageTable* subTable) { 12.8 + for (int i = 0; i < table_size; i++) { 12.9 + Atomic::add_ptr(subTable->sizes[i], &sizes[i]); 12.10 + } 12.11 +} 12.12 + 12.13 int ageTable::compute_tenuring_threshold(size_t survivor_capacity) { 12.14 size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100); 12.15 size_t total = 0;
13.1 --- a/src/share/vm/gc_implementation/shared/ageTable.hpp Thu Feb 05 11:42:10 2009 -0800 13.2 +++ b/src/share/vm/gc_implementation/shared/ageTable.hpp Fri Feb 06 01:38:50 2009 +0300 13.3 @@ -56,6 +56,7 @@ 13.4 // Merge another age table with the current one. Used 13.5 // for parallel young generation gc. 13.6 void merge(ageTable* subTable); 13.7 + void merge_par(ageTable* subTable); 13.8 13.9 // calculate new tenuring threshold based on age information 13.10 int compute_tenuring_threshold(size_t survivor_capacity);