Mercurial > hg > graal-compiler
comparison src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @ 1394:1316cec51b4d
6819061: G1: eliminate serial Other times that are proportional to the collection set length
6871109: G1: remove the concept of the scan only prefix
Summary: Removed scan only regions and associated code. The young portion of the collection set is now constructed incrementally - when a young region is retired as the current allocation region it is added to the collection set.
Reviewed-by: apetrusenko, iveresov, tonyp
author | johnc |
---|---|
date | Thu, 22 Apr 2010 10:02:38 -0700 |
parents | 79e419e5ea3b |
children | cff162798819 |
comparison
equal
deleted
inserted
replaced
1393:6ecb6e6de3d6 | 1394:1316cec51b4d |
---|---|
28 size_t G1CollectedHeap::_humongous_object_threshold_in_words = 0; | 28 size_t G1CollectedHeap::_humongous_object_threshold_in_words = 0; |
29 | 29 |
30 // turn it on so that the contents of the young list (scan-only / | 30 // turn it on so that the contents of the young list (scan-only / |
31 // to-be-collected) are printed at "strategic" points before / during | 31 // to-be-collected) are printed at "strategic" points before / during |
32 // / after the collection --- this is useful for debugging | 32 // / after the collection --- this is useful for debugging |
33 #define SCAN_ONLY_VERBOSE 0 | 33 #define YOUNG_LIST_VERBOSE 0 |
34 // CURRENT STATUS | 34 // CURRENT STATUS |
35 // This file is under construction. Search for "FIXME". | 35 // This file is under construction. Search for "FIXME". |
36 | 36 |
37 // INVARIANTS/NOTES | 37 // INVARIANTS/NOTES |
38 // | 38 // |
131 } | 131 } |
132 }; | 132 }; |
133 | 133 |
134 YoungList::YoungList(G1CollectedHeap* g1h) | 134 YoungList::YoungList(G1CollectedHeap* g1h) |
135 : _g1h(g1h), _head(NULL), | 135 : _g1h(g1h), _head(NULL), |
136 _scan_only_head(NULL), _scan_only_tail(NULL), _curr_scan_only(NULL), | 136 _length(0), |
137 _length(0), _scan_only_length(0), | |
138 _last_sampled_rs_lengths(0), | 137 _last_sampled_rs_lengths(0), |
139 _survivor_head(NULL), _survivor_tail(NULL), _survivor_length(0) | 138 _survivor_head(NULL), _survivor_tail(NULL), _survivor_length(0) |
140 { | 139 { |
141 guarantee( check_list_empty(false), "just making sure..." ); | 140 guarantee( check_list_empty(false), "just making sure..." ); |
142 } | 141 } |
162 _survivor_tail = hr; | 161 _survivor_tail = hr; |
163 } | 162 } |
164 _survivor_head = hr; | 163 _survivor_head = hr; |
165 | 164 |
166 ++_survivor_length; | 165 ++_survivor_length; |
167 } | |
168 | |
169 HeapRegion* YoungList::pop_region() { | |
170 while (_head != NULL) { | |
171 assert( length() > 0, "list should not be empty" ); | |
172 HeapRegion* ret = _head; | |
173 _head = ret->get_next_young_region(); | |
174 ret->set_next_young_region(NULL); | |
175 --_length; | |
176 assert(ret->is_young(), "region should be very young"); | |
177 | |
178 // Replace 'Survivor' region type with 'Young'. So the region will | |
179 // be treated as a young region and will not be 'confused' with | |
180 // newly created survivor regions. | |
181 if (ret->is_survivor()) { | |
182 ret->set_young(); | |
183 } | |
184 | |
185 if (!ret->is_scan_only()) { | |
186 return ret; | |
187 } | |
188 | |
189 // scan-only, we'll add it to the scan-only list | |
190 if (_scan_only_tail == NULL) { | |
191 guarantee( _scan_only_head == NULL, "invariant" ); | |
192 | |
193 _scan_only_head = ret; | |
194 _curr_scan_only = ret; | |
195 } else { | |
196 guarantee( _scan_only_head != NULL, "invariant" ); | |
197 _scan_only_tail->set_next_young_region(ret); | |
198 } | |
199 guarantee( ret->get_next_young_region() == NULL, "invariant" ); | |
200 _scan_only_tail = ret; | |
201 | |
202 // no need to be tagged as scan-only any more | |
203 ret->set_young(); | |
204 | |
205 ++_scan_only_length; | |
206 } | |
207 assert( length() == 0, "list should be empty" ); | |
208 return NULL; | |
209 } | 166 } |
210 | 167 |
211 void YoungList::empty_list(HeapRegion* list) { | 168 void YoungList::empty_list(HeapRegion* list) { |
212 while (list != NULL) { | 169 while (list != NULL) { |
213 HeapRegion* next = list->get_next_young_region(); | 170 HeapRegion* next = list->get_next_young_region(); |
223 | 180 |
224 empty_list(_head); | 181 empty_list(_head); |
225 _head = NULL; | 182 _head = NULL; |
226 _length = 0; | 183 _length = 0; |
227 | 184 |
228 empty_list(_scan_only_head); | |
229 _scan_only_head = NULL; | |
230 _scan_only_tail = NULL; | |
231 _scan_only_length = 0; | |
232 _curr_scan_only = NULL; | |
233 | |
234 empty_list(_survivor_head); | 185 empty_list(_survivor_head); |
235 _survivor_head = NULL; | 186 _survivor_head = NULL; |
236 _survivor_tail = NULL; | 187 _survivor_tail = NULL; |
237 _survivor_length = 0; | 188 _survivor_length = 0; |
238 | 189 |
246 | 197 |
247 size_t length = 0; | 198 size_t length = 0; |
248 HeapRegion* curr = _head; | 199 HeapRegion* curr = _head; |
249 HeapRegion* last = NULL; | 200 HeapRegion* last = NULL; |
250 while (curr != NULL) { | 201 while (curr != NULL) { |
251 if (!curr->is_young() || curr->is_scan_only()) { | 202 if (!curr->is_young()) { |
252 gclog_or_tty->print_cr("### YOUNG REGION "PTR_FORMAT"-"PTR_FORMAT" " | 203 gclog_or_tty->print_cr("### YOUNG REGION "PTR_FORMAT"-"PTR_FORMAT" " |
253 "incorrectly tagged (%d, %d)", | 204 "incorrectly tagged (y: %d, surv: %d)", |
254 curr->bottom(), curr->end(), | 205 curr->bottom(), curr->end(), |
255 curr->is_young(), curr->is_scan_only()); | 206 curr->is_young(), curr->is_survivor()); |
256 ret = false; | 207 ret = false; |
257 } | 208 } |
258 ++length; | 209 ++length; |
259 last = curr; | 210 last = curr; |
260 curr = curr->get_next_young_region(); | 211 curr = curr->get_next_young_region(); |
265 gclog_or_tty->print_cr("### YOUNG LIST seems not well formed!"); | 216 gclog_or_tty->print_cr("### YOUNG LIST seems not well formed!"); |
266 gclog_or_tty->print_cr("### list has %d entries, _length is %d", | 217 gclog_or_tty->print_cr("### list has %d entries, _length is %d", |
267 length, _length); | 218 length, _length); |
268 } | 219 } |
269 | 220 |
270 bool scan_only_ret = true; | 221 return ret; |
271 length = 0; | 222 } |
272 curr = _scan_only_head; | 223 |
273 last = NULL; | 224 bool YoungList::check_list_empty(bool check_sample) { |
274 while (curr != NULL) { | |
275 if (!curr->is_young() || curr->is_scan_only()) { | |
276 gclog_or_tty->print_cr("### SCAN-ONLY REGION "PTR_FORMAT"-"PTR_FORMAT" " | |
277 "incorrectly tagged (%d, %d)", | |
278 curr->bottom(), curr->end(), | |
279 curr->is_young(), curr->is_scan_only()); | |
280 scan_only_ret = false; | |
281 } | |
282 ++length; | |
283 last = curr; | |
284 curr = curr->get_next_young_region(); | |
285 } | |
286 scan_only_ret = scan_only_ret && (length == _scan_only_length); | |
287 | |
288 if ( (last != _scan_only_tail) || | |
289 (_scan_only_head == NULL && _scan_only_tail != NULL) || | |
290 (_scan_only_head != NULL && _scan_only_tail == NULL) ) { | |
291 gclog_or_tty->print_cr("## _scan_only_tail is set incorrectly"); | |
292 scan_only_ret = false; | |
293 } | |
294 | |
295 if (_curr_scan_only != NULL && _curr_scan_only != _scan_only_head) { | |
296 gclog_or_tty->print_cr("### _curr_scan_only is set incorrectly"); | |
297 scan_only_ret = false; | |
298 } | |
299 | |
300 if (!scan_only_ret) { | |
301 gclog_or_tty->print_cr("### SCAN-ONLY LIST seems not well formed!"); | |
302 gclog_or_tty->print_cr("### list has %d entries, _scan_only_length is %d", | |
303 length, _scan_only_length); | |
304 } | |
305 | |
306 return ret && scan_only_ret; | |
307 } | |
308 | |
309 bool YoungList::check_list_empty(bool ignore_scan_only_list, | |
310 bool check_sample) { | |
311 bool ret = true; | 225 bool ret = true; |
312 | 226 |
313 if (_length != 0) { | 227 if (_length != 0) { |
314 gclog_or_tty->print_cr("### YOUNG LIST should have 0 length, not %d", | 228 gclog_or_tty->print_cr("### YOUNG LIST should have 0 length, not %d", |
315 _length); | 229 _length); |
325 } | 239 } |
326 if (!ret) { | 240 if (!ret) { |
327 gclog_or_tty->print_cr("### YOUNG LIST does not seem empty"); | 241 gclog_or_tty->print_cr("### YOUNG LIST does not seem empty"); |
328 } | 242 } |
329 | 243 |
330 if (ignore_scan_only_list) | 244 return ret; |
331 return ret; | |
332 | |
333 bool scan_only_ret = true; | |
334 if (_scan_only_length != 0) { | |
335 gclog_or_tty->print_cr("### SCAN-ONLY LIST should have 0 length, not %d", | |
336 _scan_only_length); | |
337 scan_only_ret = false; | |
338 } | |
339 if (_scan_only_head != NULL) { | |
340 gclog_or_tty->print_cr("### SCAN-ONLY LIST does not have a NULL head"); | |
341 scan_only_ret = false; | |
342 } | |
343 if (_scan_only_tail != NULL) { | |
344 gclog_or_tty->print_cr("### SCAN-ONLY LIST does not have a NULL tail"); | |
345 scan_only_ret = false; | |
346 } | |
347 if (!scan_only_ret) { | |
348 gclog_or_tty->print_cr("### SCAN-ONLY LIST does not seem empty"); | |
349 } | |
350 | |
351 return ret && scan_only_ret; | |
352 } | 245 } |
353 | 246 |
354 void | 247 void |
355 YoungList::rs_length_sampling_init() { | 248 YoungList::rs_length_sampling_init() { |
356 _sampled_rs_lengths = 0; | 249 _sampled_rs_lengths = 0; |
363 } | 256 } |
364 | 257 |
365 void | 258 void |
366 YoungList::rs_length_sampling_next() { | 259 YoungList::rs_length_sampling_next() { |
367 assert( _curr != NULL, "invariant" ); | 260 assert( _curr != NULL, "invariant" ); |
368 _sampled_rs_lengths += _curr->rem_set()->occupied(); | 261 size_t rs_length = _curr->rem_set()->occupied(); |
262 | |
263 _sampled_rs_lengths += rs_length; | |
264 | |
265 // The current region may not yet have been added to the | |
266 // incremental collection set (it gets added when it is | |
267 // retired as the current allocation region). | |
268 if (_curr->in_collection_set()) { | |
269 // Update the collection set policy information for this region | |
270 _g1h->g1_policy()->update_incremental_cset_info(_curr, rs_length); | |
271 } | |
272 | |
369 _curr = _curr->get_next_young_region(); | 273 _curr = _curr->get_next_young_region(); |
370 if (_curr == NULL) { | 274 if (_curr == NULL) { |
371 _last_sampled_rs_lengths = _sampled_rs_lengths; | 275 _last_sampled_rs_lengths = _sampled_rs_lengths; |
372 // gclog_or_tty->print_cr("last sampled RS lengths = %d", _last_sampled_rs_lengths); | 276 // gclog_or_tty->print_cr("last sampled RS lengths = %d", _last_sampled_rs_lengths); |
373 } | 277 } |
374 } | 278 } |
375 | 279 |
376 void | 280 void |
377 YoungList::reset_auxilary_lists() { | 281 YoungList::reset_auxilary_lists() { |
378 // We could have just "moved" the scan-only list to the young list. | |
379 // However, the scan-only list is ordered according to the region | |
380 // age in descending order, so, by moving one entry at a time, we | |
381 // ensure that it is recreated in ascending order. | |
382 | |
383 guarantee( is_empty(), "young list should be empty" ); | 282 guarantee( is_empty(), "young list should be empty" ); |
384 assert(check_list_well_formed(), "young list should be well formed"); | 283 assert(check_list_well_formed(), "young list should be well formed"); |
385 | 284 |
386 // Add survivor regions to SurvRateGroup. | 285 // Add survivor regions to SurvRateGroup. |
387 _g1h->g1_policy()->note_start_adding_survivor_regions(); | 286 _g1h->g1_policy()->note_start_adding_survivor_regions(); |
388 _g1h->g1_policy()->finished_recalculating_age_indexes(true /* is_survivors */); | 287 _g1h->g1_policy()->finished_recalculating_age_indexes(true /* is_survivors */); |
288 | |
389 for (HeapRegion* curr = _survivor_head; | 289 for (HeapRegion* curr = _survivor_head; |
390 curr != NULL; | 290 curr != NULL; |
391 curr = curr->get_next_young_region()) { | 291 curr = curr->get_next_young_region()) { |
392 _g1h->g1_policy()->set_region_survivors(curr); | 292 _g1h->g1_policy()->set_region_survivors(curr); |
293 | |
294 // The region is a non-empty survivor so let's add it to | |
295 // the incremental collection set for the next evacuation | |
296 // pause. | |
297 _g1h->g1_policy()->add_region_to_incremental_cset_rhs(curr); | |
393 } | 298 } |
394 _g1h->g1_policy()->note_stop_adding_survivor_regions(); | 299 _g1h->g1_policy()->note_stop_adding_survivor_regions(); |
395 | 300 |
301 _head = _survivor_head; | |
302 _length = _survivor_length; | |
396 if (_survivor_head != NULL) { | 303 if (_survivor_head != NULL) { |
397 _head = _survivor_head; | 304 assert(_survivor_tail != NULL, "cause it shouldn't be"); |
398 _length = _survivor_length + _scan_only_length; | 305 assert(_survivor_length > 0, "invariant"); |
399 _survivor_tail->set_next_young_region(_scan_only_head); | 306 _survivor_tail->set_next_young_region(NULL); |
400 } else { | 307 } |
401 _head = _scan_only_head; | 308 |
402 _length = _scan_only_length; | 309 // Don't clear the survivor list handles until the start of |
403 } | 310 // the next evacuation pause - we need it in order to re-tag |
404 | 311 // the survivor regions from this evacuation pause as 'young' |
405 for (HeapRegion* curr = _scan_only_head; | 312 // at the start of the next. |
406 curr != NULL; | 313 |
407 curr = curr->get_next_young_region()) { | |
408 curr->recalculate_age_in_surv_rate_group(); | |
409 } | |
410 _scan_only_head = NULL; | |
411 _scan_only_tail = NULL; | |
412 _scan_only_length = 0; | |
413 _curr_scan_only = NULL; | |
414 | |
415 _survivor_head = NULL; | |
416 _survivor_tail = NULL; | |
417 _survivor_length = 0; | |
418 _g1h->g1_policy()->finished_recalculating_age_indexes(false /* is_survivors */); | 314 _g1h->g1_policy()->finished_recalculating_age_indexes(false /* is_survivors */); |
419 | 315 |
420 assert(check_list_well_formed(), "young list should be well formed"); | 316 assert(check_list_well_formed(), "young list should be well formed"); |
421 } | 317 } |
422 | 318 |
423 void YoungList::print() { | 319 void YoungList::print() { |
424 HeapRegion* lists[] = {_head, _scan_only_head, _survivor_head}; | 320 HeapRegion* lists[] = {_head, _survivor_head}; |
425 const char* names[] = {"YOUNG", "SCAN-ONLY", "SURVIVOR"}; | 321 const char* names[] = {"YOUNG", "SURVIVOR"}; |
426 | 322 |
427 for (unsigned int list = 0; list < ARRAY_SIZE(lists); ++list) { | 323 for (unsigned int list = 0; list < ARRAY_SIZE(lists); ++list) { |
428 gclog_or_tty->print_cr("%s LIST CONTENTS", names[list]); | 324 gclog_or_tty->print_cr("%s LIST CONTENTS", names[list]); |
429 HeapRegion *curr = lists[list]; | 325 HeapRegion *curr = lists[list]; |
430 if (curr == NULL) | 326 if (curr == NULL) |
431 gclog_or_tty->print_cr(" empty"); | 327 gclog_or_tty->print_cr(" empty"); |
432 while (curr != NULL) { | 328 while (curr != NULL) { |
433 gclog_or_tty->print_cr(" [%08x-%08x], t: %08x, P: %08x, N: %08x, C: %08x, " | 329 gclog_or_tty->print_cr(" [%08x-%08x], t: %08x, P: %08x, N: %08x, C: %08x, " |
434 "age: %4d, y: %d, s-o: %d, surv: %d", | 330 "age: %4d, y: %d, surv: %d", |
435 curr->bottom(), curr->end(), | 331 curr->bottom(), curr->end(), |
436 curr->top(), | 332 curr->top(), |
437 curr->prev_top_at_mark_start(), | 333 curr->prev_top_at_mark_start(), |
438 curr->next_top_at_mark_start(), | 334 curr->next_top_at_mark_start(), |
439 curr->top_at_conc_mark_count(), | 335 curr->top_at_conc_mark_count(), |
440 curr->age_in_surv_rate_group_cond(), | 336 curr->age_in_surv_rate_group_cond(), |
441 curr->is_young(), | 337 curr->is_young(), |
442 curr->is_scan_only(), | |
443 curr->is_survivor()); | 338 curr->is_survivor()); |
444 curr = curr->get_next_young_region(); | 339 curr = curr->get_next_young_region(); |
445 } | 340 } |
446 } | 341 } |
447 | 342 |
705 // If we do a collection pause, this will be reset to a non-NULL | 600 // If we do a collection pause, this will be reset to a non-NULL |
706 // value. If we don't, nulling here ensures that we allocate a new | 601 // value. If we don't, nulling here ensures that we allocate a new |
707 // region below. | 602 // region below. |
708 if (_cur_alloc_region != NULL) { | 603 if (_cur_alloc_region != NULL) { |
709 // We're finished with the _cur_alloc_region. | 604 // We're finished with the _cur_alloc_region. |
605 // As we're builing (at least the young portion) of the collection | |
606 // set incrementally we'll add the current allocation region to | |
607 // the collection set here. | |
608 if (_cur_alloc_region->is_young()) { | |
609 g1_policy()->add_region_to_incremental_cset_lhs(_cur_alloc_region); | |
610 } | |
710 _summary_bytes_used += _cur_alloc_region->used(); | 611 _summary_bytes_used += _cur_alloc_region->used(); |
711 _cur_alloc_region = NULL; | 612 _cur_alloc_region = NULL; |
712 } | 613 } |
713 assert(_cur_alloc_region == NULL, "Invariant."); | 614 assert(_cur_alloc_region == NULL, "Invariant."); |
714 // Completion of a heap region is perhaps a good point at which to do | 615 // Completion of a heap region is perhaps a good point at which to do |
818 // We're finished with the _cur_alloc_region. | 719 // We're finished with the _cur_alloc_region. |
819 if (_cur_alloc_region->is_empty()) { | 720 if (_cur_alloc_region->is_empty()) { |
820 _free_regions++; | 721 _free_regions++; |
821 free_region(_cur_alloc_region); | 722 free_region(_cur_alloc_region); |
822 } else { | 723 } else { |
724 // As we're builing (at least the young portion) of the collection | |
725 // set incrementally we'll add the current allocation region to | |
726 // the collection set here. | |
727 if (_cur_alloc_region->is_young()) { | |
728 g1_policy()->add_region_to_incremental_cset_lhs(_cur_alloc_region); | |
729 } | |
823 _summary_bytes_used += _cur_alloc_region->used(); | 730 _summary_bytes_used += _cur_alloc_region->used(); |
824 } | 731 } |
825 _cur_alloc_region = NULL; | 732 _cur_alloc_region = NULL; |
826 } | 733 } |
827 } | 734 } |
973 abandon_gc_alloc_regions(); | 880 abandon_gc_alloc_regions(); |
974 assert(_cur_alloc_region == NULL, "Invariant."); | 881 assert(_cur_alloc_region == NULL, "Invariant."); |
975 g1_rem_set()->as_HRInto_G1RemSet()->cleanupHRRS(); | 882 g1_rem_set()->as_HRInto_G1RemSet()->cleanupHRRS(); |
976 tear_down_region_lists(); | 883 tear_down_region_lists(); |
977 set_used_regions_to_need_zero_fill(); | 884 set_used_regions_to_need_zero_fill(); |
885 | |
886 // We may have added regions to the current incremental collection | |
887 // set between the last GC or pause and now. We need to clear the | |
888 // incremental collection set and then start rebuilding it afresh | |
889 // after this full GC. | |
890 abandon_collection_set(g1_policy()->inc_cset_head()); | |
891 g1_policy()->clear_incremental_cset(); | |
892 g1_policy()->stop_incremental_cset_building(); | |
893 | |
978 if (g1_policy()->in_young_gc_mode()) { | 894 if (g1_policy()->in_young_gc_mode()) { |
979 empty_young_list(); | 895 empty_young_list(); |
980 g1_policy()->set_full_young_gcs(true); | 896 g1_policy()->set_full_young_gcs(true); |
981 } | 897 } |
982 | 898 |
1056 if (true) { // FIXME | 972 if (true) { // FIXME |
1057 // Ask the permanent generation to adjust size for full collections | 973 // Ask the permanent generation to adjust size for full collections |
1058 perm()->compute_new_size(); | 974 perm()->compute_new_size(); |
1059 } | 975 } |
1060 | 976 |
977 // Start a new incremental collection set for the next pause | |
978 assert(g1_policy()->collection_set() == NULL, "must be"); | |
979 g1_policy()->start_incremental_cset_building(); | |
980 | |
981 // Clear the _cset_fast_test bitmap in anticipation of adding | |
982 // regions to the incremental collection set for the next | |
983 // evacuation pause. | |
984 clear_cset_fast_test(); | |
985 | |
1061 double end = os::elapsedTime(); | 986 double end = os::elapsedTime(); |
1062 g1_policy()->record_full_collection_end(); | 987 g1_policy()->record_full_collection_end(); |
1063 | 988 |
1064 #ifdef TRACESPINNING | 989 #ifdef TRACESPINNING |
1065 ParallelTaskTerminator::print_termination_counts(); | 990 ParallelTaskTerminator::print_termination_counts(); |
1074 assert(regions_accounted_for(), "Region leakage!"); | 999 assert(regions_accounted_for(), "Region leakage!"); |
1075 } | 1000 } |
1076 | 1001 |
1077 if (g1_policy()->in_young_gc_mode()) { | 1002 if (g1_policy()->in_young_gc_mode()) { |
1078 _young_list->reset_sampled_info(); | 1003 _young_list->reset_sampled_info(); |
1079 assert( check_young_list_empty(false, false), | 1004 // At this point there should be no regions in the |
1005 // entire heap tagged as young. | |
1006 assert( check_young_list_empty(true /* check_heap */), | |
1080 "young list should be empty at this point"); | 1007 "young list should be empty at this point"); |
1081 } | 1008 } |
1082 | 1009 |
1083 if (PrintHeapAtGC) { | 1010 if (PrintHeapAtGC) { |
1084 Universe::print_heap_after_gc(); | 1011 Universe::print_heap_after_gc(); |
1571 _bot_shared = new G1BlockOffsetSharedArray(_reserved, | 1498 _bot_shared = new G1BlockOffsetSharedArray(_reserved, |
1572 heap_word_size(init_byte_size)); | 1499 heap_word_size(init_byte_size)); |
1573 | 1500 |
1574 _g1h = this; | 1501 _g1h = this; |
1575 | 1502 |
1503 _in_cset_fast_test_length = max_regions(); | |
1504 _in_cset_fast_test_base = NEW_C_HEAP_ARRAY(bool, _in_cset_fast_test_length); | |
1505 | |
1506 // We're biasing _in_cset_fast_test to avoid subtracting the | |
1507 // beginning of the heap every time we want to index; basically | |
1508 // it's the same with what we do with the card table. | |
1509 _in_cset_fast_test = _in_cset_fast_test_base - | |
1510 ((size_t) _g1_reserved.start() >> HeapRegion::LogOfHRGrainBytes); | |
1511 | |
1512 // Clear the _cset_fast_test bitmap in anticipation of adding | |
1513 // regions to the incremental collection set for the first | |
1514 // evacuation pause. | |
1515 clear_cset_fast_test(); | |
1516 | |
1576 // Create the ConcurrentMark data structure and thread. | 1517 // Create the ConcurrentMark data structure and thread. |
1577 // (Must do this late, so that "max_regions" is defined.) | 1518 // (Must do this late, so that "max_regions" is defined.) |
1578 _cm = new ConcurrentMark(heap_rs, (int) max_regions()); | 1519 _cm = new ConcurrentMark(heap_rs, (int) max_regions()); |
1579 _cmThread = _cm->cmThread(); | 1520 _cmThread = _cm->cmThread(); |
1580 | 1521 |
2749 // The elapsed time induced by the start time below deliberately elides | 2690 // The elapsed time induced by the start time below deliberately elides |
2750 // the possible verification above. | 2691 // the possible verification above. |
2751 double start_time_sec = os::elapsedTime(); | 2692 double start_time_sec = os::elapsedTime(); |
2752 size_t start_used_bytes = used(); | 2693 size_t start_used_bytes = used(); |
2753 | 2694 |
2695 #if YOUNG_LIST_VERBOSE | |
2696 gclog_or_tty->print_cr("\nBefore recording pause start.\nYoung_list:"); | |
2697 _young_list->print(); | |
2698 g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty); | |
2699 #endif // YOUNG_LIST_VERBOSE | |
2700 | |
2754 g1_policy()->record_collection_pause_start(start_time_sec, | 2701 g1_policy()->record_collection_pause_start(start_time_sec, |
2755 start_used_bytes); | 2702 start_used_bytes); |
2756 | 2703 |
2757 guarantee(_in_cset_fast_test == NULL, "invariant"); | 2704 #if YOUNG_LIST_VERBOSE |
2758 guarantee(_in_cset_fast_test_base == NULL, "invariant"); | 2705 gclog_or_tty->print_cr("\nAfter recording pause start.\nYoung_list:"); |
2759 _in_cset_fast_test_length = max_regions(); | |
2760 _in_cset_fast_test_base = | |
2761 NEW_C_HEAP_ARRAY(bool, _in_cset_fast_test_length); | |
2762 memset(_in_cset_fast_test_base, false, | |
2763 _in_cset_fast_test_length * sizeof(bool)); | |
2764 // We're biasing _in_cset_fast_test to avoid subtracting the | |
2765 // beginning of the heap every time we want to index; basically | |
2766 // it's the same with what we do with the card table. | |
2767 _in_cset_fast_test = _in_cset_fast_test_base - | |
2768 ((size_t) _g1_reserved.start() >> HeapRegion::LogOfHRGrainBytes); | |
2769 | |
2770 #if SCAN_ONLY_VERBOSE | |
2771 _young_list->print(); | 2706 _young_list->print(); |
2772 #endif // SCAN_ONLY_VERBOSE | 2707 #endif // YOUNG_LIST_VERBOSE |
2773 | 2708 |
2774 if (g1_policy()->during_initial_mark_pause()) { | 2709 if (g1_policy()->during_initial_mark_pause()) { |
2775 concurrent_mark()->checkpointRootsInitialPre(); | 2710 concurrent_mark()->checkpointRootsInitialPre(); |
2776 } | 2711 } |
2777 save_marks(); | 2712 save_marks(); |
2794 assert(regions_accounted_for(), "Region leakage."); | 2729 assert(regions_accounted_for(), "Region leakage."); |
2795 | 2730 |
2796 if (mark_in_progress()) | 2731 if (mark_in_progress()) |
2797 concurrent_mark()->newCSet(); | 2732 concurrent_mark()->newCSet(); |
2798 | 2733 |
2799 // Now choose the CS. | 2734 #if YOUNG_LIST_VERBOSE |
2800 g1_policy()->choose_collection_set(); | 2735 gclog_or_tty->print_cr("\nBefore choosing collection set.\nYoung_list:"); |
2801 | 2736 _young_list->print(); |
2802 // We may abandon a pause if we find no region that will fit in the MMU | 2737 g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty); |
2803 // pause. | 2738 #endif // YOUNG_LIST_VERBOSE |
2804 bool abandoned = (g1_policy()->collection_set() == NULL); | 2739 |
2740 // Now choose the CS. We may abandon a pause if we find no | |
2741 // region that will fit in the MMU pause. | |
2742 bool abandoned = g1_policy()->choose_collection_set(); | |
2805 | 2743 |
2806 // Nothing to do if we were unable to choose a collection set. | 2744 // Nothing to do if we were unable to choose a collection set. |
2807 if (!abandoned) { | 2745 if (!abandoned) { |
2808 #if G1_REM_SET_LOGGING | 2746 #if G1_REM_SET_LOGGING |
2809 gclog_or_tty->print_cr("\nAfter pause, heap:"); | 2747 gclog_or_tty->print_cr("\nAfter pause, heap:"); |
2817 // Set up the gc allocation regions. | 2755 // Set up the gc allocation regions. |
2818 get_gc_alloc_regions(); | 2756 get_gc_alloc_regions(); |
2819 | 2757 |
2820 // Actually do the work... | 2758 // Actually do the work... |
2821 evacuate_collection_set(); | 2759 evacuate_collection_set(); |
2760 | |
2822 free_collection_set(g1_policy()->collection_set()); | 2761 free_collection_set(g1_policy()->collection_set()); |
2823 g1_policy()->clear_collection_set(); | 2762 g1_policy()->clear_collection_set(); |
2824 | 2763 |
2825 FREE_C_HEAP_ARRAY(bool, _in_cset_fast_test_base); | |
2826 // this is more for peace of mind; we're nulling them here and | |
2827 // we're expecting them to be null at the beginning of the next GC | |
2828 _in_cset_fast_test = NULL; | |
2829 _in_cset_fast_test_base = NULL; | |
2830 | |
2831 cleanup_surviving_young_words(); | 2764 cleanup_surviving_young_words(); |
2765 | |
2766 // Start a new incremental collection set for the next pause. | |
2767 g1_policy()->start_incremental_cset_building(); | |
2768 | |
2769 // Clear the _cset_fast_test bitmap in anticipation of adding | |
2770 // regions to the incremental collection set for the next | |
2771 // evacuation pause. | |
2772 clear_cset_fast_test(); | |
2832 | 2773 |
2833 if (g1_policy()->in_young_gc_mode()) { | 2774 if (g1_policy()->in_young_gc_mode()) { |
2834 _young_list->reset_sampled_info(); | 2775 _young_list->reset_sampled_info(); |
2835 assert(check_young_list_empty(true), | 2776 |
2836 "young list should be empty"); | 2777 // Don't check the whole heap at this point as the |
2837 | 2778 // GC alloc regions from this pause have been tagged |
2838 #if SCAN_ONLY_VERBOSE | 2779 // as survivors and moved on to the survivor list. |
2780 // Survivor regions will fail the !is_young() check. | |
2781 assert(check_young_list_empty(false /* check_heap */), | |
2782 "young list should be empty"); | |
2783 | |
2784 #if YOUNG_LIST_VERBOSE | |
2785 gclog_or_tty->print_cr("Before recording survivors.\nYoung List:"); | |
2839 _young_list->print(); | 2786 _young_list->print(); |
2840 #endif // SCAN_ONLY_VERBOSE | 2787 #endif // YOUNG_LIST_VERBOSE |
2841 | 2788 |
2842 g1_policy()->record_survivor_regions(_young_list->survivor_length(), | 2789 g1_policy()->record_survivor_regions(_young_list->survivor_length(), |
2843 _young_list->first_survivor_region(), | 2790 _young_list->first_survivor_region(), |
2844 _young_list->last_survivor_region()); | 2791 _young_list->last_survivor_region()); |
2792 | |
2845 _young_list->reset_auxilary_lists(); | 2793 _young_list->reset_auxilary_lists(); |
2846 } | 2794 } |
2847 } else { | 2795 } else { |
2848 if (_in_cset_fast_test != NULL) { | 2796 // We have abandoned the current collection. This can only happen |
2849 assert(_in_cset_fast_test_base != NULL, "Since _in_cset_fast_test isn't"); | 2797 // if we're not doing young or partially young collections, and |
2850 FREE_C_HEAP_ARRAY(bool, _in_cset_fast_test_base); | 2798 // we didn't find an old region that we're able to collect within |
2851 // this is more for peace of mind; we're nulling them here and | 2799 // the allowed time. |
2852 // we're expecting them to be null at the beginning of the next GC | 2800 |
2853 _in_cset_fast_test = NULL; | 2801 assert(g1_policy()->collection_set() == NULL, "should be"); |
2854 _in_cset_fast_test_base = NULL; | 2802 assert(_young_list->length() == 0, "because it should be"); |
2855 } | 2803 |
2804 // This should be a no-op. | |
2805 abandon_collection_set(g1_policy()->inc_cset_head()); | |
2806 | |
2807 g1_policy()->clear_incremental_cset(); | |
2808 g1_policy()->stop_incremental_cset_building(); | |
2809 | |
2810 // Start a new incremental collection set for the next pause. | |
2811 g1_policy()->start_incremental_cset_building(); | |
2812 | |
2813 // Clear the _cset_fast_test bitmap in anticipation of adding | |
2814 // regions to the incremental collection set for the next | |
2815 // evacuation pause. | |
2816 clear_cset_fast_test(); | |
2817 | |
2856 // This looks confusing, because the DPT should really be empty | 2818 // This looks confusing, because the DPT should really be empty |
2857 // at this point -- since we have not done any collection work, | 2819 // at this point -- since we have not done any collection work, |
2858 // there should not be any derived pointers in the table to update; | 2820 // there should not be any derived pointers in the table to update; |
2859 // however, there is some additional state in the DPT which is | 2821 // however, there is some additional state in the DPT which is |
2860 // reset at the end of the (null) "gc" here via the following call. | 2822 // reset at the end of the (null) "gc" here via the following call. |
2884 // not start until the safepoint itself is released in | 2846 // not start until the safepoint itself is released in |
2885 // ConcurrentGCThread::safepoint_desynchronize(). | 2847 // ConcurrentGCThread::safepoint_desynchronize(). |
2886 doConcurrentMark(); | 2848 doConcurrentMark(); |
2887 } | 2849 } |
2888 | 2850 |
2889 #if SCAN_ONLY_VERBOSE | 2851 #if YOUNG_LIST_VERBOSE |
2852 gclog_or_tty->print_cr("\nEnd of the pause.\nYoung_list:"); | |
2890 _young_list->print(); | 2853 _young_list->print(); |
2891 #endif // SCAN_ONLY_VERBOSE | 2854 g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty); |
2855 #endif // YOUNG_LIST_VERBOSE | |
2892 | 2856 |
2893 double end_time_sec = os::elapsedTime(); | 2857 double end_time_sec = os::elapsedTime(); |
2894 double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS; | 2858 double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS; |
2895 g1_policy()->record_pause_time_ms(pause_time_ms); | 2859 g1_policy()->record_pause_time_ms(pause_time_ms); |
2896 g1_policy()->record_collection_pause_end(abandoned); | 2860 g1_policy()->record_collection_pause_end(abandoned); |
4025 G1ParScanAndMarkPermClosure scan_mark_perm_cl(_g1h, &pss); | 3989 G1ParScanAndMarkPermClosure scan_mark_perm_cl(_g1h, &pss); |
4026 G1ParScanAndMarkHeapRSClosure scan_mark_heap_rs_cl(_g1h, &pss); | 3990 G1ParScanAndMarkHeapRSClosure scan_mark_heap_rs_cl(_g1h, &pss); |
4027 | 3991 |
4028 OopsInHeapRegionClosure *scan_root_cl; | 3992 OopsInHeapRegionClosure *scan_root_cl; |
4029 OopsInHeapRegionClosure *scan_perm_cl; | 3993 OopsInHeapRegionClosure *scan_perm_cl; |
4030 OopsInHeapRegionClosure *scan_so_cl; | |
4031 | 3994 |
4032 if (_g1h->g1_policy()->during_initial_mark_pause()) { | 3995 if (_g1h->g1_policy()->during_initial_mark_pause()) { |
4033 scan_root_cl = &scan_mark_root_cl; | 3996 scan_root_cl = &scan_mark_root_cl; |
4034 scan_perm_cl = &scan_mark_perm_cl; | 3997 scan_perm_cl = &scan_mark_perm_cl; |
4035 scan_so_cl = &scan_mark_heap_rs_cl; | |
4036 } else { | 3998 } else { |
4037 scan_root_cl = &only_scan_root_cl; | 3999 scan_root_cl = &only_scan_root_cl; |
4038 scan_perm_cl = &only_scan_perm_cl; | 4000 scan_perm_cl = &only_scan_perm_cl; |
4039 scan_so_cl = &only_scan_heap_rs_cl; | |
4040 } | 4001 } |
4041 | 4002 |
4042 pss.start_strong_roots(); | 4003 pss.start_strong_roots(); |
4043 _g1h->g1_process_strong_roots(/* not collecting perm */ false, | 4004 _g1h->g1_process_strong_roots(/* not collecting perm */ false, |
4044 SharedHeap::SO_AllClasses, | 4005 SharedHeap::SO_AllClasses, |
4045 scan_root_cl, | 4006 scan_root_cl, |
4046 &push_heap_rs_cl, | 4007 &push_heap_rs_cl, |
4047 scan_so_cl, | |
4048 scan_perm_cl, | 4008 scan_perm_cl, |
4049 i); | 4009 i); |
4050 pss.end_strong_roots(); | 4010 pss.end_strong_roots(); |
4051 { | 4011 { |
4052 double start = os::elapsedTime(); | 4012 double start = os::elapsedTime(); |
4104 G1CollectedHeap:: | 4064 G1CollectedHeap:: |
4105 g1_process_strong_roots(bool collecting_perm_gen, | 4065 g1_process_strong_roots(bool collecting_perm_gen, |
4106 SharedHeap::ScanningOption so, | 4066 SharedHeap::ScanningOption so, |
4107 OopClosure* scan_non_heap_roots, | 4067 OopClosure* scan_non_heap_roots, |
4108 OopsInHeapRegionClosure* scan_rs, | 4068 OopsInHeapRegionClosure* scan_rs, |
4109 OopsInHeapRegionClosure* scan_so, | |
4110 OopsInGenClosure* scan_perm, | 4069 OopsInGenClosure* scan_perm, |
4111 int worker_i) { | 4070 int worker_i) { |
4112 // First scan the strong roots, including the perm gen. | 4071 // First scan the strong roots, including the perm gen. |
4113 double ext_roots_start = os::elapsedTime(); | 4072 double ext_roots_start = os::elapsedTime(); |
4114 double closure_app_time_sec = 0.0; | 4073 double closure_app_time_sec = 0.0; |
4124 process_strong_roots(false, // no scoping; this is parallel code | 4083 process_strong_roots(false, // no scoping; this is parallel code |
4125 collecting_perm_gen, so, | 4084 collecting_perm_gen, so, |
4126 &buf_scan_non_heap_roots, | 4085 &buf_scan_non_heap_roots, |
4127 &eager_scan_code_roots, | 4086 &eager_scan_code_roots, |
4128 &buf_scan_perm); | 4087 &buf_scan_perm); |
4088 | |
4129 // Finish up any enqueued closure apps. | 4089 // Finish up any enqueued closure apps. |
4130 buf_scan_non_heap_roots.done(); | 4090 buf_scan_non_heap_roots.done(); |
4131 buf_scan_perm.done(); | 4091 buf_scan_perm.done(); |
4132 double ext_roots_end = os::elapsedTime(); | 4092 double ext_roots_end = os::elapsedTime(); |
4133 g1_policy()->reset_obj_copy_time(worker_i); | 4093 g1_policy()->reset_obj_copy_time(worker_i); |
4146 double mark_stack_scan_ms = (os::elapsedTime() - ext_roots_end) * 1000.0; | 4106 double mark_stack_scan_ms = (os::elapsedTime() - ext_roots_end) * 1000.0; |
4147 g1_policy()->record_mark_stack_scan_time(worker_i, mark_stack_scan_ms); | 4107 g1_policy()->record_mark_stack_scan_time(worker_i, mark_stack_scan_ms); |
4148 | 4108 |
4149 // XXX What should this be doing in the parallel case? | 4109 // XXX What should this be doing in the parallel case? |
4150 g1_policy()->record_collection_pause_end_CH_strong_roots(); | 4110 g1_policy()->record_collection_pause_end_CH_strong_roots(); |
4151 if (scan_so != NULL) { | |
4152 scan_scan_only_set(scan_so, worker_i); | |
4153 } | |
4154 // Now scan the complement of the collection set. | 4111 // Now scan the complement of the collection set. |
4155 if (scan_rs != NULL) { | 4112 if (scan_rs != NULL) { |
4156 g1_rem_set()->oops_into_collection_set_do(scan_rs, worker_i); | 4113 g1_rem_set()->oops_into_collection_set_do(scan_rs, worker_i); |
4157 } | 4114 } |
4158 // Finish with the ref_processor roots. | 4115 // Finish with the ref_processor roots. |
4159 if (!_process_strong_tasks->is_task_claimed(G1H_PS_refProcessor_oops_do)) { | 4116 if (!_process_strong_tasks->is_task_claimed(G1H_PS_refProcessor_oops_do)) { |
4160 ref_processor()->oops_do(scan_non_heap_roots); | 4117 ref_processor()->oops_do(scan_non_heap_roots); |
4161 } | 4118 } |
4162 g1_policy()->record_collection_pause_end_G1_strong_roots(); | 4119 g1_policy()->record_collection_pause_end_G1_strong_roots(); |
4163 _process_strong_tasks->all_tasks_completed(); | 4120 _process_strong_tasks->all_tasks_completed(); |
4164 } | |
4165 | |
4166 void | |
4167 G1CollectedHeap::scan_scan_only_region(HeapRegion* r, | |
4168 OopsInHeapRegionClosure* oc, | |
4169 int worker_i) { | |
4170 HeapWord* startAddr = r->bottom(); | |
4171 HeapWord* endAddr = r->used_region().end(); | |
4172 | |
4173 oc->set_region(r); | |
4174 | |
4175 HeapWord* p = r->bottom(); | |
4176 HeapWord* t = r->top(); | |
4177 guarantee( p == r->next_top_at_mark_start(), "invariant" ); | |
4178 while (p < t) { | |
4179 oop obj = oop(p); | |
4180 p += obj->oop_iterate(oc); | |
4181 } | |
4182 } | |
4183 | |
4184 void | |
4185 G1CollectedHeap::scan_scan_only_set(OopsInHeapRegionClosure* oc, | |
4186 int worker_i) { | |
4187 double start = os::elapsedTime(); | |
4188 | |
4189 BufferingOopsInHeapRegionClosure boc(oc); | |
4190 | |
4191 FilterInHeapRegionAndIntoCSClosure scan_only(this, &boc); | |
4192 FilterAndMarkInHeapRegionAndIntoCSClosure scan_and_mark(this, &boc, concurrent_mark()); | |
4193 | |
4194 OopsInHeapRegionClosure *foc; | |
4195 if (g1_policy()->during_initial_mark_pause()) | |
4196 foc = &scan_and_mark; | |
4197 else | |
4198 foc = &scan_only; | |
4199 | |
4200 HeapRegion* hr; | |
4201 int n = 0; | |
4202 while ((hr = _young_list->par_get_next_scan_only_region()) != NULL) { | |
4203 scan_scan_only_region(hr, foc, worker_i); | |
4204 ++n; | |
4205 } | |
4206 boc.done(); | |
4207 | |
4208 double closure_app_s = boc.closure_app_seconds(); | |
4209 g1_policy()->record_obj_copy_time(worker_i, closure_app_s * 1000.0); | |
4210 double ms = (os::elapsedTime() - start - closure_app_s)*1000.0; | |
4211 g1_policy()->record_scan_only_time(worker_i, ms, n); | |
4212 } | 4121 } |
4213 | 4122 |
4214 void | 4123 void |
4215 G1CollectedHeap::g1_process_weak_roots(OopClosure* root_closure, | 4124 G1CollectedHeap::g1_process_weak_roots(OopClosure* root_closure, |
4216 OopClosure* non_root_closure) { | 4125 OopClosure* non_root_closure) { |
4407 | 4316 |
4408 | 4317 |
4409 class G1ParCleanupCTTask : public AbstractGangTask { | 4318 class G1ParCleanupCTTask : public AbstractGangTask { |
4410 CardTableModRefBS* _ct_bs; | 4319 CardTableModRefBS* _ct_bs; |
4411 G1CollectedHeap* _g1h; | 4320 G1CollectedHeap* _g1h; |
4412 HeapRegion* volatile _so_head; | |
4413 HeapRegion* volatile _su_head; | 4321 HeapRegion* volatile _su_head; |
4414 public: | 4322 public: |
4415 G1ParCleanupCTTask(CardTableModRefBS* ct_bs, | 4323 G1ParCleanupCTTask(CardTableModRefBS* ct_bs, |
4416 G1CollectedHeap* g1h, | 4324 G1CollectedHeap* g1h, |
4417 HeapRegion* scan_only_list, | |
4418 HeapRegion* survivor_list) : | 4325 HeapRegion* survivor_list) : |
4419 AbstractGangTask("G1 Par Cleanup CT Task"), | 4326 AbstractGangTask("G1 Par Cleanup CT Task"), |
4420 _ct_bs(ct_bs), | 4327 _ct_bs(ct_bs), |
4421 _g1h(g1h), | 4328 _g1h(g1h), |
4422 _so_head(scan_only_list), | |
4423 _su_head(survivor_list) | 4329 _su_head(survivor_list) |
4424 { } | 4330 { } |
4425 | 4331 |
4426 void work(int i) { | 4332 void work(int i) { |
4427 HeapRegion* r; | 4333 HeapRegion* r; |
4428 while (r = _g1h->pop_dirty_cards_region()) { | 4334 while (r = _g1h->pop_dirty_cards_region()) { |
4429 clear_cards(r); | 4335 clear_cards(r); |
4430 } | 4336 } |
4431 // Redirty the cards of the scan-only and survivor regions. | 4337 // Redirty the cards of the survivor regions. |
4432 dirty_list(&this->_so_head); | |
4433 dirty_list(&this->_su_head); | 4338 dirty_list(&this->_su_head); |
4434 } | 4339 } |
4435 | 4340 |
4436 void clear_cards(HeapRegion* r) { | 4341 void clear_cards(HeapRegion* r) { |
4437 // Cards for Survivor and Scan-Only regions will be dirtied later. | 4342 // Cards for Survivor regions will be dirtied later. |
4438 if (!r->is_scan_only() && !r->is_survivor()) { | 4343 if (!r->is_survivor()) { |
4439 _ct_bs->clear(MemRegion(r->bottom(), r->end())); | 4344 _ct_bs->clear(MemRegion(r->bottom(), r->end())); |
4440 } | 4345 } |
4441 } | 4346 } |
4442 | 4347 |
4443 void dirty_list(HeapRegion* volatile * head_ptr) { | 4348 void dirty_list(HeapRegion* volatile * head_ptr) { |
4466 : _ct_bs(ct_bs) | 4371 : _ct_bs(ct_bs) |
4467 { } | 4372 { } |
4468 virtual bool doHeapRegion(HeapRegion* r) | 4373 virtual bool doHeapRegion(HeapRegion* r) |
4469 { | 4374 { |
4470 MemRegion mr(r->bottom(), r->end()); | 4375 MemRegion mr(r->bottom(), r->end()); |
4471 if (r->is_scan_only() || r->is_survivor()) { | 4376 if (r->is_survivor()) { |
4472 _ct_bs->verify_dirty_region(mr); | 4377 _ct_bs->verify_dirty_region(mr); |
4473 } else { | 4378 } else { |
4474 _ct_bs->verify_clean_region(mr); | 4379 _ct_bs->verify_clean_region(mr); |
4475 } | 4380 } |
4476 return false; | 4381 return false; |
4482 CardTableModRefBS* ct_bs = (CardTableModRefBS*) (barrier_set()); | 4387 CardTableModRefBS* ct_bs = (CardTableModRefBS*) (barrier_set()); |
4483 double start = os::elapsedTime(); | 4388 double start = os::elapsedTime(); |
4484 | 4389 |
4485 // Iterate over the dirty cards region list. | 4390 // Iterate over the dirty cards region list. |
4486 G1ParCleanupCTTask cleanup_task(ct_bs, this, | 4391 G1ParCleanupCTTask cleanup_task(ct_bs, this, |
4487 _young_list->first_scan_only_region(), | |
4488 _young_list->first_survivor_region()); | 4392 _young_list->first_survivor_region()); |
4393 | |
4489 if (ParallelGCThreads > 0) { | 4394 if (ParallelGCThreads > 0) { |
4490 set_par_threads(workers()->total_workers()); | 4395 set_par_threads(workers()->total_workers()); |
4491 workers()->run_task(&cleanup_task); | 4396 workers()->run_task(&cleanup_task); |
4492 set_par_threads(0); | 4397 set_par_threads(0); |
4493 } else { | 4398 } else { |
4499 // The last region. | 4404 // The last region. |
4500 _dirty_cards_region_list = NULL; | 4405 _dirty_cards_region_list = NULL; |
4501 } | 4406 } |
4502 r->set_next_dirty_cards_region(NULL); | 4407 r->set_next_dirty_cards_region(NULL); |
4503 } | 4408 } |
4504 // now, redirty the cards of the scan-only and survivor regions | 4409 // now, redirty the cards of the survivor regions |
4505 // (it seemed faster to do it this way, instead of iterating over | 4410 // (it seemed faster to do it this way, instead of iterating over |
4506 // all regions and then clearing / dirtying as appropriate) | 4411 // all regions and then clearing / dirtying as appropriate) |
4507 dirtyCardsForYoungRegions(ct_bs, _young_list->first_scan_only_region()); | |
4508 dirtyCardsForYoungRegions(ct_bs, _young_list->first_survivor_region()); | 4412 dirtyCardsForYoungRegions(ct_bs, _young_list->first_survivor_region()); |
4509 } | 4413 } |
4414 | |
4510 double elapsed = os::elapsedTime() - start; | 4415 double elapsed = os::elapsedTime() - start; |
4511 g1_policy()->record_clear_ct_time( elapsed * 1000.0); | 4416 g1_policy()->record_clear_ct_time( elapsed * 1000.0); |
4512 #ifndef PRODUCT | 4417 #ifndef PRODUCT |
4513 if (G1VerifyCTCleanup || VerifyAfterGC) { | 4418 if (G1VerifyCTCleanup || VerifyAfterGC) { |
4514 G1VerifyCardTableCleanup cleanup_verifier(ct_bs); | 4419 G1VerifyCardTableCleanup cleanup_verifier(ct_bs); |
4524 } | 4429 } |
4525 | 4430 |
4526 void G1CollectedHeap::free_collection_set(HeapRegion* cs_head) { | 4431 void G1CollectedHeap::free_collection_set(HeapRegion* cs_head) { |
4527 double young_time_ms = 0.0; | 4432 double young_time_ms = 0.0; |
4528 double non_young_time_ms = 0.0; | 4433 double non_young_time_ms = 0.0; |
4434 | |
4435 // Since the collection set is a superset of the the young list, | |
4436 // all we need to do to clear the young list is clear its | |
4437 // head and length, and unlink any young regions in the code below | |
4438 _young_list->clear(); | |
4529 | 4439 |
4530 G1CollectorPolicy* policy = g1_policy(); | 4440 G1CollectorPolicy* policy = g1_policy(); |
4531 | 4441 |
4532 double start_sec = os::elapsedTime(); | 4442 double start_sec = os::elapsedTime(); |
4533 bool non_young = true; | 4443 bool non_young = true; |
4568 int index = cur->young_index_in_cset(); | 4478 int index = cur->young_index_in_cset(); |
4569 guarantee( index != -1, "invariant" ); | 4479 guarantee( index != -1, "invariant" ); |
4570 guarantee( (size_t)index < policy->young_cset_length(), "invariant" ); | 4480 guarantee( (size_t)index < policy->young_cset_length(), "invariant" ); |
4571 size_t words_survived = _surviving_young_words[index]; | 4481 size_t words_survived = _surviving_young_words[index]; |
4572 cur->record_surv_words_in_group(words_survived); | 4482 cur->record_surv_words_in_group(words_survived); |
4483 | |
4484 // At this point the we have 'popped' cur from the collection set | |
4485 // (linked via next_in_collection_set()) but it is still in the | |
4486 // young list (linked via next_young_region()). Clear the | |
4487 // _next_young_region field. | |
4488 cur->set_next_young_region(NULL); | |
4573 } else { | 4489 } else { |
4574 int index = cur->young_index_in_cset(); | 4490 int index = cur->young_index_in_cset(); |
4575 guarantee( index == -1, "invariant" ); | 4491 guarantee( index == -1, "invariant" ); |
4576 } | 4492 } |
4577 | 4493 |
4583 // And the region is empty. | 4499 // And the region is empty. |
4584 assert(!cur->is_empty(), | 4500 assert(!cur->is_empty(), |
4585 "Should not have empty regions in a CS."); | 4501 "Should not have empty regions in a CS."); |
4586 free_region(cur); | 4502 free_region(cur); |
4587 } else { | 4503 } else { |
4588 guarantee( !cur->is_scan_only(), "should not be scan only" ); | |
4589 cur->uninstall_surv_rate_group(); | 4504 cur->uninstall_surv_rate_group(); |
4590 if (cur->is_young()) | 4505 if (cur->is_young()) |
4591 cur->set_young_index_in_cset(-1); | 4506 cur->set_young_index_in_cset(-1); |
4592 cur->set_not_young(); | 4507 cur->set_not_young(); |
4593 cur->set_evacuation_failed(false); | 4508 cur->set_evacuation_failed(false); |
4605 else | 4520 else |
4606 young_time_ms += elapsed_ms; | 4521 young_time_ms += elapsed_ms; |
4607 | 4522 |
4608 policy->record_young_free_cset_time_ms(young_time_ms); | 4523 policy->record_young_free_cset_time_ms(young_time_ms); |
4609 policy->record_non_young_free_cset_time_ms(non_young_time_ms); | 4524 policy->record_non_young_free_cset_time_ms(non_young_time_ms); |
4525 } | |
4526 | |
4527 // This routine is similar to the above but does not record | |
4528 // any policy statistics or update free lists; we are abandoning | |
4529 // the current incremental collection set in preparation of a | |
4530 // full collection. After the full GC we will start to build up | |
4531 // the incremental collection set again. | |
4532 // This is only called when we're doing a full collection | |
4533 // and is immediately followed by the tearing down of the young list. | |
4534 | |
4535 void G1CollectedHeap::abandon_collection_set(HeapRegion* cs_head) { | |
4536 HeapRegion* cur = cs_head; | |
4537 | |
4538 while (cur != NULL) { | |
4539 HeapRegion* next = cur->next_in_collection_set(); | |
4540 assert(cur->in_collection_set(), "bad CS"); | |
4541 cur->set_next_in_collection_set(NULL); | |
4542 cur->set_in_collection_set(false); | |
4543 cur->set_young_index_in_cset(-1); | |
4544 cur = next; | |
4545 } | |
4610 } | 4546 } |
4611 | 4547 |
4612 HeapRegion* | 4548 HeapRegion* |
4613 G1CollectedHeap::alloc_region_from_unclean_list_locked(bool zero_filled) { | 4549 G1CollectedHeap::alloc_region_from_unclean_list_locked(bool zero_filled) { |
4614 assert(ZF_mon->owned_by_self(), "Precondition"); | 4550 assert(ZF_mon->owned_by_self(), "Precondition"); |
4973 return false; | 4909 return false; |
4974 } | 4910 } |
4975 bool success() { return _success; } | 4911 bool success() { return _success; } |
4976 }; | 4912 }; |
4977 | 4913 |
4978 bool G1CollectedHeap::check_young_list_empty(bool ignore_scan_only_list, | 4914 bool G1CollectedHeap::check_young_list_empty(bool check_heap, bool check_sample) { |
4979 bool check_sample) { | 4915 bool ret = _young_list->check_list_empty(check_sample); |
4980 bool ret = true; | 4916 |
4981 | 4917 if (check_heap) { |
4982 ret = _young_list->check_list_empty(ignore_scan_only_list, check_sample); | |
4983 if (!ignore_scan_only_list) { | |
4984 NoYoungRegionsClosure closure; | 4918 NoYoungRegionsClosure closure; |
4985 heap_region_iterate(&closure); | 4919 heap_region_iterate(&closure); |
4986 ret = ret && closure.success(); | 4920 ret = ret && closure.success(); |
4987 } | 4921 } |
4988 | 4922 |