hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp
ConcurrentMark::ConcurrentMark(ReservedSpace rs,
int max_regions) :
{- -------------------------------------------
(1)
---------------------------------------- -}
_markBitMap1(rs, MinObjAlignment - 1),
_markBitMap2(rs, MinObjAlignment - 1),
_parallel_marking_threads(0),
_sleep_factor(0.0),
_marking_task_overhead(1.0),
_cleanup_sleep_factor(0.0),
_cleanup_task_overhead(1.0),
_cleanup_list("Cleanup List"),
_region_bm(max_regions, false /* in_resource_area*/),
_card_bm((rs.size() + CardTableModRefBS::card_size - 1) >>
CardTableModRefBS::card_shift,
false /* in_resource_area*/),
_prevMarkBitMap(&_markBitMap1),
_nextMarkBitMap(&_markBitMap2),
_at_least_one_mark_complete(false),
_markStack(this),
_regionStack(),
// _finger set in set_non_marking_state
_max_task_num(MAX2(ParallelGCThreads, (size_t)1)),
// _active_tasks set in set_non_marking_state
// _tasks set inside the constructor
_task_queues(new CMTaskQueueSet((int) _max_task_num)),
_terminator(ParallelTaskTerminator((int) _max_task_num, _task_queues)),
_has_overflown(false),
_concurrent(false),
_has_aborted(false),
_restart_for_overflow(false),
_concurrent_marking_in_progress(false),
_should_gray_objects(false),
// _verbose_level set below
_init_times(),
_remark_times(), _remark_mark_times(), _remark_weak_ref_times(),
_cleanup_times(),
_total_counting_time(0.0),
_total_rs_scrub_time(0.0),
_parallel_workers(NULL)
{
CMVerboseLevel verbose_level =
(CMVerboseLevel) G1MarkingVerboseLevel;
if (verbose_level < no_verbose)
verbose_level = no_verbose;
if (verbose_level > high_verbose)
verbose_level = high_verbose;
_verbose_level = verbose_level;
if (verbose_low())
gclog_or_tty->print_cr("[global] init, heap start = "PTR_FORMAT", "
"heap end = "PTR_FORMAT, _heap_start, _heap_end);
_markStack.allocate(MarkStackSize);
_regionStack.allocate(G1MarkRegionStackSize);
// Create & start a ConcurrentMark thread.
_cmThread = new ConcurrentMarkThread(this);
assert(cmThread() != NULL, "CM Thread should have been created");
assert(cmThread()->cm() != NULL, "CM Thread should refer to this cm");
_g1h = G1CollectedHeap::heap();
assert(CGC_lock != NULL, "Where's the CGC_lock?");
assert(_markBitMap1.covers(rs), "_markBitMap1 inconsistency");
assert(_markBitMap2.covers(rs), "_markBitMap2 inconsistency");
SATBMarkQueueSet& satb_qs = JavaThread::satb_mark_queue_set();
satb_qs.set_buffer_size(G1SATBBufferSize);
_tasks = NEW_C_HEAP_ARRAY(CMTask*, _max_task_num);
_accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_task_num);
// so that the assertion in MarkingTaskQueue::task_queue doesn't fail
_active_tasks = _max_task_num;
for (int i = 0; i < (int) _max_task_num; ++i) {
CMTaskQueue* task_queue = new CMTaskQueue();
task_queue->initialize();
_task_queues->register_queue(i, task_queue);
_tasks[i] = new CMTask(i, this, task_queue, _task_queues);
_accum_task_vtime[i] = 0.0;
}
if (ConcGCThreads > ParallelGCThreads) {
vm_exit_during_initialization("Can't have more ConcGCThreads "
"than ParallelGCThreads.");
}
if (ParallelGCThreads == 0) {
// if we are not running with any parallel GC threads we will not
// spawn any marking threads either
_parallel_marking_threads = 0;
_sleep_factor = 0.0;
_marking_task_overhead = 1.0;
} else {
if (ConcGCThreads > 0) {
// notice that ConcGCThreads overwrites G1MarkingOverheadPercent
// if both are set
_parallel_marking_threads = ConcGCThreads;
_sleep_factor = 0.0;
_marking_task_overhead = 1.0;
} else if (G1MarkingOverheadPercent > 0) {
// we will calculate the number of parallel marking threads
// based on a target overhead with respect to the soft real-time
// goal
double marking_overhead = (double) G1MarkingOverheadPercent / 100.0;
double overall_cm_overhead =
(double) MaxGCPauseMillis * marking_overhead /
(double) GCPauseIntervalMillis;
double cpu_ratio = 1.0 / (double) os::processor_count();
double marking_thread_num = ceil(overall_cm_overhead / cpu_ratio);
double marking_task_overhead =
overall_cm_overhead / marking_thread_num *
(double) os::processor_count();
double sleep_factor =
(1.0 - marking_task_overhead) / marking_task_overhead;
_parallel_marking_threads = (size_t) marking_thread_num;
_sleep_factor = sleep_factor;
_marking_task_overhead = marking_task_overhead;
} else {
_parallel_marking_threads = MAX2((ParallelGCThreads + 2) / 4, (size_t)1);
_sleep_factor = 0.0;
_marking_task_overhead = 1.0;
}
if (parallel_marking_threads() > 1)
_cleanup_task_overhead = 1.0;
else
_cleanup_task_overhead = marking_task_overhead();
_cleanup_sleep_factor =
(1.0 - cleanup_task_overhead()) / cleanup_task_overhead();
#if 0
gclog_or_tty->print_cr("Marking Threads %d", parallel_marking_threads());
gclog_or_tty->print_cr("CM Marking Task Overhead %1.4lf", marking_task_overhead());
gclog_or_tty->print_cr("CM Sleep Factor %1.4lf", sleep_factor());
gclog_or_tty->print_cr("CL Marking Task Overhead %1.4lf", cleanup_task_overhead());
gclog_or_tty->print_cr("CL Sleep Factor %1.4lf", cleanup_sleep_factor());
#endif
guarantee(parallel_marking_threads() > 0, "peace of mind");
_parallel_workers = new FlexibleWorkGang("G1 Parallel Marking Threads",
(int) _parallel_marking_threads, false, true);
if (_parallel_workers == NULL) {
vm_exit_during_initialization("Failed necessary allocation.");
} else {
_parallel_workers->initialize_workers();
}
}
// so that the call below can read a sensible value
_heap_start = (HeapWord*) rs.base();
set_non_marking_state();
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.