Hotspot 垃圾回收之CompactibleFreeListSpace(三) 源码解析

    目录

1、block_size / block_size_no_stall / block_size_nopar

2、oop_iterate / object_iterate / safe_object_iterate /object_iterate_mem / object_iterate_careful_m

 3、save_marks / promote / oop_since_save_marks_iterate

4、forward / prepare_for_compaction / adjust_pointers / compact / reset_after_compaction 

5、beginSweepFLCensus / endSweepFLCensus


      本篇博客继续上一篇《Hotspot 垃圾回收之CompactibleFreeListSpace(二) 源码解析》讲解CompactibleFreeListSpace的其他关键方法的实现。

1、block_size / block_size_no_stall / block_size_nopar

     这三个方法都是用来获取某个地址p对应的内存块的大小,要求p是内存块的起始地址。三个方法的实现核心是一样的,如果是空闲的FreeChunk则获取FreeChunk的大小,否则将其作为对象oop,根据Klass获取oop对应的内存块的大小。区别在于block_size / block_size_no_stall都是并发情形下调用的,会将p强转成volatile变量,会通过while循环不断尝试;block_size_nopar是在非并发情形下调用的,不会将p强转成volatile变量,也没有while循环。block_size_no_stall相比block_size多了一步,当Klass为NULL时通过CMSCollector::block_size_if_printezis_bits方法获取内存块大小,一次循环完成,而此时block_size会多次循环。这三个方法的调用链如下:

 

 

其实现如下: 

size_t CompactibleFreeListSpace::block_size(const HeapWord* p) const {
  NOT_PRODUCT(verify_objects_initialized());
  //每次读取p时都需将其转换成volatile变量,从而可以保证CPU能够及时获取对p的修改
  while (true) {
    // We must do this until we get a consistent view of the object.
    if (FreeChunk::indicatesFreeChunk(p)) {
      //如果p是一个空闲的FreeChunk
      volatile FreeChunk* fc = (volatile FreeChunk*)p;
      size_t res = fc->size();

      //强制CPU再一次读取指针p
      OrderAccess::acquire();

      //再次检查p是否是一个一个空闲的FreeChunk,如果是则返回res,如果不是则通过下一次循环进入下面的分支中
      if (FreeChunk::indicatesFreeChunk(p)) {
        assert(res != 0, "Block size should not be 0");
        return res;
      }
    } else {
      //如果p不是一个空闲的FreeChunk,即是一个对象,获取对应的Klass
      Klass* k = ((volatile oopDesc*)p)->klass_or_null();
      if (k != NULL) {
        assert(k->is_klass(), "Should really be klass oop.");
        oop o = (oop)p;
        assert(o->is_oop(true /* ignore mark word */), "Should be an oop.");

       //强制CPU再一次读取指针p
        OrderAccess::acquire();
        //根据Klass获取对象大小
        size_t res = o->size_given_klass(k);
        //将res做内存对齐
        res = adjustObjectSize(res);
        assert(res != 0, "Block size should not be 0");
        return res;
      }
    }
  }
}

inline void OrderAccess::acquire() {
  volatile intptr_t local_dummy;
#ifdef AMD64
  __asm__ volatile ("movq 0(%%rsp), %0" : "=r" (local_dummy) : : "memory");
#else
  __asm__ volatile ("movl 0(%%esp),%0" : "=r" (local_dummy) : : "memory");
#endif // AMD64
}

size_t CompactibleFreeListSpace::block_size_no_stall(HeapWord* p,
                                                     const CMSCollector* c)
const {
  assert(MemRegion(bottom(), end()).contains(p), "p not in space");
  
  DEBUG_ONLY(uint loops = 0;)
  while (true) {
     //如果p是一个空闲的FreeChunk
    if (FreeChunk::indicatesFreeChunk(p)) {
      volatile FreeChunk* fc = (volatile FreeChunk*)p;
      size_t res = fc->size();

      OrderAccess::acquire();

      if (FreeChunk::indicatesFreeChunk(p)) {
        assert(res != 0, "Block size should not be 0");
        assert(loops == 0, "Should be 0");
        return res;
      }
    } else {
      //如果p不是一个空闲的FreeChunk,即是一个对象,获取对应的Klass
      Klass* k = ((volatile oopDesc*)p)->klass_or_null();
    
      if (k != NULL) {
        assert(k->is_klass(), "Should really be klass oop.");
        oop o = (oop)p;
        assert(o->is_oop(), "Should be an oop");

        OrderAccess::acquire();

        size_t res = o->size_given_klass(k);
        res = adjustObjectSize(res);
        assert(res != 0, "Block size should not be 0");
        return res;
      } else {
        // 多了一步,当Klass为null时通过P-bits获取内存块大小,CMSCollector通过一个markBitMap维护了各内存块的大小
        return c->block_size_if_printezis_bits(p);
      }
    }
    assert(loops == 0, "Can loop at most once");
    DEBUG_ONLY(loops++;)
  }
}

//非并发场景下调用,不会将p强转成volatile变量
size_t CompactibleFreeListSpace::block_size_nopar(const HeapWord* p) const {
  NOT_PRODUCT(verify_objects_initialized());
  assert(MemRegion(bottom(), end()).contains(p), "p not in space");
  FreeChunk* fc = (FreeChunk*)p;
  if (fc->is_free()) {
    return fc->size();
  } else {
    //不校验klass是否为空,也不做循环
    assert(oop(p)->is_oop(true), "Should be an oop");
    return adjustObjectSize(oop(p)->size());
  }
}

2、oop_iterate / object_iterate / safe_object_iterate /object_iterate_mem / object_iterate_careful_m

     oop_iterate是遍历当前Space包含的oop所引用的所有其他oop,object_iterate开头的几个方法是遍历当前Space包含的oop本身,其实现基本相同,如下:

void CompactibleFreeListSpace::oop_iterate(ExtendedOopClosure* cl) {
  assert_lock_strong(freelistLock());
  HeapWord *cur, *limit;
  size_t curSize;
  //从bottom开始遍历整个Space
  for (cur = bottom(), limit = end(); cur < limit;
       cur += curSize) {
    //获取内存块的大小
    curSize = block_size(cur);
    if (block_is_obj(cur)) {
      //遍历oop所有引用类型属性对应的oop
      oop(cur)->oop_iterate(cl);
    }
  }
}

bool CompactibleFreeListSpace::block_is_obj(const HeapWord* p) const {
  FreeChunk* fc = (FreeChunk*)p;
  assert(is_in_reserved(p), "Should be in space");
  //如果是空闲的FreeChunk
  if (FreeChunk::indicatesFreeChunk(p)) return false;
  Klass* k = oop(p)->klass_or_null();
  if (k != NULL) {
    //如果Klass不为NULL
    assert(oop(p)->is_oop(true), "Should be an oop");
    return true;
  } else {
    return false;  // Was not an object at the start of collection.
  }
}

//同oop_iterate,不过遍历的是Space本身包含的对象,而非Space本身包含的对象所引用的对象
void CompactibleFreeListSpace::object_iterate(ObjectClosure* blk) {
  assert_lock_strong(freelistLock());
  NOT_PRODUCT(verify_objects_initialized());
  HeapWord *cur, *limit;
  size_t curSize;
  for (cur = bottom(), limit = end(); cur < limit;
       cur += curSize) {
    curSize = block_size(cur);
    if (block_is_obj(cur)) {
      blk->do_object(oop(cur));
    }
  }
}


//跟object_iterate相比多了一个obj_is_alive的判断,只遍历存活的对象
void CompactibleFreeListSpace::safe_object_iterate(ObjectClosure* blk) {
  assert_lock_strong(freelistLock());
  NOT_PRODUCT(verify_objects_initialized());
  HeapWord *cur, *limit;
  size_t curSize;
  for (cur = bottom(), limit = end(); cur < limit;
       cur += curSize) {
    curSize = block_size(cur);
    if (block_is_obj(cur) && obj_is_alive(cur)) {
      blk->do_object(oop(cur));
    }
  }
}

bool CompactibleFreeListSpace::obj_is_alive(const HeapWord* p) const {
  assert(SafepointSynchronize::is_at_safepoint() || !is_init_completed(),
         "Else races are possible");
  assert(block_is_obj(p), "The address should point to an object");
  //Sweeping表示正在执行清理,已经完成对象标记了
  if (_collector->abstract_state() == CMSCollector::Sweeping) {
    CMSBitMap* live_map = _collector->markBitMap();
    //通过CMSBitMap判断对象是否是存活对象
    return live_map->par_isMarked((HeapWord*) p);
  }
  return true;
}

void CompactibleFreeListSpace::object_iterate_mem(MemRegion mr,
                                                  UpwardsObjectClosure* cl) {
  assert_locked(freelistLock());
  NOT_PRODUCT(verify_objects_initialized());
  assert(!mr.is_empty(), "Should be non-empty");
  //校验mr在当前Space的内存区域范围内
  assert(MemRegion(bottom(), end()).contains(mr),
         "Should be within used space");
  //获取最近一次遍历的对象的地址,如果大于end地址,说明Space中的对象都已经遍历过了       
  HeapWord* prev = cl->previous();   // max address from last time
  if (prev >= mr.end()) { // nothing to do
    return;
  }

  bool last_was_obj_array = false;
  HeapWord *blk_start_addr, *region_start_addr;
  if (prev > mr.start()) {
    //mr中有部分对象已经遍历过了
    region_start_addr = prev;
    blk_start_addr    = prev;
    assert((BlockOffsetArrayUseUnallocatedBlock &&
            (!is_in(prev))) ||
           (blk_start_addr == block_start(region_start_addr)), "invariant");
  } else {
    region_start_addr = mr.start();
    //获取mr.start对应的内存块的起始地址
    blk_start_addr    = block_start(region_start_addr);
  }
  HeapWord* region_end_addr = mr.end();
  MemRegion derived_mr(region_start_addr, region_end_addr);

  //遍历blk_start_addr到mr.end之间的内存区域
  while (blk_start_addr < region_end_addr) {
    const size_t size = block_size(blk_start_addr);
    if (block_is_obj(blk_start_addr)) {
      //如果是对象,do_object_bm返回true表示这个对象的结束地址不应该通过set_previous方法记录
      last_was_obj_array = cl->do_object_bm(oop(blk_start_addr), derived_mr);
    } else {
      last_was_obj_array = false;
    }
    blk_start_addr += size;
  }
  if (!last_was_obj_array) {
    //如果最后一个内存块不是对象,或者是对象但是do_object_bm方法返回false,则记录blk_start_addr
    assert((bottom() <= blk_start_addr) && (blk_start_addr <= end()),
           "Should be within (closed) used space");
    assert(blk_start_addr > prev, "Invariant");
    cl->set_previous(blk_start_addr); // min address for next time
  }
}


HeapWord*
CompactibleFreeListSpace::object_iterate_careful_m(MemRegion mr,
  ObjectClosureCareful* cl) {
  assert_lock_strong(freelistLock());
  //校验mr在当前Space内
  assert(!mr.is_empty() && MemRegion(bottom(),end()).contains(mr),
         "mr should be non-empty and within used space");
  HeapWord *addr, *end;
  size_t size;
  //从mr.start对应的内存块的起始地址开始遍历
  for (addr = block_start_careful(mr.start()), end  = mr.end();
       addr < end; addr += size) {
    FreeChunk* fc = (FreeChunk*)addr;
    if (fc->is_free()) {
      //如果是空闲的内存块则跳过
      size = fc->size();
    } else {
      //如果是对象则交给ObjectClosureCareful处理,如果是一个无法解析的对象则返回0,终止处理
      size = cl->do_object_careful_m(oop(addr), mr);
      if (size == 0) {
        return addr;
      }
    }
  }
  return NULL;
}

各方法的调用链如下:

 

 

 

 3、save_marks / promote / oop_since_save_marks_iterate

      这三个方法都是执行promote相关的,所谓promote是指将某个对象从年轻代复制到老年代;save_marks用于保存_saved_mark_word,然后开启promote跟踪,所谓promote跟踪是指记录所有发生了promote的对象,将他们通过链表维护起来;oop_since_save_marks_iterate用于遍历所有发生promote的对象,通过宏定义的,实际有多个方法,如下:

其实现如下: 

void CompactibleFreeListSpace::save_marks() {
  assert(Thread::current()->is_VM_thread(),
         "Global variable should only be set when single-threaded");
  //保留_saved_mark_word
  set_saved_mark_word(unallocated_block());

  //校验未开始promote
  assert(_promoInfo.noPromotions(), "_promoInfo inconsistency");
  //准备执行跟踪promote,所谓promote是指将某个对象从新生代拷贝复制到老年代
  _promoInfo.startTrackingPromotions();
}

HeapWord* unallocated_block() const {
   //BlockOffsetArrayUseUnallocatedBlock表示是否维护unallocated_block,默认为false
    if (BlockOffsetArrayUseUnallocatedBlock) {
      HeapWord* ub = _bt.unallocated_block();
      assert(ub >= bottom() &&
             ub <= end(), "space invariant");
      return ub;
    } else {
      return end();
    }
}

void set_saved_mark_word(HeapWord* p) { _saved_mark_word = p; }

void PromotionInfo::startTrackingPromotions() {
  assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex,
         "spooling inconsistency?");
  _firstIndex = _nextIndex = 1;
  _tracking = true;
}

bool noPromotions() const {
    assert(_promoHead != NULL || _promoTail == NULL, "list inconsistency");
    return _promoHead == NULL;
}

oop CompactibleFreeListSpace::promote(oop obj, size_t obj_size) {
  assert(obj_size == (size_t)obj->size(), "bad obj_size passed in");
  assert_locked();

  //如果开启了track但是没有足够的空间则返回NULL
  if (_promoInfo.tracking() && !_promoInfo.ensure_spooling_space()) {
    return NULL;
  }
  //首先将obj_size做内存对齐,然后从当前空间内分配一块内存
  HeapWord* res = allocate(adjustObjectSize(obj_size));
  if (res != NULL) {
    //分配成功,将原来的对象拷贝到res
    Copy::aligned_disjoint_words((HeapWord*)obj, res, obj_size);
    //如果开启跟踪
    if (_promoInfo.tracking()) {
        //记录这个被promoted的对象
        _promoInfo.track((PromotedObject*)res);
    }
  }
  return oop(res);
}

#define CFLS_OOP_SINCE_SAVE_MARKS_DEFN(OopClosureType, nv_suffix)           \
                                                                            \
void CompactibleFreeListSpace::                                             \
oop_since_save_marks_iterate##nv_suffix(OopClosureType* blk) {              \
  assert(SharedHeap::heap()->n_par_threads() == 0,                          \
         "Shouldn't be called (yet) during parallel part of gc.");          \
  //实际调用_promoInfo的遍历方法       
  _promoInfo.promoted_oops_iterate##nv_suffix(blk);                         \
  /*                                                                        \
   遍历的时候会不断从_promoInfo内部的链表中移除元素,遍历结束链表头被置空,noPromotions方法返回true
   */                                                                       \
  assert(_promoInfo.noPromotions(), "_promoInfo inconsistency");            \
}

ALL_SINCE_SAVE_MARKS_CLOSURES(CFLS_OOP_SINCE_SAVE_MARKS_DEFN)

  各方法的调用链如下:

 

 

4、forward / prepare_for_compaction / adjust_pointers / compact / reset_after_compaction 

      这几个方法都是跟Space压缩相关的,改写了父类的实现,改写如下:

//修改父类实现,不再调用initialize_threshold方法,原有的cross_threshold的用途也被变更成更新bt,
//从而记录被复制对象的起始地址
HeapWord* CompactibleFreeListSpace::forward(oop q, size_t size,
                                    CompactPoint* cp, HeapWord* compact_top) {
 
  assert(this == cp->space, "'this' should be current compaction space.");
  //计算可用于compaction的最大空间
  size_t compaction_max_size = pointer_delta(end(), compact_top);

  assert(adjustObjectSize(size) == cp->space->adjust_object_size_v(size),
    "virtual adjustObjectSize_v() method is not correct");
  //计算内存对齐后的对象大小
  size_t adjusted_size = adjustObjectSize(size);
  
  assert(compaction_max_size >= MinChunkSize || compaction_max_size == 0,
         "no small fragments allowed");
  assert(minimum_free_block_size() == MinChunkSize,
         "for de-virtualized reference below");
  //如果剩余可用于compaction的空间不足了
  if (adjusted_size + MinChunkSize > compaction_max_size &&
      adjusted_size != compaction_max_size) {
    do {
      //保存compact_top
      cp->space->set_compaction_top(compact_top);
      //切换到下一个Space
      cp->space = cp->space->next_compaction_space();
      if (cp->space == NULL) {
         //切换到下一个Genaration
        cp->gen = GenCollectedHeap::heap()->prev_gen(cp->gen);
        assert(cp->gen != NULL, "compaction must succeed");
        cp->space = cp->gen->first_compaction_space();
        assert(cp->space != NULL, "generation must have a first compaction space");
      }
      //设置新的Space的compact_top
      compact_top = cp->space->bottom();
      cp->space->set_compaction_top(compact_top);
      //计算设置新的Space的adjusted_size和compaction_max_size
      adjusted_size = cp->space->adjust_object_size_v(size);
      compaction_max_size = pointer_delta(cp->space->end(), compact_top);
      assert(cp->space->minimum_free_block_size() == 0, "just checking");
    } while (adjusted_size > compaction_max_size);
  }

  if ((HeapWord*)q != compact_top) {
    //将需要移动的目的地址记录到q的对象头中
    q->forward_to(oop(compact_top));
    assert(q->is_gc_marked(), "encoding the pointer should preserve the mark");
  } else {
    // q刚好等于compact_top,则该对象不需要移动了
    q->init_mark();
    assert(q->forwardee() == NULL, "should be forwarded to NULL");
  }

  compact_top += adjusted_size;

  //通过cross_threshold方法记录被复制对象的起始地址
  cp->threshold =
    cp->space->cross_threshold(compact_top - adjusted_size, compact_top);
  return compact_top;
}

HeapWord* CompactibleFreeListSpace::cross_threshold(HeapWord* start, HeapWord* the_end) {
  _bt.single_block(start, the_end);
  return end();
}

virtual size_t minimum_free_block_size() const { return MinChunkSize; }

void CompactibleFreeListSpace::prepare_for_compaction(CompactPoint* cp) {
  //跟父类相比,就传入方法的block_is_obj和block_size是当前子类的实现
  SCAN_AND_FORWARD(cp,end,block_is_obj,block_size);
}

#define obj_size(q) adjustObjectSize(oop(q)->size())
#define adjust_obj_size(s) adjustObjectSize(s)

void CompactibleFreeListSpace::adjust_pointers() {
  //adjust_obj_size使用当前子类的实现
  SCAN_AND_ADJUST_POINTERS(adjust_obj_size);
}

void CompactibleFreeListSpace::compact() {
   //obj_size使用当前子类的实现
  SCAN_AND_COMPACT(obj_size);
}

void CompactibleFreeListSpace::reset_after_compaction() {
  MemRegion mr(compaction_top(), end());
  reset(mr);
  //_adaptive_freelists默认为true,则重新填充LinearAllocBlock
  if (_adaptive_freelists) {
    refillLinearAllocBlocksIfNeeded();
  } else {
    FreeChunk* fc = dictionary()->find_largest_dict();
    if (fc != NULL) {
      assert(fc->size() == mr.word_size(),
             "Why was the chunk broken up?");
      removeChunkFromDictionary(fc);
      HeapWord* addr = (HeapWord*) fc;
      _smallLinearAllocBlock.set(addr, fc->size() ,
        1024*SmallForLinearAlloc, fc->size());
      // Note that _unallocated_block is not updated here.
    }
  }
}

void CompactibleFreeListSpace::reset(MemRegion mr) {
  //重置FreeList和dictionary
  resetIndexedFreeListArray();
  dictionary()->reset();
  //BlockOffsetArrayUseUnallocatedBlock表示是否维护bt的unallocated_block属性
  if (BlockOffsetArrayUseUnallocatedBlock) {
    assert(end() == mr.end(), "We are compacting to the bottom of CMS gen");
    _bt.set_unallocated_block(end());
  }
  if (!mr.is_empty()) {
    assert(mr.word_size() >= MinChunkSize, "Chunk size is too small");
    //将剩余空间作为一个空闲内存块归还到Dictionary或者FreeList中
    _bt.single_block(mr.start(), mr.word_size());
    FreeChunk* fc = (FreeChunk*) mr.start();
    fc->set_size(mr.word_size());
    if (mr.word_size() >= IndexSetSize ) {
      returnChunkToDictionary(fc);
    } else {
      _bt.verify_not_unallocated((HeapWord*)fc, fc->size());
      _indexedFreeList[mr.word_size()].return_chunk_at_head(fc);
    }
    //更新coal_birth计数器
    coalBirth(mr.word_size());
  }
  //_promoInfo和_smallLinearAllocBlock各属性置为NULL
  _promoInfo.reset();
  _smallLinearAllocBlock._ptr = NULL;
  _smallLinearAllocBlock._word_size = 0;
}

void CompactibleFreeListSpace::resetIndexedFreeListArray() {
  for (size_t i = 1; i < IndexSetSize; i++) {
    assert(_indexedFreeList[i].size() == (size_t) i,
      "Indexed free list sizes are incorrect");
    _indexedFreeList[i].reset(IndexSetSize);
    assert(_indexedFreeList[i].count() == 0, "reset check failed");
    assert(_indexedFreeList[i].head() == NULL, "reset check failed");
    assert(_indexedFreeList[i].tail() == NULL, "reset check failed");
    assert(_indexedFreeList[i].hint() == IndexSetSize, "reset check failed");
  }
}

5、beginSweepFLCensus / endSweepFLCensus

      这两方法用于在执行Sweep清理前后保存或者重置相关计数器,涉及到的计数器如下:

  • ssize_t     _desired;         //用来计算_demand_rate_estimate
  • ssize_t     _coal_desired;     // 用来控制内存块合并
  • ssize_t     _bfr_surp;         // 清理开始前的当前surplus
  • ssize_t     _prev_sweep;       // 上一次清理结束后的FreeList保存的FreeChunk的个数
  • ssize_t     _before_sweep;     // 清理开始前的FreeList保存的FreeChunk的个数

其调用链如下:

 

其代码实现如下: 

void CompactibleFreeListSpace::beginSweepFLCensus(
  float inter_sweep_current,
  float inter_sweep_estimate,
  float intra_sweep_estimate) {
  assert_locked();
  size_t i;
  for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
    AdaptiveFreeList<FreeChunk>* fl    = &_indexedFreeList[i];
    if (PrintFLSStatistics > 1) {
      gclog_or_tty->print("size[" SIZE_FORMAT "] : ", i);
    }
    //这4个底层都是调用AllocationStats的方法
    fl->compute_desired(inter_sweep_current, inter_sweep_estimate, intra_sweep_estimate);
    //CMSSmallCoalSurplusPercent的默认值是1.05,计算一个阈值,控制小块内存被合并成大块内存
    fl->set_coal_desired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent));
    fl->set_before_sweep(fl->count());
    fl->set_bfr_surp(fl->surplus());
  }
  //底层调用同上
  _dictionary->begin_sweep_dict_census(CMSLargeCoalSurplusPercent,
                                    inter_sweep_current,
                                    inter_sweep_estimate,
                                    intra_sweep_estimate);
}

void CompactibleFreeListSpace::endSweepFLCensus(size_t sweep_count) {
  if (PrintFLSStatistics > 0) {
    HeapWord* largestAddr = (HeapWord*) dictionary()->find_largest_dict();
    gclog_or_tty->print_cr("CMS: Large block " PTR_FORMAT,
                           p2i(largestAddr));
  }
  setFLSurplus();
  setFLHints();
  if (PrintGC && PrintFLSCensus > 0) {
    printFLCensus(sweep_count);
  }
  clearFLCensus();
  assert_locked();
  //CMSLargeSplitSurplusPercent是一个因子,默认值是1.0,用来控制大的内存块被切分成更小的内存块
  //end_sweep_dict_census执行的动作跟对FreeList执行的清理动作是一致的
  _dictionary->end_sweep_dict_census(CMSLargeSplitSurplusPercent);
}

void CompactibleFreeListSpace::setFLSurplus() {
  assert_locked();
  size_t i;
  for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
    AdaptiveFreeList<FreeChunk> *fl = &_indexedFreeList[i];
    //重新设置surplus
    fl->set_surplus(fl->count() -
                    (ssize_t)((double)fl->desired() * CMSSmallSplitSurplusPercent));
  }
}

void CompactibleFreeListSpace::setFLHints() {
  assert_locked();
  size_t i;
  size_t h = IndexSetSize;
  //从高到底遍历
  for (i = IndexSetSize - 1; i != 0; i -= IndexSetStride) {
    AdaptiveFreeList<FreeChunk> *fl = &_indexedFreeList[i];
    //设置hint
    fl->set_hint(h);
    if (fl->surplus() > 0) {
      h = i;
    }
  }
}

void CompactibleFreeListSpace::clearFLCensus() {
  assert_locked();
  size_t i;
  for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
    AdaptiveFreeList<FreeChunk> *fl = &_indexedFreeList[i];
    //保存count,计数器清0
    fl->set_prev_sweep(fl->count());
    fl->set_coal_births(0);
    fl->set_coal_deaths(0);
    fl->set_split_births(0);
    fl->set_split_deaths(0);
  }
}

template <class Chunk_t, class FreeList_t>
void BinaryTreeDictionary<Chunk_t, FreeList_t>::end_sweep_dict_census(double splitSurplusPercent) {
  // Does walking the tree 3 times hurt?
  set_tree_surplus(splitSurplusPercent);
  set_tree_hints();
  if (PrintGC && Verbose) {
    report_statistics();
  }
  clear_tree_census();
}



  

发布了117 篇原创文章 · 获赞 8 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_31865983/article/details/103957346