Up Top

Memory allocation (& GC 処理) : メモリの確保処理 (GC 処理) : slow-path の処理 (4) GC 処理 : ParallelScavengeHeap の場合 : Major GC の処理 (UseParallelOldGC 有効時)


概要(Summary)

UseParallelOldGC オプションが指定されている場合, ParallelScavengeHeap の Major GC 処理は, PSParallelCompact::invoke() を呼び出すことで行われる (See: here for details).

実際の Major GC 処理は, PSParallelCompact::invoke() から呼び出される PSParallelCompact::invoke_no_policy() の中に実装されている. この PSParallelCompact::invoke_no_policy() の処理は, 大きく分けると4つのフェーズからなる.

  1. PSParallelCompact::marking_phase() で, 全ての生きているオブジェクト(live object)にマークを付ける.
  2. PSParallelCompact::summary_phase() で, 各 live object に対して, コンパクション後の新しいアドレスを計算する.
  3. PSParallelCompact::adjust_roots() で, strong root 内のポインタを新しいアドレスに修正する.
  4. PSParallelCompact::compact_perm() および PSParallelCompact::compact() で, 各 live object を新しいアドレスに移動させ, それらの中にあるポインタを新しいアドレスに修正する.

なお, ほとんどの処理は PSParallelCompact クラスで実装されている.

備考(Notes)

アルゴリズム自体は以下の論文で提案された手法(?).

Haim Kermany, Erez Petrank The Compressor: Concurrent, Incremental, and Parallel Compaction In Proceedings of the 2006 ACM SIGPLAN conference on Programming language design and implementation, pages 354-363

備考(Notes)

GC 中で使用される情報は, 以下のように記録/参照される.

詳細(Details)

  // region            -----+---------------------+----------
  // objects covered   [ AAA  )[ BBB )[ CCC   )[ DDD     )

この際に, 各 region 内の live object 量の計算も行われる (境界にまたがるようなオブジェクトについては, その region に含まれている分だけの大きさが加算される. 上の図のような状態なら, AAA と BBB と CCC と DDD が生きているとすると, AAA の一部と BBB と CCC と DDD の一部, の合計値になる).

marking phase でのマーク結果は, ParMarkBitMap というビットマップに格納される. このビットマップの書き換えや live object 量の更新処理は, 狂いが出ないようアトミックに行われる.

(この合計量の情報が, 各 region 内の live オブジェクトの コンパクション後の新しいアドレスを計算するために用いられる).

summary phase で計算する内容の具体例としては, 以下のようなものがある (詳細は ParallelCompactData 参照). * (前の region からはみ出して)その region の先頭部分にまでを占めている live オブジェクトの量 * その region 内での最初の live オブジェクトの位置 * この region 内のオブジェクトがコンパクション後にコピーされる先の region の数

summary phase では, 以上の内容に加えて "dense prefix" も計算する. "dense prefix" は, コンパクション後にも移動しない部分のこと (ヒープ領域の先頭部分の live オブジェクトは, コンパクション後にも同じ位置にとどまる. たとえ死んでいるオブジェクトがあった場合でも, コンパクション処理を高速化するために, ヒープ領域の先頭にはある程度ゴミが残っていてもよい, ということにして移動しない部分を作ることもある. 詳細は summarize_dense_prefix() 参照).

なお, summary phase の処理は, シングルスレッドで実行する.

    ((cite: hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp))
    // The UseParallelOldGC collector is a stop-the-world garbage collector that
    // does parts of the collection using parallel threads.  The collection includes
    // the tenured generation and the young generation.  The permanent generation is
    // collected at the same time as the other two generations but the permanent
    // generation is collect by a single GC thread.  The permanent generation is
    // collected serially because of the requirement that during the processing of a
    // klass AAA, any objects reference by AAA must already have been processed.
    // This requirement is enforced by a left (lower address) to right (higher
    // address) sliding compaction.
    //
    // There are four phases of the collection.
    //
    //      - marking phase
    //      - summary phase
    //      - compacting phase
    //      - clean up phase
    //
    // Roughly speaking these phases correspond, respectively, to
    //      - mark all the live objects
    //      - calculate the destination of each object at the end of the collection
    //      - move the objects to their destination
    //      - update some references and reinitialize some variables
    //
    // These three phases are invoked in PSParallelCompact::invoke_no_policy().  The
    // marking phase is implemented in PSParallelCompact::marking_phase() and does a
    // complete marking of the heap.  The summary phase is implemented in
    // PSParallelCompact::summary_phase().  The move and update phase is implemented
    // in PSParallelCompact::compact().
    //
    // A space that is being collected is divided into regions and with each region
    // is associated an object of type ParallelCompactData.  Each region is of a
    // fixed size and typically will contain more than 1 object and may have parts
    // of objects at the front and back of the region.
    //
    // region            -----+---------------------+----------
    // objects covered   [ AAA  )[ BBB )[ CCC   )[ DDD     )
    //
    // The marking phase does a complete marking of all live objects in the heap.
    // The marking also compiles the size of the data for all live objects covered
    // by the region.  This size includes the part of any live object spanning onto
    // the region (part of AAA if it is live) from the front, all live objects
    // contained in the region (BBB and/or CCC if they are live), and the part of
    // any live objects covered by the region that extends off the region (part of
    // DDD if it is live).  The marking phase uses multiple GC threads and marking
    // is done in a bit array of type ParMarkBitMap.  The marking of the bit map is
    // done atomically as is the accumulation of the size of the live objects
    // covered by a region.
    //
    // The summary phase calculates the total live data to the left of each region
    // XXX.  Based on that total and the bottom of the space, it can calculate the
    // starting location of the live data in XXX.  The summary phase calculates for
    // each region XXX quantites such as
    //
    //      - the amount of live data at the beginning of a region from an object
    //        entering the region.
    //      - the location of the first live data on the region
    //      - a count of the number of regions receiving live data from XXX.
    //
    // See ParallelCompactData for precise details.  The summary phase also
    // calculates the dense prefix for the compaction.  The dense prefix is a
    // portion at the beginning of the space that is not moved.  The objects in the
    // dense prefix do need to have their object references updated.  See method
    // summarize_dense_prefix().
    //
    // The summary phase is done using 1 GC thread.
    //
    // The compaction phase moves objects to their new location and updates all
    // references in the object.
    //
    // A current exception is that objects that cross a region boundary are moved
    // but do not have their references updated.  References are not updated because
    // it cannot easily be determined if the klass pointer KKK for the object AAA
    // has been updated.  KKK likely resides in a region to the left of the region
    // containing AAA.  These AAA's have there references updated at the end in a
    // clean up phase.  See the method PSParallelCompact::update_deferred_objects().
    // An alternate strategy is being investigated for this deferral of updating.
    //
    // Compaction is done on a region basis.  A region that is ready to be filled is
    // put on a ready list and GC threads take region off the list and fill them.  A
    // region is ready to be filled if it empty of live objects.  Such a region may
    // have been initially empty (only contained dead objects) or may have had all
    // its live objects copied out already.  A region that compacts into itself is
    // also ready for filling.  The ready list is initially filled with empty
    // regions and regions compacting into themselves.  There is always at least 1
    // region that can be put on the ready list.  The regions are atomically added
    // and removed from the ready list.

処理の流れ (概要)(Execution Flows : Summary)

-> PSParallelCompact::invoke()
   -> PSScavenge::invoke_no_policy()        (<= ScavengeBeforeFullGC オプションが指定されていれば)
      -> (See: here for details)
   -> PSParallelCompact::invoke_no_policy()
      -> (1) GC のための前準備を行う
             -> PSParallelCompact::pre_compact()
         
         (1) 生きているオブジェクト全てに印(mark)を付ける
             -> PSParallelCompact::marking_phase()
                (1) GCTaskQueue::create() で GCTaskQueue を作り, そこに GCTask をつめていく.
                    -> (1) 「各種 root となりうる箇所からの Mark 処理」を登録.                                 (MarkFromRootsTask)
                       (1) Threads::create_thread_roots_marking_tasks() で「各 JavaThread の root の処理」を登録. (ThreadRootsMarkingTask)
                           -> Threads::create_thread_roots_marking_tasks()
                       (1) 最後に, ParallelGCThreads 個分だけ StealMarkingTask を登録.
         
                (1) GCTaskManager::add_list() を呼び出し, 以上の GCTask を GCTaskThread 達に実行させる.
                    (なお, 実行させたスレッド自身は WaitForBarrierGCTask::wait_for() で GCTask が全て実行されるまで待機)
                    -> GCTaskManager::add_list()
                    -> WaitForBarrierGCTask::wait_for()
         
                     各 GCTask の処理の流れは以下のようになる.
                     * MarkFromRootsTask の場合:
                       -> MarkFromRootsTask::do_it()
                          (1) strong root 内にあるポインタの収集を行う.
                              この処理は, コンストラクタで指定された定数値に応じて処理範囲が異なる.
                              (なお使用するクロージャーは PSParallelCompact::MarkAndPushClosure)
                              * MarkFromRootsTask::universe の場合:
                                -> Universe::oops_do()
                                   -> (See: here for details)
                                      -> PSParallelCompact::MarkAndPushClosure::do_oop()
                                         -> PSParallelCompact::mark_and_push()
                                            -> PSParallelCompact::mark_obj()
                                               -> ParMarkBitMap::mark_obj()
                                                  -> BitMap::par_set_bit()
                                               -> ParallelCompactData::add_obj()
                                                  -> ParallelCompactData::RegionData::add_live_obj()
                                                  #TODO
                                            -> ParCompactionManager::push()
                              * MarkFromRootsTask::jni_handles の場合:
                                -> JNIHandles::oops_do()
                                   -> (See: here for details)
                              * MarkFromRootsTask::object_synchronizer の場合:
                                -> ObjectSynchronizer::oops_do()
                                   -> (See: here for details)
                              * MarkFromRootsTask::flat_profiler の場合:
                                -> FlatProfiler::oops_do()
                                   -> (See: here for details)
                              * MarkFromRootsTask::management の場合:
                                -> Management::oops_do()
                                   -> (See: here for details)
                              * MarkFromRootsTask::system_dictionary の場合:
                                -> SystemDictionary::oops_do()
                                   -> (See: here for details)
                              * MarkFromRootsTask::jvmti の場合:
                                -> JvmtiExport::oops_do()
                                   -> (See: here for details)
                              * MarkFromRootsTask::code_cache の場合:
                                -> (何もしない)
         
                          (2) ParCompactionManager::follow_marking_stacks() で, 集めたポインタに対する再帰的な marking 処理を行う.
                              -> ParCompactionManager::follow_marking_stacks()
                                 (oopDesc::follow_contents() や objArrayKlass::oop_follow_contents() による探索で
                                 新しく見つかったポインタが増えなくなるまで再帰的に繰り返す)
                                 -> oopDesc::follow_contents()
                                    -> *Klass::oop_follow_contents() で再帰的にポインタを辿ってマークを付けていく.
                                       (#TODO  クラス毎に少しずつ違うけど, 基本的には PSParallelCompact::mark_and_push() で辿るだけ??)
         
                                       (なお, ポインタ配列の場合には, _marking_stack ではなく _objarray_stack へのプッシュも行われる)
                                       -> objArrayKlass::oop_follow_contents()
                                          -> objArrayKlass::objarray_follow_contents()
                                 -> objArrayKlass::oop_follow_contents()
                                    -> (同上)
         
                     * ThreadRootsMarkingTask の場合:
                       -> ThreadRootsMarkingTask::do_it()
                          (1) 処理対象のスレッド内にあるポインタを収集する.
                              (なお使用するクロージャーは PSParallelCompact::MarkAndPushClosure と CodeBlobToOopClosure)
                              * 処理対象のスレッドが JavaThread であれば JavaThread::oops_do() を呼び出す.
                              * 処理対象のスレッドが VMThread であれば VMThread::oops_do() を呼び出す.
                              -> JavaThread::oops_do()
                                 -> (See: here for details)
                                    -> PSParallelCompact::MarkAndPushClosure::do_oop()
                                       -> (同上)
                              -> VMThread::oops_do()
                                 -> (See: here for details)
                                    -> PSParallelCompact::MarkAndPushClosure::do_oop()
                                       -> (同上)
                          (2) ParCompactionManager::follow_marking_stacks() で, 集めたポインタに対する再帰的な marking 処理を行う.
                              -> ParCompactionManager::follow_marking_stacks()
                                 -> (同上)
         
                     * StealMarkingTask の場合:
                       -> StealMarkingTask::do_it()
                          ParCompactionManager::steal_objarray() や ParCompactionManager::steal() で
                          他の GCTaskThread から仕事を奪い,
                          objArrayKlass::oop_follow_contents() や oopDesc::follow_contents(),
                          及び PSPromotionManager::drain_stacks_depth() で marking 処理を行う.
                          以降, 未処理の仕事がなくなるまでこれを繰り返す.
         
                (1) 以上の処理で見つかった参照オブジェクト(java.lang.ref オブジェクト)の処理を行う
                    -> ReferenceProcessor::process_discovered_references()
                       (なお使用するクロージャーおよびAbstractRefProcTaskExecutorは,
                       PSParallelCompact::IsAliveClosure, PSParallelCompact::MarkAndPushClosure,
                       PSParallelCompact::FollowStackClosure, RefProcTaskExecutor)
                       -> (See: here for details)
         
                           なお, 並列処理する場合はこの中で RefProcTaskExecutor が使用される.
                           RefProcTaskExecutor は, ReferenceProcessor::process_discovered_references() 内で
                           RefProcPhase1Task, RefProcPhase2Task, RefProcPhase3Task に対して以下のように呼び出される
         
                          -> RefProcTaskExecutor::execute()
                             -> RefProcTaskProxy::do_it()
                                (なお使用するクロージャーは,
                                 PSParallelCompact::IsAliveClosure, PSParallelCompact::MarkAndPushClosure, PSParallelCompact::FollowStackClosure)
                                -> AbstractRefProcTaskExecutor::ProcessTask::work()
                                   -> (実際には各サブクラスがオーバーライドしたメソッドが呼び出される
                                       (See: RefProcPhase1Task::work(), RefProcPhase2Task::work(), RefProcPhase3Task::work()))
                                      (See: here for details)
         
                (1) #TODO
                    -> SystemDictionary::do_unloading()
                    -> CodeCache::do_unloading()
                    ->
                    -> PSParallelCompact::follow_weak_klass_links()
                    -> PSParallelCompact::follow_mdo_weak_refs()
                    -> StringTable::unlink()
                    -> SymbolTable::unlink()
         
         (1) 各 live object に対して, コンパクション後の新しいアドレスを計算する.
             -> PSParallelCompact::summary_phase()
                -> PSParallelCompact::summarize_spaces_quick()
                   -> ParallelCompactData::summarize()
                -> PSParallelCompact::summarize_space()              (Perm 領域用)
                   -> PSParallelCompact::compute_dense_prefix()
                      -> PSParallelCompact::first_dead_space_region()
                      -> PSParallelCompact::dead_wood_limiter()
                      -> PSParallelCompact::dead_wood_limit_region()
                      -> PSParallelCompact::reclaimed_ratio()
                   -> PSParallelCompact::fill_dense_prefix_end()
                   -> ParallelCompactData::summarize_dense_prefix()
                   -> ParallelCompactData::summarize()
                -> PSParallelCompact::summarize_space()              (Old 領域用)
                   -> (同上)
                -> ParallelCompactData::summarize()                  (Eden 用)
                -> ParallelCompactData::summarize()                  (From 用)
                -> ParallelCompactData::summarize()                  (To 用)
         
         (1) strong root 内のポインタを新しいアドレスに修正する
             -> PSParallelCompact::adjust_roots()
                (なお使用するクロージャーは PSParallelCompact::AdjustPointerClosure)
                -> Universe::oops_do()
                   -> (See: here for details)
                      -> PSParallelCompact::AdjustPointerClosure::do_oop()
                         -> PSParallelCompact::adjust_pointer()
                            -> ParallelCompactData::calc_new_pointer()
                            -> oopDesc::encode_store_heap_oop_not_null()
                -> ReferenceProcessor::oops_do()
                   -> (See: here for details)
                -> JNIHandles::oops_do()
                   -> (See: here for details)
                -> Threads::oops_do()
                   -> (See: here for details)
                -> ObjectSynchronizer::oops_do()
                   -> (See: here for details)
                -> FlatProfiler::oops_do()
                   -> (See: here for details)
                -> Management::oops_do()
                   -> (See: here for details)
                -> JvmtiExport::oops_do()
                   -> (See: here for details)
                -> SystemDictionary::oops_do()
                   -> (See: here for details)
                -> JNIHandles::weak_oops_do()
                   -> (See: here for details)
                -> CodeCache::oops_do()
                   -> (See: here for details)
                -> StringTable::oops_do()
                   -> (See: here for details)
                -> ReferenceProcessor::weak_oops_do()
                   -> (See: here for details)
         
         (1) Perm 領域内の各 live object を新しいアドレスに移動させ, それらの中にあるポインタを新しいアドレスに修正する.
             -> PSParallelCompact::compact_perm()
                -> PSParallelCompact::move_and_update()
                   -> PSParallelCompact::update_and_deadwood_in_dense_prefix()
                      -> ParMarkBitMap::iterate()
                         (なお使用するクロージャーは UpdateOnlyClosure と FillClosure)
                         -> FillClosure::do_addr()
                         -> UpdateOnlyClosure::do_addr()
                            -> oopDesc::update_contents()
                               -> Klass::oop_update_pointers()
                                  -> (#TODO  クラス毎に少しずつ違うけど, 基本的には PSParallelCompact::adjust_pointer() で辿るだけ??)
                   -> ParMarkBitMap::iterate()
                      (なお使用するクロージャーは MoveAndUpdateClosure)
                      -> MoveAndUpdateClosure::do_addr()
                         -> ObjectStartArray::allocate_block()
                         -> Copy::aligned_conjoint_words()
                         -> oopDesc::update_contents()
                            -> (同上)
                         -> MoveAndUpdateClosure::update_state()
         
         (1) New/Old 領域内の各 live object を新しいアドレスに移動させ, それらの中にあるポインタを新しいアドレスに修正する.
             -> PSParallelCompact::compact()
                (1) GCTaskQueue::create() で GCTaskQueue を作り, そこに GCTask をつめていく.
                    (1) 「dense prefix 以外の部分の
                          live オブジェクトの移動処理およびポインタの修正処理」を登録.      (DrainStacksCompactionTask)
                        -> PSParallelCompact::enqueue_region_draining_tasks()
                    (1) 「dense prefix 部分についての, live オブジェクト内のポインタの修正処理
                          および dead オブジェクトをダミーオブジェクトで上書きする処理」を登録.   (UpdateDensePrefixTask)
                        -> PSParallelCompact::enqueue_dense_prefix_tasks()
                    (1) 最後に, ParallelGCThreads 個分だけ StealRegionCompactionTask を登録.
                        -> PSParallelCompact::enqueue_region_stealing_tasks()
         
                (1) GCTaskManager::add_list() を呼び出し, 以上の GCTask を GCTaskThread 達に実行させる.
                    (なお, 実行させたスレッド自身は WaitForBarrierGCTask::wait_for() で GCTask が全て実行されるまで待機)
                    -> GCTaskManager::add_list()
                    -> WaitForBarrierGCTask::wait_for()
         
                     各 GCTask の処理の流れは以下のようになる.
                     * DrainStacksCompactionTask の場合:
                       -> DrainStacksCompactionTask::do_it()
                          -> ParCompactionManager::drain_region_stacks()
                             -> PSParallelCompact::fill_and_update_region()
                                -> PSParallelCompact::fill_region()
                                   -> ParMarkBitMap::iterate()
                                      (なお使用するクロージャーは MoveAndUpdateClosure)
                                      -> MoveAndUpdateClosure::do_addr()
                                         -> (同上)
                                   #TODO
         
                     * UpdateDensePrefixTask の場合:
                       -> UpdateDensePrefixTask::do_it()
                          -> PSParallelCompact::update_and_deadwood_in_dense_prefix()
                             -> (同上)
         
                     * StealRegionCompactionTask の場合:
                       -> StealRegionCompactionTask::do_it()
                          -> #TODO
         
                (1) 複数 region にまたがっていたためにポインタの修正が行えていないオブジェクトに対して処理を行う.
                    -> PSParallelCompact::update_deferred_objects()
         
         (1) GC 処理の後片付けを行う
             -> PSParallelCompact::post_compact()
                -> PSParallelCompact::clear_data_covering_space()
                -> SpaceInfo::publish_new_top()
                -> PSParallelCompact::absorb_live_data_from_eden()
                -> Universe::update_heap_info_at_gc()
                -> ModRefBarrierSet::clear() or ModRefBarrierSet::invalidate()
                -> Threads::gc_epilogue()
                -> CodeCache::gc_epilogue()
                -> JvmtiExport::gc_epilogue()
         
         (1) GC 結果に基づいて領域長を調整する
             -> (See: GC Ergonomics)
             -> ParallelScavengeHeap::resize_all_tlabs()
             -> PSPermGen::compute_new_size()

処理の流れ (詳細)(Execution Flows : Details)

PSParallelCompact::invoke()

See: here for details

PSParallelCompact::invoke_no_policy()

See: here for details

PSParallelCompact::pre_compact()

See: here for details

PreGCValues::fill()

See: here for details

ParCompactionManager::reset()

See: here for details

GCTaskManager::release_all_resources()

See: here for details

GCTaskManager::set_resource_flag()

See: here for details

ParCompactionManager::gc_thread_compaction_manager()

See: here for details

CodeCache::gc_prologue()

See: here for details

Threads::gc_prologue()

See: here for details

JavaThread::gc_prologue()

See: here for details

frame_gc_prologue()

frame::gc_prologue() を呼び出すだけ.

    ((cite: hotspot/src/share/vm/runtime/thread.cpp))
    static void frame_gc_prologue(frame* f, const RegisterMap* map) { f->gc_prologue(); }

frame::gc_prologue()

See: here for details

PSParallelCompact::marking_phase()

(#Under Construction) See: here for details

Threads::create_thread_roots_marking_tasks()

See: here for details

MarkFromRootsTask::do_it()

See: here for details

PSParallelCompact::MarkAndPushClosure::do_oop()

PSParallelCompact::mark_and_push() を呼び出すだけ.

    ((cite: hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp))
    void PSParallelCompact::MarkAndPushClosure::do_oop(oop* p)       { mark_and_push(_compaction_manager, p); }
    void PSParallelCompact::MarkAndPushClosure::do_oop(narrowOop* p) { mark_and_push(_compaction_manager, p); }

PSParallelCompact::mark_and_push()

See: here for details

PSParallelCompact::mark_obj()

See: here for details

ParMarkBitMap::mark_obj(oop obj, int size)

See: here for details

ParMarkBitMap::mark_obj(HeapWord* addr, size_t size)

See: here for details

BitMap::par_set_bit()

See: here for details

ParallelCompactData::add_obj(oop p, size_t len)

    ((cite: hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp))

(1) ParallelCompactData::add_obj(引数のオーバーロード版) を呼び出すだけ.

      void add_obj(oop p, size_t len) { add_obj((HeapWord*)p, len); }

ParallelCompactData::add_obj(HeapWord* addr, size_t len)

See: here for details

ParallelCompactData::RegionData::add_live_obj()

See: here for details

ParallelCompactData::RegionData::set_partial_obj_size()

See: here for details

ParallelCompactData::RegionData::set_partial_obj_addr()

    ((cite: hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp))

(1) _partial_obj_addr フィールドをセットするだけ

        void set_partial_obj_addr(HeapWord* addr)  { _partial_obj_addr = addr; }

ParCompactionManager::push()

引数のポインタを _marking_stack にプッシュするだけ.

    ((cite: hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp))
      // Save for later processing.  Must not fail.
      inline void push(oop obj) { _marking_stack.push(obj); }

ParCompactionManager::follow_marking_stacks()

See: here for details

oopDesc::follow_contents(ParCompactionManager* cm)

See: here for details

objArrayKlass::oop_follow_contents()

See: here for details

objArrayKlass::objarray_follow_contents()

See: here for details

ParCompactionManager::push_objarray()

See: here for details

ThreadRootsMarkingTask::do_it()

See: here for details

StealMarkingTask::do_it()

See: here for details

ParCompactionManager::steal_objarray()

See: here for details

ParCompactionManager::steal()

See: here for details

RefProcTaskExecutor::execute(ProcessTask& task)

See: here for details

RefProcTaskProxy::do_it()

See: here for details

CollectedHeap::pre_full_gc_dump()

See: here for details

CollectedHeap::post_full_gc_dump()

See: here for details

PSParallelCompact::summary_phase()

See: here for details

PSParallelCompact::summarize_spaces_quick()

See: here for details

ParallelCompactData::summarize()

See: here for details

ParallelCompactData::summarize_split_space()

See: here for details

SplitInfo::record()

See: here for details

SplitInfo::is_split()

See: here for details

SplitInfo::is_valid()

    ((cite: hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp))

(1) この SplitInfo オブジェクトの値が有効なものかどうかを返す.
    (_src_region_idx フィールドの値が 0 より大きければ有効と見なす.
     逆に 0 あれば無効と見なす.)

      // Return true if this split info is valid (i.e., if a split has been
      // recorded).  The very first region cannot have a partial object and thus is
      // never split, so 0 is the 'invalid' value.
      bool is_valid() const { return _src_region_idx > 0; }

PSParallelCompact::summarize_space()

See: here for details

PSParallelCompact::compute_dense_prefix()

See: here for details

PSParallelCompact::first_dead_space_region()

See: here for details

PSParallelCompact::dead_wood_limiter()

See: here for details

PSParallelCompact::normal_distribution()

See: here for details

PSParallelCompact::initialize_dead_wood_limiter()

See: here for details

PSParallelCompact::dead_wood_limit_region()

See: here for details

PSParallelCompact::reclaimed_ratio()

See: here for details

PSParallelCompact::fill_dense_prefix_end()

See: here for details

PSParallelCompact::dead_space_crosses_boundary()

See: here for details

ParallelCompactData::summarize_dense_prefix()

See: here for details

PSParallelCompact::adjust_roots()

See: here for details

PSParallelCompact::AdjustPointerClosure::do_oop()

PSParallelCompact::adjust_pointer() を呼び出すだけ.

    ((cite: hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp))
    void PSParallelCompact::AdjustPointerClosure::do_oop(oop* p)       { adjust_pointer(p, _is_root); }
    void PSParallelCompact::AdjustPointerClosure::do_oop(narrowOop* p) { adjust_pointer(p, _is_root); }

PSParallelCompact::adjust_pointer()

See: here for details

ParallelCompactData::calc_new_pointer(oop p)

See: here for details

ParallelCompactData::calc_new_pointer(HeapWord* addr)

See: here for details

ParallelCompactData::addr_to_region_idx()

(#Under Construction)

ParallelCompactData::region()

(#Under Construction)

RegionData::partial_obj_size()

(#Under Construction)

ParMarkBitMap::live_words_in_range()

(#Under Construction)

PSParallelCompact::compact_perm()

See: here for details

PSParallelCompact::move_and_update()

See: here for details

PSParallelCompact::update_and_deadwood_in_dense_prefix()

See: here for details

ParMarkBitMap::iterate()

See: here for details

FillClosure::do_addr()

See: here for details

UpdateOnlyClosure::do_addr()

See: here for details

UpdateOnlyClosure::do_addr()

See: here for details

oopDesc::update_contents()

See: here for details

PSParallelCompact::should_update_klass()

See: here for details

ParallelCompactData::RegionData::set_completed()

See: here for details

ParMarkBitMap::iterate()

See: here for details

MoveAndUpdateClosure::do_addr()

See: here for details

PSParallelCompact::compact()

See: here for details

PSParallelCompact::enqueue_region_draining_tasks()

See: here for details

ParallelCompactData::RegionData::claim_unsafe()

See: here for details

ParallelCompactData::RegionData::available()

    ((cite: hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp))

(1) コンパクション先の region (destination count) 0 なら true を返す.

        bool available() const { return _dc_and_los < dc_one; }

PSParallelCompact::enqueue_dense_prefix_tasks()

See: here for details

PSParallelCompact::enqueue_region_stealing_tasks()

See: here for details

DrainStacksCompactionTask::do_it()

See: here for details

ParCompactionManager::drain_region_stacks()

See: here for details

PSParallelCompact::fill_and_update_region()

See: here for details

PSParallelCompact::fill_region()

(#Under Construction) See: here for details

PSParallelCompact::first_src_addr()

(#Under Construction) See: here for details

UpdateDensePrefixTask::do_it()

See: here for details

StealRegionCompactionTask::do_it()

(#Under Construction) See: here for details

PSParallelCompact::update_deferred_objects()

(#Under Construction) See: here for details

PSParallelCompact::post_compact()

(#Under Construction) See: here for details

PSParallelCompact::clear_data_covering_space()

See: here for details

SpaceInfo::publish_new_top()

_new_top フィールドの値を, 対応する Space オブジェクトの top にセットするだけ.

    ((cite: hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp))
      void publish_new_top() const              { _space->set_top(_new_top); }

PSParallelCompact::absorb_live_data_from_eden()

See: here for details

PSPermGen::compute_new_size()

See: here for details

Threads::gc_epilogue()

See: here for details

JavaThread::gc_epilogue()

See: here for details

frame_gc_epilogue()

frame::gc_epilogue() を呼び出すだけ.

    ((cite: hotspot/src/share/vm/runtime/thread.cpp))
    // GC support
    static void frame_gc_epilogue(frame* f, const RegisterMap* map) { f->gc_epilogue(); }

frame::gc_epilogue()

See: here for details

pd_gc_epilog() (sparc の場合)

See: here for details### pd_gc_epilog() (x86 の場合) See: here for details### pd_gc_epilog() (zero の場合) See: here for details

CodeCache::gc_epilogue()

(#Under Construction) See: here for details

JvmtiExport::gc_epilogue()

See: here for details

JvmtiCurrentBreakpoints::gc_epilogue()

See: here for details

JvmtiBreakpoints::gc_epilogue()

See: here for details

JvmtiBreakpointCache::gc_epilogue()

GrowableCache::gc_epilogue() を呼び出すだけ.

    ((cite: hotspot/src/share/vm/prims/jvmtiImpl.hpp))
      void gc_epilogue()                    { _cache.gc_epilogue(); }

GrowableCache::gc_epilogue()

See: here for details


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