src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp

changeset 1580
e018e6884bd8
parent 1014
0fbdb4381b99
child 1583
05b775309e59
     1.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Wed Dec 16 15:12:51 2009 -0800
     1.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Wed Dec 23 09:23:54 2009 -0800
     1.3 @@ -62,18 +62,15 @@
     1.4    // implementation, namely, the simple binary tree (splaying
     1.5    // temporarily disabled).
     1.6    switch (dictionaryChoice) {
     1.7 -    case FreeBlockDictionary::dictionaryBinaryTree:
     1.8 -      _dictionary = new BinaryTreeDictionary(mr);
     1.9 -      break;
    1.10      case FreeBlockDictionary::dictionarySplayTree:
    1.11      case FreeBlockDictionary::dictionarySkipList:
    1.12      default:
    1.13        warning("dictionaryChoice: selected option not understood; using"
    1.14                " default BinaryTreeDictionary implementation instead.");
    1.15 +    case FreeBlockDictionary::dictionaryBinaryTree:
    1.16        _dictionary = new BinaryTreeDictionary(mr);
    1.17        break;
    1.18    }
    1.19 -  splitBirth(mr.word_size());
    1.20    assert(_dictionary != NULL, "CMS dictionary initialization");
    1.21    // The indexed free lists are initially all empty and are lazily
    1.22    // filled in on demand. Initialize the array elements to NULL.
    1.23 @@ -388,6 +385,105 @@
    1.24    return res;
    1.25  }
    1.26  
    1.27 +void CompactibleFreeListSpace::print_indexed_free_lists(outputStream* st)
    1.28 +const {
    1.29 +  reportIndexedFreeListStatistics();
    1.30 +  gclog_or_tty->print_cr("Layout of Indexed Freelists");
    1.31 +  gclog_or_tty->print_cr("---------------------------");
    1.32 +  FreeList::print_labels_on(st, "size");
    1.33 +  for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
    1.34 +    _indexedFreeList[i].print_on(gclog_or_tty);
    1.35 +    for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL;
    1.36 +         fc = fc->next()) {
    1.37 +      gclog_or_tty->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ")  %s",
    1.38 +                          fc, (HeapWord*)fc + i,
    1.39 +                          fc->cantCoalesce() ? "\t CC" : "");
    1.40 +    }
    1.41 +  }
    1.42 +}
    1.43 +
    1.44 +void CompactibleFreeListSpace::print_promo_info_blocks(outputStream* st)
    1.45 +const {
    1.46 +  _promoInfo.print_on(st);
    1.47 +}
    1.48 +
    1.49 +void CompactibleFreeListSpace::print_dictionary_free_lists(outputStream* st)
    1.50 +const {
    1.51 +  _dictionary->reportStatistics();
    1.52 +  st->print_cr("Layout of Freelists in Tree");
    1.53 +  st->print_cr("---------------------------");
    1.54 +  _dictionary->print_free_lists(st);
    1.55 +}
    1.56 +
    1.57 +class BlkPrintingClosure: public BlkClosure {
    1.58 +  const CMSCollector*             _collector;
    1.59 +  const CompactibleFreeListSpace* _sp;
    1.60 +  const CMSBitMap*                _live_bit_map;
    1.61 +  const bool                      _post_remark;
    1.62 +  outputStream*                   _st;
    1.63 +public:
    1.64 +  BlkPrintingClosure(const CMSCollector* collector,
    1.65 +                     const CompactibleFreeListSpace* sp,
    1.66 +                     const CMSBitMap* live_bit_map,
    1.67 +                     outputStream* st):
    1.68 +    _collector(collector),
    1.69 +    _sp(sp),
    1.70 +    _live_bit_map(live_bit_map),
    1.71 +    _post_remark(collector->abstract_state() > CMSCollector::FinalMarking),
    1.72 +    _st(st) { }
    1.73 +  size_t do_blk(HeapWord* addr);
    1.74 +};
    1.75 +
    1.76 +size_t BlkPrintingClosure::do_blk(HeapWord* addr) {
    1.77 +  size_t sz = _sp->block_size_no_stall(addr, _collector);
    1.78 +  assert(sz != 0, "Should always be able to compute a size");
    1.79 +  if (_sp->block_is_obj(addr)) {
    1.80 +    const bool dead = _post_remark && !_live_bit_map->isMarked(addr);
    1.81 +    _st->print_cr(PTR_FORMAT ": %s object of size " SIZE_FORMAT "%s",
    1.82 +      addr,
    1.83 +      dead ? "dead" : "live",
    1.84 +      sz,
    1.85 +      (!dead && CMSPrintObjectsInDump) ? ":" : ".");
    1.86 +    if (CMSPrintObjectsInDump && !dead) {
    1.87 +      oop(addr)->print_on(_st);
    1.88 +      _st->print_cr("--------------------------------------");
    1.89 +    }
    1.90 +  } else { // free block
    1.91 +    _st->print_cr(PTR_FORMAT ": free block of size " SIZE_FORMAT "%s",
    1.92 +      addr, sz, CMSPrintChunksInDump ? ":" : ".");
    1.93 +    if (CMSPrintChunksInDump) {
    1.94 +      ((FreeChunk*)addr)->print_on(_st);
    1.95 +      _st->print_cr("--------------------------------------");
    1.96 +    }
    1.97 +  }
    1.98 +  return sz;
    1.99 +}
   1.100 +
   1.101 +void CompactibleFreeListSpace::dump_at_safepoint_with_locks(CMSCollector* c,
   1.102 +  outputStream* st) {
   1.103 +  st->print_cr("\n=========================");
   1.104 +  st->print_cr("Block layout in CMS Heap:");
   1.105 +  st->print_cr("=========================");
   1.106 +  BlkPrintingClosure  bpcl(c, this, c->markBitMap(), st);
   1.107 +  blk_iterate(&bpcl);
   1.108 +
   1.109 +  st->print_cr("\n=======================================");
   1.110 +  st->print_cr("Order & Layout of Promotion Info Blocks");
   1.111 +  st->print_cr("=======================================");
   1.112 +  print_promo_info_blocks(st);
   1.113 +
   1.114 +  st->print_cr("\n===========================");
   1.115 +  st->print_cr("Order of Indexed Free Lists");
   1.116 +  st->print_cr("=========================");
   1.117 +  print_indexed_free_lists(st);
   1.118 +
   1.119 +  st->print_cr("\n=================================");
   1.120 +  st->print_cr("Order of Free Lists in Dictionary");
   1.121 +  st->print_cr("=================================");
   1.122 +  print_dictionary_free_lists(st);
   1.123 +}
   1.124 +
   1.125 +
   1.126  void CompactibleFreeListSpace::reportFreeListStatistics() const {
   1.127    assert_lock_strong(&_freelistLock);
   1.128    assert(PrintFLSStatistics != 0, "Reporting error");
   1.129 @@ -449,37 +545,37 @@
   1.130    if (prevEnd != NULL) {
   1.131      // Resize the underlying block offset table.
   1.132      _bt.resize(pointer_delta(value, bottom()));
   1.133 -  if (value <= prevEnd) {
   1.134 -    assert(value >= unallocated_block(), "New end is below unallocated block");
   1.135 -  } else {
   1.136 -    // Now, take this new chunk and add it to the free blocks.
   1.137 -    // Note that the BOT has not yet been updated for this block.
   1.138 -    size_t newFcSize = pointer_delta(value, prevEnd);
   1.139 -    // XXX This is REALLY UGLY and should be fixed up. XXX
   1.140 -    if (!_adaptive_freelists && _smallLinearAllocBlock._ptr == NULL) {
   1.141 -      // Mark the boundary of the new block in BOT
   1.142 -      _bt.mark_block(prevEnd, value);
   1.143 -      // put it all in the linAB
   1.144 -      if (ParallelGCThreads == 0) {
   1.145 -        _smallLinearAllocBlock._ptr = prevEnd;
   1.146 -        _smallLinearAllocBlock._word_size = newFcSize;
   1.147 -        repairLinearAllocBlock(&_smallLinearAllocBlock);
   1.148 -      } else { // ParallelGCThreads > 0
   1.149 -        MutexLockerEx x(parDictionaryAllocLock(),
   1.150 -                        Mutex::_no_safepoint_check_flag);
   1.151 -        _smallLinearAllocBlock._ptr = prevEnd;
   1.152 -        _smallLinearAllocBlock._word_size = newFcSize;
   1.153 -        repairLinearAllocBlock(&_smallLinearAllocBlock);
   1.154 +    if (value <= prevEnd) {
   1.155 +      assert(value >= unallocated_block(), "New end is below unallocated block");
   1.156 +    } else {
   1.157 +      // Now, take this new chunk and add it to the free blocks.
   1.158 +      // Note that the BOT has not yet been updated for this block.
   1.159 +      size_t newFcSize = pointer_delta(value, prevEnd);
   1.160 +      // XXX This is REALLY UGLY and should be fixed up. XXX
   1.161 +      if (!_adaptive_freelists && _smallLinearAllocBlock._ptr == NULL) {
   1.162 +        // Mark the boundary of the new block in BOT
   1.163 +        _bt.mark_block(prevEnd, value);
   1.164 +        // put it all in the linAB
   1.165 +        if (ParallelGCThreads == 0) {
   1.166 +          _smallLinearAllocBlock._ptr = prevEnd;
   1.167 +          _smallLinearAllocBlock._word_size = newFcSize;
   1.168 +          repairLinearAllocBlock(&_smallLinearAllocBlock);
   1.169 +        } else { // ParallelGCThreads > 0
   1.170 +          MutexLockerEx x(parDictionaryAllocLock(),
   1.171 +                          Mutex::_no_safepoint_check_flag);
   1.172 +          _smallLinearAllocBlock._ptr = prevEnd;
   1.173 +          _smallLinearAllocBlock._word_size = newFcSize;
   1.174 +          repairLinearAllocBlock(&_smallLinearAllocBlock);
   1.175 +        }
   1.176 +        // Births of chunks put into a LinAB are not recorded.  Births
   1.177 +        // of chunks as they are allocated out of a LinAB are.
   1.178 +      } else {
   1.179 +        // Add the block to the free lists, if possible coalescing it
   1.180 +        // with the last free block, and update the BOT and census data.
   1.181 +        addChunkToFreeListsAtEndRecordingStats(prevEnd, newFcSize);
   1.182        }
   1.183 -      // Births of chunks put into a LinAB are not recorded.  Births
   1.184 -      // of chunks as they are allocated out of a LinAB are.
   1.185 -    } else {
   1.186 -      // Add the block to the free lists, if possible coalescing it
   1.187 -      // with the last free block, and update the BOT and census data.
   1.188 -      addChunkToFreeListsAtEndRecordingStats(prevEnd, newFcSize);
   1.189      }
   1.190    }
   1.191 -  }
   1.192  }
   1.193  
   1.194  class FreeListSpace_DCTOC : public Filtering_DCTOC {
   1.195 @@ -732,7 +828,7 @@
   1.196  
   1.197  void CompactibleFreeListSpace::object_iterate_mem(MemRegion mr,
   1.198                                                    UpwardsObjectClosure* cl) {
   1.199 -  assert_locked();
   1.200 +  assert_locked(freelistLock());
   1.201    NOT_PRODUCT(verify_objects_initialized());
   1.202    Space::object_iterate_mem(mr, cl);
   1.203  }
   1.204 @@ -1212,12 +1308,15 @@
   1.205  void CompactibleFreeListSpace::assert_locked() const {
   1.206    CMSLockVerifier::assert_locked(freelistLock(), parDictionaryAllocLock());
   1.207  }
   1.208 +
   1.209 +void CompactibleFreeListSpace::assert_locked(const Mutex* lock) const {
   1.210 +  CMSLockVerifier::assert_locked(lock);
   1.211 +}
   1.212  #endif
   1.213  
   1.214  FreeChunk* CompactibleFreeListSpace::allocateScratch(size_t size) {
   1.215    // In the parallel case, the main thread holds the free list lock
   1.216    // on behalf the parallel threads.
   1.217 -  assert_locked();
   1.218    FreeChunk* fc;
   1.219    {
   1.220      // If GC is parallel, this might be called by several threads.
   1.221 @@ -1298,17 +1397,18 @@
   1.222      res = blk->_ptr;
   1.223      _bt.allocated(res, blk->_word_size);
   1.224    } else if (size + MinChunkSize <= blk->_refillSize) {
   1.225 +    size_t sz = blk->_word_size;
   1.226      // Update _unallocated_block if the size is such that chunk would be
   1.227      // returned to the indexed free list.  All other chunks in the indexed
   1.228      // free lists are allocated from the dictionary so that _unallocated_block
   1.229      // has already been adjusted for them.  Do it here so that the cost
   1.230      // for all chunks added back to the indexed free lists.
   1.231 -    if (blk->_word_size < SmallForDictionary) {
   1.232 -      _bt.allocated(blk->_ptr, blk->_word_size);
   1.233 +    if (sz < SmallForDictionary) {
   1.234 +      _bt.allocated(blk->_ptr, sz);
   1.235      }
   1.236      // Return the chunk that isn't big enough, and then refill below.
   1.237 -    addChunkToFreeLists(blk->_ptr, blk->_word_size);
   1.238 -    _bt.verify_single_block(blk->_ptr, (blk->_ptr + blk->_word_size));
   1.239 +    addChunkToFreeLists(blk->_ptr, sz);
   1.240 +    splitBirth(sz);
   1.241      // Don't keep statistics on adding back chunk from a LinAB.
   1.242    } else {
   1.243      // A refilled block would not satisfy the request.
   1.244 @@ -1376,11 +1476,13 @@
   1.245      res = getChunkFromIndexedFreeListHelper(size);
   1.246    }
   1.247    _bt.verify_not_unallocated((HeapWord*) res, size);
   1.248 +  assert(res == NULL || res->size() == size, "Incorrect block size");
   1.249    return res;
   1.250  }
   1.251  
   1.252  FreeChunk*
   1.253 -CompactibleFreeListSpace::getChunkFromIndexedFreeListHelper(size_t size) {
   1.254 +CompactibleFreeListSpace::getChunkFromIndexedFreeListHelper(size_t size,
   1.255 +  bool replenish) {
   1.256    assert_locked();
   1.257    FreeChunk* fc = NULL;
   1.258    if (size < SmallForDictionary) {
   1.259 @@ -1398,54 +1500,66 @@
   1.260        // and replenishing indexed lists from the small linAB.
   1.261        //
   1.262        FreeChunk* newFc = NULL;
   1.263 -      size_t replenish_size = CMSIndexedFreeListReplenish * size;
   1.264 +      const size_t replenish_size = CMSIndexedFreeListReplenish * size;
   1.265        if (replenish_size < SmallForDictionary) {
   1.266          // Do not replenish from an underpopulated size.
   1.267          if (_indexedFreeList[replenish_size].surplus() > 0 &&
   1.268              _indexedFreeList[replenish_size].head() != NULL) {
   1.269 -          newFc =
   1.270 -            _indexedFreeList[replenish_size].getChunkAtHead();
   1.271 -        } else {
   1.272 +          newFc = _indexedFreeList[replenish_size].getChunkAtHead();
   1.273 +        } else if (bestFitFirst()) {
   1.274            newFc = bestFitSmall(replenish_size);
   1.275          }
   1.276        }
   1.277 +      if (newFc == NULL && replenish_size > size) {
   1.278 +        assert(CMSIndexedFreeListReplenish > 1, "ctl pt invariant");
   1.279 +        newFc = getChunkFromIndexedFreeListHelper(replenish_size, false);
   1.280 +      }
   1.281 +      // Note: The stats update re split-death of block obtained above
   1.282 +      // will be recorded below precisely when we know we are going to
   1.283 +      // be actually splitting it into more than one pieces below.
   1.284        if (newFc != NULL) {
   1.285 -        splitDeath(replenish_size);
   1.286 -      } else if (replenish_size > size) {
   1.287 -        assert(CMSIndexedFreeListReplenish > 1, "ctl pt invariant");
   1.288 -        newFc =
   1.289 -          getChunkFromIndexedFreeListHelper(replenish_size);
   1.290 -      }
   1.291 -      if (newFc != NULL) {
   1.292 -        assert(newFc->size() == replenish_size, "Got wrong size");
   1.293 -        size_t i;
   1.294 -        FreeChunk *curFc, *nextFc;
   1.295 -        // carve up and link blocks 0, ..., CMSIndexedFreeListReplenish - 2
   1.296 -        // The last chunk is not added to the lists but is returned as the
   1.297 -        // free chunk.
   1.298 -        for (curFc = newFc, nextFc = (FreeChunk*)((HeapWord*)curFc + size),
   1.299 -             i = 0;
   1.300 -             i < (CMSIndexedFreeListReplenish - 1);
   1.301 -             curFc = nextFc, nextFc = (FreeChunk*)((HeapWord*)nextFc + size),
   1.302 -             i++) {
   1.303 +        if  (replenish || CMSReplenishIntermediate) {
   1.304 +          // Replenish this list and return one block to caller.
   1.305 +          size_t i;
   1.306 +          FreeChunk *curFc, *nextFc;
   1.307 +          size_t num_blk = newFc->size() / size;
   1.308 +          assert(num_blk >= 1, "Smaller than requested?");
   1.309 +          assert(newFc->size() % size == 0, "Should be integral multiple of request");
   1.310 +          if (num_blk > 1) {
   1.311 +            // we are sure we will be splitting the block just obtained
   1.312 +            // into multiple pieces; record the split-death of the original
   1.313 +            splitDeath(replenish_size);
   1.314 +          }
   1.315 +          // carve up and link blocks 0, ..., num_blk - 2
   1.316 +          // The last chunk is not added to the lists but is returned as the
   1.317 +          // free chunk.
   1.318 +          for (curFc = newFc, nextFc = (FreeChunk*)((HeapWord*)curFc + size),
   1.319 +               i = 0;
   1.320 +               i < (num_blk - 1);
   1.321 +               curFc = nextFc, nextFc = (FreeChunk*)((HeapWord*)nextFc + size),
   1.322 +               i++) {
   1.323 +            curFc->setSize(size);
   1.324 +            // Don't record this as a return in order to try and
   1.325 +            // determine the "returns" from a GC.
   1.326 +            _bt.verify_not_unallocated((HeapWord*) fc, size);
   1.327 +            _indexedFreeList[size].returnChunkAtTail(curFc, false);
   1.328 +            _bt.mark_block((HeapWord*)curFc, size);
   1.329 +            splitBirth(size);
   1.330 +            // Don't record the initial population of the indexed list
   1.331 +            // as a split birth.
   1.332 +          }
   1.333 +
   1.334 +          // check that the arithmetic was OK above
   1.335 +          assert((HeapWord*)nextFc == (HeapWord*)newFc + num_blk*size,
   1.336 +            "inconsistency in carving newFc");
   1.337            curFc->setSize(size);
   1.338 -          // Don't record this as a return in order to try and
   1.339 -          // determine the "returns" from a GC.
   1.340 -          _bt.verify_not_unallocated((HeapWord*) fc, size);
   1.341 -          _indexedFreeList[size].returnChunkAtTail(curFc, false);
   1.342            _bt.mark_block((HeapWord*)curFc, size);
   1.343            splitBirth(size);
   1.344 -          // Don't record the initial population of the indexed list
   1.345 -          // as a split birth.
   1.346 +          fc = curFc;
   1.347 +        } else {
   1.348 +          // Return entire block to caller
   1.349 +          fc = newFc;
   1.350          }
   1.351 -
   1.352 -        // check that the arithmetic was OK above
   1.353 -        assert((HeapWord*)nextFc == (HeapWord*)newFc + replenish_size,
   1.354 -          "inconsistency in carving newFc");
   1.355 -        curFc->setSize(size);
   1.356 -        _bt.mark_block((HeapWord*)curFc, size);
   1.357 -        splitBirth(size);
   1.358 -        return curFc;
   1.359        }
   1.360      }
   1.361    } else {
   1.362 @@ -1453,7 +1567,7 @@
   1.363      // replenish the indexed free list.
   1.364      fc = getChunkFromDictionaryExact(size);
   1.365    }
   1.366 -  assert(fc == NULL || fc->isFree(), "Should be returning a free chunk");
   1.367 +  // assert(fc == NULL || fc->isFree(), "Should be returning a free chunk");
   1.368    return fc;
   1.369  }
   1.370  
   1.371 @@ -1512,6 +1626,11 @@
   1.372    // adjust _unallocated_block downward, as necessary
   1.373    _bt.freed((HeapWord*)chunk, size);
   1.374    _dictionary->returnChunk(chunk);
   1.375 +#ifndef PRODUCT
   1.376 +  if (CMSCollector::abstract_state() != CMSCollector::Sweeping) {
   1.377 +    TreeChunk::as_TreeChunk(chunk)->list()->verify_stats();
   1.378 +  }
   1.379 +#endif // PRODUCT
   1.380  }
   1.381  
   1.382  void
   1.383 @@ -1525,6 +1644,11 @@
   1.384    } else {
   1.385      _indexedFreeList[size].returnChunkAtHead(fc);
   1.386    }
   1.387 +#ifndef PRODUCT
   1.388 +  if (CMSCollector::abstract_state() != CMSCollector::Sweeping) {
   1.389 +     _indexedFreeList[size].verify_stats();
   1.390 +  }
   1.391 +#endif // PRODUCT
   1.392  }
   1.393  
   1.394  // Add chunk to end of last block -- if it's the largest
   1.395 @@ -1537,7 +1661,6 @@
   1.396    HeapWord* chunk, size_t     size) {
   1.397    // check that the chunk does lie in this space!
   1.398    assert(chunk != NULL && is_in_reserved(chunk), "Not in this space!");
   1.399 -  assert_locked();
   1.400    // One of the parallel gc task threads may be here
   1.401    // whilst others are allocating.
   1.402    Mutex* lock = NULL;
   1.403 @@ -1991,24 +2114,26 @@
   1.404    return frag;
   1.405  }
   1.406  
   1.407 -#define CoalSurplusPercent 1.05
   1.408 -#define SplitSurplusPercent 1.10
   1.409 -
   1.410  void CompactibleFreeListSpace::beginSweepFLCensus(
   1.411    float inter_sweep_current,
   1.412 -  float inter_sweep_estimate) {
   1.413 +  float inter_sweep_estimate,
   1.414 +  float intra_sweep_estimate) {
   1.415    assert_locked();
   1.416    size_t i;
   1.417    for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
   1.418      FreeList* fl    = &_indexedFreeList[i];
   1.419 -    fl->compute_desired(inter_sweep_current, inter_sweep_estimate);
   1.420 -    fl->set_coalDesired((ssize_t)((double)fl->desired() * CoalSurplusPercent));
   1.421 +    if (PrintFLSStatistics > 1) {
   1.422 +      gclog_or_tty->print("size[%d] : ", i);
   1.423 +    }
   1.424 +    fl->compute_desired(inter_sweep_current, inter_sweep_estimate, intra_sweep_estimate);
   1.425 +    fl->set_coalDesired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent));
   1.426      fl->set_beforeSweep(fl->count());
   1.427      fl->set_bfrSurp(fl->surplus());
   1.428    }
   1.429 -  _dictionary->beginSweepDictCensus(CoalSurplusPercent,
   1.430 +  _dictionary->beginSweepDictCensus(CMSLargeCoalSurplusPercent,
   1.431                                      inter_sweep_current,
   1.432 -                                    inter_sweep_estimate);
   1.433 +                                    inter_sweep_estimate,
   1.434 +                                    intra_sweep_estimate);
   1.435  }
   1.436  
   1.437  void CompactibleFreeListSpace::setFLSurplus() {
   1.438 @@ -2017,7 +2142,7 @@
   1.439    for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
   1.440      FreeList *fl = &_indexedFreeList[i];
   1.441      fl->set_surplus(fl->count() -
   1.442 -                    (ssize_t)((double)fl->desired() * SplitSurplusPercent));
   1.443 +                    (ssize_t)((double)fl->desired() * CMSSmallSplitSurplusPercent));
   1.444    }
   1.445  }
   1.446  
   1.447 @@ -2048,6 +2173,11 @@
   1.448  }
   1.449  
   1.450  void CompactibleFreeListSpace::endSweepFLCensus(size_t sweep_count) {
   1.451 +  if (PrintFLSStatistics > 0) {
   1.452 +    HeapWord* largestAddr = (HeapWord*) dictionary()->findLargestDict();
   1.453 +    gclog_or_tty->print_cr("CMS: Large block " PTR_FORMAT,
   1.454 +                           largestAddr);
   1.455 +  }
   1.456    setFLSurplus();
   1.457    setFLHints();
   1.458    if (PrintGC && PrintFLSCensus > 0) {
   1.459 @@ -2055,7 +2185,7 @@
   1.460    }
   1.461    clearFLCensus();
   1.462    assert_locked();
   1.463 -  _dictionary->endSweepDictCensus(SplitSurplusPercent);
   1.464 +  _dictionary->endSweepDictCensus(CMSLargeSplitSurplusPercent);
   1.465  }
   1.466  
   1.467  bool CompactibleFreeListSpace::coalOverPopulated(size_t size) {
   1.468 @@ -2312,13 +2442,18 @@
   1.469  }
   1.470  
   1.471  void CompactibleFreeListSpace::verifyIndexedFreeList(size_t size) const {
   1.472 -  FreeChunk* fc =  _indexedFreeList[size].head();
   1.473 +  FreeChunk* fc   =  _indexedFreeList[size].head();
   1.474 +  FreeChunk* tail =  _indexedFreeList[size].tail();
   1.475 +  size_t    num = _indexedFreeList[size].count();
   1.476 +  size_t      n = 0;
   1.477    guarantee((size % 2 == 0) || fc == NULL, "Odd slots should be empty");
   1.478 -  for (; fc != NULL; fc = fc->next()) {
   1.479 +  for (; fc != NULL; fc = fc->next(), n++) {
   1.480      guarantee(fc->size() == size, "Size inconsistency");
   1.481      guarantee(fc->isFree(), "!free?");
   1.482      guarantee(fc->next() == NULL || fc->next()->prev() == fc, "Broken list");
   1.483 +    guarantee((fc->next() == NULL) == (fc == tail), "Incorrect tail");
   1.484    }
   1.485 +  guarantee(n == num, "Incorrect count");
   1.486  }
   1.487  
   1.488  #ifndef PRODUCT
   1.489 @@ -2516,11 +2651,41 @@
   1.490    _tracking = true;
   1.491  }
   1.492  
   1.493 -void PromotionInfo::stopTrackingPromotions() {
   1.494 +#define CMSPrintPromoBlockInfo 1
   1.495 +
   1.496 +void PromotionInfo::stopTrackingPromotions(uint worker_id) {
   1.497    assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex,
   1.498           "spooling inconsistency?");
   1.499    _firstIndex = _nextIndex = 1;
   1.500    _tracking = false;
   1.501 +  if (CMSPrintPromoBlockInfo > 1) {
   1.502 +    print_statistics(worker_id);
   1.503 +  }
   1.504 +}
   1.505 +
   1.506 +void PromotionInfo::print_statistics(uint worker_id) const {
   1.507 +  assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex,
   1.508 +         "Else will undercount");
   1.509 +  assert(CMSPrintPromoBlockInfo > 0, "Else unnecessary call");
   1.510 +  // Count the number of blocks and slots in the free pool
   1.511 +  size_t slots  = 0;
   1.512 +  size_t blocks = 0;
   1.513 +  for (SpoolBlock* cur_spool = _spareSpool;
   1.514 +       cur_spool != NULL;
   1.515 +       cur_spool = cur_spool->nextSpoolBlock) {
   1.516 +    // the first entry is just a self-pointer; indices 1 through
   1.517 +    // bufferSize - 1 are occupied (thus, bufferSize - 1 slots).
   1.518 +    guarantee((void*)cur_spool->displacedHdr == (void*)&cur_spool->displacedHdr,
   1.519 +              "first entry of displacedHdr should be self-referential");
   1.520 +    slots += cur_spool->bufferSize - 1;
   1.521 +    blocks++;
   1.522 +  }
   1.523 +  if (_spoolHead != NULL) {
   1.524 +    slots += _spoolHead->bufferSize - 1;
   1.525 +    blocks++;
   1.526 +  }
   1.527 +  gclog_or_tty->print_cr(" [worker %d] promo_blocks = %d, promo_slots = %d ",
   1.528 +                         worker_id, blocks, slots);
   1.529  }
   1.530  
   1.531  // When _spoolTail is not NULL, then the slot <_spoolTail, _nextIndex>
   1.532 @@ -2584,15 +2749,84 @@
   1.533    guarantee(numDisplacedHdrs == numObjsWithDisplacedHdrs, "Displaced hdr count");
   1.534  }
   1.535  
   1.536 +void PromotionInfo::print_on(outputStream* st) const {
   1.537 +  SpoolBlock* curSpool = NULL;
   1.538 +  size_t i = 0;
   1.539 +  st->print_cr("start & end indices: [" SIZE_FORMAT ", " SIZE_FORMAT ")",
   1.540 +               _firstIndex, _nextIndex);
   1.541 +  for (curSpool = _spoolHead; curSpool != _spoolTail && curSpool != NULL;
   1.542 +       curSpool = curSpool->nextSpoolBlock) {
   1.543 +    curSpool->print_on(st);
   1.544 +    st->print_cr(" active ");
   1.545 +    i++;
   1.546 +  }
   1.547 +  for (curSpool = _spoolTail; curSpool != NULL;
   1.548 +       curSpool = curSpool->nextSpoolBlock) {
   1.549 +    curSpool->print_on(st);
   1.550 +    st->print_cr(" inactive ");
   1.551 +    i++;
   1.552 +  }
   1.553 +  for (curSpool = _spareSpool; curSpool != NULL;
   1.554 +       curSpool = curSpool->nextSpoolBlock) {
   1.555 +    curSpool->print_on(st);
   1.556 +    st->print_cr(" free ");
   1.557 +    i++;
   1.558 +  }
   1.559 +  st->print_cr(SIZE_FORMAT " header spooling blocks", i);
   1.560 +}
   1.561 +
   1.562 +void SpoolBlock::print_on(outputStream* st) const {
   1.563 +  st->print("[" PTR_FORMAT "," PTR_FORMAT "), " SIZE_FORMAT " HeapWords -> " PTR_FORMAT,
   1.564 +            this, (HeapWord*)displacedHdr + bufferSize,
   1.565 +            bufferSize, nextSpoolBlock);
   1.566 +}
   1.567 +
   1.568 +///////////////////////////////////////////////////////////////////////////
   1.569 +// CFLS_LAB
   1.570 +///////////////////////////////////////////////////////////////////////////
   1.571 +
   1.572 +#define VECTOR_257(x)                                                                                  \
   1.573 +  /* 1  2  3  4  5  6  7  8  9 1x 11 12 13 14 15 16 17 18 19 2x 21 22 23 24 25 26 27 28 29 3x 31 32 */ \
   1.574 +  {  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,   \
   1.575 +     x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,   \
   1.576 +     x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,   \
   1.577 +     x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,   \
   1.578 +     x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,   \
   1.579 +     x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,   \
   1.580 +     x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,   \
   1.581 +     x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,   \
   1.582 +     x }
   1.583 +
   1.584 +// Initialize with default setting of CMSParPromoteBlocksToClaim, _not_
   1.585 +// OldPLABSize, whose static default is different; if overridden at the
   1.586 +// command-line, this will get reinitialized via a call to
   1.587 +// modify_initialization() below.
   1.588 +AdaptiveWeightedAverage CFLS_LAB::_blocks_to_claim[]    =
   1.589 +  VECTOR_257(AdaptiveWeightedAverage(OldPLABWeight, (float)CMSParPromoteBlocksToClaim));
   1.590 +size_t CFLS_LAB::_global_num_blocks[]  = VECTOR_257(0);
   1.591 +int    CFLS_LAB::_global_num_workers[] = VECTOR_257(0);
   1.592  
   1.593  CFLS_LAB::CFLS_LAB(CompactibleFreeListSpace* cfls) :
   1.594    _cfls(cfls)
   1.595  {
   1.596 -  _blocks_to_claim = CMSParPromoteBlocksToClaim;
   1.597 +  assert(CompactibleFreeListSpace::IndexSetSize == 257, "Modify VECTOR_257() macro above");
   1.598    for (size_t i = CompactibleFreeListSpace::IndexSetStart;
   1.599         i < CompactibleFreeListSpace::IndexSetSize;
   1.600         i += CompactibleFreeListSpace::IndexSetStride) {
   1.601      _indexedFreeList[i].set_size(i);
   1.602 +    _num_blocks[i] = 0;
   1.603 +  }
   1.604 +}
   1.605 +
   1.606 +static bool _CFLS_LAB_modified = false;
   1.607 +
   1.608 +void CFLS_LAB::modify_initialization(size_t n, unsigned wt) {
   1.609 +  assert(!_CFLS_LAB_modified, "Call only once");
   1.610 +  _CFLS_LAB_modified = true;
   1.611 +  for (size_t i = CompactibleFreeListSpace::IndexSetStart;
   1.612 +       i < CompactibleFreeListSpace::IndexSetSize;
   1.613 +       i += CompactibleFreeListSpace::IndexSetStride) {
   1.614 +    _blocks_to_claim[i].modify(n, wt, true /* force */);
   1.615    }
   1.616  }
   1.617  
   1.618 @@ -2607,11 +2841,9 @@
   1.619      if (res == NULL) return NULL;
   1.620    } else {
   1.621      FreeList* fl = &_indexedFreeList[word_sz];
   1.622 -    bool filled = false; //TRAP
   1.623      if (fl->count() == 0) {
   1.624 -      bool filled = true; //TRAP
   1.625        // Attempt to refill this local free list.
   1.626 -      _cfls->par_get_chunk_of_blocks(word_sz, _blocks_to_claim, fl);
   1.627 +      get_from_global_pool(word_sz, fl);
   1.628        // If it didn't work, give up.
   1.629        if (fl->count() == 0) return NULL;
   1.630      }
   1.631 @@ -2626,80 +2858,190 @@
   1.632    return (HeapWord*)res;
   1.633  }
   1.634  
   1.635 -void CFLS_LAB::retire() {
   1.636 -  for (size_t i = CompactibleFreeListSpace::IndexSetStart;
   1.637 +// Get a chunk of blocks of the right size and update related
   1.638 +// book-keeping stats
   1.639 +void CFLS_LAB::get_from_global_pool(size_t word_sz, FreeList* fl) {
   1.640 +  // Get the #blocks we want to claim
   1.641 +  size_t n_blks = (size_t)_blocks_to_claim[word_sz].average();
   1.642 +  assert(n_blks > 0, "Error");
   1.643 +  assert(ResizePLAB || n_blks == OldPLABSize, "Error");
   1.644 +  // In some cases, when the application has a phase change,
   1.645 +  // there may be a sudden and sharp shift in the object survival
   1.646 +  // profile, and updating the counts at the end of a scavenge
   1.647 +  // may not be quick enough, giving rise to large scavenge pauses
   1.648 +  // during these phase changes. It is beneficial to detect such
   1.649 +  // changes on-the-fly during a scavenge and avoid such a phase-change
   1.650 +  // pothole. The following code is a heuristic attempt to do that.
   1.651 +  // It is protected by a product flag until we have gained
   1.652 +  // enough experience with this heuristic and fine-tuned its behaviour.
   1.653 +  // WARNING: This might increase fragmentation if we overreact to
   1.654 +  // small spikes, so some kind of historical smoothing based on
   1.655 +  // previous experience with the greater reactivity might be useful.
   1.656 +  // Lacking sufficient experience, CMSOldPLABResizeQuicker is disabled by
   1.657 +  // default.
   1.658 +  if (ResizeOldPLAB && CMSOldPLABResizeQuicker) {
   1.659 +    size_t multiple = _num_blocks[word_sz]/(CMSOldPLABToleranceFactor*CMSOldPLABNumRefills*n_blks);
   1.660 +    n_blks +=  CMSOldPLABReactivityFactor*multiple*n_blks;
   1.661 +    n_blks = MIN2(n_blks, CMSOldPLABMax);
   1.662 +  }
   1.663 +  assert(n_blks > 0, "Error");
   1.664 +  _cfls->par_get_chunk_of_blocks(word_sz, n_blks, fl);
   1.665 +  // Update stats table entry for this block size
   1.666 +  _num_blocks[word_sz] += fl->count();
   1.667 +}
   1.668 +
   1.669 +void CFLS_LAB::compute_desired_plab_size() {
   1.670 +  for (size_t i =  CompactibleFreeListSpace::IndexSetStart;
   1.671         i < CompactibleFreeListSpace::IndexSetSize;
   1.672         i += CompactibleFreeListSpace::IndexSetStride) {
   1.673 -    if (_indexedFreeList[i].count() > 0) {
   1.674 -      MutexLockerEx x(_cfls->_indexedFreeListParLocks[i],
   1.675 -                      Mutex::_no_safepoint_check_flag);
   1.676 -      _cfls->_indexedFreeList[i].prepend(&_indexedFreeList[i]);
   1.677 -      // Reset this list.
   1.678 -      _indexedFreeList[i] = FreeList();
   1.679 -      _indexedFreeList[i].set_size(i);
   1.680 +    assert((_global_num_workers[i] == 0) == (_global_num_blocks[i] == 0),
   1.681 +           "Counter inconsistency");
   1.682 +    if (_global_num_workers[i] > 0) {
   1.683 +      // Need to smooth wrt historical average
   1.684 +      if (ResizeOldPLAB) {
   1.685 +        _blocks_to_claim[i].sample(
   1.686 +          MAX2((size_t)CMSOldPLABMin,
   1.687 +          MIN2((size_t)CMSOldPLABMax,
   1.688 +               _global_num_blocks[i]/(_global_num_workers[i]*CMSOldPLABNumRefills))));
   1.689 +      }
   1.690 +      // Reset counters for next round
   1.691 +      _global_num_workers[i] = 0;
   1.692 +      _global_num_blocks[i] = 0;
   1.693 +      if (PrintOldPLAB) {
   1.694 +        gclog_or_tty->print_cr("[%d]: %d", i, (size_t)_blocks_to_claim[i].average());
   1.695 +      }
   1.696      }
   1.697    }
   1.698  }
   1.699  
   1.700 -void
   1.701 -CompactibleFreeListSpace::
   1.702 -par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl) {
   1.703 +void CFLS_LAB::retire(int tid) {
   1.704 +  // We run this single threaded with the world stopped;
   1.705 +  // so no need for locks and such.
   1.706 +#define CFLS_LAB_PARALLEL_ACCESS 0
   1.707 +  NOT_PRODUCT(Thread* t = Thread::current();)
   1.708 +  assert(Thread::current()->is_VM_thread(), "Error");
   1.709 +  assert(CompactibleFreeListSpace::IndexSetStart == CompactibleFreeListSpace::IndexSetStride,
   1.710 +         "Will access to uninitialized slot below");
   1.711 +#if CFLS_LAB_PARALLEL_ACCESS
   1.712 +  for (size_t i = CompactibleFreeListSpace::IndexSetSize - 1;
   1.713 +       i > 0;
   1.714 +       i -= CompactibleFreeListSpace::IndexSetStride) {
   1.715 +#else // CFLS_LAB_PARALLEL_ACCESS
   1.716 +  for (size_t i =  CompactibleFreeListSpace::IndexSetStart;
   1.717 +       i < CompactibleFreeListSpace::IndexSetSize;
   1.718 +       i += CompactibleFreeListSpace::IndexSetStride) {
   1.719 +#endif // !CFLS_LAB_PARALLEL_ACCESS
   1.720 +    assert(_num_blocks[i] >= (size_t)_indexedFreeList[i].count(),
   1.721 +           "Can't retire more than what we obtained");
   1.722 +    if (_num_blocks[i] > 0) {
   1.723 +      size_t num_retire =  _indexedFreeList[i].count();
   1.724 +      assert(_num_blocks[i] > num_retire, "Should have used at least one");
   1.725 +      {
   1.726 +#if CFLS_LAB_PARALLEL_ACCESS
   1.727 +        MutexLockerEx x(_cfls->_indexedFreeListParLocks[i],
   1.728 +                        Mutex::_no_safepoint_check_flag);
   1.729 +#endif // CFLS_LAB_PARALLEL_ACCESS
   1.730 +        // Update globals stats for num_blocks used
   1.731 +        _global_num_blocks[i] += (_num_blocks[i] - num_retire);
   1.732 +        _global_num_workers[i]++;
   1.733 +        assert(_global_num_workers[i] <= (ssize_t)ParallelGCThreads, "Too big");
   1.734 +        if (num_retire > 0) {
   1.735 +          _cfls->_indexedFreeList[i].prepend(&_indexedFreeList[i]);
   1.736 +          // Reset this list.
   1.737 +          _indexedFreeList[i] = FreeList();
   1.738 +          _indexedFreeList[i].set_size(i);
   1.739 +        }
   1.740 +      }
   1.741 +      if (PrintOldPLAB) {
   1.742 +        gclog_or_tty->print_cr("%d[%d]: %d/%d/%d",
   1.743 +                               tid, i, num_retire, _num_blocks[i], (size_t)_blocks_to_claim[i].average());
   1.744 +      }
   1.745 +      // Reset stats for next round
   1.746 +      _num_blocks[i]         = 0;
   1.747 +    }
   1.748 +  }
   1.749 +}
   1.750 +
   1.751 +void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl) {
   1.752    assert(fl->count() == 0, "Precondition.");
   1.753    assert(word_sz < CompactibleFreeListSpace::IndexSetSize,
   1.754           "Precondition");
   1.755  
   1.756 -  // We'll try all multiples of word_sz in the indexed set (starting with
   1.757 -  // word_sz itself), then try getting a big chunk and splitting it.
   1.758 -  int k = 1;
   1.759 -  size_t cur_sz = k * word_sz;
   1.760 -  bool found = false;
   1.761 -  while (cur_sz < CompactibleFreeListSpace::IndexSetSize && k == 1) {
   1.762 -    FreeList* gfl = &_indexedFreeList[cur_sz];
   1.763 -    FreeList fl_for_cur_sz;  // Empty.
   1.764 -    fl_for_cur_sz.set_size(cur_sz);
   1.765 -    {
   1.766 -      MutexLockerEx x(_indexedFreeListParLocks[cur_sz],
   1.767 -                      Mutex::_no_safepoint_check_flag);
   1.768 -      if (gfl->count() != 0) {
   1.769 -        size_t nn = MAX2(n/k, (size_t)1);
   1.770 -        gfl->getFirstNChunksFromList(nn, &fl_for_cur_sz);
   1.771 -        found = true;
   1.772 +  // We'll try all multiples of word_sz in the indexed set, starting with
   1.773 +  // word_sz itself and, if CMSSplitIndexedFreeListBlocks, try larger multiples,
   1.774 +  // then try getting a big chunk and splitting it.
   1.775 +  {
   1.776 +    bool found;
   1.777 +    int  k;
   1.778 +    size_t cur_sz;
   1.779 +    for (k = 1, cur_sz = k * word_sz, found = false;
   1.780 +         (cur_sz < CompactibleFreeListSpace::IndexSetSize) &&
   1.781 +         (CMSSplitIndexedFreeListBlocks || k <= 1);
   1.782 +         k++, cur_sz = k * word_sz) {
   1.783 +      FreeList* gfl = &_indexedFreeList[cur_sz];
   1.784 +      FreeList fl_for_cur_sz;  // Empty.
   1.785 +      fl_for_cur_sz.set_size(cur_sz);
   1.786 +      {
   1.787 +        MutexLockerEx x(_indexedFreeListParLocks[cur_sz],
   1.788 +                        Mutex::_no_safepoint_check_flag);
   1.789 +        if (gfl->count() != 0) {
   1.790 +          // nn is the number of chunks of size cur_sz that
   1.791 +          // we'd need to split k-ways each, in order to create
   1.792 +          // "n" chunks of size word_sz each.
   1.793 +          const size_t nn = MAX2(n/k, (size_t)1);
   1.794 +          gfl->getFirstNChunksFromList(nn, &fl_for_cur_sz);
   1.795 +          found = true;
   1.796 +          if (k > 1) {
   1.797 +            // Update split death stats for the cur_sz-size blocks list:
   1.798 +            // we increment the split death count by the number of blocks
   1.799 +            // we just took from the cur_sz-size blocks list and which
   1.800 +            // we will be splitting below.
   1.801 +            ssize_t deaths = _indexedFreeList[cur_sz].splitDeaths() +
   1.802 +                             fl_for_cur_sz.count();
   1.803 +            _indexedFreeList[cur_sz].set_splitDeaths(deaths);
   1.804 +          }
   1.805 +        }
   1.806 +      }
   1.807 +      // Now transfer fl_for_cur_sz to fl.  Common case, we hope, is k = 1.
   1.808 +      if (found) {
   1.809 +        if (k == 1) {
   1.810 +          fl->prepend(&fl_for_cur_sz);
   1.811 +        } else {
   1.812 +          // Divide each block on fl_for_cur_sz up k ways.
   1.813 +          FreeChunk* fc;
   1.814 +          while ((fc = fl_for_cur_sz.getChunkAtHead()) != NULL) {
   1.815 +            // Must do this in reverse order, so that anybody attempting to
   1.816 +            // access the main chunk sees it as a single free block until we
   1.817 +            // change it.
   1.818 +            size_t fc_size = fc->size();
   1.819 +            for (int i = k-1; i >= 0; i--) {
   1.820 +              FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz);
   1.821 +              ffc->setSize(word_sz);
   1.822 +              ffc->linkNext(NULL);
   1.823 +              ffc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads.
   1.824 +              // Above must occur before BOT is updated below.
   1.825 +              // splitting from the right, fc_size == (k - i + 1) * wordsize
   1.826 +              _bt.mark_block((HeapWord*)ffc, word_sz);
   1.827 +              fc_size -= word_sz;
   1.828 +              _bt.verify_not_unallocated((HeapWord*)ffc, ffc->size());
   1.829 +              _bt.verify_single_block((HeapWord*)fc, fc_size);
   1.830 +              _bt.verify_single_block((HeapWord*)ffc, ffc->size());
   1.831 +              // Push this on "fl".
   1.832 +              fl->returnChunkAtHead(ffc);
   1.833 +            }
   1.834 +            // TRAP
   1.835 +            assert(fl->tail()->next() == NULL, "List invariant.");
   1.836 +          }
   1.837 +        }
   1.838 +        // Update birth stats for this block size.
   1.839 +        size_t num = fl->count();
   1.840 +        MutexLockerEx x(_indexedFreeListParLocks[word_sz],
   1.841 +                        Mutex::_no_safepoint_check_flag);
   1.842 +        ssize_t births = _indexedFreeList[word_sz].splitBirths() + num;
   1.843 +        _indexedFreeList[word_sz].set_splitBirths(births);
   1.844 +        return;
   1.845        }
   1.846      }
   1.847 -    // Now transfer fl_for_cur_sz to fl.  Common case, we hope, is k = 1.
   1.848 -    if (found) {
   1.849 -      if (k == 1) {
   1.850 -        fl->prepend(&fl_for_cur_sz);
   1.851 -      } else {
   1.852 -        // Divide each block on fl_for_cur_sz up k ways.
   1.853 -        FreeChunk* fc;
   1.854 -        while ((fc = fl_for_cur_sz.getChunkAtHead()) != NULL) {
   1.855 -          // Must do this in reverse order, so that anybody attempting to
   1.856 -          // access the main chunk sees it as a single free block until we
   1.857 -          // change it.
   1.858 -          size_t fc_size = fc->size();
   1.859 -          for (int i = k-1; i >= 0; i--) {
   1.860 -            FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz);
   1.861 -            ffc->setSize(word_sz);
   1.862 -            ffc->linkNext(NULL);
   1.863 -            ffc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads.
   1.864 -            // Above must occur before BOT is updated below.
   1.865 -            // splitting from the right, fc_size == (k - i + 1) * wordsize
   1.866 -            _bt.mark_block((HeapWord*)ffc, word_sz);
   1.867 -            fc_size -= word_sz;
   1.868 -            _bt.verify_not_unallocated((HeapWord*)ffc, ffc->size());
   1.869 -            _bt.verify_single_block((HeapWord*)fc, fc_size);
   1.870 -            _bt.verify_single_block((HeapWord*)ffc, ffc->size());
   1.871 -            // Push this on "fl".
   1.872 -            fl->returnChunkAtHead(ffc);
   1.873 -          }
   1.874 -          // TRAP
   1.875 -          assert(fl->tail()->next() == NULL, "List invariant.");
   1.876 -        }
   1.877 -      }
   1.878 -      return;
   1.879 -    }
   1.880 -    k++; cur_sz = k * word_sz;
   1.881    }
   1.882    // Otherwise, we'll split a block from the dictionary.
   1.883    FreeChunk* fc = NULL;
   1.884 @@ -2723,17 +3065,20 @@
   1.885        }
   1.886      }
   1.887      if (fc == NULL) return;
   1.888 +    assert((ssize_t)n >= 1, "Control point invariant");
   1.889      // Otherwise, split up that block.
   1.890 -    size_t nn = fc->size() / word_sz;
   1.891 +    const size_t nn = fc->size() / word_sz;
   1.892      n = MIN2(nn, n);
   1.893 +    assert((ssize_t)n >= 1, "Control point invariant");
   1.894      rem = fc->size() - n * word_sz;
   1.895      // If there is a remainder, and it's too small, allocate one fewer.
   1.896      if (rem > 0 && rem < MinChunkSize) {
   1.897        n--; rem += word_sz;
   1.898      }
   1.899 +    assert((ssize_t)n >= 1, "Control point invariant");
   1.900      // First return the remainder, if any.
   1.901      // Note that we hold the lock until we decide if we're going to give
   1.902 -    // back the remainder to the dictionary, since a contending allocator
   1.903 +    // back the remainder to the dictionary, since a concurrent allocation
   1.904      // may otherwise see the heap as empty.  (We're willing to take that
   1.905      // hit if the block is a small block.)
   1.906      if (rem > 0) {
   1.907 @@ -2743,18 +3088,16 @@
   1.908        rem_fc->linkNext(NULL);
   1.909        rem_fc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads.
   1.910        // Above must occur before BOT is updated below.
   1.911 +      assert((ssize_t)n > 0 && prefix_size > 0 && rem_fc > fc, "Error");
   1.912        _bt.split_block((HeapWord*)fc, fc->size(), prefix_size);
   1.913        if (rem >= IndexSetSize) {
   1.914          returnChunkToDictionary(rem_fc);
   1.915 -        dictionary()->dictCensusUpdate(fc->size(),
   1.916 -                                       true /*split*/,
   1.917 -                                       true /*birth*/);
   1.918 +        dictionary()->dictCensusUpdate(rem, true /*split*/, true /*birth*/);
   1.919          rem_fc = NULL;
   1.920        }
   1.921        // Otherwise, return it to the small list below.
   1.922      }
   1.923    }
   1.924 -  //
   1.925    if (rem_fc != NULL) {
   1.926      MutexLockerEx x(_indexedFreeListParLocks[rem],
   1.927                      Mutex::_no_safepoint_check_flag);
   1.928 @@ -2762,7 +3105,7 @@
   1.929      _indexedFreeList[rem].returnChunkAtHead(rem_fc);
   1.930      smallSplitBirth(rem);
   1.931    }
   1.932 -
   1.933 +  assert((ssize_t)n > 0 && fc != NULL, "Consistency");
   1.934    // Now do the splitting up.
   1.935    // Must do this in reverse order, so that anybody attempting to
   1.936    // access the main chunk sees it as a single free block until we
   1.937 @@ -2792,13 +3135,15 @@
   1.938    _bt.verify_single_block((HeapWord*)fc, fc->size());
   1.939    fl->returnChunkAtHead(fc);
   1.940  
   1.941 +  assert((ssize_t)n > 0 && (ssize_t)n == fl->count(), "Incorrect number of blocks");
   1.942    {
   1.943 +    // Update the stats for this block size.
   1.944      MutexLockerEx x(_indexedFreeListParLocks[word_sz],
   1.945                      Mutex::_no_safepoint_check_flag);
   1.946 -    ssize_t new_births = _indexedFreeList[word_sz].splitBirths() + n;
   1.947 -    _indexedFreeList[word_sz].set_splitBirths(new_births);
   1.948 -    ssize_t new_surplus = _indexedFreeList[word_sz].surplus() + n;
   1.949 -    _indexedFreeList[word_sz].set_surplus(new_surplus);
   1.950 +    const ssize_t births = _indexedFreeList[word_sz].splitBirths() + n;
   1.951 +    _indexedFreeList[word_sz].set_splitBirths(births);
   1.952 +    // ssize_t new_surplus = _indexedFreeList[word_sz].surplus() + n;
   1.953 +    // _indexedFreeList[word_sz].set_surplus(new_surplus);
   1.954    }
   1.955  
   1.956    // TRAP

mercurial