8072498: Multi-thread JNI weak reference processing
Add parallel processing support to WeakProcessor. Reviewed-by: tschatzl, sjohanss
This commit is contained in:
parent
49b859b9d3
commit
1b02e70184
@ -75,7 +75,7 @@
|
||||
#include "gc/shared/suspendibleThreadSet.hpp"
|
||||
#include "gc/shared/referenceProcessor.inline.hpp"
|
||||
#include "gc/shared/taskqueue.inline.hpp"
|
||||
#include "gc/shared/weakProcessor.hpp"
|
||||
#include "gc/shared/weakProcessor.inline.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "memory/iterator.hpp"
|
||||
@ -3719,14 +3719,8 @@ void G1CollectedHeap::post_evacuate_collection_set(EvacuationInfo& evacuation_in
|
||||
G1STWIsAliveClosure is_alive(this);
|
||||
G1KeepAliveClosure keep_alive(this);
|
||||
|
||||
{
|
||||
double start = os::elapsedTime();
|
||||
|
||||
WeakProcessor::weak_oops_do(&is_alive, &keep_alive);
|
||||
|
||||
double time_ms = (os::elapsedTime() - start) * 1000.0;
|
||||
g1_policy()->phase_times()->record_weak_ref_proc_time(time_ms);
|
||||
}
|
||||
WeakProcessor::weak_oops_do(workers(), &is_alive, &keep_alive,
|
||||
g1_policy()->phase_times()->weak_phase_times());
|
||||
|
||||
if (G1StringDedup::is_enabled()) {
|
||||
double fixup_start = os::elapsedTime();
|
||||
|
@ -50,7 +50,7 @@
|
||||
#include "gc/shared/suspendibleThreadSet.hpp"
|
||||
#include "gc/shared/taskqueue.inline.hpp"
|
||||
#include "gc/shared/vmGCOperations.hpp"
|
||||
#include "gc/shared/weakProcessor.hpp"
|
||||
#include "gc/shared/weakProcessor.inline.hpp"
|
||||
#include "include/jvm.h"
|
||||
#include "logging/log.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
@ -1669,7 +1669,7 @@ void G1ConcurrentMark::weak_refs_work(bool clear_all_soft_refs) {
|
||||
|
||||
{
|
||||
GCTraceTime(Debug, gc, phases) debug("Weak Processing", _gc_timer_cm);
|
||||
WeakProcessor::weak_oops_do(&g1_is_alive, &do_nothing_cl);
|
||||
WeakProcessor::weak_oops_do(_g1h->workers(), &g1_is_alive, &do_nothing_cl, 1);
|
||||
}
|
||||
|
||||
// Unload Klasses, String, Code Cache, etc.
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include "gc/shared/gcTraceTime.inline.hpp"
|
||||
#include "gc/shared/preservedMarks.hpp"
|
||||
#include "gc/shared/referenceProcessor.hpp"
|
||||
#include "gc/shared/weakProcessor.hpp"
|
||||
#include "gc/shared/weakProcessor.inline.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "runtime/biasedLocking.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
@ -214,8 +214,8 @@ void G1FullCollector::phase1_mark_live_objects() {
|
||||
|
||||
// Weak oops cleanup.
|
||||
{
|
||||
GCTraceTime(Debug, gc, phases) trace("Phase 1: Weak Processing", scope()->timer());
|
||||
WeakProcessor::weak_oops_do(&_is_alive, &do_nothing_cl);
|
||||
GCTraceTime(Debug, gc, phases) debug("Phase 1: Weak Processing", scope()->timer());
|
||||
WeakProcessor::weak_oops_do(_heap->workers(), &_is_alive, &do_nothing_cl, 1);
|
||||
}
|
||||
|
||||
// Class unloading and cleanup.
|
||||
|
@ -33,8 +33,10 @@
|
||||
#include "gc/g1/heapRegion.inline.hpp"
|
||||
#include "gc/shared/gcTraceTime.inline.hpp"
|
||||
#include "gc/shared/referenceProcessor.hpp"
|
||||
#include "gc/shared/weakProcessor.inline.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "memory/iterator.inline.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
|
||||
class G1AdjustLiveClosure : public StackObj {
|
||||
G1AdjustClosure* _adjust_closure;
|
||||
@ -79,6 +81,8 @@ class G1AdjustRegionClosure : public HeapRegionClosure {
|
||||
G1FullGCAdjustTask::G1FullGCAdjustTask(G1FullCollector* collector) :
|
||||
G1FullGCTask("G1 Adjust", collector),
|
||||
_root_processor(G1CollectedHeap::heap(), collector->workers()),
|
||||
_references_done(0),
|
||||
_weak_proc_task(collector->workers()),
|
||||
_hrclaimer(collector->workers()),
|
||||
_adjust(),
|
||||
_adjust_string_dedup(NULL, &_adjust, G1StringDedup::is_enabled()) {
|
||||
@ -94,12 +98,17 @@ void G1FullGCAdjustTask::work(uint worker_id) {
|
||||
G1FullGCMarker* marker = collector()->marker(worker_id);
|
||||
marker->preserved_stack()->adjust_during_full_gc();
|
||||
|
||||
// Adjust the weak_roots.
|
||||
// Adjust the weak roots.
|
||||
|
||||
if (Atomic::add(1u, &_references_done) == 1u) { // First incr claims task.
|
||||
G1CollectedHeap::heap()->ref_processor_stw()->weak_oops_do(&_adjust);
|
||||
}
|
||||
|
||||
AlwaysTrueClosure always_alive;
|
||||
_weak_proc_task.work(worker_id, &always_alive, &_adjust);
|
||||
|
||||
CLDToOopClosure adjust_cld(&_adjust);
|
||||
CodeBlobToOopClosure adjust_code(&_adjust, CodeBlobToOopClosure::FixRelocations);
|
||||
_root_processor.process_full_gc_weak_roots(&_adjust);
|
||||
|
||||
// Needs to be last, process_all_roots calls all_tasks_completed(...).
|
||||
_root_processor.process_all_roots(
|
||||
&_adjust,
|
||||
&adjust_cld,
|
||||
|
@ -30,12 +30,16 @@
|
||||
#include "gc/g1/g1RootProcessor.hpp"
|
||||
#include "gc/g1/g1StringDedup.hpp"
|
||||
#include "gc/g1/heapRegionManager.hpp"
|
||||
#include "gc/shared/weakProcessorPhaseTimes.hpp"
|
||||
#include "gc/shared/weakProcessor.hpp"
|
||||
#include "utilities/ticks.hpp"
|
||||
|
||||
class G1CollectedHeap;
|
||||
|
||||
class G1FullGCAdjustTask : public G1FullGCTask {
|
||||
G1RootProcessor _root_processor;
|
||||
volatile uint _references_done; // Atomic counter / bool
|
||||
WeakProcessor::Task _weak_proc_task;
|
||||
HeapRegionClaimer _hrclaimer;
|
||||
G1AdjustClosure _adjust;
|
||||
G1StringDedupUnlinkOrOopsDoClosure _adjust_string_dedup;
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "gc/g1/g1HotCardCache.hpp"
|
||||
#include "gc/g1/g1ParScanThreadState.inline.hpp"
|
||||
#include "gc/g1/g1StringDedup.hpp"
|
||||
#include "gc/shared/gcTimer.hpp"
|
||||
#include "gc/shared/workerDataArray.inline.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "logging/log.hpp"
|
||||
@ -42,7 +43,8 @@ G1GCPhaseTimes::G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads) :
|
||||
_max_gc_threads(max_gc_threads),
|
||||
_gc_start_counter(0),
|
||||
_gc_pause_time_ms(0.0),
|
||||
_ref_phase_times((GCTimer*)gc_timer, max_gc_threads)
|
||||
_ref_phase_times(gc_timer, max_gc_threads),
|
||||
_weak_phase_times(max_gc_threads)
|
||||
{
|
||||
assert(max_gc_threads > 0, "Must have some GC threads");
|
||||
|
||||
@ -129,7 +131,6 @@ void G1GCPhaseTimes::reset() {
|
||||
_cur_clear_ct_time_ms = 0.0;
|
||||
_cur_expand_heap_time_ms = 0.0;
|
||||
_cur_ref_proc_time_ms = 0.0;
|
||||
_cur_weak_ref_proc_time_ms = 0.0;
|
||||
_cur_collection_start_sec = 0.0;
|
||||
_root_region_scan_wait_time_ms = 0.0;
|
||||
_external_accounted_time_ms = 0.0;
|
||||
@ -157,6 +158,7 @@ void G1GCPhaseTimes::reset() {
|
||||
}
|
||||
|
||||
_ref_phase_times.reset();
|
||||
_weak_phase_times.reset();
|
||||
}
|
||||
|
||||
void G1GCPhaseTimes::note_gc_start() {
|
||||
@ -381,7 +383,7 @@ double G1GCPhaseTimes::print_post_evacuate_collection_set() const {
|
||||
_cur_collection_code_root_fixup_time_ms +
|
||||
_recorded_preserve_cm_referents_time_ms +
|
||||
_cur_ref_proc_time_ms +
|
||||
_cur_weak_ref_proc_time_ms +
|
||||
(_weak_phase_times.total_time_sec() * MILLIUNITS) +
|
||||
_cur_clear_ct_time_ms +
|
||||
_recorded_merge_pss_time_ms +
|
||||
_cur_strong_code_root_purge_time_ms +
|
||||
@ -399,8 +401,7 @@ double G1GCPhaseTimes::print_post_evacuate_collection_set() const {
|
||||
|
||||
debug_time_for_reference("Reference Processing", _cur_ref_proc_time_ms);
|
||||
_ref_phase_times.print_all_references(2, false);
|
||||
|
||||
debug_time("Weak Processing", _cur_weak_ref_proc_time_ms);
|
||||
_weak_phase_times.log_print(2);
|
||||
|
||||
if (G1StringDedup::is_enabled()) {
|
||||
debug_time("String Dedup Fixup", _cur_string_dedup_fixup_time_ms);
|
||||
|
@ -26,6 +26,7 @@
|
||||
#define SHARE_VM_GC_G1_G1GCPHASETIMES_HPP
|
||||
|
||||
#include "gc/shared/referenceProcessorPhaseTimes.hpp"
|
||||
#include "gc/shared/weakProcessorPhaseTimes.hpp"
|
||||
#include "logging/logLevel.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
@ -127,9 +128,6 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
|
||||
double _cur_clear_ct_time_ms;
|
||||
double _cur_expand_heap_time_ms;
|
||||
double _cur_ref_proc_time_ms;
|
||||
double _cur_ref_enq_time_ms;
|
||||
|
||||
double _cur_weak_ref_proc_time_ms;
|
||||
|
||||
double _cur_collection_start_sec;
|
||||
double _root_region_scan_wait_time_ms;
|
||||
@ -163,6 +161,7 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
|
||||
double _cur_verify_after_time_ms;
|
||||
|
||||
ReferenceProcessorPhaseTimes _ref_phase_times;
|
||||
WeakProcessorPhaseTimes _weak_phase_times;
|
||||
|
||||
double worker_time(GCParPhases phase, uint worker);
|
||||
void note_gc_end();
|
||||
@ -257,10 +256,6 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
|
||||
_cur_ref_proc_time_ms = ms;
|
||||
}
|
||||
|
||||
void record_weak_ref_proc_time(double ms) {
|
||||
_cur_weak_ref_proc_time_ms = ms;
|
||||
}
|
||||
|
||||
void record_root_region_scan_wait_time(double time_ms) {
|
||||
_root_region_scan_wait_time_ms = time_ms;
|
||||
}
|
||||
@ -365,6 +360,8 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
|
||||
}
|
||||
|
||||
ReferenceProcessorPhaseTimes* ref_phase_times() { return &_ref_phase_times; }
|
||||
|
||||
WeakProcessorPhaseTimes* weak_phase_times() { return &_weak_phase_times; }
|
||||
};
|
||||
|
||||
class G1EvacPhaseWithTrimTimeTracker : public StackObj {
|
||||
|
@ -40,7 +40,6 @@
|
||||
#include "gc/g1/heapRegion.inline.hpp"
|
||||
#include "gc/shared/oopStorageParState.hpp"
|
||||
#include "gc/shared/referenceProcessor.hpp"
|
||||
#include "gc/shared/weakProcessor.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "runtime/mutex.hpp"
|
||||
#include "services/management.hpp"
|
||||
@ -314,16 +313,6 @@ void G1RootProcessor::process_code_cache_roots(CodeBlobClosure* code_closure,
|
||||
}
|
||||
}
|
||||
|
||||
void G1RootProcessor::process_full_gc_weak_roots(OopClosure* oops) {
|
||||
if (!_process_strong_tasks.is_task_claimed(G1RP_PS_refProcessor_oops_do)) {
|
||||
_g1h->ref_processor_stw()->weak_oops_do(oops);
|
||||
}
|
||||
|
||||
if (!_process_strong_tasks.is_task_claimed(G1RP_PS_weakProcessor_oops_do)) {
|
||||
WeakProcessor::oops_do(oops);
|
||||
}
|
||||
}
|
||||
|
||||
uint G1RootProcessor::n_workers() const {
|
||||
return _srs.n_threads();
|
||||
}
|
||||
|
@ -68,7 +68,6 @@ class G1RootProcessor : public StackObj {
|
||||
G1RP_PS_aot_oops_do,
|
||||
G1RP_PS_filter_satb_buffers,
|
||||
G1RP_PS_refProcessor_oops_do,
|
||||
G1RP_PS_weakProcessor_oops_do,
|
||||
// Leave this one last.
|
||||
G1RP_PS_NumElements
|
||||
};
|
||||
@ -122,10 +121,6 @@ public:
|
||||
CLDClosure* clds,
|
||||
CodeBlobClosure* blobs);
|
||||
|
||||
// Apply closure to weak roots in the system. Used during the adjust phase
|
||||
// for the Full GC.
|
||||
void process_full_gc_weak_roots(OopClosure* oops);
|
||||
|
||||
// Number of worker threads used by the root processor.
|
||||
uint n_workers() const;
|
||||
};
|
||||
|
@ -23,24 +23,107 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "gc/shared/oopStorage.inline.hpp"
|
||||
#include "gc/shared/oopStorageParState.inline.hpp"
|
||||
#include "gc/shared/weakProcessor.hpp"
|
||||
#include "prims/jvmtiExport.hpp"
|
||||
#include "runtime/jniHandles.hpp"
|
||||
#include "gc/shared/weakProcessor.inline.hpp"
|
||||
#include "gc/shared/weakProcessorPhases.hpp"
|
||||
#include "gc/shared/weakProcessorPhaseTimes.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "memory/iterator.hpp"
|
||||
#include "runtime/globals.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
#if INCLUDE_JFR
|
||||
#include "jfr/jfr.hpp"
|
||||
#endif
|
||||
|
||||
void WeakProcessor::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive) {
|
||||
JNIHandles::weak_oops_do(is_alive, keep_alive);
|
||||
JvmtiExport::weak_oops_do(is_alive, keep_alive);
|
||||
SystemDictionary::vm_weak_oop_storage()->weak_oops_do(is_alive, keep_alive);
|
||||
JFR_ONLY(Jfr::weak_oops_do(is_alive, keep_alive);)
|
||||
FOR_EACH_WEAK_PROCESSOR_PHASE(phase) {
|
||||
if (WeakProcessorPhases::is_serial(phase)) {
|
||||
WeakProcessorPhases::processor(phase)(is_alive, keep_alive);
|
||||
} else {
|
||||
WeakProcessorPhases::oop_storage(phase)->weak_oops_do(is_alive, keep_alive);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WeakProcessor::oops_do(OopClosure* closure) {
|
||||
AlwaysTrueClosure always_true;
|
||||
weak_oops_do(&always_true, closure);
|
||||
}
|
||||
|
||||
uint WeakProcessor::ergo_workers(uint max_workers) {
|
||||
// Ignore ParallelRefProcEnabled; that's for j.l.r.Reference processing.
|
||||
if (ReferencesPerThread == 0) {
|
||||
// Configuration says always use all the threads.
|
||||
return max_workers;
|
||||
}
|
||||
|
||||
// One thread per ReferencesPerThread references (or fraction thereof)
|
||||
// in the various OopStorage objects, bounded by max_threads.
|
||||
//
|
||||
// Serial phases are ignored in this calculation, because of the
|
||||
// cost of running unnecessary threads. These phases are normally
|
||||
// small or empty (assuming they are configured to exist at all),
|
||||
// and development oriented, so not allocating any threads
|
||||
// specifically for them is okay.
|
||||
size_t ref_count = 0;
|
||||
FOR_EACH_WEAK_PROCESSOR_OOP_STORAGE_PHASE(phase) {
|
||||
ref_count += WeakProcessorPhases::oop_storage(phase)->allocation_count();
|
||||
}
|
||||
|
||||
// +1 to (approx) round up the ref per thread division.
|
||||
size_t nworkers = 1 + (ref_count / ReferencesPerThread);
|
||||
nworkers = MIN2(nworkers, static_cast<size_t>(max_workers));
|
||||
return static_cast<uint>(nworkers);
|
||||
}
|
||||
|
||||
void WeakProcessor::Task::initialize() {
|
||||
assert(_nworkers != 0, "must be");
|
||||
assert(_phase_times == NULL || _nworkers <= _phase_times->max_threads(),
|
||||
"nworkers (%u) exceeds max threads (%u)",
|
||||
_nworkers, _phase_times->max_threads());
|
||||
|
||||
if (_phase_times) {
|
||||
_phase_times->set_active_workers(_nworkers);
|
||||
}
|
||||
|
||||
uint storage_count = WeakProcessorPhases::oop_storage_phase_count;
|
||||
_storage_states = NEW_C_HEAP_ARRAY(StorageState, storage_count, mtGC);
|
||||
|
||||
StorageState* states = _storage_states;
|
||||
FOR_EACH_WEAK_PROCESSOR_OOP_STORAGE_PHASE(phase) {
|
||||
OopStorage* storage = WeakProcessorPhases::oop_storage(phase);
|
||||
new (states++) StorageState(storage, _nworkers);
|
||||
}
|
||||
}
|
||||
|
||||
WeakProcessor::Task::Task(uint nworkers) :
|
||||
_phase_times(NULL),
|
||||
_nworkers(nworkers),
|
||||
_serial_phases_done(WeakProcessorPhases::serial_phase_count),
|
||||
_storage_states(NULL)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
WeakProcessor::Task::Task(WeakProcessorPhaseTimes* phase_times, uint nworkers) :
|
||||
_phase_times(phase_times),
|
||||
_nworkers(nworkers),
|
||||
_serial_phases_done(WeakProcessorPhases::serial_phase_count),
|
||||
_storage_states(NULL)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
WeakProcessor::Task::~Task() {
|
||||
if (_storage_states != NULL) {
|
||||
StorageState* states = _storage_states;
|
||||
FOR_EACH_WEAK_PROCESSOR_OOP_STORAGE_PHASE(phase) {
|
||||
states->StorageState::~StorageState();
|
||||
++states;
|
||||
}
|
||||
FREE_C_HEAP_ARRAY(StorageState, _storage_states);
|
||||
}
|
||||
}
|
||||
|
||||
void WeakProcessor::GangTask::work(uint worker_id) {
|
||||
_erased_do_work(this, worker_id);
|
||||
}
|
||||
|
@ -25,8 +25,12 @@
|
||||
#ifndef SHARE_VM_GC_SHARED_WEAKPROCESSOR_HPP
|
||||
#define SHARE_VM_GC_SHARED_WEAKPROCESSOR_HPP
|
||||
|
||||
#include "gc/shared/oopStorageParState.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "memory/iterator.hpp"
|
||||
|
||||
class WeakProcessorPhaseTimes;
|
||||
class WorkGang;
|
||||
|
||||
// Helper class to aid in root scanning and cleaning of weak oops in the VM.
|
||||
//
|
||||
@ -41,6 +45,51 @@ public:
|
||||
|
||||
// Visit all oop*s and apply the given closure.
|
||||
static void oops_do(OopClosure* closure);
|
||||
|
||||
// Parallel version. Uses ergo_workers(), active workers, and
|
||||
// phase_time's max_threads to determine the number of threads to use.
|
||||
// IsAlive must be derived from BoolObjectClosure.
|
||||
// KeepAlive must be derived from OopClosure.
|
||||
template<typename IsAlive, typename KeepAlive>
|
||||
static void weak_oops_do(WorkGang* workers,
|
||||
IsAlive* is_alive,
|
||||
KeepAlive* keep_alive,
|
||||
WeakProcessorPhaseTimes* phase_times);
|
||||
|
||||
// Convenience parallel version. Uses ergo_workers() and active workers
|
||||
// to determine the number of threads to run. Implicitly logs phase times.
|
||||
// IsAlive must be derived from BoolObjectClosure.
|
||||
// KeepAlive must be derived from OopClosure.
|
||||
template<typename IsAlive, typename KeepAlive>
|
||||
static void weak_oops_do(WorkGang* workers,
|
||||
IsAlive* is_alive,
|
||||
KeepAlive* keep_alive,
|
||||
uint indent_log);
|
||||
|
||||
static uint ergo_workers(uint max_workers);
|
||||
class Task;
|
||||
|
||||
private:
|
||||
class GangTask;
|
||||
};
|
||||
|
||||
class WeakProcessor::Task {
|
||||
typedef OopStorage::ParState<false, false> StorageState;
|
||||
|
||||
WeakProcessorPhaseTimes* _phase_times;
|
||||
uint _nworkers;
|
||||
SubTasksDone _serial_phases_done;
|
||||
StorageState* _storage_states;
|
||||
|
||||
void initialize();
|
||||
|
||||
public:
|
||||
Task(uint nworkers); // No time tracking.
|
||||
Task(WeakProcessorPhaseTimes* phase_times, uint nworkers);
|
||||
~Task();
|
||||
|
||||
template<typename IsAlive, typename KeepAlive>
|
||||
void work(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive);
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_GC_SHARED_WEAKPROCESSOR_HPP
|
||||
|
119
src/hotspot/share/gc/shared/weakProcessor.inline.hpp
Normal file
119
src/hotspot/share/gc/shared/weakProcessor.inline.hpp
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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_VM_GC_SHARED_WEAKPROCESSOR_INLINE_HPP
|
||||
#define SHARE_VM_GC_SHARED_WEAKPROCESSOR_INLINE_HPP
|
||||
|
||||
#include "gc/shared/oopStorage.inline.hpp"
|
||||
#include "gc/shared/oopStorageParState.inline.hpp"
|
||||
#include "gc/shared/weakProcessor.hpp"
|
||||
#include "gc/shared/weakProcessorPhases.hpp"
|
||||
#include "gc/shared/weakProcessorPhaseTimes.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
|
||||
class BoolObjectClosure;
|
||||
class OopClosure;
|
||||
|
||||
template<typename IsAlive, typename KeepAlive>
|
||||
void WeakProcessor::Task::work(uint worker_id,
|
||||
IsAlive* is_alive,
|
||||
KeepAlive* keep_alive) {
|
||||
assert(worker_id < _nworkers,
|
||||
"worker_id (%u) exceeds task's configured workers (%u)",
|
||||
worker_id, _nworkers);
|
||||
|
||||
FOR_EACH_WEAK_PROCESSOR_PHASE(phase) {
|
||||
if (WeakProcessorPhases::is_serial(phase)) {
|
||||
uint serial_index = WeakProcessorPhases::serial_index(phase);
|
||||
if (!_serial_phases_done.is_task_claimed(serial_index)) {
|
||||
WeakProcessorPhaseTimeTracker pt(_phase_times, phase);
|
||||
WeakProcessorPhases::processor(phase)(is_alive, keep_alive);
|
||||
}
|
||||
} else {
|
||||
WeakProcessorPhaseTimeTracker pt(_phase_times, phase, worker_id);
|
||||
uint storage_index = WeakProcessorPhases::oop_storage_index(phase);
|
||||
_storage_states[storage_index].weak_oops_do(is_alive, keep_alive);
|
||||
}
|
||||
}
|
||||
|
||||
_serial_phases_done.all_tasks_completed(_nworkers);
|
||||
}
|
||||
|
||||
class WeakProcessor::GangTask : public AbstractGangTask {
|
||||
Task _task;
|
||||
BoolObjectClosure* _is_alive;
|
||||
OopClosure* _keep_alive;
|
||||
void (*_erased_do_work)(GangTask* task, uint worker_id);
|
||||
|
||||
template<typename IsAlive, typename KeepAlive>
|
||||
static void erased_do_work(GangTask* task, uint worker_id) {
|
||||
task->_task.work(worker_id,
|
||||
static_cast<IsAlive*>(task->_is_alive),
|
||||
static_cast<KeepAlive*>(task->_keep_alive));
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename IsAlive, typename KeepAlive>
|
||||
GangTask(const char* name,
|
||||
IsAlive* is_alive,
|
||||
KeepAlive* keep_alive,
|
||||
WeakProcessorPhaseTimes* phase_times,
|
||||
uint nworkers) :
|
||||
AbstractGangTask(name),
|
||||
_task(phase_times, nworkers),
|
||||
_is_alive(is_alive),
|
||||
_keep_alive(keep_alive),
|
||||
_erased_do_work(&erased_do_work<IsAlive, KeepAlive>)
|
||||
{}
|
||||
|
||||
virtual void work(uint worker_id);
|
||||
};
|
||||
|
||||
template<typename IsAlive, typename KeepAlive>
|
||||
void WeakProcessor::weak_oops_do(WorkGang* workers,
|
||||
IsAlive* is_alive,
|
||||
KeepAlive* keep_alive,
|
||||
WeakProcessorPhaseTimes* phase_times) {
|
||||
WeakProcessorTimeTracker tt(phase_times);
|
||||
|
||||
uint nworkers = ergo_workers(MIN2(workers->active_workers(),
|
||||
phase_times->max_threads()));
|
||||
|
||||
GangTask task("Weak Processor", is_alive, keep_alive, phase_times, nworkers);
|
||||
workers->run_task(&task, nworkers);
|
||||
}
|
||||
|
||||
template<typename IsAlive, typename KeepAlive>
|
||||
void WeakProcessor::weak_oops_do(WorkGang* workers,
|
||||
IsAlive* is_alive,
|
||||
KeepAlive* keep_alive,
|
||||
uint indent_log) {
|
||||
uint nworkers = ergo_workers(workers->active_workers());
|
||||
WeakProcessorPhaseTimes pt(nworkers);
|
||||
weak_oops_do(workers, is_alive, keep_alive, &pt);
|
||||
pt.log_print_phases(indent_log);
|
||||
}
|
||||
|
||||
#endif // SHARE_VM_GC_SHARED_WEAKPROCESSOR_INLINE_HPP
|
268
src/hotspot/share/gc/shared/weakProcessorPhaseTimes.cpp
Normal file
268
src/hotspot/share/gc/shared/weakProcessorPhaseTimes.cpp
Normal file
@ -0,0 +1,268 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/shared/weakProcessorPhases.hpp"
|
||||
#include "gc/shared/weakProcessorPhaseTimes.hpp"
|
||||
#include "gc/shared/workerDataArray.inline.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "logging/logStream.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/ticks.hpp"
|
||||
|
||||
static uint phase_index(WeakProcessorPhase phase) {
|
||||
return WeakProcessorPhases::index(phase);
|
||||
}
|
||||
|
||||
static bool is_serial_phase(WeakProcessorPhase phase) {
|
||||
return WeakProcessorPhases::is_serial(phase);
|
||||
}
|
||||
|
||||
static void assert_oop_storage_phase(WeakProcessorPhase phase) {
|
||||
assert(WeakProcessorPhases::is_oop_storage(phase),
|
||||
"Not an oop_storage phase %u", phase_index(phase));
|
||||
}
|
||||
|
||||
const double uninitialized_time = -1.0;
|
||||
|
||||
#ifdef ASSERT
|
||||
static bool is_initialized_time(double t) { return t >= 0.0; }
|
||||
#endif // ASSERT
|
||||
|
||||
static void reset_times(double* times, size_t ntimes) {
|
||||
for (size_t i = 0; i < ntimes; ++i) {
|
||||
times[i] = uninitialized_time;
|
||||
}
|
||||
}
|
||||
|
||||
WeakProcessorPhaseTimes::WeakProcessorPhaseTimes(uint max_threads) :
|
||||
_max_threads(max_threads),
|
||||
_active_workers(0),
|
||||
_total_time_sec(uninitialized_time),
|
||||
_worker_phase_times_sec()
|
||||
{
|
||||
assert(_max_threads > 0, "max_threads must not be zero");
|
||||
|
||||
reset_times(_phase_times_sec, ARRAY_SIZE(_phase_times_sec));
|
||||
|
||||
if (_max_threads > 1) {
|
||||
WorkerDataArray<double>** wpt = _worker_phase_times_sec;
|
||||
FOR_EACH_WEAK_PROCESSOR_OOP_STORAGE_PHASE(phase) {
|
||||
const char* description = WeakProcessorPhases::description(phase);
|
||||
*wpt++ = new WorkerDataArray<double>(_max_threads, description);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WeakProcessorPhaseTimes::~WeakProcessorPhaseTimes() {
|
||||
for (size_t i = 0; i < ARRAY_SIZE(_worker_phase_times_sec); ++i) {
|
||||
delete _worker_phase_times_sec[i];
|
||||
}
|
||||
}
|
||||
|
||||
uint WeakProcessorPhaseTimes::max_threads() const { return _max_threads; }
|
||||
|
||||
uint WeakProcessorPhaseTimes::active_workers() const {
|
||||
assert(_active_workers != 0, "active workers not set");
|
||||
return _active_workers;
|
||||
}
|
||||
|
||||
void WeakProcessorPhaseTimes::set_active_workers(uint n) {
|
||||
assert(_active_workers == 0, "active workers already set");
|
||||
assert(n > 0, "active workers must be non-zero");
|
||||
assert(n <= _max_threads, "active workers must not exceed max threads");
|
||||
_active_workers = n;
|
||||
}
|
||||
|
||||
void WeakProcessorPhaseTimes::reset() {
|
||||
_active_workers = 0;
|
||||
_total_time_sec = uninitialized_time;
|
||||
reset_times(_phase_times_sec, ARRAY_SIZE(_phase_times_sec));
|
||||
if (_max_threads > 1) {
|
||||
for (size_t i = 0; i < ARRAY_SIZE(_worker_phase_times_sec); ++i) {
|
||||
_worker_phase_times_sec[i]->reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double WeakProcessorPhaseTimes::total_time_sec() const {
|
||||
assert(is_initialized_time(_total_time_sec), "Total time not set");
|
||||
return _total_time_sec;
|
||||
}
|
||||
|
||||
void WeakProcessorPhaseTimes::record_total_time_sec(double time_sec) {
|
||||
assert(!is_initialized_time(_total_time_sec), "Already set total time");
|
||||
_total_time_sec = time_sec;
|
||||
}
|
||||
|
||||
double WeakProcessorPhaseTimes::phase_time_sec(WeakProcessorPhase phase) const {
|
||||
assert(is_initialized_time(_phase_times_sec[phase_index(phase)]),
|
||||
"phase time not set %u", phase_index(phase));
|
||||
return _phase_times_sec[phase_index(phase)];
|
||||
}
|
||||
|
||||
void WeakProcessorPhaseTimes::record_phase_time_sec(WeakProcessorPhase phase, double time_sec) {
|
||||
assert(!is_initialized_time(_phase_times_sec[phase_index(phase)]),
|
||||
"Already set time for phase %u", phase_index(phase));
|
||||
_phase_times_sec[phase_index(phase)] = time_sec;
|
||||
}
|
||||
|
||||
WorkerDataArray<double>* WeakProcessorPhaseTimes::worker_data(WeakProcessorPhase phase) const {
|
||||
assert_oop_storage_phase(phase);
|
||||
assert(active_workers() > 1, "No worker data when single-threaded");
|
||||
return _worker_phase_times_sec[WeakProcessorPhases::oop_storage_index(phase)];
|
||||
}
|
||||
|
||||
double WeakProcessorPhaseTimes::worker_time_sec(uint worker_id, WeakProcessorPhase phase) const {
|
||||
assert(worker_id < active_workers(),
|
||||
"invalid worker id %u for %u", worker_id, active_workers());
|
||||
if (active_workers() == 1) {
|
||||
return phase_time_sec(phase);
|
||||
} else {
|
||||
return worker_data(phase)->get(worker_id);
|
||||
}
|
||||
}
|
||||
|
||||
void WeakProcessorPhaseTimes::record_worker_time_sec(uint worker_id,
|
||||
WeakProcessorPhase phase,
|
||||
double time_sec) {
|
||||
if (active_workers() == 1) {
|
||||
record_phase_time_sec(phase, time_sec);
|
||||
} else {
|
||||
worker_data(phase)->set(worker_id, time_sec);
|
||||
}
|
||||
}
|
||||
|
||||
static double elapsed_time_sec(Ticks start_time, Ticks end_time) {
|
||||
return (end_time - start_time).seconds();
|
||||
}
|
||||
|
||||
WeakProcessorTimeTracker::WeakProcessorTimeTracker(WeakProcessorPhaseTimes* times) :
|
||||
_times(times),
|
||||
_start_time(Ticks::now())
|
||||
{}
|
||||
|
||||
WeakProcessorTimeTracker::~WeakProcessorTimeTracker() {
|
||||
if (_times != NULL) {
|
||||
Ticks end_time = Ticks::now();
|
||||
_times->record_total_time_sec(elapsed_time_sec(_start_time, end_time));
|
||||
}
|
||||
}
|
||||
|
||||
WeakProcessorPhaseTimeTracker::WeakProcessorPhaseTimeTracker(WeakProcessorPhaseTimes* times,
|
||||
WeakProcessorPhase phase,
|
||||
uint worker_id) :
|
||||
_times(times),
|
||||
_phase(phase),
|
||||
_worker_id(worker_id),
|
||||
_start_time(Ticks::now())
|
||||
{
|
||||
assert_oop_storage_phase(_phase);
|
||||
assert(_times == NULL || worker_id < _times->active_workers(),
|
||||
"Invalid worker_id %u", worker_id);
|
||||
}
|
||||
|
||||
WeakProcessorPhaseTimeTracker::WeakProcessorPhaseTimeTracker(WeakProcessorPhaseTimes* times,
|
||||
WeakProcessorPhase phase) :
|
||||
_times(times),
|
||||
_phase(phase),
|
||||
_worker_id(0),
|
||||
_start_time(Ticks::now())
|
||||
{
|
||||
assert(is_serial_phase(phase), "Not a serial phase %u", phase_index(phase));
|
||||
}
|
||||
|
||||
WeakProcessorPhaseTimeTracker::~WeakProcessorPhaseTimeTracker() {
|
||||
if (_times != NULL) {
|
||||
double time_sec = elapsed_time_sec(_start_time, Ticks::now());
|
||||
if (is_serial_phase(_phase)) {
|
||||
_times->record_phase_time_sec(_phase, time_sec);
|
||||
} else {
|
||||
_times->record_worker_time_sec(_worker_id, _phase, time_sec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Printing times
|
||||
|
||||
const char* const indents[] = {"", " ", " ", " ", " "};
|
||||
const size_t max_indents_index = ARRAY_SIZE(indents) - 1;
|
||||
|
||||
static const char* indent_str(size_t i) {
|
||||
return indents[MIN2(i, max_indents_index)];
|
||||
}
|
||||
|
||||
#define TIME_FORMAT "%.1lfms"
|
||||
|
||||
void WeakProcessorPhaseTimes::log_st_phase(WeakProcessorPhase phase,
|
||||
uint indent) const {
|
||||
log_debug(gc, phases)("%s%s: " TIME_FORMAT,
|
||||
indent_str(indent),
|
||||
WeakProcessorPhases::description(phase),
|
||||
phase_time_sec(phase) * MILLIUNITS);
|
||||
}
|
||||
|
||||
void WeakProcessorPhaseTimes::log_mt_phase_summary(WeakProcessorPhase phase,
|
||||
uint indent) const {
|
||||
LogTarget(Debug, gc, phases) lt;
|
||||
LogStream ls(lt);
|
||||
ls.print("%s", indents[indent]);
|
||||
worker_data(phase)->print_summary_on(&ls, true);
|
||||
}
|
||||
|
||||
void WeakProcessorPhaseTimes::log_mt_phase_details(WeakProcessorPhase phase,
|
||||
uint indent) const {
|
||||
LogTarget(Trace, gc, phases) lt;
|
||||
LogStream ls(lt);
|
||||
ls.print("%s", indents[indent]);
|
||||
worker_data(phase)->print_details_on(&ls);
|
||||
}
|
||||
|
||||
void WeakProcessorPhaseTimes::log_print_phases(uint indent) const {
|
||||
if (log_is_enabled(Debug, gc, phases)) {
|
||||
bool details_enabled = log_is_enabled(Trace, gc, phases);
|
||||
FOR_EACH_WEAK_PROCESSOR_PHASE(phase) {
|
||||
if (is_serial_phase(phase) || (active_workers() == 1)) {
|
||||
log_st_phase(phase, indent);
|
||||
} else {
|
||||
log_mt_phase_summary(phase, indent);
|
||||
if (details_enabled) {
|
||||
log_mt_phase_details(phase, indent + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WeakProcessorPhaseTimes::log_print(uint indent) const {
|
||||
if (log_is_enabled(Debug, gc, phases)) {
|
||||
log_debug(gc, phases)("%s%s: " TIME_FORMAT,
|
||||
indent_str(indent),
|
||||
"Weak Processing",
|
||||
total_time_sec() * MILLIUNITS);
|
||||
log_print_phases(indent + 1);
|
||||
}
|
||||
}
|
115
src/hotspot/share/gc/shared/weakProcessorPhaseTimes.hpp
Normal file
115
src/hotspot/share/gc/shared/weakProcessorPhaseTimes.hpp
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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_SHARED_WEAKPROCESSORPHASETIMES_HPP
|
||||
#define SHARE_GC_SHARED_WEAKPROCESSORPHASETIMES_HPP
|
||||
|
||||
#include "gc/shared/weakProcessorPhases.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/ticks.hpp"
|
||||
|
||||
template<typename T> class WorkerDataArray;
|
||||
|
||||
class WeakProcessorPhaseTimes : public CHeapObj<mtGC> {
|
||||
uint _max_threads;
|
||||
uint _active_workers;
|
||||
|
||||
// Total time for weak processor.
|
||||
double _total_time_sec;
|
||||
|
||||
// Total time for each serially processed phase. Entries for phases
|
||||
// processed by multiple threads are unused, as are entries for
|
||||
// unexecuted phases.
|
||||
double _phase_times_sec[WeakProcessorPhases::phase_count];
|
||||
|
||||
// Per-worker times, if multiple threads used and the phase was executed.
|
||||
WorkerDataArray<double>* _worker_phase_times_sec[WeakProcessorPhases::oop_storage_phase_count];
|
||||
|
||||
WorkerDataArray<double>* worker_data(WeakProcessorPhase phase) const;
|
||||
|
||||
void log_st_phase(WeakProcessorPhase phase, uint indent) const;
|
||||
void log_mt_phase_summary(WeakProcessorPhase phase, uint indent) const;
|
||||
void log_mt_phase_details(WeakProcessorPhase phase, uint indent) const;
|
||||
|
||||
public:
|
||||
WeakProcessorPhaseTimes(uint max_threads);
|
||||
~WeakProcessorPhaseTimes();
|
||||
|
||||
uint max_threads() const;
|
||||
uint active_workers() const;
|
||||
void set_active_workers(uint n);
|
||||
|
||||
double total_time_sec() const;
|
||||
double phase_time_sec(WeakProcessorPhase phase) const;
|
||||
double worker_time_sec(uint worker_id, WeakProcessorPhase phase) const;
|
||||
|
||||
void record_total_time_sec(double time_sec);
|
||||
void record_phase_time_sec(WeakProcessorPhase phase, double time_sec);
|
||||
void record_worker_time_sec(uint worker_id, WeakProcessorPhase phase, double time_sec);
|
||||
|
||||
void reset();
|
||||
|
||||
void log_print(uint indent = 0) const;
|
||||
void log_print_phases(uint indent = 0) const;
|
||||
};
|
||||
|
||||
// Record total weak processor time and worker count in times.
|
||||
// Does nothing if times is NULL.
|
||||
class WeakProcessorTimeTracker : StackObj {
|
||||
WeakProcessorPhaseTimes* _times;
|
||||
Ticks _start_time;
|
||||
|
||||
public:
|
||||
WeakProcessorTimeTracker(WeakProcessorPhaseTimes* times);
|
||||
~WeakProcessorTimeTracker();
|
||||
};
|
||||
|
||||
// Record phase time contribution for the current thread in phase times.
|
||||
// Does nothing if phase times is NULL.
|
||||
class WeakProcessorPhaseTimeTracker : StackObj {
|
||||
private:
|
||||
WeakProcessorPhaseTimes* _times;
|
||||
WeakProcessorPhase _phase;
|
||||
uint _worker_id;
|
||||
Ticks _start_time;
|
||||
|
||||
public:
|
||||
// For tracking serial phase times.
|
||||
// Precondition: WeakProcessorPhases::is_serial(phase)
|
||||
WeakProcessorPhaseTimeTracker(WeakProcessorPhaseTimes* times,
|
||||
WeakProcessorPhase phase);
|
||||
|
||||
// For tracking possibly parallel phase times (even if processed by
|
||||
// only one thread).
|
||||
// Precondition: WeakProcessorPhases::is_oop_storage(phase)
|
||||
// Precondition: worker_id < times->max_threads().
|
||||
WeakProcessorPhaseTimeTracker(WeakProcessorPhaseTimes* times,
|
||||
WeakProcessorPhase phase,
|
||||
uint worker_id);
|
||||
|
||||
~WeakProcessorPhaseTimeTracker();
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_SHARED_WEAKPROCESSORPHASETIMES_HPP
|
99
src/hotspot/share/gc/shared/weakProcessorPhases.cpp
Normal file
99
src/hotspot/share/gc/shared/weakProcessorPhases.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "gc/shared/weakProcessorPhases.hpp"
|
||||
#include "runtime/jniHandles.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
#if INCLUDE_JFR
|
||||
#include "jfr/jfr.hpp"
|
||||
#endif // INCLUDE_JFR
|
||||
|
||||
#if INCLUDE_JVMTI
|
||||
#include "prims/jvmtiExport.hpp"
|
||||
#endif // INCLUDE_JVMTI
|
||||
|
||||
WeakProcessorPhases::Phase WeakProcessorPhases::phase(uint value) {
|
||||
assert(value < phase_count, "Invalid phase value %u", value);
|
||||
return static_cast<Phase>(value);
|
||||
}
|
||||
|
||||
uint WeakProcessorPhases::index(Phase phase) {
|
||||
uint value = static_cast<uint>(phase);
|
||||
assert(value < phase_count, "Invalid phase %u", value);
|
||||
return value;
|
||||
}
|
||||
|
||||
uint WeakProcessorPhases::serial_index(Phase phase) {
|
||||
assert(is_serial(phase), "not serial phase %u", index(phase));
|
||||
return index(phase) - serial_phase_start;
|
||||
}
|
||||
|
||||
uint WeakProcessorPhases::oop_storage_index(Phase phase) {
|
||||
assert(is_oop_storage(phase), "not oop storage phase %u", index(phase));
|
||||
return index(phase) - oop_storage_phase_start;
|
||||
}
|
||||
|
||||
bool WeakProcessorPhases::is_serial(Phase phase) {
|
||||
return (index(phase) - serial_phase_start) < serial_phase_count;
|
||||
}
|
||||
|
||||
bool WeakProcessorPhases::is_oop_storage(Phase phase) {
|
||||
return (index(phase) - oop_storage_phase_start) < oop_storage_phase_count;
|
||||
}
|
||||
|
||||
const char* WeakProcessorPhases::description(Phase phase) {
|
||||
switch (phase) {
|
||||
JVMTI_ONLY(case jvmti: return "JVMTI weak processing";)
|
||||
JFR_ONLY(case jfr: return "JFR weak processing";)
|
||||
case jni: return "JNI weak processing";
|
||||
case vm: return "VM weak processing";
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
return "Invalid weak processing phase";
|
||||
}
|
||||
}
|
||||
|
||||
WeakProcessorPhases::Processor WeakProcessorPhases::processor(Phase phase) {
|
||||
switch (phase) {
|
||||
JVMTI_ONLY(case jvmti: return &JvmtiExport::weak_oops_do;)
|
||||
JFR_ONLY(case jfr: return &Jfr::weak_oops_do;)
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
OopStorage* WeakProcessorPhases::oop_storage(Phase phase) {
|
||||
switch (phase) {
|
||||
case jni: return JNIHandles::weak_global_handles();
|
||||
case vm: return SystemDictionary::vm_weak_oop_storage();
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
return NULL;
|
||||
}
|
||||
}
|
83
src/hotspot/share/gc/shared/weakProcessorPhases.hpp
Normal file
83
src/hotspot/share/gc/shared/weakProcessorPhases.hpp
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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_SHARED_WEAKPROCESSORPHASES_HPP
|
||||
#define SHARE_GC_SHARED_WEAKPROCESSORPHASES_HPP
|
||||
|
||||
#include "memory/allocation.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
class BoolObjectClosure;
|
||||
class OopClosure;
|
||||
class OopStorage;
|
||||
|
||||
class WeakProcessorPhases : AllStatic {
|
||||
public:
|
||||
typedef void (*Processor)(BoolObjectClosure*, OopClosure*);
|
||||
|
||||
enum Phase {
|
||||
// Serial phases.
|
||||
JVMTI_ONLY(jvmti COMMA)
|
||||
JFR_ONLY(jfr COMMA)
|
||||
|
||||
// OopStorage phases.
|
||||
jni,
|
||||
vm
|
||||
};
|
||||
|
||||
static const uint serial_phase_start = 0;
|
||||
static const uint serial_phase_count = jni;
|
||||
static const uint oop_storage_phase_start = serial_phase_count;
|
||||
static const uint oop_storage_phase_count = (vm + 1) - oop_storage_phase_start;
|
||||
static const uint phase_count = serial_phase_count + oop_storage_phase_count;
|
||||
|
||||
static Phase phase(uint value);
|
||||
static uint index(Phase phase);
|
||||
// Indexes relative to the corresponding phase_start constant.
|
||||
static uint serial_index(Phase phase);
|
||||
static uint oop_storage_index(Phase phase);
|
||||
|
||||
static bool is_serial(Phase phase);
|
||||
static bool is_oop_storage(Phase phase);
|
||||
|
||||
static const char* description(Phase phase);
|
||||
static Processor processor(Phase phase); // Precondition: is_serial(phase)
|
||||
static OopStorage* oop_storage(Phase phase); // Precondition: is_oop_storage(phase)
|
||||
};
|
||||
|
||||
typedef WeakProcessorPhases::Phase WeakProcessorPhase;
|
||||
|
||||
#define FOR_EACH_WEAK_PROCESSOR_PHASE(P) \
|
||||
for (WeakProcessorPhase P = static_cast<WeakProcessorPhase>(0); \
|
||||
static_cast<uint>(P) < WeakProcessorPhases::phase_count; \
|
||||
P = static_cast<WeakProcessorPhase>(static_cast<uint>(P) + 1))
|
||||
|
||||
#define FOR_EACH_WEAK_PROCESSOR_OOP_STORAGE_PHASE(P) \
|
||||
for (WeakProcessorPhase P = static_cast<WeakProcessorPhase>(WeakProcessorPhases::oop_storage_phase_start); \
|
||||
static_cast<uint>(P) < (WeakProcessorPhases::oop_storage_phase_start + \
|
||||
WeakProcessorPhases::oop_storage_phase_count); \
|
||||
P = static_cast<WeakProcessorPhase>(static_cast<uint>(P) + 1))
|
||||
|
||||
#endif // SHARE_GC_SHARED_WEAKPROCESSORPHASES_HPP
|
@ -462,7 +462,7 @@ void SubTasksDone::all_tasks_completed(uint n_threads) {
|
||||
|
||||
|
||||
SubTasksDone::~SubTasksDone() {
|
||||
if (_tasks != NULL) FREE_C_HEAP_ARRAY(jint, _tasks);
|
||||
if (_tasks != NULL) FREE_C_HEAP_ARRAY(uint, _tasks);
|
||||
}
|
||||
|
||||
// *** SequentialSubTasksDone
|
||||
|
Loading…
Reference in New Issue
Block a user