From 5cdf192706cc66ab8228057151bd807ea6267222 Mon Sep 17 00:00:00 2001
Date: Thu, 21 Sep 2023 16:44:51 +0800
Subject: add 8267185-Add-string-deduplication-support-to

---
 .../gc/parallel/parallelScavengeHeap.cpp      | 13 +++++
 .../gc/parallel/parallelScavengeHeap.hpp      |  3 ++
 .../share/gc/parallel/psCompactionManager.cpp |  6 +++
 .../share/gc/parallel/psCompactionManager.hpp |  9 ++++
 .../parallel/psCompactionManager.inline.hpp   |  7 +++
 .../share/gc/parallel/psParallelCompact.cpp   |  3 ++
 .../share/gc/parallel/psPromotionManager.cpp  |  1 +
 .../share/gc/parallel/psPromotionManager.hpp  |  5 ++
 .../gc/parallel/psPromotionManager.inline.hpp |  7 +++
 .../share/gc/parallel/psStringDedup.hpp       | 50 +++++++++++++++++++
 .../shared/stringdedup/stringDedupConfig.cpp  |  2 +-
 .../TestStringDeduplicationAgeThreshold.java  | 13 +++++
 .../TestStringDeduplicationFullGC.java        | 13 +++++
 .../TestStringDeduplicationInterned.java      | 13 +++++
 .../TestStringDeduplicationPrintOptions.java  | 13 +++++
 .../TestStringDeduplicationTableResize.java   | 13 +++++
 .../TestStringDeduplicationYoungGC.java       | 13 +++++
 17 files changed, 183 insertions(+), 1 deletion(-)
 create mode 100644 src/hotspot/share/gc/parallel/psStringDedup.hpp

diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp
index 16c7d91c4..cf9d34eb9 100644
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp
@@ -41,6 +41,7 @@
 #include "gc/shared/gcInitLogger.hpp"
 #include "gc/shared/locationPrinter.inline.hpp"
 #include "gc/shared/scavengableNMethods.hpp"
+#include "gc/shared/suspendibleThreadSet.hpp"
 #include "logging/log.hpp"
 #include "memory/iterator.hpp"
 #include "memory/metaspaceCounters.hpp"
@@ -162,6 +163,18 @@ void ParallelScavengeHeap::initialize_serviceability() {
 
 }
 
+void ParallelScavengeHeap::safepoint_synchronize_begin() {
+  if (UseStringDeduplication) {
+    SuspendibleThreadSet::synchronize();
+  }
+}
+
+void ParallelScavengeHeap::safepoint_synchronize_end() {
+  if (UseStringDeduplication) {
+    SuspendibleThreadSet::desynchronize();
+  }
+}
+
 class PSIsScavengable : public BoolObjectClosure {
   bool do_object_b(oop obj) {
     return ParallelScavengeHeap::heap()->is_in_young(obj);
diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp
index 689400fbe..b35df689f 100644
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp
@@ -139,6 +139,9 @@ class ParallelScavengeHeap : public CollectedHeap {
   // Returns JNI_OK on success
   virtual jint initialize();
 
+  virtual void safepoint_synchronize_begin();
+  virtual void safepoint_synchronize_end();
+
   void post_initialize();
   void update_counters();
 
diff --git a/src/hotspot/share/gc/parallel/psCompactionManager.cpp b/src/hotspot/share/gc/parallel/psCompactionManager.cpp
index b2c17140d..bab67b219 100644
--- a/src/hotspot/share/gc/parallel/psCompactionManager.cpp
+++ b/src/hotspot/share/gc/parallel/psCompactionManager.cpp
@@ -107,6 +107,12 @@ void ParCompactionManager::reset_all_bitmap_query_caches() {
   }
 }
 
+void ParCompactionManager::flush_all_string_dedup_requests() {
+  uint parallel_gc_threads = ParallelScavengeHeap::heap()->workers().total_workers();
+  for (uint i=0; i<=parallel_gc_threads; i++) {
+    _manager_array[i]->flush_string_dedup_requests();
+  }
+}
 
 ParCompactionManager*
 ParCompactionManager::gc_thread_compaction_manager(uint index) {
diff --git a/src/hotspot/share/gc/parallel/psCompactionManager.hpp b/src/hotspot/share/gc/parallel/psCompactionManager.hpp
index 12b5d891d..86810d32c 100644
--- a/src/hotspot/share/gc/parallel/psCompactionManager.hpp
+++ b/src/hotspot/share/gc/parallel/psCompactionManager.hpp
@@ -26,6 +26,7 @@
 #define SHARE_GC_PARALLEL_PSCOMPACTIONMANAGER_HPP
 
 #include "gc/parallel/psParallelCompact.hpp"
+#include "gc/shared/stringdedup/stringDedup.hpp"
 #include "gc/shared/taskqueue.hpp"
 #include "gc/shared/taskTerminator.hpp"
 #include "memory/allocation.hpp"
@@ -88,6 +89,8 @@ class ParCompactionManager : public CHeapObj<mtGC> {
   oop _last_query_obj;
   size_t _last_query_ret;
 
+  StringDedup::Requests _string_dedup_requests;
+
   static PSOldGen* old_gen()             { return _old_gen; }
   static ObjectStartArray* start_array() { return _start_array; }
   static OopTaskQueueSet* oop_task_queues()  { return _oop_task_queues; }
@@ -126,6 +129,10 @@ class ParCompactionManager : public CHeapObj<mtGC> {
     _last_query_ret = 0;
   }
 
+  void flush_string_dedup_requests() {
+    _string_dedup_requests.flush();
+  }
+
   // Bitmap query support, cache last query and result
   HeapWord* last_query_begin() { return _last_query_beg; }
   oop last_query_object() { return _last_query_obj; }
@@ -137,6 +144,8 @@ class ParCompactionManager : public CHeapObj<mtGC> {
 
   static void reset_all_bitmap_query_caches();
 
+  static void flush_all_string_dedup_requests();
+
   RegionTaskQueue* region_stack()                { return &_region_stack; }
 
   static ParCompactionManager* get_vmthread_cm() { return _manager_array[ParallelGCThreads]; }
diff --git a/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp b/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp
index e40e3689d..45e8dae5a 100644
--- a/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp
+++ b/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp
@@ -31,6 +31,7 @@
 #include "classfile/javaClasses.inline.hpp"
 #include "gc/parallel/parMarkBitMap.hpp"
 #include "gc/parallel/psParallelCompact.inline.hpp"
+#include "gc/parallel/psStringDedup.hpp"
 #include "gc/shared/taskqueue.inline.hpp"
 #include "oops/access.inline.hpp"
 #include "oops/arrayOop.hpp"
@@ -108,6 +109,12 @@ inline void ParCompactionManager::mark_and_push(T* p) {
 
     if (mark_bitmap()->is_unmarked(obj) && PSParallelCompact::mark_obj(obj)) {
       push(obj);
+
+      if (StringDedup::is_enabled() &&
+          java_lang_String::is_instance_inlined(obj) &&
+          psStringDedup::is_candidate_from_mark(obj)) {
+        _string_dedup_requests.add(obj);
+      }
     }
   }
 }
diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp
index 3c276db70..8ac733fa5 100644
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp
@@ -41,6 +41,7 @@
 #include "gc/parallel/psRootType.hpp"
 #include "gc/parallel/psScavenge.hpp"
 #include "gc/parallel/psYoungGen.hpp"
+#include "gc/parallel/psStringDedup.hpp"
 #include "gc/shared/gcCause.hpp"
 #include "gc/shared/gcHeapSummary.hpp"
 #include "gc/shared/gcId.hpp"
@@ -1021,6 +1022,8 @@ void PSParallelCompact::post_compact()
     _space_info[id].publish_new_top();
   }
 
+  ParCompactionManager::flush_all_string_dedup_requests();
+
   MutableSpace* const eden_space = _space_info[eden_space_id].space();
   MutableSpace* const from_space = _space_info[from_space_id].space();
   MutableSpace* const to_space   = _space_info[to_space_id].space();
diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.cpp b/src/hotspot/share/gc/parallel/psPromotionManager.cpp
index c5f321f54..56e2683f3 100644
--- a/src/hotspot/share/gc/parallel/psPromotionManager.cpp
+++ b/src/hotspot/share/gc/parallel/psPromotionManager.cpp
@@ -121,6 +121,7 @@ bool PSPromotionManager::post_scavenge(YoungGCTracer& gc_tracer) {
       promotion_failure_occurred = true;
     }
     manager->flush_labs();
+    manager->flush_string_dedup_requests();
   }
   if (!promotion_failure_occurred) {
     // If there was no promotion failure, the preserved mark stacks
diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.hpp b/src/hotspot/share/gc/parallel/psPromotionManager.hpp
index e94be81b6..462beec76 100644
--- a/src/hotspot/share/gc/parallel/psPromotionManager.hpp
+++ b/src/hotspot/share/gc/parallel/psPromotionManager.hpp
@@ -29,6 +29,7 @@
 #include "gc/shared/copyFailedInfo.hpp"
 #include "gc/shared/gcTrace.hpp"
 #include "gc/shared/preservedMarks.hpp"
+#include "gc/shared/stringdedup/stringDedup.hpp"
 #include "gc/shared/taskqueue.hpp"
 #include "memory/padded.hpp"
 #include "utilities/globalDefinitions.hpp"
@@ -92,6 +93,8 @@ class PSPromotionManager {
   PreservedMarks*                     _preserved_marks;
   PromotionFailedInfo                 _promotion_failed_info;
 
+  StringDedup::Requests _string_dedup_requests;
+
   // Accessors
   static PSOldGen* old_gen()         { return _old_gen; }
   static MutableSpace* young_space() { return _young_space; }
@@ -146,6 +149,8 @@ class PSPromotionManager {
   static void restore_preserved_marks();
 
   void flush_labs();
+  void flush_string_dedup_requests() { _string_dedup_requests.flush(); }
+
   void drain_stacks(bool totally_drain) {
     drain_stacks_depth(totally_drain);
   }
diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp
index a0149e447..e754d84b6 100644
--- a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp
+++ b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp
@@ -32,6 +32,7 @@
 #include "gc/parallel/psOldGen.hpp"
 #include "gc/parallel/psPromotionLAB.inline.hpp"
 #include "gc/parallel/psScavenge.inline.hpp"
+#include "gc/parallel/psStringDedup.hpp"
 #include "gc/shared/taskqueue.inline.hpp"
 #include "gc/shared/tlab_globals.hpp"
 #include "logging/log.hpp"
@@ -286,6 +287,12 @@ inline oop PSPromotionManager::copy_unmarked_to_survivor_space(oop o,
     } else {
       // we'll just push its contents
       push_contents(new_obj);
+
+      if (StringDedup::is_enabled() &&
+          java_lang_String::is_instance_inlined(new_obj) &&
+          psStringDedup::is_candidate_from_evacuation(new_obj, new_obj_is_tenured)) {
+        _string_dedup_requests.add(o);
+      }
     }
     return new_obj;
   } else {
diff --git a/src/hotspot/share/gc/parallel/psStringDedup.hpp b/src/hotspot/share/gc/parallel/psStringDedup.hpp
new file mode 100644
index 000000000..d1debbddc
--- /dev/null
+++ b/src/hotspot/share/gc/parallel/psStringDedup.hpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_GC_PARALLEL_PSSTRINGDEDUP_HPP
+#define SHARE_GC_PARALLEL_PSSTRINGDEDUP_HPP
+
+#include "gc/parallel/psScavenge.hpp"
+#include "gc/shared/stringdedup/stringDedup.hpp"
+#include "memory/allStatic.hpp"
+#include "oops/oopsHierarchy.hpp"
+
+class psStringDedup : AllStatic {
+public:
+  static bool is_candidate_from_mark(oop java_string) {
+    // Candidate if string is being evacuated from young to old but has not
+    // reached the deduplication age threshold, i.e. has not previously been a
+    // candidate during its life in the young generation.
+    return PSScavenge::is_obj_in_young(java_string) &&
+           StringDedup::is_below_threshold_age(java_string->age());
+  }
+
+  static bool is_candidate_from_evacuation(oop obj,
+                                           bool obj_is_tenured) {
+    return obj_is_tenured ?
+           StringDedup::is_below_threshold_age(obj->age()) :
+           StringDedup::is_threshold_age(obj->age());
+  }
+};
+#endif // SHARE_GC_PARALLEL_PSSTRINGDEDUP_HPP
diff --git a/src/hotspot/share/gc/shared/stringdedup/stringDedupConfig.cpp b/src/hotspot/share/gc/shared/stringdedup/stringDedupConfig.cpp
index 71ec8d563..258f497c5 100644
--- a/src/hotspot/share/gc/shared/stringdedup/stringDedupConfig.cpp
+++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupConfig.cpp
@@ -116,7 +116,7 @@ size_t StringDedup::Config::desired_table_size(size_t entry_count) {
 bool StringDedup::Config::ergo_initialize() {
   if (!UseStringDeduplication) {
     return true;
-  } else if (!UseG1GC && !UseShenandoahGC) {
+  } else if (!UseG1GC && !UseShenandoahGC && !UseParallelGC) {
     // String deduplication requested but not supported by the selected GC.
     // Warn and force disable, but don't error except in debug build with
     // incorrect default.
diff --git a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationAgeThreshold.java b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationAgeThreshold.java
index ae57bf7df..f652b58d2 100644
--- a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationAgeThreshold.java
+++ b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationAgeThreshold.java
@@ -36,6 +36,19 @@ package gc.stringdedup;
  * @run driver gc.stringdedup.TestStringDeduplicationAgeThreshold G1
  */
 
+/*
+ * @test TestStringDeduplicationAgeThreshold
+ * @summary Test string deduplication age threshold
+ * @bug 8029075
+ * @requires vm.gc.Parallel
+ * @library /test/lib
+ * @library /
+ * @modules java.base/jdk.internal.misc:open
+ * @modules java.base/java.lang:open
+ *          java.management
+ * @run driver gc.stringdedup.TestStringDeduplicationAgeThreshold Parallel
+ */
+
 /*
  * @test TestStringDeduplicationAgeThreshold
  * @summary Test string deduplication age threshold
diff --git a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationFullGC.java b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationFullGC.java
index 7e5bb9ae5..83a652a8e 100644
--- a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationFullGC.java
+++ b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationFullGC.java
@@ -36,6 +36,19 @@ package gc.stringdedup;
  * @run driver gc.stringdedup.TestStringDeduplicationFullGC G1
  */
 
+/*
+ * @test TestStringDeduplicationFullGC
+ * @summary Test string deduplication during full GC
+ * @bug 8029075
+ * @requires vm.gc.Parallel
+ * @library /test/lib
+ * @library /
+ * @modules java.base/jdk.internal.misc:open
+ * @modules java.base/java.lang:open
+ *          java.management
+ * @run driver gc.stringdedup.TestStringDeduplicationFullGC Parallel
+ */
+
 /*
  * @test TestStringDeduplicationFullGC
  * @summary Test string deduplication during full GC
diff --git a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationInterned.java b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationInterned.java
index a5720b88e..a39419f0a 100644
--- a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationInterned.java
+++ b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationInterned.java
@@ -48,6 +48,20 @@ package gc.stringdedup;
  *          java.management
  * @run driver gc.stringdedup.TestStringDeduplicationInterned Shenandoah
  */
+
+/*
+ * @test TestStringDeduplicationInterned
+ * @summary Test string deduplication of interned strings
+ * @bug 8029075
+ * @requires vm.gc.Parallel
+ * @library /test/lib
+ * @library /
+ * @modules java.base/jdk.internal.misc:open
+ * @modules java.base/java.lang:open
+ *          java.management
+ * @run driver gc.stringdedup.TestStringDeduplicationInterned Parallel
+ */
+
 public class TestStringDeduplicationInterned {
     public static void main(String[] args) throws Exception {
         TestStringDeduplicationTools.selectGC(args);
diff --git a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationPrintOptions.java b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationPrintOptions.java
index d57e726a5..c3f2f10dc 100644
--- a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationPrintOptions.java
+++ b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationPrintOptions.java
@@ -36,6 +36,19 @@ package gc.stringdedup;
  * @run driver gc.stringdedup.TestStringDeduplicationPrintOptions G1
  */
 
+/*
+ * @test TestStringDeduplicationPrintOptions
+ * @summary Test string deduplication print options
+ * @bug 8029075
+ * @requires vm.gc.Parallel
+ * @library /test/lib
+ * @library /
+ * @modules java.base/jdk.internal.misc:open
+ * @modules java.base/java.lang:open
+ *          java.management
+ * @run driver gc.stringdedup.TestStringDeduplicationPrintOptions Parallel
+ */
+
 /*
  * @test TestStringDeduplicationPrintOptions
  * @summary Test string deduplication print options
diff --git a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTableResize.java b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTableResize.java
index 53c71f1ec..03070b1cb 100644
--- a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTableResize.java
+++ b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTableResize.java
@@ -36,6 +36,19 @@ package gc.stringdedup;
  * @run driver gc.stringdedup.TestStringDeduplicationTableResize G1
  */
 
+/*
+ * @test TestStringDeduplicationTableResize
+ * @summary Test string deduplication table resize
+ * @bug 8029075
+ * @requires vm.gc.Parallel
+ * @library /test/lib
+ * @library /
+ * @modules java.base/jdk.internal.misc:open
+ * @modules java.base/java.lang:open
+ *          java.management
+ * @run driver gc.stringdedup.TestStringDeduplicationTableResize Parallel
+ */
+
 /*
  * @test TestStringDeduplicationTableResize
  * @summary Test string deduplication table resize
diff --git a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationYoungGC.java b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationYoungGC.java
index 02cf647e4..1f0e9a70e 100644
--- a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationYoungGC.java
+++ b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationYoungGC.java
@@ -36,6 +36,19 @@ package gc.stringdedup;
  * @run driver gc.stringdedup.TestStringDeduplicationYoungGC G1
  */
 
+/*
+ * @test TestStringDeduplicationYoungGC
+ * @summary Test string deduplication during young GC
+ * @bug 8029075
+ * @requires vm.gc.Parallel
+ * @library /test/lib
+ * @library /
+ * @modules java.base/jdk.internal.misc:open
+ * @modules java.base/java.lang:open
+ *          java.management
+ * @run driver gc.stringdedup.TestStringDeduplicationYoungGC Parallel
+ */
+
 /*
  * @test TestStringDeduplicationYoungGC
  * @summary Test string deduplication during young GC
-- 
2.22.0

