Mercurial > hg > graal-compiler
annotate src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @ 1145:e018e6884bd8
6631166: CMS: better heuristics when combatting fragmentation
Summary: Autonomic per-worker free block cache sizing, tunable coalition policies, fixes to per-size block statistics, retuned gain and bandwidth of some feedback loop filters to allow quicker reactivity to abrupt changes in ambient demand, and other heuristics to reduce fragmentation of the CMS old gen. Also tightened some assertions, including those related to locking.
Reviewed-by: jmasa
author | ysr |
---|---|
date | Wed, 23 Dec 2009 09:23:54 -0800 |
parents | 44f61c24ddab |
children | 7b0e9cba0307 |
rev | line source |
---|---|
342 | 1 /* |
579 | 2 * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. |
342 | 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 #include "incls/_precompiled.incl" | |
26 #include "incls/_g1CollectedHeap.cpp.incl" | |
27 | |
942
2c79770d1f6e
6819085: G1: use larger and/or user settable region size
tonyp
parents:
941
diff
changeset
|
28 size_t G1CollectedHeap::_humongous_object_threshold_in_words = 0; |
2c79770d1f6e
6819085: G1: use larger and/or user settable region size
tonyp
parents:
941
diff
changeset
|
29 |
342 | 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 | |
32 // / after the collection --- this is useful for debugging | |
33 #define SCAN_ONLY_VERBOSE 0 | |
34 // CURRENT STATUS | |
35 // This file is under construction. Search for "FIXME". | |
36 | |
37 // INVARIANTS/NOTES | |
38 // | |
39 // All allocation activity covered by the G1CollectedHeap interface is | |
40 // serialized by acquiring the HeapLock. This happens in | |
41 // mem_allocate_work, which all such allocation functions call. | |
42 // (Note that this does not apply to TLAB allocation, which is not part | |
43 // of this interface: it is done by clients of this interface.) | |
44 | |
45 // Local to this file. | |
46 | |
47 class RefineCardTableEntryClosure: public CardTableEntryClosure { | |
48 SuspendibleThreadSet* _sts; | |
49 G1RemSet* _g1rs; | |
50 ConcurrentG1Refine* _cg1r; | |
51 bool _concurrent; | |
52 public: | |
53 RefineCardTableEntryClosure(SuspendibleThreadSet* sts, | |
54 G1RemSet* g1rs, | |
55 ConcurrentG1Refine* cg1r) : | |
56 _sts(sts), _g1rs(g1rs), _cg1r(cg1r), _concurrent(true) | |
57 {} | |
58 bool do_card_ptr(jbyte* card_ptr, int worker_i) { | |
59 _g1rs->concurrentRefineOneCard(card_ptr, worker_i); | |
60 if (_concurrent && _sts->should_yield()) { | |
61 // Caller will actually yield. | |
62 return false; | |
63 } | |
64 // Otherwise, we finished successfully; return true. | |
65 return true; | |
66 } | |
67 void set_concurrent(bool b) { _concurrent = b; } | |
68 }; | |
69 | |
70 | |
71 class ClearLoggedCardTableEntryClosure: public CardTableEntryClosure { | |
72 int _calls; | |
73 G1CollectedHeap* _g1h; | |
74 CardTableModRefBS* _ctbs; | |
75 int _histo[256]; | |
76 public: | |
77 ClearLoggedCardTableEntryClosure() : | |
78 _calls(0) | |
79 { | |
80 _g1h = G1CollectedHeap::heap(); | |
81 _ctbs = (CardTableModRefBS*)_g1h->barrier_set(); | |
82 for (int i = 0; i < 256; i++) _histo[i] = 0; | |
83 } | |
84 bool do_card_ptr(jbyte* card_ptr, int worker_i) { | |
85 if (_g1h->is_in_reserved(_ctbs->addr_for(card_ptr))) { | |
86 _calls++; | |
87 unsigned char* ujb = (unsigned char*)card_ptr; | |
88 int ind = (int)(*ujb); | |
89 _histo[ind]++; | |
90 *card_ptr = -1; | |
91 } | |
92 return true; | |
93 } | |
94 int calls() { return _calls; } | |
95 void print_histo() { | |
96 gclog_or_tty->print_cr("Card table value histogram:"); | |
97 for (int i = 0; i < 256; i++) { | |
98 if (_histo[i] != 0) { | |
99 gclog_or_tty->print_cr(" %d: %d", i, _histo[i]); | |
100 } | |
101 } | |
102 } | |
103 }; | |
104 | |
105 class RedirtyLoggedCardTableEntryClosure: public CardTableEntryClosure { | |
106 int _calls; | |
107 G1CollectedHeap* _g1h; | |
108 CardTableModRefBS* _ctbs; | |
109 public: | |
110 RedirtyLoggedCardTableEntryClosure() : | |
111 _calls(0) | |
112 { | |
113 _g1h = G1CollectedHeap::heap(); | |
114 _ctbs = (CardTableModRefBS*)_g1h->barrier_set(); | |
115 } | |
116 bool do_card_ptr(jbyte* card_ptr, int worker_i) { | |
117 if (_g1h->is_in_reserved(_ctbs->addr_for(card_ptr))) { | |
118 _calls++; | |
119 *card_ptr = 0; | |
120 } | |
121 return true; | |
122 } | |
123 int calls() { return _calls; } | |
124 }; | |
125 | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
126 class RedirtyLoggedCardTableEntryFastClosure : public CardTableEntryClosure { |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
127 public: |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
128 bool do_card_ptr(jbyte* card_ptr, int worker_i) { |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
129 *card_ptr = CardTableModRefBS::dirty_card_val(); |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
130 return true; |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
131 } |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
132 }; |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
133 |
342 | 134 YoungList::YoungList(G1CollectedHeap* g1h) |
135 : _g1h(g1h), _head(NULL), | |
136 _scan_only_head(NULL), _scan_only_tail(NULL), _curr_scan_only(NULL), | |
137 _length(0), _scan_only_length(0), | |
138 _last_sampled_rs_lengths(0), | |
545 | 139 _survivor_head(NULL), _survivor_tail(NULL), _survivor_length(0) |
342 | 140 { |
141 guarantee( check_list_empty(false), "just making sure..." ); | |
142 } | |
143 | |
144 void YoungList::push_region(HeapRegion *hr) { | |
145 assert(!hr->is_young(), "should not already be young"); | |
146 assert(hr->get_next_young_region() == NULL, "cause it should!"); | |
147 | |
148 hr->set_next_young_region(_head); | |
149 _head = hr; | |
150 | |
151 hr->set_young(); | |
152 double yg_surv_rate = _g1h->g1_policy()->predict_yg_surv_rate((int)_length); | |
153 ++_length; | |
154 } | |
155 | |
156 void YoungList::add_survivor_region(HeapRegion* hr) { | |
545 | 157 assert(hr->is_survivor(), "should be flagged as survivor region"); |
342 | 158 assert(hr->get_next_young_region() == NULL, "cause it should!"); |
159 | |
160 hr->set_next_young_region(_survivor_head); | |
161 if (_survivor_head == NULL) { | |
545 | 162 _survivor_tail = hr; |
342 | 163 } |
164 _survivor_head = hr; | |
165 | |
166 ++_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 } | |
210 | |
211 void YoungList::empty_list(HeapRegion* list) { | |
212 while (list != NULL) { | |
213 HeapRegion* next = list->get_next_young_region(); | |
214 list->set_next_young_region(NULL); | |
215 list->uninstall_surv_rate_group(); | |
216 list->set_not_young(); | |
217 list = next; | |
218 } | |
219 } | |
220 | |
221 void YoungList::empty_list() { | |
222 assert(check_list_well_formed(), "young list should be well formed"); | |
223 | |
224 empty_list(_head); | |
225 _head = NULL; | |
226 _length = 0; | |
227 | |
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); | |
235 _survivor_head = NULL; | |
545 | 236 _survivor_tail = NULL; |
342 | 237 _survivor_length = 0; |
238 | |
239 _last_sampled_rs_lengths = 0; | |
240 | |
241 assert(check_list_empty(false), "just making sure..."); | |
242 } | |
243 | |
244 bool YoungList::check_list_well_formed() { | |
245 bool ret = true; | |
246 | |
247 size_t length = 0; | |
248 HeapRegion* curr = _head; | |
249 HeapRegion* last = NULL; | |
250 while (curr != NULL) { | |
251 if (!curr->is_young() || curr->is_scan_only()) { | |
252 gclog_or_tty->print_cr("### YOUNG REGION "PTR_FORMAT"-"PTR_FORMAT" " | |
253 "incorrectly tagged (%d, %d)", | |
254 curr->bottom(), curr->end(), | |
255 curr->is_young(), curr->is_scan_only()); | |
256 ret = false; | |
257 } | |
258 ++length; | |
259 last = curr; | |
260 curr = curr->get_next_young_region(); | |
261 } | |
262 ret = ret && (length == _length); | |
263 | |
264 if (!ret) { | |
265 gclog_or_tty->print_cr("### YOUNG LIST seems not well formed!"); | |
266 gclog_or_tty->print_cr("### list has %d entries, _length is %d", | |
267 length, _length); | |
268 } | |
269 | |
270 bool scan_only_ret = true; | |
271 length = 0; | |
272 curr = _scan_only_head; | |
273 last = NULL; | |
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; | |
312 | |
313 if (_length != 0) { | |
314 gclog_or_tty->print_cr("### YOUNG LIST should have 0 length, not %d", | |
315 _length); | |
316 ret = false; | |
317 } | |
318 if (check_sample && _last_sampled_rs_lengths != 0) { | |
319 gclog_or_tty->print_cr("### YOUNG LIST has non-zero last sampled RS lengths"); | |
320 ret = false; | |
321 } | |
322 if (_head != NULL) { | |
323 gclog_or_tty->print_cr("### YOUNG LIST does not have a NULL head"); | |
324 ret = false; | |
325 } | |
326 if (!ret) { | |
327 gclog_or_tty->print_cr("### YOUNG LIST does not seem empty"); | |
328 } | |
329 | |
330 if (ignore_scan_only_list) | |
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 } | |
353 | |
354 void | |
355 YoungList::rs_length_sampling_init() { | |
356 _sampled_rs_lengths = 0; | |
357 _curr = _head; | |
358 } | |
359 | |
360 bool | |
361 YoungList::rs_length_sampling_more() { | |
362 return _curr != NULL; | |
363 } | |
364 | |
365 void | |
366 YoungList::rs_length_sampling_next() { | |
367 assert( _curr != NULL, "invariant" ); | |
368 _sampled_rs_lengths += _curr->rem_set()->occupied(); | |
369 _curr = _curr->get_next_young_region(); | |
370 if (_curr == NULL) { | |
371 _last_sampled_rs_lengths = _sampled_rs_lengths; | |
372 // gclog_or_tty->print_cr("last sampled RS lengths = %d", _last_sampled_rs_lengths); | |
373 } | |
374 } | |
375 | |
376 void | |
377 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" ); | |
384 assert(check_list_well_formed(), "young list should be well formed"); | |
385 | |
386 // Add survivor regions to SurvRateGroup. | |
387 _g1h->g1_policy()->note_start_adding_survivor_regions(); | |
545 | 388 _g1h->g1_policy()->finished_recalculating_age_indexes(true /* is_survivors */); |
342 | 389 for (HeapRegion* curr = _survivor_head; |
390 curr != NULL; | |
391 curr = curr->get_next_young_region()) { | |
392 _g1h->g1_policy()->set_region_survivors(curr); | |
393 } | |
394 _g1h->g1_policy()->note_stop_adding_survivor_regions(); | |
395 | |
396 if (_survivor_head != NULL) { | |
397 _head = _survivor_head; | |
398 _length = _survivor_length + _scan_only_length; | |
545 | 399 _survivor_tail->set_next_young_region(_scan_only_head); |
342 | 400 } else { |
401 _head = _scan_only_head; | |
402 _length = _scan_only_length; | |
403 } | |
404 | |
405 for (HeapRegion* curr = _scan_only_head; | |
406 curr != NULL; | |
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; | |
545 | 416 _survivor_tail = NULL; |
342 | 417 _survivor_length = 0; |
545 | 418 _g1h->g1_policy()->finished_recalculating_age_indexes(false /* is_survivors */); |
342 | 419 |
420 assert(check_list_well_formed(), "young list should be well formed"); | |
421 } | |
422 | |
423 void YoungList::print() { | |
424 HeapRegion* lists[] = {_head, _scan_only_head, _survivor_head}; | |
425 const char* names[] = {"YOUNG", "SCAN-ONLY", "SURVIVOR"}; | |
426 | |
427 for (unsigned int list = 0; list < ARRAY_SIZE(lists); ++list) { | |
428 gclog_or_tty->print_cr("%s LIST CONTENTS", names[list]); | |
429 HeapRegion *curr = lists[list]; | |
430 if (curr == NULL) | |
431 gclog_or_tty->print_cr(" empty"); | |
432 while (curr != NULL) { | |
433 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", | |
435 curr->bottom(), curr->end(), | |
436 curr->top(), | |
437 curr->prev_top_at_mark_start(), | |
438 curr->next_top_at_mark_start(), | |
439 curr->top_at_conc_mark_count(), | |
440 curr->age_in_surv_rate_group_cond(), | |
441 curr->is_young(), | |
442 curr->is_scan_only(), | |
443 curr->is_survivor()); | |
444 curr = curr->get_next_young_region(); | |
445 } | |
446 } | |
447 | |
448 gclog_or_tty->print_cr(""); | |
449 } | |
450 | |
796
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
451 void G1CollectedHeap::push_dirty_cards_region(HeapRegion* hr) |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
452 { |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
453 // Claim the right to put the region on the dirty cards region list |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
454 // by installing a self pointer. |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
455 HeapRegion* next = hr->get_next_dirty_cards_region(); |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
456 if (next == NULL) { |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
457 HeapRegion* res = (HeapRegion*) |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
458 Atomic::cmpxchg_ptr(hr, hr->next_dirty_cards_region_addr(), |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
459 NULL); |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
460 if (res == NULL) { |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
461 HeapRegion* head; |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
462 do { |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
463 // Put the region to the dirty cards region list. |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
464 head = _dirty_cards_region_list; |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
465 next = (HeapRegion*) |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
466 Atomic::cmpxchg_ptr(hr, &_dirty_cards_region_list, head); |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
467 if (next == head) { |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
468 assert(hr->get_next_dirty_cards_region() == hr, |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
469 "hr->get_next_dirty_cards_region() != hr"); |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
470 if (next == NULL) { |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
471 // The last region in the list points to itself. |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
472 hr->set_next_dirty_cards_region(hr); |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
473 } else { |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
474 hr->set_next_dirty_cards_region(next); |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
475 } |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
476 } |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
477 } while (next != head); |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
478 } |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
479 } |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
480 } |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
481 |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
482 HeapRegion* G1CollectedHeap::pop_dirty_cards_region() |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
483 { |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
484 HeapRegion* head; |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
485 HeapRegion* hr; |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
486 do { |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
487 head = _dirty_cards_region_list; |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
488 if (head == NULL) { |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
489 return NULL; |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
490 } |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
491 HeapRegion* new_head = head->get_next_dirty_cards_region(); |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
492 if (head == new_head) { |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
493 // The last region. |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
494 new_head = NULL; |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
495 } |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
496 hr = (HeapRegion*)Atomic::cmpxchg_ptr(new_head, &_dirty_cards_region_list, |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
497 head); |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
498 } while (hr != head); |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
499 assert(hr != NULL, "invariant"); |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
500 hr->set_next_dirty_cards_region(NULL); |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
501 return hr; |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
502 } |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
503 |
342 | 504 void G1CollectedHeap::stop_conc_gc_threads() { |
794 | 505 _cg1r->stop(); |
342 | 506 _czft->stop(); |
507 _cmThread->stop(); | |
508 } | |
509 | |
510 | |
511 void G1CollectedHeap::check_ct_logs_at_safepoint() { | |
512 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); | |
513 CardTableModRefBS* ct_bs = (CardTableModRefBS*)barrier_set(); | |
514 | |
515 // Count the dirty cards at the start. | |
516 CountNonCleanMemRegionClosure count1(this); | |
517 ct_bs->mod_card_iterate(&count1); | |
518 int orig_count = count1.n(); | |
519 | |
520 // First clear the logged cards. | |
521 ClearLoggedCardTableEntryClosure clear; | |
522 dcqs.set_closure(&clear); | |
523 dcqs.apply_closure_to_all_completed_buffers(); | |
524 dcqs.iterate_closure_all_threads(false); | |
525 clear.print_histo(); | |
526 | |
527 // Now ensure that there's no dirty cards. | |
528 CountNonCleanMemRegionClosure count2(this); | |
529 ct_bs->mod_card_iterate(&count2); | |
530 if (count2.n() != 0) { | |
531 gclog_or_tty->print_cr("Card table has %d entries; %d originally", | |
532 count2.n(), orig_count); | |
533 } | |
534 guarantee(count2.n() == 0, "Card table should be clean."); | |
535 | |
536 RedirtyLoggedCardTableEntryClosure redirty; | |
537 JavaThread::dirty_card_queue_set().set_closure(&redirty); | |
538 dcqs.apply_closure_to_all_completed_buffers(); | |
539 dcqs.iterate_closure_all_threads(false); | |
540 gclog_or_tty->print_cr("Log entries = %d, dirty cards = %d.", | |
541 clear.calls(), orig_count); | |
542 guarantee(redirty.calls() == clear.calls(), | |
543 "Or else mechanism is broken."); | |
544 | |
545 CountNonCleanMemRegionClosure count3(this); | |
546 ct_bs->mod_card_iterate(&count3); | |
547 if (count3.n() != orig_count) { | |
548 gclog_or_tty->print_cr("Should have restored them all: orig = %d, final = %d.", | |
549 orig_count, count3.n()); | |
550 guarantee(count3.n() >= orig_count, "Should have restored them all."); | |
551 } | |
552 | |
553 JavaThread::dirty_card_queue_set().set_closure(_refine_cte_cl); | |
554 } | |
555 | |
556 // Private class members. | |
557 | |
558 G1CollectedHeap* G1CollectedHeap::_g1h; | |
559 | |
560 // Private methods. | |
561 | |
562 // Finds a HeapRegion that can be used to allocate a given size of block. | |
563 | |
564 | |
565 HeapRegion* G1CollectedHeap::newAllocRegion_work(size_t word_size, | |
566 bool do_expand, | |
567 bool zero_filled) { | |
568 ConcurrentZFThread::note_region_alloc(); | |
569 HeapRegion* res = alloc_free_region_from_lists(zero_filled); | |
570 if (res == NULL && do_expand) { | |
571 expand(word_size * HeapWordSize); | |
572 res = alloc_free_region_from_lists(zero_filled); | |
573 assert(res == NULL || | |
574 (!res->isHumongous() && | |
575 (!zero_filled || | |
576 res->zero_fill_state() == HeapRegion::Allocated)), | |
577 "Alloc Regions must be zero filled (and non-H)"); | |
578 } | |
579 if (res != NULL && res->is_empty()) _free_regions--; | |
580 assert(res == NULL || | |
581 (!res->isHumongous() && | |
582 (!zero_filled || | |
583 res->zero_fill_state() == HeapRegion::Allocated)), | |
584 "Non-young alloc Regions must be zero filled (and non-H)"); | |
585 | |
751 | 586 if (G1PrintRegions) { |
342 | 587 if (res != NULL) { |
588 gclog_or_tty->print_cr("new alloc region %d:["PTR_FORMAT", "PTR_FORMAT"], " | |
589 "top "PTR_FORMAT, | |
590 res->hrs_index(), res->bottom(), res->end(), res->top()); | |
591 } | |
592 } | |
593 | |
594 return res; | |
595 } | |
596 | |
597 HeapRegion* G1CollectedHeap::newAllocRegionWithExpansion(int purpose, | |
598 size_t word_size, | |
599 bool zero_filled) { | |
600 HeapRegion* alloc_region = NULL; | |
601 if (_gc_alloc_region_counts[purpose] < g1_policy()->max_regions(purpose)) { | |
602 alloc_region = newAllocRegion_work(word_size, true, zero_filled); | |
603 if (purpose == GCAllocForSurvived && alloc_region != NULL) { | |
545 | 604 alloc_region->set_survivor(); |
342 | 605 } |
606 ++_gc_alloc_region_counts[purpose]; | |
607 } else { | |
608 g1_policy()->note_alloc_region_limit_reached(purpose); | |
609 } | |
610 return alloc_region; | |
611 } | |
612 | |
613 // If could fit into free regions w/o expansion, try. | |
614 // Otherwise, if can expand, do so. | |
615 // Otherwise, if using ex regions might help, try with ex given back. | |
616 HeapWord* G1CollectedHeap::humongousObjAllocate(size_t word_size) { | |
617 assert(regions_accounted_for(), "Region leakage!"); | |
618 | |
619 // We can't allocate H regions while cleanupComplete is running, since | |
620 // some of the regions we find to be empty might not yet be added to the | |
621 // unclean list. (If we're already at a safepoint, this call is | |
622 // unnecessary, not to mention wrong.) | |
623 if (!SafepointSynchronize::is_at_safepoint()) | |
624 wait_for_cleanup_complete(); | |
625 | |
626 size_t num_regions = | |
627 round_to(word_size, HeapRegion::GrainWords) / HeapRegion::GrainWords; | |
628 | |
629 // Special case if < one region??? | |
630 | |
631 // Remember the ft size. | |
632 size_t x_size = expansion_regions(); | |
633 | |
634 HeapWord* res = NULL; | |
635 bool eliminated_allocated_from_lists = false; | |
636 | |
637 // Can the allocation potentially fit in the free regions? | |
638 if (free_regions() >= num_regions) { | |
639 res = _hrs->obj_allocate(word_size); | |
640 } | |
641 if (res == NULL) { | |
642 // Try expansion. | |
643 size_t fs = _hrs->free_suffix(); | |
644 if (fs + x_size >= num_regions) { | |
645 expand((num_regions - fs) * HeapRegion::GrainBytes); | |
646 res = _hrs->obj_allocate(word_size); | |
647 assert(res != NULL, "This should have worked."); | |
648 } else { | |
649 // Expansion won't help. Are there enough free regions if we get rid | |
650 // of reservations? | |
651 size_t avail = free_regions(); | |
652 if (avail >= num_regions) { | |
653 res = _hrs->obj_allocate(word_size); | |
654 if (res != NULL) { | |
655 remove_allocated_regions_from_lists(); | |
656 eliminated_allocated_from_lists = true; | |
657 } | |
658 } | |
659 } | |
660 } | |
661 if (res != NULL) { | |
662 // Increment by the number of regions allocated. | |
663 // FIXME: Assumes regions all of size GrainBytes. | |
664 #ifndef PRODUCT | |
665 mr_bs()->verify_clean_region(MemRegion(res, res + num_regions * | |
666 HeapRegion::GrainWords)); | |
667 #endif | |
668 if (!eliminated_allocated_from_lists) | |
669 remove_allocated_regions_from_lists(); | |
670 _summary_bytes_used += word_size * HeapWordSize; | |
671 _free_regions -= num_regions; | |
672 _num_humongous_regions += (int) num_regions; | |
673 } | |
674 assert(regions_accounted_for(), "Region Leakage"); | |
675 return res; | |
676 } | |
677 | |
678 HeapWord* | |
679 G1CollectedHeap::attempt_allocation_slow(size_t word_size, | |
680 bool permit_collection_pause) { | |
681 HeapWord* res = NULL; | |
682 HeapRegion* allocated_young_region = NULL; | |
683 | |
684 assert( SafepointSynchronize::is_at_safepoint() || | |
685 Heap_lock->owned_by_self(), "pre condition of the call" ); | |
686 | |
687 if (isHumongous(word_size)) { | |
688 // Allocation of a humongous object can, in a sense, complete a | |
689 // partial region, if the previous alloc was also humongous, and | |
690 // caused the test below to succeed. | |
691 if (permit_collection_pause) | |
692 do_collection_pause_if_appropriate(word_size); | |
693 res = humongousObjAllocate(word_size); | |
694 assert(_cur_alloc_region == NULL | |
695 || !_cur_alloc_region->isHumongous(), | |
696 "Prevent a regression of this bug."); | |
697 | |
698 } else { | |
354
c0f8f7790199
6652160: G1: assert(cur_used_bytes == _g1->recalculate_used(),"It should!") at g1CollectorPolicy.cpp:1425
iveresov
parents:
353
diff
changeset
|
699 // We may have concurrent cleanup working at the time. Wait for it |
c0f8f7790199
6652160: G1: assert(cur_used_bytes == _g1->recalculate_used(),"It should!") at g1CollectorPolicy.cpp:1425
iveresov
parents:
353
diff
changeset
|
700 // to complete. In the future we would probably want to make the |
c0f8f7790199
6652160: G1: assert(cur_used_bytes == _g1->recalculate_used(),"It should!") at g1CollectorPolicy.cpp:1425
iveresov
parents:
353
diff
changeset
|
701 // concurrent cleanup truly concurrent by decoupling it from the |
c0f8f7790199
6652160: G1: assert(cur_used_bytes == _g1->recalculate_used(),"It should!") at g1CollectorPolicy.cpp:1425
iveresov
parents:
353
diff
changeset
|
702 // allocation. |
c0f8f7790199
6652160: G1: assert(cur_used_bytes == _g1->recalculate_used(),"It should!") at g1CollectorPolicy.cpp:1425
iveresov
parents:
353
diff
changeset
|
703 if (!SafepointSynchronize::is_at_safepoint()) |
c0f8f7790199
6652160: G1: assert(cur_used_bytes == _g1->recalculate_used(),"It should!") at g1CollectorPolicy.cpp:1425
iveresov
parents:
353
diff
changeset
|
704 wait_for_cleanup_complete(); |
342 | 705 // 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 | |
707 // region below. | |
708 if (_cur_alloc_region != NULL) { | |
709 // We're finished with the _cur_alloc_region. | |
710 _summary_bytes_used += _cur_alloc_region->used(); | |
711 _cur_alloc_region = NULL; | |
712 } | |
713 assert(_cur_alloc_region == NULL, "Invariant."); | |
714 // Completion of a heap region is perhaps a good point at which to do | |
715 // a collection pause. | |
716 if (permit_collection_pause) | |
717 do_collection_pause_if_appropriate(word_size); | |
718 // Make sure we have an allocation region available. | |
719 if (_cur_alloc_region == NULL) { | |
720 if (!SafepointSynchronize::is_at_safepoint()) | |
721 wait_for_cleanup_complete(); | |
722 bool next_is_young = should_set_young_locked(); | |
723 // If the next region is not young, make sure it's zero-filled. | |
724 _cur_alloc_region = newAllocRegion(word_size, !next_is_young); | |
725 if (_cur_alloc_region != NULL) { | |
726 _summary_bytes_used -= _cur_alloc_region->used(); | |
727 if (next_is_young) { | |
728 set_region_short_lived_locked(_cur_alloc_region); | |
729 allocated_young_region = _cur_alloc_region; | |
730 } | |
731 } | |
732 } | |
733 assert(_cur_alloc_region == NULL || !_cur_alloc_region->isHumongous(), | |
734 "Prevent a regression of this bug."); | |
735 | |
736 // Now retry the allocation. | |
737 if (_cur_alloc_region != NULL) { | |
738 res = _cur_alloc_region->allocate(word_size); | |
739 } | |
740 } | |
741 | |
742 // NOTE: fails frequently in PRT | |
743 assert(regions_accounted_for(), "Region leakage!"); | |
744 | |
745 if (res != NULL) { | |
746 if (!SafepointSynchronize::is_at_safepoint()) { | |
747 assert( permit_collection_pause, "invariant" ); | |
748 assert( Heap_lock->owned_by_self(), "invariant" ); | |
749 Heap_lock->unlock(); | |
750 } | |
751 | |
752 if (allocated_young_region != NULL) { | |
753 HeapRegion* hr = allocated_young_region; | |
754 HeapWord* bottom = hr->bottom(); | |
755 HeapWord* end = hr->end(); | |
756 MemRegion mr(bottom, end); | |
757 ((CardTableModRefBS*)_g1h->barrier_set())->dirty(mr); | |
758 } | |
759 } | |
760 | |
761 assert( SafepointSynchronize::is_at_safepoint() || | |
762 (res == NULL && Heap_lock->owned_by_self()) || | |
763 (res != NULL && !Heap_lock->owned_by_self()), | |
764 "post condition of the call" ); | |
765 | |
766 return res; | |
767 } | |
768 | |
769 HeapWord* | |
770 G1CollectedHeap::mem_allocate(size_t word_size, | |
771 bool is_noref, | |
772 bool is_tlab, | |
773 bool* gc_overhead_limit_was_exceeded) { | |
774 debug_only(check_for_valid_allocation_state()); | |
775 assert(no_gc_in_progress(), "Allocation during gc not allowed"); | |
776 HeapWord* result = NULL; | |
777 | |
778 // Loop until the allocation is satisified, | |
779 // or unsatisfied after GC. | |
780 for (int try_count = 1; /* return or throw */; try_count += 1) { | |
781 int gc_count_before; | |
782 { | |
783 Heap_lock->lock(); | |
784 result = attempt_allocation(word_size); | |
785 if (result != NULL) { | |
786 // attempt_allocation should have unlocked the heap lock | |
787 assert(is_in(result), "result not in heap"); | |
788 return result; | |
789 } | |
790 // Read the gc count while the heap lock is held. | |
791 gc_count_before = SharedHeap::heap()->total_collections(); | |
792 Heap_lock->unlock(); | |
793 } | |
794 | |
795 // Create the garbage collection operation... | |
796 VM_G1CollectForAllocation op(word_size, | |
797 gc_count_before); | |
798 | |
799 // ...and get the VM thread to execute it. | |
800 VMThread::execute(&op); | |
801 if (op.prologue_succeeded()) { | |
802 result = op.result(); | |
803 assert(result == NULL || is_in(result), "result not in heap"); | |
804 return result; | |
805 } | |
806 | |
807 // Give a warning if we seem to be looping forever. | |
808 if ((QueuedAllocationWarningCount > 0) && | |
809 (try_count % QueuedAllocationWarningCount == 0)) { | |
810 warning("G1CollectedHeap::mem_allocate_work retries %d times", | |
811 try_count); | |
812 } | |
813 } | |
814 } | |
815 | |
816 void G1CollectedHeap::abandon_cur_alloc_region() { | |
817 if (_cur_alloc_region != NULL) { | |
818 // We're finished with the _cur_alloc_region. | |
819 if (_cur_alloc_region->is_empty()) { | |
820 _free_regions++; | |
821 free_region(_cur_alloc_region); | |
822 } else { | |
823 _summary_bytes_used += _cur_alloc_region->used(); | |
824 } | |
825 _cur_alloc_region = NULL; | |
826 } | |
827 } | |
828 | |
636 | 829 void G1CollectedHeap::abandon_gc_alloc_regions() { |
830 // first, make sure that the GC alloc region list is empty (it should!) | |
831 assert(_gc_alloc_region_list == NULL, "invariant"); | |
832 release_gc_alloc_regions(true /* totally */); | |
833 } | |
834 | |
342 | 835 class PostMCRemSetClearClosure: public HeapRegionClosure { |
836 ModRefBarrierSet* _mr_bs; | |
837 public: | |
838 PostMCRemSetClearClosure(ModRefBarrierSet* mr_bs) : _mr_bs(mr_bs) {} | |
839 bool doHeapRegion(HeapRegion* r) { | |
840 r->reset_gc_time_stamp(); | |
841 if (r->continuesHumongous()) | |
842 return false; | |
843 HeapRegionRemSet* hrrs = r->rem_set(); | |
844 if (hrrs != NULL) hrrs->clear(); | |
845 // You might think here that we could clear just the cards | |
846 // corresponding to the used region. But no: if we leave a dirty card | |
847 // in a region we might allocate into, then it would prevent that card | |
848 // from being enqueued, and cause it to be missed. | |
849 // Re: the performance cost: we shouldn't be doing full GC anyway! | |
850 _mr_bs->clear(MemRegion(r->bottom(), r->end())); | |
851 return false; | |
852 } | |
853 }; | |
854 | |
855 | |
856 class PostMCRemSetInvalidateClosure: public HeapRegionClosure { | |
857 ModRefBarrierSet* _mr_bs; | |
858 public: | |
859 PostMCRemSetInvalidateClosure(ModRefBarrierSet* mr_bs) : _mr_bs(mr_bs) {} | |
860 bool doHeapRegion(HeapRegion* r) { | |
861 if (r->continuesHumongous()) return false; | |
862 if (r->used_region().word_size() != 0) { | |
863 _mr_bs->invalidate(r->used_region(), true /*whole heap*/); | |
864 } | |
865 return false; | |
866 } | |
867 }; | |
868 | |
626
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
869 class RebuildRSOutOfRegionClosure: public HeapRegionClosure { |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
870 G1CollectedHeap* _g1h; |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
871 UpdateRSOopClosure _cl; |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
872 int _worker_i; |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
873 public: |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
874 RebuildRSOutOfRegionClosure(G1CollectedHeap* g1, int worker_i = 0) : |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
875 _cl(g1->g1_rem_set()->as_HRInto_G1RemSet(), worker_i), |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
876 _worker_i(worker_i), |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
877 _g1h(g1) |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
878 { } |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
879 bool doHeapRegion(HeapRegion* r) { |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
880 if (!r->continuesHumongous()) { |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
881 _cl.set_from(r); |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
882 r->oop_iterate(&_cl); |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
883 } |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
884 return false; |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
885 } |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
886 }; |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
887 |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
888 class ParRebuildRSTask: public AbstractGangTask { |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
889 G1CollectedHeap* _g1; |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
890 public: |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
891 ParRebuildRSTask(G1CollectedHeap* g1) |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
892 : AbstractGangTask("ParRebuildRSTask"), |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
893 _g1(g1) |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
894 { } |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
895 |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
896 void work(int i) { |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
897 RebuildRSOutOfRegionClosure rebuild_rs(_g1, i); |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
898 _g1->heap_region_par_iterate_chunked(&rebuild_rs, i, |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
899 HeapRegion::RebuildRSClaimValue); |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
900 } |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
901 }; |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
902 |
342 | 903 void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs, |
904 size_t word_size) { | |
905 ResourceMark rm; | |
906 | |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
907 if (PrintHeapAtGC) { |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
908 Universe::print_heap_before_gc(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
909 } |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
910 |
342 | 911 if (full && DisableExplicitGC) { |
912 gclog_or_tty->print("\n\n\nDisabling Explicit GC\n\n\n"); | |
913 return; | |
914 } | |
915 | |
916 assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint"); | |
917 assert(Thread::current() == VMThread::vm_thread(), "should be in vm thread"); | |
918 | |
919 if (GC_locker::is_active()) { | |
920 return; // GC is disabled (e.g. JNI GetXXXCritical operation) | |
921 } | |
922 | |
923 { | |
924 IsGCActiveMark x; | |
925 | |
926 // Timing | |
927 gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); | |
928 TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); | |
929 TraceTime t(full ? "Full GC (System.gc())" : "Full GC", PrintGC, true, gclog_or_tty); | |
930 | |
1089
db0d5eba9d20
6815790: G1: Missing MemoryPoolMXBeans with -XX:+UseG1GC
tonyp
parents:
1088
diff
changeset
|
931 TraceMemoryManagerStats tms(true /* fullGC */); |
db0d5eba9d20
6815790: G1: Missing MemoryPoolMXBeans with -XX:+UseG1GC
tonyp
parents:
1088
diff
changeset
|
932 |
342 | 933 double start = os::elapsedTime(); |
934 g1_policy()->record_full_collection_start(); | |
935 | |
936 gc_prologue(true); | |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
937 increment_total_collections(true /* full gc */); |
342 | 938 |
939 size_t g1h_prev_used = used(); | |
940 assert(used() == recalculate_used(), "Should be equal"); | |
941 | |
942 if (VerifyBeforeGC && total_collections() >= VerifyGCStartAt) { | |
943 HandleMark hm; // Discard invalid handles created during verification | |
944 prepare_for_verify(); | |
945 gclog_or_tty->print(" VerifyBeforeGC:"); | |
946 Universe::verify(true); | |
947 } | |
948 assert(regions_accounted_for(), "Region leakage!"); | |
949 | |
950 COMPILER2_PRESENT(DerivedPointerTable::clear()); | |
951 | |
952 // We want to discover references, but not process them yet. | |
953 // This mode is disabled in | |
954 // instanceRefKlass::process_discovered_references if the | |
955 // generation does some collection work, or | |
956 // instanceRefKlass::enqueue_discovered_references if the | |
957 // generation returns without doing any work. | |
958 ref_processor()->disable_discovery(); | |
959 ref_processor()->abandon_partial_discovery(); | |
960 ref_processor()->verify_no_references_recorded(); | |
961 | |
962 // Abandon current iterations of concurrent marking and concurrent | |
963 // refinement, if any are in progress. | |
964 concurrent_mark()->abort(); | |
965 | |
966 // Make sure we'll choose a new allocation region afterwards. | |
967 abandon_cur_alloc_region(); | |
636 | 968 abandon_gc_alloc_regions(); |
342 | 969 assert(_cur_alloc_region == NULL, "Invariant."); |
970 g1_rem_set()->as_HRInto_G1RemSet()->cleanupHRRS(); | |
971 tear_down_region_lists(); | |
972 set_used_regions_to_need_zero_fill(); | |
973 if (g1_policy()->in_young_gc_mode()) { | |
974 empty_young_list(); | |
975 g1_policy()->set_full_young_gcs(true); | |
976 } | |
977 | |
978 // Temporarily make reference _discovery_ single threaded (non-MT). | |
979 ReferenceProcessorMTMutator rp_disc_ser(ref_processor(), false); | |
980 | |
981 // Temporarily make refs discovery atomic | |
982 ReferenceProcessorAtomicMutator rp_disc_atomic(ref_processor(), true); | |
983 | |
984 // Temporarily clear _is_alive_non_header | |
985 ReferenceProcessorIsAliveMutator rp_is_alive_null(ref_processor(), NULL); | |
986 | |
987 ref_processor()->enable_discovery(); | |
457
27a80744a83b
6778647: snap(), snap_policy() should be renamed setup(), setup_policy()
ysr
parents:
453
diff
changeset
|
988 ref_processor()->setup_policy(clear_all_soft_refs); |
342 | 989 |
990 // Do collection work | |
991 { | |
992 HandleMark hm; // Discard invalid handles created during gc | |
993 G1MarkSweep::invoke_at_safepoint(ref_processor(), clear_all_soft_refs); | |
994 } | |
995 // Because freeing humongous regions may have added some unclean | |
996 // regions, it is necessary to tear down again before rebuilding. | |
997 tear_down_region_lists(); | |
998 rebuild_region_lists(); | |
999 | |
1000 _summary_bytes_used = recalculate_used(); | |
1001 | |
1002 ref_processor()->enqueue_discovered_references(); | |
1003 | |
1004 COMPILER2_PRESENT(DerivedPointerTable::update_pointers()); | |
1005 | |
1089
db0d5eba9d20
6815790: G1: Missing MemoryPoolMXBeans with -XX:+UseG1GC
tonyp
parents:
1088
diff
changeset
|
1006 MemoryService::track_memory_usage(); |
db0d5eba9d20
6815790: G1: Missing MemoryPoolMXBeans with -XX:+UseG1GC
tonyp
parents:
1088
diff
changeset
|
1007 |
342 | 1008 if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) { |
1009 HandleMark hm; // Discard invalid handles created during verification | |
1010 gclog_or_tty->print(" VerifyAfterGC:"); | |
637
25e146966e7c
6817419: G1: Enable extensive verification for humongous regions
iveresov
parents:
636
diff
changeset
|
1011 prepare_for_verify(); |
342 | 1012 Universe::verify(false); |
1013 } | |
1014 NOT_PRODUCT(ref_processor()->verify_no_references_recorded()); | |
1015 | |
1016 reset_gc_time_stamp(); | |
1017 // Since everything potentially moved, we will clear all remembered | |
626
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
1018 // sets, and clear all cards. Later we will rebuild remebered |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
1019 // sets. We will also reset the GC time stamps of the regions. |
342 | 1020 PostMCRemSetClearClosure rs_clear(mr_bs()); |
1021 heap_region_iterate(&rs_clear); | |
1022 | |
1023 // Resize the heap if necessary. | |
1024 resize_if_necessary_after_full_collection(full ? 0 : word_size); | |
1025 | |
1026 if (_cg1r->use_cache()) { | |
1027 _cg1r->clear_and_record_card_counts(); | |
1028 _cg1r->clear_hot_cache(); | |
1029 } | |
1030 | |
626
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
1031 // Rebuild remembered sets of all regions. |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
1032 if (ParallelGCThreads > 0) { |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
1033 ParRebuildRSTask rebuild_rs_task(this); |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
1034 assert(check_heap_region_claim_values( |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
1035 HeapRegion::InitialClaimValue), "sanity check"); |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
1036 set_par_threads(workers()->total_workers()); |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
1037 workers()->run_task(&rebuild_rs_task); |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
1038 set_par_threads(0); |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
1039 assert(check_heap_region_claim_values( |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
1040 HeapRegion::RebuildRSClaimValue), "sanity check"); |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
1041 reset_heap_region_claim_values(); |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
1042 } else { |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
1043 RebuildRSOutOfRegionClosure rebuild_rs(this); |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
1044 heap_region_iterate(&rebuild_rs); |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
1045 } |
87fa6e083d82
6760309: G1: update remembered sets during Full GCs
apetrusenko
parents:
620
diff
changeset
|
1046 |
342 | 1047 if (PrintGC) { |
1048 print_size_transition(gclog_or_tty, g1h_prev_used, used(), capacity()); | |
1049 } | |
1050 | |
1051 if (true) { // FIXME | |
1052 // Ask the permanent generation to adjust size for full collections | |
1053 perm()->compute_new_size(); | |
1054 } | |
1055 | |
1056 double end = os::elapsedTime(); | |
1057 g1_policy()->record_full_collection_end(); | |
1058 | |
546
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
545
diff
changeset
|
1059 #ifdef TRACESPINNING |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
545
diff
changeset
|
1060 ParallelTaskTerminator::print_termination_counts(); |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
545
diff
changeset
|
1061 #endif |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
545
diff
changeset
|
1062 |
342 | 1063 gc_epilogue(true); |
1064 | |
794 | 1065 // Discard all rset updates |
1066 JavaThread::dirty_card_queue_set().abandon_logs(); | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
1067 assert(!G1DeferredRSUpdate |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
1068 || (G1DeferredRSUpdate && (dirty_card_queue_set().completed_buffers_num() == 0)), "Should not be any"); |
342 | 1069 assert(regions_accounted_for(), "Region leakage!"); |
1070 } | |
1071 | |
1072 if (g1_policy()->in_young_gc_mode()) { | |
1073 _young_list->reset_sampled_info(); | |
1074 assert( check_young_list_empty(false, false), | |
1075 "young list should be empty at this point"); | |
1076 } | |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
1077 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
1078 if (PrintHeapAtGC) { |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
1079 Universe::print_heap_after_gc(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
1080 } |
342 | 1081 } |
1082 | |
1083 void G1CollectedHeap::do_full_collection(bool clear_all_soft_refs) { | |
1084 do_collection(true, clear_all_soft_refs, 0); | |
1085 } | |
1086 | |
1087 // This code is mostly copied from TenuredGeneration. | |
1088 void | |
1089 G1CollectedHeap:: | |
1090 resize_if_necessary_after_full_collection(size_t word_size) { | |
1091 assert(MinHeapFreeRatio <= MaxHeapFreeRatio, "sanity check"); | |
1092 | |
1093 // Include the current allocation, if any, and bytes that will be | |
1094 // pre-allocated to support collections, as "used". | |
1095 const size_t used_after_gc = used(); | |
1096 const size_t capacity_after_gc = capacity(); | |
1097 const size_t free_after_gc = capacity_after_gc - used_after_gc; | |
1098 | |
1099 // We don't have floating point command-line arguments | |
1100 const double minimum_free_percentage = (double) MinHeapFreeRatio / 100; | |
1101 const double maximum_used_percentage = 1.0 - minimum_free_percentage; | |
1102 const double maximum_free_percentage = (double) MaxHeapFreeRatio / 100; | |
1103 const double minimum_used_percentage = 1.0 - maximum_free_percentage; | |
1104 | |
1105 size_t minimum_desired_capacity = (size_t) (used_after_gc / maximum_used_percentage); | |
1106 size_t maximum_desired_capacity = (size_t) (used_after_gc / minimum_used_percentage); | |
1107 | |
1108 // Don't shrink less than the initial size. | |
1109 minimum_desired_capacity = | |
1110 MAX2(minimum_desired_capacity, | |
1111 collector_policy()->initial_heap_byte_size()); | |
1112 maximum_desired_capacity = | |
1113 MAX2(maximum_desired_capacity, | |
1114 collector_policy()->initial_heap_byte_size()); | |
1115 | |
1116 // We are failing here because minimum_desired_capacity is | |
1117 assert(used_after_gc <= minimum_desired_capacity, "sanity check"); | |
1118 assert(minimum_desired_capacity <= maximum_desired_capacity, "sanity check"); | |
1119 | |
1120 if (PrintGC && Verbose) { | |
1121 const double free_percentage = ((double)free_after_gc) / capacity(); | |
1122 gclog_or_tty->print_cr("Computing new size after full GC "); | |
1123 gclog_or_tty->print_cr(" " | |
1124 " minimum_free_percentage: %6.2f", | |
1125 minimum_free_percentage); | |
1126 gclog_or_tty->print_cr(" " | |
1127 " maximum_free_percentage: %6.2f", | |
1128 maximum_free_percentage); | |
1129 gclog_or_tty->print_cr(" " | |
1130 " capacity: %6.1fK" | |
1131 " minimum_desired_capacity: %6.1fK" | |
1132 " maximum_desired_capacity: %6.1fK", | |
1133 capacity() / (double) K, | |
1134 minimum_desired_capacity / (double) K, | |
1135 maximum_desired_capacity / (double) K); | |
1136 gclog_or_tty->print_cr(" " | |
1137 " free_after_gc : %6.1fK" | |
1138 " used_after_gc : %6.1fK", | |
1139 free_after_gc / (double) K, | |
1140 used_after_gc / (double) K); | |
1141 gclog_or_tty->print_cr(" " | |
1142 " free_percentage: %6.2f", | |
1143 free_percentage); | |
1144 } | |
1145 if (capacity() < minimum_desired_capacity) { | |
1146 // Don't expand unless it's significant | |
1147 size_t expand_bytes = minimum_desired_capacity - capacity_after_gc; | |
1148 expand(expand_bytes); | |
1149 if (PrintGC && Verbose) { | |
1150 gclog_or_tty->print_cr(" expanding:" | |
1151 " minimum_desired_capacity: %6.1fK" | |
1152 " expand_bytes: %6.1fK", | |
1153 minimum_desired_capacity / (double) K, | |
1154 expand_bytes / (double) K); | |
1155 } | |
1156 | |
1157 // No expansion, now see if we want to shrink | |
1158 } else if (capacity() > maximum_desired_capacity) { | |
1159 // Capacity too large, compute shrinking size | |
1160 size_t shrink_bytes = capacity_after_gc - maximum_desired_capacity; | |
1161 shrink(shrink_bytes); | |
1162 if (PrintGC && Verbose) { | |
1163 gclog_or_tty->print_cr(" " | |
1164 " shrinking:" | |
1165 " initSize: %.1fK" | |
1166 " maximum_desired_capacity: %.1fK", | |
1167 collector_policy()->initial_heap_byte_size() / (double) K, | |
1168 maximum_desired_capacity / (double) K); | |
1169 gclog_or_tty->print_cr(" " | |
1170 " shrink_bytes: %.1fK", | |
1171 shrink_bytes / (double) K); | |
1172 } | |
1173 } | |
1174 } | |
1175 | |
1176 | |
1177 HeapWord* | |
1178 G1CollectedHeap::satisfy_failed_allocation(size_t word_size) { | |
1179 HeapWord* result = NULL; | |
1180 | |
1181 // In a G1 heap, we're supposed to keep allocation from failing by | |
1182 // incremental pauses. Therefore, at least for now, we'll favor | |
1183 // expansion over collection. (This might change in the future if we can | |
1184 // do something smarter than full collection to satisfy a failed alloc.) | |
1185 | |
1186 result = expand_and_allocate(word_size); | |
1187 if (result != NULL) { | |
1188 assert(is_in(result), "result not in heap"); | |
1189 return result; | |
1190 } | |
1191 | |
1192 // OK, I guess we have to try collection. | |
1193 | |
1194 do_collection(false, false, word_size); | |
1195 | |
1196 result = attempt_allocation(word_size, /*permit_collection_pause*/false); | |
1197 | |
1198 if (result != NULL) { | |
1199 assert(is_in(result), "result not in heap"); | |
1200 return result; | |
1201 } | |
1202 | |
1203 // Try collecting soft references. | |
1204 do_collection(false, true, word_size); | |
1205 result = attempt_allocation(word_size, /*permit_collection_pause*/false); | |
1206 if (result != NULL) { | |
1207 assert(is_in(result), "result not in heap"); | |
1208 return result; | |
1209 } | |
1210 | |
1211 // What else? We might try synchronous finalization later. If the total | |
1212 // space available is large enough for the allocation, then a more | |
1213 // complete compaction phase than we've tried so far might be | |
1214 // appropriate. | |
1215 return NULL; | |
1216 } | |
1217 | |
1218 // Attempting to expand the heap sufficiently | |
1219 // to support an allocation of the given "word_size". If | |
1220 // successful, perform the allocation and return the address of the | |
1221 // allocated block, or else "NULL". | |
1222 | |
1223 HeapWord* G1CollectedHeap::expand_and_allocate(size_t word_size) { | |
1224 size_t expand_bytes = word_size * HeapWordSize; | |
1225 if (expand_bytes < MinHeapDeltaBytes) { | |
1226 expand_bytes = MinHeapDeltaBytes; | |
1227 } | |
1228 expand(expand_bytes); | |
1229 assert(regions_accounted_for(), "Region leakage!"); | |
1230 HeapWord* result = attempt_allocation(word_size, false /* permit_collection_pause */); | |
1231 return result; | |
1232 } | |
1233 | |
1234 size_t G1CollectedHeap::free_region_if_totally_empty(HeapRegion* hr) { | |
1235 size_t pre_used = 0; | |
1236 size_t cleared_h_regions = 0; | |
1237 size_t freed_regions = 0; | |
1238 UncleanRegionList local_list; | |
1239 free_region_if_totally_empty_work(hr, pre_used, cleared_h_regions, | |
1240 freed_regions, &local_list); | |
1241 | |
1242 finish_free_region_work(pre_used, cleared_h_regions, freed_regions, | |
1243 &local_list); | |
1244 return pre_used; | |
1245 } | |
1246 | |
1247 void | |
1248 G1CollectedHeap::free_region_if_totally_empty_work(HeapRegion* hr, | |
1249 size_t& pre_used, | |
1250 size_t& cleared_h, | |
1251 size_t& freed_regions, | |
1252 UncleanRegionList* list, | |
1253 bool par) { | |
1254 assert(!hr->continuesHumongous(), "should have filtered these out"); | |
1255 size_t res = 0; | |
677 | 1256 if (hr->used() > 0 && hr->garbage_bytes() == hr->used() && |
1257 !hr->is_young()) { | |
1258 if (G1PolicyVerbose > 0) | |
1259 gclog_or_tty->print_cr("Freeing empty region "PTR_FORMAT "(" SIZE_FORMAT " bytes)" | |
1260 " during cleanup", hr, hr->used()); | |
1261 free_region_work(hr, pre_used, cleared_h, freed_regions, list, par); | |
342 | 1262 } |
1263 } | |
1264 | |
1265 // FIXME: both this and shrink could probably be more efficient by | |
1266 // doing one "VirtualSpace::expand_by" call rather than several. | |
1267 void G1CollectedHeap::expand(size_t expand_bytes) { | |
1268 size_t old_mem_size = _g1_storage.committed_size(); | |
1269 // We expand by a minimum of 1K. | |
1270 expand_bytes = MAX2(expand_bytes, (size_t)K); | |
1271 size_t aligned_expand_bytes = | |
1272 ReservedSpace::page_align_size_up(expand_bytes); | |
1273 aligned_expand_bytes = align_size_up(aligned_expand_bytes, | |
1274 HeapRegion::GrainBytes); | |
1275 expand_bytes = aligned_expand_bytes; | |
1276 while (expand_bytes > 0) { | |
1277 HeapWord* base = (HeapWord*)_g1_storage.high(); | |
1278 // Commit more storage. | |
1279 bool successful = _g1_storage.expand_by(HeapRegion::GrainBytes); | |
1280 if (!successful) { | |
1281 expand_bytes = 0; | |
1282 } else { | |
1283 expand_bytes -= HeapRegion::GrainBytes; | |
1284 // Expand the committed region. | |
1285 HeapWord* high = (HeapWord*) _g1_storage.high(); | |
1286 _g1_committed.set_end(high); | |
1287 // Create a new HeapRegion. | |
1288 MemRegion mr(base, high); | |
1289 bool is_zeroed = !_g1_max_committed.contains(base); | |
1290 HeapRegion* hr = new HeapRegion(_bot_shared, mr, is_zeroed); | |
1291 | |
1292 // Now update max_committed if necessary. | |
1293 _g1_max_committed.set_end(MAX2(_g1_max_committed.end(), high)); | |
1294 | |
1295 // Add it to the HeapRegionSeq. | |
1296 _hrs->insert(hr); | |
1297 // Set the zero-fill state, according to whether it's already | |
1298 // zeroed. | |
1299 { | |
1300 MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag); | |
1301 if (is_zeroed) { | |
1302 hr->set_zero_fill_complete(); | |
1303 put_free_region_on_list_locked(hr); | |
1304 } else { | |
1305 hr->set_zero_fill_needed(); | |
1306 put_region_on_unclean_list_locked(hr); | |
1307 } | |
1308 } | |
1309 _free_regions++; | |
1310 // And we used up an expansion region to create it. | |
1311 _expansion_regions--; | |
1312 // Tell the cardtable about it. | |
1313 Universe::heap()->barrier_set()->resize_covered_region(_g1_committed); | |
1314 // And the offset table as well. | |
1315 _bot_shared->resize(_g1_committed.word_size()); | |
1316 } | |
1317 } | |
1318 if (Verbose && PrintGC) { | |
1319 size_t new_mem_size = _g1_storage.committed_size(); | |
1320 gclog_or_tty->print_cr("Expanding garbage-first heap from %ldK by %ldK to %ldK", | |
1321 old_mem_size/K, aligned_expand_bytes/K, | |
1322 new_mem_size/K); | |
1323 } | |
1324 } | |
1325 | |
1326 void G1CollectedHeap::shrink_helper(size_t shrink_bytes) | |
1327 { | |
1328 size_t old_mem_size = _g1_storage.committed_size(); | |
1329 size_t aligned_shrink_bytes = | |
1330 ReservedSpace::page_align_size_down(shrink_bytes); | |
1331 aligned_shrink_bytes = align_size_down(aligned_shrink_bytes, | |
1332 HeapRegion::GrainBytes); | |
1333 size_t num_regions_deleted = 0; | |
1334 MemRegion mr = _hrs->shrink_by(aligned_shrink_bytes, num_regions_deleted); | |
1335 | |
1336 assert(mr.end() == (HeapWord*)_g1_storage.high(), "Bad shrink!"); | |
1337 if (mr.byte_size() > 0) | |
1338 _g1_storage.shrink_by(mr.byte_size()); | |
1339 assert(mr.start() == (HeapWord*)_g1_storage.high(), "Bad shrink!"); | |
1340 | |
1341 _g1_committed.set_end(mr.start()); | |
1342 _free_regions -= num_regions_deleted; | |
1343 _expansion_regions += num_regions_deleted; | |
1344 | |
1345 // Tell the cardtable about it. | |
1346 Universe::heap()->barrier_set()->resize_covered_region(_g1_committed); | |
1347 | |
1348 // And the offset table as well. | |
1349 _bot_shared->resize(_g1_committed.word_size()); | |
1350 | |
1351 HeapRegionRemSet::shrink_heap(n_regions()); | |
1352 | |
1353 if (Verbose && PrintGC) { | |
1354 size_t new_mem_size = _g1_storage.committed_size(); | |
1355 gclog_or_tty->print_cr("Shrinking garbage-first heap from %ldK by %ldK to %ldK", | |
1356 old_mem_size/K, aligned_shrink_bytes/K, | |
1357 new_mem_size/K); | |
1358 } | |
1359 } | |
1360 | |
1361 void G1CollectedHeap::shrink(size_t shrink_bytes) { | |
636 | 1362 release_gc_alloc_regions(true /* totally */); |
342 | 1363 tear_down_region_lists(); // We will rebuild them in a moment. |
1364 shrink_helper(shrink_bytes); | |
1365 rebuild_region_lists(); | |
1366 } | |
1367 | |
1368 // Public methods. | |
1369 | |
1370 #ifdef _MSC_VER // the use of 'this' below gets a warning, make it go away | |
1371 #pragma warning( disable:4355 ) // 'this' : used in base member initializer list | |
1372 #endif // _MSC_VER | |
1373 | |
1374 | |
1375 G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) : | |
1376 SharedHeap(policy_), | |
1377 _g1_policy(policy_), | |
1111 | 1378 _dirty_card_queue_set(false), |
342 | 1379 _ref_processor(NULL), |
1380 _process_strong_tasks(new SubTasksDone(G1H_PS_NumElements)), | |
1381 _bot_shared(NULL), | |
1382 _par_alloc_during_gc_lock(Mutex::leaf, "par alloc during GC lock"), | |
1383 _objs_with_preserved_marks(NULL), _preserved_marks_of_objs(NULL), | |
1384 _evac_failure_scan_stack(NULL) , | |
1385 _mark_in_progress(false), | |
1386 _cg1r(NULL), _czft(NULL), _summary_bytes_used(0), | |
1387 _cur_alloc_region(NULL), | |
1388 _refine_cte_cl(NULL), | |
1389 _free_region_list(NULL), _free_region_list_size(0), | |
1390 _free_regions(0), | |
1391 _full_collection(false), | |
1392 _unclean_region_list(), | |
1393 _unclean_regions_coming(false), | |
1394 _young_list(new YoungList(this)), | |
1395 _gc_time_stamp(0), | |
526 | 1396 _surviving_young_words(NULL), |
1397 _in_cset_fast_test(NULL), | |
796
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
1398 _in_cset_fast_test_base(NULL), |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
1399 _dirty_cards_region_list(NULL) { |
342 | 1400 _g1h = this; // To catch bugs. |
1401 if (_process_strong_tasks == NULL || !_process_strong_tasks->valid()) { | |
1402 vm_exit_during_initialization("Failed necessary allocation."); | |
1403 } | |
942
2c79770d1f6e
6819085: G1: use larger and/or user settable region size
tonyp
parents:
941
diff
changeset
|
1404 |
2c79770d1f6e
6819085: G1: use larger and/or user settable region size
tonyp
parents:
941
diff
changeset
|
1405 _humongous_object_threshold_in_words = HeapRegion::GrainWords / 2; |
2c79770d1f6e
6819085: G1: use larger and/or user settable region size
tonyp
parents:
941
diff
changeset
|
1406 |
342 | 1407 int n_queues = MAX2((int)ParallelGCThreads, 1); |
1408 _task_queues = new RefToScanQueueSet(n_queues); | |
1409 | |
1410 int n_rem_sets = HeapRegionRemSet::num_par_rem_sets(); | |
1411 assert(n_rem_sets > 0, "Invariant."); | |
1412 | |
1413 HeapRegionRemSetIterator** iter_arr = | |
1414 NEW_C_HEAP_ARRAY(HeapRegionRemSetIterator*, n_queues); | |
1415 for (int i = 0; i < n_queues; i++) { | |
1416 iter_arr[i] = new HeapRegionRemSetIterator(); | |
1417 } | |
1418 _rem_set_iterator = iter_arr; | |
1419 | |
1420 for (int i = 0; i < n_queues; i++) { | |
1421 RefToScanQueue* q = new RefToScanQueue(); | |
1422 q->initialize(); | |
1423 _task_queues->register_queue(i, q); | |
1424 } | |
1425 | |
1426 for (int ap = 0; ap < GCAllocPurposeCount; ++ap) { | |
636 | 1427 _gc_alloc_regions[ap] = NULL; |
1428 _gc_alloc_region_counts[ap] = 0; | |
1429 _retained_gc_alloc_regions[ap] = NULL; | |
1430 // by default, we do not retain a GC alloc region for each ap; | |
1431 // we'll override this, when appropriate, below | |
1432 _retain_gc_alloc_region[ap] = false; | |
1433 } | |
1434 | |
1435 // We will try to remember the last half-full tenured region we | |
1436 // allocated to at the end of a collection so that we can re-use it | |
1437 // during the next collection. | |
1438 _retain_gc_alloc_region[GCAllocForTenured] = true; | |
1439 | |
342 | 1440 guarantee(_task_queues != NULL, "task_queues allocation failure."); |
1441 } | |
1442 | |
1443 jint G1CollectedHeap::initialize() { | |
1444 os::enable_vtime(); | |
1445 | |
1446 // Necessary to satisfy locking discipline assertions. | |
1447 | |
1448 MutexLocker x(Heap_lock); | |
1449 | |
1450 // While there are no constraints in the GC code that HeapWordSize | |
1451 // be any particular value, there are multiple other areas in the | |
1452 // system which believe this to be true (e.g. oop->object_size in some | |
1453 // cases incorrectly returns the size in wordSize units rather than | |
1454 // HeapWordSize). | |
1455 guarantee(HeapWordSize == wordSize, "HeapWordSize must equal wordSize"); | |
1456 | |
1457 size_t init_byte_size = collector_policy()->initial_heap_byte_size(); | |
1458 size_t max_byte_size = collector_policy()->max_heap_byte_size(); | |
1459 | |
1460 // Ensure that the sizes are properly aligned. | |
1461 Universe::check_alignment(init_byte_size, HeapRegion::GrainBytes, "g1 heap"); | |
1462 Universe::check_alignment(max_byte_size, HeapRegion::GrainBytes, "g1 heap"); | |
1463 | |
1464 _cg1r = new ConcurrentG1Refine(); | |
1465 | |
1466 // Reserve the maximum. | |
1467 PermanentGenerationSpec* pgs = collector_policy()->permanent_generation(); | |
1468 // Includes the perm-gen. | |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1469 |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1470 const size_t total_reserved = max_byte_size + pgs->max_size(); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1471 char* addr = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1472 |
342 | 1473 ReservedSpace heap_rs(max_byte_size + pgs->max_size(), |
1474 HeapRegion::GrainBytes, | |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1475 false /*ism*/, addr); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1476 |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1477 if (UseCompressedOops) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1478 if (addr != NULL && !heap_rs.is_reserved()) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1479 // Failed to reserve at specified address - the requested memory |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1480 // region is taken already, for example, by 'java' launcher. |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1481 // Try again to reserver heap higher. |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1482 addr = Universe::preferred_heap_base(total_reserved, Universe::ZeroBasedNarrowOop); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1483 ReservedSpace heap_rs0(total_reserved, HeapRegion::GrainBytes, |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1484 false /*ism*/, addr); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1485 if (addr != NULL && !heap_rs0.is_reserved()) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1486 // Failed to reserve at specified address again - give up. |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1487 addr = Universe::preferred_heap_base(total_reserved, Universe::HeapBasedNarrowOop); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1488 assert(addr == NULL, ""); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1489 ReservedSpace heap_rs1(total_reserved, HeapRegion::GrainBytes, |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1490 false /*ism*/, addr); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1491 heap_rs = heap_rs1; |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1492 } else { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1493 heap_rs = heap_rs0; |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1494 } |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1495 } |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
620
diff
changeset
|
1496 } |
342 | 1497 |
1498 if (!heap_rs.is_reserved()) { | |
1499 vm_exit_during_initialization("Could not reserve enough space for object heap"); | |
1500 return JNI_ENOMEM; | |
1501 } | |
1502 | |
1503 // It is important to do this in a way such that concurrent readers can't | |
1504 // temporarily think somethings in the heap. (I've actually seen this | |
1505 // happen in asserts: DLD.) | |
1506 _reserved.set_word_size(0); | |
1507 _reserved.set_start((HeapWord*)heap_rs.base()); | |
1508 _reserved.set_end((HeapWord*)(heap_rs.base() + heap_rs.size())); | |
1509 | |
1510 _expansion_regions = max_byte_size/HeapRegion::GrainBytes; | |
1511 | |
1512 _num_humongous_regions = 0; | |
1513 | |
1514 // Create the gen rem set (and barrier set) for the entire reserved region. | |
1515 _rem_set = collector_policy()->create_rem_set(_reserved, 2); | |
1516 set_barrier_set(rem_set()->bs()); | |
1517 if (barrier_set()->is_a(BarrierSet::ModRef)) { | |
1518 _mr_bs = (ModRefBarrierSet*)_barrier_set; | |
1519 } else { | |
1520 vm_exit_during_initialization("G1 requires a mod ref bs."); | |
1521 return JNI_ENOMEM; | |
1522 } | |
1523 | |
1524 // Also create a G1 rem set. | |
1525 if (G1UseHRIntoRS) { | |
1526 if (mr_bs()->is_a(BarrierSet::CardTableModRef)) { | |
1527 _g1_rem_set = new HRInto_G1RemSet(this, (CardTableModRefBS*)mr_bs()); | |
1528 } else { | |
1529 vm_exit_during_initialization("G1 requires a cardtable mod ref bs."); | |
1530 return JNI_ENOMEM; | |
1531 } | |
1532 } else { | |
1533 _g1_rem_set = new StupidG1RemSet(this); | |
1534 } | |
1535 | |
1536 // Carve out the G1 part of the heap. | |
1537 | |
1538 ReservedSpace g1_rs = heap_rs.first_part(max_byte_size); | |
1539 _g1_reserved = MemRegion((HeapWord*)g1_rs.base(), | |
1540 g1_rs.size()/HeapWordSize); | |
1541 ReservedSpace perm_gen_rs = heap_rs.last_part(max_byte_size); | |
1542 | |
1543 _perm_gen = pgs->init(perm_gen_rs, pgs->init_size(), rem_set()); | |
1544 | |
1545 _g1_storage.initialize(g1_rs, 0); | |
1546 _g1_committed = MemRegion((HeapWord*)_g1_storage.low(), (size_t) 0); | |
1547 _g1_max_committed = _g1_committed; | |
393 | 1548 _hrs = new HeapRegionSeq(_expansion_regions); |
342 | 1549 guarantee(_hrs != NULL, "Couldn't allocate HeapRegionSeq"); |
1550 guarantee(_cur_alloc_region == NULL, "from constructor"); | |
1551 | |
807
d44bdab1c03d
6843694: G1: assert(index < _vs.committed_size(),"bad index"), g1BlockOffsetTable.inline.hpp:55
johnc
parents:
796
diff
changeset
|
1552 // 6843694 - ensure that the maximum region index can fit |
d44bdab1c03d
6843694: G1: assert(index < _vs.committed_size(),"bad index"), g1BlockOffsetTable.inline.hpp:55
johnc
parents:
796
diff
changeset
|
1553 // in the remembered set structures. |
d44bdab1c03d
6843694: G1: assert(index < _vs.committed_size(),"bad index"), g1BlockOffsetTable.inline.hpp:55
johnc
parents:
796
diff
changeset
|
1554 const size_t max_region_idx = ((size_t)1 << (sizeof(RegionIdx_t)*BitsPerByte-1)) - 1; |
d44bdab1c03d
6843694: G1: assert(index < _vs.committed_size(),"bad index"), g1BlockOffsetTable.inline.hpp:55
johnc
parents:
796
diff
changeset
|
1555 guarantee((max_regions() - 1) <= max_region_idx, "too many regions"); |
d44bdab1c03d
6843694: G1: assert(index < _vs.committed_size(),"bad index"), g1BlockOffsetTable.inline.hpp:55
johnc
parents:
796
diff
changeset
|
1556 |
d44bdab1c03d
6843694: G1: assert(index < _vs.committed_size(),"bad index"), g1BlockOffsetTable.inline.hpp:55
johnc
parents:
796
diff
changeset
|
1557 size_t max_cards_per_region = ((size_t)1 << (sizeof(CardIdx_t)*BitsPerByte-1)) - 1; |
942
2c79770d1f6e
6819085: G1: use larger and/or user settable region size
tonyp
parents:
941
diff
changeset
|
1558 guarantee(HeapRegion::CardsPerRegion > 0, "make sure it's initialized"); |
2c79770d1f6e
6819085: G1: use larger and/or user settable region size
tonyp
parents:
941
diff
changeset
|
1559 guarantee((size_t) HeapRegion::CardsPerRegion < max_cards_per_region, |
2c79770d1f6e
6819085: G1: use larger and/or user settable region size
tonyp
parents:
941
diff
changeset
|
1560 "too many cards per region"); |
807
d44bdab1c03d
6843694: G1: assert(index < _vs.committed_size(),"bad index"), g1BlockOffsetTable.inline.hpp:55
johnc
parents:
796
diff
changeset
|
1561 |
342 | 1562 _bot_shared = new G1BlockOffsetSharedArray(_reserved, |
1563 heap_word_size(init_byte_size)); | |
1564 | |
1565 _g1h = this; | |
1566 | |
1567 // Create the ConcurrentMark data structure and thread. | |
1568 // (Must do this late, so that "max_regions" is defined.) | |
1569 _cm = new ConcurrentMark(heap_rs, (int) max_regions()); | |
1570 _cmThread = _cm->cmThread(); | |
1571 | |
1572 // ...and the concurrent zero-fill thread, if necessary. | |
1573 if (G1ConcZeroFill) { | |
1574 _czft = new ConcurrentZFThread(); | |
1575 } | |
1576 | |
1577 // Initialize the from_card cache structure of HeapRegionRemSet. | |
1578 HeapRegionRemSet::init_heap(max_regions()); | |
1579 | |
677 | 1580 // Now expand into the initial heap size. |
1581 expand(init_byte_size); | |
342 | 1582 |
1583 // Perform any initialization actions delegated to the policy. | |
1584 g1_policy()->init(); | |
1585 | |
1586 g1_policy()->note_start_of_mark_thread(); | |
1587 | |
1588 _refine_cte_cl = | |
1589 new RefineCardTableEntryClosure(ConcurrentG1RefineThread::sts(), | |
1590 g1_rem_set(), | |
1591 concurrent_g1_refine()); | |
1592 JavaThread::dirty_card_queue_set().set_closure(_refine_cte_cl); | |
1593 | |
1594 JavaThread::satb_mark_queue_set().initialize(SATB_Q_CBL_mon, | |
1595 SATB_Q_FL_lock, | |
1111 | 1596 G1SATBProcessCompletedThreshold, |
342 | 1597 Shared_SATB_Q_lock); |
794 | 1598 |
1599 JavaThread::dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon, | |
1600 DirtyCardQ_FL_lock, | |
1111 | 1601 concurrent_g1_refine()->yellow_zone(), |
1602 concurrent_g1_refine()->red_zone(), | |
794 | 1603 Shared_DirtyCardQ_lock); |
1604 | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
1605 if (G1DeferredRSUpdate) { |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
1606 dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon, |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
1607 DirtyCardQ_FL_lock, |
1111 | 1608 -1, // never trigger processing |
1609 -1, // no limit on length | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
1610 Shared_DirtyCardQ_lock, |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
1611 &JavaThread::dirty_card_queue_set()); |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
1612 } |
342 | 1613 // In case we're keeping closure specialization stats, initialize those |
1614 // counts and that mechanism. | |
1615 SpecializationStats::clear(); | |
1616 | |
1617 _gc_alloc_region_list = NULL; | |
1618 | |
1619 // Do later initialization work for concurrent refinement. | |
1620 _cg1r->init(); | |
1621 | |
1622 return JNI_OK; | |
1623 } | |
1624 | |
1625 void G1CollectedHeap::ref_processing_init() { | |
1626 SharedHeap::ref_processing_init(); | |
1627 MemRegion mr = reserved_region(); | |
1628 _ref_processor = ReferenceProcessor::create_ref_processor( | |
1629 mr, // span | |
1630 false, // Reference discovery is not atomic | |
1631 // (though it shouldn't matter here.) | |
1632 true, // mt_discovery | |
1633 NULL, // is alive closure: need to fill this in for efficiency | |
1634 ParallelGCThreads, | |
1635 ParallelRefProcEnabled, | |
1636 true); // Setting next fields of discovered | |
1637 // lists requires a barrier. | |
1638 } | |
1639 | |
1640 size_t G1CollectedHeap::capacity() const { | |
1641 return _g1_committed.byte_size(); | |
1642 } | |
1643 | |
1644 void G1CollectedHeap::iterate_dirty_card_closure(bool concurrent, | |
1645 int worker_i) { | |
889 | 1646 // Clean cards in the hot card cache |
1647 concurrent_g1_refine()->clean_up_cache(worker_i, g1_rem_set()); | |
1648 | |
342 | 1649 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); |
1650 int n_completed_buffers = 0; | |
1651 while (dcqs.apply_closure_to_completed_buffer(worker_i, 0, true)) { | |
1652 n_completed_buffers++; | |
1653 } | |
1654 g1_policy()->record_update_rs_processed_buffers(worker_i, | |
1655 (double) n_completed_buffers); | |
1656 dcqs.clear_n_completed_buffers(); | |
1657 assert(!dcqs.completed_buffers_exist_dirty(), "Completed buffers exist!"); | |
1658 } | |
1659 | |
1660 | |
1661 // Computes the sum of the storage used by the various regions. | |
1662 | |
1663 size_t G1CollectedHeap::used() const { | |
862
36b5611220a7
6863216: Clean up debugging debris inadvertently pushed with 6700789
ysr
parents:
861
diff
changeset
|
1664 assert(Heap_lock->owner() != NULL, |
36b5611220a7
6863216: Clean up debugging debris inadvertently pushed with 6700789
ysr
parents:
861
diff
changeset
|
1665 "Should be owned on this thread's behalf."); |
342 | 1666 size_t result = _summary_bytes_used; |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
1667 // Read only once in case it is set to NULL concurrently |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
1668 HeapRegion* hr = _cur_alloc_region; |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
1669 if (hr != NULL) |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
1670 result += hr->used(); |
342 | 1671 return result; |
1672 } | |
1673 | |
846
42d84bbbecf4
6859911: G1: assert(Heap_lock->owner() = NULL, "Should be owned on this thread's behalf")
tonyp
parents:
845
diff
changeset
|
1674 size_t G1CollectedHeap::used_unlocked() const { |
42d84bbbecf4
6859911: G1: assert(Heap_lock->owner() = NULL, "Should be owned on this thread's behalf")
tonyp
parents:
845
diff
changeset
|
1675 size_t result = _summary_bytes_used; |
42d84bbbecf4
6859911: G1: assert(Heap_lock->owner() = NULL, "Should be owned on this thread's behalf")
tonyp
parents:
845
diff
changeset
|
1676 return result; |
42d84bbbecf4
6859911: G1: assert(Heap_lock->owner() = NULL, "Should be owned on this thread's behalf")
tonyp
parents:
845
diff
changeset
|
1677 } |
42d84bbbecf4
6859911: G1: assert(Heap_lock->owner() = NULL, "Should be owned on this thread's behalf")
tonyp
parents:
845
diff
changeset
|
1678 |
342 | 1679 class SumUsedClosure: public HeapRegionClosure { |
1680 size_t _used; | |
1681 public: | |
1682 SumUsedClosure() : _used(0) {} | |
1683 bool doHeapRegion(HeapRegion* r) { | |
1684 if (!r->continuesHumongous()) { | |
1685 _used += r->used(); | |
1686 } | |
1687 return false; | |
1688 } | |
1689 size_t result() { return _used; } | |
1690 }; | |
1691 | |
1692 size_t G1CollectedHeap::recalculate_used() const { | |
1693 SumUsedClosure blk; | |
1694 _hrs->iterate(&blk); | |
1695 return blk.result(); | |
1696 } | |
1697 | |
1698 #ifndef PRODUCT | |
1699 class SumUsedRegionsClosure: public HeapRegionClosure { | |
1700 size_t _num; | |
1701 public: | |
677 | 1702 SumUsedRegionsClosure() : _num(0) {} |
342 | 1703 bool doHeapRegion(HeapRegion* r) { |
1704 if (r->continuesHumongous() || r->used() > 0 || r->is_gc_alloc_region()) { | |
1705 _num += 1; | |
1706 } | |
1707 return false; | |
1708 } | |
1709 size_t result() { return _num; } | |
1710 }; | |
1711 | |
1712 size_t G1CollectedHeap::recalculate_used_regions() const { | |
1713 SumUsedRegionsClosure blk; | |
1714 _hrs->iterate(&blk); | |
1715 return blk.result(); | |
1716 } | |
1717 #endif // PRODUCT | |
1718 | |
1719 size_t G1CollectedHeap::unsafe_max_alloc() { | |
1720 if (_free_regions > 0) return HeapRegion::GrainBytes; | |
1721 // otherwise, is there space in the current allocation region? | |
1722 | |
1723 // We need to store the current allocation region in a local variable | |
1724 // here. The problem is that this method doesn't take any locks and | |
1725 // there may be other threads which overwrite the current allocation | |
1726 // region field. attempt_allocation(), for example, sets it to NULL | |
1727 // and this can happen *after* the NULL check here but before the call | |
1728 // to free(), resulting in a SIGSEGV. Note that this doesn't appear | |
1729 // to be a problem in the optimized build, since the two loads of the | |
1730 // current allocation region field are optimized away. | |
1731 HeapRegion* car = _cur_alloc_region; | |
1732 | |
1733 // FIXME: should iterate over all regions? | |
1734 if (car == NULL) { | |
1735 return 0; | |
1736 } | |
1737 return car->free(); | |
1738 } | |
1739 | |
1740 void G1CollectedHeap::collect_as_vm_thread(GCCause::Cause cause) { | |
1741 assert(Thread::current()->is_VM_thread(), "Precondition#1"); | |
1742 assert(Heap_lock->is_locked(), "Precondition#2"); | |
1743 GCCauseSetter gcs(this, cause); | |
1744 switch (cause) { | |
1745 case GCCause::_heap_inspection: | |
1746 case GCCause::_heap_dump: { | |
1747 HandleMark hm; | |
1748 do_full_collection(false); // don't clear all soft refs | |
1749 break; | |
1750 } | |
1751 default: // XXX FIX ME | |
1752 ShouldNotReachHere(); // Unexpected use of this function | |
1753 } | |
1754 } | |
1755 | |
1088
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1756 void G1CollectedHeap::collect(GCCause::Cause cause) { |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1757 // The caller doesn't have the Heap_lock |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1758 assert(!Heap_lock->owned_by_self(), "this thread should not own the Heap_lock"); |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1759 |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1760 int gc_count_before; |
342 | 1761 { |
1088
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1762 MutexLocker ml(Heap_lock); |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1763 // Read the GC count while holding the Heap_lock |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1764 gc_count_before = SharedHeap::heap()->total_collections(); |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1765 |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1766 // Don't want to do a GC until cleanup is completed. |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1767 wait_for_cleanup_complete(); |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1768 } // We give up heap lock; VMThread::execute gets it back below |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1769 switch (cause) { |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1770 case GCCause::_scavenge_alot: { |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1771 // Do an incremental pause, which might sometimes be abandoned. |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1772 VM_G1IncCollectionPause op(gc_count_before, cause); |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1773 VMThread::execute(&op); |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1774 break; |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1775 } |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1776 default: { |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1777 // In all other cases, we currently do a full gc. |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1778 VM_G1CollectFull op(gc_count_before, cause); |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1779 VMThread::execute(&op); |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
1780 } |
342 | 1781 } |
1782 } | |
1783 | |
1784 bool G1CollectedHeap::is_in(const void* p) const { | |
1785 if (_g1_committed.contains(p)) { | |
1786 HeapRegion* hr = _hrs->addr_to_region(p); | |
1787 return hr->is_in(p); | |
1788 } else { | |
1789 return _perm_gen->as_gen()->is_in(p); | |
1790 } | |
1791 } | |
1792 | |
1793 // Iteration functions. | |
1794 | |
1795 // Iterates an OopClosure over all ref-containing fields of objects | |
1796 // within a HeapRegion. | |
1797 | |
1798 class IterateOopClosureRegionClosure: public HeapRegionClosure { | |
1799 MemRegion _mr; | |
1800 OopClosure* _cl; | |
1801 public: | |
1802 IterateOopClosureRegionClosure(MemRegion mr, OopClosure* cl) | |
1803 : _mr(mr), _cl(cl) {} | |
1804 bool doHeapRegion(HeapRegion* r) { | |
1805 if (! r->continuesHumongous()) { | |
1806 r->oop_iterate(_cl); | |
1807 } | |
1808 return false; | |
1809 } | |
1810 }; | |
1811 | |
678 | 1812 void G1CollectedHeap::oop_iterate(OopClosure* cl, bool do_perm) { |
342 | 1813 IterateOopClosureRegionClosure blk(_g1_committed, cl); |
1814 _hrs->iterate(&blk); | |
678 | 1815 if (do_perm) { |
1816 perm_gen()->oop_iterate(cl); | |
1817 } | |
342 | 1818 } |
1819 | |
678 | 1820 void G1CollectedHeap::oop_iterate(MemRegion mr, OopClosure* cl, bool do_perm) { |
342 | 1821 IterateOopClosureRegionClosure blk(mr, cl); |
1822 _hrs->iterate(&blk); | |
678 | 1823 if (do_perm) { |
1824 perm_gen()->oop_iterate(cl); | |
1825 } | |
342 | 1826 } |
1827 | |
1828 // Iterates an ObjectClosure over all objects within a HeapRegion. | |
1829 | |
1830 class IterateObjectClosureRegionClosure: public HeapRegionClosure { | |
1831 ObjectClosure* _cl; | |
1832 public: | |
1833 IterateObjectClosureRegionClosure(ObjectClosure* cl) : _cl(cl) {} | |
1834 bool doHeapRegion(HeapRegion* r) { | |
1835 if (! r->continuesHumongous()) { | |
1836 r->object_iterate(_cl); | |
1837 } | |
1838 return false; | |
1839 } | |
1840 }; | |
1841 | |
678 | 1842 void G1CollectedHeap::object_iterate(ObjectClosure* cl, bool do_perm) { |
342 | 1843 IterateObjectClosureRegionClosure blk(cl); |
1844 _hrs->iterate(&blk); | |
678 | 1845 if (do_perm) { |
1846 perm_gen()->object_iterate(cl); | |
1847 } | |
342 | 1848 } |
1849 | |
1850 void G1CollectedHeap::object_iterate_since_last_GC(ObjectClosure* cl) { | |
1851 // FIXME: is this right? | |
1852 guarantee(false, "object_iterate_since_last_GC not supported by G1 heap"); | |
1853 } | |
1854 | |
1855 // Calls a SpaceClosure on a HeapRegion. | |
1856 | |
1857 class SpaceClosureRegionClosure: public HeapRegionClosure { | |
1858 SpaceClosure* _cl; | |
1859 public: | |
1860 SpaceClosureRegionClosure(SpaceClosure* cl) : _cl(cl) {} | |
1861 bool doHeapRegion(HeapRegion* r) { | |
1862 _cl->do_space(r); | |
1863 return false; | |
1864 } | |
1865 }; | |
1866 | |
1867 void G1CollectedHeap::space_iterate(SpaceClosure* cl) { | |
1868 SpaceClosureRegionClosure blk(cl); | |
1869 _hrs->iterate(&blk); | |
1870 } | |
1871 | |
1872 void G1CollectedHeap::heap_region_iterate(HeapRegionClosure* cl) { | |
1873 _hrs->iterate(cl); | |
1874 } | |
1875 | |
1876 void G1CollectedHeap::heap_region_iterate_from(HeapRegion* r, | |
1877 HeapRegionClosure* cl) { | |
1878 _hrs->iterate_from(r, cl); | |
1879 } | |
1880 | |
1881 void | |
1882 G1CollectedHeap::heap_region_iterate_from(int idx, HeapRegionClosure* cl) { | |
1883 _hrs->iterate_from(idx, cl); | |
1884 } | |
1885 | |
1886 HeapRegion* G1CollectedHeap::region_at(size_t idx) { return _hrs->at(idx); } | |
1887 | |
1888 void | |
1889 G1CollectedHeap::heap_region_par_iterate_chunked(HeapRegionClosure* cl, | |
1890 int worker, | |
1891 jint claim_value) { | |
355 | 1892 const size_t regions = n_regions(); |
1893 const size_t worker_num = (ParallelGCThreads > 0 ? ParallelGCThreads : 1); | |
1894 // try to spread out the starting points of the workers | |
1895 const size_t start_index = regions / worker_num * (size_t) worker; | |
1896 | |
1897 // each worker will actually look at all regions | |
1898 for (size_t count = 0; count < regions; ++count) { | |
1899 const size_t index = (start_index + count) % regions; | |
1900 assert(0 <= index && index < regions, "sanity"); | |
1901 HeapRegion* r = region_at(index); | |
1902 // we'll ignore "continues humongous" regions (we'll process them | |
1903 // when we come across their corresponding "start humongous" | |
1904 // region) and regions already claimed | |
1905 if (r->claim_value() == claim_value || r->continuesHumongous()) { | |
1906 continue; | |
1907 } | |
1908 // OK, try to claim it | |
342 | 1909 if (r->claimHeapRegion(claim_value)) { |
355 | 1910 // success! |
1911 assert(!r->continuesHumongous(), "sanity"); | |
1912 if (r->startsHumongous()) { | |
1913 // If the region is "starts humongous" we'll iterate over its | |
1914 // "continues humongous" first; in fact we'll do them | |
1915 // first. The order is important. In on case, calling the | |
1916 // closure on the "starts humongous" region might de-allocate | |
1917 // and clear all its "continues humongous" regions and, as a | |
1918 // result, we might end up processing them twice. So, we'll do | |
1919 // them first (notice: most closures will ignore them anyway) and | |
1920 // then we'll do the "starts humongous" region. | |
1921 for (size_t ch_index = index + 1; ch_index < regions; ++ch_index) { | |
1922 HeapRegion* chr = region_at(ch_index); | |
1923 | |
1924 // if the region has already been claimed or it's not | |
1925 // "continues humongous" we're done | |
1926 if (chr->claim_value() == claim_value || | |
1927 !chr->continuesHumongous()) { | |
1928 break; | |
1929 } | |
1930 | |
1931 // Noone should have claimed it directly. We can given | |
1932 // that we claimed its "starts humongous" region. | |
1933 assert(chr->claim_value() != claim_value, "sanity"); | |
1934 assert(chr->humongous_start_region() == r, "sanity"); | |
1935 | |
1936 if (chr->claimHeapRegion(claim_value)) { | |
1937 // we should always be able to claim it; noone else should | |
1938 // be trying to claim this region | |
1939 | |
1940 bool res2 = cl->doHeapRegion(chr); | |
1941 assert(!res2, "Should not abort"); | |
1942 | |
1943 // Right now, this holds (i.e., no closure that actually | |
1944 // does something with "continues humongous" regions | |
1945 // clears them). We might have to weaken it in the future, | |
1946 // but let's leave these two asserts here for extra safety. | |
1947 assert(chr->continuesHumongous(), "should still be the case"); | |
1948 assert(chr->humongous_start_region() == r, "sanity"); | |
1949 } else { | |
1950 guarantee(false, "we should not reach here"); | |
1951 } | |
1952 } | |
1953 } | |
1954 | |
1955 assert(!r->continuesHumongous(), "sanity"); | |
1956 bool res = cl->doHeapRegion(r); | |
1957 assert(!res, "Should not abort"); | |
1958 } | |
1959 } | |
1960 } | |
1961 | |
390 | 1962 class ResetClaimValuesClosure: public HeapRegionClosure { |
1963 public: | |
1964 bool doHeapRegion(HeapRegion* r) { | |
1965 r->set_claim_value(HeapRegion::InitialClaimValue); | |
1966 return false; | |
1967 } | |
1968 }; | |
1969 | |
1970 void | |
1971 G1CollectedHeap::reset_heap_region_claim_values() { | |
1972 ResetClaimValuesClosure blk; | |
1973 heap_region_iterate(&blk); | |
1974 } | |
1975 | |
355 | 1976 #ifdef ASSERT |
1977 // This checks whether all regions in the heap have the correct claim | |
1978 // value. I also piggy-backed on this a check to ensure that the | |
1979 // humongous_start_region() information on "continues humongous" | |
1980 // regions is correct. | |
1981 | |
1982 class CheckClaimValuesClosure : public HeapRegionClosure { | |
1983 private: | |
1984 jint _claim_value; | |
1985 size_t _failures; | |
1986 HeapRegion* _sh_region; | |
1987 public: | |
1988 CheckClaimValuesClosure(jint claim_value) : | |
1989 _claim_value(claim_value), _failures(0), _sh_region(NULL) { } | |
1990 bool doHeapRegion(HeapRegion* r) { | |
1991 if (r->claim_value() != _claim_value) { | |
1992 gclog_or_tty->print_cr("Region ["PTR_FORMAT","PTR_FORMAT"), " | |
1993 "claim value = %d, should be %d", | |
1994 r->bottom(), r->end(), r->claim_value(), | |
1995 _claim_value); | |
1996 ++_failures; | |
1997 } | |
1998 if (!r->isHumongous()) { | |
1999 _sh_region = NULL; | |
2000 } else if (r->startsHumongous()) { | |
2001 _sh_region = r; | |
2002 } else if (r->continuesHumongous()) { | |
2003 if (r->humongous_start_region() != _sh_region) { | |
2004 gclog_or_tty->print_cr("Region ["PTR_FORMAT","PTR_FORMAT"), " | |
2005 "HS = "PTR_FORMAT", should be "PTR_FORMAT, | |
2006 r->bottom(), r->end(), | |
2007 r->humongous_start_region(), | |
2008 _sh_region); | |
2009 ++_failures; | |
342 | 2010 } |
2011 } | |
355 | 2012 return false; |
2013 } | |
2014 size_t failures() { | |
2015 return _failures; | |
2016 } | |
2017 }; | |
2018 | |
2019 bool G1CollectedHeap::check_heap_region_claim_values(jint claim_value) { | |
2020 CheckClaimValuesClosure cl(claim_value); | |
2021 heap_region_iterate(&cl); | |
2022 return cl.failures() == 0; | |
2023 } | |
2024 #endif // ASSERT | |
342 | 2025 |
2026 void G1CollectedHeap::collection_set_iterate(HeapRegionClosure* cl) { | |
2027 HeapRegion* r = g1_policy()->collection_set(); | |
2028 while (r != NULL) { | |
2029 HeapRegion* next = r->next_in_collection_set(); | |
2030 if (cl->doHeapRegion(r)) { | |
2031 cl->incomplete(); | |
2032 return; | |
2033 } | |
2034 r = next; | |
2035 } | |
2036 } | |
2037 | |
2038 void G1CollectedHeap::collection_set_iterate_from(HeapRegion* r, | |
2039 HeapRegionClosure *cl) { | |
2040 assert(r->in_collection_set(), | |
2041 "Start region must be a member of the collection set."); | |
2042 HeapRegion* cur = r; | |
2043 while (cur != NULL) { | |
2044 HeapRegion* next = cur->next_in_collection_set(); | |
2045 if (cl->doHeapRegion(cur) && false) { | |
2046 cl->incomplete(); | |
2047 return; | |
2048 } | |
2049 cur = next; | |
2050 } | |
2051 cur = g1_policy()->collection_set(); | |
2052 while (cur != r) { | |
2053 HeapRegion* next = cur->next_in_collection_set(); | |
2054 if (cl->doHeapRegion(cur) && false) { | |
2055 cl->incomplete(); | |
2056 return; | |
2057 } | |
2058 cur = next; | |
2059 } | |
2060 } | |
2061 | |
2062 CompactibleSpace* G1CollectedHeap::first_compactible_space() { | |
2063 return _hrs->length() > 0 ? _hrs->at(0) : NULL; | |
2064 } | |
2065 | |
2066 | |
2067 Space* G1CollectedHeap::space_containing(const void* addr) const { | |
2068 Space* res = heap_region_containing(addr); | |
2069 if (res == NULL) | |
2070 res = perm_gen()->space_containing(addr); | |
2071 return res; | |
2072 } | |
2073 | |
2074 HeapWord* G1CollectedHeap::block_start(const void* addr) const { | |
2075 Space* sp = space_containing(addr); | |
2076 if (sp != NULL) { | |
2077 return sp->block_start(addr); | |
2078 } | |
2079 return NULL; | |
2080 } | |
2081 | |
2082 size_t G1CollectedHeap::block_size(const HeapWord* addr) const { | |
2083 Space* sp = space_containing(addr); | |
2084 assert(sp != NULL, "block_size of address outside of heap"); | |
2085 return sp->block_size(addr); | |
2086 } | |
2087 | |
2088 bool G1CollectedHeap::block_is_obj(const HeapWord* addr) const { | |
2089 Space* sp = space_containing(addr); | |
2090 return sp->block_is_obj(addr); | |
2091 } | |
2092 | |
2093 bool G1CollectedHeap::supports_tlab_allocation() const { | |
2094 return true; | |
2095 } | |
2096 | |
2097 size_t G1CollectedHeap::tlab_capacity(Thread* ignored) const { | |
2098 return HeapRegion::GrainBytes; | |
2099 } | |
2100 | |
2101 size_t G1CollectedHeap::unsafe_max_tlab_alloc(Thread* ignored) const { | |
2102 // Return the remaining space in the cur alloc region, but not less than | |
2103 // the min TLAB size. | |
2104 // Also, no more than half the region size, since we can't allow tlabs to | |
2105 // grow big enough to accomodate humongous objects. | |
2106 | |
2107 // We need to story it locally, since it might change between when we | |
2108 // test for NULL and when we use it later. | |
2109 ContiguousSpace* cur_alloc_space = _cur_alloc_region; | |
2110 if (cur_alloc_space == NULL) { | |
2111 return HeapRegion::GrainBytes/2; | |
2112 } else { | |
2113 return MAX2(MIN2(cur_alloc_space->free(), | |
2114 (size_t)(HeapRegion::GrainBytes/2)), | |
2115 (size_t)MinTLABSize); | |
2116 } | |
2117 } | |
2118 | |
2119 HeapWord* G1CollectedHeap::allocate_new_tlab(size_t size) { | |
2120 bool dummy; | |
2121 return G1CollectedHeap::mem_allocate(size, false, true, &dummy); | |
2122 } | |
2123 | |
2124 bool G1CollectedHeap::allocs_are_zero_filled() { | |
2125 return false; | |
2126 } | |
2127 | |
2128 size_t G1CollectedHeap::large_typearray_limit() { | |
2129 // FIXME | |
2130 return HeapRegion::GrainBytes/HeapWordSize; | |
2131 } | |
2132 | |
2133 size_t G1CollectedHeap::max_capacity() const { | |
1092
ed52bcc32739
6880903: G1: G1 reports incorrect Runtime.maxMemory()
tonyp
parents:
1089
diff
changeset
|
2134 return g1_reserved_obj_bytes(); |
342 | 2135 } |
2136 | |
2137 jlong G1CollectedHeap::millis_since_last_gc() { | |
2138 // assert(false, "NYI"); | |
2139 return 0; | |
2140 } | |
2141 | |
2142 | |
2143 void G1CollectedHeap::prepare_for_verify() { | |
2144 if (SafepointSynchronize::is_at_safepoint() || ! UseTLAB) { | |
2145 ensure_parsability(false); | |
2146 } | |
2147 g1_rem_set()->prepare_for_verify(); | |
2148 } | |
2149 | |
2150 class VerifyLivenessOopClosure: public OopClosure { | |
2151 G1CollectedHeap* g1h; | |
2152 public: | |
2153 VerifyLivenessOopClosure(G1CollectedHeap* _g1h) { | |
2154 g1h = _g1h; | |
2155 } | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2156 void do_oop(narrowOop *p) { do_oop_work(p); } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2157 void do_oop( oop *p) { do_oop_work(p); } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2158 |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2159 template <class T> void do_oop_work(T *p) { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2160 oop obj = oopDesc::load_decode_heap_oop(p); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2161 guarantee(obj == NULL || !g1h->is_obj_dead(obj), |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2162 "Dead object referenced by a not dead object"); |
342 | 2163 } |
2164 }; | |
2165 | |
2166 class VerifyObjsInRegionClosure: public ObjectClosure { | |
811 | 2167 private: |
342 | 2168 G1CollectedHeap* _g1h; |
2169 size_t _live_bytes; | |
2170 HeapRegion *_hr; | |
811 | 2171 bool _use_prev_marking; |
342 | 2172 public: |
811 | 2173 // use_prev_marking == true -> use "prev" marking information, |
2174 // use_prev_marking == false -> use "next" marking information | |
2175 VerifyObjsInRegionClosure(HeapRegion *hr, bool use_prev_marking) | |
2176 : _live_bytes(0), _hr(hr), _use_prev_marking(use_prev_marking) { | |
342 | 2177 _g1h = G1CollectedHeap::heap(); |
2178 } | |
2179 void do_object(oop o) { | |
2180 VerifyLivenessOopClosure isLive(_g1h); | |
2181 assert(o != NULL, "Huh?"); | |
811 | 2182 if (!_g1h->is_obj_dead_cond(o, _use_prev_marking)) { |
342 | 2183 o->oop_iterate(&isLive); |
2184 if (!_hr->obj_allocated_since_prev_marking(o)) | |
2185 _live_bytes += (o->size() * HeapWordSize); | |
2186 } | |
2187 } | |
2188 size_t live_bytes() { return _live_bytes; } | |
2189 }; | |
2190 | |
2191 class PrintObjsInRegionClosure : public ObjectClosure { | |
2192 HeapRegion *_hr; | |
2193 G1CollectedHeap *_g1; | |
2194 public: | |
2195 PrintObjsInRegionClosure(HeapRegion *hr) : _hr(hr) { | |
2196 _g1 = G1CollectedHeap::heap(); | |
2197 }; | |
2198 | |
2199 void do_object(oop o) { | |
2200 if (o != NULL) { | |
2201 HeapWord *start = (HeapWord *) o; | |
2202 size_t word_sz = o->size(); | |
2203 gclog_or_tty->print("\nPrinting obj "PTR_FORMAT" of size " SIZE_FORMAT | |
2204 " isMarkedPrev %d isMarkedNext %d isAllocSince %d\n", | |
2205 (void*) o, word_sz, | |
2206 _g1->isMarkedPrev(o), | |
2207 _g1->isMarkedNext(o), | |
2208 _hr->obj_allocated_since_prev_marking(o)); | |
2209 HeapWord *end = start + word_sz; | |
2210 HeapWord *cur; | |
2211 int *val; | |
2212 for (cur = start; cur < end; cur++) { | |
2213 val = (int *) cur; | |
2214 gclog_or_tty->print("\t "PTR_FORMAT":"PTR_FORMAT"\n", val, *val); | |
2215 } | |
2216 } | |
2217 } | |
2218 }; | |
2219 | |
2220 class VerifyRegionClosure: public HeapRegionClosure { | |
811 | 2221 private: |
342 | 2222 bool _allow_dirty; |
390 | 2223 bool _par; |
811 | 2224 bool _use_prev_marking; |
1020
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2225 bool _failures; |
811 | 2226 public: |
2227 // use_prev_marking == true -> use "prev" marking information, | |
2228 // use_prev_marking == false -> use "next" marking information | |
2229 VerifyRegionClosure(bool allow_dirty, bool par, bool use_prev_marking) | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2230 : _allow_dirty(allow_dirty), |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2231 _par(par), |
1020
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2232 _use_prev_marking(use_prev_marking), |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2233 _failures(false) {} |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2234 |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2235 bool failures() { |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2236 return _failures; |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2237 } |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2238 |
342 | 2239 bool doHeapRegion(HeapRegion* r) { |
390 | 2240 guarantee(_par || r->claim_value() == HeapRegion::InitialClaimValue, |
2241 "Should be unclaimed at verify points."); | |
637
25e146966e7c
6817419: G1: Enable extensive verification for humongous regions
iveresov
parents:
636
diff
changeset
|
2242 if (!r->continuesHumongous()) { |
1020
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2243 bool failures = false; |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2244 r->verify(_allow_dirty, _use_prev_marking, &failures); |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2245 if (failures) { |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2246 _failures = true; |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2247 } else { |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2248 VerifyObjsInRegionClosure not_dead_yet_cl(r, _use_prev_marking); |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2249 r->object_iterate(¬_dead_yet_cl); |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2250 if (r->max_live_bytes() < not_dead_yet_cl.live_bytes()) { |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2251 gclog_or_tty->print_cr("["PTR_FORMAT","PTR_FORMAT"] " |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2252 "max_live_bytes "SIZE_FORMAT" " |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2253 "< calculated "SIZE_FORMAT, |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2254 r->bottom(), r->end(), |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2255 r->max_live_bytes(), |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2256 not_dead_yet_cl.live_bytes()); |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2257 _failures = true; |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2258 } |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2259 } |
342 | 2260 } |
1020
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2261 return false; // stop the region iteration if we hit a failure |
342 | 2262 } |
2263 }; | |
2264 | |
2265 class VerifyRootsClosure: public OopsInGenClosure { | |
2266 private: | |
2267 G1CollectedHeap* _g1h; | |
1020
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2268 bool _use_prev_marking; |
342 | 2269 bool _failures; |
2270 public: | |
811 | 2271 // use_prev_marking == true -> use "prev" marking information, |
2272 // use_prev_marking == false -> use "next" marking information | |
2273 VerifyRootsClosure(bool use_prev_marking) : | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2274 _g1h(G1CollectedHeap::heap()), |
1020
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2275 _use_prev_marking(use_prev_marking), |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2276 _failures(false) { } |
342 | 2277 |
2278 bool failures() { return _failures; } | |
2279 | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2280 template <class T> void do_oop_nv(T* p) { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2281 T heap_oop = oopDesc::load_heap_oop(p); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2282 if (!oopDesc::is_null(heap_oop)) { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2283 oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); |
811 | 2284 if (_g1h->is_obj_dead_cond(obj, _use_prev_marking)) { |
342 | 2285 gclog_or_tty->print_cr("Root location "PTR_FORMAT" " |
1020
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2286 "points to dead obj "PTR_FORMAT, p, (void*) obj); |
342 | 2287 obj->print_on(gclog_or_tty); |
2288 _failures = true; | |
2289 } | |
2290 } | |
2291 } | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2292 |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2293 void do_oop(oop* p) { do_oop_nv(p); } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2294 void do_oop(narrowOop* p) { do_oop_nv(p); } |
342 | 2295 }; |
2296 | |
390 | 2297 // This is the task used for parallel heap verification. |
2298 | |
2299 class G1ParVerifyTask: public AbstractGangTask { | |
2300 private: | |
2301 G1CollectedHeap* _g1h; | |
2302 bool _allow_dirty; | |
811 | 2303 bool _use_prev_marking; |
1020
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2304 bool _failures; |
390 | 2305 |
2306 public: | |
811 | 2307 // use_prev_marking == true -> use "prev" marking information, |
2308 // use_prev_marking == false -> use "next" marking information | |
2309 G1ParVerifyTask(G1CollectedHeap* g1h, bool allow_dirty, | |
2310 bool use_prev_marking) : | |
390 | 2311 AbstractGangTask("Parallel verify task"), |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2312 _g1h(g1h), |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2313 _allow_dirty(allow_dirty), |
1020
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2314 _use_prev_marking(use_prev_marking), |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2315 _failures(false) { } |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2316 |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2317 bool failures() { |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2318 return _failures; |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2319 } |
390 | 2320 |
2321 void work(int worker_i) { | |
637
25e146966e7c
6817419: G1: Enable extensive verification for humongous regions
iveresov
parents:
636
diff
changeset
|
2322 HandleMark hm; |
811 | 2323 VerifyRegionClosure blk(_allow_dirty, true, _use_prev_marking); |
390 | 2324 _g1h->heap_region_par_iterate_chunked(&blk, worker_i, |
2325 HeapRegion::ParVerifyClaimValue); | |
1020
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2326 if (blk.failures()) { |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2327 _failures = true; |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2328 } |
390 | 2329 } |
2330 }; | |
2331 | |
342 | 2332 void G1CollectedHeap::verify(bool allow_dirty, bool silent) { |
811 | 2333 verify(allow_dirty, silent, /* use_prev_marking */ true); |
2334 } | |
2335 | |
2336 void G1CollectedHeap::verify(bool allow_dirty, | |
2337 bool silent, | |
2338 bool use_prev_marking) { | |
342 | 2339 if (SafepointSynchronize::is_at_safepoint() || ! UseTLAB) { |
2340 if (!silent) { gclog_or_tty->print("roots "); } | |
811 | 2341 VerifyRootsClosure rootsCl(use_prev_marking); |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
890
diff
changeset
|
2342 CodeBlobToOopClosure blobsCl(&rootsCl, /*do_marking=*/ false); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
890
diff
changeset
|
2343 process_strong_roots(true, // activate StrongRootsScope |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
890
diff
changeset
|
2344 false, |
342 | 2345 SharedHeap::SO_AllClasses, |
2346 &rootsCl, | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
890
diff
changeset
|
2347 &blobsCl, |
342 | 2348 &rootsCl); |
1020
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2349 bool failures = rootsCl.failures(); |
342 | 2350 rem_set()->invalidate(perm_gen()->used_region(), false); |
2351 if (!silent) { gclog_or_tty->print("heapRegions "); } | |
390 | 2352 if (GCParallelVerificationEnabled && ParallelGCThreads > 1) { |
2353 assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue), | |
2354 "sanity check"); | |
2355 | |
811 | 2356 G1ParVerifyTask task(this, allow_dirty, use_prev_marking); |
390 | 2357 int n_workers = workers()->total_workers(); |
2358 set_par_threads(n_workers); | |
2359 workers()->run_task(&task); | |
2360 set_par_threads(0); | |
1020
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2361 if (task.failures()) { |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2362 failures = true; |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2363 } |
390 | 2364 |
2365 assert(check_heap_region_claim_values(HeapRegion::ParVerifyClaimValue), | |
2366 "sanity check"); | |
2367 | |
2368 reset_heap_region_claim_values(); | |
2369 | |
2370 assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue), | |
2371 "sanity check"); | |
2372 } else { | |
811 | 2373 VerifyRegionClosure blk(allow_dirty, false, use_prev_marking); |
390 | 2374 _hrs->iterate(&blk); |
1020
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2375 if (blk.failures()) { |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2376 failures = true; |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2377 } |
390 | 2378 } |
342 | 2379 if (!silent) gclog_or_tty->print("remset "); |
2380 rem_set()->verify(); | |
1020
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2381 |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2382 if (failures) { |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2383 gclog_or_tty->print_cr("Heap:"); |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2384 print_on(gclog_or_tty, true /* extended */); |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2385 gclog_or_tty->print_cr(""); |
1044 | 2386 if (VerifyDuringGC && G1VerifyDuringGCPrintReachable) { |
2387 concurrent_mark()->print_reachable(use_prev_marking, | |
2388 "failed-verification"); | |
1020
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2389 } |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2390 gclog_or_tty->flush(); |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2391 } |
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2392 guarantee(!failures, "there should not have been any failures"); |
342 | 2393 } else { |
2394 if (!silent) gclog_or_tty->print("(SKIPPING roots, heapRegions, remset) "); | |
2395 } | |
2396 } | |
2397 | |
2398 class PrintRegionClosure: public HeapRegionClosure { | |
2399 outputStream* _st; | |
2400 public: | |
2401 PrintRegionClosure(outputStream* st) : _st(st) {} | |
2402 bool doHeapRegion(HeapRegion* r) { | |
2403 r->print_on(_st); | |
2404 return false; | |
2405 } | |
2406 }; | |
2407 | |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2408 void G1CollectedHeap::print() const { print_on(tty); } |
342 | 2409 |
2410 void G1CollectedHeap::print_on(outputStream* st) const { | |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2411 print_on(st, PrintHeapAtGCExtended); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2412 } |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2413 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2414 void G1CollectedHeap::print_on(outputStream* st, bool extended) const { |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2415 st->print(" %-20s", "garbage-first heap"); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2416 st->print(" total " SIZE_FORMAT "K, used " SIZE_FORMAT "K", |
846
42d84bbbecf4
6859911: G1: assert(Heap_lock->owner() = NULL, "Should be owned on this thread's behalf")
tonyp
parents:
845
diff
changeset
|
2417 capacity()/K, used_unlocked()/K); |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2418 st->print(" [" INTPTR_FORMAT ", " INTPTR_FORMAT ", " INTPTR_FORMAT ")", |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2419 _g1_storage.low_boundary(), |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2420 _g1_storage.high(), |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2421 _g1_storage.high_boundary()); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2422 st->cr(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2423 st->print(" region size " SIZE_FORMAT "K, ", |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2424 HeapRegion::GrainBytes/K); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2425 size_t young_regions = _young_list->length(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2426 st->print(SIZE_FORMAT " young (" SIZE_FORMAT "K), ", |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2427 young_regions, young_regions * HeapRegion::GrainBytes / K); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2428 size_t survivor_regions = g1_policy()->recorded_survivor_regions(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2429 st->print(SIZE_FORMAT " survivors (" SIZE_FORMAT "K)", |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2430 survivor_regions, survivor_regions * HeapRegion::GrainBytes / K); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2431 st->cr(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2432 perm()->as_gen()->print_on(st); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2433 if (extended) { |
1020
ff2402f6a50b
6882730: G1: parallel heap verification messes up region dump
tonyp
parents:
1019
diff
changeset
|
2434 st->cr(); |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2435 print_on_extended(st); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2436 } |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2437 } |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2438 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2439 void G1CollectedHeap::print_on_extended(outputStream* st) const { |
342 | 2440 PrintRegionClosure blk(st); |
2441 _hrs->iterate(&blk); | |
2442 } | |
2443 | |
2444 void G1CollectedHeap::print_gc_threads_on(outputStream* st) const { | |
2445 if (ParallelGCThreads > 0) { | |
1019 | 2446 workers()->print_worker_threads_on(st); |
2447 } | |
2448 | |
2449 _cmThread->print_on(st); | |
342 | 2450 st->cr(); |
1019 | 2451 |
2452 _cm->print_worker_threads_on(st); | |
2453 | |
2454 _cg1r->print_worker_threads_on(st); | |
2455 | |
342 | 2456 _czft->print_on(st); |
2457 st->cr(); | |
2458 } | |
2459 | |
2460 void G1CollectedHeap::gc_threads_do(ThreadClosure* tc) const { | |
2461 if (ParallelGCThreads > 0) { | |
2462 workers()->threads_do(tc); | |
2463 } | |
2464 tc->do_thread(_cmThread); | |
794 | 2465 _cg1r->threads_do(tc); |
342 | 2466 tc->do_thread(_czft); |
2467 } | |
2468 | |
2469 void G1CollectedHeap::print_tracing_info() const { | |
2470 // We'll overload this to mean "trace GC pause statistics." | |
2471 if (TraceGen0Time || TraceGen1Time) { | |
2472 // The "G1CollectorPolicy" is keeping track of these stats, so delegate | |
2473 // to that. | |
2474 g1_policy()->print_tracing_info(); | |
2475 } | |
751 | 2476 if (G1SummarizeRSetStats) { |
342 | 2477 g1_rem_set()->print_summary_info(); |
2478 } | |
751 | 2479 if (G1SummarizeConcurrentMark) { |
342 | 2480 concurrent_mark()->print_summary_info(); |
2481 } | |
751 | 2482 if (G1SummarizeZFStats) { |
342 | 2483 ConcurrentZFThread::print_summary_info(); |
2484 } | |
2485 g1_policy()->print_yg_surv_rate_info(); | |
2486 | |
2487 SpecializationStats::print(); | |
2488 } | |
2489 | |
2490 | |
2491 int G1CollectedHeap::addr_to_arena_id(void* addr) const { | |
2492 HeapRegion* hr = heap_region_containing(addr); | |
2493 if (hr == NULL) { | |
2494 return 0; | |
2495 } else { | |
2496 return 1; | |
2497 } | |
2498 } | |
2499 | |
2500 G1CollectedHeap* G1CollectedHeap::heap() { | |
2501 assert(_sh->kind() == CollectedHeap::G1CollectedHeap, | |
2502 "not a garbage-first heap"); | |
2503 return _g1h; | |
2504 } | |
2505 | |
2506 void G1CollectedHeap::gc_prologue(bool full /* Ignored */) { | |
2507 assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer"); | |
2508 // Call allocation profiler | |
2509 AllocationProfiler::iterate_since_last_gc(); | |
2510 // Fill TLAB's and such | |
2511 ensure_parsability(true); | |
2512 } | |
2513 | |
2514 void G1CollectedHeap::gc_epilogue(bool full /* Ignored */) { | |
2515 // FIXME: what is this about? | |
2516 // I'm ignoring the "fill_newgen()" call if "alloc_event_enabled" | |
2517 // is set. | |
2518 COMPILER2_PRESENT(assert(DerivedPointerTable::is_empty(), | |
2519 "derived pointer present")); | |
2520 } | |
2521 | |
2522 void G1CollectedHeap::do_collection_pause() { | |
2523 // Read the GC count while holding the Heap_lock | |
2524 // we need to do this _before_ wait_for_cleanup_complete(), to | |
2525 // ensure that we do not give up the heap lock and potentially | |
2526 // pick up the wrong count | |
2527 int gc_count_before = SharedHeap::heap()->total_collections(); | |
2528 | |
2529 // Don't want to do a GC pause while cleanup is being completed! | |
2530 wait_for_cleanup_complete(); | |
2531 | |
2532 g1_policy()->record_stop_world_start(); | |
2533 { | |
2534 MutexUnlocker mu(Heap_lock); // give up heap lock, execute gets it back | |
2535 VM_G1IncCollectionPause op(gc_count_before); | |
2536 VMThread::execute(&op); | |
2537 } | |
2538 } | |
2539 | |
2540 void | |
2541 G1CollectedHeap::doConcurrentMark() { | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2542 MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2543 if (!_cmThread->in_progress()) { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2544 _cmThread->set_started(); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2545 CGC_lock->notify(); |
342 | 2546 } |
2547 } | |
2548 | |
2549 class VerifyMarkedObjsClosure: public ObjectClosure { | |
2550 G1CollectedHeap* _g1h; | |
2551 public: | |
2552 VerifyMarkedObjsClosure(G1CollectedHeap* g1h) : _g1h(g1h) {} | |
2553 void do_object(oop obj) { | |
2554 assert(obj->mark()->is_marked() ? !_g1h->is_obj_dead(obj) : true, | |
2555 "markandsweep mark should agree with concurrent deadness"); | |
2556 } | |
2557 }; | |
2558 | |
2559 void | |
2560 G1CollectedHeap::checkConcurrentMark() { | |
2561 VerifyMarkedObjsClosure verifycl(this); | |
2562 // MutexLockerEx x(getMarkBitMapLock(), | |
2563 // Mutex::_no_safepoint_check_flag); | |
678 | 2564 object_iterate(&verifycl, false); |
342 | 2565 } |
2566 | |
2567 void G1CollectedHeap::do_sync_mark() { | |
2568 _cm->checkpointRootsInitial(); | |
2569 _cm->markFromRoots(); | |
2570 _cm->checkpointRootsFinal(false); | |
2571 } | |
2572 | |
2573 // <NEW PREDICTION> | |
2574 | |
2575 double G1CollectedHeap::predict_region_elapsed_time_ms(HeapRegion *hr, | |
2576 bool young) { | |
2577 return _g1_policy->predict_region_elapsed_time_ms(hr, young); | |
2578 } | |
2579 | |
2580 void G1CollectedHeap::check_if_region_is_too_expensive(double | |
2581 predicted_time_ms) { | |
2582 _g1_policy->check_if_region_is_too_expensive(predicted_time_ms); | |
2583 } | |
2584 | |
2585 size_t G1CollectedHeap::pending_card_num() { | |
2586 size_t extra_cards = 0; | |
2587 JavaThread *curr = Threads::first(); | |
2588 while (curr != NULL) { | |
2589 DirtyCardQueue& dcq = curr->dirty_card_queue(); | |
2590 extra_cards += dcq.size(); | |
2591 curr = curr->next(); | |
2592 } | |
2593 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); | |
2594 size_t buffer_size = dcqs.buffer_size(); | |
2595 size_t buffer_num = dcqs.completed_buffers_num(); | |
2596 return buffer_size * buffer_num + extra_cards; | |
2597 } | |
2598 | |
2599 size_t G1CollectedHeap::max_pending_card_num() { | |
2600 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); | |
2601 size_t buffer_size = dcqs.buffer_size(); | |
2602 size_t buffer_num = dcqs.completed_buffers_num(); | |
2603 int thread_num = Threads::number_of_threads(); | |
2604 return (buffer_num + thread_num) * buffer_size; | |
2605 } | |
2606 | |
2607 size_t G1CollectedHeap::cards_scanned() { | |
2608 HRInto_G1RemSet* g1_rset = (HRInto_G1RemSet*) g1_rem_set(); | |
2609 return g1_rset->cardsScanned(); | |
2610 } | |
2611 | |
2612 void | |
2613 G1CollectedHeap::setup_surviving_young_words() { | |
2614 guarantee( _surviving_young_words == NULL, "pre-condition" ); | |
2615 size_t array_length = g1_policy()->young_cset_length(); | |
2616 _surviving_young_words = NEW_C_HEAP_ARRAY(size_t, array_length); | |
2617 if (_surviving_young_words == NULL) { | |
2618 vm_exit_out_of_memory(sizeof(size_t) * array_length, | |
2619 "Not enough space for young surv words summary."); | |
2620 } | |
2621 memset(_surviving_young_words, 0, array_length * sizeof(size_t)); | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2622 #ifdef ASSERT |
342 | 2623 for (size_t i = 0; i < array_length; ++i) { |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2624 assert( _surviving_young_words[i] == 0, "memset above" ); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2625 } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2626 #endif // !ASSERT |
342 | 2627 } |
2628 | |
2629 void | |
2630 G1CollectedHeap::update_surviving_young_words(size_t* surv_young_words) { | |
2631 MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag); | |
2632 size_t array_length = g1_policy()->young_cset_length(); | |
2633 for (size_t i = 0; i < array_length; ++i) | |
2634 _surviving_young_words[i] += surv_young_words[i]; | |
2635 } | |
2636 | |
2637 void | |
2638 G1CollectedHeap::cleanup_surviving_young_words() { | |
2639 guarantee( _surviving_young_words != NULL, "pre-condition" ); | |
2640 FREE_C_HEAP_ARRAY(size_t, _surviving_young_words); | |
2641 _surviving_young_words = NULL; | |
2642 } | |
2643 | |
2644 // </NEW PREDICTION> | |
2645 | |
2646 void | |
677 | 2647 G1CollectedHeap::do_collection_pause_at_safepoint() { |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2648 if (PrintHeapAtGC) { |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2649 Universe::print_heap_before_gc(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2650 } |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2651 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2652 { |
1089
db0d5eba9d20
6815790: G1: Missing MemoryPoolMXBeans with -XX:+UseG1GC
tonyp
parents:
1088
diff
changeset
|
2653 ResourceMark rm; |
db0d5eba9d20
6815790: G1: Missing MemoryPoolMXBeans with -XX:+UseG1GC
tonyp
parents:
1088
diff
changeset
|
2654 |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2655 char verbose_str[128]; |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2656 sprintf(verbose_str, "GC pause "); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2657 if (g1_policy()->in_young_gc_mode()) { |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2658 if (g1_policy()->full_young_gcs()) |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2659 strcat(verbose_str, "(young)"); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2660 else |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2661 strcat(verbose_str, "(partial)"); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2662 } |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2663 if (g1_policy()->should_initiate_conc_mark()) |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2664 strcat(verbose_str, " (initial-mark)"); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2665 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2666 // if PrintGCDetails is on, we'll print long statistics information |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2667 // in the collector policy code, so let's not print this as the output |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2668 // is messy if we do. |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2669 gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2670 TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2671 TraceTime t(verbose_str, PrintGC && !PrintGCDetails, true, gclog_or_tty); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2672 |
1089
db0d5eba9d20
6815790: G1: Missing MemoryPoolMXBeans with -XX:+UseG1GC
tonyp
parents:
1088
diff
changeset
|
2673 TraceMemoryManagerStats tms(false /* fullGC */); |
db0d5eba9d20
6815790: G1: Missing MemoryPoolMXBeans with -XX:+UseG1GC
tonyp
parents:
1088
diff
changeset
|
2674 |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2675 assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint"); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2676 assert(Thread::current() == VMThread::vm_thread(), "should be in vm thread"); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2677 guarantee(!is_gc_active(), "collection is not reentrant"); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2678 assert(regions_accounted_for(), "Region leakage!"); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2679 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2680 increment_gc_time_stamp(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2681 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2682 if (g1_policy()->in_young_gc_mode()) { |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2683 assert(check_young_list_well_formed(), |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2684 "young list should be well formed"); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2685 } |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2686 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2687 if (GC_locker::is_active()) { |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2688 return; // GC is disabled (e.g. JNI GetXXXCritical operation) |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2689 } |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2690 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2691 bool abandoned = false; |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2692 { // Call to jvmpi::post_class_unload_events must occur outside of active GC |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2693 IsGCActiveMark x; |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2694 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2695 gc_prologue(false); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2696 increment_total_collections(false /* full gc */); |
342 | 2697 |
2698 #if G1_REM_SET_LOGGING | |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2699 gclog_or_tty->print_cr("\nJust chose CS, heap:"); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2700 print(); |
342 | 2701 #endif |
2702 | |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2703 if (VerifyBeforeGC && total_collections() >= VerifyGCStartAt) { |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2704 HandleMark hm; // Discard invalid handles created during verification |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2705 prepare_for_verify(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2706 gclog_or_tty->print(" VerifyBeforeGC:"); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2707 Universe::verify(false); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2708 } |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2709 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2710 COMPILER2_PRESENT(DerivedPointerTable::clear()); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2711 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2712 // We want to turn off ref discovery, if necessary, and turn it back on |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2713 // on again later if we do. XXX Dubious: why is discovery disabled? |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2714 bool was_enabled = ref_processor()->discovery_enabled(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2715 if (was_enabled) ref_processor()->disable_discovery(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2716 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2717 // Forget the current alloc region (we might even choose it to be part |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2718 // of the collection set!). |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2719 abandon_cur_alloc_region(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2720 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2721 // The elapsed time induced by the start time below deliberately elides |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2722 // the possible verification above. |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2723 double start_time_sec = os::elapsedTime(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2724 size_t start_used_bytes = used(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2725 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2726 g1_policy()->record_collection_pause_start(start_time_sec, |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2727 start_used_bytes); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2728 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2729 guarantee(_in_cset_fast_test == NULL, "invariant"); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2730 guarantee(_in_cset_fast_test_base == NULL, "invariant"); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2731 _in_cset_fast_test_length = max_regions(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2732 _in_cset_fast_test_base = |
526 | 2733 NEW_C_HEAP_ARRAY(bool, _in_cset_fast_test_length); |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2734 memset(_in_cset_fast_test_base, false, |
526 | 2735 _in_cset_fast_test_length * sizeof(bool)); |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2736 // We're biasing _in_cset_fast_test to avoid subtracting the |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2737 // beginning of the heap every time we want to index; basically |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2738 // it's the same with what we do with the card table. |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2739 _in_cset_fast_test = _in_cset_fast_test_base - |
526 | 2740 ((size_t) _g1_reserved.start() >> HeapRegion::LogOfHRGrainBytes); |
2741 | |
342 | 2742 #if SCAN_ONLY_VERBOSE |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2743 _young_list->print(); |
342 | 2744 #endif // SCAN_ONLY_VERBOSE |
2745 | |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2746 if (g1_policy()->should_initiate_conc_mark()) { |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2747 concurrent_mark()->checkpointRootsInitialPre(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2748 } |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2749 save_marks(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2750 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2751 // We must do this before any possible evacuation that should propagate |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2752 // marks. |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2753 if (mark_in_progress()) { |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2754 double start_time_sec = os::elapsedTime(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2755 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2756 _cm->drainAllSATBBuffers(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2757 double finish_mark_ms = (os::elapsedTime() - start_time_sec) * 1000.0; |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2758 g1_policy()->record_satb_drain_time(finish_mark_ms); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2759 } |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2760 // Record the number of elements currently on the mark stack, so we |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2761 // only iterate over these. (Since evacuation may add to the mark |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2762 // stack, doing more exposes race conditions.) If no mark is in |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2763 // progress, this will be zero. |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2764 _cm->set_oops_do_bound(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2765 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2766 assert(regions_accounted_for(), "Region leakage."); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2767 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2768 if (mark_in_progress()) |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2769 concurrent_mark()->newCSet(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2770 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2771 // Now choose the CS. |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2772 g1_policy()->choose_collection_set(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2773 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2774 // We may abandon a pause if we find no region that will fit in the MMU |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2775 // pause. |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2776 bool abandoned = (g1_policy()->collection_set() == NULL); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2777 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2778 // Nothing to do if we were unable to choose a collection set. |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2779 if (!abandoned) { |
342 | 2780 #if G1_REM_SET_LOGGING |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2781 gclog_or_tty->print_cr("\nAfter pause, heap:"); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2782 print(); |
342 | 2783 #endif |
2784 | |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2785 setup_surviving_young_words(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2786 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2787 // Set up the gc allocation regions. |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2788 get_gc_alloc_regions(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2789 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2790 // Actually do the work... |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2791 evacuate_collection_set(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2792 free_collection_set(g1_policy()->collection_set()); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2793 g1_policy()->clear_collection_set(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2794 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2795 FREE_C_HEAP_ARRAY(bool, _in_cset_fast_test_base); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2796 // this is more for peace of mind; we're nulling them here and |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2797 // we're expecting them to be null at the beginning of the next GC |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2798 _in_cset_fast_test = NULL; |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2799 _in_cset_fast_test_base = NULL; |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2800 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2801 cleanup_surviving_young_words(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2802 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2803 if (g1_policy()->in_young_gc_mode()) { |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2804 _young_list->reset_sampled_info(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2805 assert(check_young_list_empty(true), |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2806 "young list should be empty"); |
342 | 2807 |
2808 #if SCAN_ONLY_VERBOSE | |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2809 _young_list->print(); |
342 | 2810 #endif // SCAN_ONLY_VERBOSE |
2811 | |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2812 g1_policy()->record_survivor_regions(_young_list->survivor_length(), |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2813 _young_list->first_survivor_region(), |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2814 _young_list->last_survivor_region()); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2815 _young_list->reset_auxilary_lists(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2816 } |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2817 } else { |
1088
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
2818 if (_in_cset_fast_test != NULL) { |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
2819 assert(_in_cset_fast_test_base != NULL, "Since _in_cset_fast_test isn't"); |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
2820 FREE_C_HEAP_ARRAY(bool, _in_cset_fast_test_base); |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
2821 // this is more for peace of mind; we're nulling them here and |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
2822 // we're expecting them to be null at the beginning of the next GC |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
2823 _in_cset_fast_test = NULL; |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
2824 _in_cset_fast_test_base = NULL; |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
2825 } |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
2826 // This looks confusing, because the DPT should really be empty |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
2827 // at this point -- since we have not done any collection work, |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
2828 // there should not be any derived pointers in the table to update; |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
2829 // however, there is some additional state in the DPT which is |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
2830 // reset at the end of the (null) "gc" here via the following call. |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
2831 // A better approach might be to split off that state resetting work |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
2832 // into a separate method that asserts that the DPT is empty and call |
3fc996d4edd2
6902303: G1: ScavengeALot should cause an incremental, rather than a full, collection
ysr
parents:
1045
diff
changeset
|
2833 // that here. That is deferred for now. |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2834 COMPILER2_PRESENT(DerivedPointerTable::update_pointers()); |
342 | 2835 } |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2836 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2837 if (evacuation_failed()) { |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2838 _summary_bytes_used = recalculate_used(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2839 } else { |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2840 // The "used" of the the collection set have already been subtracted |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2841 // when they were freed. Add in the bytes evacuated. |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2842 _summary_bytes_used += g1_policy()->bytes_in_to_space(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2843 } |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2844 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2845 if (g1_policy()->in_young_gc_mode() && |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2846 g1_policy()->should_initiate_conc_mark()) { |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2847 concurrent_mark()->checkpointRootsInitialPost(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2848 set_marking_started(); |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2849 // CAUTION: after the doConcurrentMark() call below, |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2850 // the concurrent marking thread(s) could be running |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2851 // concurrently with us. Make sure that anything after |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2852 // this point does not assume that we are the only GC thread |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2853 // running. Note: of course, the actual marking work will |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2854 // not start until the safepoint itself is released in |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
2855 // ConcurrentGCThread::safepoint_desynchronize(). |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2856 doConcurrentMark(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2857 } |
342 | 2858 |
2859 #if SCAN_ONLY_VERBOSE | |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2860 _young_list->print(); |
342 | 2861 #endif // SCAN_ONLY_VERBOSE |
2862 | |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2863 double end_time_sec = os::elapsedTime(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2864 double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS; |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2865 g1_policy()->record_pause_time_ms(pause_time_ms); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2866 g1_policy()->record_collection_pause_end(abandoned); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2867 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2868 assert(regions_accounted_for(), "Region leakage."); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2869 |
1089
db0d5eba9d20
6815790: G1: Missing MemoryPoolMXBeans with -XX:+UseG1GC
tonyp
parents:
1088
diff
changeset
|
2870 MemoryService::track_memory_usage(); |
db0d5eba9d20
6815790: G1: Missing MemoryPoolMXBeans with -XX:+UseG1GC
tonyp
parents:
1088
diff
changeset
|
2871 |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2872 if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) { |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2873 HandleMark hm; // Discard invalid handles created during verification |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2874 gclog_or_tty->print(" VerifyAfterGC:"); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2875 prepare_for_verify(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2876 Universe::verify(false); |
342 | 2877 } |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2878 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2879 if (was_enabled) ref_processor()->enable_discovery(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2880 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2881 { |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2882 size_t expand_bytes = g1_policy()->expansion_amount(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2883 if (expand_bytes > 0) { |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2884 size_t bytes_before = capacity(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2885 expand(expand_bytes); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2886 } |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2887 } |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2888 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2889 if (mark_in_progress()) { |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2890 concurrent_mark()->update_g1_committed(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2891 } |
546
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
545
diff
changeset
|
2892 |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
545
diff
changeset
|
2893 #ifdef TRACESPINNING |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2894 ParallelTaskTerminator::print_termination_counts(); |
546
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
545
diff
changeset
|
2895 #endif |
342 | 2896 |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2897 gc_epilogue(false); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2898 } |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2899 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2900 assert(verify_region_lists(), "Bad region lists."); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2901 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2902 if (ExitAfterGCNum > 0 && total_collections() == ExitAfterGCNum) { |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2903 gclog_or_tty->print_cr("Stopping after GC #%d", ExitAfterGCNum); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2904 print_tracing_info(); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2905 vm_exit(-1); |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2906 } |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2907 } |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2908 |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2909 if (PrintHeapAtGC) { |
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
2910 Universe::print_heap_after_gc(); |
342 | 2911 } |
884
83b687ce3090
6866591: G1: print update buffer processing stats more often
tonyp
parents:
883
diff
changeset
|
2912 if (G1SummarizeRSetStats && |
83b687ce3090
6866591: G1: print update buffer processing stats more often
tonyp
parents:
883
diff
changeset
|
2913 (G1SummarizeRSetStatsPeriod > 0) && |
83b687ce3090
6866591: G1: print update buffer processing stats more often
tonyp
parents:
883
diff
changeset
|
2914 (total_collections() % G1SummarizeRSetStatsPeriod == 0)) { |
83b687ce3090
6866591: G1: print update buffer processing stats more often
tonyp
parents:
883
diff
changeset
|
2915 g1_rem_set()->print_summary_info(); |
83b687ce3090
6866591: G1: print update buffer processing stats more often
tonyp
parents:
883
diff
changeset
|
2916 } |
342 | 2917 } |
2918 | |
2919 void G1CollectedHeap::set_gc_alloc_region(int purpose, HeapRegion* r) { | |
2920 assert(purpose >= 0 && purpose < GCAllocPurposeCount, "invalid purpose"); | |
636 | 2921 // make sure we don't call set_gc_alloc_region() multiple times on |
2922 // the same region | |
2923 assert(r == NULL || !r->is_gc_alloc_region(), | |
2924 "shouldn't already be a GC alloc region"); | |
342 | 2925 HeapWord* original_top = NULL; |
2926 if (r != NULL) | |
2927 original_top = r->top(); | |
2928 | |
2929 // We will want to record the used space in r as being there before gc. | |
2930 // One we install it as a GC alloc region it's eligible for allocation. | |
2931 // So record it now and use it later. | |
2932 size_t r_used = 0; | |
2933 if (r != NULL) { | |
2934 r_used = r->used(); | |
2935 | |
2936 if (ParallelGCThreads > 0) { | |
2937 // need to take the lock to guard against two threads calling | |
2938 // get_gc_alloc_region concurrently (very unlikely but...) | |
2939 MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag); | |
2940 r->save_marks(); | |
2941 } | |
2942 } | |
2943 HeapRegion* old_alloc_region = _gc_alloc_regions[purpose]; | |
2944 _gc_alloc_regions[purpose] = r; | |
2945 if (old_alloc_region != NULL) { | |
2946 // Replace aliases too. | |
2947 for (int ap = 0; ap < GCAllocPurposeCount; ++ap) { | |
2948 if (_gc_alloc_regions[ap] == old_alloc_region) { | |
2949 _gc_alloc_regions[ap] = r; | |
2950 } | |
2951 } | |
2952 } | |
2953 if (r != NULL) { | |
2954 push_gc_alloc_region(r); | |
2955 if (mark_in_progress() && original_top != r->next_top_at_mark_start()) { | |
2956 // We are using a region as a GC alloc region after it has been used | |
2957 // as a mutator allocation region during the current marking cycle. | |
2958 // The mutator-allocated objects are currently implicitly marked, but | |
2959 // when we move hr->next_top_at_mark_start() forward at the the end | |
2960 // of the GC pause, they won't be. We therefore mark all objects in | |
2961 // the "gap". We do this object-by-object, since marking densely | |
2962 // does not currently work right with marking bitmap iteration. This | |
2963 // means we rely on TLAB filling at the start of pauses, and no | |
2964 // "resuscitation" of filled TLAB's. If we want to do this, we need | |
2965 // to fix the marking bitmap iteration. | |
2966 HeapWord* curhw = r->next_top_at_mark_start(); | |
2967 HeapWord* t = original_top; | |
2968 | |
2969 while (curhw < t) { | |
2970 oop cur = (oop)curhw; | |
2971 // We'll assume parallel for generality. This is rare code. | |
2972 concurrent_mark()->markAndGrayObjectIfNecessary(cur); // can't we just mark them? | |
2973 curhw = curhw + cur->size(); | |
2974 } | |
2975 assert(curhw == t, "Should have parsed correctly."); | |
2976 } | |
2977 if (G1PolicyVerbose > 1) { | |
2978 gclog_or_tty->print("New alloc region ["PTR_FORMAT", "PTR_FORMAT", " PTR_FORMAT") " | |
2979 "for survivors:", r->bottom(), original_top, r->end()); | |
2980 r->print(); | |
2981 } | |
2982 g1_policy()->record_before_bytes(r_used); | |
2983 } | |
2984 } | |
2985 | |
2986 void G1CollectedHeap::push_gc_alloc_region(HeapRegion* hr) { | |
2987 assert(Thread::current()->is_VM_thread() || | |
2988 par_alloc_during_gc_lock()->owned_by_self(), "Precondition"); | |
2989 assert(!hr->is_gc_alloc_region() && !hr->in_collection_set(), | |
2990 "Precondition."); | |
2991 hr->set_is_gc_alloc_region(true); | |
2992 hr->set_next_gc_alloc_region(_gc_alloc_region_list); | |
2993 _gc_alloc_region_list = hr; | |
2994 } | |
2995 | |
2996 #ifdef G1_DEBUG | |
2997 class FindGCAllocRegion: public HeapRegionClosure { | |
2998 public: | |
2999 bool doHeapRegion(HeapRegion* r) { | |
3000 if (r->is_gc_alloc_region()) { | |
3001 gclog_or_tty->print_cr("Region %d ["PTR_FORMAT"...] is still a gc_alloc_region.", | |
3002 r->hrs_index(), r->bottom()); | |
3003 } | |
3004 return false; | |
3005 } | |
3006 }; | |
3007 #endif // G1_DEBUG | |
3008 | |
3009 void G1CollectedHeap::forget_alloc_region_list() { | |
3010 assert(Thread::current()->is_VM_thread(), "Precondition"); | |
3011 while (_gc_alloc_region_list != NULL) { | |
3012 HeapRegion* r = _gc_alloc_region_list; | |
3013 assert(r->is_gc_alloc_region(), "Invariant."); | |
637
25e146966e7c
6817419: G1: Enable extensive verification for humongous regions
iveresov
parents:
636
diff
changeset
|
3014 // We need HeapRegion::oops_on_card_seq_iterate_careful() to work on |
25e146966e7c
6817419: G1: Enable extensive verification for humongous regions
iveresov
parents:
636
diff
changeset
|
3015 // newly allocated data in order to be able to apply deferred updates |
25e146966e7c
6817419: G1: Enable extensive verification for humongous regions
iveresov
parents:
636
diff
changeset
|
3016 // before the GC is done for verification purposes (i.e to allow |
25e146966e7c
6817419: G1: Enable extensive verification for humongous regions
iveresov
parents:
636
diff
changeset
|
3017 // G1HRRSFlushLogBuffersOnVerify). It's safe thing to do after the |
25e146966e7c
6817419: G1: Enable extensive verification for humongous regions
iveresov
parents:
636
diff
changeset
|
3018 // collection. |
25e146966e7c
6817419: G1: Enable extensive verification for humongous regions
iveresov
parents:
636
diff
changeset
|
3019 r->ContiguousSpace::set_saved_mark(); |
342 | 3020 _gc_alloc_region_list = r->next_gc_alloc_region(); |
3021 r->set_next_gc_alloc_region(NULL); | |
3022 r->set_is_gc_alloc_region(false); | |
545 | 3023 if (r->is_survivor()) { |
3024 if (r->is_empty()) { | |
3025 r->set_not_young(); | |
3026 } else { | |
3027 _young_list->add_survivor_region(r); | |
3028 } | |
3029 } | |
342 | 3030 if (r->is_empty()) { |
3031 ++_free_regions; | |
3032 } | |
3033 } | |
3034 #ifdef G1_DEBUG | |
3035 FindGCAllocRegion fa; | |
3036 heap_region_iterate(&fa); | |
3037 #endif // G1_DEBUG | |
3038 } | |
3039 | |
3040 | |
3041 bool G1CollectedHeap::check_gc_alloc_regions() { | |
3042 // TODO: allocation regions check | |
3043 return true; | |
3044 } | |
3045 | |
3046 void G1CollectedHeap::get_gc_alloc_regions() { | |
636 | 3047 // First, let's check that the GC alloc region list is empty (it should) |
3048 assert(_gc_alloc_region_list == NULL, "invariant"); | |
3049 | |
342 | 3050 for (int ap = 0; ap < GCAllocPurposeCount; ++ap) { |
636 | 3051 assert(_gc_alloc_regions[ap] == NULL, "invariant"); |
861
45d97a99715b
6862661: G1: _gc_alloc_region_counts is not updated properly after 6604422
apetrusenko
parents:
846
diff
changeset
|
3052 assert(_gc_alloc_region_counts[ap] == 0, "invariant"); |
636 | 3053 |
342 | 3054 // Create new GC alloc regions. |
636 | 3055 HeapRegion* alloc_region = _retained_gc_alloc_regions[ap]; |
3056 _retained_gc_alloc_regions[ap] = NULL; | |
3057 | |
3058 if (alloc_region != NULL) { | |
3059 assert(_retain_gc_alloc_region[ap], "only way to retain a GC region"); | |
3060 | |
3061 // let's make sure that the GC alloc region is not tagged as such | |
3062 // outside a GC operation | |
3063 assert(!alloc_region->is_gc_alloc_region(), "sanity"); | |
3064 | |
3065 if (alloc_region->in_collection_set() || | |
3066 alloc_region->top() == alloc_region->end() || | |
3067 alloc_region->top() == alloc_region->bottom()) { | |
3068 // we will discard the current GC alloc region if it's in the | |
3069 // collection set (it can happen!), if it's already full (no | |
3070 // point in using it), or if it's empty (this means that it | |
3071 // was emptied during a cleanup and it should be on the free | |
3072 // list now). | |
3073 | |
3074 alloc_region = NULL; | |
3075 } | |
3076 } | |
3077 | |
3078 if (alloc_region == NULL) { | |
3079 // we will get a new GC alloc region | |
342 | 3080 alloc_region = newAllocRegionWithExpansion(ap, 0); |
861
45d97a99715b
6862661: G1: _gc_alloc_region_counts is not updated properly after 6604422
apetrusenko
parents:
846
diff
changeset
|
3081 } else { |
45d97a99715b
6862661: G1: _gc_alloc_region_counts is not updated properly after 6604422
apetrusenko
parents:
846
diff
changeset
|
3082 // the region was retained from the last collection |
45d97a99715b
6862661: G1: _gc_alloc_region_counts is not updated properly after 6604422
apetrusenko
parents:
846
diff
changeset
|
3083 ++_gc_alloc_region_counts[ap]; |
342 | 3084 } |
636 | 3085 |
342 | 3086 if (alloc_region != NULL) { |
636 | 3087 assert(_gc_alloc_regions[ap] == NULL, "pre-condition"); |
342 | 3088 set_gc_alloc_region(ap, alloc_region); |
3089 } | |
636 | 3090 |
3091 assert(_gc_alloc_regions[ap] == NULL || | |
3092 _gc_alloc_regions[ap]->is_gc_alloc_region(), | |
3093 "the GC alloc region should be tagged as such"); | |
3094 assert(_gc_alloc_regions[ap] == NULL || | |
3095 _gc_alloc_regions[ap] == _gc_alloc_region_list, | |
3096 "the GC alloc region should be the same as the GC alloc list head"); | |
342 | 3097 } |
3098 // Set alternative regions for allocation purposes that have reached | |
636 | 3099 // their limit. |
342 | 3100 for (int ap = 0; ap < GCAllocPurposeCount; ++ap) { |
3101 GCAllocPurpose alt_purpose = g1_policy()->alternative_purpose(ap); | |
3102 if (_gc_alloc_regions[ap] == NULL && alt_purpose != ap) { | |
3103 _gc_alloc_regions[ap] = _gc_alloc_regions[alt_purpose]; | |
3104 } | |
3105 } | |
3106 assert(check_gc_alloc_regions(), "alloc regions messed up"); | |
3107 } | |
3108 | |
636 | 3109 void G1CollectedHeap::release_gc_alloc_regions(bool totally) { |
342 | 3110 // We keep a separate list of all regions that have been alloc regions in |
636 | 3111 // the current collection pause. Forget that now. This method will |
3112 // untag the GC alloc regions and tear down the GC alloc region | |
3113 // list. It's desirable that no regions are tagged as GC alloc | |
3114 // outside GCs. | |
342 | 3115 forget_alloc_region_list(); |
3116 | |
3117 // The current alloc regions contain objs that have survived | |
3118 // collection. Make them no longer GC alloc regions. | |
3119 for (int ap = 0; ap < GCAllocPurposeCount; ++ap) { | |
3120 HeapRegion* r = _gc_alloc_regions[ap]; | |
636 | 3121 _retained_gc_alloc_regions[ap] = NULL; |
861
45d97a99715b
6862661: G1: _gc_alloc_region_counts is not updated properly after 6604422
apetrusenko
parents:
846
diff
changeset
|
3122 _gc_alloc_region_counts[ap] = 0; |
636 | 3123 |
3124 if (r != NULL) { | |
3125 // we retain nothing on _gc_alloc_regions between GCs | |
3126 set_gc_alloc_region(ap, NULL); | |
3127 | |
3128 if (r->is_empty()) { | |
3129 // we didn't actually allocate anything in it; let's just put | |
3130 // it on the free list | |
342 | 3131 MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag); |
3132 r->set_zero_fill_complete(); | |
3133 put_free_region_on_list_locked(r); | |
636 | 3134 } else if (_retain_gc_alloc_region[ap] && !totally) { |
3135 // retain it so that we can use it at the beginning of the next GC | |
3136 _retained_gc_alloc_regions[ap] = r; | |
342 | 3137 } |
3138 } | |
636 | 3139 } |
3140 } | |
3141 | |
3142 #ifndef PRODUCT | |
3143 // Useful for debugging | |
3144 | |
3145 void G1CollectedHeap::print_gc_alloc_regions() { | |
3146 gclog_or_tty->print_cr("GC alloc regions"); | |
3147 for (int ap = 0; ap < GCAllocPurposeCount; ++ap) { | |
3148 HeapRegion* r = _gc_alloc_regions[ap]; | |
3149 if (r == NULL) { | |
3150 gclog_or_tty->print_cr(" %2d : "PTR_FORMAT, ap, NULL); | |
3151 } else { | |
3152 gclog_or_tty->print_cr(" %2d : "PTR_FORMAT" "SIZE_FORMAT, | |
3153 ap, r->bottom(), r->used()); | |
3154 } | |
3155 } | |
3156 } | |
3157 #endif // PRODUCT | |
342 | 3158 |
3159 void G1CollectedHeap::init_for_evac_failure(OopsInHeapRegionClosure* cl) { | |
3160 _drain_in_progress = false; | |
3161 set_evac_failure_closure(cl); | |
3162 _evac_failure_scan_stack = new (ResourceObj::C_HEAP) GrowableArray<oop>(40, true); | |
3163 } | |
3164 | |
3165 void G1CollectedHeap::finalize_for_evac_failure() { | |
3166 assert(_evac_failure_scan_stack != NULL && | |
3167 _evac_failure_scan_stack->length() == 0, | |
3168 "Postcondition"); | |
3169 assert(!_drain_in_progress, "Postcondition"); | |
1045 | 3170 delete _evac_failure_scan_stack; |
342 | 3171 _evac_failure_scan_stack = NULL; |
3172 } | |
3173 | |
3174 | |
3175 | |
3176 // *** Sequential G1 Evacuation | |
3177 | |
3178 HeapWord* G1CollectedHeap::allocate_during_gc(GCAllocPurpose purpose, size_t word_size) { | |
3179 HeapRegion* alloc_region = _gc_alloc_regions[purpose]; | |
3180 // let the caller handle alloc failure | |
3181 if (alloc_region == NULL) return NULL; | |
3182 assert(isHumongous(word_size) || !alloc_region->isHumongous(), | |
3183 "Either the object is humongous or the region isn't"); | |
3184 HeapWord* block = alloc_region->allocate(word_size); | |
3185 if (block == NULL) { | |
3186 block = allocate_during_gc_slow(purpose, alloc_region, false, word_size); | |
3187 } | |
3188 return block; | |
3189 } | |
3190 | |
3191 class G1IsAliveClosure: public BoolObjectClosure { | |
3192 G1CollectedHeap* _g1; | |
3193 public: | |
3194 G1IsAliveClosure(G1CollectedHeap* g1) : _g1(g1) {} | |
3195 void do_object(oop p) { assert(false, "Do not call."); } | |
3196 bool do_object_b(oop p) { | |
3197 // It is reachable if it is outside the collection set, or is inside | |
3198 // and forwarded. | |
3199 | |
3200 #ifdef G1_DEBUG | |
3201 gclog_or_tty->print_cr("is alive "PTR_FORMAT" in CS %d forwarded %d overall %d", | |
3202 (void*) p, _g1->obj_in_cs(p), p->is_forwarded(), | |
3203 !_g1->obj_in_cs(p) || p->is_forwarded()); | |
3204 #endif // G1_DEBUG | |
3205 | |
3206 return !_g1->obj_in_cs(p) || p->is_forwarded(); | |
3207 } | |
3208 }; | |
3209 | |
3210 class G1KeepAliveClosure: public OopClosure { | |
3211 G1CollectedHeap* _g1; | |
3212 public: | |
3213 G1KeepAliveClosure(G1CollectedHeap* g1) : _g1(g1) {} | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3214 void do_oop(narrowOop* p) { guarantee(false, "Not needed"); } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3215 void do_oop( oop* p) { |
342 | 3216 oop obj = *p; |
3217 #ifdef G1_DEBUG | |
3218 if (PrintGC && Verbose) { | |
3219 gclog_or_tty->print_cr("keep alive *"PTR_FORMAT" = "PTR_FORMAT" "PTR_FORMAT, | |
3220 p, (void*) obj, (void*) *p); | |
3221 } | |
3222 #endif // G1_DEBUG | |
3223 | |
3224 if (_g1->obj_in_cs(obj)) { | |
3225 assert( obj->is_forwarded(), "invariant" ); | |
3226 *p = obj->forwardee(); | |
3227 #ifdef G1_DEBUG | |
3228 gclog_or_tty->print_cr(" in CSet: moved "PTR_FORMAT" -> "PTR_FORMAT, | |
3229 (void*) obj, (void*) *p); | |
3230 #endif // G1_DEBUG | |
3231 } | |
3232 } | |
3233 }; | |
3234 | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3235 class UpdateRSetImmediate : public OopsInHeapRegionClosure { |
342 | 3236 private: |
3237 G1CollectedHeap* _g1; | |
3238 G1RemSet* _g1_rem_set; | |
3239 public: | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3240 UpdateRSetImmediate(G1CollectedHeap* g1) : |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3241 _g1(g1), _g1_rem_set(g1->g1_rem_set()) {} |
342 | 3242 |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3243 virtual void do_oop(narrowOop* p) { do_oop_work(p); } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3244 virtual void do_oop( oop* p) { do_oop_work(p); } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3245 template <class T> void do_oop_work(T* p) { |
342 | 3246 assert(_from->is_in_reserved(p), "paranoia"); |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3247 T heap_oop = oopDesc::load_heap_oop(p); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3248 if (!oopDesc::is_null(heap_oop) && !_from->is_survivor()) { |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3249 _g1_rem_set->par_write_ref(_from, p, 0); |
342 | 3250 } |
3251 } | |
3252 }; | |
3253 | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3254 class UpdateRSetDeferred : public OopsInHeapRegionClosure { |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3255 private: |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3256 G1CollectedHeap* _g1; |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3257 DirtyCardQueue *_dcq; |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3258 CardTableModRefBS* _ct_bs; |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3259 |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3260 public: |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3261 UpdateRSetDeferred(G1CollectedHeap* g1, DirtyCardQueue* dcq) : |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3262 _g1(g1), _ct_bs((CardTableModRefBS*)_g1->barrier_set()), _dcq(dcq) {} |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3263 |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3264 virtual void do_oop(narrowOop* p) { do_oop_work(p); } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3265 virtual void do_oop( oop* p) { do_oop_work(p); } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3266 template <class T> void do_oop_work(T* p) { |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3267 assert(_from->is_in_reserved(p), "paranoia"); |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3268 if (!_from->is_in_reserved(oopDesc::load_decode_heap_oop(p)) && |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3269 !_from->is_survivor()) { |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3270 size_t card_index = _ct_bs->index_for(p); |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3271 if (_ct_bs->mark_card_deferred(card_index)) { |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3272 _dcq->enqueue((jbyte*)_ct_bs->byte_for_index(card_index)); |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3273 } |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3274 } |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3275 } |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3276 }; |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3277 |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3278 |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3279 |
342 | 3280 class RemoveSelfPointerClosure: public ObjectClosure { |
3281 private: | |
3282 G1CollectedHeap* _g1; | |
3283 ConcurrentMark* _cm; | |
3284 HeapRegion* _hr; | |
3285 size_t _prev_marked_bytes; | |
3286 size_t _next_marked_bytes; | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3287 OopsInHeapRegionClosure *_cl; |
342 | 3288 public: |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3289 RemoveSelfPointerClosure(G1CollectedHeap* g1, OopsInHeapRegionClosure* cl) : |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3290 _g1(g1), _cm(_g1->concurrent_mark()), _prev_marked_bytes(0), |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3291 _next_marked_bytes(0), _cl(cl) {} |
342 | 3292 |
3293 size_t prev_marked_bytes() { return _prev_marked_bytes; } | |
3294 size_t next_marked_bytes() { return _next_marked_bytes; } | |
3295 | |
352
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3296 // The original idea here was to coalesce evacuated and dead objects. |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3297 // However that caused complications with the block offset table (BOT). |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3298 // In particular if there were two TLABs, one of them partially refined. |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3299 // |----- TLAB_1--------|----TLAB_2-~~~(partially refined part)~~~| |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3300 // The BOT entries of the unrefined part of TLAB_2 point to the start |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3301 // of TLAB_2. If the last object of the TLAB_1 and the first object |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3302 // of TLAB_2 are coalesced, then the cards of the unrefined part |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3303 // would point into middle of the filler object. |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3304 // |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3305 // The current approach is to not coalesce and leave the BOT contents intact. |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3306 void do_object(oop obj) { |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3307 if (obj->is_forwarded() && obj->forwardee() == obj) { |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3308 // The object failed to move. |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3309 assert(!_g1->is_obj_dead(obj), "We should not be preserving dead objs."); |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3310 _cm->markPrev(obj); |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3311 assert(_cm->isPrevMarked(obj), "Should be marked!"); |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3312 _prev_marked_bytes += (obj->size() * HeapWordSize); |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3313 if (_g1->mark_in_progress() && !_g1->is_obj_ill(obj)) { |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3314 _cm->markAndGrayObjectIfNecessary(obj); |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3315 } |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3316 obj->set_mark(markOopDesc::prototype()); |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3317 // While we were processing RSet buffers during the |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3318 // collection, we actually didn't scan any cards on the |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3319 // collection set, since we didn't want to update remebered |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3320 // sets with entries that point into the collection set, given |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3321 // that live objects fromthe collection set are about to move |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3322 // and such entries will be stale very soon. This change also |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3323 // dealt with a reliability issue which involved scanning a |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3324 // card in the collection set and coming across an array that |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3325 // was being chunked and looking malformed. The problem is |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3326 // that, if evacuation fails, we might have remembered set |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3327 // entries missing given that we skipped cards on the |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3328 // collection set. So, we'll recreate such entries now. |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3329 obj->oop_iterate(_cl); |
352
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3330 assert(_cm->isPrevMarked(obj), "Should be marked!"); |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3331 } else { |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3332 // The object has been either evacuated or is dead. Fill it with a |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3333 // dummy object. |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
3334 MemRegion mr((HeapWord*)obj, obj->size()); |
481
7d7a7c599c17
6578152: fill_region_with_object has usability and safety issues
jcoomes
parents:
457
diff
changeset
|
3335 CollectedHeap::fill_with_object(mr); |
342 | 3336 _cm->clearRangeBothMaps(mr); |
3337 } | |
3338 } | |
3339 }; | |
3340 | |
3341 void G1CollectedHeap::remove_self_forwarding_pointers() { | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3342 UpdateRSetImmediate immediate_update(_g1h); |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3343 DirtyCardQueue dcq(&_g1h->dirty_card_queue_set()); |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3344 UpdateRSetDeferred deferred_update(_g1h, &dcq); |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3345 OopsInHeapRegionClosure *cl; |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3346 if (G1DeferredRSUpdate) { |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3347 cl = &deferred_update; |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3348 } else { |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3349 cl = &immediate_update; |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3350 } |
342 | 3351 HeapRegion* cur = g1_policy()->collection_set(); |
3352 while (cur != NULL) { | |
3353 assert(g1_policy()->assertMarkedBytesDataOK(), "Should be!"); | |
3354 | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3355 RemoveSelfPointerClosure rspc(_g1h, cl); |
342 | 3356 if (cur->evacuation_failed()) { |
3357 assert(cur->in_collection_set(), "bad CS"); | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3358 cl->set_region(cur); |
342 | 3359 cur->object_iterate(&rspc); |
3360 | |
3361 // A number of manipulations to make the TAMS be the current top, | |
3362 // and the marked bytes be the ones observed in the iteration. | |
3363 if (_g1h->concurrent_mark()->at_least_one_mark_complete()) { | |
3364 // The comments below are the postconditions achieved by the | |
3365 // calls. Note especially the last such condition, which says that | |
3366 // the count of marked bytes has been properly restored. | |
3367 cur->note_start_of_marking(false); | |
3368 // _next_top_at_mark_start == top, _next_marked_bytes == 0 | |
3369 cur->add_to_marked_bytes(rspc.prev_marked_bytes()); | |
3370 // _next_marked_bytes == prev_marked_bytes. | |
3371 cur->note_end_of_marking(); | |
3372 // _prev_top_at_mark_start == top(), | |
3373 // _prev_marked_bytes == prev_marked_bytes | |
3374 } | |
3375 // If there is no mark in progress, we modified the _next variables | |
3376 // above needlessly, but harmlessly. | |
3377 if (_g1h->mark_in_progress()) { | |
3378 cur->note_start_of_marking(false); | |
3379 // _next_top_at_mark_start == top, _next_marked_bytes == 0 | |
3380 // _next_marked_bytes == next_marked_bytes. | |
3381 } | |
3382 | |
3383 // Now make sure the region has the right index in the sorted array. | |
3384 g1_policy()->note_change_in_marked_bytes(cur); | |
3385 } | |
3386 cur = cur->next_in_collection_set(); | |
3387 } | |
3388 assert(g1_policy()->assertMarkedBytesDataOK(), "Should be!"); | |
3389 | |
3390 // Now restore saved marks, if any. | |
3391 if (_objs_with_preserved_marks != NULL) { | |
3392 assert(_preserved_marks_of_objs != NULL, "Both or none."); | |
3393 assert(_objs_with_preserved_marks->length() == | |
3394 _preserved_marks_of_objs->length(), "Both or none."); | |
3395 guarantee(_objs_with_preserved_marks->length() == | |
3396 _preserved_marks_of_objs->length(), "Both or none."); | |
3397 for (int i = 0; i < _objs_with_preserved_marks->length(); i++) { | |
3398 oop obj = _objs_with_preserved_marks->at(i); | |
3399 markOop m = _preserved_marks_of_objs->at(i); | |
3400 obj->set_mark(m); | |
3401 } | |
3402 // Delete the preserved marks growable arrays (allocated on the C heap). | |
3403 delete _objs_with_preserved_marks; | |
3404 delete _preserved_marks_of_objs; | |
3405 _objs_with_preserved_marks = NULL; | |
3406 _preserved_marks_of_objs = NULL; | |
3407 } | |
3408 } | |
3409 | |
3410 void G1CollectedHeap::push_on_evac_failure_scan_stack(oop obj) { | |
3411 _evac_failure_scan_stack->push(obj); | |
3412 } | |
3413 | |
3414 void G1CollectedHeap::drain_evac_failure_scan_stack() { | |
3415 assert(_evac_failure_scan_stack != NULL, "precondition"); | |
3416 | |
3417 while (_evac_failure_scan_stack->length() > 0) { | |
3418 oop obj = _evac_failure_scan_stack->pop(); | |
3419 _evac_failure_closure->set_region(heap_region_containing(obj)); | |
3420 obj->oop_iterate_backwards(_evac_failure_closure); | |
3421 } | |
3422 } | |
3423 | |
3424 void G1CollectedHeap::handle_evacuation_failure(oop old) { | |
3425 markOop m = old->mark(); | |
3426 // forward to self | |
3427 assert(!old->is_forwarded(), "precondition"); | |
3428 | |
3429 old->forward_to(old); | |
3430 handle_evacuation_failure_common(old, m); | |
3431 } | |
3432 | |
3433 oop | |
3434 G1CollectedHeap::handle_evacuation_failure_par(OopsInHeapRegionClosure* cl, | |
3435 oop old) { | |
3436 markOop m = old->mark(); | |
3437 oop forward_ptr = old->forward_to_atomic(old); | |
3438 if (forward_ptr == NULL) { | |
3439 // Forward-to-self succeeded. | |
3440 if (_evac_failure_closure != cl) { | |
3441 MutexLockerEx x(EvacFailureStack_lock, Mutex::_no_safepoint_check_flag); | |
3442 assert(!_drain_in_progress, | |
3443 "Should only be true while someone holds the lock."); | |
3444 // Set the global evac-failure closure to the current thread's. | |
3445 assert(_evac_failure_closure == NULL, "Or locking has failed."); | |
3446 set_evac_failure_closure(cl); | |
3447 // Now do the common part. | |
3448 handle_evacuation_failure_common(old, m); | |
3449 // Reset to NULL. | |
3450 set_evac_failure_closure(NULL); | |
3451 } else { | |
3452 // The lock is already held, and this is recursive. | |
3453 assert(_drain_in_progress, "This should only be the recursive case."); | |
3454 handle_evacuation_failure_common(old, m); | |
3455 } | |
3456 return old; | |
3457 } else { | |
3458 // Someone else had a place to copy it. | |
3459 return forward_ptr; | |
3460 } | |
3461 } | |
3462 | |
3463 void G1CollectedHeap::handle_evacuation_failure_common(oop old, markOop m) { | |
3464 set_evacuation_failed(true); | |
3465 | |
3466 preserve_mark_if_necessary(old, m); | |
3467 | |
3468 HeapRegion* r = heap_region_containing(old); | |
3469 if (!r->evacuation_failed()) { | |
3470 r->set_evacuation_failed(true); | |
751 | 3471 if (G1PrintRegions) { |
342 | 3472 gclog_or_tty->print("evacuation failed in heap region "PTR_FORMAT" " |
3473 "["PTR_FORMAT","PTR_FORMAT")\n", | |
3474 r, r->bottom(), r->end()); | |
3475 } | |
3476 } | |
3477 | |
3478 push_on_evac_failure_scan_stack(old); | |
3479 | |
3480 if (!_drain_in_progress) { | |
3481 // prevent recursion in copy_to_survivor_space() | |
3482 _drain_in_progress = true; | |
3483 drain_evac_failure_scan_stack(); | |
3484 _drain_in_progress = false; | |
3485 } | |
3486 } | |
3487 | |
3488 void G1CollectedHeap::preserve_mark_if_necessary(oop obj, markOop m) { | |
3489 if (m != markOopDesc::prototype()) { | |
3490 if (_objs_with_preserved_marks == NULL) { | |
3491 assert(_preserved_marks_of_objs == NULL, "Both or none."); | |
3492 _objs_with_preserved_marks = | |
3493 new (ResourceObj::C_HEAP) GrowableArray<oop>(40, true); | |
3494 _preserved_marks_of_objs = | |
3495 new (ResourceObj::C_HEAP) GrowableArray<markOop>(40, true); | |
3496 } | |
3497 _objs_with_preserved_marks->push(obj); | |
3498 _preserved_marks_of_objs->push(m); | |
3499 } | |
3500 } | |
3501 | |
3502 // *** Parallel G1 Evacuation | |
3503 | |
3504 HeapWord* G1CollectedHeap::par_allocate_during_gc(GCAllocPurpose purpose, | |
3505 size_t word_size) { | |
3506 HeapRegion* alloc_region = _gc_alloc_regions[purpose]; | |
3507 // let the caller handle alloc failure | |
3508 if (alloc_region == NULL) return NULL; | |
3509 | |
3510 HeapWord* block = alloc_region->par_allocate(word_size); | |
3511 if (block == NULL) { | |
3512 MutexLockerEx x(par_alloc_during_gc_lock(), | |
3513 Mutex::_no_safepoint_check_flag); | |
3514 block = allocate_during_gc_slow(purpose, alloc_region, true, word_size); | |
3515 } | |
3516 return block; | |
3517 } | |
3518 | |
545 | 3519 void G1CollectedHeap::retire_alloc_region(HeapRegion* alloc_region, |
3520 bool par) { | |
3521 // Another thread might have obtained alloc_region for the given | |
3522 // purpose, and might be attempting to allocate in it, and might | |
3523 // succeed. Therefore, we can't do the "finalization" stuff on the | |
3524 // region below until we're sure the last allocation has happened. | |
3525 // We ensure this by allocating the remaining space with a garbage | |
3526 // object. | |
3527 if (par) par_allocate_remaining_space(alloc_region); | |
3528 // Now we can do the post-GC stuff on the region. | |
3529 alloc_region->note_end_of_copying(); | |
3530 g1_policy()->record_after_bytes(alloc_region->used()); | |
3531 } | |
3532 | |
342 | 3533 HeapWord* |
3534 G1CollectedHeap::allocate_during_gc_slow(GCAllocPurpose purpose, | |
3535 HeapRegion* alloc_region, | |
3536 bool par, | |
3537 size_t word_size) { | |
3538 HeapWord* block = NULL; | |
3539 // In the parallel case, a previous thread to obtain the lock may have | |
3540 // already assigned a new gc_alloc_region. | |
3541 if (alloc_region != _gc_alloc_regions[purpose]) { | |
3542 assert(par, "But should only happen in parallel case."); | |
3543 alloc_region = _gc_alloc_regions[purpose]; | |
3544 if (alloc_region == NULL) return NULL; | |
3545 block = alloc_region->par_allocate(word_size); | |
3546 if (block != NULL) return block; | |
3547 // Otherwise, continue; this new region is empty, too. | |
3548 } | |
3549 assert(alloc_region != NULL, "We better have an allocation region"); | |
545 | 3550 retire_alloc_region(alloc_region, par); |
342 | 3551 |
3552 if (_gc_alloc_region_counts[purpose] >= g1_policy()->max_regions(purpose)) { | |
3553 // Cannot allocate more regions for the given purpose. | |
3554 GCAllocPurpose alt_purpose = g1_policy()->alternative_purpose(purpose); | |
3555 // Is there an alternative? | |
3556 if (purpose != alt_purpose) { | |
3557 HeapRegion* alt_region = _gc_alloc_regions[alt_purpose]; | |
3558 // Has not the alternative region been aliased? | |
545 | 3559 if (alloc_region != alt_region && alt_region != NULL) { |
342 | 3560 // Try to allocate in the alternative region. |
3561 if (par) { | |
3562 block = alt_region->par_allocate(word_size); | |
3563 } else { | |
3564 block = alt_region->allocate(word_size); | |
3565 } | |
3566 // Make an alias. | |
3567 _gc_alloc_regions[purpose] = _gc_alloc_regions[alt_purpose]; | |
545 | 3568 if (block != NULL) { |
3569 return block; | |
3570 } | |
3571 retire_alloc_region(alt_region, par); | |
342 | 3572 } |
3573 // Both the allocation region and the alternative one are full | |
3574 // and aliased, replace them with a new allocation region. | |
3575 purpose = alt_purpose; | |
3576 } else { | |
3577 set_gc_alloc_region(purpose, NULL); | |
3578 return NULL; | |
3579 } | |
3580 } | |
3581 | |
3582 // Now allocate a new region for allocation. | |
3583 alloc_region = newAllocRegionWithExpansion(purpose, word_size, false /*zero_filled*/); | |
3584 | |
3585 // let the caller handle alloc failure | |
3586 if (alloc_region != NULL) { | |
3587 | |
3588 assert(check_gc_alloc_regions(), "alloc regions messed up"); | |
3589 assert(alloc_region->saved_mark_at_top(), | |
3590 "Mark should have been saved already."); | |
3591 // We used to assert that the region was zero-filled here, but no | |
3592 // longer. | |
3593 | |
3594 // This must be done last: once it's installed, other regions may | |
3595 // allocate in it (without holding the lock.) | |
3596 set_gc_alloc_region(purpose, alloc_region); | |
3597 | |
3598 if (par) { | |
3599 block = alloc_region->par_allocate(word_size); | |
3600 } else { | |
3601 block = alloc_region->allocate(word_size); | |
3602 } | |
3603 // Caller handles alloc failure. | |
3604 } else { | |
3605 // This sets other apis using the same old alloc region to NULL, also. | |
3606 set_gc_alloc_region(purpose, NULL); | |
3607 } | |
3608 return block; // May be NULL. | |
3609 } | |
3610 | |
3611 void G1CollectedHeap::par_allocate_remaining_space(HeapRegion* r) { | |
3612 HeapWord* block = NULL; | |
3613 size_t free_words; | |
3614 do { | |
3615 free_words = r->free()/HeapWordSize; | |
3616 // If there's too little space, no one can allocate, so we're done. | |
3617 if (free_words < (size_t)oopDesc::header_size()) return; | |
3618 // Otherwise, try to claim it. | |
3619 block = r->par_allocate(free_words); | |
3620 } while (block == NULL); | |
481
7d7a7c599c17
6578152: fill_region_with_object has usability and safety issues
jcoomes
parents:
457
diff
changeset
|
3621 fill_with_object(block, free_words); |
342 | 3622 } |
3623 | |
3624 #ifndef PRODUCT | |
3625 bool GCLabBitMapClosure::do_bit(size_t offset) { | |
3626 HeapWord* addr = _bitmap->offsetToHeapWord(offset); | |
3627 guarantee(_cm->isMarked(oop(addr)), "it should be!"); | |
3628 return true; | |
3629 } | |
3630 #endif // PRODUCT | |
3631 | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3632 G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, int queue_num) |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3633 : _g1h(g1h), |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3634 _refs(g1h->task_queue(queue_num)), |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3635 _dcq(&g1h->dirty_card_queue_set()), |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3636 _ct_bs((CardTableModRefBS*)_g1h->barrier_set()), |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3637 _g1_rem(g1h->g1_rem_set()), |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3638 _hash_seed(17), _queue_num(queue_num), |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3639 _term_attempts(0), |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3640 _age_table(false), |
342 | 3641 #if G1_DETAILED_STATS |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3642 _pushes(0), _pops(0), _steals(0), |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3643 _steal_attempts(0), _overflow_pushes(0), |
342 | 3644 #endif |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3645 _strong_roots_time(0), _term_time(0), |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3646 _alloc_buffer_waste(0), _undo_waste(0) |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3647 { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3648 // we allocate G1YoungSurvRateNumRegions plus one entries, since |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3649 // we "sacrifice" entry 0 to keep track of surviving bytes for |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3650 // non-young regions (where the age is -1) |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3651 // We also add a few elements at the beginning and at the end in |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3652 // an attempt to eliminate cache contention |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3653 size_t real_length = 1 + _g1h->g1_policy()->young_cset_length(); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3654 size_t array_length = PADDING_ELEM_NUM + |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3655 real_length + |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3656 PADDING_ELEM_NUM; |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3657 _surviving_young_words_base = NEW_C_HEAP_ARRAY(size_t, array_length); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3658 if (_surviving_young_words_base == NULL) |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3659 vm_exit_out_of_memory(array_length * sizeof(size_t), |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3660 "Not enough space for young surv histo."); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3661 _surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM; |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3662 memset(_surviving_young_words, 0, real_length * sizeof(size_t)); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3663 |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3664 _overflowed_refs = new OverflowQueue(10); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3665 |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3666 _start = os::elapsedTime(); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3667 } |
342 | 3668 |
3669 G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : | |
3670 _g1(g1), _g1_rem(_g1->g1_rem_set()), _cm(_g1->concurrent_mark()), | |
3671 _par_scan_state(par_scan_state) { } | |
3672 | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3673 template <class T> void G1ParCopyHelper::mark_forwardee(T* p) { |
342 | 3674 // This is called _after_ do_oop_work has been called, hence after |
3675 // the object has been relocated to its new location and *p points | |
3676 // to its new location. | |
3677 | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3678 T heap_oop = oopDesc::load_heap_oop(p); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3679 if (!oopDesc::is_null(heap_oop)) { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3680 oop obj = oopDesc::decode_heap_oop(heap_oop); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3681 assert((_g1->evacuation_failed()) || (!_g1->obj_in_cs(obj)), |
342 | 3682 "shouldn't still be in the CSet if evacuation didn't fail."); |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3683 HeapWord* addr = (HeapWord*)obj; |
342 | 3684 if (_g1->is_in_g1_reserved(addr)) |
3685 _cm->grayRoot(oop(addr)); | |
3686 } | |
3687 } | |
3688 | |
3689 oop G1ParCopyHelper::copy_to_survivor_space(oop old) { | |
3690 size_t word_sz = old->size(); | |
3691 HeapRegion* from_region = _g1->heap_region_containing_raw(old); | |
3692 // +1 to make the -1 indexes valid... | |
3693 int young_index = from_region->young_index_in_cset()+1; | |
3694 assert( (from_region->is_young() && young_index > 0) || | |
3695 (!from_region->is_young() && young_index == 0), "invariant" ); | |
3696 G1CollectorPolicy* g1p = _g1->g1_policy(); | |
3697 markOop m = old->mark(); | |
545 | 3698 int age = m->has_displaced_mark_helper() ? m->displaced_mark_helper()->age() |
3699 : m->age(); | |
3700 GCAllocPurpose alloc_purpose = g1p->evacuation_destination(from_region, age, | |
342 | 3701 word_sz); |
3702 HeapWord* obj_ptr = _par_scan_state->allocate(alloc_purpose, word_sz); | |
3703 oop obj = oop(obj_ptr); | |
3704 | |
3705 if (obj_ptr == NULL) { | |
3706 // This will either forward-to-self, or detect that someone else has | |
3707 // installed a forwarding pointer. | |
3708 OopsInHeapRegionClosure* cl = _par_scan_state->evac_failure_closure(); | |
3709 return _g1->handle_evacuation_failure_par(cl, old); | |
3710 } | |
3711 | |
526 | 3712 // We're going to allocate linearly, so might as well prefetch ahead. |
3713 Prefetch::write(obj_ptr, PrefetchCopyIntervalInBytes); | |
3714 | |
342 | 3715 oop forward_ptr = old->forward_to_atomic(obj); |
3716 if (forward_ptr == NULL) { | |
3717 Copy::aligned_disjoint_words((HeapWord*) old, obj_ptr, word_sz); | |
526 | 3718 if (g1p->track_object_age(alloc_purpose)) { |
3719 // We could simply do obj->incr_age(). However, this causes a | |
3720 // performance issue. obj->incr_age() will first check whether | |
3721 // the object has a displaced mark by checking its mark word; | |
3722 // getting the mark word from the new location of the object | |
3723 // stalls. So, given that we already have the mark word and we | |
3724 // are about to install it anyway, it's better to increase the | |
3725 // age on the mark word, when the object does not have a | |
3726 // displaced mark word. We're not expecting many objects to have | |
3727 // a displaced marked word, so that case is not optimized | |
3728 // further (it could be...) and we simply call obj->incr_age(). | |
3729 | |
3730 if (m->has_displaced_mark_helper()) { | |
3731 // in this case, we have to install the mark word first, | |
3732 // otherwise obj looks to be forwarded (the old mark word, | |
3733 // which contains the forward pointer, was copied) | |
3734 obj->set_mark(m); | |
3735 obj->incr_age(); | |
3736 } else { | |
3737 m = m->incr_age(); | |
545 | 3738 obj->set_mark(m); |
526 | 3739 } |
545 | 3740 _par_scan_state->age_table()->add(obj, word_sz); |
3741 } else { | |
3742 obj->set_mark(m); | |
526 | 3743 } |
3744 | |
342 | 3745 // preserve "next" mark bit |
3746 if (_g1->mark_in_progress() && !_g1->is_obj_ill(old)) { | |
3747 if (!use_local_bitmaps || | |
3748 !_par_scan_state->alloc_buffer(alloc_purpose)->mark(obj_ptr)) { | |
3749 // if we couldn't mark it on the local bitmap (this happens when | |
3750 // the object was not allocated in the GCLab), we have to bite | |
3751 // the bullet and do the standard parallel mark | |
3752 _cm->markAndGrayObjectIfNecessary(obj); | |
3753 } | |
3754 #if 1 | |
3755 if (_g1->isMarkedNext(old)) { | |
3756 _cm->nextMarkBitMap()->parClear((HeapWord*)old); | |
3757 } | |
3758 #endif | |
3759 } | |
3760 | |
3761 size_t* surv_young_words = _par_scan_state->surviving_young_words(); | |
3762 surv_young_words[young_index] += word_sz; | |
3763 | |
3764 if (obj->is_objArray() && arrayOop(obj)->length() >= ParGCArrayScanChunk) { | |
3765 arrayOop(old)->set_length(0); | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3766 oop* old_p = set_partial_array_mask(old); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3767 _par_scan_state->push_on_queue(old_p); |
342 | 3768 } else { |
526 | 3769 // No point in using the slower heap_region_containing() method, |
3770 // given that we know obj is in the heap. | |
3771 _scanner->set_region(_g1->heap_region_containing_raw(obj)); | |
342 | 3772 obj->oop_iterate_backwards(_scanner); |
3773 } | |
3774 } else { | |
3775 _par_scan_state->undo_allocation(alloc_purpose, obj_ptr, word_sz); | |
3776 obj = forward_ptr; | |
3777 } | |
3778 return obj; | |
3779 } | |
3780 | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3781 template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_forwardee, bool skip_cset_test> |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3782 template <class T> |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3783 void G1ParCopyClosure <do_gen_barrier, barrier, do_mark_forwardee, skip_cset_test> |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3784 ::do_oop_work(T* p) { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3785 oop obj = oopDesc::load_decode_heap_oop(p); |
342 | 3786 assert(barrier != G1BarrierRS || obj != NULL, |
3787 "Precondition: G1BarrierRS implies obj is nonNull"); | |
3788 | |
526 | 3789 // The only time we skip the cset test is when we're scanning |
3790 // references popped from the queue. And we only push on the queue | |
3791 // references that we know point into the cset, so no point in | |
3792 // checking again. But we'll leave an assert here for peace of mind. | |
3793 assert(!skip_cset_test || _g1->obj_in_cs(obj), "invariant"); | |
3794 | |
3795 // here the null check is implicit in the cset_fast_test() test | |
3796 if (skip_cset_test || _g1->in_cset_fast_test(obj)) { | |
342 | 3797 #if G1_REM_SET_LOGGING |
526 | 3798 gclog_or_tty->print_cr("Loc "PTR_FORMAT" contains pointer "PTR_FORMAT" " |
3799 "into CS.", p, (void*) obj); | |
342 | 3800 #endif |
526 | 3801 if (obj->is_forwarded()) { |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3802 oopDesc::encode_store_heap_oop(p, obj->forwardee()); |
526 | 3803 } else { |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3804 oop copy_oop = copy_to_survivor_space(obj); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3805 oopDesc::encode_store_heap_oop(p, copy_oop); |
342 | 3806 } |
526 | 3807 // When scanning the RS, we only care about objs in CS. |
3808 if (barrier == G1BarrierRS) { | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3809 _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num()); |
342 | 3810 } |
526 | 3811 } |
3812 | |
3813 // When scanning moved objs, must look at all oops. | |
3814 if (barrier == G1BarrierEvac && obj != NULL) { | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3815 _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num()); |
526 | 3816 } |
3817 | |
3818 if (do_gen_barrier && obj != NULL) { | |
3819 par_do_barrier(p); | |
3820 } | |
3821 } | |
3822 | |
3823 template void G1ParCopyClosure<false, G1BarrierEvac, false, true>::do_oop_work(oop* p); | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3824 template void G1ParCopyClosure<false, G1BarrierEvac, false, true>::do_oop_work(narrowOop* p); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3825 |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3826 template <class T> void G1ParScanPartialArrayClosure::do_oop_nv(T* p) { |
526 | 3827 assert(has_partial_array_mask(p), "invariant"); |
3828 oop old = clear_partial_array_mask(p); | |
342 | 3829 assert(old->is_objArray(), "must be obj array"); |
3830 assert(old->is_forwarded(), "must be forwarded"); | |
3831 assert(Universe::heap()->is_in_reserved(old), "must be in heap."); | |
3832 | |
3833 objArrayOop obj = objArrayOop(old->forwardee()); | |
3834 assert((void*)old != (void*)old->forwardee(), "self forwarding here?"); | |
3835 // Process ParGCArrayScanChunk elements now | |
3836 // and push the remainder back onto queue | |
3837 int start = arrayOop(old)->length(); | |
3838 int end = obj->length(); | |
3839 int remainder = end - start; | |
3840 assert(start <= end, "just checking"); | |
3841 if (remainder > 2 * ParGCArrayScanChunk) { | |
3842 // Test above combines last partial chunk with a full chunk | |
3843 end = start + ParGCArrayScanChunk; | |
3844 arrayOop(old)->set_length(end); | |
3845 // Push remainder. | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3846 oop* old_p = set_partial_array_mask(old); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3847 assert(arrayOop(old)->length() < obj->length(), "Empty push?"); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3848 _par_scan_state->push_on_queue(old_p); |
342 | 3849 } else { |
3850 // Restore length so that the heap remains parsable in | |
3851 // case of evacuation failure. | |
3852 arrayOop(old)->set_length(end); | |
3853 } | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3854 _scanner.set_region(_g1->heap_region_containing_raw(obj)); |
342 | 3855 // process our set of indices (include header in first chunk) |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3856 obj->oop_iterate_range(&_scanner, start, end); |
342 | 3857 } |
3858 | |
3859 class G1ParEvacuateFollowersClosure : public VoidClosure { | |
3860 protected: | |
3861 G1CollectedHeap* _g1h; | |
3862 G1ParScanThreadState* _par_scan_state; | |
3863 RefToScanQueueSet* _queues; | |
3864 ParallelTaskTerminator* _terminator; | |
3865 | |
3866 G1ParScanThreadState* par_scan_state() { return _par_scan_state; } | |
3867 RefToScanQueueSet* queues() { return _queues; } | |
3868 ParallelTaskTerminator* terminator() { return _terminator; } | |
3869 | |
3870 public: | |
3871 G1ParEvacuateFollowersClosure(G1CollectedHeap* g1h, | |
3872 G1ParScanThreadState* par_scan_state, | |
3873 RefToScanQueueSet* queues, | |
3874 ParallelTaskTerminator* terminator) | |
3875 : _g1h(g1h), _par_scan_state(par_scan_state), | |
3876 _queues(queues), _terminator(terminator) {} | |
3877 | |
3878 void do_void() { | |
3879 G1ParScanThreadState* pss = par_scan_state(); | |
3880 while (true) { | |
3881 pss->trim_queue(); | |
3882 IF_G1_DETAILED_STATS(pss->note_steal_attempt()); | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3883 |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3884 StarTask stolen_task; |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3885 if (queues()->steal(pss->queue_num(), pss->hash_seed(), stolen_task)) { |
342 | 3886 IF_G1_DETAILED_STATS(pss->note_steal()); |
526 | 3887 |
3888 // slightly paranoid tests; I'm trying to catch potential | |
3889 // problems before we go into push_on_queue to know where the | |
3890 // problem is coming from | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3891 assert((oop*)stolen_task != NULL, "Error"); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3892 if (stolen_task.is_narrow()) { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3893 assert(UseCompressedOops, "Error"); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3894 narrowOop* p = (narrowOop*) stolen_task; |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3895 assert(has_partial_array_mask(p) || |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3896 _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "Error"); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3897 pss->push_on_queue(p); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3898 } else { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3899 oop* p = (oop*) stolen_task; |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3900 assert(has_partial_array_mask(p) || _g1h->obj_in_cs(*p), "Error"); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3901 pss->push_on_queue(p); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3902 } |
342 | 3903 continue; |
3904 } | |
3905 pss->start_term_time(); | |
3906 if (terminator()->offer_termination()) break; | |
3907 pss->end_term_time(); | |
3908 } | |
3909 pss->end_term_time(); | |
3910 pss->retire_alloc_buffers(); | |
3911 } | |
3912 }; | |
3913 | |
3914 class G1ParTask : public AbstractGangTask { | |
3915 protected: | |
3916 G1CollectedHeap* _g1h; | |
3917 RefToScanQueueSet *_queues; | |
3918 ParallelTaskTerminator _terminator; | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3919 int _n_workers; |
342 | 3920 |
3921 Mutex _stats_lock; | |
3922 Mutex* stats_lock() { return &_stats_lock; } | |
3923 | |
3924 size_t getNCards() { | |
3925 return (_g1h->capacity() + G1BlockOffsetSharedArray::N_bytes - 1) | |
3926 / G1BlockOffsetSharedArray::N_bytes; | |
3927 } | |
3928 | |
3929 public: | |
3930 G1ParTask(G1CollectedHeap* g1h, int workers, RefToScanQueueSet *task_queues) | |
3931 : AbstractGangTask("G1 collection"), | |
3932 _g1h(g1h), | |
3933 _queues(task_queues), | |
3934 _terminator(workers, _queues), | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3935 _stats_lock(Mutex::leaf, "parallel G1 stats lock", true), |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3936 _n_workers(workers) |
342 | 3937 {} |
3938 | |
3939 RefToScanQueueSet* queues() { return _queues; } | |
3940 | |
3941 RefToScanQueue *work_queue(int i) { | |
3942 return queues()->queue(i); | |
3943 } | |
3944 | |
3945 void work(int i) { | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
838
diff
changeset
|
3946 if (i >= _n_workers) return; // no work needed this round |
342 | 3947 ResourceMark rm; |
3948 HandleMark hm; | |
3949 | |
526 | 3950 G1ParScanThreadState pss(_g1h, i); |
3951 G1ParScanHeapEvacClosure scan_evac_cl(_g1h, &pss); | |
3952 G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss); | |
3953 G1ParScanPartialArrayClosure partial_scan_cl(_g1h, &pss); | |
342 | 3954 |
3955 pss.set_evac_closure(&scan_evac_cl); | |
3956 pss.set_evac_failure_closure(&evac_failure_cl); | |
3957 pss.set_partial_scan_closure(&partial_scan_cl); | |
3958 | |
3959 G1ParScanExtRootClosure only_scan_root_cl(_g1h, &pss); | |
3960 G1ParScanPermClosure only_scan_perm_cl(_g1h, &pss); | |
3961 G1ParScanHeapRSClosure only_scan_heap_rs_cl(_g1h, &pss); | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
3962 |
342 | 3963 G1ParScanAndMarkExtRootClosure scan_mark_root_cl(_g1h, &pss); |
3964 G1ParScanAndMarkPermClosure scan_mark_perm_cl(_g1h, &pss); | |
3965 G1ParScanAndMarkHeapRSClosure scan_mark_heap_rs_cl(_g1h, &pss); | |
3966 | |
3967 OopsInHeapRegionClosure *scan_root_cl; | |
3968 OopsInHeapRegionClosure *scan_perm_cl; | |
3969 OopsInHeapRegionClosure *scan_so_cl; | |
3970 | |
3971 if (_g1h->g1_policy()->should_initiate_conc_mark()) { | |
3972 scan_root_cl = &scan_mark_root_cl; | |
3973 scan_perm_cl = &scan_mark_perm_cl; | |
3974 scan_so_cl = &scan_mark_heap_rs_cl; | |
3975 } else { | |
3976 scan_root_cl = &only_scan_root_cl; | |
3977 scan_perm_cl = &only_scan_perm_cl; | |
3978 scan_so_cl = &only_scan_heap_rs_cl; | |
3979 } | |
3980 | |
3981 pss.start_strong_roots(); | |
3982 _g1h->g1_process_strong_roots(/* not collecting perm */ false, | |
3983 SharedHeap::SO_AllClasses, | |
3984 scan_root_cl, | |
3985 &only_scan_heap_rs_cl, | |
3986 scan_so_cl, | |
3987 scan_perm_cl, | |
3988 i); | |
3989 pss.end_strong_roots(); | |
3990 { | |
3991 double start = os::elapsedTime(); | |
3992 G1ParEvacuateFollowersClosure evac(_g1h, &pss, _queues, &_terminator); | |
3993 evac.do_void(); | |
3994 double elapsed_ms = (os::elapsedTime()-start)*1000.0; | |
3995 double term_ms = pss.term_time()*1000.0; | |
3996 _g1h->g1_policy()->record_obj_copy_time(i, elapsed_ms-term_ms); | |
3997 _g1h->g1_policy()->record_termination_time(i, term_ms); | |
3998 } | |
751 | 3999 if (G1UseSurvivorSpaces) { |
545 | 4000 _g1h->g1_policy()->record_thread_age_table(pss.age_table()); |
4001 } | |
342 | 4002 _g1h->update_surviving_young_words(pss.surviving_young_words()+1); |
4003 | |
4004 // Clean up any par-expanded rem sets. | |
4005 HeapRegionRemSet::par_cleanup(); | |
4006 | |
4007 MutexLocker x(stats_lock()); | |
4008 if (ParallelGCVerbose) { | |
4009 gclog_or_tty->print("Thread %d complete:\n", i); | |
4010 #if G1_DETAILED_STATS | |
4011 gclog_or_tty->print(" Pushes: %7d Pops: %7d Overflows: %7d Steals %7d (in %d attempts)\n", | |
4012 pss.pushes(), | |
4013 pss.pops(), | |
4014 pss.overflow_pushes(), | |
4015 pss.steals(), | |
4016 pss.steal_attempts()); | |
4017 #endif | |
4018 double elapsed = pss.elapsed(); | |
4019 double strong_roots = pss.strong_roots_time(); | |
4020 double term = pss.term_time(); | |
4021 gclog_or_tty->print(" Elapsed: %7.2f ms.\n" | |
4022 " Strong roots: %7.2f ms (%6.2f%%)\n" | |
4023 " Termination: %7.2f ms (%6.2f%%) (in %d entries)\n", | |
4024 elapsed * 1000.0, | |
4025 strong_roots * 1000.0, (strong_roots*100.0/elapsed), | |
4026 term * 1000.0, (term*100.0/elapsed), | |
4027 pss.term_attempts()); | |
4028 size_t total_waste = pss.alloc_buffer_waste() + pss.undo_waste(); | |
4029 gclog_or_tty->print(" Waste: %8dK\n" | |
4030 " Alloc Buffer: %8dK\n" | |
4031 " Undo: %8dK\n", | |
4032 (total_waste * HeapWordSize) / K, | |
4033 (pss.alloc_buffer_waste() * HeapWordSize) / K, | |
4034 (pss.undo_waste() * HeapWordSize) / K); | |
4035 } | |
4036 | |
4037 assert(pss.refs_to_scan() == 0, "Task queue should be empty"); | |
4038 assert(pss.overflowed_refs_to_scan() == 0, "Overflow queue should be empty"); | |
4039 } | |
4040 }; | |
4041 | |
4042 // *** Common G1 Evacuation Stuff | |
4043 | |
4044 void | |
4045 G1CollectedHeap:: | |
4046 g1_process_strong_roots(bool collecting_perm_gen, | |
4047 SharedHeap::ScanningOption so, | |
4048 OopClosure* scan_non_heap_roots, | |
4049 OopsInHeapRegionClosure* scan_rs, | |
4050 OopsInHeapRegionClosure* scan_so, | |
4051 OopsInGenClosure* scan_perm, | |
4052 int worker_i) { | |
4053 // First scan the strong roots, including the perm gen. | |
4054 double ext_roots_start = os::elapsedTime(); | |
4055 double closure_app_time_sec = 0.0; | |
4056 | |
4057 BufferingOopClosure buf_scan_non_heap_roots(scan_non_heap_roots); | |
4058 BufferingOopsInGenClosure buf_scan_perm(scan_perm); | |
4059 buf_scan_perm.set_generation(perm_gen()); | |
4060 | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
890
diff
changeset
|
4061 // Walk the code cache w/o buffering, because StarTask cannot handle |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
890
diff
changeset
|
4062 // unaligned oop locations. |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
890
diff
changeset
|
4063 CodeBlobToOopClosure eager_scan_code_roots(scan_non_heap_roots, /*do_marking=*/ true); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
890
diff
changeset
|
4064 |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
890
diff
changeset
|
4065 process_strong_roots(false, // no scoping; this is parallel code |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
890
diff
changeset
|
4066 collecting_perm_gen, so, |
342 | 4067 &buf_scan_non_heap_roots, |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
890
diff
changeset
|
4068 &eager_scan_code_roots, |
342 | 4069 &buf_scan_perm); |
4070 // Finish up any enqueued closure apps. | |
4071 buf_scan_non_heap_roots.done(); | |
4072 buf_scan_perm.done(); | |
4073 double ext_roots_end = os::elapsedTime(); | |
4074 g1_policy()->reset_obj_copy_time(worker_i); | |
4075 double obj_copy_time_sec = | |
4076 buf_scan_non_heap_roots.closure_app_seconds() + | |
4077 buf_scan_perm.closure_app_seconds(); | |
4078 g1_policy()->record_obj_copy_time(worker_i, obj_copy_time_sec * 1000.0); | |
4079 double ext_root_time_ms = | |
4080 ((ext_roots_end - ext_roots_start) - obj_copy_time_sec) * 1000.0; | |
4081 g1_policy()->record_ext_root_scan_time(worker_i, ext_root_time_ms); | |
4082 | |
4083 // Scan strong roots in mark stack. | |
4084 if (!_process_strong_tasks->is_task_claimed(G1H_PS_mark_stack_oops_do)) { | |
4085 concurrent_mark()->oops_do(scan_non_heap_roots); | |
4086 } | |
4087 double mark_stack_scan_ms = (os::elapsedTime() - ext_roots_end) * 1000.0; | |
4088 g1_policy()->record_mark_stack_scan_time(worker_i, mark_stack_scan_ms); | |
4089 | |
4090 // XXX What should this be doing in the parallel case? | |
4091 g1_policy()->record_collection_pause_end_CH_strong_roots(); | |
4092 if (scan_so != NULL) { | |
4093 scan_scan_only_set(scan_so, worker_i); | |
4094 } | |
4095 // Now scan the complement of the collection set. | |
4096 if (scan_rs != NULL) { | |
4097 g1_rem_set()->oops_into_collection_set_do(scan_rs, worker_i); | |
4098 } | |
4099 // Finish with the ref_processor roots. | |
4100 if (!_process_strong_tasks->is_task_claimed(G1H_PS_refProcessor_oops_do)) { | |
4101 ref_processor()->oops_do(scan_non_heap_roots); | |
4102 } | |
4103 g1_policy()->record_collection_pause_end_G1_strong_roots(); | |
4104 _process_strong_tasks->all_tasks_completed(); | |
4105 } | |
4106 | |
4107 void | |
4108 G1CollectedHeap::scan_scan_only_region(HeapRegion* r, | |
4109 OopsInHeapRegionClosure* oc, | |
4110 int worker_i) { | |
4111 HeapWord* startAddr = r->bottom(); | |
4112 HeapWord* endAddr = r->used_region().end(); | |
4113 | |
4114 oc->set_region(r); | |
4115 | |
4116 HeapWord* p = r->bottom(); | |
4117 HeapWord* t = r->top(); | |
4118 guarantee( p == r->next_top_at_mark_start(), "invariant" ); | |
4119 while (p < t) { | |
4120 oop obj = oop(p); | |
4121 p += obj->oop_iterate(oc); | |
4122 } | |
4123 } | |
4124 | |
4125 void | |
4126 G1CollectedHeap::scan_scan_only_set(OopsInHeapRegionClosure* oc, | |
4127 int worker_i) { | |
4128 double start = os::elapsedTime(); | |
4129 | |
4130 BufferingOopsInHeapRegionClosure boc(oc); | |
4131 | |
4132 FilterInHeapRegionAndIntoCSClosure scan_only(this, &boc); | |
4133 FilterAndMarkInHeapRegionAndIntoCSClosure scan_and_mark(this, &boc, concurrent_mark()); | |
4134 | |
4135 OopsInHeapRegionClosure *foc; | |
4136 if (g1_policy()->should_initiate_conc_mark()) | |
4137 foc = &scan_and_mark; | |
4138 else | |
4139 foc = &scan_only; | |
4140 | |
4141 HeapRegion* hr; | |
4142 int n = 0; | |
4143 while ((hr = _young_list->par_get_next_scan_only_region()) != NULL) { | |
4144 scan_scan_only_region(hr, foc, worker_i); | |
4145 ++n; | |
4146 } | |
4147 boc.done(); | |
4148 | |
4149 double closure_app_s = boc.closure_app_seconds(); | |
4150 g1_policy()->record_obj_copy_time(worker_i, closure_app_s * 1000.0); | |
4151 double ms = (os::elapsedTime() - start - closure_app_s)*1000.0; | |
4152 g1_policy()->record_scan_only_time(worker_i, ms, n); | |
4153 } | |
4154 | |
4155 void | |
4156 G1CollectedHeap::g1_process_weak_roots(OopClosure* root_closure, | |
4157 OopClosure* non_root_closure) { | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
890
diff
changeset
|
4158 CodeBlobToOopClosure roots_in_blobs(root_closure, /*do_marking=*/ false); |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
890
diff
changeset
|
4159 SharedHeap::process_weak_roots(root_closure, &roots_in_blobs, non_root_closure); |
342 | 4160 } |
4161 | |
4162 | |
4163 class SaveMarksClosure: public HeapRegionClosure { | |
4164 public: | |
4165 bool doHeapRegion(HeapRegion* r) { | |
4166 r->save_marks(); | |
4167 return false; | |
4168 } | |
4169 }; | |
4170 | |
4171 void G1CollectedHeap::save_marks() { | |
4172 if (ParallelGCThreads == 0) { | |
4173 SaveMarksClosure sm; | |
4174 heap_region_iterate(&sm); | |
4175 } | |
4176 // We do this even in the parallel case | |
4177 perm_gen()->save_marks(); | |
4178 } | |
4179 | |
4180 void G1CollectedHeap::evacuate_collection_set() { | |
4181 set_evacuation_failed(false); | |
4182 | |
4183 g1_rem_set()->prepare_for_oops_into_collection_set_do(); | |
4184 concurrent_g1_refine()->set_use_cache(false); | |
889 | 4185 concurrent_g1_refine()->clear_hot_cache_claimed_index(); |
4186 | |
342 | 4187 int n_workers = (ParallelGCThreads > 0 ? workers()->total_workers() : 1); |
4188 set_par_threads(n_workers); | |
4189 G1ParTask g1_par_task(this, n_workers, _task_queues); | |
4190 | |
4191 init_for_evac_failure(NULL); | |
4192 | |
4193 rem_set()->prepare_for_younger_refs_iterate(true); | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
4194 |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
4195 assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty"); |
342 | 4196 double start_par = os::elapsedTime(); |
4197 if (ParallelGCThreads > 0) { | |
4198 // The individual threads will set their evac-failure closures. | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
890
diff
changeset
|
4199 StrongRootsScope srs(this); |
342 | 4200 workers()->run_task(&g1_par_task); |
4201 } else { | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
890
diff
changeset
|
4202 StrongRootsScope srs(this); |
342 | 4203 g1_par_task.work(0); |
4204 } | |
4205 | |
4206 double par_time = (os::elapsedTime() - start_par) * 1000.0; | |
4207 g1_policy()->record_par_time(par_time); | |
4208 set_par_threads(0); | |
4209 // Is this the right thing to do here? We don't save marks | |
4210 // on individual heap regions when we allocate from | |
4211 // them in parallel, so this seems like the correct place for this. | |
545 | 4212 retire_all_alloc_regions(); |
342 | 4213 { |
4214 G1IsAliveClosure is_alive(this); | |
4215 G1KeepAliveClosure keep_alive(this); | |
4216 JNIHandles::weak_oops_do(&is_alive, &keep_alive); | |
4217 } | |
940
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4218 release_gc_alloc_regions(false /* totally */); |
342 | 4219 g1_rem_set()->cleanup_after_oops_into_collection_set_do(); |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
4220 |
889 | 4221 concurrent_g1_refine()->clear_hot_cache(); |
342 | 4222 concurrent_g1_refine()->set_use_cache(true); |
4223 | |
4224 finalize_for_evac_failure(); | |
4225 | |
4226 // Must do this before removing self-forwarding pointers, which clears | |
4227 // the per-region evac-failure flags. | |
4228 concurrent_mark()->complete_marking_in_collection_set(); | |
4229 | |
4230 if (evacuation_failed()) { | |
4231 remove_self_forwarding_pointers(); | |
4232 if (PrintGCDetails) { | |
4233 gclog_or_tty->print(" (evacuation failed)"); | |
4234 } else if (PrintGC) { | |
4235 gclog_or_tty->print("--"); | |
4236 } | |
4237 } | |
4238 | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
4239 if (G1DeferredRSUpdate) { |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
4240 RedirtyLoggedCardTableEntryFastClosure redirty; |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
4241 dirty_card_queue_set().set_closure(&redirty); |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
4242 dirty_card_queue_set().apply_closure_to_all_completed_buffers(); |
1111 | 4243 |
4244 DirtyCardQueueSet& dcq = JavaThread::dirty_card_queue_set(); | |
4245 dcq.merge_bufferlists(&dirty_card_queue_set()); | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
4246 assert(dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed"); |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
595
diff
changeset
|
4247 } |
342 | 4248 COMPILER2_PRESENT(DerivedPointerTable::update_pointers()); |
4249 } | |
4250 | |
4251 void G1CollectedHeap::free_region(HeapRegion* hr) { | |
4252 size_t pre_used = 0; | |
4253 size_t cleared_h_regions = 0; | |
4254 size_t freed_regions = 0; | |
4255 UncleanRegionList local_list; | |
4256 | |
4257 HeapWord* start = hr->bottom(); | |
4258 HeapWord* end = hr->prev_top_at_mark_start(); | |
4259 size_t used_bytes = hr->used(); | |
4260 size_t live_bytes = hr->max_live_bytes(); | |
4261 if (used_bytes > 0) { | |
4262 guarantee( live_bytes <= used_bytes, "invariant" ); | |
4263 } else { | |
4264 guarantee( live_bytes == 0, "invariant" ); | |
4265 } | |
4266 | |
4267 size_t garbage_bytes = used_bytes - live_bytes; | |
4268 if (garbage_bytes > 0) | |
4269 g1_policy()->decrease_known_garbage_bytes(garbage_bytes); | |
4270 | |
4271 free_region_work(hr, pre_used, cleared_h_regions, freed_regions, | |
4272 &local_list); | |
4273 finish_free_region_work(pre_used, cleared_h_regions, freed_regions, | |
4274 &local_list); | |
4275 } | |
4276 | |
4277 void | |
4278 G1CollectedHeap::free_region_work(HeapRegion* hr, | |
4279 size_t& pre_used, | |
4280 size_t& cleared_h_regions, | |
4281 size_t& freed_regions, | |
4282 UncleanRegionList* list, | |
4283 bool par) { | |
4284 pre_used += hr->used(); | |
4285 if (hr->isHumongous()) { | |
4286 assert(hr->startsHumongous(), | |
4287 "Only the start of a humongous region should be freed."); | |
4288 int ind = _hrs->find(hr); | |
4289 assert(ind != -1, "Should have an index."); | |
4290 // Clear the start region. | |
4291 hr->hr_clear(par, true /*clear_space*/); | |
4292 list->insert_before_head(hr); | |
4293 cleared_h_regions++; | |
4294 freed_regions++; | |
4295 // Clear any continued regions. | |
4296 ind++; | |
4297 while ((size_t)ind < n_regions()) { | |
4298 HeapRegion* hrc = _hrs->at(ind); | |
4299 if (!hrc->continuesHumongous()) break; | |
4300 // Otherwise, does continue the H region. | |
4301 assert(hrc->humongous_start_region() == hr, "Huh?"); | |
4302 hrc->hr_clear(par, true /*clear_space*/); | |
4303 cleared_h_regions++; | |
4304 freed_regions++; | |
4305 list->insert_before_head(hrc); | |
4306 ind++; | |
4307 } | |
4308 } else { | |
4309 hr->hr_clear(par, true /*clear_space*/); | |
4310 list->insert_before_head(hr); | |
4311 freed_regions++; | |
4312 // If we're using clear2, this should not be enabled. | |
4313 // assert(!hr->in_cohort(), "Can't be both free and in a cohort."); | |
4314 } | |
4315 } | |
4316 | |
4317 void G1CollectedHeap::finish_free_region_work(size_t pre_used, | |
4318 size_t cleared_h_regions, | |
4319 size_t freed_regions, | |
4320 UncleanRegionList* list) { | |
4321 if (list != NULL && list->sz() > 0) { | |
4322 prepend_region_list_on_unclean_list(list); | |
4323 } | |
4324 // Acquire a lock, if we're parallel, to update possibly-shared | |
4325 // variables. | |
4326 Mutex* lock = (n_par_threads() > 0) ? ParGCRareEvent_lock : NULL; | |
4327 { | |
4328 MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag); | |
4329 _summary_bytes_used -= pre_used; | |
4330 _num_humongous_regions -= (int) cleared_h_regions; | |
4331 _free_regions += freed_regions; | |
4332 } | |
4333 } | |
4334 | |
4335 | |
4336 void G1CollectedHeap::dirtyCardsForYoungRegions(CardTableModRefBS* ct_bs, HeapRegion* list) { | |
4337 while (list != NULL) { | |
4338 guarantee( list->is_young(), "invariant" ); | |
4339 | |
4340 HeapWord* bottom = list->bottom(); | |
4341 HeapWord* end = list->end(); | |
4342 MemRegion mr(bottom, end); | |
4343 ct_bs->dirty(mr); | |
4344 | |
4345 list = list->get_next_young_region(); | |
4346 } | |
4347 } | |
4348 | |
796
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4349 |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4350 class G1ParCleanupCTTask : public AbstractGangTask { |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4351 CardTableModRefBS* _ct_bs; |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4352 G1CollectedHeap* _g1h; |
940
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4353 HeapRegion* volatile _so_head; |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4354 HeapRegion* volatile _su_head; |
796
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4355 public: |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4356 G1ParCleanupCTTask(CardTableModRefBS* ct_bs, |
940
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4357 G1CollectedHeap* g1h, |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4358 HeapRegion* scan_only_list, |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4359 HeapRegion* survivor_list) : |
796
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4360 AbstractGangTask("G1 Par Cleanup CT Task"), |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4361 _ct_bs(ct_bs), |
940
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4362 _g1h(g1h), |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4363 _so_head(scan_only_list), |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4364 _su_head(survivor_list) |
796
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4365 { } |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4366 |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4367 void work(int i) { |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4368 HeapRegion* r; |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4369 while (r = _g1h->pop_dirty_cards_region()) { |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4370 clear_cards(r); |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4371 } |
940
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4372 // Redirty the cards of the scan-only and survivor regions. |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4373 dirty_list(&this->_so_head); |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4374 dirty_list(&this->_su_head); |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4375 } |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4376 |
796
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4377 void clear_cards(HeapRegion* r) { |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4378 // Cards for Survivor and Scan-Only regions will be dirtied later. |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4379 if (!r->is_scan_only() && !r->is_survivor()) { |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4380 _ct_bs->clear(MemRegion(r->bottom(), r->end())); |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4381 } |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4382 } |
940
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4383 |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4384 void dirty_list(HeapRegion* volatile * head_ptr) { |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4385 HeapRegion* head; |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4386 do { |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4387 // Pop region off the list. |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4388 head = *head_ptr; |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4389 if (head != NULL) { |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4390 HeapRegion* r = (HeapRegion*) |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4391 Atomic::cmpxchg_ptr(head->get_next_young_region(), head_ptr, head); |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4392 if (r == head) { |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4393 assert(!r->isHumongous(), "Humongous regions shouldn't be on survivor list"); |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4394 _ct_bs->dirty(MemRegion(r->bottom(), r->end())); |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4395 } |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4396 } |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4397 } while (*head_ptr != NULL); |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4398 } |
796
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4399 }; |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4400 |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4401 |
940
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4402 #ifndef PRODUCT |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4403 class G1VerifyCardTableCleanup: public HeapRegionClosure { |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4404 CardTableModRefBS* _ct_bs; |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4405 public: |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4406 G1VerifyCardTableCleanup(CardTableModRefBS* ct_bs) |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4407 : _ct_bs(ct_bs) |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4408 { } |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4409 virtual bool doHeapRegion(HeapRegion* r) |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4410 { |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4411 MemRegion mr(r->bottom(), r->end()); |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4412 if (r->is_scan_only() || r->is_survivor()) { |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4413 _ct_bs->verify_dirty_region(mr); |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4414 } else { |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4415 _ct_bs->verify_clean_region(mr); |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4416 } |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4417 return false; |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4418 } |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4419 }; |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4420 #endif |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4421 |
342 | 4422 void G1CollectedHeap::cleanUpCardTable() { |
4423 CardTableModRefBS* ct_bs = (CardTableModRefBS*) (barrier_set()); | |
4424 double start = os::elapsedTime(); | |
4425 | |
796
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4426 // Iterate over the dirty cards region list. |
940
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4427 G1ParCleanupCTTask cleanup_task(ct_bs, this, |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4428 _young_list->first_scan_only_region(), |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4429 _young_list->first_survivor_region()); |
796
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4430 if (ParallelGCThreads > 0) { |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4431 set_par_threads(workers()->total_workers()); |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4432 workers()->run_task(&cleanup_task); |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4433 set_par_threads(0); |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4434 } else { |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4435 while (_dirty_cards_region_list) { |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4436 HeapRegion* r = _dirty_cards_region_list; |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4437 cleanup_task.clear_cards(r); |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4438 _dirty_cards_region_list = r->get_next_dirty_cards_region(); |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4439 if (_dirty_cards_region_list == r) { |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4440 // The last region. |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4441 _dirty_cards_region_list = NULL; |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4442 } |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4443 r->set_next_dirty_cards_region(NULL); |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
4444 } |
940
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4445 // now, redirty the cards of the scan-only and survivor regions |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4446 // (it seemed faster to do it this way, instead of iterating over |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4447 // all regions and then clearing / dirtying as appropriate) |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4448 dirtyCardsForYoungRegions(ct_bs, _young_list->first_scan_only_region()); |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4449 dirtyCardsForYoungRegions(ct_bs, _young_list->first_survivor_region()); |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4450 } |
342 | 4451 double elapsed = os::elapsedTime() - start; |
4452 g1_policy()->record_clear_ct_time( elapsed * 1000.0); | |
940
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4453 #ifndef PRODUCT |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4454 if (G1VerifyCTCleanup || VerifyAfterGC) { |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4455 G1VerifyCardTableCleanup cleanup_verifier(ct_bs); |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4456 heap_region_iterate(&cleanup_verifier); |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4457 } |
8624da129f0b
6841313: G1: dirty cards of survivor regions in parallel
apetrusenko
parents:
936
diff
changeset
|
4458 #endif |
342 | 4459 } |
4460 | |
4461 void G1CollectedHeap::do_collection_pause_if_appropriate(size_t word_size) { | |
4462 if (g1_policy()->should_do_collection_pause(word_size)) { | |
4463 do_collection_pause(); | |
4464 } | |
4465 } | |
4466 | |
4467 void G1CollectedHeap::free_collection_set(HeapRegion* cs_head) { | |
4468 double young_time_ms = 0.0; | |
4469 double non_young_time_ms = 0.0; | |
4470 | |
4471 G1CollectorPolicy* policy = g1_policy(); | |
4472 | |
4473 double start_sec = os::elapsedTime(); | |
4474 bool non_young = true; | |
4475 | |
4476 HeapRegion* cur = cs_head; | |
4477 int age_bound = -1; | |
4478 size_t rs_lengths = 0; | |
4479 | |
4480 while (cur != NULL) { | |
4481 if (non_young) { | |
4482 if (cur->is_young()) { | |
4483 double end_sec = os::elapsedTime(); | |
4484 double elapsed_ms = (end_sec - start_sec) * 1000.0; | |
4485 non_young_time_ms += elapsed_ms; | |
4486 | |
4487 start_sec = os::elapsedTime(); | |
4488 non_young = false; | |
4489 } | |
4490 } else { | |
4491 if (!cur->is_on_free_list()) { | |
4492 double end_sec = os::elapsedTime(); | |
4493 double elapsed_ms = (end_sec - start_sec) * 1000.0; | |
4494 young_time_ms += elapsed_ms; | |
4495 | |
4496 start_sec = os::elapsedTime(); | |
4497 non_young = true; | |
4498 } | |
4499 } | |
4500 | |
4501 rs_lengths += cur->rem_set()->occupied(); | |
4502 | |
4503 HeapRegion* next = cur->next_in_collection_set(); | |
4504 assert(cur->in_collection_set(), "bad CS"); | |
4505 cur->set_next_in_collection_set(NULL); | |
4506 cur->set_in_collection_set(false); | |
4507 | |
4508 if (cur->is_young()) { | |
4509 int index = cur->young_index_in_cset(); | |
4510 guarantee( index != -1, "invariant" ); | |
4511 guarantee( (size_t)index < policy->young_cset_length(), "invariant" ); | |
4512 size_t words_survived = _surviving_young_words[index]; | |
4513 cur->record_surv_words_in_group(words_survived); | |
4514 } else { | |
4515 int index = cur->young_index_in_cset(); | |
4516 guarantee( index == -1, "invariant" ); | |
4517 } | |
4518 | |
4519 assert( (cur->is_young() && cur->young_index_in_cset() > -1) || | |
4520 (!cur->is_young() && cur->young_index_in_cset() == -1), | |
4521 "invariant" ); | |
4522 | |
4523 if (!cur->evacuation_failed()) { | |
4524 // And the region is empty. | |
4525 assert(!cur->is_empty(), | |
4526 "Should not have empty regions in a CS."); | |
4527 free_region(cur); | |
4528 } else { | |
4529 guarantee( !cur->is_scan_only(), "should not be scan only" ); | |
4530 cur->uninstall_surv_rate_group(); | |
4531 if (cur->is_young()) | |
4532 cur->set_young_index_in_cset(-1); | |
4533 cur->set_not_young(); | |
4534 cur->set_evacuation_failed(false); | |
4535 } | |
4536 cur = next; | |
4537 } | |
4538 | |
4539 policy->record_max_rs_lengths(rs_lengths); | |
4540 policy->cset_regions_freed(); | |
4541 | |
4542 double end_sec = os::elapsedTime(); | |
4543 double elapsed_ms = (end_sec - start_sec) * 1000.0; | |
4544 if (non_young) | |
4545 non_young_time_ms += elapsed_ms; | |
4546 else | |
4547 young_time_ms += elapsed_ms; | |
4548 | |
4549 policy->record_young_free_cset_time_ms(young_time_ms); | |
4550 policy->record_non_young_free_cset_time_ms(non_young_time_ms); | |
4551 } | |
4552 | |
4553 HeapRegion* | |
4554 G1CollectedHeap::alloc_region_from_unclean_list_locked(bool zero_filled) { | |
4555 assert(ZF_mon->owned_by_self(), "Precondition"); | |
4556 HeapRegion* res = pop_unclean_region_list_locked(); | |
4557 if (res != NULL) { | |
4558 assert(!res->continuesHumongous() && | |
4559 res->zero_fill_state() != HeapRegion::Allocated, | |
4560 "Only free regions on unclean list."); | |
4561 if (zero_filled) { | |
4562 res->ensure_zero_filled_locked(); | |
4563 res->set_zero_fill_allocated(); | |
4564 } | |
4565 } | |
4566 return res; | |
4567 } | |
4568 | |
4569 HeapRegion* G1CollectedHeap::alloc_region_from_unclean_list(bool zero_filled) { | |
4570 MutexLockerEx zx(ZF_mon, Mutex::_no_safepoint_check_flag); | |
4571 return alloc_region_from_unclean_list_locked(zero_filled); | |
4572 } | |
4573 | |
4574 void G1CollectedHeap::put_region_on_unclean_list(HeapRegion* r) { | |
4575 MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag); | |
4576 put_region_on_unclean_list_locked(r); | |
4577 if (should_zf()) ZF_mon->notify_all(); // Wake up ZF thread. | |
4578 } | |
4579 | |
4580 void G1CollectedHeap::set_unclean_regions_coming(bool b) { | |
4581 MutexLockerEx x(Cleanup_mon); | |
4582 set_unclean_regions_coming_locked(b); | |
4583 } | |
4584 | |
4585 void G1CollectedHeap::set_unclean_regions_coming_locked(bool b) { | |
4586 assert(Cleanup_mon->owned_by_self(), "Precondition"); | |
4587 _unclean_regions_coming = b; | |
4588 // Wake up mutator threads that might be waiting for completeCleanup to | |
4589 // finish. | |
4590 if (!b) Cleanup_mon->notify_all(); | |
4591 } | |
4592 | |
4593 void G1CollectedHeap::wait_for_cleanup_complete() { | |
4594 MutexLockerEx x(Cleanup_mon); | |
4595 wait_for_cleanup_complete_locked(); | |
4596 } | |
4597 | |
4598 void G1CollectedHeap::wait_for_cleanup_complete_locked() { | |
4599 assert(Cleanup_mon->owned_by_self(), "precondition"); | |
4600 while (_unclean_regions_coming) { | |
4601 Cleanup_mon->wait(); | |
4602 } | |
4603 } | |
4604 | |
4605 void | |
4606 G1CollectedHeap::put_region_on_unclean_list_locked(HeapRegion* r) { | |
4607 assert(ZF_mon->owned_by_self(), "precondition."); | |
4608 _unclean_region_list.insert_before_head(r); | |
4609 } | |
4610 | |
4611 void | |
4612 G1CollectedHeap::prepend_region_list_on_unclean_list(UncleanRegionList* list) { | |
4613 MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag); | |
4614 prepend_region_list_on_unclean_list_locked(list); | |
4615 if (should_zf()) ZF_mon->notify_all(); // Wake up ZF thread. | |
4616 } | |
4617 | |
4618 void | |
4619 G1CollectedHeap:: | |
4620 prepend_region_list_on_unclean_list_locked(UncleanRegionList* list) { | |
4621 assert(ZF_mon->owned_by_self(), "precondition."); | |
4622 _unclean_region_list.prepend_list(list); | |
4623 } | |
4624 | |
4625 HeapRegion* G1CollectedHeap::pop_unclean_region_list_locked() { | |
4626 assert(ZF_mon->owned_by_self(), "precondition."); | |
4627 HeapRegion* res = _unclean_region_list.pop(); | |
4628 if (res != NULL) { | |
4629 // Inform ZF thread that there's a new unclean head. | |
4630 if (_unclean_region_list.hd() != NULL && should_zf()) | |
4631 ZF_mon->notify_all(); | |
4632 } | |
4633 return res; | |
4634 } | |
4635 | |
4636 HeapRegion* G1CollectedHeap::peek_unclean_region_list_locked() { | |
4637 assert(ZF_mon->owned_by_self(), "precondition."); | |
4638 return _unclean_region_list.hd(); | |
4639 } | |
4640 | |
4641 | |
4642 bool G1CollectedHeap::move_cleaned_region_to_free_list_locked() { | |
4643 assert(ZF_mon->owned_by_self(), "Precondition"); | |
4644 HeapRegion* r = peek_unclean_region_list_locked(); | |
4645 if (r != NULL && r->zero_fill_state() == HeapRegion::ZeroFilled) { | |
4646 // Result of below must be equal to "r", since we hold the lock. | |
4647 (void)pop_unclean_region_list_locked(); | |
4648 put_free_region_on_list_locked(r); | |
4649 return true; | |
4650 } else { | |
4651 return false; | |
4652 } | |
4653 } | |
4654 | |
4655 bool G1CollectedHeap::move_cleaned_region_to_free_list() { | |
4656 MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag); | |
4657 return move_cleaned_region_to_free_list_locked(); | |
4658 } | |
4659 | |
4660 | |
4661 void G1CollectedHeap::put_free_region_on_list_locked(HeapRegion* r) { | |
4662 assert(ZF_mon->owned_by_self(), "precondition."); | |
4663 assert(_free_region_list_size == free_region_list_length(), "Inv"); | |
4664 assert(r->zero_fill_state() == HeapRegion::ZeroFilled, | |
4665 "Regions on free list must be zero filled"); | |
4666 assert(!r->isHumongous(), "Must not be humongous."); | |
4667 assert(r->is_empty(), "Better be empty"); | |
4668 assert(!r->is_on_free_list(), | |
4669 "Better not already be on free list"); | |
4670 assert(!r->is_on_unclean_list(), | |
4671 "Better not already be on unclean list"); | |
4672 r->set_on_free_list(true); | |
4673 r->set_next_on_free_list(_free_region_list); | |
4674 _free_region_list = r; | |
4675 _free_region_list_size++; | |
4676 assert(_free_region_list_size == free_region_list_length(), "Inv"); | |
4677 } | |
4678 | |
4679 void G1CollectedHeap::put_free_region_on_list(HeapRegion* r) { | |
4680 MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag); | |
4681 put_free_region_on_list_locked(r); | |
4682 } | |
4683 | |
4684 HeapRegion* G1CollectedHeap::pop_free_region_list_locked() { | |
4685 assert(ZF_mon->owned_by_self(), "precondition."); | |
4686 assert(_free_region_list_size == free_region_list_length(), "Inv"); | |
4687 HeapRegion* res = _free_region_list; | |
4688 if (res != NULL) { | |
4689 _free_region_list = res->next_from_free_list(); | |
4690 _free_region_list_size--; | |
4691 res->set_on_free_list(false); | |
4692 res->set_next_on_free_list(NULL); | |
4693 assert(_free_region_list_size == free_region_list_length(), "Inv"); | |
4694 } | |
4695 return res; | |
4696 } | |
4697 | |
4698 | |
4699 HeapRegion* G1CollectedHeap::alloc_free_region_from_lists(bool zero_filled) { | |
4700 // By self, or on behalf of self. | |
4701 assert(Heap_lock->is_locked(), "Precondition"); | |
4702 HeapRegion* res = NULL; | |
4703 bool first = true; | |
4704 while (res == NULL) { | |
4705 if (zero_filled || !first) { | |
4706 MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag); | |
4707 res = pop_free_region_list_locked(); | |
4708 if (res != NULL) { | |
4709 assert(!res->zero_fill_is_allocated(), | |
4710 "No allocated regions on free list."); | |
4711 res->set_zero_fill_allocated(); | |
4712 } else if (!first) { | |
4713 break; // We tried both, time to return NULL. | |
4714 } | |
4715 } | |
4716 | |
4717 if (res == NULL) { | |
4718 res = alloc_region_from_unclean_list(zero_filled); | |
4719 } | |
4720 assert(res == NULL || | |
4721 !zero_filled || | |
4722 res->zero_fill_is_allocated(), | |
4723 "We must have allocated the region we're returning"); | |
4724 first = false; | |
4725 } | |
4726 return res; | |
4727 } | |
4728 | |
4729 void G1CollectedHeap::remove_allocated_regions_from_lists() { | |
4730 MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag); | |
4731 { | |
4732 HeapRegion* prev = NULL; | |
4733 HeapRegion* cur = _unclean_region_list.hd(); | |
4734 while (cur != NULL) { | |
4735 HeapRegion* next = cur->next_from_unclean_list(); | |
4736 if (cur->zero_fill_is_allocated()) { | |
4737 // Remove from the list. | |
4738 if (prev == NULL) { | |
4739 (void)_unclean_region_list.pop(); | |
4740 } else { | |
4741 _unclean_region_list.delete_after(prev); | |
4742 } | |
4743 cur->set_on_unclean_list(false); | |
4744 cur->set_next_on_unclean_list(NULL); | |
4745 } else { | |
4746 prev = cur; | |
4747 } | |
4748 cur = next; | |
4749 } | |
4750 assert(_unclean_region_list.sz() == unclean_region_list_length(), | |
4751 "Inv"); | |
4752 } | |
4753 | |
4754 { | |
4755 HeapRegion* prev = NULL; | |
4756 HeapRegion* cur = _free_region_list; | |
4757 while (cur != NULL) { | |
4758 HeapRegion* next = cur->next_from_free_list(); | |
4759 if (cur->zero_fill_is_allocated()) { | |
4760 // Remove from the list. | |
4761 if (prev == NULL) { | |
4762 _free_region_list = cur->next_from_free_list(); | |
4763 } else { | |
4764 prev->set_next_on_free_list(cur->next_from_free_list()); | |
4765 } | |
4766 cur->set_on_free_list(false); | |
4767 cur->set_next_on_free_list(NULL); | |
4768 _free_region_list_size--; | |
4769 } else { | |
4770 prev = cur; | |
4771 } | |
4772 cur = next; | |
4773 } | |
4774 assert(_free_region_list_size == free_region_list_length(), "Inv"); | |
4775 } | |
4776 } | |
4777 | |
4778 bool G1CollectedHeap::verify_region_lists() { | |
4779 MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag); | |
4780 return verify_region_lists_locked(); | |
4781 } | |
4782 | |
4783 bool G1CollectedHeap::verify_region_lists_locked() { | |
4784 HeapRegion* unclean = _unclean_region_list.hd(); | |
4785 while (unclean != NULL) { | |
4786 guarantee(unclean->is_on_unclean_list(), "Well, it is!"); | |
4787 guarantee(!unclean->is_on_free_list(), "Well, it shouldn't be!"); | |
4788 guarantee(unclean->zero_fill_state() != HeapRegion::Allocated, | |
4789 "Everything else is possible."); | |
4790 unclean = unclean->next_from_unclean_list(); | |
4791 } | |
4792 guarantee(_unclean_region_list.sz() == unclean_region_list_length(), "Inv"); | |
4793 | |
4794 HeapRegion* free_r = _free_region_list; | |
4795 while (free_r != NULL) { | |
4796 assert(free_r->is_on_free_list(), "Well, it is!"); | |
4797 assert(!free_r->is_on_unclean_list(), "Well, it shouldn't be!"); | |
4798 switch (free_r->zero_fill_state()) { | |
4799 case HeapRegion::NotZeroFilled: | |
4800 case HeapRegion::ZeroFilling: | |
4801 guarantee(false, "Should not be on free list."); | |
4802 break; | |
4803 default: | |
4804 // Everything else is possible. | |
4805 break; | |
4806 } | |
4807 free_r = free_r->next_from_free_list(); | |
4808 } | |
4809 guarantee(_free_region_list_size == free_region_list_length(), "Inv"); | |
4810 // If we didn't do an assertion... | |
4811 return true; | |
4812 } | |
4813 | |
4814 size_t G1CollectedHeap::free_region_list_length() { | |
4815 assert(ZF_mon->owned_by_self(), "precondition."); | |
4816 size_t len = 0; | |
4817 HeapRegion* cur = _free_region_list; | |
4818 while (cur != NULL) { | |
4819 len++; | |
4820 cur = cur->next_from_free_list(); | |
4821 } | |
4822 return len; | |
4823 } | |
4824 | |
4825 size_t G1CollectedHeap::unclean_region_list_length() { | |
4826 assert(ZF_mon->owned_by_self(), "precondition."); | |
4827 return _unclean_region_list.length(); | |
4828 } | |
4829 | |
4830 size_t G1CollectedHeap::n_regions() { | |
4831 return _hrs->length(); | |
4832 } | |
4833 | |
4834 size_t G1CollectedHeap::max_regions() { | |
4835 return | |
4836 (size_t)align_size_up(g1_reserved_obj_bytes(), HeapRegion::GrainBytes) / | |
4837 HeapRegion::GrainBytes; | |
4838 } | |
4839 | |
4840 size_t G1CollectedHeap::free_regions() { | |
4841 /* Possibly-expensive assert. | |
4842 assert(_free_regions == count_free_regions(), | |
4843 "_free_regions is off."); | |
4844 */ | |
4845 return _free_regions; | |
4846 } | |
4847 | |
4848 bool G1CollectedHeap::should_zf() { | |
4849 return _free_region_list_size < (size_t) G1ConcZFMaxRegions; | |
4850 } | |
4851 | |
4852 class RegionCounter: public HeapRegionClosure { | |
4853 size_t _n; | |
4854 public: | |
4855 RegionCounter() : _n(0) {} | |
4856 bool doHeapRegion(HeapRegion* r) { | |
677 | 4857 if (r->is_empty()) { |
342 | 4858 assert(!r->isHumongous(), "H regions should not be empty."); |
4859 _n++; | |
4860 } | |
4861 return false; | |
4862 } | |
4863 int res() { return (int) _n; } | |
4864 }; | |
4865 | |
4866 size_t G1CollectedHeap::count_free_regions() { | |
4867 RegionCounter rc; | |
4868 heap_region_iterate(&rc); | |
4869 size_t n = rc.res(); | |
4870 if (_cur_alloc_region != NULL && _cur_alloc_region->is_empty()) | |
4871 n--; | |
4872 return n; | |
4873 } | |
4874 | |
4875 size_t G1CollectedHeap::count_free_regions_list() { | |
4876 size_t n = 0; | |
4877 size_t o = 0; | |
4878 ZF_mon->lock_without_safepoint_check(); | |
4879 HeapRegion* cur = _free_region_list; | |
4880 while (cur != NULL) { | |
4881 cur = cur->next_from_free_list(); | |
4882 n++; | |
4883 } | |
4884 size_t m = unclean_region_list_length(); | |
4885 ZF_mon->unlock(); | |
4886 return n + m; | |
4887 } | |
4888 | |
4889 bool G1CollectedHeap::should_set_young_locked() { | |
4890 assert(heap_lock_held_for_gc(), | |
4891 "the heap lock should already be held by or for this thread"); | |
4892 return (g1_policy()->in_young_gc_mode() && | |
4893 g1_policy()->should_add_next_region_to_young_list()); | |
4894 } | |
4895 | |
4896 void G1CollectedHeap::set_region_short_lived_locked(HeapRegion* hr) { | |
4897 assert(heap_lock_held_for_gc(), | |
4898 "the heap lock should already be held by or for this thread"); | |
4899 _young_list->push_region(hr); | |
4900 g1_policy()->set_region_short_lived(hr); | |
4901 } | |
4902 | |
4903 class NoYoungRegionsClosure: public HeapRegionClosure { | |
4904 private: | |
4905 bool _success; | |
4906 public: | |
4907 NoYoungRegionsClosure() : _success(true) { } | |
4908 bool doHeapRegion(HeapRegion* r) { | |
4909 if (r->is_young()) { | |
4910 gclog_or_tty->print_cr("Region ["PTR_FORMAT", "PTR_FORMAT") tagged as young", | |
4911 r->bottom(), r->end()); | |
4912 _success = false; | |
4913 } | |
4914 return false; | |
4915 } | |
4916 bool success() { return _success; } | |
4917 }; | |
4918 | |
4919 bool G1CollectedHeap::check_young_list_empty(bool ignore_scan_only_list, | |
4920 bool check_sample) { | |
4921 bool ret = true; | |
4922 | |
4923 ret = _young_list->check_list_empty(ignore_scan_only_list, check_sample); | |
4924 if (!ignore_scan_only_list) { | |
4925 NoYoungRegionsClosure closure; | |
4926 heap_region_iterate(&closure); | |
4927 ret = ret && closure.success(); | |
4928 } | |
4929 | |
4930 return ret; | |
4931 } | |
4932 | |
4933 void G1CollectedHeap::empty_young_list() { | |
4934 assert(heap_lock_held_for_gc(), | |
4935 "the heap lock should already be held by or for this thread"); | |
4936 assert(g1_policy()->in_young_gc_mode(), "should be in young GC mode"); | |
4937 | |
4938 _young_list->empty_list(); | |
4939 } | |
4940 | |
4941 bool G1CollectedHeap::all_alloc_regions_no_allocs_since_save_marks() { | |
4942 bool no_allocs = true; | |
4943 for (int ap = 0; ap < GCAllocPurposeCount && no_allocs; ++ap) { | |
4944 HeapRegion* r = _gc_alloc_regions[ap]; | |
4945 no_allocs = r == NULL || r->saved_mark_at_top(); | |
4946 } | |
4947 return no_allocs; | |
4948 } | |
4949 | |
545 | 4950 void G1CollectedHeap::retire_all_alloc_regions() { |
342 | 4951 for (int ap = 0; ap < GCAllocPurposeCount; ++ap) { |
4952 HeapRegion* r = _gc_alloc_regions[ap]; | |
4953 if (r != NULL) { | |
4954 // Check for aliases. | |
4955 bool has_processed_alias = false; | |
4956 for (int i = 0; i < ap; ++i) { | |
4957 if (_gc_alloc_regions[i] == r) { | |
4958 has_processed_alias = true; | |
4959 break; | |
4960 } | |
4961 } | |
4962 if (!has_processed_alias) { | |
545 | 4963 retire_alloc_region(r, false /* par */); |
342 | 4964 } |
4965 } | |
4966 } | |
4967 } | |
4968 | |
4969 | |
4970 // Done at the start of full GC. | |
4971 void G1CollectedHeap::tear_down_region_lists() { | |
4972 MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag); | |
4973 while (pop_unclean_region_list_locked() != NULL) ; | |
4974 assert(_unclean_region_list.hd() == NULL && _unclean_region_list.sz() == 0, | |
4975 "Postconditions of loop.") | |
4976 while (pop_free_region_list_locked() != NULL) ; | |
4977 assert(_free_region_list == NULL, "Postcondition of loop."); | |
4978 if (_free_region_list_size != 0) { | |
4979 gclog_or_tty->print_cr("Size is %d.", _free_region_list_size); | |
838
0316eac49d5a
6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set
tonyp
parents:
811
diff
changeset
|
4980 print_on(gclog_or_tty, true /* extended */); |
342 | 4981 } |
4982 assert(_free_region_list_size == 0, "Postconditions of loop."); | |
4983 } | |
4984 | |
4985 | |
4986 class RegionResetter: public HeapRegionClosure { | |
4987 G1CollectedHeap* _g1; | |
4988 int _n; | |
4989 public: | |
4990 RegionResetter() : _g1(G1CollectedHeap::heap()), _n(0) {} | |
4991 bool doHeapRegion(HeapRegion* r) { | |
4992 if (r->continuesHumongous()) return false; | |
4993 if (r->top() > r->bottom()) { | |
4994 if (r->top() < r->end()) { | |
4995 Copy::fill_to_words(r->top(), | |
4996 pointer_delta(r->end(), r->top())); | |
4997 } | |
4998 r->set_zero_fill_allocated(); | |
4999 } else { | |
5000 assert(r->is_empty(), "tautology"); | |
677 | 5001 _n++; |
5002 switch (r->zero_fill_state()) { | |
342 | 5003 case HeapRegion::NotZeroFilled: |
5004 case HeapRegion::ZeroFilling: | |
5005 _g1->put_region_on_unclean_list_locked(r); | |
5006 break; | |
5007 case HeapRegion::Allocated: | |
5008 r->set_zero_fill_complete(); | |
5009 // no break; go on to put on free list. | |
5010 case HeapRegion::ZeroFilled: | |
5011 _g1->put_free_region_on_list_locked(r); | |
5012 break; | |
5013 } | |
5014 } | |
5015 return false; | |
5016 } | |
5017 | |
5018 int getFreeRegionCount() {return _n;} | |
5019 }; | |
5020 | |
5021 // Done at the end of full GC. | |
5022 void G1CollectedHeap::rebuild_region_lists() { | |
5023 MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag); | |
5024 // This needs to go at the end of the full GC. | |
5025 RegionResetter rs; | |
5026 heap_region_iterate(&rs); | |
5027 _free_regions = rs.getFreeRegionCount(); | |
5028 // Tell the ZF thread it may have work to do. | |
5029 if (should_zf()) ZF_mon->notify_all(); | |
5030 } | |
5031 | |
5032 class UsedRegionsNeedZeroFillSetter: public HeapRegionClosure { | |
5033 G1CollectedHeap* _g1; | |
5034 int _n; | |
5035 public: | |
5036 UsedRegionsNeedZeroFillSetter() : _g1(G1CollectedHeap::heap()), _n(0) {} | |
5037 bool doHeapRegion(HeapRegion* r) { | |
5038 if (r->continuesHumongous()) return false; | |
5039 if (r->top() > r->bottom()) { | |
5040 // There are assertions in "set_zero_fill_needed()" below that | |
5041 // require top() == bottom(), so this is technically illegal. | |
5042 // We'll skirt the law here, by making that true temporarily. | |
5043 DEBUG_ONLY(HeapWord* save_top = r->top(); | |
5044 r->set_top(r->bottom())); | |
5045 r->set_zero_fill_needed(); | |
5046 DEBUG_ONLY(r->set_top(save_top)); | |
5047 } | |
5048 return false; | |
5049 } | |
5050 }; | |
5051 | |
5052 // Done at the start of full GC. | |
5053 void G1CollectedHeap::set_used_regions_to_need_zero_fill() { | |
5054 MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag); | |
5055 // This needs to go at the end of the full GC. | |
5056 UsedRegionsNeedZeroFillSetter rs; | |
5057 heap_region_iterate(&rs); | |
5058 } | |
5059 | |
5060 void G1CollectedHeap::set_refine_cte_cl_concurrency(bool concurrent) { | |
5061 _refine_cte_cl->set_concurrent(concurrent); | |
5062 } | |
5063 | |
5064 #ifndef PRODUCT | |
5065 | |
5066 class PrintHeapRegionClosure: public HeapRegionClosure { | |
5067 public: | |
5068 bool doHeapRegion(HeapRegion *r) { | |
5069 gclog_or_tty->print("Region: "PTR_FORMAT":", r); | |
5070 if (r != NULL) { | |
5071 if (r->is_on_free_list()) | |
5072 gclog_or_tty->print("Free "); | |
5073 if (r->is_young()) | |
5074 gclog_or_tty->print("Young "); | |
5075 if (r->isHumongous()) | |
5076 gclog_or_tty->print("Is Humongous "); | |
5077 r->print(); | |
5078 } | |
5079 return false; | |
5080 } | |
5081 }; | |
5082 | |
5083 class SortHeapRegionClosure : public HeapRegionClosure { | |
5084 size_t young_regions,free_regions, unclean_regions; | |
5085 size_t hum_regions, count; | |
5086 size_t unaccounted, cur_unclean, cur_alloc; | |
5087 size_t total_free; | |
5088 HeapRegion* cur; | |
5089 public: | |
5090 SortHeapRegionClosure(HeapRegion *_cur) : cur(_cur), young_regions(0), | |
5091 free_regions(0), unclean_regions(0), | |
5092 hum_regions(0), | |
5093 count(0), unaccounted(0), | |
5094 cur_alloc(0), total_free(0) | |
5095 {} | |
5096 bool doHeapRegion(HeapRegion *r) { | |
5097 count++; | |
5098 if (r->is_on_free_list()) free_regions++; | |
5099 else if (r->is_on_unclean_list()) unclean_regions++; | |
5100 else if (r->isHumongous()) hum_regions++; | |
5101 else if (r->is_young()) young_regions++; | |
5102 else if (r == cur) cur_alloc++; | |
5103 else unaccounted++; | |
5104 return false; | |
5105 } | |
5106 void print() { | |
5107 total_free = free_regions + unclean_regions; | |
5108 gclog_or_tty->print("%d regions\n", count); | |
5109 gclog_or_tty->print("%d free: free_list = %d unclean = %d\n", | |
5110 total_free, free_regions, unclean_regions); | |
5111 gclog_or_tty->print("%d humongous %d young\n", | |
5112 hum_regions, young_regions); | |
5113 gclog_or_tty->print("%d cur_alloc\n", cur_alloc); | |
5114 gclog_or_tty->print("UHOH unaccounted = %d\n", unaccounted); | |
5115 } | |
5116 }; | |
5117 | |
5118 void G1CollectedHeap::print_region_counts() { | |
5119 SortHeapRegionClosure sc(_cur_alloc_region); | |
5120 PrintHeapRegionClosure cl; | |
5121 heap_region_iterate(&cl); | |
5122 heap_region_iterate(&sc); | |
5123 sc.print(); | |
5124 print_region_accounting_info(); | |
5125 }; | |
5126 | |
5127 bool G1CollectedHeap::regions_accounted_for() { | |
5128 // TODO: regions accounting for young/survivor/tenured | |
5129 return true; | |
5130 } | |
5131 | |
5132 bool G1CollectedHeap::print_region_accounting_info() { | |
5133 gclog_or_tty->print_cr("Free regions: %d (count: %d count list %d) (clean: %d unclean: %d).", | |
5134 free_regions(), | |
5135 count_free_regions(), count_free_regions_list(), | |
5136 _free_region_list_size, _unclean_region_list.sz()); | |
5137 gclog_or_tty->print_cr("cur_alloc: %d.", | |
5138 (_cur_alloc_region == NULL ? 0 : 1)); | |
5139 gclog_or_tty->print_cr("H regions: %d.", _num_humongous_regions); | |
5140 | |
5141 // TODO: check regions accounting for young/survivor/tenured | |
5142 return true; | |
5143 } | |
5144 | |
5145 bool G1CollectedHeap::is_in_closed_subset(const void* p) const { | |
5146 HeapRegion* hr = heap_region_containing(p); | |
5147 if (hr == NULL) { | |
5148 return is_in_permanent(p); | |
5149 } else { | |
5150 return hr->is_in(p); | |
5151 } | |
5152 } | |
941 | 5153 #endif // !PRODUCT |
342 | 5154 |
5155 void G1CollectedHeap::g1_unimplemented() { | |
5156 // Unimplemented(); | |
5157 } |