Top


定義場所(file name)

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

説明(description)

// This method contains no policy. You should probably
// be calling invoke() instead.

名前(function name)

void PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {

本体部(body)

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

      assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");
      assert(ref_processor() != NULL, "Sanity");

  {- -------------------------------------------
  (1) もし GC_locker によって GC が禁止されていれば, ここでリターン.
      ---------------------------------------- -}

      if (GC_locker::check_active_before_gc()) {
        return;
      }

  {- -------------------------------------------
  (1) (変数宣言など)
      (これらはトレース出力用のために使われる)
      ---------------------------------------- -}

      TimeStamp marking_start;
      TimeStamp compaction_start;
      TimeStamp collection_exit;

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

      ParallelScavengeHeap* heap = gc_heap();
      GCCause::Cause gc_cause = heap->gc_cause();
      PSYoungGen* young_gen = heap->young_gen();
      PSOldGen* old_gen = heap->old_gen();
      PSPermGen* perm_gen = heap->perm_gen();
      PSAdaptiveSizePolicy* size_policy = heap->size_policy();

      // The scope of casr should end after code that can change
      // CollectorPolicy::_should_clear_all_soft_refs.
      ClearedAllSoftRefs casr(maximum_heap_compaction,
                              heap->collector_policy());

  {- -------------------------------------------
  (1) (デバッグ用の処理)
      (ZapUnusedHeapArea オプションが指定されている場合は ...#TODO)
      ---------------------------------------- -}

      if (ZapUnusedHeapArea) {
        // Save information needed to minimize mangling
        heap->record_gen_tops_before_GC();
      }

  {- -------------------------------------------
  (1) (トレース出力)
      (See: CollectedHeap::pre_full_gc_dump())
      ---------------------------------------- -}

      heap->pre_full_gc_dump();

  {- -------------------------------------------
  (1) (トレース出力用の処理)
      (PSParallelCompact::print_phases() の値を設定しておく)
      ---------------------------------------- -}

      _print_phases = PrintGCDetails && PrintParallelOldGCPhaseTimes;

  {- -------------------------------------------
  (1) PSParallelCompact::pre_compact() を呼んで, GC のための前準備を行う.
      ---------------------------------------- -}

      // Make sure data structures are sane, make the heap parsable, and do other
      // miscellaneous bookkeeping.
      PreGCValues pre_gc_values;
      pre_compact(&pre_gc_values);

  {- -------------------------------------------
  (1) VMThread 用の ParCompactionManager オブジェクトを取得する.
      ---------------------------------------- -}

      // Get the compaction manager reserved for the VM thread.
      ParCompactionManager* const vmthread_cm =
        ParCompactionManager::manager_array(gc_task_manager()->workers());

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

      // Place after pre_compact() where the number of invocations is incremented.
      AdaptiveSizePolicyOutput(size_policy, heap->total_collections());

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

      {
        ResourceMark rm;
        HandleMark hm;

        const bool is_system_gc = gc_cause == GCCause::_java_lang_system_gc;

  {- -------------------------------------------
  (1) (トレース出力用の処理) & (トレース出力)
      ---------------------------------------- -}

        // This is useful for debugging but don't change the output the
        // the customer sees.
        const char* gc_cause_str = "Full GC";
        if (is_system_gc && PrintGCDetails) {
          gc_cause_str = "Full GC (System)";
        }
        gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
        TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
        TraceTime t1(gc_cause_str, PrintGC, !PrintGCDetails, gclog_or_tty);
        TraceCollectorStats tcs(counters());

  {- -------------------------------------------
  (1) (トレース出力用の処理) (DTrace のフック点) (JMM のフック点)
      (See: TraceMemoryManagerStats)
      ---------------------------------------- -}

        TraceMemoryManagerStats tms(true /* Full GC */,gc_cause);

  {- -------------------------------------------
  (1) (トレース出力用の処理)
      (Old 領域の GC にかかる時間を記録)
      ---------------------------------------- -}

        if (TraceGen1Time) accumulated_time()->start();

  {- -------------------------------------------
  (1) AdaptiveSizePolicy を更新する
      (ここから先が GC 処理の時間になるので, 
       AdaptiveSizePolicy::major_collection_begin() を呼んで
       PSAdaptiveSizePolicy オブジェクト内の非GC時間情報を更新)
      ---------------------------------------- -}

        // Let the size policy know we're starting
        size_policy->major_collection_begin();

  {- -------------------------------------------
  (1) フレーム中の bcp (byte code pointer, バイトコードを指すポインタ) を格納している箇所については
      GC によって methodOop が移動すると値が不正になってしまうので, 
      Threads::gc_prologue() を呼んで
      フレーム中の bcp を bci (byte code index, そのバイトコードのメソッド先頭からのオフセット値) に変えておく.

      (なお, CodeCache::gc_prologue()の方は, 単なる(assert) (See: CodeCache::gc_prologue()))
      ---------------------------------------- -}

        // When collecting the permanent generation methodOops may be moving,
        // so we either have to flush all bcp data or convert it into bci.
        CodeCache::gc_prologue();
        Threads::gc_prologue();

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

        NOT_PRODUCT(ref_processor()->verify_no_references_recorded());

  {- -------------------------------------------
  (1) #ifdef COMPILER2 の場合には, (これから GC を行うので) DerivedPointerTable の値をリセットしておく.
      (See: DerivedPointerTable)
      ---------------------------------------- -}

        COMPILER2_PRESENT(DerivedPointerTable::clear());

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

        ref_processor()->enable_discovery();
        ref_processor()->setup_policy(maximum_heap_compaction);

  {- -------------------------------------------
  (1) ?? (この変数はこの後使われてないが...)
      ---------------------------------------- -}

        bool marked_for_unloading = false;

  {- -------------------------------------------
  (1) (トレース出力用の処理)
      (GC 開始時の時刻を計測しておく)
      ---------------------------------------- -}

        marking_start.update();

  {- -------------------------------------------
  (1) PSParallelCompact::marking_phase() を呼び出して, 生きているオブジェクト全てに印(mark)を付ける.
      ---------------------------------------- -}

        marking_phase(vmthread_cm, maximum_heap_compaction);

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

    #ifndef PRODUCT
        if (TraceParallelOldGCMarkingPhase) {
          gclog_or_tty->print_cr("marking_phase: cas_tries %d  cas_retries %d "
            "cas_by_another %d",
            mark_bitmap()->cas_tries(), mark_bitmap()->cas_retries(),
            mark_bitmap()->cas_by_another());
        }
    #endif  // #ifndef PRODUCT

  {- -------------------------------------------
  (1) PSParallelCompact::summary_phase() を呼んで, #TODO
      ---------------------------------------- -}

        bool max_on_system_gc = UseMaximumCompactionOnSystemGC && is_system_gc;
        summary_phase(vmthread_cm, maximum_heap_compaction || max_on_system_gc);

  {- -------------------------------------------
  (1) #ifdef COMPILER2 の場合, DerivedPointerTable::set_active() を呼んで, 
      DerivedPointerTable にこれ以上ポインタが登録されないようにしておく.
      ---------------------------------------- -}

        COMPILER2_PRESENT(assert(DerivedPointerTable::is_active(), "Sanity"));
        COMPILER2_PRESENT(DerivedPointerTable::set_active(false));

  {- -------------------------------------------
  (1) PSParallelCompact::adjust_roots() を呼んで, 
      全ての strong root 内のポインタをコンパクション後の新しいアドレスに修正する.
      ---------------------------------------- -}

        // adjust_roots() updates Universe::_intArrayKlassObj which is
        // needed by the compaction for filling holes in the dense prefix.
        adjust_roots();

  {- -------------------------------------------
  (1) (トレース出力用の処理)
      (コンパクション開始時の時刻を計測しておく)
      ---------------------------------------- -}

        compaction_start.update();

  {- -------------------------------------------
  (1) PSParallelCompact::compact_perm() と PSParallelCompact::compact() を呼んで, 
      それぞれ Perm 領域内, New/Old 領域内の各 live object について
      新しいアドレスに移動させ, それらの中にあるポインタを新しいアドレスに修正する.
      ---------------------------------------- -}

        // Does the perm gen always have to be done serially because
        // klasses are used in the update of an object?
        compact_perm(vmthread_cm);

        compact();

  {- -------------------------------------------
  (1) PSParallelCompact::post_compact() を呼んで, GC 処理の後片付けを行う
      ---------------------------------------- -}

        // Reset the mark bitmap, summary data, and do other bookkeeping.  Must be
        // done before resizing.
        post_compact();

  {- -------------------------------------------
  (1) AdaptiveSizePolicy を更新する
      (ここまでが GC 処理の時間になるので, 
       AdaptiveSizePolicy::major_collection_end() を呼んで, 
       PSAdaptiveSizePolicy オブジェクト内の GC 時間情報を更新する)
      ---------------------------------------- -}

        // Let the size policy know we're done
        size_policy->major_collection_end(old_gen->used_in_bytes(), gc_cause);

  {- -------------------------------------------
  (1) GC 結果に基づいて領域長を調整しておく.
      (See: GC Ergonomics)
      ---------------------------------------- -}

        if (UseAdaptiveSizePolicy) {
          if (PrintAdaptiveSizePolicy) {
            gclog_or_tty->print("AdaptiveSizeStart: ");
            gclog_or_tty->stamp();
            gclog_or_tty->print_cr(" collection: %d ",
                           heap->total_collections());
            if (Verbose) {
              gclog_or_tty->print("old_gen_capacity: %d young_gen_capacity: %d"
                " perm_gen_capacity: %d ",
                old_gen->capacity_in_bytes(), young_gen->capacity_in_bytes(),
                perm_gen->capacity_in_bytes());
            }
          }

          // Don't check if the size_policy is ready here.  Let
          // the size_policy check that internally.
          if (UseAdaptiveGenerationSizePolicyAtMajorCollection &&
              ((gc_cause != GCCause::_java_lang_system_gc) ||
                UseAdaptiveSizePolicyWithSystemGC)) {
            // Calculate optimal free space amounts
            assert(young_gen->max_size() >
              young_gen->from_space()->capacity_in_bytes() +
              young_gen->to_space()->capacity_in_bytes(),
              "Sizes of space in young gen are out-of-bounds");
            size_t max_eden_size = young_gen->max_size() -
              young_gen->from_space()->capacity_in_bytes() -
              young_gen->to_space()->capacity_in_bytes();
            size_policy->compute_generation_free_space(
                                  young_gen->used_in_bytes(),
                                  young_gen->eden_space()->used_in_bytes(),
                                  old_gen->used_in_bytes(),
                                  perm_gen->used_in_bytes(),
                                  young_gen->eden_space()->capacity_in_bytes(),
                                  old_gen->max_gen_size(),
                                  max_eden_size,
                                  true /* full gc*/,
                                  gc_cause,
                                  heap->collector_policy());

            heap->resize_old_gen(
              size_policy->calculated_old_free_size_in_bytes());

            // Don't resize the young generation at an major collection.  A
            // desired young generation size may have been calculated but
            // resizing the young generation complicates the code because the
            // resizing of the old generation may have moved the boundary
            // between the young generation and the old generation.  Let the
            // young generation resizing happen at the minor collections.
          }
          if (PrintAdaptiveSizePolicy) {
            gclog_or_tty->print_cr("AdaptiveSizeStop: collection: %d ",
                           heap->total_collections());
          }
        }

  {- -------------------------------------------
  (1) (プロファイル情報の記録) (See: PSGCAdaptivePolicyCounters)
      ---------------------------------------- -}

        if (UsePerfData) {
          PSGCAdaptivePolicyCounters* const counters = heap->gc_policy_counters();
          counters->update_counters();
          counters->update_old_capacity(old_gen->capacity_in_bytes());
          counters->update_young_capacity(young_gen->capacity_in_bytes());
        }

  {- -------------------------------------------
  (1) ParallelScavengeHeap::resize_all_tlabs() で, 各スレッドの TLAB の大きさを最適に調整しておく.
      ---------------------------------------- -}

        heap->resize_all_tlabs();

  {- -------------------------------------------
  (1) Perm 領域内のゴミも回収したので, 
      PSPermGen::compute_new_size() を呼んで, 大きさを最適に調整しておく.
      ---------------------------------------- -}

        // We collected the perm gen, so we'll resize it here.
        perm_gen->compute_new_size(pre_gc_values.perm_gen_used());

  {- -------------------------------------------
  (1) (トレース出力用の処理)
      (Old 領域の GC にかかる時間を記録)
      ---------------------------------------- -}

        if (TraceGen1Time) accumulated_time()->stop();

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

        if (PrintGC) {
          if (PrintGCDetails) {
            // No GC timestamp here.  This is after GC so it would be confusing.
            young_gen->print_used_change(pre_gc_values.young_gen_used());
            old_gen->print_used_change(pre_gc_values.old_gen_used());
            heap->print_heap_change(pre_gc_values.heap_used());
            // Print perm gen last (print_heap_change() excludes the perm gen).
            perm_gen->print_used_change(pre_gc_values.perm_gen_used());
          } else {
            heap->print_heap_change(pre_gc_values.heap_used());
          }
        }

  {- -------------------------------------------
  (1) (プロファイル情報の記録)(JMM 用) (See: MemoryUsage)
      及び (JMM のフック点) でもある  (See: LowMemoryDetector)
      ---------------------------------------- -}

        // Track memory usage and detect low memory
        MemoryService::track_memory_usage();

  {- -------------------------------------------
  (1) ParallelScavengeHeap::update_counters()を呼んで, (プロファイル情報の記録)を行う.
      (See: SpaceCounter, PSGenerationCounters)
      ---------------------------------------- -}

        heap->update_counters();
      }

  {- -------------------------------------------
  (1) (デバッグ用の処理) (#ifdef ASSERT 時にのみ実行)
      ---------------------------------------- -}

    #ifdef ASSERT
      for (size_t i = 0; i < ParallelGCThreads + 1; ++i) {
        ParCompactionManager* const cm =
          ParCompactionManager::manager_array(int(i));
        assert(cm->marking_stack()->is_empty(),       "should be empty");
        assert(cm->region_stack()->is_empty(),        "should be empty");
        assert(cm->revisit_klass_stack()->is_empty(), "should be empty");
      }
    #endif // ASSERT

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

      if (VerifyAfterGC && heap->total_collections() >= VerifyGCStartAt) {
        HandleMark hm;  // Discard invalid handles created during verification
        gclog_or_tty->print(" VerifyAfterGC:");
        Universe::verify(false);
      }

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

      // Re-verify object start arrays
      if (VerifyObjectStartArray &&
          VerifyAfterGC) {
        old_gen->verify_object_start_array();
        perm_gen->verify_object_start_array();
      }

  {- -------------------------------------------
  (1) (デバッグ用の処理)
      (ZapUnusedHeapArea オプションが指定されている場合は ...#TODO)
      ---------------------------------------- -}

      if (ZapUnusedHeapArea) {
        old_gen->object_space()->check_mangled_unused_area_complete();
        perm_gen->object_space()->check_mangled_unused_area_complete();
      }

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

      NOT_PRODUCT(ref_processor()->verify_no_references_recorded());

  {- -------------------------------------------
  (1) (トレース出力用の処理)
      (GC 終了時の時刻を計測しておく)
      ---------------------------------------- -}

      collection_exit.update();

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

      if (PrintHeapAtGC) {
        Universe::print_heap_after_gc();
      }
      if (PrintGCTaskTimeStamps) {
        gclog_or_tty->print_cr("VM-Thread " INT64_FORMAT " " INT64_FORMAT " "
                               INT64_FORMAT,
                               marking_start.ticks(), compaction_start.ticks(),
                               collection_exit.ticks());
        gc_task_manager()->print_task_time_stamps();
      }

  {- -------------------------------------------
  (1) (トレース出力)
      (See: CollectedHeap::post_full_gc_dump())
      ---------------------------------------- -}

      heap->post_full_gc_dump();

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

    #ifdef TRACESPINNING
      ParallelTaskTerminator::print_termination_counts();
    #endif
    }

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