hotspot/src/share/vm/memory/referenceProcessor.cpp
void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list,
HeapWord* pending_list_addr) {
{- -------------------------------------------
(1) (この関数が呼ばれた時点では, リスト内の参照オブジェクトは
それぞれの discovered フィールドに次の参照オブジェクトへのポインタが格納されることで
リスト状につながっている.
これらを pending list につなぐために,
discovered フィールドのポインタを next フィールドに移して
next フィールドを介してつながるリストにする.
その後, できたリストを pending list の先頭に追加する.)
---------------------------------------- -}
// Given a list of refs linked through the "discovered" field
// (java.lang.ref.Reference.discovered) chain them through the
// "next" field (java.lang.ref.Reference.next) and prepend
// to the pending list.
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
if (TraceReferenceGC && PrintGCDetails) {
gclog_or_tty->print_cr("ReferenceProcessor::enqueue_discovered_reflist list "
INTPTR_FORMAT, (address)refs_list.head());
}
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
oop obj = refs_list.head();
{- -------------------------------------------
(1) (以下の while 文の中でリスト中の参照オブジェクトを全て辿る)
---------------------------------------- -}
// Walk down the list, copying the discovered field into
// the next field and clearing it (except for the last
// non-sentinel object which is treated specially to avoid
// confusion with an active reference).
while (obj != sentinel_ref()) {
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(obj->is_instanceRef(), "should be reference object");
{- -------------------------------------------
(1) discovered フィールドの値を取得する
---------------------------------------- -}
oop next = java_lang_ref_Reference::discovered(obj);
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
if (TraceReferenceGC && PrintGCDetails) {
gclog_or_tty->print_cr(" obj " INTPTR_FORMAT "/next " INTPTR_FORMAT,
obj, next);
}
assert(java_lang_ref_Reference::next(obj) == NULL,
"The reference should not be enqueued");
{- -------------------------------------------
(1) discovered フィールドの値を next フィールドに書き込み,
代わりに discovered フィールドは NULL に戻しておく.
ただしリストの最後の要素にまで到達した場合は, この処理の代わりに
処理していたリストを pending list の先頭に追加する処理を行う.
(より具体的には, oopDesc::atomic_exchange_oop() で pending list を処理していたリスト全体で置き換え,
その後, リスト中の最後の要素の next フィールドに pending list の先頭だった要素を書き込む.
なお, 置き換え前の pending list が空だった場合は, リスト中の最後の要素の next フィールドは自分自身を指すようにする.)
(ところで, コメントで enqueue_discovered_reflists() 内の oop-check がどうとか書かれているが,
この処理は今は ReferenceProcessor::enqueue_discovered_ref_helper() 内にある模様.)
---------------------------------------- -}
if (next == sentinel_ref()) { // obj is last
// Swap refs_list into pendling_list_addr and
// set obj's next to what we read from pending_list_addr.
oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr);
// Need oop_check on pending_list_addr above;
// see special oop-check code at the end of
// enqueue_discovered_reflists() further below.
if (old == NULL) {
// obj should be made to point to itself, since
// pending list was empty.
java_lang_ref_Reference::set_next(obj, obj);
} else {
java_lang_ref_Reference::set_next(obj, old);
}
} else {
java_lang_ref_Reference::set_next(obj, next);
}
java_lang_ref_Reference::set_discovered(obj, (oop) NULL);
obj = next;
}
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.