123 } |
123 } |
124 |
124 |
125 size_t num_processed() const { return _num_processed; } |
125 size_t num_processed() const { return _num_processed; } |
126 }; |
126 }; |
127 |
127 |
128 YoungList::YoungList(G1CollectedHeap* g1h) : |
|
129 _g1h(g1h), _head(NULL), _length(0), _last_sampled_rs_lengths(0), |
|
130 _survivor_head(NULL), _survivor_tail(NULL), _survivor_length(0) { |
|
131 guarantee(check_list_empty(false), "just making sure..."); |
|
132 } |
|
133 |
|
134 void YoungList::push_region(HeapRegion *hr) { |
|
135 assert(!hr->is_young(), "should not already be young"); |
|
136 assert(hr->get_next_young_region() == NULL, "cause it should!"); |
|
137 |
|
138 hr->set_next_young_region(_head); |
|
139 _head = hr; |
|
140 |
|
141 _g1h->g1_policy()->set_region_eden(hr, (int) _length); |
|
142 ++_length; |
|
143 } |
|
144 |
|
145 void YoungList::add_survivor_region(HeapRegion* hr) { |
|
146 assert(hr->is_survivor(), "should be flagged as survivor region"); |
|
147 assert(hr->get_next_young_region() == NULL, "cause it should!"); |
|
148 |
|
149 hr->set_next_young_region(_survivor_head); |
|
150 if (_survivor_head == NULL) { |
|
151 _survivor_tail = hr; |
|
152 } |
|
153 _survivor_head = hr; |
|
154 ++_survivor_length; |
|
155 } |
|
156 |
|
157 void YoungList::empty_list(HeapRegion* list) { |
|
158 while (list != NULL) { |
|
159 HeapRegion* next = list->get_next_young_region(); |
|
160 list->set_next_young_region(NULL); |
|
161 list->uninstall_surv_rate_group(); |
|
162 // This is called before a Full GC and all the non-empty / |
|
163 // non-humongous regions at the end of the Full GC will end up as |
|
164 // old anyway. |
|
165 list->set_old(); |
|
166 list = next; |
|
167 } |
|
168 } |
|
169 |
|
170 void YoungList::empty_list() { |
|
171 assert(check_list_well_formed(), "young list should be well formed"); |
|
172 |
|
173 empty_list(_head); |
|
174 _head = NULL; |
|
175 _length = 0; |
|
176 |
|
177 empty_list(_survivor_head); |
|
178 _survivor_head = NULL; |
|
179 _survivor_tail = NULL; |
|
180 _survivor_length = 0; |
|
181 |
|
182 _last_sampled_rs_lengths = 0; |
|
183 |
|
184 assert(check_list_empty(false), "just making sure..."); |
|
185 } |
|
186 |
|
187 bool YoungList::check_list_well_formed() { |
|
188 bool ret = true; |
|
189 |
|
190 uint length = 0; |
|
191 HeapRegion* curr = _head; |
|
192 HeapRegion* last = NULL; |
|
193 while (curr != NULL) { |
|
194 if (!curr->is_young()) { |
|
195 gclog_or_tty->print_cr("### YOUNG REGION " PTR_FORMAT "-" PTR_FORMAT " " |
|
196 "incorrectly tagged (y: %d, surv: %d)", |
|
197 p2i(curr->bottom()), p2i(curr->end()), |
|
198 curr->is_young(), curr->is_survivor()); |
|
199 ret = false; |
|
200 } |
|
201 ++length; |
|
202 last = curr; |
|
203 curr = curr->get_next_young_region(); |
|
204 } |
|
205 ret = ret && (length == _length); |
|
206 |
|
207 if (!ret) { |
|
208 gclog_or_tty->print_cr("### YOUNG LIST seems not well formed!"); |
|
209 gclog_or_tty->print_cr("### list has %u entries, _length is %u", |
|
210 length, _length); |
|
211 } |
|
212 |
|
213 return ret; |
|
214 } |
|
215 |
|
216 bool YoungList::check_list_empty(bool check_sample) { |
|
217 bool ret = true; |
|
218 |
|
219 if (_length != 0) { |
|
220 gclog_or_tty->print_cr("### YOUNG LIST should have 0 length, not %u", |
|
221 _length); |
|
222 ret = false; |
|
223 } |
|
224 if (check_sample && _last_sampled_rs_lengths != 0) { |
|
225 gclog_or_tty->print_cr("### YOUNG LIST has non-zero last sampled RS lengths"); |
|
226 ret = false; |
|
227 } |
|
228 if (_head != NULL) { |
|
229 gclog_or_tty->print_cr("### YOUNG LIST does not have a NULL head"); |
|
230 ret = false; |
|
231 } |
|
232 if (!ret) { |
|
233 gclog_or_tty->print_cr("### YOUNG LIST does not seem empty"); |
|
234 } |
|
235 |
|
236 return ret; |
|
237 } |
|
238 |
|
239 void |
|
240 YoungList::rs_length_sampling_init() { |
|
241 _sampled_rs_lengths = 0; |
|
242 _curr = _head; |
|
243 } |
|
244 |
|
245 bool |
|
246 YoungList::rs_length_sampling_more() { |
|
247 return _curr != NULL; |
|
248 } |
|
249 |
|
250 void |
|
251 YoungList::rs_length_sampling_next() { |
|
252 assert( _curr != NULL, "invariant" ); |
|
253 size_t rs_length = _curr->rem_set()->occupied(); |
|
254 |
|
255 _sampled_rs_lengths += rs_length; |
|
256 |
|
257 // The current region may not yet have been added to the |
|
258 // incremental collection set (it gets added when it is |
|
259 // retired as the current allocation region). |
|
260 if (_curr->in_collection_set()) { |
|
261 // Update the collection set policy information for this region |
|
262 _g1h->g1_policy()->update_incremental_cset_info(_curr, rs_length); |
|
263 } |
|
264 |
|
265 _curr = _curr->get_next_young_region(); |
|
266 if (_curr == NULL) { |
|
267 _last_sampled_rs_lengths = _sampled_rs_lengths; |
|
268 // gclog_or_tty->print_cr("last sampled RS lengths = %d", _last_sampled_rs_lengths); |
|
269 } |
|
270 } |
|
271 |
|
272 void |
|
273 YoungList::reset_auxilary_lists() { |
|
274 guarantee( is_empty(), "young list should be empty" ); |
|
275 assert(check_list_well_formed(), "young list should be well formed"); |
|
276 |
|
277 // Add survivor regions to SurvRateGroup. |
|
278 _g1h->g1_policy()->note_start_adding_survivor_regions(); |
|
279 _g1h->g1_policy()->finished_recalculating_age_indexes(true /* is_survivors */); |
|
280 |
|
281 int young_index_in_cset = 0; |
|
282 for (HeapRegion* curr = _survivor_head; |
|
283 curr != NULL; |
|
284 curr = curr->get_next_young_region()) { |
|
285 _g1h->g1_policy()->set_region_survivor(curr, young_index_in_cset); |
|
286 |
|
287 // The region is a non-empty survivor so let's add it to |
|
288 // the incremental collection set for the next evacuation |
|
289 // pause. |
|
290 _g1h->g1_policy()->add_region_to_incremental_cset_rhs(curr); |
|
291 young_index_in_cset += 1; |
|
292 } |
|
293 assert((uint) young_index_in_cset == _survivor_length, "post-condition"); |
|
294 _g1h->g1_policy()->note_stop_adding_survivor_regions(); |
|
295 |
|
296 _head = _survivor_head; |
|
297 _length = _survivor_length; |
|
298 if (_survivor_head != NULL) { |
|
299 assert(_survivor_tail != NULL, "cause it shouldn't be"); |
|
300 assert(_survivor_length > 0, "invariant"); |
|
301 _survivor_tail->set_next_young_region(NULL); |
|
302 } |
|
303 |
|
304 // Don't clear the survivor list handles until the start of |
|
305 // the next evacuation pause - we need it in order to re-tag |
|
306 // the survivor regions from this evacuation pause as 'young' |
|
307 // at the start of the next. |
|
308 |
|
309 _g1h->g1_policy()->finished_recalculating_age_indexes(false /* is_survivors */); |
|
310 |
|
311 assert(check_list_well_formed(), "young list should be well formed"); |
|
312 } |
|
313 |
|
314 void YoungList::print() { |
|
315 HeapRegion* lists[] = {_head, _survivor_head}; |
|
316 const char* names[] = {"YOUNG", "SURVIVOR"}; |
|
317 |
|
318 for (uint list = 0; list < ARRAY_SIZE(lists); ++list) { |
|
319 gclog_or_tty->print_cr("%s LIST CONTENTS", names[list]); |
|
320 HeapRegion *curr = lists[list]; |
|
321 if (curr == NULL) |
|
322 gclog_or_tty->print_cr(" empty"); |
|
323 while (curr != NULL) { |
|
324 gclog_or_tty->print_cr(" " HR_FORMAT ", P: " PTR_FORMAT ", N: " PTR_FORMAT ", age: %4d", |
|
325 HR_FORMAT_PARAMS(curr), |
|
326 p2i(curr->prev_top_at_mark_start()), |
|
327 p2i(curr->next_top_at_mark_start()), |
|
328 curr->age_in_surv_rate_group_cond()); |
|
329 curr = curr->get_next_young_region(); |
|
330 } |
|
331 } |
|
332 |
|
333 gclog_or_tty->cr(); |
|
334 } |
|
335 |
128 |
336 void G1RegionMappingChangedListener::reset_from_card_cache(uint start_idx, size_t num_regions) { |
129 void G1RegionMappingChangedListener::reset_from_card_cache(uint start_idx, size_t num_regions) { |
337 HeapRegionRemSet::invalidate_from_card_cache(start_idx, num_regions); |
130 HeapRegionRemSet::invalidate_from_card_cache(start_idx, num_regions); |
338 } |
131 } |
339 |
132 |