8140597: Forcing an initial mark causes G1 to abort mixed collections
authortschatzl
Tue, 10 Nov 2015 11:07:15 +0100
changeset 33808 ee899178e46b
parent 33807 9f8b0f8a3f29
child 33809 62f8fb907ad5
8140597: Forcing an initial mark causes G1 to abort mixed collections Summary: Postpone the initial mark request until the current mixed GC phase has finished. Reviewed-by: mgerdin
hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp
hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp
hotspot/src/share/vm/prims/whitebox.cpp
--- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp	Tue Oct 27 12:25:08 2015 +0100
+++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp	Tue Nov 10 11:07:15 2015 +0100
@@ -930,8 +930,12 @@
   return other_time_ms(pause_time_ms) - young_other_time_ms() - non_young_other_time_ms();
 }
 
+bool G1CollectorPolicy::about_to_start_mixed_phase() const {
+  return _g1->concurrent_mark()->cmThread()->during_cycle() || collector_state()->last_young_gc();
+}
+
 bool G1CollectorPolicy::need_to_start_conc_mark(const char* source, size_t alloc_word_size) {
-  if (_g1->concurrent_mark()->cmThread()->during_cycle()) {
+  if (about_to_start_mixed_phase()) {
     return false;
   }
 
@@ -1058,17 +1062,13 @@
   if (collector_state()->last_young_gc()) {
     // This is supposed to to be the "last young GC" before we start
     // doing mixed GCs. Here we decide whether to start mixed GCs or not.
+    assert(!last_pause_included_initial_mark, "The last young GC is not allowed to be an initial mark GC");
 
-    if (!last_pause_included_initial_mark) {
-      if (next_gc_should_be_mixed("start mixed GCs",
-                                  "do not start mixed GCs")) {
-        collector_state()->set_gcs_are_young(false);
-      }
-    } else {
-      ergo_verbose0(ErgoMixedGCs,
-                    "do not start mixed GCs",
-                    ergo_format_reason("concurrent cycle is about to start"));
+    if (next_gc_should_be_mixed("start mixed GCs",
+                                "do not start mixed GCs")) {
+      collector_state()->set_gcs_are_young(false);
     }
+
     collector_state()->set_last_young_gc(false);
   }
 
@@ -1586,8 +1586,10 @@
         HeapRegion::GrainWords * _max_survivor_regions, counters());
 }
 
-bool G1CollectorPolicy::force_initial_mark_if_outside_cycle(
-                                                     GCCause::Cause gc_cause) {
+bool G1CollectorPolicy::force_initial_mark_if_outside_cycle(GCCause::Cause gc_cause) {
+  // We actually check whether we are marking here and not if we are in a
+  // reclamation phase. This means that we will schedule a concurrent mark
+  // even while we are still in the process of reclaiming memory.
   bool during_cycle = _g1->concurrent_mark()->cmThread()->during_cycle();
   if (!during_cycle) {
     ergo_verbose1(ErgoConcCycles,
@@ -1607,8 +1609,7 @@
   }
 }
 
-void
-G1CollectorPolicy::decide_on_conc_mark_initiation() {
+void G1CollectorPolicy::decide_on_conc_mark_initiation() {
   // We are about to decide on whether this pause will be an
   // initial-mark pause.
 
@@ -1623,21 +1624,11 @@
     // gone over the initiating threshold and we should start a
     // concurrent marking cycle. So we might initiate one.
 
-    bool during_cycle = _g1->concurrent_mark()->cmThread()->during_cycle();
-    if (!during_cycle) {
-      // The concurrent marking thread is not "during a cycle", i.e.,
-      // it has completed the last one. So we can go ahead and
-      // initiate a new cycle.
+    if (!about_to_start_mixed_phase() && collector_state()->gcs_are_young()) {
+      // Initiate a new initial mark only if there is no marking or reclamation going
+      // on.
 
       collector_state()->set_during_initial_mark_pause(true);
-      // We do not allow mixed GCs during marking.
-      if (!collector_state()->gcs_are_young()) {
-        collector_state()->set_gcs_are_young(true);
-        ergo_verbose0(ErgoMixedGCs,
-                      "end mixed GCs",
-                      ergo_format_reason("concurrent cycle is about to start"));
-      }
-
       // And we can now clear initiate_conc_mark_if_possible() as
       // we've already acted on it.
       collector_state()->set_initiate_conc_mark_if_possible(false);
--- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp	Tue Oct 27 12:25:08 2015 +0100
+++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp	Tue Nov 10 11:07:15 2015 +0100
@@ -570,6 +570,8 @@
 
   bool need_to_start_conc_mark(const char* source, size_t alloc_word_size = 0);
 
+  bool about_to_start_mixed_phase() const;
+
   // Record the start and end of an evacuation pause.
   void record_collection_pause_start(double start_time_sec);
   void record_collection_pause_end(double pause_time_ms, size_t cards_scanned);
--- a/hotspot/src/share/vm/prims/whitebox.cpp	Tue Oct 27 12:25:08 2015 +0100
+++ b/hotspot/src/share/vm/prims/whitebox.cpp	Tue Nov 10 11:07:15 2015 +0100
@@ -322,8 +322,8 @@
 WB_END
 
 WB_ENTRY(jboolean, WB_G1InConcurrentMark(JNIEnv* env, jobject o))
-  G1CollectedHeap* g1 = G1CollectedHeap::heap();
-  return g1->concurrent_mark()->cmThread()->during_cycle();
+  G1CollectedHeap* g1h = G1CollectedHeap::heap();
+  return g1h->concurrent_mark()->cmThread()->during_cycle();
 WB_END
 
 WB_ENTRY(jboolean, WB_G1StartMarkCycle(JNIEnv* env, jobject o))