Mercurial > hg > graal-compiler
annotate src/share/vm/gc_implementation/g1/g1RemSet.cpp @ 1705:2d160770d2e5
6814437: G1: remove the _new_refs array
Summary: The per-worker _new_refs array is used to hold references that point into the collection set. It is populated during RSet updating and subsequently processed. In the event of an evacuation failure it processed again to recreate the RSets of regions in the collection set. Remove the per-worker _new_refs array by processing the references directly. Use a DirtyCardQueue to hold the cards containing the references so that the RSets of regions in the collection set can be recreated when handling an evacuation failure.
Reviewed-by: iveresov, jmasa, tonyp
author | johnc |
---|---|
date | Mon, 02 Aug 2010 12:51:43 -0700 |
parents | 5cbac8938c4c |
children | a03ae377b2e8 |
rev | line source |
---|---|
342 | 1 /* |
1666
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1282
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1282
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1282
diff
changeset
|
21 * questions. |
342 | 22 * |
23 */ | |
24 | |
25 #include "incls/_precompiled.incl" | |
26 #include "incls/_g1RemSet.cpp.incl" | |
27 | |
28 #define CARD_REPEAT_HISTO 0 | |
29 | |
30 #if CARD_REPEAT_HISTO | |
31 static size_t ct_freq_sz; | |
32 static jbyte* ct_freq = NULL; | |
33 | |
34 void init_ct_freq_table(size_t heap_sz_bytes) { | |
35 if (ct_freq == NULL) { | |
36 ct_freq_sz = heap_sz_bytes/CardTableModRefBS::card_size; | |
37 ct_freq = new jbyte[ct_freq_sz]; | |
38 for (size_t j = 0; j < ct_freq_sz; j++) ct_freq[j] = 0; | |
39 } | |
40 } | |
41 | |
42 void ct_freq_note_card(size_t index) { | |
43 assert(0 <= index && index < ct_freq_sz, "Bounds error."); | |
44 if (ct_freq[index] < 100) { ct_freq[index]++; } | |
45 } | |
46 | |
47 static IntHistogram card_repeat_count(10, 10); | |
48 | |
49 void ct_freq_update_histo_and_reset() { | |
50 for (size_t j = 0; j < ct_freq_sz; j++) { | |
51 card_repeat_count.add_entry(ct_freq[j]); | |
52 ct_freq[j] = 0; | |
53 } | |
54 | |
55 } | |
56 #endif | |
57 | |
58 | |
59 class IntoCSOopClosure: public OopsInHeapRegionClosure { | |
60 OopsInHeapRegionClosure* _blk; | |
61 G1CollectedHeap* _g1; | |
62 public: | |
63 IntoCSOopClosure(G1CollectedHeap* g1, OopsInHeapRegionClosure* blk) : | |
64 _g1(g1), _blk(blk) {} | |
65 void set_region(HeapRegion* from) { | |
66 _blk->set_region(from); | |
67 } | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
796
diff
changeset
|
68 virtual void do_oop(narrowOop* p) { do_oop_work(p); } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
796
diff
changeset
|
69 virtual void do_oop( oop* p) { do_oop_work(p); } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
796
diff
changeset
|
70 template <class T> void do_oop_work(T* p) { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
796
diff
changeset
|
71 oop obj = oopDesc::load_decode_heap_oop(p); |
342 | 72 if (_g1->obj_in_cs(obj)) _blk->do_oop(p); |
73 } | |
74 bool apply_to_weak_ref_discovered_field() { return true; } | |
75 bool idempotent() { return true; } | |
76 }; | |
77 | |
78 class IntoCSRegionClosure: public HeapRegionClosure { | |
79 IntoCSOopClosure _blk; | |
80 G1CollectedHeap* _g1; | |
81 public: | |
82 IntoCSRegionClosure(G1CollectedHeap* g1, OopsInHeapRegionClosure* blk) : | |
83 _g1(g1), _blk(g1, blk) {} | |
84 bool doHeapRegion(HeapRegion* r) { | |
85 if (!r->in_collection_set()) { | |
86 _blk.set_region(r); | |
87 if (r->isHumongous()) { | |
88 if (r->startsHumongous()) { | |
89 oop obj = oop(r->bottom()); | |
90 obj->oop_iterate(&_blk); | |
91 } | |
92 } else { | |
93 r->oop_before_save_marks_iterate(&_blk); | |
94 } | |
95 } | |
96 return false; | |
97 } | |
98 }; | |
99 | |
100 void | |
101 StupidG1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc, | |
102 int worker_i) { | |
103 IntoCSRegionClosure rc(_g1, oc); | |
104 _g1->heap_region_iterate(&rc); | |
105 } | |
106 | |
107 class VerifyRSCleanCardOopClosure: public OopClosure { | |
108 G1CollectedHeap* _g1; | |
109 public: | |
110 VerifyRSCleanCardOopClosure(G1CollectedHeap* g1) : _g1(g1) {} | |
111 | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
796
diff
changeset
|
112 virtual void do_oop(narrowOop* p) { do_oop_work(p); } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
796
diff
changeset
|
113 virtual void do_oop( oop* p) { do_oop_work(p); } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
796
diff
changeset
|
114 template <class T> void do_oop_work(T* p) { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
796
diff
changeset
|
115 oop obj = oopDesc::load_decode_heap_oop(p); |
342 | 116 HeapRegion* to = _g1->heap_region_containing(obj); |
117 guarantee(to == NULL || !to->in_collection_set(), | |
118 "Missed a rem set member."); | |
119 } | |
120 }; | |
121 | |
122 HRInto_G1RemSet::HRInto_G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs) | |
123 : G1RemSet(g1), _ct_bs(ct_bs), _g1p(_g1->g1_policy()), | |
124 _cg1r(g1->concurrent_g1_refine()), | |
1705 | 125 _par_traversal_in_progress(false), |
126 _cset_rs_update_cl(NULL), | |
342 | 127 _cards_scanned(NULL), _total_cards_scanned(0) |
128 { | |
129 _seq_task = new SubTasksDone(NumSeqTasks); | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
545
diff
changeset
|
130 guarantee(n_workers() > 0, "There should be some workers"); |
1705 | 131 _cset_rs_update_cl = NEW_C_HEAP_ARRAY(OopsInHeapRegionClosure*, n_workers()); |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
545
diff
changeset
|
132 for (uint i = 0; i < n_workers(); i++) { |
1705 | 133 _cset_rs_update_cl[i] = NULL; |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
545
diff
changeset
|
134 } |
342 | 135 } |
136 | |
137 HRInto_G1RemSet::~HRInto_G1RemSet() { | |
138 delete _seq_task; | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
545
diff
changeset
|
139 for (uint i = 0; i < n_workers(); i++) { |
1705 | 140 assert(_cset_rs_update_cl[i] == NULL, "it should be"); |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
545
diff
changeset
|
141 } |
1705 | 142 FREE_C_HEAP_ARRAY(OopsInHeapRegionClosure*, _cset_rs_update_cl); |
342 | 143 } |
144 | |
145 void CountNonCleanMemRegionClosure::do_MemRegion(MemRegion mr) { | |
146 if (_g1->is_in_g1_reserved(mr.start())) { | |
147 _n += (int) ((mr.byte_size() / CardTableModRefBS::card_size)); | |
148 if (_start_first == NULL) _start_first = mr.start(); | |
149 } | |
150 } | |
151 | |
152 class ScanRSClosure : public HeapRegionClosure { | |
153 size_t _cards_done, _cards; | |
154 G1CollectedHeap* _g1h; | |
155 OopsInHeapRegionClosure* _oc; | |
156 G1BlockOffsetSharedArray* _bot_shared; | |
157 CardTableModRefBS *_ct_bs; | |
158 int _worker_i; | |
1261 | 159 int _block_size; |
342 | 160 bool _try_claimed; |
161 public: | |
162 ScanRSClosure(OopsInHeapRegionClosure* oc, int worker_i) : | |
163 _oc(oc), | |
164 _cards(0), | |
165 _cards_done(0), | |
166 _worker_i(worker_i), | |
167 _try_claimed(false) | |
168 { | |
169 _g1h = G1CollectedHeap::heap(); | |
170 _bot_shared = _g1h->bot_shared(); | |
171 _ct_bs = (CardTableModRefBS*) (_g1h->barrier_set()); | |
1261 | 172 _block_size = MAX2<int>(G1RSetScanBlockSize, 1); |
342 | 173 } |
174 | |
175 void set_try_claimed() { _try_claimed = true; } | |
176 | |
177 void scanCard(size_t index, HeapRegion *r) { | |
178 _cards_done++; | |
179 DirtyCardToOopClosure* cl = | |
180 r->new_dcto_closure(_oc, | |
181 CardTableModRefBS::Precise, | |
182 HeapRegionDCTOC::IntoCSFilterKind); | |
183 | |
184 // Set the "from" region in the closure. | |
185 _oc->set_region(r); | |
186 HeapWord* card_start = _bot_shared->address_for_index(index); | |
187 HeapWord* card_end = card_start + G1BlockOffsetSharedArray::N_words; | |
188 Space *sp = SharedHeap::heap()->space_containing(card_start); | |
189 MemRegion sm_region; | |
190 if (ParallelGCThreads > 0) { | |
191 // first find the used area | |
192 sm_region = sp->used_region_at_save_marks(); | |
193 } else { | |
194 // The closure is not idempotent. We shouldn't look at objects | |
195 // allocated during the GC. | |
196 sm_region = sp->used_region_at_save_marks(); | |
197 } | |
198 MemRegion mr = sm_region.intersection(MemRegion(card_start,card_end)); | |
199 if (!mr.is_empty()) { | |
200 cl->do_MemRegion(mr); | |
201 } | |
202 } | |
203 | |
204 void printCard(HeapRegion* card_region, size_t card_index, | |
205 HeapWord* card_start) { | |
206 gclog_or_tty->print_cr("T %d Region [" PTR_FORMAT ", " PTR_FORMAT ") " | |
207 "RS names card %p: " | |
208 "[" PTR_FORMAT ", " PTR_FORMAT ")", | |
209 _worker_i, | |
210 card_region->bottom(), card_region->end(), | |
211 card_index, | |
212 card_start, card_start + G1BlockOffsetSharedArray::N_words); | |
213 } | |
214 | |
215 bool doHeapRegion(HeapRegion* r) { | |
216 assert(r->in_collection_set(), "should only be called on elements of CS."); | |
217 HeapRegionRemSet* hrrs = r->rem_set(); | |
218 if (hrrs->iter_is_complete()) return false; // All done. | |
219 if (!_try_claimed && !hrrs->claim_iter()) return false; | |
796
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
220 _g1h->push_dirty_cards_region(r); |
342 | 221 // If we didn't return above, then |
222 // _try_claimed || r->claim_iter() | |
223 // is true: either we're supposed to work on claimed-but-not-complete | |
224 // regions, or we successfully claimed the region. | |
225 HeapRegionRemSetIterator* iter = _g1h->rem_set_iterator(_worker_i); | |
226 hrrs->init_iterator(iter); | |
227 size_t card_index; | |
1261 | 228 |
229 // We claim cards in block so as to recude the contention. The block size is determined by | |
230 // the G1RSetScanBlockSize parameter. | |
231 size_t jump_to_card = hrrs->iter_claimed_next(_block_size); | |
232 for (size_t current_card = 0; iter->has_next(card_index); current_card++) { | |
233 if (current_card >= jump_to_card + _block_size) { | |
234 jump_to_card = hrrs->iter_claimed_next(_block_size); | |
747 | 235 } |
1261 | 236 if (current_card < jump_to_card) continue; |
342 | 237 HeapWord* card_start = _g1h->bot_shared()->address_for_index(card_index); |
238 #if 0 | |
239 gclog_or_tty->print("Rem set iteration yielded card [" PTR_FORMAT ", " PTR_FORMAT ").\n", | |
240 card_start, card_start + CardTableModRefBS::card_size_in_words); | |
241 #endif | |
242 | |
243 HeapRegion* card_region = _g1h->heap_region_containing(card_start); | |
244 assert(card_region != NULL, "Yielding cards not in the heap?"); | |
245 _cards++; | |
246 | |
796
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
247 if (!card_region->is_on_dirty_cards_region_list()) { |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
248 _g1h->push_dirty_cards_region(card_region); |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
249 } |
29e7d79232b9
6819065: G1: eliminate high serial card table clearing time
apetrusenko
parents:
794
diff
changeset
|
250 |
747 | 251 // If the card is dirty, then we will scan it during updateRS. |
252 if (!card_region->in_collection_set() && !_ct_bs->is_card_dirty(card_index)) { | |
1261 | 253 // We make the card as "claimed" lazily (so races are possible but they're benign), |
254 // which reduces the number of duplicate scans (the rsets of the regions in the cset | |
255 // can intersect). | |
256 if (!_ct_bs->is_card_claimed(card_index)) { | |
257 _ct_bs->set_card_claimed(card_index); | |
258 scanCard(card_index, card_region); | |
259 } | |
342 | 260 } |
261 } | |
747 | 262 if (!_try_claimed) { |
263 hrrs->set_iter_complete(); | |
264 } | |
342 | 265 return false; |
266 } | |
267 // Set all cards back to clean. | |
268 void cleanup() {_g1h->cleanUpCardTable();} | |
269 size_t cards_done() { return _cards_done;} | |
270 size_t cards_looked_up() { return _cards;} | |
271 }; | |
272 | |
273 // We want the parallel threads to start their scanning at | |
274 // different collection set regions to avoid contention. | |
275 // If we have: | |
276 // n collection set regions | |
277 // p threads | |
278 // Then thread t will start at region t * floor (n/p) | |
279 | |
280 HeapRegion* HRInto_G1RemSet::calculateStartRegion(int worker_i) { | |
281 HeapRegion* result = _g1p->collection_set(); | |
282 if (ParallelGCThreads > 0) { | |
283 size_t cs_size = _g1p->collection_set_size(); | |
284 int n_workers = _g1->workers()->total_workers(); | |
285 size_t cs_spans = cs_size / n_workers; | |
286 size_t ind = cs_spans * worker_i; | |
287 for (size_t i = 0; i < ind; i++) | |
288 result = result->next_in_collection_set(); | |
289 } | |
290 return result; | |
291 } | |
292 | |
293 void HRInto_G1RemSet::scanRS(OopsInHeapRegionClosure* oc, int worker_i) { | |
294 double rs_time_start = os::elapsedTime(); | |
295 HeapRegion *startRegion = calculateStartRegion(worker_i); | |
296 | |
1261 | 297 ScanRSClosure scanRScl(oc, worker_i); |
342 | 298 _g1->collection_set_iterate_from(startRegion, &scanRScl); |
299 scanRScl.set_try_claimed(); | |
300 _g1->collection_set_iterate_from(startRegion, &scanRScl); | |
301 | |
1261 | 302 double scan_rs_time_sec = os::elapsedTime() - rs_time_start; |
342 | 303 |
304 assert( _cards_scanned != NULL, "invariant" ); | |
305 _cards_scanned[worker_i] = scanRScl.cards_done(); | |
306 | |
307 _g1p->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0); | |
308 } | |
309 | |
1705 | 310 // Closure used for updating RSets and recording references that |
311 // point into the collection set. Only called during an | |
312 // evacuation pause. | |
313 | |
314 class RefineRecordRefsIntoCSCardTableEntryClosure: public CardTableEntryClosure { | |
315 G1RemSet* _g1rs; | |
316 DirtyCardQueue* _into_cset_dcq; | |
317 public: | |
318 RefineRecordRefsIntoCSCardTableEntryClosure(G1CollectedHeap* g1h, | |
319 DirtyCardQueue* into_cset_dcq) : | |
320 _g1rs(g1h->g1_rem_set()), _into_cset_dcq(into_cset_dcq) | |
321 {} | |
322 bool do_card_ptr(jbyte* card_ptr, int worker_i) { | |
323 // The only time we care about recording cards that | |
324 // contain references that point into the collection set | |
325 // is during RSet updating within an evacuation pause. | |
326 // In this case worker_i should be the id of a GC worker thread. | |
327 assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause"); | |
328 assert(worker_i < (int) DirtyCardQueueSet::num_par_ids(), "should be a GC worker"); | |
342 | 329 |
1705 | 330 if (_g1rs->concurrentRefineOneCard(card_ptr, worker_i, true)) { |
331 // 'card_ptr' contains references that point into the collection | |
332 // set. We need to record the card in the DCQS | |
333 // (G1CollectedHeap::into_cset_dirty_card_queue_set()) | |
334 // that's used for that purpose. | |
335 // | |
336 // Enqueue the card | |
337 _into_cset_dcq->enqueue(card_ptr); | |
338 } | |
339 return true; | |
340 } | |
341 }; | |
342 | |
343 void HRInto_G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, int worker_i) { | |
342 | 344 double start = os::elapsedTime(); |
1705 | 345 // Apply the given closure to all remaining log entries. |
346 RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq); | |
347 _g1->iterate_dirty_card_closure(&into_cset_update_rs_cl, into_cset_dcq, false, worker_i); | |
348 | |
794 | 349 // Now there should be no dirty cards. |
350 if (G1RSLogCheckCardTable) { | |
351 CountNonCleanMemRegionClosure cl(_g1); | |
352 _ct_bs->mod_card_iterate(&cl); | |
353 // XXX This isn't true any more: keeping cards of young regions | |
354 // marked dirty broke it. Need some reasonable fix. | |
355 guarantee(cl.n() == 0, "Card table should be clean."); | |
342 | 356 } |
794 | 357 |
342 | 358 _g1p->record_update_rs_time(worker_i, (os::elapsedTime() - start) * 1000.0); |
359 } | |
360 | |
361 #ifndef PRODUCT | |
362 class PrintRSClosure : public HeapRegionClosure { | |
363 int _count; | |
364 public: | |
365 PrintRSClosure() : _count(0) {} | |
366 bool doHeapRegion(HeapRegion* r) { | |
367 HeapRegionRemSet* hrrs = r->rem_set(); | |
368 _count += (int) hrrs->occupied(); | |
369 if (hrrs->occupied() == 0) { | |
370 gclog_or_tty->print("Heap Region [" PTR_FORMAT ", " PTR_FORMAT ") " | |
371 "has no remset entries\n", | |
372 r->bottom(), r->end()); | |
373 } else { | |
374 gclog_or_tty->print("Printing rem set for heap region [" PTR_FORMAT ", " PTR_FORMAT ")\n", | |
375 r->bottom(), r->end()); | |
376 r->print(); | |
377 hrrs->print(); | |
378 gclog_or_tty->print("\nDone printing rem set\n"); | |
379 } | |
380 return false; | |
381 } | |
382 int occupied() {return _count;} | |
383 }; | |
384 #endif | |
385 | |
386 class CountRSSizeClosure: public HeapRegionClosure { | |
387 size_t _n; | |
388 size_t _tot; | |
389 size_t _max; | |
390 HeapRegion* _max_r; | |
391 enum { | |
392 N = 20, | |
393 MIN = 6 | |
394 }; | |
395 int _histo[N]; | |
396 public: | |
397 CountRSSizeClosure() : _n(0), _tot(0), _max(0), _max_r(NULL) { | |
398 for (int i = 0; i < N; i++) _histo[i] = 0; | |
399 } | |
400 bool doHeapRegion(HeapRegion* r) { | |
401 if (!r->continuesHumongous()) { | |
402 size_t occ = r->rem_set()->occupied(); | |
403 _n++; | |
404 _tot += occ; | |
405 if (occ > _max) { | |
406 _max = occ; | |
407 _max_r = r; | |
408 } | |
409 // Fit it into a histo bin. | |
410 int s = 1 << MIN; | |
411 int i = 0; | |
412 while (occ > (size_t) s && i < (N-1)) { | |
413 s = s << 1; | |
414 i++; | |
415 } | |
416 _histo[i]++; | |
417 } | |
418 return false; | |
419 } | |
420 size_t n() { return _n; } | |
421 size_t tot() { return _tot; } | |
422 size_t mx() { return _max; } | |
423 HeapRegion* mxr() { return _max_r; } | |
424 void print_histo() { | |
425 int mx = N; | |
426 while (mx >= 0) { | |
427 if (_histo[mx-1] > 0) break; | |
428 mx--; | |
429 } | |
430 gclog_or_tty->print_cr("Number of regions with given RS sizes:"); | |
431 gclog_or_tty->print_cr(" <= %8d %8d", 1 << MIN, _histo[0]); | |
432 for (int i = 1; i < mx-1; i++) { | |
433 gclog_or_tty->print_cr(" %8d - %8d %8d", | |
434 (1 << (MIN + i - 1)) + 1, | |
435 1 << (MIN + i), | |
436 _histo[i]); | |
437 } | |
438 gclog_or_tty->print_cr(" > %8d %8d", (1 << (MIN+mx-2))+1, _histo[mx-1]); | |
439 } | |
440 }; | |
441 | |
442 void HRInto_G1RemSet::cleanupHRRS() { | |
443 HeapRegionRemSet::cleanup(); | |
444 } | |
445 | |
446 void | |
447 HRInto_G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc, | |
448 int worker_i) { | |
449 #if CARD_REPEAT_HISTO | |
450 ct_freq_update_histo_and_reset(); | |
451 #endif | |
452 if (worker_i == 0) { | |
453 _cg1r->clear_and_record_card_counts(); | |
454 } | |
455 | |
456 // Make this into a command-line flag... | |
457 if (G1RSCountHisto && (ParallelGCThreads == 0 || worker_i == 0)) { | |
458 CountRSSizeClosure count_cl; | |
459 _g1->heap_region_iterate(&count_cl); | |
460 gclog_or_tty->print_cr("Avg of %d RS counts is %f, max is %d, " | |
461 "max region is " PTR_FORMAT, | |
462 count_cl.n(), (float)count_cl.tot()/(float)count_cl.n(), | |
463 count_cl.mx(), count_cl.mxr()); | |
464 count_cl.print_histo(); | |
465 } | |
466 | |
1705 | 467 // We cache the value of 'oc' closure into the appropriate slot in the |
468 // _cset_rs_update_cl for this worker | |
469 assert(worker_i < (int)n_workers(), "sanity"); | |
470 _cset_rs_update_cl[worker_i] = oc; | |
471 | |
472 // A DirtyCardQueue that is used to hold cards containing references | |
473 // that point into the collection set. This DCQ is associated with a | |
474 // special DirtyCardQueueSet (see g1CollectedHeap.hpp). Under normal | |
475 // circumstances (i.e. the pause successfully completes), these cards | |
476 // are just discarded (there's no need to update the RSets of regions | |
477 // that were in the collection set - after the pause these regions | |
478 // are wholly 'free' of live objects. In the event of an evacuation | |
479 // failure the cards/buffers in this queue set are: | |
480 // * passed to the DirtyCardQueueSet that is used to manage deferred | |
481 // RSet updates, or | |
482 // * scanned for references that point into the collection set | |
483 // and the RSet of the corresponding region in the collection set | |
484 // is updated immediately. | |
485 DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set()); | |
486 | |
342 | 487 if (ParallelGCThreads > 0) { |
638
2a5da27ccae9
6816154: G1: introduce flags to enable/disable RSet updating and scanning
tonyp
parents:
637
diff
changeset
|
488 // The two flags below were introduced temporarily to serialize |
2a5da27ccae9
6816154: G1: introduce flags to enable/disable RSet updating and scanning
tonyp
parents:
637
diff
changeset
|
489 // the updating and scanning of remembered sets. There are some |
2a5da27ccae9
6816154: G1: introduce flags to enable/disable RSet updating and scanning
tonyp
parents:
637
diff
changeset
|
490 // race conditions when these two operations are done in parallel |
2a5da27ccae9
6816154: G1: introduce flags to enable/disable RSet updating and scanning
tonyp
parents:
637
diff
changeset
|
491 // and they are causing failures. When we resolve said race |
2a5da27ccae9
6816154: G1: introduce flags to enable/disable RSet updating and scanning
tonyp
parents:
637
diff
changeset
|
492 // conditions, we'll revert back to parallel remembered set |
2a5da27ccae9
6816154: G1: introduce flags to enable/disable RSet updating and scanning
tonyp
parents:
637
diff
changeset
|
493 // updating and scanning. See CRs 6677707 and 6677708. |
1282 | 494 if (G1UseParallelRSetUpdating || (worker_i == 0)) { |
1705 | 495 updateRS(&into_cset_dcq, worker_i); |
648
2314b7336582
6820321: G1: Error: guarantee(check_nums(total, n, parts), "all seq lengths should match")
tonyp
parents:
640
diff
changeset
|
496 } else { |
2314b7336582
6820321: G1: Error: guarantee(check_nums(total, n, parts), "all seq lengths should match")
tonyp
parents:
640
diff
changeset
|
497 _g1p->record_update_rs_processed_buffers(worker_i, 0.0); |
2314b7336582
6820321: G1: Error: guarantee(check_nums(total, n, parts), "all seq lengths should match")
tonyp
parents:
640
diff
changeset
|
498 _g1p->record_update_rs_time(worker_i, 0.0); |
638
2a5da27ccae9
6816154: G1: introduce flags to enable/disable RSet updating and scanning
tonyp
parents:
637
diff
changeset
|
499 } |
1282 | 500 if (G1UseParallelRSetScanning || (worker_i == 0)) { |
342 | 501 scanRS(oc, worker_i); |
648
2314b7336582
6820321: G1: Error: guarantee(check_nums(total, n, parts), "all seq lengths should match")
tonyp
parents:
640
diff
changeset
|
502 } else { |
2314b7336582
6820321: G1: Error: guarantee(check_nums(total, n, parts), "all seq lengths should match")
tonyp
parents:
640
diff
changeset
|
503 _g1p->record_scan_rs_time(worker_i, 0.0); |
342 | 504 } |
505 } else { | |
506 assert(worker_i == 0, "invariant"); | |
1705 | 507 updateRS(&into_cset_dcq, 0); |
342 | 508 scanRS(oc, 0); |
509 } | |
1705 | 510 |
511 // We now clear the cached values of _cset_rs_update_cl for this worker | |
512 _cset_rs_update_cl[worker_i] = NULL; | |
342 | 513 } |
514 | |
515 void HRInto_G1RemSet:: | |
516 prepare_for_oops_into_collection_set_do() { | |
517 #if G1_REM_SET_LOGGING | |
518 PrintRSClosure cl; | |
519 _g1->collection_set_iterate(&cl); | |
520 #endif | |
521 cleanupHRRS(); | |
522 ConcurrentG1Refine* cg1r = _g1->concurrent_g1_refine(); | |
523 _g1->set_refine_cte_cl_concurrency(false); | |
524 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); | |
525 dcqs.concatenate_logs(); | |
526 | |
527 assert(!_par_traversal_in_progress, "Invariant between iterations."); | |
528 if (ParallelGCThreads > 0) { | |
529 set_par_traversal(true); | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
545
diff
changeset
|
530 _seq_task->set_par_threads((int)n_workers()); |
342 | 531 } |
532 guarantee( _cards_scanned == NULL, "invariant" ); | |
533 _cards_scanned = NEW_C_HEAP_ARRAY(size_t, n_workers()); | |
545 | 534 for (uint i = 0; i < n_workers(); ++i) { |
535 _cards_scanned[i] = 0; | |
536 } | |
342 | 537 _total_cards_scanned = 0; |
538 } | |
539 | |
540 | |
541 class cleanUpIteratorsClosure : public HeapRegionClosure { | |
542 bool doHeapRegion(HeapRegion *r) { | |
543 HeapRegionRemSet* hrrs = r->rem_set(); | |
544 hrrs->init_for_par_iteration(); | |
545 return false; | |
546 } | |
547 }; | |
548 | |
1705 | 549 // This closure, applied to a DirtyCardQueueSet, is used to immediately |
550 // update the RSets for the regions in the CSet. For each card it iterates | |
551 // through the oops which coincide with that card. It scans the reference | |
552 // fields in each oop; when it finds an oop that points into the collection | |
553 // set, the RSet for the region containing the referenced object is updated. | |
554 // Note: _par_traversal_in_progress in the G1RemSet must be FALSE; otherwise | |
555 // the UpdateRSetImmediate closure will cause cards to be enqueued on to | |
556 // the DCQS that we're iterating over, causing an infinite loop. | |
557 class UpdateRSetCardTableEntryIntoCSetClosure: public CardTableEntryClosure { | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
545
diff
changeset
|
558 G1CollectedHeap* _g1; |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
545
diff
changeset
|
559 CardTableModRefBS* _ct_bs; |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
545
diff
changeset
|
560 public: |
1705 | 561 UpdateRSetCardTableEntryIntoCSetClosure(G1CollectedHeap* g1, |
562 CardTableModRefBS* bs): | |
563 _g1(g1), _ct_bs(bs) | |
564 { } | |
565 | |
566 bool do_card_ptr(jbyte* card_ptr, int worker_i) { | |
567 // Construct the region representing the card. | |
568 HeapWord* start = _ct_bs->addr_for(card_ptr); | |
569 // And find the region containing it. | |
570 HeapRegion* r = _g1->heap_region_containing(start); | |
571 assert(r != NULL, "unexpected null"); | |
572 | |
573 // Scan oops in the card looking for references into the collection set | |
574 HeapWord* end = _ct_bs->addr_for(card_ptr + 1); | |
575 MemRegion scanRegion(start, end); | |
576 | |
577 UpdateRSetImmediate update_rs_cl(_g1->g1_rem_set()); | |
578 FilterIntoCSClosure update_rs_cset_oop_cl(NULL, _g1, &update_rs_cl); | |
579 FilterOutOfRegionClosure filter_then_update_rs_cset_oop_cl(r, &update_rs_cset_oop_cl); | |
580 | |
581 // We can pass false as the "filter_young" parameter here as: | |
582 // * we should be in a STW pause, | |
583 // * the DCQS to which this closure is applied is used to hold | |
584 // references that point into the collection set from the prior | |
585 // RSet updating, | |
586 // * the post-write barrier shouldn't be logging updates to young | |
587 // regions (but there is a situation where this can happen - see | |
588 // the comment in HRInto_G1RemSet::concurrentRefineOneCard below - | |
589 // that should not be applicable here), and | |
590 // * during actual RSet updating, the filtering of cards in young | |
591 // regions in HeapRegion::oops_on_card_seq_iterate_careful is | |
592 // employed. | |
593 // As a result, when this closure is applied to "refs into cset" | |
594 // DCQS, we shouldn't see any cards in young regions. | |
595 update_rs_cl.set_region(r); | |
596 HeapWord* stop_point = | |
597 r->oops_on_card_seq_iterate_careful(scanRegion, | |
598 &filter_then_update_rs_cset_oop_cl, | |
599 false /* filter_young */); | |
600 | |
601 // Since this is performed in the event of an evacuation failure, we | |
602 // we shouldn't see a non-null stop point | |
603 assert(stop_point == NULL, "saw an unallocated region"); | |
604 return true; | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
545
diff
changeset
|
605 } |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
545
diff
changeset
|
606 }; |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
545
diff
changeset
|
607 |
342 | 608 void HRInto_G1RemSet::cleanup_after_oops_into_collection_set_do() { |
609 guarantee( _cards_scanned != NULL, "invariant" ); | |
610 _total_cards_scanned = 0; | |
611 for (uint i = 0; i < n_workers(); ++i) | |
612 _total_cards_scanned += _cards_scanned[i]; | |
613 FREE_C_HEAP_ARRAY(size_t, _cards_scanned); | |
614 _cards_scanned = NULL; | |
615 // Cleanup after copy | |
616 #if G1_REM_SET_LOGGING | |
617 PrintRSClosure cl; | |
618 _g1->heap_region_iterate(&cl); | |
619 #endif | |
620 _g1->set_refine_cte_cl_concurrency(true); | |
621 cleanUpIteratorsClosure iterClosure; | |
622 _g1->collection_set_iterate(&iterClosure); | |
623 // Set all cards back to clean. | |
624 _g1->cleanUpCardTable(); | |
794 | 625 |
342 | 626 if (ParallelGCThreads > 0) { |
627 set_par_traversal(false); | |
628 } | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
545
diff
changeset
|
629 |
1705 | 630 DirtyCardQueueSet& into_cset_dcqs = _g1->into_cset_dirty_card_queue_set(); |
631 int into_cset_n_buffers = into_cset_dcqs.completed_buffers_num(); | |
632 | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
545
diff
changeset
|
633 if (_g1->evacuation_failed()) { |
1705 | 634 // Restore remembered sets for the regions pointing into the collection set. |
635 | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
545
diff
changeset
|
636 if (G1DeferredRSUpdate) { |
1705 | 637 // If deferred RS updates are enabled then we just need to transfer |
638 // the completed buffers from (a) the DirtyCardQueueSet used to hold | |
639 // cards that contain references that point into the collection set | |
640 // to (b) the DCQS used to hold the deferred RS updates | |
641 _g1->dirty_card_queue_set().merge_bufferlists(&into_cset_dcqs); | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
545
diff
changeset
|
642 } else { |
1705 | 643 |
644 CardTableModRefBS* bs = (CardTableModRefBS*)_g1->barrier_set(); | |
645 UpdateRSetCardTableEntryIntoCSetClosure update_rs_cset_immediate(_g1, bs); | |
646 | |
647 int n_completed_buffers = 0; | |
648 while (into_cset_dcqs.apply_closure_to_completed_buffer(&update_rs_cset_immediate, | |
649 0, 0, true)) { | |
650 n_completed_buffers++; | |
651 } | |
652 assert(n_completed_buffers == into_cset_n_buffers, "missed some buffers"); | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
545
diff
changeset
|
653 } |
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
545
diff
changeset
|
654 } |
1705 | 655 |
656 // Free any completed buffers in the DirtyCardQueueSet used to hold cards | |
657 // which contain references that point into the collection. | |
658 _g1->into_cset_dirty_card_queue_set().clear(); | |
659 assert(_g1->into_cset_dirty_card_queue_set().completed_buffers_num() == 0, | |
660 "all buffers should be freed"); | |
661 _g1->into_cset_dirty_card_queue_set().clear_n_completed_buffers(); | |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
545
diff
changeset
|
662 |
342 | 663 assert(!_par_traversal_in_progress, "Invariant between iterations."); |
664 } | |
665 | |
666 class UpdateRSObjectClosure: public ObjectClosure { | |
667 UpdateRSOopClosure* _update_rs_oop_cl; | |
668 public: | |
669 UpdateRSObjectClosure(UpdateRSOopClosure* update_rs_oop_cl) : | |
670 _update_rs_oop_cl(update_rs_oop_cl) {} | |
671 void do_object(oop obj) { | |
672 obj->oop_iterate(_update_rs_oop_cl); | |
673 } | |
674 | |
675 }; | |
676 | |
677 class ScrubRSClosure: public HeapRegionClosure { | |
678 G1CollectedHeap* _g1h; | |
679 BitMap* _region_bm; | |
680 BitMap* _card_bm; | |
681 CardTableModRefBS* _ctbs; | |
682 public: | |
683 ScrubRSClosure(BitMap* region_bm, BitMap* card_bm) : | |
684 _g1h(G1CollectedHeap::heap()), | |
685 _region_bm(region_bm), _card_bm(card_bm), | |
686 _ctbs(NULL) | |
687 { | |
688 ModRefBarrierSet* bs = _g1h->mr_bs(); | |
689 guarantee(bs->is_a(BarrierSet::CardTableModRef), "Precondition"); | |
690 _ctbs = (CardTableModRefBS*)bs; | |
691 } | |
692 | |
693 bool doHeapRegion(HeapRegion* r) { | |
694 if (!r->continuesHumongous()) { | |
695 r->rem_set()->scrub(_ctbs, _region_bm, _card_bm); | |
696 } | |
697 return false; | |
698 } | |
699 }; | |
700 | |
701 void HRInto_G1RemSet::scrub(BitMap* region_bm, BitMap* card_bm) { | |
702 ScrubRSClosure scrub_cl(region_bm, card_bm); | |
703 _g1->heap_region_iterate(&scrub_cl); | |
704 } | |
705 | |
706 void HRInto_G1RemSet::scrub_par(BitMap* region_bm, BitMap* card_bm, | |
707 int worker_num, int claim_val) { | |
708 ScrubRSClosure scrub_cl(region_bm, card_bm); | |
709 _g1->heap_region_par_iterate_chunked(&scrub_cl, worker_num, claim_val); | |
710 } | |
711 | |
712 | |
713 static IntHistogram out_of_histo(50, 50); | |
714 | |
1705 | 715 class TriggerClosure : public OopClosure { |
716 bool _trigger; | |
717 public: | |
718 TriggerClosure() : _trigger(false) { } | |
719 bool value() const { return _trigger; } | |
720 template <class T> void do_oop_nv(T* p) { _trigger = true; } | |
721 virtual void do_oop(oop* p) { do_oop_nv(p); } | |
722 virtual void do_oop(narrowOop* p) { do_oop_nv(p); } | |
723 }; | |
724 | |
725 class InvokeIfNotTriggeredClosure: public OopClosure { | |
726 TriggerClosure* _t; | |
727 OopClosure* _oc; | |
728 public: | |
729 InvokeIfNotTriggeredClosure(TriggerClosure* t, OopClosure* oc): | |
730 _t(t), _oc(oc) { } | |
731 template <class T> void do_oop_nv(T* p) { | |
732 if (!_t->value()) _oc->do_oop(p); | |
733 } | |
734 virtual void do_oop(oop* p) { do_oop_nv(p); } | |
735 virtual void do_oop(narrowOop* p) { do_oop_nv(p); } | |
736 }; | |
737 | |
738 class Mux2Closure : public OopClosure { | |
739 OopClosure* _c1; | |
740 OopClosure* _c2; | |
741 public: | |
742 Mux2Closure(OopClosure *c1, OopClosure *c2) : _c1(c1), _c2(c2) { } | |
743 template <class T> void do_oop_nv(T* p) { | |
744 _c1->do_oop(p); _c2->do_oop(p); | |
745 } | |
746 virtual void do_oop(oop* p) { do_oop_nv(p); } | |
747 virtual void do_oop(narrowOop* p) { do_oop_nv(p); } | |
748 }; | |
749 | |
750 bool HRInto_G1RemSet::concurrentRefineOneCard_impl(jbyte* card_ptr, int worker_i, | |
751 bool check_for_refs_into_cset) { | |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
752 // Construct the region representing the card. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
753 HeapWord* start = _ct_bs->addr_for(card_ptr); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
754 // And find the region containing it. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
755 HeapRegion* r = _g1->heap_region_containing(start); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
756 assert(r != NULL, "unexpected null"); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
757 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
758 HeapWord* end = _ct_bs->addr_for(card_ptr + 1); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
759 MemRegion dirtyRegion(start, end); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
760 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
761 #if CARD_REPEAT_HISTO |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
762 init_ct_freq_table(_g1->g1_reserved_obj_bytes()); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
763 ct_freq_note_card(_ct_bs->index_for(start)); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
764 #endif |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
765 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
766 UpdateRSOopClosure update_rs_oop_cl(this, worker_i); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
767 update_rs_oop_cl.set_from(r); |
1705 | 768 |
769 TriggerClosure trigger_cl; | |
770 FilterIntoCSClosure into_cs_cl(NULL, _g1, &trigger_cl); | |
771 InvokeIfNotTriggeredClosure invoke_cl(&trigger_cl, &into_cs_cl); | |
772 Mux2Closure mux(&invoke_cl, &update_rs_oop_cl); | |
773 | |
774 FilterOutOfRegionClosure filter_then_update_rs_oop_cl(r, | |
775 (check_for_refs_into_cset ? | |
776 (OopClosure*)&mux : | |
777 (OopClosure*)&update_rs_oop_cl)); | |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
778 |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
779 // Undirty the card. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
780 *card_ptr = CardTableModRefBS::clean_card_val(); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
781 // We must complete this write before we do any of the reads below. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
782 OrderAccess::storeload(); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
783 // And process it, being careful of unallocated portions of TLAB's. |
1666
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
784 |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
785 // The region for the current card may be a young region. The |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
786 // current card may have been a card that was evicted from the |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
787 // card cache. When the card was inserted into the cache, we had |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
788 // determined that its region was non-young. While in the cache, |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
789 // the region may have been freed during a cleanup pause, reallocated |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
790 // and tagged as young. |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
791 // |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
792 // We wish to filter out cards for such a region but the current |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
793 // thread, if we're running conucrrently, may "see" the young type |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
794 // change at any time (so an earlier "is_young" check may pass or |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
795 // fail arbitrarily). We tell the iteration code to perform this |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
796 // filtering when it has been determined that there has been an actual |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
797 // allocation in this region and making it safe to check the young type. |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
798 bool filter_young = true; |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
799 |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
800 HeapWord* stop_point = |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
801 r->oops_on_card_seq_iterate_careful(dirtyRegion, |
1666
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
802 &filter_then_update_rs_oop_cl, |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
803 filter_young); |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
804 |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
805 // If stop_point is non-null, then we encountered an unallocated region |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
806 // (perhaps the unfilled portion of a TLAB.) For now, we'll dirty the |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
807 // card and re-enqueue: if we put off the card until a GC pause, then the |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
808 // unallocated portion will be filled in. Alternatively, we might try |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
809 // the full complexity of the technique used in "regular" precleaning. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
810 if (stop_point != NULL) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
811 // The card might have gotten re-dirtied and re-enqueued while we |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
812 // worked. (In fact, it's pretty likely.) |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
813 if (*card_ptr != CardTableModRefBS::dirty_card_val()) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
814 *card_ptr = CardTableModRefBS::dirty_card_val(); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
815 MutexLockerEx x(Shared_DirtyCardQ_lock, |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
816 Mutex::_no_safepoint_check_flag); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
817 DirtyCardQueue* sdcq = |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
818 JavaThread::dirty_card_queue_set().shared_dirty_card_queue(); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
819 sdcq->enqueue(card_ptr); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
820 } |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
821 } else { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
822 out_of_histo.add_entry(filter_then_update_rs_oop_cl.out_of_region()); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
823 _conc_refine_cards++; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
824 } |
1705 | 825 |
826 return trigger_cl.value(); | |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
827 } |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
828 |
1705 | 829 bool HRInto_G1RemSet::concurrentRefineOneCard(jbyte* card_ptr, int worker_i, |
830 bool check_for_refs_into_cset) { | |
342 | 831 // If the card is no longer dirty, nothing to do. |
1705 | 832 if (*card_ptr != CardTableModRefBS::dirty_card_val()) { |
833 // No need to return that this card contains refs that point | |
834 // into the collection set. | |
835 return false; | |
836 } | |
342 | 837 |
838 // Construct the region representing the card. | |
839 HeapWord* start = _ct_bs->addr_for(card_ptr); | |
840 // And find the region containing it. | |
841 HeapRegion* r = _g1->heap_region_containing(start); | |
842 if (r == NULL) { | |
843 guarantee(_g1->is_in_permanent(start), "Or else where?"); | |
1705 | 844 // Again no need to return that this card contains refs that |
845 // point into the collection set. | |
846 return false; // Not in the G1 heap (might be in perm, for example.) | |
342 | 847 } |
848 // Why do we have to check here whether a card is on a young region, | |
849 // given that we dirty young regions and, as a result, the | |
850 // post-barrier is supposed to filter them out and never to enqueue | |
851 // them? When we allocate a new region as the "allocation region" we | |
852 // actually dirty its cards after we release the lock, since card | |
853 // dirtying while holding the lock was a performance bottleneck. So, | |
854 // as a result, it is possible for other threads to actually | |
855 // allocate objects in the region (after the acquire the lock) | |
856 // before all the cards on the region are dirtied. This is unlikely, | |
857 // and it doesn't happen often, but it can happen. So, the extra | |
858 // check below filters out those cards. | |
637
25e146966e7c
6817419: G1: Enable extensive verification for humongous regions
iveresov
parents:
626
diff
changeset
|
859 if (r->is_young()) { |
1705 | 860 return false; |
342 | 861 } |
862 // While we are processing RSet buffers during the collection, we | |
863 // actually don't want to scan any cards on the collection set, | |
864 // since we don't want to update remebered sets with entries that | |
865 // point into the collection set, given that live objects from the | |
866 // collection set are about to move and such entries will be stale | |
867 // very soon. This change also deals with a reliability issue which | |
868 // involves scanning a card in the collection set and coming across | |
869 // an array that was being chunked and looking malformed. Note, | |
870 // however, that if evacuation fails, we have to scan any objects | |
871 // that were not moved and create any missing entries. | |
872 if (r->in_collection_set()) { | |
1705 | 873 return false; |
342 | 874 } |
875 | |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
876 // Should we defer processing the card? |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
877 // |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
878 // Previously the result from the insert_cache call would be |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
879 // either card_ptr (implying that card_ptr was currently "cold"), |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
880 // null (meaning we had inserted the card ptr into the "hot" |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
881 // cache, which had some headroom), or a "hot" card ptr |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
882 // extracted from the "hot" cache. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
883 // |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
884 // Now that the _card_counts cache in the ConcurrentG1Refine |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
885 // instance is an evicting hash table, the result we get back |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
886 // could be from evicting the card ptr in an already occupied |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
887 // bucket (in which case we have replaced the card ptr in the |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
888 // bucket with card_ptr and "defer" is set to false). To avoid |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
889 // having a data structure (updates to which would need a lock) |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
890 // to hold these unprocessed dirty cards, we need to immediately |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
891 // process card_ptr. The actions needed to be taken on return |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
892 // from cache_insert are summarized in the following table: |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
893 // |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
894 // res defer action |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
895 // -------------------------------------------------------------- |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
896 // null false card evicted from _card_counts & replaced with |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
897 // card_ptr; evicted ptr added to hot cache. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
898 // No need to process res; immediately process card_ptr |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
899 // |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
900 // null true card not evicted from _card_counts; card_ptr added |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
901 // to hot cache. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
902 // Nothing to do. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
903 // |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
904 // non-null false card evicted from _card_counts & replaced with |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
905 // card_ptr; evicted ptr is currently "cold" or |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
906 // caused an eviction from the hot cache. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
907 // Immediately process res; process card_ptr. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
908 // |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
909 // non-null true card not evicted from _card_counts; card_ptr is |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
910 // currently cold, or caused an eviction from hot |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
911 // cache. |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
912 // Immediately process res; no need to process card_ptr. |
342 | 913 |
1705 | 914 |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
915 jbyte* res = card_ptr; |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
916 bool defer = false; |
1705 | 917 |
918 // This gets set to true if the card being refined has references | |
919 // that point into the collection set. | |
920 bool oops_into_cset = false; | |
921 | |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
922 if (_cg1r->use_cache()) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
923 jbyte* res = _cg1r->cache_insert(card_ptr, &defer); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
924 if (res != NULL && (res != card_ptr || defer)) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
925 start = _ct_bs->addr_for(res); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
926 r = _g1->heap_region_containing(start); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
927 if (r == NULL) { |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
928 assert(_g1->is_in_permanent(start), "Or else where?"); |
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
929 } else { |
1666
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
930 // Checking whether the region we got back from the cache |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
931 // is young here is inappropriate. The region could have been |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
932 // freed, reallocated and tagged as young while in the cache. |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
933 // Hence we could see its young type change at any time. |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
934 // |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
935 // Process card pointer we get back from the hot card cache. This |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
936 // will check whether the region containing the card is young |
5cbac8938c4c
6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307
johnc
parents:
1611
diff
changeset
|
937 // _after_ checking that the region has been allocated from. |
1705 | 938 oops_into_cset = concurrentRefineOneCard_impl(res, worker_i, |
939 false /* check_for_refs_into_cset */); | |
940 // The above call to concurrentRefineOneCard_impl is only | |
941 // performed if the hot card cache is enabled. This cache is | |
942 // disabled during an evacuation pause - which is the only | |
943 // time when we need know if the card contains references | |
944 // that point into the collection set. Also when the hot card | |
945 // cache is enabled, this code is executed by the concurrent | |
946 // refine threads - rather than the GC worker threads - and | |
947 // concurrentRefineOneCard_impl will return false. | |
948 assert(!oops_into_cset, "should not see true here"); | |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
949 } |
342 | 950 } |
951 } | |
952 | |
890
6cb8e9df7174
6819077: G1: first GC thread coming late into the GC.
johnc
parents:
845
diff
changeset
|
953 if (!defer) { |
1705 | 954 oops_into_cset = |
955 concurrentRefineOneCard_impl(card_ptr, worker_i, check_for_refs_into_cset); | |
956 // We should only be detecting that the card contains references | |
957 // that point into the collection set if the current thread is | |
958 // a GC worker thread. | |
959 assert(!oops_into_cset || SafepointSynchronize::is_at_safepoint(), | |
960 "invalid result at non safepoint"); | |
342 | 961 } |
1705 | 962 return oops_into_cset; |
342 | 963 } |
964 | |
965 class HRRSStatsIter: public HeapRegionClosure { | |
966 size_t _occupied; | |
967 size_t _total_mem_sz; | |
968 size_t _max_mem_sz; | |
969 HeapRegion* _max_mem_sz_region; | |
970 public: | |
971 HRRSStatsIter() : | |
972 _occupied(0), | |
973 _total_mem_sz(0), | |
974 _max_mem_sz(0), | |
975 _max_mem_sz_region(NULL) | |
976 {} | |
977 | |
978 bool doHeapRegion(HeapRegion* r) { | |
979 if (r->continuesHumongous()) return false; | |
980 size_t mem_sz = r->rem_set()->mem_size(); | |
981 if (mem_sz > _max_mem_sz) { | |
982 _max_mem_sz = mem_sz; | |
983 _max_mem_sz_region = r; | |
984 } | |
985 _total_mem_sz += mem_sz; | |
986 size_t occ = r->rem_set()->occupied(); | |
987 _occupied += occ; | |
988 return false; | |
989 } | |
990 size_t total_mem_sz() { return _total_mem_sz; } | |
991 size_t max_mem_sz() { return _max_mem_sz; } | |
992 size_t occupied() { return _occupied; } | |
993 HeapRegion* max_mem_sz_region() { return _max_mem_sz_region; } | |
994 }; | |
995 | |
794 | 996 class PrintRSThreadVTimeClosure : public ThreadClosure { |
997 public: | |
998 virtual void do_thread(Thread *t) { | |
999 ConcurrentG1RefineThread* crt = (ConcurrentG1RefineThread*) t; | |
1000 gclog_or_tty->print(" %5.2f", crt->vtime_accum()); | |
1001 } | |
1002 }; | |
1003 | |
342 | 1004 void HRInto_G1RemSet::print_summary_info() { |
1005 G1CollectedHeap* g1 = G1CollectedHeap::heap(); | |
1006 | |
1007 #if CARD_REPEAT_HISTO | |
1008 gclog_or_tty->print_cr("\nG1 card_repeat count histogram: "); | |
1009 gclog_or_tty->print_cr(" # of repeats --> # of cards with that number."); | |
1010 card_repeat_count.print_on(gclog_or_tty); | |
1011 #endif | |
1012 | |
1013 if (FILTEROUTOFREGIONCLOSURE_DOHISTOGRAMCOUNT) { | |
1014 gclog_or_tty->print_cr("\nG1 rem-set out-of-region histogram: "); | |
1015 gclog_or_tty->print_cr(" # of CS ptrs --> # of cards with that number."); | |
1016 out_of_histo.print_on(gclog_or_tty); | |
1017 } | |
794 | 1018 gclog_or_tty->print_cr("\n Concurrent RS processed %d cards", |
1019 _conc_refine_cards); | |
342 | 1020 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); |
1021 jint tot_processed_buffers = | |
1022 dcqs.processed_buffers_mut() + dcqs.processed_buffers_rs_thread(); | |
1023 gclog_or_tty->print_cr(" Of %d completed buffers:", tot_processed_buffers); | |
794 | 1024 gclog_or_tty->print_cr(" %8d (%5.1f%%) by conc RS threads.", |
342 | 1025 dcqs.processed_buffers_rs_thread(), |
1026 100.0*(float)dcqs.processed_buffers_rs_thread()/ | |
1027 (float)tot_processed_buffers); | |
1028 gclog_or_tty->print_cr(" %8d (%5.1f%%) by mutator threads.", | |
1029 dcqs.processed_buffers_mut(), | |
1030 100.0*(float)dcqs.processed_buffers_mut()/ | |
1031 (float)tot_processed_buffers); | |
794 | 1032 gclog_or_tty->print_cr(" Conc RS threads times(s)"); |
1033 PrintRSThreadVTimeClosure p; | |
1034 gclog_or_tty->print(" "); | |
1035 g1->concurrent_g1_refine()->threads_do(&p); | |
342 | 1036 gclog_or_tty->print_cr(""); |
794 | 1037 |
342 | 1038 if (G1UseHRIntoRS) { |
1039 HRRSStatsIter blk; | |
1040 g1->heap_region_iterate(&blk); | |
1041 gclog_or_tty->print_cr(" Total heap region rem set sizes = " SIZE_FORMAT "K." | |
1042 " Max = " SIZE_FORMAT "K.", | |
1043 blk.total_mem_sz()/K, blk.max_mem_sz()/K); | |
1044 gclog_or_tty->print_cr(" Static structures = " SIZE_FORMAT "K," | |
1045 " free_lists = " SIZE_FORMAT "K.", | |
1046 HeapRegionRemSet::static_mem_size()/K, | |
1047 HeapRegionRemSet::fl_mem_size()/K); | |
1048 gclog_or_tty->print_cr(" %d occupied cards represented.", | |
1049 blk.occupied()); | |
1050 gclog_or_tty->print_cr(" Max sz region = [" PTR_FORMAT ", " PTR_FORMAT " )" | |
677 | 1051 ", cap = " SIZE_FORMAT "K, occ = " SIZE_FORMAT "K.", |
342 | 1052 blk.max_mem_sz_region()->bottom(), blk.max_mem_sz_region()->end(), |
1053 (blk.max_mem_sz_region()->rem_set()->mem_size() + K - 1)/K, | |
1054 (blk.max_mem_sz_region()->rem_set()->occupied() + K - 1)/K); | |
1055 gclog_or_tty->print_cr(" Did %d coarsenings.", | |
1056 HeapRegionRemSet::n_coarsenings()); | |
1057 | |
1058 } | |
1059 } | |
1705 | 1060 |
342 | 1061 void HRInto_G1RemSet::prepare_for_verify() { |
637
25e146966e7c
6817419: G1: Enable extensive verification for humongous regions
iveresov
parents:
626
diff
changeset
|
1062 if (G1HRRSFlushLogBuffersOnVerify && |
25e146966e7c
6817419: G1: Enable extensive verification for humongous regions
iveresov
parents:
626
diff
changeset
|
1063 (VerifyBeforeGC || VerifyAfterGC) |
25e146966e7c
6817419: G1: Enable extensive verification for humongous regions
iveresov
parents:
626
diff
changeset
|
1064 && !_g1->full_collection()) { |
342 | 1065 cleanupHRRS(); |
1066 _g1->set_refine_cte_cl_concurrency(false); | |
1067 if (SafepointSynchronize::is_at_safepoint()) { | |
1068 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); | |
1069 dcqs.concatenate_logs(); | |
1070 } | |
1071 bool cg1r_use_cache = _cg1r->use_cache(); | |
1072 _cg1r->set_use_cache(false); | |
1705 | 1073 DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set()); |
1074 updateRS(&into_cset_dcq, 0); | |
1075 _g1->into_cset_dirty_card_queue_set().clear(); | |
342 | 1076 _cg1r->set_use_cache(cg1r_use_cache); |
637
25e146966e7c
6817419: G1: Enable extensive verification for humongous regions
iveresov
parents:
626
diff
changeset
|
1077 |
25e146966e7c
6817419: G1: Enable extensive verification for humongous regions
iveresov
parents:
626
diff
changeset
|
1078 assert(JavaThread::dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed"); |
342 | 1079 } |
1080 } |