15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "gc/g1/concurrentG1Refine.hpp"
27 #include "gc/g1/concurrentG1RefineThread.hpp"
28 #include "gc/g1/g1BlockOffsetTable.inline.hpp"
29 #include "gc/g1/g1CollectedHeap.inline.hpp"
30 #include "gc/g1/g1CollectorPolicy.hpp"
31 #include "gc/g1/g1GCPhaseTimes.hpp"
32 #include "gc/g1/g1HotCardCache.hpp"
33 #include "gc/g1/g1OopClosures.inline.hpp"
34 #include "gc/g1/g1RemSet.inline.hpp"
35 #include "gc/g1/heapRegionManager.inline.hpp"
36 #include "gc/g1/heapRegionRemSet.hpp"
37 #include "memory/iterator.hpp"
38 #include "oops/oop.inline.hpp"
39 #include "utilities/globalDefinitions.hpp"
40 #include "utilities/intHisto.hpp"
41 #include "utilities/stack.inline.hpp"
42
43 #define CARD_REPEAT_HISTO 0
44
45 #if CARD_REPEAT_HISTO
46 static size_t ct_freq_sz;
47 static jbyte* ct_freq = NULL;
48
49 void init_ct_freq_table(size_t heap_sz_bytes) {
50 if (ct_freq == NULL) {
51 ct_freq_sz = heap_sz_bytes/CardTableModRefBS::card_size;
52 ct_freq = new jbyte[ct_freq_sz];
53 for (size_t j = 0; j < ct_freq_sz; j++) ct_freq[j] = 0;
54 }
209 scanCard(card_index, card_region);
210 }
211 }
212 if (!_try_claimed) {
213 // Scan the strong code root list attached to the current region
214 scan_strong_code_roots(r);
215
216 hrrs->set_iter_complete();
217 }
218 return false;
219 }
220
221 double strong_code_root_scan_time_sec() {
222 return _strong_code_root_scan_time_sec;
223 }
224
225 size_t cards_done() { return _cards_done;}
226 size_t cards_looked_up() { return _cards;}
227 };
228
229 size_t G1RemSet::scanRS(G1ParPushHeapRSClosure* oc,
230 CodeBlobClosure* heap_region_codeblobs,
231 uint worker_i) {
232 double rs_time_start = os::elapsedTime();
233
234 HeapRegion *startRegion = _g1->start_cset_region_for_worker(worker_i);
235
236 ScanRSClosure scanRScl(oc, heap_region_codeblobs, worker_i);
237
238 _g1->collection_set_iterate_from(startRegion, &scanRScl);
239 scanRScl.set_try_claimed();
240 _g1->collection_set_iterate_from(startRegion, &scanRScl);
241
242 double scan_rs_time_sec = (os::elapsedTime() - rs_time_start)
243 - scanRScl.strong_code_root_scan_time_sec();
244
245 _g1p->phase_times()->record_time_secs(G1GCPhaseTimes::ScanRS, worker_i, scan_rs_time_sec);
246 _g1p->phase_times()->record_time_secs(G1GCPhaseTimes::CodeRoots, worker_i, scanRScl.strong_code_root_scan_time_sec());
247
248 return scanRScl.cards_done();
249 }
250
251 // Closure used for updating RSets and recording references that
252 // point into the collection set. Only called during an
253 // evacuation pause.
254
255 class RefineRecordRefsIntoCSCardTableEntryClosure: public CardTableEntryClosure {
256 G1RemSet* _g1rs;
276 //
277 // Enqueue the card
278 _into_cset_dcq->enqueue(card_ptr);
279 }
280 return true;
281 }
282 };
283
284 void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i) {
285 G1GCParPhaseTimesTracker x(_g1p->phase_times(), G1GCPhaseTimes::UpdateRS, worker_i);
286 // Apply the given closure to all remaining log entries.
287 RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq);
288
289 _g1->iterate_dirty_card_closure(&into_cset_update_rs_cl, into_cset_dcq, false, worker_i);
290 }
291
292 void G1RemSet::cleanupHRRS() {
293 HeapRegionRemSet::cleanup();
294 }
295
296 size_t G1RemSet::oops_into_collection_set_do(G1ParPushHeapRSClosure* oc,
297 CodeBlobClosure* heap_region_codeblobs,
298 uint worker_i) {
299 #if CARD_REPEAT_HISTO
300 ct_freq_update_histo_and_reset();
301 #endif
302
303 // We cache the value of 'oc' closure into the appropriate slot in the
304 // _cset_rs_update_cl for this worker
305 assert(worker_i < n_workers(), "sanity");
306 _cset_rs_update_cl[worker_i] = oc;
307
308 // A DirtyCardQueue that is used to hold cards containing references
309 // that point into the collection set. This DCQ is associated with a
310 // special DirtyCardQueueSet (see g1CollectedHeap.hpp). Under normal
311 // circumstances (i.e. the pause successfully completes), these cards
312 // are just discarded (there's no need to update the RSets of regions
313 // that were in the collection set - after the pause these regions
314 // are wholly 'free' of live objects. In the event of an evacuation
315 // failure the cards/buffers in this queue set are passed to the
316 // DirtyCardQueueSet that is used to manage RSet updates
317 DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set());
318
319 updateRS(&into_cset_dcq, worker_i);
320 size_t cards_scanned = scanRS(oc, heap_region_codeblobs, worker_i);
321
322 // We now clear the cached values of _cset_rs_update_cl for this worker
323 _cset_rs_update_cl[worker_i] = NULL;
324 return cards_scanned;
325 }
326
327 void G1RemSet::prepare_for_oops_into_collection_set_do() {
328 cleanupHRRS();
329 _g1->set_refine_cte_cl_concurrency(false);
330 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
331 dcqs.concatenate_logs();
332 }
333
334 void G1RemSet::cleanup_after_oops_into_collection_set_do() {
335 // Cleanup after copy
336 _g1->set_refine_cte_cl_concurrency(true);
337 // Set all cards back to clean.
338 _g1->cleanUpCardTable();
339
340 DirtyCardQueueSet& into_cset_dcqs = _g1->into_cset_dirty_card_queue_set();
|
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "gc/g1/concurrentG1Refine.hpp"
27 #include "gc/g1/concurrentG1RefineThread.hpp"
28 #include "gc/g1/g1BlockOffsetTable.inline.hpp"
29 #include "gc/g1/g1CollectedHeap.inline.hpp"
30 #include "gc/g1/g1CollectorPolicy.hpp"
31 #include "gc/g1/g1GCPhaseTimes.hpp"
32 #include "gc/g1/g1HotCardCache.hpp"
33 #include "gc/g1/g1OopClosures.inline.hpp"
34 #include "gc/g1/g1RemSet.inline.hpp"
35 #include "gc/g1/g1RootClosures.hpp"
36 #include "gc/g1/heapRegionManager.inline.hpp"
37 #include "gc/g1/heapRegionRemSet.hpp"
38 #include "memory/iterator.hpp"
39 #include "oops/oop.inline.hpp"
40 #include "utilities/globalDefinitions.hpp"
41 #include "utilities/intHisto.hpp"
42 #include "utilities/stack.inline.hpp"
43
44 #define CARD_REPEAT_HISTO 0
45
46 #if CARD_REPEAT_HISTO
47 static size_t ct_freq_sz;
48 static jbyte* ct_freq = NULL;
49
50 void init_ct_freq_table(size_t heap_sz_bytes) {
51 if (ct_freq == NULL) {
52 ct_freq_sz = heap_sz_bytes/CardTableModRefBS::card_size;
53 ct_freq = new jbyte[ct_freq_sz];
54 for (size_t j = 0; j < ct_freq_sz; j++) ct_freq[j] = 0;
55 }
210 scanCard(card_index, card_region);
211 }
212 }
213 if (!_try_claimed) {
214 // Scan the strong code root list attached to the current region
215 scan_strong_code_roots(r);
216
217 hrrs->set_iter_complete();
218 }
219 return false;
220 }
221
222 double strong_code_root_scan_time_sec() {
223 return _strong_code_root_scan_time_sec;
224 }
225
226 size_t cards_done() { return _cards_done;}
227 size_t cards_looked_up() { return _cards;}
228 };
229
230 size_t G1RemSet::scanRS(G1EvacuationRootClosures* closures,
231 uint worker_i) {
232 double rs_time_start = os::elapsedTime();
233
234 HeapRegion *startRegion = _g1->start_cset_region_for_worker(worker_i);
235
236 ScanRSClosure scanRScl(closures->inter_region_oops(),
237 closures->weak_codeblobs(),
238 worker_i);
239
240 _g1->collection_set_iterate_from(startRegion, &scanRScl);
241 scanRScl.set_try_claimed();
242 _g1->collection_set_iterate_from(startRegion, &scanRScl);
243
244 double scan_rs_time_sec = (os::elapsedTime() - rs_time_start)
245 - scanRScl.strong_code_root_scan_time_sec();
246
247 _g1p->phase_times()->record_time_secs(G1GCPhaseTimes::ScanRS, worker_i, scan_rs_time_sec);
248 _g1p->phase_times()->record_time_secs(G1GCPhaseTimes::CodeRoots, worker_i, scanRScl.strong_code_root_scan_time_sec());
249
250 return scanRScl.cards_done();
251 }
252
253 // Closure used for updating RSets and recording references that
254 // point into the collection set. Only called during an
255 // evacuation pause.
256
257 class RefineRecordRefsIntoCSCardTableEntryClosure: public CardTableEntryClosure {
258 G1RemSet* _g1rs;
278 //
279 // Enqueue the card
280 _into_cset_dcq->enqueue(card_ptr);
281 }
282 return true;
283 }
284 };
285
286 void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i) {
287 G1GCParPhaseTimesTracker x(_g1p->phase_times(), G1GCPhaseTimes::UpdateRS, worker_i);
288 // Apply the given closure to all remaining log entries.
289 RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq);
290
291 _g1->iterate_dirty_card_closure(&into_cset_update_rs_cl, into_cset_dcq, false, worker_i);
292 }
293
294 void G1RemSet::cleanupHRRS() {
295 HeapRegionRemSet::cleanup();
296 }
297
298 size_t G1RemSet::oops_into_collection_set_do(G1EvacuationRootClosures* closures,
299 uint worker_i) {
300 #if CARD_REPEAT_HISTO
301 ct_freq_update_histo_and_reset();
302 #endif
303
304 // We cache the value of 'oc' closure into the appropriate slot in the
305 // _cset_rs_update_cl for this worker
306 assert(worker_i < n_workers(), "sanity");
307 _cset_rs_update_cl[worker_i] = closures->inter_region_oops();
308
309 // A DirtyCardQueue that is used to hold cards containing references
310 // that point into the collection set. This DCQ is associated with a
311 // special DirtyCardQueueSet (see g1CollectedHeap.hpp). Under normal
312 // circumstances (i.e. the pause successfully completes), these cards
313 // are just discarded (there's no need to update the RSets of regions
314 // that were in the collection set - after the pause these regions
315 // are wholly 'free' of live objects. In the event of an evacuation
316 // failure the cards/buffers in this queue set are passed to the
317 // DirtyCardQueueSet that is used to manage RSet updates
318 DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set());
319
320 updateRS(&into_cset_dcq, worker_i);
321 size_t cards_scanned = scanRS(closures, worker_i);
322
323 // We now clear the cached values of _cset_rs_update_cl for this worker
324 _cset_rs_update_cl[worker_i] = NULL;
325 return cards_scanned;
326 }
327
328 void G1RemSet::prepare_for_oops_into_collection_set_do() {
329 cleanupHRRS();
330 _g1->set_refine_cte_cl_concurrency(false);
331 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
332 dcqs.concatenate_logs();
333 }
334
335 void G1RemSet::cleanup_after_oops_into_collection_set_do() {
336 // Cleanup after copy
337 _g1->set_refine_cte_cl_concurrency(true);
338 // Set all cards back to clean.
339 _g1->cleanUpCardTable();
340
341 DirtyCardQueueSet& into_cset_dcqs = _g1->into_cset_dirty_card_queue_set();
|