Top


定義場所(file name)

hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp

名前(function name)

void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) {

本体部(body)

  {- -------------------------------------------
  (1) (変数宣言など)
      ---------------------------------------- -}

      ResourceMark rm;
      HandleMark   hm;
      G1CollectedHeap* g1h   = G1CollectedHeap::heap();
      ReferenceProcessor* rp = g1h->ref_processor();

  {- -------------------------------------------
  (1) (ReferenceProcessor がどう concurrent に動作するかは
       G1CollectedHeap::ref_processing_init() のコメント参照, とのこと)
      ---------------------------------------- -}

      // See the comment in G1CollectedHeap::ref_processing_init()
      // about how reference processing currently works in G1.

  {- -------------------------------------------
  (1) これから GC を行うので, ReferenceProcessor オブジェクトをリセットしておく.
      ---------------------------------------- -}

      // Process weak references.
      rp->setup_policy(clear_all_soft_refs);

  {- -------------------------------------------
  (1) (assert)
      ---------------------------------------- -}

      assert(_markStack.isEmpty(), "mark stack should be empty");

  {- -------------------------------------------
  (1) (変数宣言など)
      ---------------------------------------- -}

      G1CMIsAliveClosure   g1_is_alive(g1h);
      G1CMKeepAliveClosure g1_keep_alive(g1h, this, nextMarkBitMap());
      G1CMDrainMarkingStackClosure
        g1_drain_mark_stack(nextMarkBitMap(), &_markStack, &g1_keep_alive);
      // We use the work gang from the G1CollectedHeap and we utilize all
      // the worker threads.
      int active_workers = g1h->workers() ? g1h->workers()->total_workers() : 1;
      active_workers = MAX2(MIN2(active_workers, (int)_max_task_num), 1);

      G1RefProcTaskExecutor par_task_executor(g1h, this, nextMarkBitMap(),
                                              g1h->workers(), active_workers);


  {- -------------------------------------------
  (1) ReferenceProcessor::process_discovered_references() を呼び出して, 
      これまでの処理(= ConcurrentMark::checkpointRootsFinalWork() の処理)中に発見された
      参照オブジェクト(java.lang.ref オブジェクト) の処理を行う.

      (なお, 使用する ReferenceProcessor オブジェクトの _processing_is_mt フィールドが 
       true である場合は, この処理をマルチスレッドで行う.
       その場合には AbstractRefProcTaskExecutor として G1RefProcTaskExecutor が使用される.)
      ---------------------------------------- -}

      if (rp->processing_is_mt()) {
        // Set the degree of MT here.  If the discovery is done MT, there
        // may have been a different number of threads doing the discovery
        // and a different number of discovered lists may have Ref objects.
        // That is OK as long as the Reference lists are balanced (see
        // balance_all_queues() and balance_queues()).
        rp->set_active_mt_degree(active_workers);

        rp->process_discovered_references(&g1_is_alive,
                                          &g1_keep_alive,
                                          &g1_drain_mark_stack,
                                          &par_task_executor);

        // The work routines of the parallel keep_alive and drain_marking_stack
        // will set the has_overflown flag if we overflow the global marking
        // stack.
      } else {
        rp->process_discovered_references(&g1_is_alive,
                                          &g1_keep_alive,
                                          &g1_drain_mark_stack,
                                          NULL);

      }

  {- -------------------------------------------
  (1) (assert)
      ---------------------------------------- -}

      assert(_markStack.overflow() || _markStack.isEmpty(),
          "mark stack should be empty (unless it overflowed)");

  {- -------------------------------------------
  (1) 
      ---------------------------------------- -}

      if (_markStack.overflow()) {
        // Should have been done already when we tried to push an
        // entry on to the global mark stack. But let's do it again.
        set_has_overflown();
      }

  {- -------------------------------------------
  (1) 次に, ReferenceProcessor::enqueue_discovered_references() で
      リストに残った参照オブジェクト(= 差し先が死んだため特殊な処理が必要な参照オブジェクト)を pending list に追加する.

      (マルチスレッドで行う場合は, この処理でも AbstractRefProcTaskExecutor として G1RefProcTaskExecutor を使用)
      ---------------------------------------- -}

      if (rp->processing_is_mt()) {
        assert(rp->num_q() == active_workers, "why not");
        rp->enqueue_discovered_references(&par_task_executor);
      } else {
        rp->enqueue_discovered_references();
      }

  {- -------------------------------------------
  (1) (verify)
      ---------------------------------------- -}

      rp->verify_no_references_recorded();

  {- -------------------------------------------
  (1) (assert)
      ---------------------------------------- -}

      assert(!rp->discovery_enabled(), "should have been disabled");

  {- -------------------------------------------
  (1) 
      ---------------------------------------- -}

      // Now clean up stale oops in StringTable
      StringTable::unlink(&g1_is_alive);
      // Clean up unreferenced symbols in symbol table.
      SymbolTable::unlink();
    }

This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.