Top


定義場所(file name)

hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp

名前(function name)

void PSParallelCompact::marking_phase(ParCompactionManager* cm,
                                      bool maximum_heap_compaction) {

本体部(body)

  {- -------------------------------------------
  (1) (トレース出力)
      ---------------------------------------- -}

      // Recursively traverse all live objects and mark them
      EventMark m("1 mark object");
      TraceTime tm("marking phase", print_phases(), true, gclog_or_tty);

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

      ParallelScavengeHeap* heap = gc_heap();
      uint parallel_gc_threads = heap->gc_task_manager()->workers();
      TaskQueueSetSuper* qset = ParCompactionManager::region_array();
      ParallelTaskTerminator terminator(parallel_gc_threads, qset);

      PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
      PSParallelCompact::FollowStackClosure follow_stack_closure(cm);

  {- -------------------------------------------
  (1) (以下のブロックの中で, 全ての生きているオブジェクトに mark を付ける処理を行う)
      ---------------------------------------- -}

      {

    {- -------------------------------------------
  (1.1) (トレース出力)
        ---------------------------------------- -}

        TraceTime tm_m("par mark", print_phases(), true, gclog_or_tty);

    {- -------------------------------------------
  (1.1) nmethod 用の前準備をしておく (See: ParallelScavengeHeap::ParStrongRootsScope)
        ---------------------------------------- -}

        ParallelScavengeHeap::ParStrongRootsScope psrs;

    {- -------------------------------------------
  (1.1) GCTaskQueue::create() で GCTaskQueue を作り, 
        そこに MarkFromRootsTask や ThreadRootsMarkingTask をつめていく.
        ---------------------------------------- -}

        GCTaskQueue* q = GCTaskQueue::create();

        q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::universe));
        q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::jni_handles));
        // We scan the thread roots in parallel
        Threads::create_thread_roots_marking_tasks(q);
        q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::object_synchronizer));
        q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::flat_profiler));
        q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::management));
        q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::system_dictionary));
        q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::jvmti));
        q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::code_cache));

    {- -------------------------------------------
  (1.1) さらに, ParallelGCThreads 個分だけ StealMarkingTask を追加.
        ---------------------------------------- -}

        if (parallel_gc_threads > 1) {
          for (uint j = 0; j < parallel_gc_threads; j++) {
            q->enqueue(new StealMarkingTask(&terminator));
          }
        }

    {- -------------------------------------------
  (1.1) 最後に, 以上の処理が終了するまで待機するための WaitForBarrierGCTask も追加しておく.
        ---------------------------------------- -}

        WaitForBarrierGCTask* fin = WaitForBarrierGCTask::create();
        q->enqueue(fin);

    {- -------------------------------------------
  (1.1) GCTaskManager::add_list() で, GCTask をキューに追加して GCTaskThread 達に実行させる.
        ---------------------------------------- -}

        gc_task_manager()->add_list(q);

    {- -------------------------------------------
  (1.1) WaitForBarrierGCTask::wait_for() で GCTask が全て実行されるまで待機する.
        待機が解けたら, WaitForBarrierGCTask::destroy() で WaitForBarrierGCTask オブジェクトを破棄する.
        ---------------------------------------- -}

        fin->wait_for();

        // We have to release the barrier tasks!
        WaitForBarrierGCTask::destroy(fin);
      }

  {- -------------------------------------------
  (1) (以下のブロックの中で, 上の mark 処理中に見つかった参照オブジェクト(java.lang.ref オブジェクト)の処理を行う)
      (See: [here](no289169tf.html) for details)

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

      // Process reference objects found during marking
      {
        TraceTime tm_r("reference processing", print_phases(), true, gclog_or_tty);
        if (ref_processor()->processing_is_mt()) {
          RefProcTaskExecutor task_executor;
          ref_processor()->process_discovered_references(
            is_alive_closure(), &mark_and_push_closure, &follow_stack_closure,
            &task_executor);
        } else {
          ref_processor()->process_discovered_references(
            is_alive_closure(), &mark_and_push_closure, &follow_stack_closure, NULL);
        }
      }

  {- -------------------------------------------
  (1) (トレース出力)
      (これ以降のクラスやコードキャッシュ等のアンロード処理に掛かる時間を出力)
      ---------------------------------------- -}

      TraceTime tm_c("class unloading", print_phases(), true, gclog_or_tty);

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

      // Follow system dictionary roots and unload classes.
      bool purged_class = SystemDictionary::do_unloading(is_alive_closure());

  {- -------------------------------------------
  (1) #TODO
      ---------------------------------------- -}

      // Follow code cache roots.
      CodeCache::do_unloading(is_alive_closure(), &mark_and_push_closure,
                              purged_class);
      cm->follow_marking_stacks(); // Flush marking stack.

  {- -------------------------------------------
  (1) #TODO
      ---------------------------------------- -}

      // Update subklass/sibling/implementor links of live klasses
      // revisit_klass_stack is used in follow_weak_klass_links().
      follow_weak_klass_links();

  {- -------------------------------------------
  (1) #TODO
      ---------------------------------------- -}

      // Revisit memoized MDO's and clear any unmarked weak refs
      follow_mdo_weak_refs();

  {- -------------------------------------------
  (1) #TODO
      ---------------------------------------- -}

      // Visit interned string tables and delete unmarked oops
      StringTable::unlink(is_alive_closure());

  {- -------------------------------------------
  (1) #TODO
      ---------------------------------------- -}

      // Clean up unreferenced symbols in symbol table.
      SymbolTable::unlink();

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

      assert(cm->marking_stacks_empty(), "marking stacks should be empty");
    }

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