Up Top

Memory allocation (& GC 処理) : Garbage Collection を補佐する処理 : Write Barrier 処理 : Template Interpreter での処理


概要(Summary)

Template Interpreter の場合, do_oop_store() 関数によって Write Barrier 処理を行うコードが生成される.

なお, do_oop_store() は現在は以下のパスで(のみ)呼び出されている.

  TemplateTable::putfield_or_static()
  -> do_oop_store()
  TemplateTable::fast_storefield()
  -> do_oop_store()
  TemplateTable::aastore()
  -> do_oop_store()

備考(Notes)

なお G1GC の場合は, java.lang.ref.Reference.get() の処理 (= InterpreterGenerator::generate_Reference_get_entry() が生成するコード)においても, MacroAssembler::g1_write_barrier_pre() が生成したコードによる処理が行われる (See: here for details).

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

sparc の場合

-> do_oop_store() が生成するコード
   -> 使用する GC アルゴリズムが G1GC かどうかに応じて 2通りの処理が存在
      * G1GC 以外の場合:
        -> (1) 対象のポインタ値の書き換えを行う
               -> MacroAssembler::store_heap_oop() が生成するコード or
                  MacroAssembler::store_heap_oop_null()

           (2) 書き換え箇所に対応する Barrier Set 中の値を dirty にする
               -> MacroAssembler::store_check() が生成するコード
                  -> MacroAssembler::card_table_write() が生成するコード

      * G1GC の場合:
        -> (1) SATB 用の Write Barrier 処理を (その必要があれば) 実行する
               -> MacroAssembler::g1_write_barrier_pre() が生成するコード
                  -> * ConcurrentMarkThread が作業をしていない場合: (See: here for details)
                       何もしない
                     * 現在の値(= 書き換え前の値)が NULL の場合:
                       何もしない
                     * それ以外の場合:
                       -> generate_satb_log_enqueue_if_necessary() が生成するコード
                          -> generate_satb_log_enqueue() が生成するコード
                             -> SATBMarkQueueSet::handle_zero_index_for_thread() (<= もうバッファに空きがない場合には呼び出す)
                                -> PtrQueue::handle_zero_index()
                                   -> ObjPtrQueue::should_enqueue_buffer()
                                   -> * ロックと関連づけられているバッファの場合:
                                        -> PtrQueue::locking_enqueue_completed_buffer()
                                           -> PtrQueueSet::enqueue_complete_buffer()
                                              -> Monitor::notify()
                                      * ロックと関連づけられていないバッファの場合:
                                        -> PtrQueueSet::process_or_enqueue_complete_buffer()
                                           -> * 自分で処理してしまう場合:
                                                -> DirtyCardQueueSet::mut_process_buffer()
                                              * それ以外の場合:
                                                -> PtrQueueSet::enqueue_complete_buffer()
                                                   -> (同上)
                                   -> PtrQueueSet::allocate_buffer()

           (2) 対象のポインタ値の書き換えを行う
               -> MacroAssembler::store_heap_oop() が生成するコード

           (3) 書き換え箇所に対応する Barrier Set 中の値を dirty にする
               -> MacroAssembler::g1_write_barrier_post() が生成するコード
                  -> * 同一 HeapRegion 内を指している場合:
                       何もしない
                     * それ以外の場合:
                       -> generate_dirty_card_log_enqueue_if_necessary() が生成するコード
                          -> generate_dirty_card_log_enqueue() が生成するコード
                             -> DirtyCardQueueSet::handle_zero_index_for_thread() (<= もうバッファに空きがない場合には呼び出す)
                                -> PtrQueue::handle_zero_index()
                                   -> (略) (同上)
                                      (ただし, ObjPtrQueue::should_enqueue_buffer() ではなく PtrQueue::should_enqueue_buffer() が呼び出される)
                                      -> PtrQueueSet::enqueue_complete_buffer()
                                         -> Monitor::notify()  (<= DirtyCardQ_CBL_mon に対して. これは ConcurrentG1RefineThread を起床させる処理 (See: here for details))

x86_64 の場合

-> do_oop_store() が生成するコード
   -> 使用する GC アルゴリズムが G1GC かどうかに応じて 2通りの処理が存在
      * G1GC 以外の場合:
        -> (1) 対象のポインタ値の書き換えを行う
               -> MacroAssembler::store_heap_oop() が生成するコード

           (2) 書き換え箇所に対応する Barrier Set 中の値を dirty にする
               -> MacroAssembler::store_check()
                  -> MacroAssembler::store_check_part_1() が生成するコード
                  -> MacroAssembler::store_check_part_2() が生成するコード

      * G1GC の場合:
        -> (1) SATB 用の Write Barrier 処理を (その必要があれば) 実行する
               -> MacroAssembler::g1_write_barrier_pre()
                  -> * ConcurrentMarkThread が作業をしていない場合: (See: here for details)
                       何もしない
                     * 現在の値(= 書き換え前の値)が NULL の場合:
                       何もしない
                     * それ以外の場合:
                       -> SharedRuntime::g1_wb_pre() (← もうバッファに空きがない場合には呼び出す)
                          -> PtrQueue::enqueue()     (← thread->satb_mark_queue() に対して呼び出す)
                             -> PtrQueue::enqueue_known_active()
                                -> PtrQueue::handle_zero_index()
                                   -> (同上)

           (2) 対象のポインタ値の書き換えを行う
               -> MacroAssembler::store_heap_oop() が生成するコード, または 
                  MacroAssembler::store_heap_oop_null() が生成するコード

           (2) 書き換え箇所に対応する Barrier Set 中の値を dirty にする
               -> MacroAssembler::g1_write_barrier_post() が生成するコード
                  -> SharedRuntime::g1_wb_post() (← もうバッファに空きがない場合には呼び出す)
                     -> PtrQueue::enqueue()      (← thread->dirty_card_queue() に対して呼び出す)
                        -> (同上)

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

do_oop_store() (sparc の場合)

See: here for details

MacroAssembler::card_write_barrier_post() (sparc の場合)

See: here for details

MacroAssembler::card_table_write() (sparc の場合)

See: here for details

MacroAssembler::g1_write_barrier_pre() (sparc の場合)

See: here for details

generate_satb_log_enqueue_if_necessary() (sparc の場合)

See: here for details

generate_satb_log_enqueue() (sparc の場合)

See: here for details

SATBMarkQueueSet::handle_zero_index_for_thread()

See: here for details

PtrQueue::handle_zero_index()

See: here for details

ObjPtrQueue::should_enqueue_buffer()

See: here for details

PtrQueue::locking_enqueue_completed_buffer()

See: here for details

PtrQueueSet::enqueue_complete_buffer()

See: here for details

PtrQueueSet::process_or_enqueue_complete_buffer()

See: here for details

DirtyCardQueueSet::mut_process_buffer()

See: here for details

PtrQueueSet::allocate_buffer()

See: here for details

MacroAssembler::g1_write_barrier_post() (sparc の場合)

See: here for details

generate_dirty_card_log_enqueue_if_necessary() (sparc の場合)

See: here for details

generate_dirty_card_log_enqueue() (sparc の場合)

See: here for details

DirtyCardQueueSet::handle_zero_index_for_thread()

See: here for details

PtrQueue::should_enqueue_buffer()

See: here for details

do_oop_store() (x86_64 の場合)

See: here for details

MacroAssembler::store_check() (x86_64 の場合)

See: here for details

MacroAssembler::store_check_part_1() (x86_64 の場合)

See: here for details

MacroAssembler::store_check_part_2() (x86_64 の場合)

See: here for details

MacroAssembler::g1_write_barrier_pre() (x86_64 の場合)

See: here for details

SharedRuntime::g1_wb_pre()

See: here for details

PtrQueue::enqueue()

See: here for details

PtrQueue::enqueue_known_active()

See: here for details

MacroAssembler::g1_write_barrier_post() (x86_64 の場合)

See: here for details

SharedRuntime::g1_wb_post()

See: here for details


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