< prev index next >

src/share/vm/gc/g1/g1RemSet.cpp

Print this page
rev 12513 : 8071278: Fix the closure mess in G1RemSet::refine_card()
Summary: Remove the use of many nested closure in the code to refine a card.
Reviewed-by: kbarrett, sjohanss
   1 /*
   2  * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
   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  *
  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  *


 510   G1CollectedHeap* _g1h;
 511   G1CardLiveData* _live_data;
 512 public:
 513   G1ScrubRSClosure(G1CardLiveData* live_data) :
 514     _g1h(G1CollectedHeap::heap()),
 515     _live_data(live_data) { }
 516 
 517   bool doHeapRegion(HeapRegion* r) {
 518     if (!r->is_continues_humongous()) {
 519       r->rem_set()->scrub(_live_data);
 520     }
 521     return false;
 522   }
 523 };
 524 
 525 void G1RemSet::scrub(uint worker_num, HeapRegionClaimer *hrclaimer) {
 526   G1ScrubRSClosure scrub_cl(&_card_live_data);
 527   _g1->heap_region_par_iterate(&scrub_cl, worker_num, hrclaimer);
 528 }
 529 
 530 G1TriggerClosure::G1TriggerClosure() :
 531   _triggered(false) { }
 532 
 533 G1InvokeIfNotTriggeredClosure::G1InvokeIfNotTriggeredClosure(G1TriggerClosure* t_cl,
 534                                                              OopClosure* oop_cl)  :
 535   _trigger_cl(t_cl), _oop_cl(oop_cl) { }
 536 
 537 G1Mux2Closure::G1Mux2Closure(OopClosure *c1, OopClosure *c2) :
 538   _c1(c1), _c2(c2) { }
 539 
 540 G1UpdateRSOrPushRefOopClosure::
 541 G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h,
 542                               G1RemSet* rs,
 543                               G1ParPushHeapRSClosure* push_ref_cl,
 544                               bool record_refs_into_cset,
 545                               uint worker_i) :
 546   _g1(g1h), _g1_rem_set(rs), _from(NULL),

 547   _record_refs_into_cset(record_refs_into_cset),
 548   _push_ref_cl(push_ref_cl), _worker_i(worker_i) { }


 549 
 550 // Returns true if the given card contains references that point
 551 // into the collection set, if we're checking for such references;
 552 // false otherwise.
 553 
 554 bool G1RemSet::refine_card(jbyte* card_ptr,
 555                            uint worker_i,
 556                            G1ParPushHeapRSClosure*  oops_in_heap_closure) {
 557   assert(_g1->is_in_exact(_ct_bs->addr_for(card_ptr)),
 558          "Card at " PTR_FORMAT " index " SIZE_FORMAT " representing heap at " PTR_FORMAT " (%u) must be in committed heap",
 559          p2i(card_ptr),
 560          _ct_bs->index_for(_ct_bs->addr_for(card_ptr)),
 561          p2i(_ct_bs->addr_for(card_ptr)),
 562          _g1->addr_to_region(_ct_bs->addr_for(card_ptr)));
 563 
 564   bool check_for_refs_into_cset = oops_in_heap_closure != NULL;
 565 
 566   // If the card is no longer dirty, nothing to do.
 567   if (*card_ptr != CardTableModRefBS::dirty_card_val()) {
 568     // No need to return that this card contains refs that point


 673   // Okay to clean and process the card now.  There are still some
 674   // stale card cases that may be detected by iteration and dealt with
 675   // as iteration failure.
 676   *const_cast<volatile jbyte*>(card_ptr) = CardTableModRefBS::clean_card_val();
 677 
 678   // This fence serves two purposes.  First, the card must be cleaned
 679   // before processing the contents.  Second, we can't proceed with
 680   // processing until after the read of top, for synchronization with
 681   // possibly concurrent humongous object allocation.  It's okay that
 682   // reading top and reading type were racy wrto each other.  We need
 683   // both set, in any order, to proceed.
 684   OrderAccess::fence();
 685 
 686   // Don't use addr_for(card_ptr + 1) which can ask for
 687   // a card beyond the heap.
 688   HeapWord* end = start + CardTableModRefBS::card_size_in_words;
 689   MemRegion dirty_region(start, MIN2(scan_limit, end));
 690   assert(!dirty_region.is_empty(), "sanity");
 691 
 692   G1UpdateRSOrPushRefOopClosure update_rs_oop_cl(_g1,
 693                                                  _g1->g1_rem_set(),
 694                                                  oops_in_heap_closure,
 695                                                  check_for_refs_into_cset,
 696                                                  worker_i);
 697   update_rs_oop_cl.set_from(r);
 698 
 699   G1TriggerClosure trigger_cl;
 700   FilterIntoCSClosure into_cs_cl(_g1, &trigger_cl);
 701   G1InvokeIfNotTriggeredClosure invoke_cl(&trigger_cl, &into_cs_cl);
 702   G1Mux2Closure mux(&invoke_cl, &update_rs_oop_cl);
 703 
 704   FilterOutOfRegionClosure filter_then_update_rs_oop_cl(r,
 705                         (check_for_refs_into_cset ?
 706                                 (OopClosure*)&mux :
 707                                 (OopClosure*)&update_rs_oop_cl));
 708 
 709   bool card_processed =
 710     r->oops_on_card_seq_iterate_careful(dirty_region,
 711                                         &filter_then_update_rs_oop_cl);
 712 
 713   // If unable to process the card then we encountered an unparsable
 714   // part of the heap (e.g. a partially allocated object) while
 715   // processing a stale card.  Despite the card being stale, redirty
 716   // and re-enqueue, because we've already cleaned the card.  Without
 717   // this we could incorrectly discard a non-stale card.
 718   if (!card_processed) {
 719     assert(!_g1->is_gc_active(), "Unparsable heap during GC");
 720     // The card might have gotten re-dirtied and re-enqueued while we
 721     // worked.  (In fact, it's pretty likely.)
 722     if (*card_ptr != CardTableModRefBS::dirty_card_val()) {
 723       *card_ptr = CardTableModRefBS::dirty_card_val();
 724       MutexLockerEx x(Shared_DirtyCardQ_lock,
 725                       Mutex::_no_safepoint_check_flag);
 726       DirtyCardQueue* sdcq =
 727         JavaThread::dirty_card_queue_set().shared_dirty_card_queue();
 728       sdcq->enqueue(card_ptr);
 729     }
 730   } else {
 731     _conc_refine_cards++;
 732   }
 733 
 734   // This gets set to true if the card being refined has
 735   // references that point into the collection set.
 736   bool has_refs_into_cset = trigger_cl.triggered();
 737 
 738   // We should only be detecting that the card contains references
 739   // that point into the collection set if the current thread is
 740   // a GC worker thread.
 741   assert(!has_refs_into_cset || SafepointSynchronize::is_at_safepoint(),
 742            "invalid result at non safepoint");
 743 
 744   return has_refs_into_cset;
 745 }
 746 
 747 void G1RemSet::print_periodic_summary_info(const char* header, uint period_count) {
 748   if ((G1SummarizeRSetStatsPeriod > 0) && log_is_enabled(Trace, gc, remset) &&
 749       (period_count % G1SummarizeRSetStatsPeriod == 0)) {
 750 
 751     if (!_prev_period_summary.initialized()) {
 752       _prev_period_summary.initialize(this);
 753     }
 754 
 755     G1RemSetSummary current;
 756     current.initialize(this);


   1 /*
   2  * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
   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  *
  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  *


 510   G1CollectedHeap* _g1h;
 511   G1CardLiveData* _live_data;
 512 public:
 513   G1ScrubRSClosure(G1CardLiveData* live_data) :
 514     _g1h(G1CollectedHeap::heap()),
 515     _live_data(live_data) { }
 516 
 517   bool doHeapRegion(HeapRegion* r) {
 518     if (!r->is_continues_humongous()) {
 519       r->rem_set()->scrub(_live_data);
 520     }
 521     return false;
 522   }
 523 };
 524 
 525 void G1RemSet::scrub(uint worker_num, HeapRegionClaimer *hrclaimer) {
 526   G1ScrubRSClosure scrub_cl(&_card_live_data);
 527   _g1->heap_region_par_iterate(&scrub_cl, worker_num, hrclaimer);
 528 }
 529 
 530 G1UpdateRSOrPushRefOopClosure::G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h,












 531                                                              G1ParPushHeapRSClosure* push_ref_cl,
 532                                                              bool record_refs_into_cset,
 533                                                              uint worker_i) :
 534   _g1(g1h),
 535   _from(NULL),
 536   _record_refs_into_cset(record_refs_into_cset),
 537   _has_refs_into_cset(false),
 538   _push_ref_cl(push_ref_cl),
 539   _worker_i(worker_i) { }
 540 
 541 // Returns true if the given card contains references that point
 542 // into the collection set, if we're checking for such references;
 543 // false otherwise.
 544 
 545 bool G1RemSet::refine_card(jbyte* card_ptr,
 546                            uint worker_i,
 547                            G1ParPushHeapRSClosure*  oops_in_heap_closure) {
 548   assert(_g1->is_in_exact(_ct_bs->addr_for(card_ptr)),
 549          "Card at " PTR_FORMAT " index " SIZE_FORMAT " representing heap at " PTR_FORMAT " (%u) must be in committed heap",
 550          p2i(card_ptr),
 551          _ct_bs->index_for(_ct_bs->addr_for(card_ptr)),
 552          p2i(_ct_bs->addr_for(card_ptr)),
 553          _g1->addr_to_region(_ct_bs->addr_for(card_ptr)));
 554 
 555   bool check_for_refs_into_cset = oops_in_heap_closure != NULL;
 556 
 557   // If the card is no longer dirty, nothing to do.
 558   if (*card_ptr != CardTableModRefBS::dirty_card_val()) {
 559     // No need to return that this card contains refs that point


 664   // Okay to clean and process the card now.  There are still some
 665   // stale card cases that may be detected by iteration and dealt with
 666   // as iteration failure.
 667   *const_cast<volatile jbyte*>(card_ptr) = CardTableModRefBS::clean_card_val();
 668 
 669   // This fence serves two purposes.  First, the card must be cleaned
 670   // before processing the contents.  Second, we can't proceed with
 671   // processing until after the read of top, for synchronization with
 672   // possibly concurrent humongous object allocation.  It's okay that
 673   // reading top and reading type were racy wrto each other.  We need
 674   // both set, in any order, to proceed.
 675   OrderAccess::fence();
 676 
 677   // Don't use addr_for(card_ptr + 1) which can ask for
 678   // a card beyond the heap.
 679   HeapWord* end = start + CardTableModRefBS::card_size_in_words;
 680   MemRegion dirty_region(start, MIN2(scan_limit, end));
 681   assert(!dirty_region.is_empty(), "sanity");
 682 
 683   G1UpdateRSOrPushRefOopClosure update_rs_oop_cl(_g1,

 684                                                  oops_in_heap_closure,
 685                                                  check_for_refs_into_cset,
 686                                                  worker_i);
 687   update_rs_oop_cl.set_from(r);
 688 










 689   bool card_processed =
 690     r->oops_on_card_seq_iterate_careful(dirty_region,
 691                                         &update_rs_oop_cl);
 692 
 693   // If unable to process the card then we encountered an unparsable
 694   // part of the heap (e.g. a partially allocated object) while
 695   // processing a stale card.  Despite the card being stale, redirty
 696   // and re-enqueue, because we've already cleaned the card.  Without
 697   // this we could incorrectly discard a non-stale card.
 698   if (!card_processed) {
 699     assert(!_g1->is_gc_active(), "Unparsable heap during GC");
 700     // The card might have gotten re-dirtied and re-enqueued while we
 701     // worked.  (In fact, it's pretty likely.)
 702     if (*card_ptr != CardTableModRefBS::dirty_card_val()) {
 703       *card_ptr = CardTableModRefBS::dirty_card_val();
 704       MutexLockerEx x(Shared_DirtyCardQ_lock,
 705                       Mutex::_no_safepoint_check_flag);
 706       DirtyCardQueue* sdcq =
 707         JavaThread::dirty_card_queue_set().shared_dirty_card_queue();
 708       sdcq->enqueue(card_ptr);
 709     }
 710   } else {
 711     _conc_refine_cards++;
 712   }
 713 
 714   // This gets set to true if the card being refined has references that point
 715   // into the collection set.
 716   bool has_refs_into_cset = update_rs_oop_cl.has_refs_into_cset();
 717 
 718   // We should only be detecting that the card contains references
 719   // that point into the collection set if the current thread is
 720   // a GC worker thread.
 721   assert(!has_refs_into_cset || SafepointSynchronize::is_at_safepoint(),
 722          "invalid result at non safepoint");
 723 
 724   return has_refs_into_cset;
 725 }
 726 
 727 void G1RemSet::print_periodic_summary_info(const char* header, uint period_count) {
 728   if ((G1SummarizeRSetStatsPeriod > 0) && log_is_enabled(Trace, gc, remset) &&
 729       (period_count % G1SummarizeRSetStatsPeriod == 0)) {
 730 
 731     if (!_prev_period_summary.initialized()) {
 732       _prev_period_summary.initialize(this);
 733     }
 734 
 735     G1RemSetSummary current;
 736     current.initialize(this);


< prev index next >