< prev index next >

src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp

Print this page
rev 7520 : 8048179: Early reclaim of large objects that are referenced by a few objects
Summary:
Reviewed-by:
rev 7521 : [mq]: bengt-review


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 


< prev index next >