hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp
bool doHeapRegion(HeapRegion* hr) {
{- -------------------------------------------
(1) 初回の呼び出し時であれば _start_vtime_sec を初期化しておく
---------------------------------------- -}
if (!_final && _regions_done == 0)
_start_vtime_sec = os::elapsedVTime();
{- -------------------------------------------
(1) もし対象の HeapRegion が Humongous オブジェクトの途中に当たる場合は
特にすることはないので, ここでリターン.
---------------------------------------- -}
if (hr->continuesHumongous()) {
// We will ignore these here and process them when their
// associated "starts humongous" region is processed (see
// set_bit_for_heap_region()). Note that we cannot rely on their
// associated "starts humongous" region to have their bit set to
// 1 since, due to the region chunking in the parallel region
// iteration, a "continues humongous" region might be visited
// before its associated "starts humongous".
return false;
}
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
HeapWord* nextTop = hr->next_top_at_mark_start();
HeapWord* start = hr->top_at_conc_mark_count();
assert(hr->bottom() <= start && start <= hr->end() &&
hr->bottom() <= nextTop && nextTop <= hr->end() &&
start <= nextTop,
"Preconditions.");
// Otherwise, record the number of word's we'll examine.
size_t words_done = (nextTop - start);
{- -------------------------------------------
(1) CMBitMapRO::getNextMarkedWordAddress() を呼んで,
---------------------------------------- -}
// Find the first marked object at or after "start".
start = _bm->getNextMarkedWordAddress(start, nextTop);
size_t marked_bytes = 0;
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
// Below, the term "card num" means the result of shifting an address
// by the card shift -- address 0 corresponds to card number 0. One
// must subtract the card num of the bottom of the heap to obtain a
// card table index.
// The first card num of the sequence of live cards currently being
// constructed. -1 ==> no sequence.
intptr_t start_card_num = -1;
// The last card num of the sequence of live cards currently being
// constructed. -1 ==> no sequence.
intptr_t last_card_num = -1;
{- -------------------------------------------
(1)
---------------------------------------- -}
while (start < nextTop) {
if (_yield && _cm->do_yield_check()) {
// We yielded. It might be for a full collection, in which case
// all bets are off; terminate the traversal.
if (_cm->has_aborted()) {
_changed = false;
return true;
} else {
// Otherwise, it might be a collection pause, and the region
// we're looking at might be in the collection set. We'll
// abandon this region.
return false;
}
}
oop obj = oop(start);
int obj_sz = obj->size();
// The card num of the start of the current object.
intptr_t obj_card_num =
intptr_t(uintptr_t(start) >> CardTableModRefBS::card_shift);
HeapWord* obj_last = start + obj_sz - 1;
intptr_t obj_last_card_num =
intptr_t(uintptr_t(obj_last) >> CardTableModRefBS::card_shift);
if (obj_card_num != last_card_num) {
if (start_card_num == -1) {
assert(last_card_num == -1, "Both or neither.");
start_card_num = obj_card_num;
} else {
assert(last_card_num != -1, "Both or neither.");
assert(obj_card_num >= last_card_num, "Inv");
if ((obj_card_num - last_card_num) > 1) {
// Mark the last run, and start a new one.
mark_card_num_range(start_card_num, last_card_num);
start_card_num = obj_card_num;
}
}
#if CARD_BM_TEST_MODE
/*
gclog_or_tty->print_cr("Setting bits from %d/%d.",
obj_card_num - _bottom_card_num,
obj_last_card_num - _bottom_card_num);
*/
for (intptr_t j = obj_card_num; j <= obj_last_card_num; j++) {
_card_bm->par_at_put(j - _bottom_card_num, 1);
}
#endif
}
// In any case, we set the last card num.
last_card_num = obj_last_card_num;
marked_bytes += (size_t)obj_sz * HeapWordSize;
// Find the next marked object after this one.
start = _bm->getNextMarkedWordAddress(start + 1, nextTop);
_changed = true;
}
{- -------------------------------------------
(1)
---------------------------------------- -}
// Handle the last range, if any.
if (start_card_num != -1)
mark_card_num_range(start_card_num, last_card_num);
if (_final) {
// Mark the allocated-since-marking portion...
HeapWord* tp = hr->top();
if (nextTop < tp) {
start_card_num =
intptr_t(uintptr_t(nextTop) >> CardTableModRefBS::card_shift);
last_card_num =
intptr_t(uintptr_t(tp) >> CardTableModRefBS::card_shift);
mark_card_num_range(start_card_num, last_card_num);
// This definitely means the region has live objects.
set_bit_for_region(hr);
}
}
hr->add_to_marked_bytes(marked_bytes);
// Update the live region bitmap.
if (marked_bytes > 0) {
set_bit_for_region(hr);
}
hr->set_top_at_conc_mark_count(nextTop);
_tot_live += hr->next_live_bytes();
_tot_used += hr->used();
_words_done = words_done;
{- -------------------------------------------
(1) Concurrent 処理中に呼ばれた場合は (= _final フィールドが false の場合は),
Concurrent marking によるオーバーヘッドを平準化するため,
適当な時間だけ os::sleep() で待機しておく
(正確には, 呼び出された回数を _regions_done に記録しており, 10 回呼び出されると 1回待機する.
待機時間は, 前回の待機処理以降の処理時間(以下の elapsed_vtime_sec)に比例.
ただし, 処理時間(elapsed_vtime_sec)があまりに短い場合(0.01 sec未満)には, 待機処理は(もう10回分先まで)延期する)
---------------------------------------- -}
if (!_final) {
++_regions_done;
if (_regions_done % 10 == 0) {
double end_vtime_sec = os::elapsedVTime();
double elapsed_vtime_sec = end_vtime_sec - _start_vtime_sec;
if (elapsed_vtime_sec > (10.0 / 1000.0)) {
jlong sleep_time_ms =
(jlong) (elapsed_vtime_sec * _cm->cleanup_sleep_factor() * 1000.0);
os::sleep(Thread::current(), sleep_time_ms, false);
_start_vtime_sec = end_vtime_sec;
}
}
}
{- -------------------------------------------
(1) リターン
---------------------------------------- -}
return false;
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.