src/hotspot/share/gc/g1/g1ConcurrentMark.cpp
changeset 49809 ef5220d644e3
parent 49807 fe4156ef739b
child 49811 bfba4712d4ff
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp	Wed Apr 18 11:36:48 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp	Wed Apr 18 11:36:48 2018 +0200
@@ -1387,35 +1387,40 @@
   virtual void do_oop(      oop* p) { do_oop_work(p); }
 
   template <class T> void do_oop_work(T* p) {
-    if (!_cm->has_overflown()) {
-      _task->deal_with_reference(p);
-      _ref_counter--;
-
-      if (_ref_counter == 0) {
-        // We have dealt with _ref_counter_limit references, pushing them
-        // and objects reachable from them on to the local stack (and
-        // possibly the global stack). Call G1CMTask::do_marking_step() to
-        // process these entries.
-        //
-        // We call G1CMTask::do_marking_step() in a loop, which we'll exit if
-        // there's nothing more to do (i.e. we're done with the entries that
-        // were pushed as a result of the G1CMTask::deal_with_reference() calls
-        // above) or we overflow.
-        //
-        // Note: G1CMTask::do_marking_step() can set the G1CMTask::has_aborted()
-        // flag while there may still be some work to do. (See the comment at
-        // the beginning of G1CMTask::do_marking_step() for those conditions -
-        // one of which is reaching the specified time target.) It is only
-        // when G1CMTask::do_marking_step() returns without setting the
-        // has_aborted() flag that the marking step has completed.
-        do {
-          double mark_step_duration_ms = G1ConcMarkStepDurationMillis;
-          _task->do_marking_step(mark_step_duration_ms,
-                                 false      /* do_termination */,
-                                 _is_serial);
-        } while (_task->has_aborted() && !_cm->has_overflown());
-        _ref_counter = _ref_counter_limit;
-      }
+    if (_cm->has_overflown()) {
+      return;
+    }
+    if (!_task->deal_with_reference(p)) {
+      // We did not add anything to the mark bitmap (or mark stack), so there is
+      // no point trying to drain it.
+      return;
+    }
+    _ref_counter--;
+
+    if (_ref_counter == 0) {
+      // We have dealt with _ref_counter_limit references, pushing them
+      // and objects reachable from them on to the local stack (and
+      // possibly the global stack). Call G1CMTask::do_marking_step() to
+      // process these entries.
+      //
+      // We call G1CMTask::do_marking_step() in a loop, which we'll exit if
+      // there's nothing more to do (i.e. we're done with the entries that
+      // were pushed as a result of the G1CMTask::deal_with_reference() calls
+      // above) or we overflow.
+      //
+      // Note: G1CMTask::do_marking_step() can set the G1CMTask::has_aborted()
+      // flag while there may still be some work to do. (See the comment at
+      // the beginning of G1CMTask::do_marking_step() for those conditions -
+      // one of which is reaching the specified time target.) It is only
+      // when G1CMTask::do_marking_step() returns without setting the
+      // has_aborted() flag that the marking step has completed.
+      do {
+        double mark_step_duration_ms = G1ConcMarkStepDurationMillis;
+        _task->do_marking_step(mark_step_duration_ms,
+                               false      /* do_termination */,
+                               _is_serial);
+      } while (_task->has_aborted() && !_cm->has_overflown());
+      _ref_counter = _ref_counter_limit;
     }
   }
 };