8264987: G1: Fill BOTs for Survivor-turned-to-Old regions in full gc

Co-authored-by: Shoubing Ma <mashoubing1@huawei.com>
Reviewed-by: tschatzl, sjohanss
diff --git a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp
index d068cad..2386511 100644
--- a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp
+++ b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp
@@ -63,10 +63,16 @@
     } else {
       assert(MarkSweepDeadRatio > 0,
              "only skip compaction for other regions when MarkSweepDeadRatio > 0");
-
       // Force the high live ratio region as compacting to skip these regions in the
       // later compaction step.
       force_not_compacted = true;
+      if (hr->is_young()) {
+        // G1 updates the BOT for old region contents incrementally, but young regions
+        // lack BOT information for performance reasons.
+        // Recreate BOT information of high live ratio young regions here to keep expected
+        // performance during scanning their card tables in the collection pauses later.
+        update_bot(hr);
+      }
       log_debug(gc, phases)("Phase 2: skip compaction region index: %u, live words: " SIZE_FORMAT,
                             hr->hrm_index(), _collector->live_words(hr->hrm_index()));
     }
@@ -157,6 +163,22 @@
   return live_words <= live_words_threshold;
 }
 
+void G1FullGCPrepareTask::G1CalculatePointersClosure::update_bot(HeapRegion* hr) {
+  HeapWord* const limit = hr->top();
+  HeapWord* next_addr = hr->bottom();
+  HeapWord* threshold = hr->initialize_threshold();
+  HeapWord* prev_addr;
+  while (next_addr < limit) {
+    prev_addr = next_addr;
+    next_addr = _bitmap->get_next_marked_addr(next_addr + 1, limit);
+
+    if (next_addr > threshold) {
+      threshold = hr->cross_threshold(prev_addr, next_addr);
+    }
+  }
+  assert(next_addr == limit, "Should stop the scan at the limit.");
+}
+
 void G1FullGCPrepareTask::G1CalculatePointersClosure::reset_region_metadata(HeapRegion* hr) {
   hr->rem_set()->clear();
   hr->clear_cardtable();
diff --git a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.hpp b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.hpp
index a1529c8..c27dc4a 100644
--- a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.hpp
+++ b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.hpp
@@ -63,6 +63,7 @@
     void prepare_for_compaction_work(G1FullGCCompactionPoint* cp, HeapRegion* hr);
     void free_humongous_region(HeapRegion* hr);
     void free_open_archive_region(HeapRegion* hr);
+    void update_bot(HeapRegion* hr);
 
     void reset_region_metadata(HeapRegion* hr);