hotspot/src/share/vm/memory/referenceProcessor.cpp
inline void
ReferenceProcessor::add_to_discovered_list_mt(DiscoveredList& refs_list,
oop obj,
HeapWord* discovered_addr) {
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(_discovery_is_mt, "!_discovery_is_mt should have been handled by caller");
{- -------------------------------------------
(1) (同一の参照オブジェクトが複数回 enqueue されると困るので discovered フィールドの書き換えは CAS で行う, とのこと)
---------------------------------------- -}
// First we must make sure this object is only enqueued once. CAS in a non null
// discovered_addr.
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
oop current_head = refs_list.head();
{- -------------------------------------------
(1) write barrier の実行が要求されている場合(_discovered_list_needs_barrier が true の場合)であっても
G1GC の場合は BarrierSet::write_ref_field_pre() の実行までは必要ない.
(というのは, 書き込む前の discovered フィールドの値が NULL だから)
コメントによると, 「将来の GC アルゴリズムで pre-barrier を
必要とするものが出てくるかもしれないので, この if 文を書いてある」とのこと.
(現状だと, そもそも _discovered_list_needs_barrier が true になるのが G1GC の場合しかないような...)
---------------------------------------- -}
// Note: In the case of G1, this specific pre-barrier is strictly
// not necessary because the only case we are interested in
// here is when *discovered_addr is NULL (see the CAS further below),
// so this will expand to nothing. As a result, we have manually
// elided this out for G1, but left in the test for some future
// collector that might have need for a pre-barrier here.
if (_discovered_list_needs_barrier && !UseG1GC) {
if (UseCompressedOops) {
_bs->write_ref_field_pre((narrowOop*)discovered_addr, current_head);
} else {
_bs->write_ref_field_pre((oop*)discovered_addr, current_head);
}
guarantee(false, "Need to check non-G1 collector");
}
{- -------------------------------------------
(1) CAS を用いて,
処理対象の参照オブジェクトの discovered フィールドを
現在リストの先頭になっている参照オブジェクトに置き換える.
(なお, 書き換え前の discovered フィールドは NULL だという想定)
---------------------------------------- -}
oop retest = oopDesc::atomic_compare_exchange_oop(current_head, discovered_addr,
NULL);
{- -------------------------------------------
(1) もし CAS が成功していれば, 以下の処理を行う.
* リストの先頭を今回処理した参照オブジェクトに置き換える (ついでにリストの長さをインクリメントする).
* write barrier の実行が要求されている場合(_discovered_list_needs_barrier が true の場合)には
BarrierSet::write_ref_field() を呼び出して barrier set を書き換えておく.
* (トレース出力)
---------------------------------------- -}
if (retest == NULL) {
// This thread just won the right to enqueue the object.
// We have separate lists for enqueueing so no synchronization
// is necessary.
refs_list.set_head(obj);
refs_list.inc_length(1);
if (_discovered_list_needs_barrier) {
_bs->write_ref_field((void*)discovered_addr, current_head);
}
if (TraceReferenceGC) {
gclog_or_tty->print_cr("Enqueued reference (mt) (" INTPTR_FORMAT ": %s)",
obj, obj->blueprint()->internal_name());
}
{- -------------------------------------------
(1) もし CAS が失敗していたら, (トレース出力)を出すだけ.
---------------------------------------- -}
} else {
// If retest was non NULL, another thread beat us to it:
// The reference has already been discovered...
if (TraceReferenceGC) {
gclog_or_tty->print_cr("Already enqueued reference (" INTPTR_FORMAT ": %s)",
obj, obj->blueprint()->internal_name());
}
}
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.