--- old/src/hotspot/share/gc/shared/collectedHeap.cpp 2020-08-14 20:19:30.917811885 +0200 +++ new/src/hotspot/share/gc/shared/collectedHeap.cpp 2020-08-14 20:19:30.741808722 +0200 @@ -122,19 +122,6 @@ ms_chunk_free_list_summary, class_chunk_free_list_summary); } -void CollectedHeap::run_task_at_safepoint(AbstractGangTask* task, uint num_workers) { - assert(SafepointSynchronize::is_at_safepoint(), "Should only be called at a safepoint"); - - WorkGang* gang = get_safepoint_workers(); - if (gang == NULL) { - // GC doesn't support parallel worker threads. - // Execute in this thread with worker id 0. - task->work(0); - } else { - gang->run_task(task, num_workers); - } -} - void CollectedHeap::print_heap_before_gc() { Universe::print_heap_before_gc(); if (_gc_heap_log != NULL) { --- old/src/hotspot/share/gc/shared/collectedHeap.hpp 2020-08-14 20:19:31.217817276 +0200 +++ new/src/hotspot/share/gc/shared/collectedHeap.hpp 2020-08-14 20:19:31.073814688 +0200 @@ -467,11 +467,6 @@ // Iterator for all GC threads (other than VM thread) virtual void gc_threads_do(ThreadClosure* tc) const = 0; - // Runs the given task with (up to) the requested number of workers. - // Some GCs don't support parallel worker threads and will run the - // task in one thread, with worker id 0. - void run_task_at_safepoint(AbstractGangTask* task, uint num_workers); - // Print any relevant tracing info that flags imply. // Default implementation does nothing. virtual void print_tracing_info() const = 0; --- old/src/hotspot/share/gc/shared/workgroup.hpp 2020-08-14 20:19:31.553823315 +0200 +++ new/src/hotspot/share/gc/shared/workgroup.hpp 2020-08-14 20:19:31.377820152 +0200 @@ -202,6 +202,27 @@ virtual AbstractGangWorker* allocate_worker(uint which); }; +// Temporarily try to set the number of active workers. +// It's not guaranteed that it succeeds, and users need to +// query the number of active workers. +class WithUpdatedActiveWorkers : public StackObj { +private: + AbstractWorkGang* const _gang; + const uint _old_active_workers; + +public: + WithUpdatedActiveWorkers(AbstractWorkGang* gang, uint requested_num_workers) : + _gang(gang), + _old_active_workers(gang->active_workers()) { + uint capped_num_workers = MIN2(requested_num_workers, gang->total_workers()); + gang->update_active_workers(capped_num_workers); + } + + ~WithUpdatedActiveWorkers() { + _gang->update_active_workers(_old_active_workers); + } +}; + // Several instances of this class run in parallel as workers for a gang. class AbstractGangWorker: public WorkerThread { public: --- old/src/hotspot/share/memory/heapInspection.cpp 2020-08-14 20:19:31.893829425 +0200 +++ new/src/hotspot/share/memory/heapInspection.cpp 2020-08-14 20:19:31.717826262 +0200 @@ -575,13 +575,26 @@ // Try parallel first. if (parallel_thread_num > 1) { ResourceMark rm; - ParallelObjectIterator* poi = Universe::heap()->parallel_object_iterator(parallel_thread_num); - if (poi != NULL) { - ParHeapInspectTask task(poi, cit, filter); - Universe::heap()->run_task_at_safepoint(&task, parallel_thread_num); - delete poi; - if (task.success()) { - return task.missed_count(); + + WorkGang* gang = Universe::heap()->get_safepoint_workers(); + if (gang != NULL) { + // The GC provided a WorkGang to be used during a safepoint. + + // Can't run with more threads than provided by the WorkGang. + WithUpdatedActiveWorkers update_and_restore(gang, parallel_thread_num); + + ParallelObjectIterator* poi = Universe::heap()->parallel_object_iterator(gang->active_workers()); + if (poi != NULL) { + // The GC supports parallel object iteration. + + ParHeapInspectTask task(poi, cit, filter); + // Run task with the active workers. + gang->run_task(&task); + + delete poi; + if (task.success()) { + return task.missed_count(); + } } } }