8224659: Parallel GC: Use WorkGang (1: PCRefProcTask)
authorlkorinth
Fri, 16 Aug 2019 09:18:19 +0200
changeset 57767 b3e44e1b135d
parent 57766 81ce766c9111
child 57768 fc82b6cb8b14
8224659: Parallel GC: Use WorkGang (1: PCRefProcTask) Reviewed-by: stefank, kbarrett, tschatzl
src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp
src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp
src/hotspot/share/gc/parallel/pcTasks.cpp
src/hotspot/share/gc/parallel/pcTasks.hpp
src/hotspot/share/gc/parallel/psCompactionManager.hpp
src/hotspot/share/gc/parallel/psParallelCompact.cpp
src/hotspot/share/gc/parallel/psScavenge.cpp
test/hotspot/jtreg/gc/ergonomics/TestInitialGCThreadLogging.java
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp	Fri Aug 16 08:42:09 2019 +0800
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp	Fri Aug 16 09:18:19 2019 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, 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
@@ -123,6 +123,9 @@
     return JNI_ENOMEM;
   }
 
+  // Set up WorkGang
+  _workers.initialize_workers();
+
   return JNI_OK;
 }
 
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp	Fri Aug 16 08:42:09 2019 +0800
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp	Fri Aug 16 09:18:19 2019 +0200
@@ -37,6 +37,7 @@
 #include "gc/shared/referenceProcessor.hpp"
 #include "gc/shared/softRefPolicy.hpp"
 #include "gc/shared/strongRootsScope.hpp"
+#include "gc/shared/workgroup.hpp"
 #include "logging/log.hpp"
 #include "memory/metaspace.hpp"
 #include "utilities/growableArray.hpp"
@@ -78,6 +79,8 @@
   MemoryPool* _survivor_pool;
   MemoryPool* _old_pool;
 
+  WorkGang _workers;
+
   virtual void initialize_serviceability();
 
   void trace_heap(GCWhen::Type when, const GCTracer* tracer);
@@ -99,7 +102,11 @@
     _old_manager(NULL),
     _eden_pool(NULL),
     _survivor_pool(NULL),
-    _old_pool(NULL) { }
+    _old_pool(NULL),
+    _workers("GC Thread",
+             ParallelGCThreads,
+             true /* are_GC_task_threads */,
+             false /* are_ConcurrentGC_threads */) { }
 
   // For use by VM operations
   enum CollectionType {
@@ -252,6 +259,10 @@
 
   GCMemoryManager* old_gc_manager() const { return _old_manager; }
   GCMemoryManager* young_gc_manager() const { return _young_manager; }
+
+  WorkGang& workers() {
+    return _workers;
+  }
 };
 
 // Class that can be used to print information about the
--- a/src/hotspot/share/gc/parallel/pcTasks.cpp	Fri Aug 16 08:42:09 2019 +0800
+++ b/src/hotspot/share/gc/parallel/pcTasks.cpp	Fri Aug 16 09:18:19 2019 +0200
@@ -131,48 +131,6 @@
 
 
 //
-// RefProcTaskProxy
-//
-
-void RefProcTaskProxy::do_it(GCTaskManager* manager, uint which)
-{
-  assert(ParallelScavengeHeap::heap()->is_gc_active(), "called outside gc");
-
-  ParCompactionManager* cm =
-    ParCompactionManager::gc_thread_compaction_manager(which);
-  PCMarkAndPushClosure mark_and_push_closure(cm);
-  ParCompactionManager::FollowStackClosure follow_stack_closure(cm);
-  _rp_task.work(_work_id, *PSParallelCompact::is_alive_closure(),
-                mark_and_push_closure, follow_stack_closure);
-}
-
-//
-// RefProcTaskExecutor
-//
-
-void RefProcTaskExecutor::execute(ProcessTask& task, uint ergo_workers)
-{
-  ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
-  uint active_gc_threads = heap->gc_task_manager()->active_workers();
-  assert(active_gc_threads == ergo_workers,
-         "Ergonomically chosen workers (%u) must be equal to active workers (%u)",
-         ergo_workers, active_gc_threads);
-  OopTaskQueueSet* qset = ParCompactionManager::stack_array();
-  TaskTerminator terminator(active_gc_threads, qset);
-
-  GCTaskQueue* q = GCTaskQueue::create();
-  for(uint i=0; i<active_gc_threads; i++) {
-    q->enqueue(new RefProcTaskProxy(task, i));
-  }
-  if (task.marks_oops_alive() && (active_gc_threads>1)) {
-    for (uint j=0; j<active_gc_threads; j++) {
-      q->enqueue(new StealMarkingTask(terminator.terminator()));
-    }
-  }
-  PSParallelCompact::gc_task_manager()->execute_and_wait(q);
-}
-
-//
 // StealMarkingTask
 //
 
--- a/src/hotspot/share/gc/parallel/pcTasks.hpp	Fri Aug 16 08:42:09 2019 +0800
+++ b/src/hotspot/share/gc/parallel/pcTasks.hpp	Fri Aug 16 09:18:19 2019 +0200
@@ -110,40 +110,6 @@
   virtual void do_it(GCTaskManager* manager, uint which);
 };
 
-//
-// RefProcTaskProxy
-//
-// This task is used as a proxy to parallel reference processing tasks .
-//
-
-class RefProcTaskProxy : public GCTask {
-  typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask;
-  ProcessTask & _rp_task;
-  uint          _work_id;
-public:
-  RefProcTaskProxy(ProcessTask & rp_task, uint work_id)
-    : _rp_task(rp_task),
-      _work_id(work_id)
-  { }
-
-private:
-  virtual char* name() { return (char *)"Process referents by policy in parallel"; }
-
-  virtual void do_it(GCTaskManager* manager, uint which);
-};
-
-
-//
-// RefProcTaskExecutor
-//
-// Task executor is an interface for the reference processor to run
-// tasks using GCTaskManager.
-//
-
-class RefProcTaskExecutor: public AbstractRefProcTaskExecutor {
-  virtual void execute(ProcessTask& task, uint ergo_workers);
-};
-
 
 //
 // StealMarkingTask
--- a/src/hotspot/share/gc/parallel/psCompactionManager.hpp	Fri Aug 16 08:42:09 2019 +0800
+++ b/src/hotspot/share/gc/parallel/psCompactionManager.hpp	Fri Aug 16 09:18:19 2019 +0200
@@ -44,6 +44,7 @@
   friend class UpdateAndFillClosure;
   friend class RefProcTaskExecutor;
   friend class IdleGCTask;
+  friend class PCRefProcTask;
 
  public:
 
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp	Fri Aug 16 08:42:09 2019 +0800
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp	Fri Aug 16 09:18:19 2019 +0200
@@ -55,6 +55,7 @@
 #include "gc/shared/referenceProcessorPhaseTimes.hpp"
 #include "gc/shared/spaceDecorator.hpp"
 #include "gc/shared/weakProcessor.hpp"
+#include "gc/shared/workerPolicy.hpp"
 #include "logging/log.hpp"
 #include "memory/iterator.inline.hpp"
 #include "memory/resourceArea.hpp"
@@ -1789,6 +1790,12 @@
     ResourceMark rm;
     HandleMark hm;
 
+    const uint active_workers =
+      WorkerPolicy::calc_active_workers(ParallelScavengeHeap::heap()->workers().total_workers(),
+                                        ParallelScavengeHeap::heap()->workers().active_workers(),
+                                        Threads::number_of_non_daemon_threads());
+    ParallelScavengeHeap::heap()->workers().update_active_workers(active_workers);
+
     // Set the number of GC threads to be used in this collection
     gc_task_manager()->set_active_gang();
     gc_task_manager()->task_idle_workers();
@@ -2089,6 +2096,66 @@
   }
 };
 
+static void steal_marking_work(ParallelTaskTerminator& terminator, uint worker_id) {
+  assert(ParallelScavengeHeap::heap()->is_gc_active(), "called outside gc");
+
+  ParCompactionManager* cm =
+    ParCompactionManager::gc_thread_compaction_manager(worker_id);
+
+  oop obj = NULL;
+  ObjArrayTask task;
+  do {
+    while (ParCompactionManager::steal_objarray(worker_id,  task)) {
+      cm->follow_array((objArrayOop)task.obj(), task.index());
+      cm->follow_marking_stacks();
+    }
+    while (ParCompactionManager::steal(worker_id, obj)) {
+      cm->follow_contents(obj);
+      cm->follow_marking_stacks();
+    }
+  } while (!terminator.offer_termination());
+}
+
+class PCRefProcTask : public AbstractGangTask {
+  typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask;
+  ProcessTask& _task;
+  uint _ergo_workers;
+  TaskTerminator _terminator;
+
+public:
+  PCRefProcTask(ProcessTask& task, uint ergo_workers) :
+      AbstractGangTask("PCRefProcTask"),
+      _task(task),
+      _ergo_workers(ergo_workers),
+      _terminator(_ergo_workers, ParCompactionManager::stack_array()) {
+  }
+
+  virtual void work(uint worker_id) {
+    ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
+    assert(ParallelScavengeHeap::heap()->is_gc_active(), "called outside gc");
+
+    ParCompactionManager* cm =
+      ParCompactionManager::gc_thread_compaction_manager(worker_id);
+    PCMarkAndPushClosure mark_and_push_closure(cm);
+    ParCompactionManager::FollowStackClosure follow_stack_closure(cm);
+    _task.work(worker_id, *PSParallelCompact::is_alive_closure(),
+               mark_and_push_closure, follow_stack_closure);
+
+    steal_marking_work(*_terminator.terminator(), worker_id);
+  }
+};
+
+class RefProcTaskExecutor: public AbstractRefProcTaskExecutor {
+  void execute(ProcessTask& process_task, uint ergo_workers) {
+    assert(ParallelScavengeHeap::heap()->workers().active_workers() == ergo_workers,
+           "Ergonomically chosen workers (%u) must be equal to active workers (%u)",
+           ergo_workers, ParallelScavengeHeap::heap()->workers().active_workers());
+
+    PCRefProcTask task(process_task, ergo_workers);
+    ParallelScavengeHeap::heap()->workers().run_task(&task);
+  }
+};
+
 void PSParallelCompact::marking_phase(ParCompactionManager* cm,
                                       bool maximum_heap_compaction,
                                       ParallelOldTracer *gc_tracer) {
--- a/src/hotspot/share/gc/parallel/psScavenge.cpp	Fri Aug 16 08:42:09 2019 +0800
+++ b/src/hotspot/share/gc/parallel/psScavenge.cpp	Fri Aug 16 09:18:19 2019 +0200
@@ -47,6 +47,7 @@
 #include "gc/shared/referenceProcessorPhaseTimes.hpp"
 #include "gc/shared/spaceDecorator.hpp"
 #include "gc/shared/weakProcessor.hpp"
+#include "gc/shared/workerPolicy.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.hpp"
 #include "logging/log.hpp"
@@ -339,15 +340,20 @@
     // straying into the promotion labs.
     HeapWord* old_top = old_gen->object_space()->top();
 
+    const uint active_workers =
+      WorkerPolicy::calc_active_workers(ParallelScavengeHeap::heap()->workers().total_workers(),
+                                        ParallelScavengeHeap::heap()->workers().active_workers(),
+                                        Threads::number_of_non_daemon_threads());
+    ParallelScavengeHeap::heap()->workers().update_active_workers(active_workers);
+
     // Release all previously held resources
     gc_task_manager()->release_all_resources();
 
     // Set the number of GC threads to be used in this collection
     gc_task_manager()->set_active_gang();
     gc_task_manager()->task_idle_workers();
-    // Get the active number of workers here and use that value
-    // throughout the methods.
-    uint active_workers = gc_task_manager()->active_workers();
+
+    assert(active_workers == gc_task_manager()->active_workers(), "sanity, taskmanager and workgang ought to agree");
 
     PSPromotionManager::pre_scavenge();
 
--- a/test/hotspot/jtreg/gc/ergonomics/TestInitialGCThreadLogging.java	Fri Aug 16 08:42:09 2019 +0800
+++ b/test/hotspot/jtreg/gc/ergonomics/TestInitialGCThreadLogging.java	Fri Aug 16 09:18:19 2019 +0200
@@ -56,7 +56,7 @@
 
     if (GC.Parallel.isSupported()) {
       noneGCSupported = false;
-      testInitialGCThreadLogging("UseParallelGC", "ParGC Thread");
+      testInitialGCThreadLogging("UseParallelGC", "GC Thread");
     }
 
     if (GC.Shenandoah.isSupported()) {