Top


定義場所(file name)

hotspot/src/share/vm/memory/referenceProcessor.cpp

名前(function name)

void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list,
                                                    HeapWord* pending_list_addr) {

本体部(body)

  {- -------------------------------------------
  (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.