< prev index next >

src/hotspot/share/gc/g1/g1ConcurrentMark.cpp

Print this page
rev 49511 : imported patch 8200234-g1concurrentmark-refactorings
rev 49512 : imported patch 8200234-stefanj-review
rev 49515 : 8200255: Remove G1CMTask::_concurrent
Reviewed-by: sangheki, sjohanss
rev 49516 : 8200074: Remove G1ConcurrentMark::_concurrent_marking_in_progress
Reviewed-by: sjohanss, sangheki
rev 49517 : imported patch 8200305-gc,liveness-output
rev 49518 : imported patch 8200385-prev-bitmap-marks-left
rev 49519 : imported patch 8200385-stefanj-review
rev 49520 : imported patch 8178105-switch-at-remark
rev 49521 : [mq]: 8178105-stefanj-review

@@ -1006,10 +1006,12 @@
 
 class G1UpdateRemSetTrackingBeforeRebuild : public HeapRegionClosure {
   G1CollectedHeap* _g1h;
   G1ConcurrentMark* _cm;
 
+  G1PrintRegionLivenessInfoClosure _cl;
+
   uint _num_regions_selected_for_rebuild;  // The number of regions actually selected for rebuild.
 
   void update_remset_before_rebuild(HeapRegion * hr) {
     G1RemSetTrackingPolicy* tracking_policy = _g1h->g1_policy()->remset_tracker();
 

@@ -1019,16 +1021,64 @@
       _num_regions_selected_for_rebuild++;
     }
     _cm->update_top_at_rebuild_start(hr);
   }
 
+  void distribute_marked_bytes(HeapRegion* hr, size_t marked_words) {
+    uint const region_idx = hr->hrm_index();
+    assert(hr->is_starts_humongous(),
+           "Should not have marked bytes " SIZE_FORMAT " in non-starts humongous region %u (%s)",
+           marked_words, region_idx, hr->get_type_str());
+    uint num_regions_in_humongous = (uint)G1CollectedHeap::humongous_obj_size_in_regions(marked_words);
+
+    for (uint i = region_idx; i < (region_idx + num_regions_in_humongous); i++) {
+      HeapRegion* const r = _g1h->region_at(i);
+      size_t const words_to_add = MIN2(HeapRegion::GrainWords, marked_words);
+      assert(words_to_add > 0, "Out of space to distribute before end of humongous object in region %u (starts %u)", i, region_idx);
+
+      r->add_to_marked_bytes(words_to_add * HeapWordSize);
+      marked_words -= words_to_add;
+    }
+    assert(marked_words == 0,
+           SIZE_FORMAT " words left after distributing space across %u regions",
+           marked_words, num_regions_in_humongous);
+  }
+
+  void update_marked_bytes(HeapRegion* hr) {
+    uint const region_idx = hr->hrm_index();
+    size_t marked_words = _cm->liveness(region_idx);
+    // The marking attributes the object's size completely to the humongous starts
+    // region. We need to distribute this value across the entire set of regions a
+    // humongous object spans.
+    if (hr->is_humongous()) {
+      if (marked_words > 0) {
+        log_trace(gc, marking)("Adding " SIZE_FORMAT " words to humongous start region %u (%s), word size %d (%f)", 
+                               marked_words, region_idx, hr->get_type_str(),
+                               oop(hr->bottom())->size(), (double)oop(hr->bottom())->size() / HeapRegion::GrainWords);
+        distribute_marked_bytes(hr, marked_words);
+      } else {
+        assert(marked_words == 0,
+               "Asked to add " SIZE_FORMAT " words to add to continues humongous region %u (%s)",
+               marked_words, region_idx, hr->get_type_str());
+      }
+    } else {
+      log_trace(gc, marking)("Adding " SIZE_FORMAT " words to region %u (%s)", marked_words, region_idx, hr->get_type_str());
+      hr->add_to_marked_bytes(marked_words * HeapWordSize);
+    }
+  }
+
 public:
   G1UpdateRemSetTrackingBeforeRebuild(G1CollectedHeap* g1h, G1ConcurrentMark* cm) :
-    _g1h(g1h), _cm(cm), _num_regions_selected_for_rebuild(0) { }
+    _g1h(g1h), _cm(cm), _cl("Post-Marking"), _num_regions_selected_for_rebuild(0) { }
 
   virtual bool do_heap_region(HeapRegion* r) {
     update_remset_before_rebuild(r);
+    update_marked_bytes(r);
+    if (log_is_enabled(Trace, gc, liveness)) {
+      _cl.do_heap_region(r);
+    }
+    r->note_end_of_marking();
     return false;
   }
 
   uint num_selected_for_rebuild() const { return _num_regions_selected_for_rebuild; }
 };

@@ -1081,19 +1131,21 @@
     {
       GCTraceTime(Debug, gc, phases)("Flush Task Caches");
       flush_all_task_caches();
     }
 
+    // Install newly created mark bitmap as "prev".
+    swap_mark_bitmaps();
     {
       GCTraceTime(Debug, gc, phases)("Update Remembered Set Tracking Before Rebuild");
       G1UpdateRemSetTrackingBeforeRebuild cl(_g1h, this);
       _g1h->heap_region_iterate(&cl);
       log_debug(gc, remset, tracking)("Remembered Set Tracking update regions total %u, selected %u",
                                       _g1h->num_regions(), cl.num_selected_for_rebuild());
     }
 
-    verify_during_pause(G1HeapVerifier::G1VerifyRemark, VerifyOption_G1UseNextMarking, "Remark after");
+    verify_during_pause(G1HeapVerifier::G1VerifyRemark, VerifyOption_G1UsePrevMarking, "Remark after");
 
     assert(!restart_for_overflow(), "sanity");
     // Completely reset the marking state since marking completed
     reset_at_marking_complete();
   } else {

@@ -1107,11 +1159,11 @@
     reset_marking_for_restart();
   }
 
   {
     GCTraceTime(Debug, gc, phases)("Report Object Count");
-    report_object_count();
+    report_object_count(mark_finished);
   }
 
   // Statistics
   double now = os::elapsedTime();
   _remark_mark_times.add((mark_work_end - start) * 1000.0);

@@ -1145,12 +1197,10 @@
     size_t freed_bytes() { return _freed_bytes; }
     const uint old_regions_removed() { return _old_regions_removed; }
     const uint humongous_regions_removed() { return _humongous_regions_removed; }
 
     bool do_heap_region(HeapRegion *hr) {
-      hr->note_end_of_marking();
-
       if (hr->used() > 0 && hr->max_live_bytes() == 0 && !hr->is_young() && !hr->is_archive()) {
         _freed_bytes += hr->used();
         hr->set_containing_set(NULL);
         if (hr->is_humongous()) {
           _humongous_regions_removed++;

@@ -1241,11 +1291,11 @@
   G1Policy* g1p = _g1h->g1_policy();
   g1p->record_concurrent_mark_cleanup_start();
 
   double start = os::elapsedTime();
 
-  verify_during_pause(G1HeapVerifier::G1VerifyCleanup, VerifyOption_G1UseNextMarking, "Cleanup before");
+  verify_during_pause(G1HeapVerifier::G1VerifyCleanup, VerifyOption_G1UsePrevMarking, "Cleanup before");
 
   {
     GCTraceTime(Debug, gc, phases)("Update Remembered Set Tracking After Rebuild");
     G1UpdateRemSetTrackingAfterRebuild cl(_g1h);
     _g1h->heap_region_iterate(&cl);

@@ -1254,12 +1304,10 @@
   if (log_is_enabled(Trace, gc, liveness)) {
     G1PrintRegionLivenessInfoClosure cl("Post-Cleanup");
     _g1h->heap_region_iterate(&cl);
   }
 
-  // Install newly created mark bitmap as "prev".
-  swap_mark_bitmaps();
   {
     GCTraceTime(Debug, gc, phases)("Reclaim Empty Regions");
     reclaim_empty_regions();
   }
 

@@ -1623,15 +1671,37 @@
     // class unloading is disabled.
     _g1h->partial_cleaning(&g1_is_alive, false, false, G1StringDedup::is_enabled());
   }
 }
 
-void G1ConcurrentMark::report_object_count() {
+// When sampling object counts, we already swapped the mark bitmaps, so we need to use
+// the prev bitmap determining liveness.
+class G1ObjectCountIsAliveClosure: public BoolObjectClosure {
+  G1CollectedHeap* _g1;
+ public:
+  G1ObjectCountIsAliveClosure(G1CollectedHeap* g1) : _g1(g1) { }
+
+  bool do_object_b(oop obj) {
+    HeapWord* addr = (HeapWord*)obj;
+    return addr != NULL &&
+           (!_g1->is_in_g1_reserved(addr) || !_g1->is_obj_dead(obj));
+  }
+};
+
+void G1ConcurrentMark::report_object_count(bool mark_completed) {
+  // Depending on the completion of the marking liveness needs to be determined
+  // using either the next or prev bitmap.
+  if (mark_completed) {
+    G1ObjectCountIsAliveClosure is_alive(_g1h);
+    _gc_tracer_cm->report_object_count_after_gc(&is_alive);
+  } else {
   G1CMIsAliveClosure is_alive(_g1h);
   _gc_tracer_cm->report_object_count_after_gc(&is_alive);
+  }
 }
 
+
 void G1ConcurrentMark::swap_mark_bitmaps() {
   G1CMBitMap* temp = _prev_mark_bitmap;
   _prev_mark_bitmap = _next_mark_bitmap;
   _next_mark_bitmap = temp;
   _g1h->collector_state()->set_clearing_next_bitmap(true);
< prev index next >