Top


定義場所(file name)

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

説明(description)

// Update interior oops in the ranges of regions [beg_region, end_region).

名前(function name)

void
PSParallelCompact::update_and_deadwood_in_dense_prefix(ParCompactionManager* cm,
                                                       SpaceId space_id,
                                                       size_t beg_region,
                                                       size_t end_region) {

本体部(body)

  {- -------------------------------------------
  (1) (変数宣言など)
      (beg_addr は, 処理対象範囲の先頭を指すアドレス. ただし後で微修正される可能性有り.
       end_addr は, 処理対象範囲の終端を指すアドレス.)
      ---------------------------------------- -}

      ParallelCompactData& sd = summary_data();
      ParMarkBitMap* const mbm = mark_bitmap();

      HeapWord* beg_addr = sd.region_to_addr(beg_region);
      HeapWord* const end_addr = sd.region_to_addr(end_region);
      assert(beg_region <= end_region, "bad region range");
      assert(end_addr <= dense_prefix(space_id), "not in the dense prefix");

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

    #ifdef  ASSERT
      // Claim the regions to avoid triggering an assert when they are marked as
      // filled.
      for (size_t claim_region = beg_region; claim_region < end_region; ++claim_region) {
        assert(sd.region(claim_region)->claim_unsafe(), "claim() failed");
      }
    #endif  // #ifdef ASSERT

  {- -------------------------------------------
  (1) 引数で指定された処理対象範囲の先頭アドレス(beg_addr)は, 
      たいていの場合オブジェクトの境界とはずれているので, 
      一番近いオブジェクトの頭出しを行い, 
      beg_addr をそのオブジェクトの先頭に変更しておく.

      (ただし, beg_addr がヒープ領域(Space)の一番先頭(bottom)の場合は, 
       明らかにオブジェクトの先頭を指しているので, この処理は省略する.)

      頭出しは以下のようにして行う.
      * 対象の region に partial object がある場合 (RegionData::partial_obj_size() != 0 の場合):
        partial object の直後にあわせる (ParallelCompactData::partial_obj_end() で取得)
      * 対象の region の先頭を dead object がまたいでいる場合 (PSParallelCompact::dead_space_crosses_boundary() が true の場合):
        最初の live オブジェクトの先頭にあわせる (ParMarkBitMap::find_obj_beg() で取得)
      * それ以外の場合:
        何もしない
      ---------------------------------------- -}

      if (beg_addr != space(space_id)->bottom()) {
        // Find the first live object or block of dead space that *starts* in this
        // range of regions.  If a partial object crosses onto the region, skip it;
        // it will be marked for 'deferred update' when the object head is
        // processed.  If dead space crosses onto the region, it is also skipped; it
        // will be filled when the prior region is processed.  If neither of those
        // apply, the first word in the region is the start of a live object or dead
        // space.
        assert(beg_addr > space(space_id)->bottom(), "sanity");
        const RegionData* const cp = sd.region(beg_region);
        if (cp->partial_obj_size() != 0) {
          beg_addr = sd.partial_obj_end(beg_region);
        } else if (dead_space_crosses_boundary(cp, mbm->addr_to_bit(beg_addr))) {
          beg_addr = mbm->find_obj_beg(beg_addr, end_addr);
        }
      }

  {- -------------------------------------------
  (1) 処理対象範囲(beg_addr ~ end_addr)を ParMarkBitMap::iterate() で辿る.
      この中で UpdateOnlyClosure 及び FillClosure によって
      live オブジェクト内のポインタの修正処理, 及び 
      dead オブジェクトをダミーオブジェクトで上書きする処理を行う.

      (ただし, 処理対象範囲が空の場合(= beg_addr と end_addr が一致する場合)には, 
       何もすることはないので, この処理自体を省略する)

      (なお, ParMarkBitMap::iterate() の返値が ParMarkBitMap::incomplete だった場合には, 
       処理されなかったオブジェクトが残っているということなので (See: ParMarkBitMap::iterate()), 
       最後に UpdateOnlyClosure::do_addr() を呼び出して
       そのオブジェクトの処理も終わらせておく.)
      ---------------------------------------- -}

      if (beg_addr < end_addr) {
        // A live object or block of dead space starts in this range of Regions.
         HeapWord* const dense_prefix_end = dense_prefix(space_id);

        // Create closures and iterate.
        UpdateOnlyClosure update_closure(mbm, cm, space_id);
        FillClosure fill_closure(cm, space_id);
        ParMarkBitMap::IterationStatus status;
        status = mbm->iterate(&update_closure, &fill_closure, beg_addr, end_addr,
                              dense_prefix_end);
        if (status == ParMarkBitMap::incomplete) {
          update_closure.do_addr(update_closure.source());
        }
      }

  {- -------------------------------------------
  (1) 処理が終わったので, 
      処理範囲に対応する PSParallelCompact::RegionData オブジェクトに対して
      PSParallelCompact::RegionData::set_completed() を呼んで, 
      処理完了の印を付けておく.
      ---------------------------------------- -}

      // Mark the regions as filled.
      RegionData* const beg_cp = sd.region(beg_region);
      RegionData* const end_cp = sd.region(end_region);
      for (RegionData* cp = beg_cp; cp < end_cp; ++cp) {
        cp->set_completed();
      }
    }

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