3131#include " utilities/quickSort.hpp"
3232
3333// Determine collection set candidates (from marking): For all regions determine
34- // whether they should be a collection set candidate, calculate their efficiency,
35- // sort and put them into the candidates.
34+ // whether they should be a collection set candidate. Calculate their efficiency,
35+ // sort, and put them into the collection set candidates.
36+ //
3637// Threads calculate the GC efficiency of the regions they get to process, and
3738// put them into some work area without sorting. At the end that array is sorted and
3839// moved to the destination.
3940class G1BuildCandidateRegionsTask : public WorkerTask {
40-
41- using CandidateInfo = G1CollectionSetCandidateInfo;
42-
4341 // Work area for building the set of collection set candidates. Contains references
4442 // to heap regions with their GC efficiencies calculated. To reduce contention
4543 // on claiming array elements, worker threads claim parts of this array in chunks;
4644 // Array elements may be null as threads might not get enough regions to fill
4745 // up their chunks completely.
4846 // Final sorting will remove them.
4947 class G1BuildCandidateArray : public StackObj {
50-
5148 uint const _max_size;
5249 uint const _chunk_size;
5350
54- CandidateInfo * _data;
51+ G1HeapRegion* * _data;
5552
5653 uint volatile _cur_claim_idx;
5754
55+ static int compare_region_gc_efficiency (G1HeapRegion** rr1, G1HeapRegion** rr2) {
56+ G1HeapRegion* r1 = *rr1;
57+ G1HeapRegion* r2 = *rr2;
58+ // Make sure that null entries are moved to the end.
59+ if (r1 == nullptr ) {
60+ if (r2 == nullptr ) {
61+ return 0 ;
62+ } else {
63+ return 1 ;
64+ }
65+ } else if (r2 == nullptr ) {
66+ return -1 ;
67+ }
68+
69+ G1Policy* p = G1CollectedHeap::heap ()->policy ();
70+ double gc_efficiency1 = p->predict_gc_efficiency (r1);
71+ double gc_efficiency2 = p->predict_gc_efficiency (r2);
72+
73+ if (gc_efficiency1 > gc_efficiency2) {
74+ return -1 ;
75+ } else if (gc_efficiency1 < gc_efficiency2) {
76+ return 1 ;
77+ } else {
78+ return 0 ;
79+ }
80+ }
81+
5882 // Calculates the maximum array size that will be used.
5983 static uint required_array_size (uint num_regions, uint chunk_size, uint num_workers) {
6084 uint const max_waste = num_workers * chunk_size;
@@ -68,15 +92,15 @@ class G1BuildCandidateRegionsTask : public WorkerTask {
6892 G1BuildCandidateArray (uint max_num_regions, uint chunk_size, uint num_workers) :
6993 _max_size (required_array_size(max_num_regions, chunk_size, num_workers)),
7094 _chunk_size (chunk_size),
71- _data (NEW_C_HEAP_ARRAY(CandidateInfo , _max_size, mtGC)),
95+ _data (NEW_C_HEAP_ARRAY(G1HeapRegion* , _max_size, mtGC)),
7296 _cur_claim_idx (0 ) {
7397 for (uint i = 0 ; i < _max_size; i++) {
74- _data[i] = CandidateInfo () ;
98+ _data[i] = nullptr ;
7599 }
76100 }
77101
78102 ~G1BuildCandidateArray () {
79- FREE_C_HEAP_ARRAY (CandidateInfo , _data);
103+ FREE_C_HEAP_ARRAY (G1HeapRegion* , _data);
80104 }
81105
82106 // Claim a new chunk, returning its bounds [from, to[.
@@ -92,24 +116,24 @@ class G1BuildCandidateRegionsTask : public WorkerTask {
92116 // Set element in array.
93117 void set (uint idx, G1HeapRegion* hr) {
94118 assert (idx < _max_size, " Index %u out of bounds %u" , idx, _max_size);
95- assert (_data[idx]. _r == nullptr , " Value must not have been set." );
96- _data[idx] = CandidateInfo (hr) ;
119+ assert (_data[idx] == nullptr , " Value must not have been set." );
120+ _data[idx] = hr ;
97121 }
98122
99123 void sort_by_gc_efficiency () {
100124 if (_cur_claim_idx == 0 ) {
101125 return ;
102126 }
103127 for (uint i = _cur_claim_idx; i < _max_size; i++) {
104- assert (_data[i]. _r == nullptr , " must be" );
128+ assert (_data[i] == nullptr , " must be" );
105129 }
106- qsort (_data, _cur_claim_idx, sizeof (_data[0 ]), (_sort_Fn)G1CollectionSetCandidateInfo:: compare_region_gc_efficiency);
130+ qsort (_data, _cur_claim_idx, sizeof (_data[0 ]), (_sort_Fn)compare_region_gc_efficiency);
107131 for (uint i = _cur_claim_idx; i < _max_size; i++) {
108- assert (_data[i]. _r == nullptr , " must be" );
132+ assert (_data[i] == nullptr , " must be" );
109133 }
110134 }
111135
112- CandidateInfo * array () const { return _data; }
136+ G1HeapRegion* * array () const { return _data; }
113137 };
114138
115139 // Per-region closure. In addition to determining whether a region should be
@@ -193,7 +217,7 @@ class G1BuildCandidateRegionsTask : public WorkerTask {
193217 // available (for forward progress in evacuation) or the waste accumulated by the
194218 // removed regions is above the maximum allowed waste.
195219 // Updates number of candidates and reclaimable bytes given.
196- void prune (CandidateInfo * data) {
220+ void prune (G1HeapRegion* * data) {
197221 G1Policy* p = G1CollectedHeap::heap ()->policy ();
198222
199223 uint num_candidates = Atomic::load (&_num_regions_added);
@@ -211,7 +235,7 @@ class G1BuildCandidateRegionsTask : public WorkerTask {
211235 uint max_to_prune = num_candidates - min_old_cset_length;
212236
213237 while (true ) {
214- G1HeapRegion* r = data[num_candidates - num_pruned - 1 ]. _r ;
238+ G1HeapRegion* r = data[num_candidates - num_pruned - 1 ];
215239 size_t const reclaimable = r->reclaimable_bytes ();
216240 if (num_pruned >= max_to_prune ||
217241 wasted_bytes + reclaimable > allowed_waste) {
0 commit comments