1 /*
2 * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
27 #include "gc/g1/g1CollectionSet.hpp"
28 #include "gc/g1/g1CollectorState.hpp"
29 #include "gc/g1/g1ParScanThreadState.hpp"
30 #include "gc/g1/g1Policy.hpp"
31 #include "gc/g1/heapRegion.inline.hpp"
32 #include "gc/g1/heapRegionRemSet.hpp"
33 #include "gc/g1/heapRegionSet.hpp"
34 #include "logging/logStream.hpp"
35 #include "utilities/debug.hpp"
36 #include "utilities/globalDefinitions.hpp"
37 #include "utilities/quickSort.hpp"
38
39 G1CollectorState* G1CollectionSet::collector_state() {
40 return _g1h->collector_state();
41 }
42
43 G1GCPhaseTimes* G1CollectionSet::phase_times() {
44 return _policy->phase_times();
45 }
46
47 CollectionSetChooser* G1CollectionSet::cset_chooser() {
48 return _cset_chooser;
49 }
50
51 double G1CollectionSet::predict_region_elapsed_time_ms(HeapRegion* hr) {
52 return _policy->predict_region_elapsed_time_ms(hr, collector_state()->in_young_only_phase());
53 }
54
55 G1CollectionSet::G1CollectionSet(G1CollectedHeap* g1h, G1Policy* policy) :
56 _g1h(g1h),
57 _policy(policy),
58 _cset_chooser(new CollectionSetChooser()),
59 _eden_region_length(0),
60 _survivor_region_length(0),
61 _old_region_length(0),
62 _collection_set_regions(NULL),
63 _collection_set_cur_length(0),
64 _collection_set_max_length(0),
65 _optional_regions(NULL),
66 _optional_region_length(0),
67 _optional_region_max_length(0),
68 _bytes_used_before(0),
69 _recorded_rs_lengths(0),
70 _inc_build_state(Inactive),
71 _inc_bytes_used_before(0),
72 _inc_recorded_rs_lengths(0),
73 _inc_recorded_rs_lengths_diffs(0),
74 _inc_predicted_elapsed_time_ms(0.0),
75 _inc_predicted_elapsed_time_ms_diffs(0.0) {
76 }
77
78 G1CollectionSet::~G1CollectionSet() {
79 if (_collection_set_regions != NULL) {
80 FREE_C_HEAP_ARRAY(uint, _collection_set_regions);
81 }
82 free_optional_regions();
83 delete _cset_chooser;
84 }
85
86 void G1CollectionSet::init_region_lengths(uint eden_cset_region_length,
87 uint survivor_cset_region_length) {
88 assert_at_safepoint_on_vm_thread();
89
90 _eden_region_length = eden_cset_region_length;
91 _survivor_region_length = survivor_cset_region_length;
92
93 assert((size_t) young_region_length() == _collection_set_cur_length,
94 "Young region length %u should match collection set length " SIZE_FORMAT, young_region_length(), _collection_set_cur_length);
95
96 _old_region_length = 0;
97 _optional_region_length = 0;
98 }
99
100 void G1CollectionSet::initialize(uint max_region_length) {
101 guarantee(_collection_set_regions == NULL, "Must only initialize once.");
102 _collection_set_max_length = max_region_length;
103 _collection_set_regions = NEW_C_HEAP_ARRAY(uint, max_region_length, mtGC);
422 // Clear the fields that point to the survivor list - they are all young now.
423 survivors->convert_to_eden();
424
425 _bytes_used_before = _inc_bytes_used_before;
426 time_remaining_ms = MAX2(time_remaining_ms - _inc_predicted_elapsed_time_ms, 0.0);
427
428 log_trace(gc, ergo, cset)("Add young regions to CSet. eden: %u regions, survivors: %u regions, predicted young region time: %1.2fms, target pause time: %1.2fms",
429 eden_region_length, survivor_region_length, _inc_predicted_elapsed_time_ms, target_pause_time_ms);
430
431 // The number of recorded young regions is the incremental
432 // collection set's current size
433 set_recorded_rs_lengths(_inc_recorded_rs_lengths);
434
435 double young_end_time_sec = os::elapsedTime();
436 phase_times()->record_young_cset_choice_time_ms((young_end_time_sec - young_start_time_sec) * 1000.0);
437
438 return time_remaining_ms;
439 }
440
441 void G1CollectionSet::add_as_old(HeapRegion* hr) {
442 cset_chooser()->pop(); // already have region via peek()
443 _g1h->old_set_remove(hr);
444 add_old_region(hr);
445 }
446
447 void G1CollectionSet::add_as_optional(HeapRegion* hr) {
448 assert(_optional_regions != NULL, "Must not be called before array is allocated");
449 cset_chooser()->pop(); // already have region via peek()
450 _g1h->old_set_remove(hr);
451 add_optional_region(hr);
452 }
453
454 bool G1CollectionSet::optional_is_full() {
455 assert(_optional_region_length <= _optional_region_max_length, "Invariant");
456 return _optional_region_length == _optional_region_max_length;
457 }
458
459 void G1CollectionSet::clear_optional_region(const HeapRegion* hr) {
460 assert(_optional_regions != NULL, "Must not be called before array is allocated");
461 uint index = hr->index_in_opt_cset();
462 _optional_regions[index] = NULL;
463 }
464
465 static int compare_region_idx(const uint a, const uint b) {
466 if (a > b) {
467 return 1;
468 } else if (a == b) {
469 return 0;
470 } else {
471 return -1;
472 }
473 }
474
475 void G1CollectionSet::finalize_old_part(double time_remaining_ms) {
476 double non_young_start_time_sec = os::elapsedTime();
477 double predicted_old_time_ms = 0.0;
478 double predicted_optional_time_ms = 0.0;
479 double optional_threshold_ms = time_remaining_ms * _policy->optional_prediction_fraction();
480 uint expensive_region_num = 0;
481
482 if (collector_state()->in_mixed_phase()) {
483 cset_chooser()->verify();
484 const uint min_old_cset_length = _policy->calc_min_old_cset_length();
485 const uint max_old_cset_length = MAX2(min_old_cset_length, _policy->calc_max_old_cset_length());
486 bool check_time_remaining = _policy->adaptive_young_list_length();
487
488 initialize_optional(max_old_cset_length - min_old_cset_length);
489 log_debug(gc, ergo, cset)("Start adding old regions for mixed gc. min %u regions, max %u regions, "
490 "time remaining %1.2fms, optional threshold %1.2fms",
491 min_old_cset_length, max_old_cset_length, time_remaining_ms, optional_threshold_ms);
492
493 HeapRegion* hr = cset_chooser()->peek();
494 while (hr != NULL) {
495 if (old_region_length() + optional_region_length() >= max_old_cset_length) {
496 // Added maximum number of old regions to the CSet.
497 log_debug(gc, ergo, cset)("Finish adding old regions to CSet (old CSet region num reached max). "
498 "old %u regions, optional %u regions",
499 old_region_length(), optional_region_length());
500 break;
501 }
502
503 // Stop adding regions if the remaining reclaimable space is
504 // not above G1HeapWastePercent.
505 size_t reclaimable_bytes = cset_chooser()->remaining_reclaimable_bytes();
506 double reclaimable_percent = _policy->reclaimable_bytes_percent(reclaimable_bytes);
507 double threshold = (double) G1HeapWastePercent;
508 if (reclaimable_percent <= threshold) {
509 // We've added enough old regions that the amount of uncollected
510 // reclaimable space is at or below the waste threshold. Stop
511 // adding old regions to the CSet.
512 log_debug(gc, ergo, cset)("Finish adding old regions to CSet (reclaimable percentage not over threshold). "
513 "reclaimable: " SIZE_FORMAT "%s (%1.2f%%) threshold: " UINTX_FORMAT "%%",
514 byte_size_in_proper_unit(reclaimable_bytes), proper_unit_for_byte_size(reclaimable_bytes),
515 reclaimable_percent, G1HeapWastePercent);
516 break;
517 }
518
519 double predicted_time_ms = predict_region_elapsed_time_ms(hr);
520 time_remaining_ms = MAX2(time_remaining_ms - predicted_time_ms, 0.0);
521 // Add regions to old set until we reach minimum amount
522 if (old_region_length() < min_old_cset_length) {
523 predicted_old_time_ms += predicted_time_ms;
524 add_as_old(hr);
525 // Record the number of regions added when no time remaining
534 break;
535 }
536 // Keep adding regions to old set until we reach optional threshold
537 if (time_remaining_ms > optional_threshold_ms) {
538 predicted_old_time_ms += predicted_time_ms;
539 add_as_old(hr);
540 } else if (time_remaining_ms > 0) {
541 // Keep adding optional regions until time is up
542 if (!optional_is_full()) {
543 predicted_optional_time_ms += predicted_time_ms;
544 add_as_optional(hr);
545 } else {
546 log_debug(gc, ergo, cset)("Finish adding old regions to CSet (optional set full).");
547 break;
548 }
549 } else {
550 log_debug(gc, ergo, cset)("Finish adding old regions to CSet (predicted time is too high).");
551 break;
552 }
553 }
554 hr = cset_chooser()->peek();
555 }
556 if (hr == NULL) {
557 log_debug(gc, ergo, cset)("Finish adding old regions to CSet (candidate old regions not available)");
558 }
559
560 cset_chooser()->verify();
561 }
562
563 stop_incremental_building();
564
565 log_debug(gc, ergo, cset)("Finish choosing CSet regions old: %u, optional: %u, "
566 "predicted old time: %1.2fms, predicted optional time: %1.2fms, time remaining: %1.2f",
567 old_region_length(), optional_region_length(),
568 predicted_old_time_ms, predicted_optional_time_ms, time_remaining_ms);
569 if (expensive_region_num > 0) {
570 log_debug(gc, ergo, cset)("CSet contains %u old regions that were added although the predicted time was too high.",
571 expensive_region_num);
572 }
573
574 double non_young_end_time_sec = os::elapsedTime();
575 phase_times()->record_non_young_cset_choice_time_ms((non_young_end_time_sec - non_young_start_time_sec) * 1000.0);
576
577 QuickSort::sort(_collection_set_regions, _collection_set_cur_length, compare_region_idx, true);
578 }
579
580 HeapRegion* G1OptionalCSet::region_at(uint index) {
613
614 void G1OptionalCSet::complete_evacuation() {
615 _evacuation_failed = false;
616 for (uint i = _current_index; i < _current_limit; i++) {
617 HeapRegion* hr = region_at(i);
618 _cset->clear_optional_region(hr);
619 if (hr->evacuation_failed()){
620 _evacuation_failed = true;
621 }
622 }
623 _current_index = _current_limit;
624 }
625
626 bool G1OptionalCSet::evacuation_failed() {
627 return _evacuation_failed;
628 }
629
630 G1OptionalCSet::~G1OptionalCSet() {
631 G1CollectedHeap* g1h = G1CollectedHeap::heap();
632 while (!is_empty()) {
633 // We want to return regions not evacuated to the
634 // chooser in reverse order to maintain the old order.
635 HeapRegion* hr = _cset->remove_last_optional_region();
636 assert(hr != NULL, "Should be valid region left");
637 _pset->record_unused_optional_region(hr);
638 g1h->old_set_add(hr);
639 g1h->clear_in_cset(hr);
640 hr->set_index_in_opt_cset(InvalidCSetIndex);
641 _cset->cset_chooser()->push(hr);
642 }
643 _cset->free_optional_regions();
644 }
645
646 uint G1OptionalCSet::size() {
647 return _cset->optional_region_length() - _current_index;
648 }
649
650 bool G1OptionalCSet::is_empty() {
651 return size() == 0;
652 }
653
654 void G1OptionalCSet::prepare_to_evacuate_optional_region(HeapRegion* hr) {
655 log_trace(gc, cset)("Adding region %u for optional evacuation", hr->hrm_index());
656 G1CollectedHeap::heap()->clear_in_cset(hr);
657 _cset->add_old_region(hr);
658 }
659
660 #ifdef ASSERT
661 class G1VerifyYoungCSetIndicesClosure : public HeapRegionClosure {
|
1 /*
2 * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
27 #include "gc/g1/g1CollectionSet.hpp"
28 #include "gc/g1/g1CollectorState.hpp"
29 #include "gc/g1/g1ParScanThreadState.hpp"
30 #include "gc/g1/g1Policy.hpp"
31 #include "gc/g1/heapRegion.inline.hpp"
32 #include "gc/g1/heapRegionRemSet.hpp"
33 #include "gc/g1/heapRegionSet.hpp"
34 #include "logging/logStream.hpp"
35 #include "utilities/debug.hpp"
36 #include "utilities/globalDefinitions.hpp"
37 #include "utilities/quickSort.hpp"
38
39 G1CollectorState* G1CollectionSet::collector_state() {
40 return _g1h->collector_state();
41 }
42
43 G1GCPhaseTimes* G1CollectionSet::phase_times() {
44 return _policy->phase_times();
45 }
46
47 double G1CollectionSet::predict_region_elapsed_time_ms(HeapRegion* hr) {
48 return _policy->predict_region_elapsed_time_ms(hr, collector_state()->in_young_only_phase());
49 }
50
51 G1CollectionSet::G1CollectionSet(G1CollectedHeap* g1h, G1Policy* policy) :
52 _g1h(g1h),
53 _policy(policy),
54 _candidates(NULL),
55 _eden_region_length(0),
56 _survivor_region_length(0),
57 _old_region_length(0),
58 _collection_set_regions(NULL),
59 _collection_set_cur_length(0),
60 _collection_set_max_length(0),
61 _optional_regions(NULL),
62 _optional_region_length(0),
63 _optional_region_max_length(0),
64 _bytes_used_before(0),
65 _recorded_rs_lengths(0),
66 _inc_build_state(Inactive),
67 _inc_bytes_used_before(0),
68 _inc_recorded_rs_lengths(0),
69 _inc_recorded_rs_lengths_diffs(0),
70 _inc_predicted_elapsed_time_ms(0.0),
71 _inc_predicted_elapsed_time_ms_diffs(0.0) {
72 }
73
74 G1CollectionSet::~G1CollectionSet() {
75 if (_collection_set_regions != NULL) {
76 FREE_C_HEAP_ARRAY(uint, _collection_set_regions);
77 }
78 free_optional_regions();
79 clear_candidates();
80 }
81
82 void G1CollectionSet::init_region_lengths(uint eden_cset_region_length,
83 uint survivor_cset_region_length) {
84 assert_at_safepoint_on_vm_thread();
85
86 _eden_region_length = eden_cset_region_length;
87 _survivor_region_length = survivor_cset_region_length;
88
89 assert((size_t) young_region_length() == _collection_set_cur_length,
90 "Young region length %u should match collection set length " SIZE_FORMAT, young_region_length(), _collection_set_cur_length);
91
92 _old_region_length = 0;
93 _optional_region_length = 0;
94 }
95
96 void G1CollectionSet::initialize(uint max_region_length) {
97 guarantee(_collection_set_regions == NULL, "Must only initialize once.");
98 _collection_set_max_length = max_region_length;
99 _collection_set_regions = NEW_C_HEAP_ARRAY(uint, max_region_length, mtGC);
418 // Clear the fields that point to the survivor list - they are all young now.
419 survivors->convert_to_eden();
420
421 _bytes_used_before = _inc_bytes_used_before;
422 time_remaining_ms = MAX2(time_remaining_ms - _inc_predicted_elapsed_time_ms, 0.0);
423
424 log_trace(gc, ergo, cset)("Add young regions to CSet. eden: %u regions, survivors: %u regions, predicted young region time: %1.2fms, target pause time: %1.2fms",
425 eden_region_length, survivor_region_length, _inc_predicted_elapsed_time_ms, target_pause_time_ms);
426
427 // The number of recorded young regions is the incremental
428 // collection set's current size
429 set_recorded_rs_lengths(_inc_recorded_rs_lengths);
430
431 double young_end_time_sec = os::elapsedTime();
432 phase_times()->record_young_cset_choice_time_ms((young_end_time_sec - young_start_time_sec) * 1000.0);
433
434 return time_remaining_ms;
435 }
436
437 void G1CollectionSet::add_as_old(HeapRegion* hr) {
438 candidates()->pop_front(); // already have region via peek()
439 _g1h->old_set_remove(hr);
440 add_old_region(hr);
441 }
442
443 void G1CollectionSet::add_as_optional(HeapRegion* hr) {
444 assert(_optional_regions != NULL, "Must not be called before array is allocated");
445 candidates()->pop_front(); // already have region via peek()
446 _g1h->old_set_remove(hr);
447 add_optional_region(hr);
448 }
449
450 bool G1CollectionSet::optional_is_full() {
451 assert(_optional_region_length <= _optional_region_max_length, "Invariant");
452 return _optional_region_length == _optional_region_max_length;
453 }
454
455 void G1CollectionSet::clear_optional_region(const HeapRegion* hr) {
456 assert(_optional_regions != NULL, "Must not be called before array is allocated");
457 uint index = hr->index_in_opt_cset();
458 _optional_regions[index] = NULL;
459 }
460
461 static int compare_region_idx(const uint a, const uint b) {
462 if (a > b) {
463 return 1;
464 } else if (a == b) {
465 return 0;
466 } else {
467 return -1;
468 }
469 }
470
471 void G1CollectionSet::finalize_old_part(double time_remaining_ms) {
472 double non_young_start_time_sec = os::elapsedTime();
473 double predicted_old_time_ms = 0.0;
474 double predicted_optional_time_ms = 0.0;
475 double optional_threshold_ms = time_remaining_ms * _policy->optional_prediction_fraction();
476 uint expensive_region_num = 0;
477
478 if (collector_state()->in_mixed_phase()) {
479 candidates()->verify();
480 const uint min_old_cset_length = _policy->calc_min_old_cset_length();
481 const uint max_old_cset_length = MAX2(min_old_cset_length, _policy->calc_max_old_cset_length());
482 bool check_time_remaining = _policy->adaptive_young_list_length();
483
484 initialize_optional(max_old_cset_length - min_old_cset_length);
485 log_debug(gc, ergo, cset)("Start adding old regions for mixed gc. min %u regions, max %u regions, "
486 "time remaining %1.2fms, optional threshold %1.2fms",
487 min_old_cset_length, max_old_cset_length, time_remaining_ms, optional_threshold_ms);
488
489 HeapRegion* hr = candidates()->peek_front();
490 while (hr != NULL) {
491 if (old_region_length() + optional_region_length() >= max_old_cset_length) {
492 // Added maximum number of old regions to the CSet.
493 log_debug(gc, ergo, cset)("Finish adding old regions to CSet (old CSet region num reached max). "
494 "old %u regions, optional %u regions",
495 old_region_length(), optional_region_length());
496 break;
497 }
498
499 // Stop adding regions if the remaining reclaimable space is
500 // not above G1HeapWastePercent.
501 size_t reclaimable_bytes = candidates()->remaining_reclaimable_bytes();
502 double reclaimable_percent = _policy->reclaimable_bytes_percent(reclaimable_bytes);
503 double threshold = (double) G1HeapWastePercent;
504 if (reclaimable_percent <= threshold) {
505 // We've added enough old regions that the amount of uncollected
506 // reclaimable space is at or below the waste threshold. Stop
507 // adding old regions to the CSet.
508 log_debug(gc, ergo, cset)("Finish adding old regions to CSet (reclaimable percentage not over threshold). "
509 "reclaimable: " SIZE_FORMAT "%s (%1.2f%%) threshold: " UINTX_FORMAT "%%",
510 byte_size_in_proper_unit(reclaimable_bytes), proper_unit_for_byte_size(reclaimable_bytes),
511 reclaimable_percent, G1HeapWastePercent);
512 break;
513 }
514
515 double predicted_time_ms = predict_region_elapsed_time_ms(hr);
516 time_remaining_ms = MAX2(time_remaining_ms - predicted_time_ms, 0.0);
517 // Add regions to old set until we reach minimum amount
518 if (old_region_length() < min_old_cset_length) {
519 predicted_old_time_ms += predicted_time_ms;
520 add_as_old(hr);
521 // Record the number of regions added when no time remaining
530 break;
531 }
532 // Keep adding regions to old set until we reach optional threshold
533 if (time_remaining_ms > optional_threshold_ms) {
534 predicted_old_time_ms += predicted_time_ms;
535 add_as_old(hr);
536 } else if (time_remaining_ms > 0) {
537 // Keep adding optional regions until time is up
538 if (!optional_is_full()) {
539 predicted_optional_time_ms += predicted_time_ms;
540 add_as_optional(hr);
541 } else {
542 log_debug(gc, ergo, cset)("Finish adding old regions to CSet (optional set full).");
543 break;
544 }
545 } else {
546 log_debug(gc, ergo, cset)("Finish adding old regions to CSet (predicted time is too high).");
547 break;
548 }
549 }
550 hr = candidates()->peek_front();
551 }
552 if (hr == NULL) {
553 log_debug(gc, ergo, cset)("Finish adding old regions to CSet (candidate old regions not available)");
554 }
555
556 candidates()->verify();
557 }
558
559 stop_incremental_building();
560
561 log_debug(gc, ergo, cset)("Finish choosing CSet regions old: %u, optional: %u, "
562 "predicted old time: %1.2fms, predicted optional time: %1.2fms, time remaining: %1.2f",
563 old_region_length(), optional_region_length(),
564 predicted_old_time_ms, predicted_optional_time_ms, time_remaining_ms);
565 if (expensive_region_num > 0) {
566 log_debug(gc, ergo, cset)("CSet contains %u old regions that were added although the predicted time was too high.",
567 expensive_region_num);
568 }
569
570 double non_young_end_time_sec = os::elapsedTime();
571 phase_times()->record_non_young_cset_choice_time_ms((non_young_end_time_sec - non_young_start_time_sec) * 1000.0);
572
573 QuickSort::sort(_collection_set_regions, _collection_set_cur_length, compare_region_idx, true);
574 }
575
576 HeapRegion* G1OptionalCSet::region_at(uint index) {
609
610 void G1OptionalCSet::complete_evacuation() {
611 _evacuation_failed = false;
612 for (uint i = _current_index; i < _current_limit; i++) {
613 HeapRegion* hr = region_at(i);
614 _cset->clear_optional_region(hr);
615 if (hr->evacuation_failed()){
616 _evacuation_failed = true;
617 }
618 }
619 _current_index = _current_limit;
620 }
621
622 bool G1OptionalCSet::evacuation_failed() {
623 return _evacuation_failed;
624 }
625
626 G1OptionalCSet::~G1OptionalCSet() {
627 G1CollectedHeap* g1h = G1CollectedHeap::heap();
628 while (!is_empty()) {
629 // We want to return regions not evacuated to the collection set candidates
630 // in reverse order to maintain the old order.
631 HeapRegion* hr = _cset->remove_last_optional_region();
632 assert(hr != NULL, "Should be valid region left");
633 _pset->record_unused_optional_region(hr);
634 g1h->old_set_add(hr);
635 g1h->clear_in_cset(hr);
636 hr->set_index_in_opt_cset(InvalidCSetIndex);
637 _cset->candidates()->push_front(hr);
638 }
639 _cset->free_optional_regions();
640 }
641
642 uint G1OptionalCSet::size() {
643 return _cset->optional_region_length() - _current_index;
644 }
645
646 bool G1OptionalCSet::is_empty() {
647 return size() == 0;
648 }
649
650 void G1OptionalCSet::prepare_to_evacuate_optional_region(HeapRegion* hr) {
651 log_trace(gc, cset)("Adding region %u for optional evacuation", hr->hrm_index());
652 G1CollectedHeap::heap()->clear_in_cset(hr);
653 _cset->add_old_region(hr);
654 }
655
656 #ifdef ASSERT
657 class G1VerifyYoungCSetIndicesClosure : public HeapRegionClosure {
|