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