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/dirtyCardQueue.hpp"
27 #include "gc/g1/g1BlockOffsetTable.inline.hpp"
28 #include "gc/g1/g1CardTable.inline.hpp"
29 #include "gc/g1/g1CollectedHeap.inline.hpp"
30 #include "gc/g1/g1ConcurrentRefine.hpp"
31 #include "gc/g1/g1FromCardCache.hpp"
32 #include "gc/g1/g1GCPhaseTimes.hpp"
33 #include "gc/g1/g1HotCardCache.hpp"
34 #include "gc/g1/g1OopClosures.inline.hpp"
35 #include "gc/g1/g1RemSet.hpp"
36 #include "gc/g1/heapRegion.inline.hpp"
37 #include "gc/g1/heapRegionManager.inline.hpp"
38 #include "gc/g1/heapRegionRemSet.hpp"
39 #include "gc/shared/gcTraceTime.inline.hpp"
40 #include "gc/shared/suspendibleThreadSet.hpp"
41 #include "memory/iterator.hpp"
42 #include "memory/resourceArea.hpp"
43 #include "oops/access.inline.hpp"
44 #include "oops/oop.inline.hpp"
45 #include "utilities/align.hpp"
46 #include "utilities/globalDefinitions.hpp"
47 #include "utilities/intHisto.hpp"
48 #include "utilities/stack.inline.hpp"
49 #include "utilities/ticks.inline.hpp"
50
51 // Collects information about the overall remembered set scan progress during an evacuation.
52 class G1RemSetScanState : public CHeapObj<mtGC> {
53 private:
54 class G1ClearCardTableTask : public AbstractGangTask {
288 _prev_period_summary() {
289 }
290
291 G1RemSet::~G1RemSet() {
292 if (_scan_state != NULL) {
293 delete _scan_state;
294 }
295 }
296
297 uint G1RemSet::num_par_rem_sets() {
298 return DirtyCardQueueSet::num_par_ids() + G1ConcurrentRefine::max_num_threads() + MAX2(ConcGCThreads, ParallelGCThreads);
299 }
300
301 void G1RemSet::initialize(size_t capacity, uint max_regions) {
302 G1FromCardCache::initialize(num_par_rem_sets(), max_regions);
303 _scan_state->initialize(max_regions);
304 }
305
306 G1ScanRSForRegionClosure::G1ScanRSForRegionClosure(G1RemSetScanState* scan_state,
307 G1ScanObjsDuringScanRSClosure* scan_obj_on_card,
308 CodeBlobClosure* code_root_cl,
309 uint worker_i) :
310 _scan_state(scan_state),
311 _scan_objs_on_card_cl(scan_obj_on_card),
312 _code_root_cl(code_root_cl),
313 _strong_code_root_scan_time_sec(0.0),
314 _cards_claimed(0),
315 _cards_scanned(0),
316 _cards_skipped(0),
317 _worker_i(worker_i) {
318 _g1h = G1CollectedHeap::heap();
319 _bot = _g1h->bot();
320 _ct = _g1h->card_table();
321 }
322
323 void G1ScanRSForRegionClosure::scan_card(MemRegion mr, uint region_idx_for_card) {
324 HeapRegion* const card_region = _g1h->region_at(region_idx_for_card);
325 _scan_objs_on_card_cl->set_region(card_region);
326 card_region->oops_on_card_seq_iterate_careful<true>(mr, _scan_objs_on_card_cl);
327 _cards_scanned++;
328 }
329
330 void G1ScanRSForRegionClosure::scan_strong_code_roots(HeapRegion* r) {
331 double scan_start = os::elapsedTime();
332 r->strong_code_roots_do(_code_root_cl);
333 _strong_code_root_scan_time_sec += (os::elapsedTime() - scan_start);
334 }
335
336 void G1ScanRSForRegionClosure::claim_card(size_t card_index, const uint region_idx_for_card){
337 _ct->set_card_claimed(card_index);
338 _scan_state->add_dirty_region(region_idx_for_card);
339 }
340
341 bool G1ScanRSForRegionClosure::do_heap_region(HeapRegion* r) {
342 assert(r->in_collection_set(), "should only be called on elements of CS.");
343 uint region_idx = r->hrm_index();
344
345 if (_scan_state->iter_is_complete(region_idx)) {
346 return false;
347 }
348 if (_scan_state->claim_iter(region_idx)) {
349 // If we ever free the collection set concurrently, we should also
350 // clear the card table concurrently therefore we won't need to
351 // add regions of the collection set to the dirty cards region.
352 _scan_state->add_dirty_region(region_idx);
353 }
354
355 // We claim cards in blocks so as to reduce the contention.
356 size_t const block_size = G1RSetScanBlockSize;
357
358 HeapRegionRemSetIterator iter(r->rem_set());
359 size_t card_index;
360
361 size_t claimed_card_block = _scan_state->iter_claimed_next(region_idx, block_size);
362 for (size_t current_card = 0; iter.has_next(card_index); current_card++) {
363 if (current_card >= claimed_card_block + block_size) {
364 claimed_card_block = _scan_state->iter_claimed_next(region_idx, block_size);
365 }
366 if (current_card < claimed_card_block) {
367 _cards_skipped++;
379
380 assert(_g1h->region_at(region_idx_for_card)->is_in_reserved(card_start),
381 "Card start " PTR_FORMAT " to scan outside of region %u", p2i(card_start), _g1h->region_at(region_idx_for_card)->hrm_index());
382 HeapWord* const top = _scan_state->scan_top(region_idx_for_card);
383 if (card_start >= top) {
384 continue;
385 }
386
387 // We claim lazily (so races are possible but they're benign), which reduces the
388 // number of duplicate scans (the rsets of the regions in the cset can intersect).
389 // Claim the card after checking bounds above: the remembered set may contain
390 // random cards into current survivor, and we would then have an incorrectly
391 // claimed card in survivor space. Card table clear does not reset the card table
392 // of survivor space regions.
393 claim_card(card_index, region_idx_for_card);
394
395 MemRegion const mr(card_start, MIN2(card_start + BOTConstants::N_words, top));
396
397 scan_card(mr, region_idx_for_card);
398 }
399 if (_scan_state->set_iter_complete(region_idx)) {
400 // Scan the strong code root list attached to the current region
401 scan_strong_code_roots(r);
402 }
403 return false;
404 }
405
406 void G1RemSet::scan_rem_set(G1ParScanThreadState* pss,
407 CodeBlobClosure* heap_region_codeblobs,
408 uint worker_i) {
409 double rs_time_start = os::elapsedTime();
410
411 G1ScanObjsDuringScanRSClosure scan_cl(_g1h, pss);
412 G1ScanRSForRegionClosure cl(_scan_state, &scan_cl, heap_region_codeblobs, worker_i);
413 _g1h->collection_set_iterate_from(&cl, worker_i);
414
415 double scan_rs_time_sec = (os::elapsedTime() - rs_time_start) -
416 cl.strong_code_root_scan_time_sec();
417
418 G1GCPhaseTimes* p = _g1p->phase_times();
419
420 p->record_time_secs(G1GCPhaseTimes::ScanRS, worker_i, scan_rs_time_sec);
421 p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_scanned(), G1GCPhaseTimes::ScanRSScannedCards);
422 p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_claimed(), G1GCPhaseTimes::ScanRSClaimedCards);
423 p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_skipped(), G1GCPhaseTimes::ScanRSSkippedCards);
424
425 p->record_time_secs(G1GCPhaseTimes::CodeRoots, worker_i, cl.strong_code_root_scan_time_sec());
426 }
427
428 // Closure used for updating rem sets. Only called during an evacuation pause.
429 class G1RefineCardClosure: public CardTableEntryClosure {
430 G1RemSet* _g1rs;
431 G1ScanObjsDuringUpdateRSClosure* _update_rs_cl;
432
433 size_t _cards_scanned;
434 size_t _cards_skipped;
435 public:
436 G1RefineCardClosure(G1CollectedHeap* g1h, G1ScanObjsDuringUpdateRSClosure* update_rs_cl) :
437 _g1rs(g1h->g1_rem_set()), _update_rs_cl(update_rs_cl), _cards_scanned(0), _cards_skipped(0)
438 {}
439
440 bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
441 // The only time we care about recording cards that
442 // contain references that point into the collection set
443 // is during RSet updating within an evacuation pause.
444 // In this case worker_i should be the id of a GC worker thread.
445 assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause");
446
447 bool card_scanned = _g1rs->refine_card_during_gc(card_ptr, _update_rs_cl);
448
449 if (card_scanned) {
450 _cards_scanned++;
451 } else {
452 _cards_skipped++;
453 }
454 return true;
455 }
456
457 size_t cards_scanned() const { return _cards_scanned; }
458 size_t cards_skipped() const { return _cards_skipped; }
459 };
460
461 void G1RemSet::update_rem_set(G1ParScanThreadState* pss, uint worker_i) {
462 G1ScanObjsDuringUpdateRSClosure update_rs_cl(_g1h, pss, worker_i);
463 G1RefineCardClosure refine_card_cl(_g1h, &update_rs_cl);
464
465 G1GCParPhaseTimesTracker x(_g1p->phase_times(), G1GCPhaseTimes::UpdateRS, worker_i);
466 if (G1HotCardCache::default_use_cache()) {
467 // Apply the closure to the entries of the hot card cache.
468 G1GCParPhaseTimesTracker y(_g1p->phase_times(), G1GCPhaseTimes::ScanHCC, worker_i);
469 _g1h->iterate_hcc_closure(&refine_card_cl, worker_i);
470 }
471 // Apply the closure to all remaining log entries.
472 _g1h->iterate_dirty_card_closure(&refine_card_cl, worker_i);
473
474 G1GCPhaseTimes* p = _g1p->phase_times();
475 p->record_thread_work_item(G1GCPhaseTimes::UpdateRS, worker_i, refine_card_cl.cards_scanned(), G1GCPhaseTimes::UpdateRSScannedCards);
476 p->record_thread_work_item(G1GCPhaseTimes::UpdateRS, worker_i, refine_card_cl.cards_skipped(), G1GCPhaseTimes::UpdateRSSkippedCards);
477 }
478
479 void G1RemSet::cleanupHRRS() {
480 HeapRegionRemSet::cleanup();
481 }
482
483 void G1RemSet::oops_into_collection_set_do(G1ParScanThreadState* pss,
484 CodeBlobClosure* heap_region_codeblobs,
485 uint worker_i) {
486 update_rem_set(pss, worker_i);
487 scan_rem_set(pss, heap_region_codeblobs, worker_i);;
488 }
489
490 void G1RemSet::prepare_for_oops_into_collection_set_do() {
491 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
492 dcqs.concatenate_logs();
493
494 _scan_state->reset();
495 }
496
497 void G1RemSet::cleanup_after_oops_into_collection_set_do() {
498 G1GCPhaseTimes* phase_times = _g1h->g1_policy()->phase_times();
499
500 // Set all cards back to clean.
501 double start = os::elapsedTime();
502 _scan_state->clear_card_table(_g1h->workers());
503 phase_times->record_clear_ct_time((os::elapsedTime() - start) * 1000.0);
504 }
505
506 inline void check_card_ptr(jbyte* card_ptr, G1CardTable* ct) {
507 #ifdef ASSERT
|
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/dirtyCardQueue.hpp"
27 #include "gc/g1/g1BlockOffsetTable.inline.hpp"
28 #include "gc/g1/g1CardTable.inline.hpp"
29 #include "gc/g1/g1CollectedHeap.inline.hpp"
30 #include "gc/g1/g1ConcurrentRefine.hpp"
31 #include "gc/g1/g1FromCardCache.hpp"
32 #include "gc/g1/g1GCPhaseTimes.hpp"
33 #include "gc/g1/g1HotCardCache.hpp"
34 #include "gc/g1/g1OopClosures.inline.hpp"
35 #include "gc/g1/g1RootClosures.hpp"
36 #include "gc/g1/g1RemSet.hpp"
37 #include "gc/g1/heapRegion.inline.hpp"
38 #include "gc/g1/heapRegionManager.inline.hpp"
39 #include "gc/g1/heapRegionRemSet.hpp"
40 #include "gc/shared/gcTraceTime.inline.hpp"
41 #include "gc/shared/suspendibleThreadSet.hpp"
42 #include "memory/iterator.hpp"
43 #include "memory/resourceArea.hpp"
44 #include "oops/access.inline.hpp"
45 #include "oops/oop.inline.hpp"
46 #include "utilities/align.hpp"
47 #include "utilities/globalDefinitions.hpp"
48 #include "utilities/intHisto.hpp"
49 #include "utilities/stack.inline.hpp"
50 #include "utilities/ticks.inline.hpp"
51
52 // Collects information about the overall remembered set scan progress during an evacuation.
53 class G1RemSetScanState : public CHeapObj<mtGC> {
54 private:
55 class G1ClearCardTableTask : public AbstractGangTask {
289 _prev_period_summary() {
290 }
291
292 G1RemSet::~G1RemSet() {
293 if (_scan_state != NULL) {
294 delete _scan_state;
295 }
296 }
297
298 uint G1RemSet::num_par_rem_sets() {
299 return DirtyCardQueueSet::num_par_ids() + G1ConcurrentRefine::max_num_threads() + MAX2(ConcGCThreads, ParallelGCThreads);
300 }
301
302 void G1RemSet::initialize(size_t capacity, uint max_regions) {
303 G1FromCardCache::initialize(num_par_rem_sets(), max_regions);
304 _scan_state->initialize(max_regions);
305 }
306
307 G1ScanRSForRegionClosure::G1ScanRSForRegionClosure(G1RemSetScanState* scan_state,
308 G1ScanObjsDuringScanRSClosure* scan_obj_on_card,
309 G1ParScanThreadState* pss,
310 uint worker_i) :
311 _g1h(G1CollectedHeap::heap()),
312 _ct(_g1h->card_table()),
313 _pss(pss),
314 _scan_objs_on_card_cl(scan_obj_on_card),
315 _scan_state(scan_state),
316 _worker_i(worker_i),
317 _cards_claimed(0),
318 _cards_scanned(0),
319 _cards_skipped(0),
320 _rem_set_root_scan_time(),
321 _rem_set_trim_partially_time(),
322 _strong_code_root_scan_time(),
323 _strong_code_trim_partially_time() {
324 }
325
326 void G1ScanRSForRegionClosure::claim_card(size_t card_index, const uint region_idx_for_card){
327 _ct->set_card_claimed(card_index);
328 _scan_state->add_dirty_region(region_idx_for_card);
329 }
330
331 void G1ScanRSForRegionClosure::scan_card(MemRegion mr, uint region_idx_for_card) {
332 HeapRegion* const card_region = _g1h->region_at(region_idx_for_card);
333 _scan_objs_on_card_cl->set_region(card_region);
334 card_region->oops_on_card_seq_iterate_careful<true>(mr, _scan_objs_on_card_cl);
335 _scan_objs_on_card_cl->trim_queue_partially();
336 _cards_scanned++;
337 }
338
339 void G1ScanRSForRegionClosure::scan_rem_set_roots(HeapRegion* r) {
340 uint const region_idx = r->hrm_index();
341
342 if (_scan_state->claim_iter(region_idx)) {
343 // If we ever free the collection set concurrently, we should also
344 // clear the card table concurrently therefore we won't need to
345 // add regions of the collection set to the dirty cards region.
346 _scan_state->add_dirty_region(region_idx);
347 }
348
349 // We claim cards in blocks so as to reduce the contention.
350 size_t const block_size = G1RSetScanBlockSize;
351
352 HeapRegionRemSetIterator iter(r->rem_set());
353 size_t card_index;
354
355 size_t claimed_card_block = _scan_state->iter_claimed_next(region_idx, block_size);
356 for (size_t current_card = 0; iter.has_next(card_index); current_card++) {
357 if (current_card >= claimed_card_block + block_size) {
358 claimed_card_block = _scan_state->iter_claimed_next(region_idx, block_size);
359 }
360 if (current_card < claimed_card_block) {
361 _cards_skipped++;
373
374 assert(_g1h->region_at(region_idx_for_card)->is_in_reserved(card_start),
375 "Card start " PTR_FORMAT " to scan outside of region %u", p2i(card_start), _g1h->region_at(region_idx_for_card)->hrm_index());
376 HeapWord* const top = _scan_state->scan_top(region_idx_for_card);
377 if (card_start >= top) {
378 continue;
379 }
380
381 // We claim lazily (so races are possible but they're benign), which reduces the
382 // number of duplicate scans (the rsets of the regions in the cset can intersect).
383 // Claim the card after checking bounds above: the remembered set may contain
384 // random cards into current survivor, and we would then have an incorrectly
385 // claimed card in survivor space. Card table clear does not reset the card table
386 // of survivor space regions.
387 claim_card(card_index, region_idx_for_card);
388
389 MemRegion const mr(card_start, MIN2(card_start + BOTConstants::N_words, top));
390
391 scan_card(mr, region_idx_for_card);
392 }
393 }
394
395 void G1ScanRSForRegionClosure::scan_strong_code_roots(HeapRegion* r) {
396 r->strong_code_roots_do(_pss->closures()->weak_codeblobs());
397 }
398
399 bool G1ScanRSForRegionClosure::do_heap_region(HeapRegion* r) {
400 assert(r->in_collection_set(),
401 "Should only be called on elements of the collection set but region %u is not.",
402 r->hrm_index());
403 uint const region_idx = r->hrm_index();
404
405 // Do an early out if we know we are complete.
406 if (_scan_state->iter_is_complete(region_idx)) {
407 return false;
408 }
409
410 {
411 G1EvacPhaseWithTrimTimeTracker timer(_pss, _rem_set_root_scan_time, _rem_set_trim_partially_time);
412 scan_rem_set_roots(r);
413 }
414
415 if (_scan_state->set_iter_complete(region_idx)) {
416 G1EvacPhaseWithTrimTimeTracker timer(_pss, _strong_code_root_scan_time, _strong_code_trim_partially_time);
417 // Scan the strong code root list attached to the current region
418 scan_strong_code_roots(r);
419 }
420 return false;
421 }
422
423 void G1RemSet::scan_rem_set(G1ParScanThreadState* pss, uint worker_i) {
424 G1ScanObjsDuringScanRSClosure scan_cl(_g1h, pss);
425 G1ScanRSForRegionClosure cl(_scan_state, &scan_cl, pss, worker_i);
426 _g1h->collection_set_iterate_from(&cl, worker_i);
427
428 G1GCPhaseTimes* p = _g1p->phase_times();
429
430 p->record_time_secs(G1GCPhaseTimes::ScanRS, worker_i, TicksToTimeHelper::seconds(cl.rem_set_root_scan_time()));
431 p->add_time_secs(G1GCPhaseTimes::ObjCopy, worker_i, TicksToTimeHelper::seconds(cl.rem_set_trim_partially_time()));
432
433 p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_scanned(), G1GCPhaseTimes::ScanRSScannedCards);
434 p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_claimed(), G1GCPhaseTimes::ScanRSClaimedCards);
435 p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_skipped(), G1GCPhaseTimes::ScanRSSkippedCards);
436
437 p->record_time_secs(G1GCPhaseTimes::CodeRoots, worker_i, TicksToTimeHelper::seconds(cl.strong_code_root_scan_time()));
438 p->add_time_secs(G1GCPhaseTimes::ObjCopy, worker_i, TicksToTimeHelper::seconds(cl.strong_code_root_trim_partially_time()));
439 }
440
441 // Closure used for updating rem sets. Only called during an evacuation pause.
442 class G1RefineCardClosure: public CardTableEntryClosure {
443 G1RemSet* _g1rs;
444 G1ScanObjsDuringUpdateRSClosure* _update_rs_cl;
445
446 size_t _cards_scanned;
447 size_t _cards_skipped;
448 public:
449 G1RefineCardClosure(G1CollectedHeap* g1h, G1ScanObjsDuringUpdateRSClosure* update_rs_cl) :
450 _g1rs(g1h->g1_rem_set()), _update_rs_cl(update_rs_cl), _cards_scanned(0), _cards_skipped(0)
451 {}
452
453 bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
454 // The only time we care about recording cards that
455 // contain references that point into the collection set
456 // is during RSet updating within an evacuation pause.
457 // In this case worker_i should be the id of a GC worker thread.
458 assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause");
459
460 bool card_scanned = _g1rs->refine_card_during_gc(card_ptr, _update_rs_cl);
461
462 if (card_scanned) {
463 _update_rs_cl->trim_queue_partially();
464 _cards_scanned++;
465 } else {
466 _cards_skipped++;
467 }
468 return true;
469 }
470
471 size_t cards_scanned() const { return _cards_scanned; }
472 size_t cards_skipped() const { return _cards_skipped; }
473 };
474
475 void G1RemSet::update_rem_set(G1ParScanThreadState* pss, uint worker_i) {
476 G1GCPhaseTimes* p = _g1p->phase_times();
477
478 // Apply closure to log entries in the HCC.
479 if (G1HotCardCache::default_use_cache()) {
480 G1EvacPhaseTimesTracker x(p, pss, G1GCPhaseTimes::ScanHCC, worker_i);
481
482 G1ScanObjsDuringUpdateRSClosure scan_hcc_cl(_g1h, pss, worker_i);
483 G1RefineCardClosure refine_card_cl(_g1h, &scan_hcc_cl);
484 _g1h->iterate_hcc_closure(&refine_card_cl, worker_i);
485 }
486
487 // Now apply the closure to all remaining log entries.
488 {
489 G1EvacPhaseTimesTracker x(p, pss, G1GCPhaseTimes::UpdateRS, worker_i);
490
491 G1ScanObjsDuringUpdateRSClosure update_rs_cl(_g1h, pss, worker_i);
492 G1RefineCardClosure refine_card_cl(_g1h, &update_rs_cl);
493 _g1h->iterate_dirty_card_closure(&refine_card_cl, worker_i);
494
495 p->record_thread_work_item(G1GCPhaseTimes::UpdateRS, worker_i, refine_card_cl.cards_scanned(), G1GCPhaseTimes::UpdateRSScannedCards);
496 p->record_thread_work_item(G1GCPhaseTimes::UpdateRS, worker_i, refine_card_cl.cards_skipped(), G1GCPhaseTimes::UpdateRSSkippedCards);
497 }
498 }
499
500 void G1RemSet::cleanupHRRS() {
501 HeapRegionRemSet::cleanup();
502 }
503
504 void G1RemSet::oops_into_collection_set_do(G1ParScanThreadState* pss, uint worker_i) {
505 update_rem_set(pss, worker_i);
506 scan_rem_set(pss, worker_i);;
507 }
508
509 void G1RemSet::prepare_for_oops_into_collection_set_do() {
510 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
511 dcqs.concatenate_logs();
512
513 _scan_state->reset();
514 }
515
516 void G1RemSet::cleanup_after_oops_into_collection_set_do() {
517 G1GCPhaseTimes* phase_times = _g1h->g1_policy()->phase_times();
518
519 // Set all cards back to clean.
520 double start = os::elapsedTime();
521 _scan_state->clear_card_table(_g1h->workers());
522 phase_times->record_clear_ct_time((os::elapsedTime() - start) * 1000.0);
523 }
524
525 inline void check_card_ptr(jbyte* card_ptr, G1CardTable* ct) {
526 #ifdef ASSERT
|