3471 // PtrQueueSet::buffer_size() and PtrQueue:size() return sizes
3472 // in bytes - not the number of 'entries'. We need to convert
3473 // into a number of cards.
3474 return (buffer_size * buffer_num + extra_cards) / oopSize;
3475 }
3476
3477 size_t G1CollectedHeap::cards_scanned() {
3478 return g1_rem_set()->cardsScanned();
3479 }
3480
3481 bool G1CollectedHeap::humongous_region_is_always_live(uint index) {
3482 HeapRegion* region = region_at(index);
3483 assert(region->is_starts_humongous(), "Must start a humongous object");
3484 return oop(region->bottom())->is_objArray() || !region->rem_set()->is_empty();
3485 }
3486
3487 class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure {
3488 private:
3489 size_t _total_humongous;
3490 size_t _candidate_humongous;
3491 public:
3492 RegisterHumongousWithInCSetFastTestClosure() : _total_humongous(0), _candidate_humongous(0) {
3493 }
3494
3495 virtual bool doHeapRegion(HeapRegion* r) {
3496 if (!r->is_starts_humongous()) {
3497 return false;
3498 }
3499 G1CollectedHeap* g1h = G1CollectedHeap::heap();
3500
3501 uint region_idx = r->hrm_index();
3502 bool is_candidate = !g1h->humongous_region_is_always_live(region_idx);
3503 // Is_candidate already filters out humongous regions with some remembered set.
3504 // This will not lead to humongous object that we mistakenly keep alive because
3505 // during young collection the remembered sets will only be added to.
3506 if (is_candidate) {
3507 g1h->register_humongous_region_with_in_cset_fast_test(region_idx);
3508 _candidate_humongous++;
3509 }
3510 _total_humongous++;
3511
3512 return false;
3513 }
3514
3515 size_t total_humongous() const { return _total_humongous; }
3516 size_t candidate_humongous() const { return _candidate_humongous; }
3517 };
3518
3519 void G1CollectedHeap::register_humongous_regions_with_in_cset_fast_test() {
3520 if (!G1ReclaimDeadHumongousObjectsAtYoungGC) {
3521 g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(0, 0);
3522 return;
3523 }
3524
3525 RegisterHumongousWithInCSetFastTestClosure cl;
3526 heap_region_iterate(&cl);
3527 g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(cl.total_humongous(),
3528 cl.candidate_humongous());
3529 _has_humongous_reclaim_candidates = cl.candidate_humongous() > 0;
3530
3531 if (_has_humongous_reclaim_candidates || G1TraceReclaimDeadHumongousObjectsAtYoungGC) {
3532 clear_humongous_is_live_table();
3533 }
3534 }
3535
3536 void
3537 G1CollectedHeap::setup_surviving_young_words() {
3538 assert(_surviving_young_words == NULL, "pre-condition");
3539 uint array_length = g1_policy()->young_cset_region_length();
3540 _surviving_young_words = NEW_C_HEAP_ARRAY(size_t, (size_t) array_length, mtGC);
3541 if (_surviving_young_words == NULL) {
3542 vm_exit_out_of_memory(sizeof(size_t) * array_length, OOM_MALLOC_ERROR,
3543 "Not enough space for young surv words summary.");
3544 }
3545 memset(_surviving_young_words, 0, (size_t) array_length * sizeof(size_t));
3546 #ifdef ASSERT
3547 for (uint i = 0; i < array_length; ++i) {
3548 assert( _surviving_young_words[i] == 0, "memset above" );
3549 }
3550 #endif // !ASSERT
3551 }
3552
3553 void
6116 // A humongous object cannot be live if there is no remembered set for it
6117 // because:
6118 // - there can be no references from within humongous starts regions referencing
6119 // the object because we never allocate other objects into them.
6120 // (I.e. there are no intra-region references that may be missed by the
6121 // remembered set)
6122 // - as soon there is a remembered set entry to the humongous starts region
6123 // (i.e. it has "escaped" to an old object) this remembered set entry will stay
6124 // until the end of a concurrent mark.
6125 //
6126 // It is not required to check whether the object has been found dead by marking
6127 // or not, in fact it would prevent reclamation within a concurrent cycle, as
6128 // all objects allocated during that time are considered live.
6129 // SATB marking is even more conservative than the remembered set.
6130 // So if at this point in the collection there is no remembered set entry,
6131 // nobody has a reference to it.
6132 // At the start of collection we flush all refinement logs, and remembered sets
6133 // are completely up-to-date wrt to references to the humongous object.
6134 //
6135 // Other implementation considerations:
6136 // - never consider object arrays: while they are a valid target, they have not
6137 // been observed to be used as temporary objects.
6138 // - they would also pose considerable effort for cleaning up the the remembered
6139 // sets.
6140 // While this cleanup is not strictly necessary to be done (or done instantly),
6141 // given that their occurrence is very low, this saves us this additional
6142 // complexity.
6143 uint region_idx = r->hrm_index();
6144 if (g1h->humongous_is_live(region_idx) ||
6145 g1h->humongous_region_is_always_live(region_idx)) {
6146
6147 if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) {
6148 gclog_or_tty->print_cr("Live humongous %d region %d size "SIZE_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d",
6149 r->is_humongous(),
6150 region_idx,
6151 obj->size()*HeapWordSize,
6152 r->rem_set()->occupied(),
6153 r->rem_set()->strong_code_roots_list_length(),
6154 next_bitmap->isMarked(r->bottom()),
6155 g1h->humongous_is_live(region_idx),
6156 obj->is_objArray()
6157 );
6158 }
6159
6160 return false;
6161 }
6162
6163 guarantee(!obj->is_objArray(),
6164 err_msg("Eagerly reclaiming object arrays is not supported, but the object "PTR_FORMAT" is.",
6165 r->bottom()));
6166
6167 if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) {
6168 gclog_or_tty->print_cr("Reclaim humongous region %d size "SIZE_FORMAT" start "PTR_FORMAT" region %d length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d",
6169 r->is_humongous(),
6170 obj->size()*HeapWordSize,
6171 r->bottom(),
6172 region_idx,
6173 r->region_num(),
6174 r->rem_set()->occupied(),
6175 r->rem_set()->strong_code_roots_list_length(),
6176 next_bitmap->isMarked(r->bottom()),
6177 g1h->humongous_is_live(region_idx),
6178 obj->is_objArray()
6179 );
6180 }
6181 // Need to clear mark bit of the humongous object if already set.
6182 if (next_bitmap->isMarked(r->bottom())) {
6183 next_bitmap->clear(r->bottom());
6184 }
6185 _freed_bytes += r->used();
6186 r->set_containing_set(NULL);
6187 _humongous_regions_removed.increment(1u, r->capacity());
6188 g1h->free_humongous_region(r, _free_region_list, false);
6189
6190 return false;
6191 }
6192
|
3471 // PtrQueueSet::buffer_size() and PtrQueue:size() return sizes
3472 // in bytes - not the number of 'entries'. We need to convert
3473 // into a number of cards.
3474 return (buffer_size * buffer_num + extra_cards) / oopSize;
3475 }
3476
3477 size_t G1CollectedHeap::cards_scanned() {
3478 return g1_rem_set()->cardsScanned();
3479 }
3480
3481 bool G1CollectedHeap::humongous_region_is_always_live(uint index) {
3482 HeapRegion* region = region_at(index);
3483 assert(region->is_starts_humongous(), "Must start a humongous object");
3484 return oop(region->bottom())->is_objArray() || !region->rem_set()->is_empty();
3485 }
3486
3487 class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure {
3488 private:
3489 size_t _total_humongous;
3490 size_t _candidate_humongous;
3491
3492 DirtyCardQueue _dcq;
3493
3494 bool humongous_region_is_candidate(uint index) {
3495 HeapRegion* region = G1CollectedHeap::heap()->region_at(index);
3496 assert(region->is_starts_humongous(), "Must start a humongous object");
3497 HeapRegionRemSet* const rset = region->rem_set();
3498 bool const allow_stale_refs = G1ReclaimDeadHumongousObjectsWithStaleRefsAtYoungGC;
3499 return !oop(region->bottom())->is_objArray() &&
3500 ((allow_stale_refs && rset->occupancy_less_or_equal_than(G1RSetSparseRegionEntries)) ||
3501 (!allow_stale_refs && rset->is_empty()));
3502 }
3503
3504 public:
3505 RegisterHumongousWithInCSetFastTestClosure()
3506 : _total_humongous(0),
3507 _candidate_humongous(0),
3508 _dcq(&JavaThread::dirty_card_queue_set()) {
3509 }
3510
3511 virtual bool doHeapRegion(HeapRegion* r) {
3512 if (!r->is_starts_humongous()) {
3513 return false;
3514 }
3515 G1CollectedHeap* g1h = G1CollectedHeap::heap();
3516
3517 uint region_idx = r->hrm_index();
3518 bool is_candidate = humongous_region_is_candidate(region_idx);
3519 // Is_candidate already filters out humongous object with large remembered sets.
3520 // If we have a humongous object with a few remembered sets, we simply flush these
3521 // remembered set entries into the DCQS. That will result in automatic
3522 // re-evaluation of their remembered set entries during the following evacuation
3523 // phase.
3524 if (is_candidate) {
3525 if (!r->rem_set()->is_empty()) {
3526 guarantee(r->rem_set()->occupancy_less_or_equal_than(G1RSetSparseRegionEntries),
3527 "Found a not-small remembered set here. This is inconsistent with previous assumptions.");
3528 G1SATBCardTableLoggingModRefBS* bs = g1h->g1_barrier_set();
3529 HeapRegionRemSetIterator hrrs(r->rem_set());
3530 size_t card_index;
3531 while (hrrs.has_next(card_index)) {
3532 jbyte* card_ptr = (jbyte*)bs->byte_for_index(card_index);
3533 if (*card_ptr != CardTableModRefBS::dirty_card_val()) {
3534 *card_ptr = CardTableModRefBS::dirty_card_val();
3535 _dcq.enqueue(card_ptr);
3536 }
3537 }
3538 r->rem_set()->clear_locked();
3539 }
3540 assert(r->rem_set()->is_empty(), "At this point any humongous candidate remembered set must be empty.");
3541 g1h->register_humongous_region_with_in_cset_fast_test(region_idx);
3542 _candidate_humongous++;
3543 }
3544 _total_humongous++;
3545
3546 return false;
3547 }
3548
3549 size_t total_humongous() const { return _total_humongous; }
3550 size_t candidate_humongous() const { return _candidate_humongous; }
3551
3552 void flush_rem_set_entries() { _dcq.flush(); }
3553 };
3554
3555 void G1CollectedHeap::register_humongous_regions_with_in_cset_fast_test() {
3556 if (!G1ReclaimDeadHumongousObjectsAtYoungGC) {
3557 g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(0.0, 0, 0);
3558 return;
3559 }
3560 double time = os::elapsed_counter();
3561
3562 RegisterHumongousWithInCSetFastTestClosure cl;
3563 heap_region_iterate(&cl);
3564
3565 time = ((double)(os::elapsed_counter() - time) / os::elapsed_frequency()) * 1000.0;
3566 g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(time,
3567 cl.total_humongous(),
3568 cl.candidate_humongous());
3569 _has_humongous_reclaim_candidates = cl.candidate_humongous() > 0;
3570
3571 if (_has_humongous_reclaim_candidates || G1TraceReclaimDeadHumongousObjectsAtYoungGC) {
3572 clear_humongous_is_live_table();
3573 }
3574
3575 // Finally flush all remembered set entries to re-check into the global DCQS.
3576 cl.flush_rem_set_entries();
3577 }
3578
3579 void
3580 G1CollectedHeap::setup_surviving_young_words() {
3581 assert(_surviving_young_words == NULL, "pre-condition");
3582 uint array_length = g1_policy()->young_cset_region_length();
3583 _surviving_young_words = NEW_C_HEAP_ARRAY(size_t, (size_t) array_length, mtGC);
3584 if (_surviving_young_words == NULL) {
3585 vm_exit_out_of_memory(sizeof(size_t) * array_length, OOM_MALLOC_ERROR,
3586 "Not enough space for young surv words summary.");
3587 }
3588 memset(_surviving_young_words, 0, (size_t) array_length * sizeof(size_t));
3589 #ifdef ASSERT
3590 for (uint i = 0; i < array_length; ++i) {
3591 assert( _surviving_young_words[i] == 0, "memset above" );
3592 }
3593 #endif // !ASSERT
3594 }
3595
3596 void
6159 // A humongous object cannot be live if there is no remembered set for it
6160 // because:
6161 // - there can be no references from within humongous starts regions referencing
6162 // the object because we never allocate other objects into them.
6163 // (I.e. there are no intra-region references that may be missed by the
6164 // remembered set)
6165 // - as soon there is a remembered set entry to the humongous starts region
6166 // (i.e. it has "escaped" to an old object) this remembered set entry will stay
6167 // until the end of a concurrent mark.
6168 //
6169 // It is not required to check whether the object has been found dead by marking
6170 // or not, in fact it would prevent reclamation within a concurrent cycle, as
6171 // all objects allocated during that time are considered live.
6172 // SATB marking is even more conservative than the remembered set.
6173 // So if at this point in the collection there is no remembered set entry,
6174 // nobody has a reference to it.
6175 // At the start of collection we flush all refinement logs, and remembered sets
6176 // are completely up-to-date wrt to references to the humongous object.
6177 //
6178 // Other implementation considerations:
6179 // - never consider object arrays at this time because they would pose
6180 // considerable effort for cleaning up the the remembered sets. This is
6181 // required because stale remembered sets might reference locations that
6182 // are currently allocated into.
6183 uint region_idx = r->hrm_index();
6184 if (g1h->humongous_is_live(region_idx) ||
6185 g1h->humongous_region_is_always_live(region_idx)) {
6186
6187 if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) {
6188 gclog_or_tty->print_cr("Live humongous region %u size "SIZE_FORMAT" start "PTR_FORMAT" length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d",
6189 region_idx,
6190 obj->size()*HeapWordSize,
6191 r->bottom(),
6192 r->region_num(),
6193 r->rem_set()->occupied(),
6194 r->rem_set()->strong_code_roots_list_length(),
6195 next_bitmap->isMarked(r->bottom()),
6196 g1h->humongous_is_live(region_idx),
6197 obj->is_objArray()
6198 );
6199 }
6200
6201 return false;
6202 }
6203
6204 guarantee(!obj->is_objArray(),
6205 err_msg("Eagerly reclaiming object arrays is not supported, but the object "PTR_FORMAT" is.",
6206 r->bottom()));
6207
6208 if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) {
6209 gclog_or_tty->print_cr("Dead humongous region %u size "SIZE_FORMAT" start "PTR_FORMAT" length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d",
6210 region_idx,
6211 obj->size()*HeapWordSize,
6212 r->bottom(),
6213 r->region_num(),
6214 r->rem_set()->occupied(),
6215 r->rem_set()->strong_code_roots_list_length(),
6216 next_bitmap->isMarked(r->bottom()),
6217 g1h->humongous_is_live(region_idx),
6218 obj->is_objArray()
6219 );
6220 }
6221 // Need to clear mark bit of the humongous object if already set.
6222 if (next_bitmap->isMarked(r->bottom())) {
6223 next_bitmap->clear(r->bottom());
6224 }
6225 _freed_bytes += r->used();
6226 r->set_containing_set(NULL);
6227 _humongous_regions_removed.increment(1u, r->capacity());
6228 g1h->free_humongous_region(r, _free_region_list, false);
6229
6230 return false;
6231 }
6232
|