< prev index next >

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

Print this page
rev 8813 : imported patch 8003237-no-wait-for-free-list
rev 8814 : imported patch jon-fast-evac-failure
rev 8815 : [mq]: bengt-jon-more-naming
rev 8816 : imported patch 8073013-add-detailed-information-about-plab-memory-usage
rev 8819 : imported patch 8040162-avoid-reallocating-plab-allocators


  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  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "gc/g1/g1CollectedHeap.inline.hpp"
  27 #include "gc/g1/g1OopClosures.inline.hpp"
  28 #include "gc/g1/g1ParScanThreadState.inline.hpp"
  29 #include "gc/g1/g1StringDedup.hpp"
  30 #include "gc/shared/taskqueue.inline.hpp"
  31 #include "oops/oop.inline.hpp"
  32 #include "runtime/prefetch.inline.hpp"
  33 
  34 G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id, ReferenceProcessor* rp)
  35   : _g1h(g1h),
  36     _refs(g1h->task_queue(worker_id)),
  37     _dcq(&g1h->dirty_card_queue_set()),
  38     _ct_bs(g1h->g1_barrier_set()),
  39     _g1_rem(g1h->g1_rem_set()),
  40     _hash_seed(17), _worker_id(worker_id),
  41     _term_attempts(0),
  42     _tenuring_threshold(g1h->g1_policy()->tenuring_threshold()),
  43     _age_table(false), _scanner(g1h, rp),
  44     _strong_roots_time(0), _term_time(0),
  45     _old_gen_is_full(false)
  46 {
  47   _scanner.set_par_scan_thread_state(this);
  48   // we allocate G1YoungSurvRateNumRegions plus one entries, since
  49   // we "sacrifice" entry 0 to keep track of surviving bytes for
  50   // non-young regions (where the age is -1)
  51   // We also add a few elements at the beginning and at the end in
  52   // an attempt to eliminate cache contention
  53   uint real_length = 1 + _g1h->g1_policy()->young_cset_region_length();
  54   uint array_length = PADDING_ELEM_NUM +
  55                       real_length +
  56                       PADDING_ELEM_NUM;
  57   _surviving_young_words_base = NEW_C_HEAP_ARRAY(size_t, array_length, mtGC);
  58   if (_surviving_young_words_base == NULL)
  59     vm_exit_out_of_memory(array_length * sizeof(size_t), OOM_MALLOC_ERROR,
  60                           "Not enough space for young surv histo.");
  61   _surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM;
  62   memset(_surviving_young_words, 0, (size_t) real_length * sizeof(size_t));
  63 
  64   _plab_allocator = G1PLABAllocator::create_allocator(_g1h->allocator());
  65 
  66   _dest[InCSetState::NotInCSet]    = InCSetState::NotInCSet;
  67   // The dest for Young is used when the objects are aged enough to
  68   // need to be moved to the next space.
  69   _dest[InCSetState::Young]        = InCSetState::Old;
  70   _dest[InCSetState::Old]          = InCSetState::Old;
  71 
  72   _start = os::elapsedTime();
  73 }
  74 
  75 G1ParScanThreadState::~G1ParScanThreadState() {
  76   _plab_allocator->flush_and_retire_stats();
  77   delete _plab_allocator;
  78   FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base);
  79 }
  80 
  81 void G1ParScanThreadState::print_termination_stats_hdr(outputStream* const st) {
  82   st->print_raw_cr("GC Termination Stats");
  83   st->print_raw_cr("     elapsed  --strong roots-- -------termination------- ------waste (KiB)------");
  84   st->print_raw_cr("thr     ms        ms      %        ms      %    attempts  total   alloc    undo");
  85   st->print_raw_cr("--- --------- --------- ------ --------- ------ -------- ------- ------- -------");
  86 }
  87 
  88 void G1ParScanThreadState::print_termination_stats(outputStream* const st) const {
  89   const double elapsed_ms = elapsed_time() * 1000.0;
  90   const double s_roots_ms = strong_roots_time() * 1000.0;
  91   const double term_ms    = term_time() * 1000.0;
  92   size_t alloc_buffer_waste = 0;
  93   size_t undo_waste = 0;
  94   _plab_allocator->waste(alloc_buffer_waste, undo_waste);
  95   st->print_cr("%3u %9.2f %9.2f %6.2f "
  96                "%9.2f %6.2f " SIZE_FORMAT_W(8) " "
  97                SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7),
  98                _worker_id, elapsed_ms, s_roots_ms, s_roots_ms * 100 / elapsed_ms,
  99                term_ms, term_ms * 100 / elapsed_ms, term_attempts(),
 100                (alloc_buffer_waste + undo_waste) * HeapWordSize / K,
 101                alloc_buffer_waste * HeapWordSize / K,
 102                undo_waste * HeapWordSize / K);
 103 }
 104 
 105 #ifdef ASSERT
 106 bool G1ParScanThreadState::verify_ref(narrowOop* ref) const {
 107   assert(ref != NULL, "invariant");
 108   assert(UseCompressedOops, "sanity");
 109   assert(!has_partial_array_mask(ref), err_msg("ref=" PTR_FORMAT, p2i(ref)));
 110   oop p = oopDesc::load_decode_heap_oop(ref);
 111   assert(_g1h->is_in_g1_reserved(p),
 112          err_msg("ref=" PTR_FORMAT " p=" PTR_FORMAT, p2i(ref), p2i(p)));
 113   return true;
 114 }
 115 
 116 bool G1ParScanThreadState::verify_ref(oop* ref) const {
 117   assert(ref != NULL, "invariant");
 118   if (has_partial_array_mask(ref)) {
 119     // Must be in the collection set--it's already been copied.
 120     oop p = clear_partial_array_mask(ref);
 121     assert(_g1h->obj_in_cs(p),
 122            err_msg("ref=" PTR_FORMAT " p=" PTR_FORMAT, p2i(ref), p2i(p)));


 274         obj->set_mark(old_mark->set_age(age));
 275       }
 276       age_table()->add(age, word_sz);
 277     } else {
 278       obj->set_mark(old_mark);
 279     }
 280 
 281     if (G1StringDedup::is_enabled()) {
 282       const bool is_from_young = state.is_young();
 283       const bool is_to_young = dest_state.is_young();
 284       assert(is_from_young == _g1h->heap_region_containing_raw(old)->is_young(),
 285              "sanity");
 286       assert(is_to_young == _g1h->heap_region_containing_raw(obj)->is_young(),
 287              "sanity");
 288       G1StringDedup::enqueue_from_evacuation(is_from_young,
 289                                              is_to_young,
 290                                              _worker_id,
 291                                              obj);
 292     }
 293 
 294     size_t* const surv_young_words = surviving_young_words();
 295     surv_young_words[young_index] += word_sz;
 296 
 297     if (obj->is_objArray() && arrayOop(obj)->length() >= ParGCArrayScanChunk) {
 298       // We keep track of the next start index in the length field of
 299       // the to-space object. The actual length can be found in the
 300       // length field of the from-space object.
 301       arrayOop(obj)->set_length(0);
 302       oop* old_p = set_partial_array_mask(old);
 303       push_on_queue(old_p);
 304     } else {
 305       HeapRegion* const to_region = _g1h->heap_region_containing_raw(obj_ptr);
 306       _scanner.set_region(to_region);
 307       obj->oop_iterate_backwards(&_scanner);
 308     }
 309     return obj;
 310   } else {
 311     _plab_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context);
 312     return forward_ptr;
 313   }
 314 }
 315 




  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  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "gc/g1/g1CollectedHeap.inline.hpp"
  27 #include "gc/g1/g1OopClosures.inline.hpp"
  28 #include "gc/g1/g1ParScanThreadState.inline.hpp"
  29 #include "gc/g1/g1StringDedup.hpp"
  30 #include "gc/shared/taskqueue.inline.hpp"
  31 #include "oops/oop.inline.hpp"
  32 #include "runtime/prefetch.inline.hpp"
  33 
  34 G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id)
  35   : _g1h(g1h),
  36     _refs(g1h->task_queue(worker_id)),
  37     _dcq(&g1h->dirty_card_queue_set()),
  38     _ct_bs(g1h->g1_barrier_set()),
  39     _g1_rem(g1h->g1_rem_set()),
  40     _hash_seed(17),
  41     _worker_id(worker_id),
  42     _tenuring_threshold(g1h->g1_policy()->tenuring_threshold()),
  43     _age_table(false),
  44     _scanner(g1h),
  45     _old_gen_is_full(false)
  46 {
  47   _scanner.set_par_scan_thread_state(this);
  48   // we allocate G1YoungSurvRateNumRegions plus one entries, since
  49   // we "sacrifice" entry 0 to keep track of surviving bytes for
  50   // non-young regions (where the age is -1)
  51   // We also add a few elements at the beginning and at the end in
  52   // an attempt to eliminate cache contention
  53   uint real_length = 1 + _g1h->g1_policy()->young_cset_region_length();
  54   uint array_length = PADDING_ELEM_NUM +
  55                       real_length +
  56                       PADDING_ELEM_NUM;
  57   _surviving_young_words_base = NEW_C_HEAP_ARRAY(size_t, array_length, mtGC);
  58   if (_surviving_young_words_base == NULL)
  59     vm_exit_out_of_memory(array_length * sizeof(size_t), OOM_MALLOC_ERROR,
  60                           "Not enough space for young surv histo.");
  61   _surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM;
  62   memset(_surviving_young_words, 0, (size_t) real_length * sizeof(size_t));
  63 
  64   _plab_allocator = G1PLABAllocator::create_allocator(_g1h->allocator());
  65 
  66   _dest[InCSetState::NotInCSet]    = InCSetState::NotInCSet;
  67   // The dest for Young is used when the objects are aged enough to
  68   // need to be moved to the next space.
  69   _dest[InCSetState::Young]        = InCSetState::Old;
  70   _dest[InCSetState::Old]          = InCSetState::Old;


  71 }
  72 
  73 G1ParScanThreadState::~G1ParScanThreadState() {
  74   _plab_allocator->flush_and_retire_stats();
  75   delete _plab_allocator;
  76   FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base);
  77 }
  78 
  79 void G1ParScanThreadState::waste(size_t& wasted, size_t& undo_wasted) {
  80   _plab_allocator->waste(wasted, undo_wasted);




















  81 }
  82 
  83 #ifdef ASSERT
  84 bool G1ParScanThreadState::verify_ref(narrowOop* ref) const {
  85   assert(ref != NULL, "invariant");
  86   assert(UseCompressedOops, "sanity");
  87   assert(!has_partial_array_mask(ref), err_msg("ref=" PTR_FORMAT, p2i(ref)));
  88   oop p = oopDesc::load_decode_heap_oop(ref);
  89   assert(_g1h->is_in_g1_reserved(p),
  90          err_msg("ref=" PTR_FORMAT " p=" PTR_FORMAT, p2i(ref), p2i(p)));
  91   return true;
  92 }
  93 
  94 bool G1ParScanThreadState::verify_ref(oop* ref) const {
  95   assert(ref != NULL, "invariant");
  96   if (has_partial_array_mask(ref)) {
  97     // Must be in the collection set--it's already been copied.
  98     oop p = clear_partial_array_mask(ref);
  99     assert(_g1h->obj_in_cs(p),
 100            err_msg("ref=" PTR_FORMAT " p=" PTR_FORMAT, p2i(ref), p2i(p)));


 252         obj->set_mark(old_mark->set_age(age));
 253       }
 254       age_table()->add(age, word_sz);
 255     } else {
 256       obj->set_mark(old_mark);
 257     }
 258 
 259     if (G1StringDedup::is_enabled()) {
 260       const bool is_from_young = state.is_young();
 261       const bool is_to_young = dest_state.is_young();
 262       assert(is_from_young == _g1h->heap_region_containing_raw(old)->is_young(),
 263              "sanity");
 264       assert(is_to_young == _g1h->heap_region_containing_raw(obj)->is_young(),
 265              "sanity");
 266       G1StringDedup::enqueue_from_evacuation(is_from_young,
 267                                              is_to_young,
 268                                              _worker_id,
 269                                              obj);
 270     }
 271 
 272     _surviving_young_words[young_index] += word_sz;

 273 
 274     if (obj->is_objArray() && arrayOop(obj)->length() >= ParGCArrayScanChunk) {
 275       // We keep track of the next start index in the length field of
 276       // the to-space object. The actual length can be found in the
 277       // length field of the from-space object.
 278       arrayOop(obj)->set_length(0);
 279       oop* old_p = set_partial_array_mask(old);
 280       push_on_queue(old_p);
 281     } else {
 282       HeapRegion* const to_region = _g1h->heap_region_containing_raw(obj_ptr);
 283       _scanner.set_region(to_region);
 284       obj->oop_iterate_backwards(&_scanner);
 285     }
 286     return obj;
 287   } else {
 288     _plab_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context);
 289     return forward_ptr;
 290   }
 291 }
 292 


< prev index next >