mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 22:34:27 +02:00
7131629: Generalize the CMS free list code
Make the FreeChunk, FreeList, TreeList, and BinaryTreeDictionary classes usable outside CMS. Reviewed-by: brutisso, johnc, jwilhelm
This commit is contained in:
parent
6de80de07f
commit
f5558edf7b
17 changed files with 579 additions and 449 deletions
|
@ -38,7 +38,7 @@
|
|||
|
||||
CMSPermGen::CMSPermGen(ReservedSpace rs, size_t initial_byte_size,
|
||||
CardTableRS* ct,
|
||||
FreeBlockDictionary::DictionaryChoice dictionaryChoice) {
|
||||
FreeBlockDictionary<FreeChunk>::DictionaryChoice dictionaryChoice) {
|
||||
CMSPermGenGen* g =
|
||||
new CMSPermGenGen(rs, initial_byte_size, -1, ct);
|
||||
if (g == NULL) {
|
||||
|
|
|
@ -45,7 +45,7 @@ class CMSPermGen: public PermGen {
|
|||
|
||||
public:
|
||||
CMSPermGen(ReservedSpace rs, size_t initial_byte_size,
|
||||
CardTableRS* ct, FreeBlockDictionary::DictionaryChoice);
|
||||
CardTableRS* ct, FreeBlockDictionary<FreeChunk>::DictionaryChoice);
|
||||
|
||||
HeapWord* mem_allocate(size_t size);
|
||||
|
||||
|
@ -65,7 +65,7 @@ public:
|
|||
// regarding not using adaptive free lists for a perm gen.
|
||||
ConcurrentMarkSweepGeneration(rs, initial_byte_size, // MinPermHeapExapnsion
|
||||
level, ct, false /* use adaptive freelists */,
|
||||
(FreeBlockDictionary::DictionaryChoice)CMSDictionaryChoice)
|
||||
(FreeBlockDictionary<FreeChunk>::DictionaryChoice)CMSDictionaryChoice)
|
||||
{}
|
||||
|
||||
void initialize_performance_counters();
|
||||
|
|
|
@ -69,7 +69,7 @@ void CompactibleFreeListSpace::set_cms_values() {
|
|||
// Constructor
|
||||
CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs,
|
||||
MemRegion mr, bool use_adaptive_freelists,
|
||||
FreeBlockDictionary::DictionaryChoice dictionaryChoice) :
|
||||
FreeBlockDictionary<FreeChunk>::DictionaryChoice dictionaryChoice) :
|
||||
_dictionaryChoice(dictionaryChoice),
|
||||
_adaptive_freelists(use_adaptive_freelists),
|
||||
_bt(bs, mr),
|
||||
|
@ -87,6 +87,8 @@ CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs,
|
|||
CMSConcMarkMultiple),
|
||||
_collector(NULL)
|
||||
{
|
||||
assert(sizeof(FreeChunk) / BytesPerWord <= MinChunkSize,
|
||||
"FreeChunk is larger than expected");
|
||||
_bt.set_space(this);
|
||||
initialize(mr, SpaceDecorator::Clear, SpaceDecorator::Mangle);
|
||||
// We have all of "mr", all of which we place in the dictionary
|
||||
|
@ -96,13 +98,13 @@ CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs,
|
|||
// implementation, namely, the simple binary tree (splaying
|
||||
// temporarily disabled).
|
||||
switch (dictionaryChoice) {
|
||||
case FreeBlockDictionary::dictionarySplayTree:
|
||||
case FreeBlockDictionary::dictionarySkipList:
|
||||
case FreeBlockDictionary<FreeChunk>::dictionarySplayTree:
|
||||
case FreeBlockDictionary<FreeChunk>::dictionarySkipList:
|
||||
default:
|
||||
warning("dictionaryChoice: selected option not understood; using"
|
||||
" default BinaryTreeDictionary implementation instead.");
|
||||
case FreeBlockDictionary::dictionaryBinaryTree:
|
||||
_dictionary = new BinaryTreeDictionary(mr);
|
||||
case FreeBlockDictionary<FreeChunk>::dictionaryBinaryTree:
|
||||
_dictionary = new BinaryTreeDictionary<FreeChunk>(mr, use_adaptive_freelists);
|
||||
break;
|
||||
}
|
||||
assert(_dictionary != NULL, "CMS dictionary initialization");
|
||||
|
@ -448,7 +450,7 @@ const {
|
|||
reportIndexedFreeListStatistics();
|
||||
gclog_or_tty->print_cr("Layout of Indexed Freelists");
|
||||
gclog_or_tty->print_cr("---------------------------");
|
||||
FreeList::print_labels_on(st, "size");
|
||||
FreeList<FreeChunk>::print_labels_on(st, "size");
|
||||
for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
|
||||
_indexedFreeList[i].print_on(gclog_or_tty);
|
||||
for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL;
|
||||
|
@ -1331,7 +1333,7 @@ FreeChunk* CompactibleFreeListSpace::getChunkFromGreater(size_t numWords) {
|
|||
size_t currSize = numWords + MinChunkSize;
|
||||
assert(currSize % MinObjAlignment == 0, "currSize should be aligned");
|
||||
for (i = currSize; i < IndexSetSize; i += IndexSetStride) {
|
||||
FreeList* fl = &_indexedFreeList[i];
|
||||
FreeList<FreeChunk>* fl = &_indexedFreeList[i];
|
||||
if (fl->head()) {
|
||||
ret = getFromListGreater(fl, numWords);
|
||||
assert(ret == NULL || ret->isFree(), "Should be returning a free chunk");
|
||||
|
@ -1714,7 +1716,7 @@ CompactibleFreeListSpace::returnChunkToDictionary(FreeChunk* chunk) {
|
|||
_dictionary->returnChunk(chunk);
|
||||
#ifndef PRODUCT
|
||||
if (CMSCollector::abstract_state() != CMSCollector::Sweeping) {
|
||||
TreeChunk::as_TreeChunk(chunk)->list()->verify_stats();
|
||||
TreeChunk<FreeChunk>::as_TreeChunk(chunk)->list()->verify_stats();
|
||||
}
|
||||
#endif // PRODUCT
|
||||
}
|
||||
|
@ -1862,11 +1864,11 @@ FreeChunk* CompactibleFreeListSpace::bestFitSmall(size_t numWords) {
|
|||
the excess is >= MIN_CHUNK. */
|
||||
size_t start = align_object_size(numWords + MinChunkSize);
|
||||
if (start < IndexSetSize) {
|
||||
FreeList* it = _indexedFreeList;
|
||||
FreeList<FreeChunk>* it = _indexedFreeList;
|
||||
size_t hint = _indexedFreeList[start].hint();
|
||||
while (hint < IndexSetSize) {
|
||||
assert(hint % MinObjAlignment == 0, "hint should be aligned");
|
||||
FreeList *fl = &_indexedFreeList[hint];
|
||||
FreeList<FreeChunk> *fl = &_indexedFreeList[hint];
|
||||
if (fl->surplus() > 0 && fl->head() != NULL) {
|
||||
// Found a list with surplus, reset original hint
|
||||
// and split out a free chunk which is returned.
|
||||
|
@ -1885,7 +1887,7 @@ FreeChunk* CompactibleFreeListSpace::bestFitSmall(size_t numWords) {
|
|||
}
|
||||
|
||||
/* Requires fl->size >= numWords + MinChunkSize */
|
||||
FreeChunk* CompactibleFreeListSpace::getFromListGreater(FreeList* fl,
|
||||
FreeChunk* CompactibleFreeListSpace::getFromListGreater(FreeList<FreeChunk>* fl,
|
||||
size_t numWords) {
|
||||
FreeChunk *curr = fl->head();
|
||||
size_t oldNumWords = curr->size();
|
||||
|
@ -2167,7 +2169,7 @@ void CompactibleFreeListSpace::beginSweepFLCensus(
|
|||
assert_locked();
|
||||
size_t i;
|
||||
for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
|
||||
FreeList* fl = &_indexedFreeList[i];
|
||||
FreeList<FreeChunk>* fl = &_indexedFreeList[i];
|
||||
if (PrintFLSStatistics > 1) {
|
||||
gclog_or_tty->print("size[%d] : ", i);
|
||||
}
|
||||
|
@ -2186,7 +2188,7 @@ void CompactibleFreeListSpace::setFLSurplus() {
|
|||
assert_locked();
|
||||
size_t i;
|
||||
for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
|
||||
FreeList *fl = &_indexedFreeList[i];
|
||||
FreeList<FreeChunk> *fl = &_indexedFreeList[i];
|
||||
fl->set_surplus(fl->count() -
|
||||
(ssize_t)((double)fl->desired() * CMSSmallSplitSurplusPercent));
|
||||
}
|
||||
|
@ -2197,7 +2199,7 @@ void CompactibleFreeListSpace::setFLHints() {
|
|||
size_t i;
|
||||
size_t h = IndexSetSize;
|
||||
for (i = IndexSetSize - 1; i != 0; i -= IndexSetStride) {
|
||||
FreeList *fl = &_indexedFreeList[i];
|
||||
FreeList<FreeChunk> *fl = &_indexedFreeList[i];
|
||||
fl->set_hint(h);
|
||||
if (fl->surplus() > 0) {
|
||||
h = i;
|
||||
|
@ -2209,7 +2211,7 @@ void CompactibleFreeListSpace::clearFLCensus() {
|
|||
assert_locked();
|
||||
size_t i;
|
||||
for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
|
||||
FreeList *fl = &_indexedFreeList[i];
|
||||
FreeList<FreeChunk> *fl = &_indexedFreeList[i];
|
||||
fl->set_prevSweep(fl->count());
|
||||
fl->set_coalBirths(0);
|
||||
fl->set_coalDeaths(0);
|
||||
|
@ -2236,7 +2238,7 @@ void CompactibleFreeListSpace::endSweepFLCensus(size_t sweep_count) {
|
|||
|
||||
bool CompactibleFreeListSpace::coalOverPopulated(size_t size) {
|
||||
if (size < SmallForDictionary) {
|
||||
FreeList *fl = &_indexedFreeList[size];
|
||||
FreeList<FreeChunk> *fl = &_indexedFreeList[size];
|
||||
return (fl->coalDesired() < 0) ||
|
||||
((int)fl->count() > fl->coalDesired());
|
||||
} else {
|
||||
|
@ -2246,14 +2248,14 @@ bool CompactibleFreeListSpace::coalOverPopulated(size_t size) {
|
|||
|
||||
void CompactibleFreeListSpace::smallCoalBirth(size_t size) {
|
||||
assert(size < SmallForDictionary, "Size too large for indexed list");
|
||||
FreeList *fl = &_indexedFreeList[size];
|
||||
FreeList<FreeChunk> *fl = &_indexedFreeList[size];
|
||||
fl->increment_coalBirths();
|
||||
fl->increment_surplus();
|
||||
}
|
||||
|
||||
void CompactibleFreeListSpace::smallCoalDeath(size_t size) {
|
||||
assert(size < SmallForDictionary, "Size too large for indexed list");
|
||||
FreeList *fl = &_indexedFreeList[size];
|
||||
FreeList<FreeChunk> *fl = &_indexedFreeList[size];
|
||||
fl->increment_coalDeaths();
|
||||
fl->decrement_surplus();
|
||||
}
|
||||
|
@ -2280,14 +2282,14 @@ void CompactibleFreeListSpace::coalDeath(size_t size) {
|
|||
|
||||
void CompactibleFreeListSpace::smallSplitBirth(size_t size) {
|
||||
assert(size < SmallForDictionary, "Size too large for indexed list");
|
||||
FreeList *fl = &_indexedFreeList[size];
|
||||
FreeList<FreeChunk> *fl = &_indexedFreeList[size];
|
||||
fl->increment_splitBirths();
|
||||
fl->increment_surplus();
|
||||
}
|
||||
|
||||
void CompactibleFreeListSpace::smallSplitDeath(size_t size) {
|
||||
assert(size < SmallForDictionary, "Size too large for indexed list");
|
||||
FreeList *fl = &_indexedFreeList[size];
|
||||
FreeList<FreeChunk> *fl = &_indexedFreeList[size];
|
||||
fl->increment_splitDeaths();
|
||||
fl->decrement_surplus();
|
||||
}
|
||||
|
@ -2530,7 +2532,7 @@ void CompactibleFreeListSpace::check_free_list_consistency() const {
|
|||
assert(_dictionary->minSize() <= IndexSetSize,
|
||||
"Some sizes can't be allocated without recourse to"
|
||||
" linear allocation buffers");
|
||||
assert(MIN_TREE_CHUNK_SIZE*HeapWordSize == sizeof(TreeChunk),
|
||||
assert(BinaryTreeDictionary<FreeChunk>::min_tree_chunk_size*HeapWordSize == sizeof(TreeChunk<FreeChunk>),
|
||||
"else MIN_TREE_CHUNK_SIZE is wrong");
|
||||
assert((IndexSetStride == 2 && IndexSetStart == 4) || // 32-bit
|
||||
(IndexSetStride == 1 && IndexSetStart == 3), "just checking"); // 64-bit
|
||||
|
@ -2543,15 +2545,15 @@ void CompactibleFreeListSpace::check_free_list_consistency() const {
|
|||
|
||||
void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const {
|
||||
assert_lock_strong(&_freelistLock);
|
||||
FreeList total;
|
||||
FreeList<FreeChunk> total;
|
||||
gclog_or_tty->print("end sweep# " SIZE_FORMAT "\n", sweep_count);
|
||||
FreeList::print_labels_on(gclog_or_tty, "size");
|
||||
FreeList<FreeChunk>::print_labels_on(gclog_or_tty, "size");
|
||||
size_t totalFree = 0;
|
||||
for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
|
||||
const FreeList *fl = &_indexedFreeList[i];
|
||||
const FreeList<FreeChunk> *fl = &_indexedFreeList[i];
|
||||
totalFree += fl->count() * fl->size();
|
||||
if (i % (40*IndexSetStride) == 0) {
|
||||
FreeList::print_labels_on(gclog_or_tty, "size");
|
||||
FreeList<FreeChunk>::print_labels_on(gclog_or_tty, "size");
|
||||
}
|
||||
fl->print_on(gclog_or_tty);
|
||||
total.set_bfrSurp( total.bfrSurp() + fl->bfrSurp() );
|
||||
|
@ -2634,7 +2636,7 @@ HeapWord* CFLS_LAB::alloc(size_t word_sz) {
|
|||
res = _cfls->getChunkFromDictionaryExact(word_sz);
|
||||
if (res == NULL) return NULL;
|
||||
} else {
|
||||
FreeList* fl = &_indexedFreeList[word_sz];
|
||||
FreeList<FreeChunk>* fl = &_indexedFreeList[word_sz];
|
||||
if (fl->count() == 0) {
|
||||
// Attempt to refill this local free list.
|
||||
get_from_global_pool(word_sz, fl);
|
||||
|
@ -2654,7 +2656,7 @@ HeapWord* CFLS_LAB::alloc(size_t word_sz) {
|
|||
|
||||
// Get a chunk of blocks of the right size and update related
|
||||
// book-keeping stats
|
||||
void CFLS_LAB::get_from_global_pool(size_t word_sz, FreeList* fl) {
|
||||
void CFLS_LAB::get_from_global_pool(size_t word_sz, FreeList<FreeChunk>* fl) {
|
||||
// Get the #blocks we want to claim
|
||||
size_t n_blks = (size_t)_blocks_to_claim[word_sz].average();
|
||||
assert(n_blks > 0, "Error");
|
||||
|
@ -2736,7 +2738,7 @@ void CFLS_LAB::retire(int tid) {
|
|||
if (num_retire > 0) {
|
||||
_cfls->_indexedFreeList[i].prepend(&_indexedFreeList[i]);
|
||||
// Reset this list.
|
||||
_indexedFreeList[i] = FreeList();
|
||||
_indexedFreeList[i] = FreeList<FreeChunk>();
|
||||
_indexedFreeList[i].set_size(i);
|
||||
}
|
||||
}
|
||||
|
@ -2750,7 +2752,7 @@ void CFLS_LAB::retire(int tid) {
|
|||
}
|
||||
}
|
||||
|
||||
void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl) {
|
||||
void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList<FreeChunk>* fl) {
|
||||
assert(fl->count() == 0, "Precondition.");
|
||||
assert(word_sz < CompactibleFreeListSpace::IndexSetSize,
|
||||
"Precondition");
|
||||
|
@ -2766,12 +2768,12 @@ void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n
|
|||
(cur_sz < CompactibleFreeListSpace::IndexSetSize) &&
|
||||
(CMSSplitIndexedFreeListBlocks || k <= 1);
|
||||
k++, cur_sz = k * word_sz) {
|
||||
FreeList fl_for_cur_sz; // Empty.
|
||||
FreeList<FreeChunk> fl_for_cur_sz; // Empty.
|
||||
fl_for_cur_sz.set_size(cur_sz);
|
||||
{
|
||||
MutexLockerEx x(_indexedFreeListParLocks[cur_sz],
|
||||
Mutex::_no_safepoint_check_flag);
|
||||
FreeList* gfl = &_indexedFreeList[cur_sz];
|
||||
FreeList<FreeChunk>* gfl = &_indexedFreeList[cur_sz];
|
||||
if (gfl->count() != 0) {
|
||||
// nn is the number of chunks of size cur_sz that
|
||||
// we'd need to split k-ways each, in order to create
|
||||
|
@ -2848,7 +2850,7 @@ void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n
|
|||
while (n > 0) {
|
||||
fc = dictionary()->getChunk(MAX2(n * word_sz,
|
||||
_dictionary->minSize()),
|
||||
FreeBlockDictionary::atLeast);
|
||||
FreeBlockDictionary<FreeChunk>::atLeast);
|
||||
if (fc != NULL) {
|
||||
_bt.allocated((HeapWord*)fc, fc->size(), true /* reducing */); // update _unallocated_blk
|
||||
dictionary()->dictCensusUpdate(fc->size(),
|
||||
|
|
|
@ -25,10 +25,10 @@
|
|||
#ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_COMPACTIBLEFREELISTSPACE_HPP
|
||||
#define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_COMPACTIBLEFREELISTSPACE_HPP
|
||||
|
||||
#include "gc_implementation/concurrentMarkSweep/binaryTreeDictionary.hpp"
|
||||
#include "gc_implementation/concurrentMarkSweep/freeList.hpp"
|
||||
#include "gc_implementation/concurrentMarkSweep/promotionInfo.hpp"
|
||||
#include "memory/binaryTreeDictionary.hpp"
|
||||
#include "memory/blockOffsetTable.inline.hpp"
|
||||
#include "memory/freeList.hpp"
|
||||
#include "memory/space.hpp"
|
||||
|
||||
// Classes in support of keeping track of promotions into a non-Contiguous
|
||||
|
@ -129,10 +129,10 @@ class CompactibleFreeListSpace: public CompactibleSpace {
|
|||
// Linear allocation blocks
|
||||
LinearAllocBlock _smallLinearAllocBlock;
|
||||
|
||||
FreeBlockDictionary::DictionaryChoice _dictionaryChoice;
|
||||
FreeBlockDictionary* _dictionary; // ptr to dictionary for large size blocks
|
||||
FreeBlockDictionary<FreeChunk>::DictionaryChoice _dictionaryChoice;
|
||||
FreeBlockDictionary<FreeChunk>* _dictionary; // ptr to dictionary for large size blocks
|
||||
|
||||
FreeList _indexedFreeList[IndexSetSize];
|
||||
FreeList<FreeChunk> _indexedFreeList[IndexSetSize];
|
||||
// indexed array for small size blocks
|
||||
// allocation stategy
|
||||
bool _fitStrategy; // Use best fit strategy.
|
||||
|
@ -169,7 +169,7 @@ class CompactibleFreeListSpace: public CompactibleSpace {
|
|||
// If the count of "fl" is negative, it's absolute value indicates a
|
||||
// number of free chunks that had been previously "borrowed" from global
|
||||
// list of size "word_sz", and must now be decremented.
|
||||
void par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl);
|
||||
void par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList<FreeChunk>* fl);
|
||||
|
||||
// Allocation helper functions
|
||||
// Allocate using a strategy that takes from the indexed free lists
|
||||
|
@ -215,7 +215,7 @@ class CompactibleFreeListSpace: public CompactibleSpace {
|
|||
// and return it. The split off remainder is returned to
|
||||
// the free lists. The old name for getFromListGreater
|
||||
// was lookInListGreater.
|
||||
FreeChunk* getFromListGreater(FreeList* fl, size_t numWords);
|
||||
FreeChunk* getFromListGreater(FreeList<FreeChunk>* fl, size_t numWords);
|
||||
// Get a chunk in the indexed free list or dictionary,
|
||||
// by considering a larger chunk and splitting it.
|
||||
FreeChunk* getChunkFromGreater(size_t numWords);
|
||||
|
@ -286,10 +286,10 @@ class CompactibleFreeListSpace: public CompactibleSpace {
|
|||
// Constructor...
|
||||
CompactibleFreeListSpace(BlockOffsetSharedArray* bs, MemRegion mr,
|
||||
bool use_adaptive_freelists,
|
||||
FreeBlockDictionary::DictionaryChoice);
|
||||
FreeBlockDictionary<FreeChunk>::DictionaryChoice);
|
||||
// accessors
|
||||
bool bestFitFirst() { return _fitStrategy == FreeBlockBestFitFirst; }
|
||||
FreeBlockDictionary* dictionary() const { return _dictionary; }
|
||||
FreeBlockDictionary<FreeChunk>* dictionary() const { return _dictionary; }
|
||||
HeapWord* nearLargestChunk() const { return _nearLargestChunk; }
|
||||
void set_nearLargestChunk(HeapWord* v) { _nearLargestChunk = v; }
|
||||
|
||||
|
@ -622,7 +622,7 @@ class CFLS_LAB : public CHeapObj {
|
|||
CompactibleFreeListSpace* _cfls;
|
||||
|
||||
// Our local free lists.
|
||||
FreeList _indexedFreeList[CompactibleFreeListSpace::IndexSetSize];
|
||||
FreeList<FreeChunk> _indexedFreeList[CompactibleFreeListSpace::IndexSetSize];
|
||||
|
||||
// Initialized from a command-line arg.
|
||||
|
||||
|
@ -635,7 +635,7 @@ class CFLS_LAB : public CHeapObj {
|
|||
size_t _num_blocks [CompactibleFreeListSpace::IndexSetSize];
|
||||
|
||||
// Internal work method
|
||||
void get_from_global_pool(size_t word_sz, FreeList* fl);
|
||||
void get_from_global_pool(size_t word_sz, FreeList<FreeChunk>* fl);
|
||||
|
||||
public:
|
||||
CFLS_LAB(CompactibleFreeListSpace* cfls);
|
||||
|
|
|
@ -188,7 +188,7 @@ class CMSParGCThreadState: public CHeapObj {
|
|||
ConcurrentMarkSweepGeneration::ConcurrentMarkSweepGeneration(
|
||||
ReservedSpace rs, size_t initial_byte_size, int level,
|
||||
CardTableRS* ct, bool use_adaptive_freelists,
|
||||
FreeBlockDictionary::DictionaryChoice dictionaryChoice) :
|
||||
FreeBlockDictionary<FreeChunk>::DictionaryChoice dictionaryChoice) :
|
||||
CardGeneration(rs, initial_byte_size, level, ct),
|
||||
_dilatation_factor(((double)MinChunkSize)/((double)(CollectedHeap::min_fill_size()))),
|
||||
_debug_collection_type(Concurrent_collection_type)
|
||||
|
|
|
@ -25,10 +25,10 @@
|
|||
#ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_CONCURRENTMARKSWEEPGENERATION_HPP
|
||||
#define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_CONCURRENTMARKSWEEPGENERATION_HPP
|
||||
|
||||
#include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp"
|
||||
#include "gc_implementation/shared/gSpaceCounters.hpp"
|
||||
#include "gc_implementation/shared/gcStats.hpp"
|
||||
#include "gc_implementation/shared/generationCounters.hpp"
|
||||
#include "memory/freeBlockDictionary.hpp"
|
||||
#include "memory/generation.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "runtime/virtualspace.hpp"
|
||||
|
@ -1106,7 +1106,7 @@ class ConcurrentMarkSweepGeneration: public CardGeneration {
|
|||
ConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size,
|
||||
int level, CardTableRS* ct,
|
||||
bool use_adaptive_freelists,
|
||||
FreeBlockDictionary::DictionaryChoice);
|
||||
FreeBlockDictionary<FreeChunk>::DictionaryChoice);
|
||||
|
||||
// Accessors
|
||||
CMSCollector* collector() const { return _collector; }
|
||||
|
@ -1328,7 +1328,7 @@ class ASConcurrentMarkSweepGeneration : public ConcurrentMarkSweepGeneration {
|
|||
ASConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size,
|
||||
int level, CardTableRS* ct,
|
||||
bool use_adaptive_freelists,
|
||||
FreeBlockDictionary::DictionaryChoice
|
||||
FreeBlockDictionary<FreeChunk>::DictionaryChoice
|
||||
dictionaryChoice) :
|
||||
ConcurrentMarkSweepGeneration(rs, initial_byte_size, level, ct,
|
||||
use_adaptive_freelists, dictionaryChoice) {}
|
||||
|
|
|
@ -23,7 +23,8 @@
|
|||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp"
|
||||
#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
|
||||
#include "memory/freeBlockDictionary.hpp"
|
||||
#include "utilities/copy.hpp"
|
||||
|
||||
#ifndef PRODUCT
|
||||
|
|
|
@ -44,11 +44,11 @@
|
|||
nonstatic_field(FreeChunk, _next, FreeChunk*) \
|
||||
nonstatic_field(FreeChunk, _prev, FreeChunk*) \
|
||||
nonstatic_field(LinearAllocBlock, _word_size, size_t) \
|
||||
nonstatic_field(FreeList, _size, size_t) \
|
||||
nonstatic_field(FreeList, _count, ssize_t) \
|
||||
nonstatic_field(BinaryTreeDictionary, _totalSize, size_t) \
|
||||
nonstatic_field(CompactibleFreeListSpace, _dictionary, FreeBlockDictionary*) \
|
||||
nonstatic_field(CompactibleFreeListSpace, _indexedFreeList[0], FreeList) \
|
||||
nonstatic_field(FreeList<FreeChunk>, _size, size_t) \
|
||||
nonstatic_field(FreeList<FreeChunk>, _count, ssize_t) \
|
||||
nonstatic_field(BinaryTreeDictionary<FreeChunk>,_totalSize, size_t) \
|
||||
nonstatic_field(CompactibleFreeListSpace, _dictionary, FreeBlockDictionary<FreeChunk>*) \
|
||||
nonstatic_field(CompactibleFreeListSpace, _indexedFreeList[0], FreeList<FreeChunk>) \
|
||||
nonstatic_field(CompactibleFreeListSpace, _smallLinearAllocBlock, LinearAllocBlock)
|
||||
|
||||
|
||||
|
@ -70,13 +70,13 @@
|
|||
declare_toplevel_type(CompactibleFreeListSpace*) \
|
||||
declare_toplevel_type(CMSCollector*) \
|
||||
declare_toplevel_type(FreeChunk*) \
|
||||
declare_toplevel_type(BinaryTreeDictionary*) \
|
||||
declare_toplevel_type(FreeBlockDictionary*) \
|
||||
declare_toplevel_type(FreeList*) \
|
||||
declare_toplevel_type(FreeList) \
|
||||
declare_toplevel_type(BinaryTreeDictionary<FreeChunk>*) \
|
||||
declare_toplevel_type(FreeBlockDictionary<FreeChunk>*) \
|
||||
declare_toplevel_type(FreeList<FreeChunk>*) \
|
||||
declare_toplevel_type(FreeList<FreeChunk>) \
|
||||
declare_toplevel_type(LinearAllocBlock) \
|
||||
declare_toplevel_type(FreeBlockDictionary) \
|
||||
declare_type(BinaryTreeDictionary, FreeBlockDictionary)
|
||||
declare_toplevel_type(FreeBlockDictionary<FreeChunk>) \
|
||||
declare_type(BinaryTreeDictionary<FreeChunk>, FreeBlockDictionary<FreeChunk>)
|
||||
|
||||
#define VM_INT_CONSTANTS_CMS(declare_constant) \
|
||||
declare_constant(Generation::ConcurrentMarkSweep) \
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -22,51 +22,65 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_BINARYTREEDICTIONARY_HPP
|
||||
#define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_BINARYTREEDICTIONARY_HPP
|
||||
#ifndef SHARE_VM_MEMORY_BINARYTREEDICTIONARY_HPP
|
||||
#define SHARE_VM_MEMORY_BINARYTREEDICTIONARY_HPP
|
||||
|
||||
#include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp"
|
||||
#include "gc_implementation/concurrentMarkSweep/freeList.hpp"
|
||||
#include "memory/freeBlockDictionary.hpp"
|
||||
#include "memory/freeList.hpp"
|
||||
|
||||
/*
|
||||
* A binary tree based search structure for free blocks.
|
||||
* This is currently used in the Concurrent Mark&Sweep implementation.
|
||||
* This is currently used in the Concurrent Mark&Sweep implementation, but
|
||||
* will be used for free block management for metadata.
|
||||
*/
|
||||
|
||||
// A TreeList is a FreeList which can be used to maintain a
|
||||
// binary tree of free lists.
|
||||
|
||||
class TreeChunk;
|
||||
class BinaryTreeDictionary;
|
||||
class AscendTreeCensusClosure;
|
||||
class DescendTreeCensusClosure;
|
||||
class DescendTreeSearchClosure;
|
||||
template <class Chunk> class TreeChunk;
|
||||
template <class Chunk> class BinaryTreeDictionary;
|
||||
template <class Chunk> class AscendTreeCensusClosure;
|
||||
template <class Chunk> class DescendTreeCensusClosure;
|
||||
template <class Chunk> class DescendTreeSearchClosure;
|
||||
|
||||
class TreeList: public FreeList {
|
||||
friend class TreeChunk;
|
||||
friend class BinaryTreeDictionary;
|
||||
friend class AscendTreeCensusClosure;
|
||||
friend class DescendTreeCensusClosure;
|
||||
friend class DescendTreeSearchClosure;
|
||||
template <class Chunk>
|
||||
class TreeList: public FreeList<Chunk> {
|
||||
friend class TreeChunk<Chunk>;
|
||||
friend class BinaryTreeDictionary<Chunk>;
|
||||
friend class AscendTreeCensusClosure<Chunk>;
|
||||
friend class DescendTreeCensusClosure<Chunk>;
|
||||
friend class DescendTreeSearchClosure<Chunk>;
|
||||
|
||||
TreeList<Chunk>* _parent;
|
||||
TreeList<Chunk>* _left;
|
||||
TreeList<Chunk>* _right;
|
||||
|
||||
protected:
|
||||
TreeList* parent() const { return _parent; }
|
||||
TreeList* left() const { return _left; }
|
||||
TreeList* right() const { return _right; }
|
||||
TreeList<Chunk>* parent() const { return _parent; }
|
||||
TreeList<Chunk>* left() const { return _left; }
|
||||
TreeList<Chunk>* right() const { return _right; }
|
||||
|
||||
// Wrapper on call to base class, to get the template to compile.
|
||||
Chunk* head() const { return FreeList<Chunk>::head(); }
|
||||
Chunk* tail() const { return FreeList<Chunk>::tail(); }
|
||||
void set_head(Chunk* head) { FreeList<Chunk>::set_head(head); }
|
||||
void set_tail(Chunk* tail) { FreeList<Chunk>::set_tail(tail); }
|
||||
|
||||
size_t size() const { return FreeList<Chunk>::size(); }
|
||||
|
||||
// Accessors for links in tree.
|
||||
|
||||
void setLeft(TreeList* tl) {
|
||||
void setLeft(TreeList<Chunk>* tl) {
|
||||
_left = tl;
|
||||
if (tl != NULL)
|
||||
tl->setParent(this);
|
||||
}
|
||||
void setRight(TreeList* tl) {
|
||||
void setRight(TreeList<Chunk>* tl) {
|
||||
_right = tl;
|
||||
if (tl != NULL)
|
||||
tl->setParent(this);
|
||||
}
|
||||
void setParent(TreeList* tl) { _parent = tl; }
|
||||
void setParent(TreeList<Chunk>* tl) { _parent = tl; }
|
||||
|
||||
void clearLeft() { _left = NULL; }
|
||||
void clearRight() { _right = NULL; }
|
||||
|
@ -75,20 +89,20 @@ class TreeList: public FreeList {
|
|||
|
||||
// For constructing a TreeList from a Tree chunk or
|
||||
// address and size.
|
||||
static TreeList* as_TreeList(TreeChunk* tc);
|
||||
static TreeList* as_TreeList(HeapWord* addr, size_t size);
|
||||
static TreeList<Chunk>* as_TreeList(TreeChunk<Chunk>* tc);
|
||||
static TreeList<Chunk>* as_TreeList(HeapWord* addr, size_t size);
|
||||
|
||||
// Returns the head of the free list as a pointer to a TreeChunk.
|
||||
TreeChunk* head_as_TreeChunk();
|
||||
TreeChunk<Chunk>* head_as_TreeChunk();
|
||||
|
||||
// Returns the first available chunk in the free list as a pointer
|
||||
// to a TreeChunk.
|
||||
TreeChunk* first_available();
|
||||
TreeChunk<Chunk>* first_available();
|
||||
|
||||
// Returns the block with the largest heap address amongst
|
||||
// those in the list for this size; potentially slow and expensive,
|
||||
// use with caution!
|
||||
TreeChunk* largest_address();
|
||||
TreeChunk<Chunk>* largest_address();
|
||||
|
||||
// removeChunkReplaceIfNeeded() removes the given "tc" from the TreeList.
|
||||
// If "tc" is the first chunk in the list, it is also the
|
||||
|
@ -96,13 +110,13 @@ class TreeList: public FreeList {
|
|||
// returns the possibly replaced TreeList* for the node in
|
||||
// the tree. It also updates the parent of the original
|
||||
// node to point to the new node.
|
||||
TreeList* removeChunkReplaceIfNeeded(TreeChunk* tc);
|
||||
TreeList<Chunk>* removeChunkReplaceIfNeeded(TreeChunk<Chunk>* tc);
|
||||
// See FreeList.
|
||||
void returnChunkAtHead(TreeChunk* tc);
|
||||
void returnChunkAtTail(TreeChunk* tc);
|
||||
void returnChunkAtHead(TreeChunk<Chunk>* tc);
|
||||
void returnChunkAtTail(TreeChunk<Chunk>* tc);
|
||||
};
|
||||
|
||||
// A TreeChunk is a subclass of a FreeChunk that additionally
|
||||
// A TreeChunk is a subclass of a Chunk that additionally
|
||||
// maintains a pointer to the free list on which it is currently
|
||||
// linked.
|
||||
// A TreeChunk is also used as a node in the binary tree. This
|
||||
|
@ -115,92 +129,111 @@ class TreeList: public FreeList {
|
|||
// on the free list for a node in the tree and is only removed if
|
||||
// it is the last chunk on the free list.
|
||||
|
||||
class TreeChunk : public FreeChunk {
|
||||
friend class TreeList;
|
||||
TreeList* _list;
|
||||
TreeList _embedded_list; // if non-null, this chunk is on _list
|
||||
template <class Chunk>
|
||||
class TreeChunk : public Chunk {
|
||||
friend class TreeList<Chunk>;
|
||||
TreeList<Chunk>* _list;
|
||||
TreeList<Chunk> _embedded_list; // if non-null, this chunk is on _list
|
||||
protected:
|
||||
TreeList* embedded_list() const { return (TreeList*) &_embedded_list; }
|
||||
void set_embedded_list(TreeList* v) { _embedded_list = *v; }
|
||||
TreeList<Chunk>* embedded_list() const { return (TreeList<Chunk>*) &_embedded_list; }
|
||||
void set_embedded_list(TreeList<Chunk>* v) { _embedded_list = *v; }
|
||||
public:
|
||||
TreeList* list() { return _list; }
|
||||
void set_list(TreeList* v) { _list = v; }
|
||||
static TreeChunk* as_TreeChunk(FreeChunk* fc);
|
||||
TreeList<Chunk>* list() { return _list; }
|
||||
void set_list(TreeList<Chunk>* v) { _list = v; }
|
||||
static TreeChunk<Chunk>* as_TreeChunk(Chunk* fc);
|
||||
// Initialize fields in a TreeChunk that should be
|
||||
// initialized when the TreeChunk is being added to
|
||||
// a free list in the tree.
|
||||
void initialize() { embedded_list()->initialize(); }
|
||||
|
||||
Chunk* next() const { return Chunk::next(); }
|
||||
Chunk* prev() const { return Chunk::prev(); }
|
||||
size_t size() const volatile { return Chunk::size(); }
|
||||
|
||||
// debugging
|
||||
void verifyTreeChunkList() const;
|
||||
};
|
||||
|
||||
const size_t MIN_TREE_CHUNK_SIZE = sizeof(TreeChunk)/HeapWordSize;
|
||||
|
||||
class BinaryTreeDictionary: public FreeBlockDictionary {
|
||||
template <class Chunk>
|
||||
class BinaryTreeDictionary: public FreeBlockDictionary<Chunk> {
|
||||
friend class VMStructs;
|
||||
bool _splay;
|
||||
size_t _totalSize;
|
||||
size_t _totalFreeBlocks;
|
||||
TreeList* _root;
|
||||
TreeList<Chunk>* _root;
|
||||
bool _adaptive_freelists;
|
||||
|
||||
// private accessors
|
||||
bool splay() const { return _splay; }
|
||||
void set_splay(bool v) { _splay = v; }
|
||||
size_t totalSize() const { return _totalSize; }
|
||||
void set_totalSize(size_t v) { _totalSize = v; }
|
||||
virtual void inc_totalSize(size_t v);
|
||||
virtual void dec_totalSize(size_t v);
|
||||
size_t totalFreeBlocks() const { return _totalFreeBlocks; }
|
||||
void set_totalFreeBlocks(size_t v) { _totalFreeBlocks = v; }
|
||||
TreeList* root() const { return _root; }
|
||||
void set_root(TreeList* v) { _root = v; }
|
||||
TreeList<Chunk>* root() const { return _root; }
|
||||
void set_root(TreeList<Chunk>* v) { _root = v; }
|
||||
bool adaptive_freelists() { return _adaptive_freelists; }
|
||||
|
||||
// This field is added and can be set to point to the
|
||||
// the Mutex used to synchronize access to the
|
||||
// dictionary so that assertion checking can be done.
|
||||
// For example it is set to point to _parDictionaryAllocLock.
|
||||
NOT_PRODUCT(Mutex* _lock;)
|
||||
|
||||
// Remove a chunk of size "size" or larger from the tree and
|
||||
// return it. If the chunk
|
||||
// is the last chunk of that size, remove the node for that size
|
||||
// from the tree.
|
||||
TreeChunk* getChunkFromTree(size_t size, Dither dither, bool splay);
|
||||
TreeChunk<Chunk>* getChunkFromTree(size_t size, enum FreeBlockDictionary<Chunk>::Dither dither, bool splay);
|
||||
// Return a list of the specified size or NULL from the tree.
|
||||
// The list is not removed from the tree.
|
||||
TreeList* findList (size_t size) const;
|
||||
TreeList<Chunk>* findList (size_t size) const;
|
||||
// Remove this chunk from the tree. If the removal results
|
||||
// in an empty list in the tree, remove the empty list.
|
||||
TreeChunk* removeChunkFromTree(TreeChunk* tc);
|
||||
TreeChunk<Chunk>* removeChunkFromTree(TreeChunk<Chunk>* tc);
|
||||
// Remove the node in the trees starting at tl that has the
|
||||
// minimum value and return it. Repair the tree as needed.
|
||||
TreeList* removeTreeMinimum(TreeList* tl);
|
||||
void semiSplayStep(TreeList* tl);
|
||||
TreeList<Chunk>* removeTreeMinimum(TreeList<Chunk>* tl);
|
||||
void semiSplayStep(TreeList<Chunk>* tl);
|
||||
// Add this free chunk to the tree.
|
||||
void insertChunkInTree(FreeChunk* freeChunk);
|
||||
void insertChunkInTree(Chunk* freeChunk);
|
||||
public:
|
||||
|
||||
static const size_t min_tree_chunk_size = sizeof(TreeChunk<Chunk>)/HeapWordSize;
|
||||
|
||||
void verifyTree() const;
|
||||
// verify that the given chunk is in the tree.
|
||||
bool verifyChunkInFreeLists(FreeChunk* tc) const;
|
||||
bool verifyChunkInFreeLists(Chunk* tc) const;
|
||||
private:
|
||||
void verifyTreeHelper(TreeList* tl) const;
|
||||
static size_t verifyPrevFreePtrs(TreeList* tl);
|
||||
void verifyTreeHelper(TreeList<Chunk>* tl) const;
|
||||
static size_t verifyPrevFreePtrs(TreeList<Chunk>* tl);
|
||||
|
||||
// Returns the total number of chunks in the list.
|
||||
size_t totalListLength(TreeList* tl) const;
|
||||
size_t totalListLength(TreeList<Chunk>* tl) const;
|
||||
// Returns the total number of words in the chunks in the tree
|
||||
// starting at "tl".
|
||||
size_t totalSizeInTree(TreeList* tl) const;
|
||||
size_t totalSizeInTree(TreeList<Chunk>* tl) const;
|
||||
// Returns the sum of the square of the size of each block
|
||||
// in the tree starting at "tl".
|
||||
double sum_of_squared_block_sizes(TreeList* const tl) const;
|
||||
double sum_of_squared_block_sizes(TreeList<Chunk>* const tl) const;
|
||||
// Returns the total number of free blocks in the tree starting
|
||||
// at "tl".
|
||||
size_t totalFreeBlocksInTree(TreeList* tl) const;
|
||||
size_t totalFreeBlocksInTree(TreeList<Chunk>* tl) const;
|
||||
size_t numFreeBlocks() const;
|
||||
size_t treeHeight() const;
|
||||
size_t treeHeightHelper(TreeList* tl) const;
|
||||
size_t totalNodesInTree(TreeList* tl) const;
|
||||
size_t totalNodesHelper(TreeList* tl) const;
|
||||
size_t treeHeightHelper(TreeList<Chunk>* tl) const;
|
||||
size_t totalNodesInTree(TreeList<Chunk>* tl) const;
|
||||
size_t totalNodesHelper(TreeList<Chunk>* tl) const;
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
BinaryTreeDictionary(MemRegion mr, bool splay = false);
|
||||
BinaryTreeDictionary(bool adaptive_freelists, bool splay = false);
|
||||
BinaryTreeDictionary(MemRegion mr, bool adaptive_freelists, bool splay = false);
|
||||
|
||||
// Public accessors
|
||||
size_t totalSize() const { return _totalSize; }
|
||||
|
||||
// Reset the dictionary to the initial conditions with
|
||||
// a single free chunk.
|
||||
|
@ -212,22 +245,22 @@ class BinaryTreeDictionary: public FreeBlockDictionary {
|
|||
// Return a chunk of size "size" or greater from
|
||||
// the tree.
|
||||
// want a better dynamic splay strategy for the future.
|
||||
FreeChunk* getChunk(size_t size, Dither dither) {
|
||||
verify_par_locked();
|
||||
FreeChunk* res = getChunkFromTree(size, dither, splay());
|
||||
Chunk* getChunk(size_t size, enum FreeBlockDictionary<Chunk>::Dither dither) {
|
||||
FreeBlockDictionary<Chunk>::verify_par_locked();
|
||||
Chunk* res = getChunkFromTree(size, dither, splay());
|
||||
assert(res == NULL || res->isFree(),
|
||||
"Should be returning a free chunk");
|
||||
return res;
|
||||
}
|
||||
|
||||
void returnChunk(FreeChunk* chunk) {
|
||||
verify_par_locked();
|
||||
void returnChunk(Chunk* chunk) {
|
||||
FreeBlockDictionary<Chunk>::verify_par_locked();
|
||||
insertChunkInTree(chunk);
|
||||
}
|
||||
|
||||
void removeChunk(FreeChunk* chunk) {
|
||||
verify_par_locked();
|
||||
removeChunkFromTree((TreeChunk*)chunk);
|
||||
void removeChunk(Chunk* chunk) {
|
||||
FreeBlockDictionary<Chunk>::verify_par_locked();
|
||||
removeChunkFromTree((TreeChunk<Chunk>*)chunk);
|
||||
assert(chunk->isFree(), "Should still be a free chunk");
|
||||
}
|
||||
|
||||
|
@ -243,14 +276,14 @@ class BinaryTreeDictionary: public FreeBlockDictionary {
|
|||
}
|
||||
|
||||
size_t minSize() const {
|
||||
return MIN_TREE_CHUNK_SIZE;
|
||||
return min_tree_chunk_size;
|
||||
}
|
||||
|
||||
double sum_of_squared_block_sizes() const {
|
||||
return sum_of_squared_block_sizes(root());
|
||||
}
|
||||
|
||||
FreeChunk* find_chunk_ends_at(HeapWord* target) const;
|
||||
Chunk* find_chunk_ends_at(HeapWord* target) const;
|
||||
|
||||
// Find the list with size "size" in the binary tree and update
|
||||
// the statistics in the list according to "split" (chunk was
|
||||
|
@ -269,7 +302,7 @@ class BinaryTreeDictionary: public FreeBlockDictionary {
|
|||
// statistics for the sweep.
|
||||
void endSweepDictCensus(double splitSurplusPercent);
|
||||
// Return the largest free chunk in the tree.
|
||||
FreeChunk* findLargestDict() const;
|
||||
Chunk* findLargestDict() const;
|
||||
// Accessors for statistics
|
||||
void setTreeSurplus(double splitSurplusPercent);
|
||||
void setTreeHints(void);
|
||||
|
@ -293,4 +326,4 @@ class BinaryTreeDictionary: public FreeBlockDictionary {
|
|||
void verify() const;
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_BINARYTREEDICTIONARY_HPP
|
||||
#endif // SHARE_VM_MEMORY_BINARYTREEDICTIONARY_HPP
|
|
@ -23,7 +23,10 @@
|
|||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp"
|
||||
#ifndef SERIALGC
|
||||
#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
|
||||
#endif // SERIALGC
|
||||
#include "memory/freeBlockDictionary.hpp"
|
||||
#ifdef TARGET_OS_FAMILY_linux
|
||||
# include "thread_linux.inline.hpp"
|
||||
#endif
|
||||
|
@ -38,15 +41,15 @@
|
|||
#endif
|
||||
|
||||
#ifndef PRODUCT
|
||||
Mutex* FreeBlockDictionary::par_lock() const {
|
||||
template <class Chunk> Mutex* FreeBlockDictionary<Chunk>::par_lock() const {
|
||||
return _lock;
|
||||
}
|
||||
|
||||
void FreeBlockDictionary::set_par_lock(Mutex* lock) {
|
||||
template <class Chunk> void FreeBlockDictionary<Chunk>::set_par_lock(Mutex* lock) {
|
||||
_lock = lock;
|
||||
}
|
||||
|
||||
void FreeBlockDictionary::verify_par_locked() const {
|
||||
template <class Chunk> void FreeBlockDictionary<Chunk>::verify_par_locked() const {
|
||||
#ifdef ASSERT
|
||||
if (ParallelGCThreads > 0) {
|
||||
Thread* myThread = Thread::current();
|
||||
|
@ -58,3 +61,8 @@ void FreeBlockDictionary::verify_par_locked() const {
|
|||
#endif // ASSERT
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SERIALGC
|
||||
// Explicitly instantiate for FreeChunk
|
||||
template class FreeBlockDictionary<FreeChunk>;
|
||||
#endif // SERIALGC
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -22,12 +22,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_FREEBLOCKDICTIONARY_HPP
|
||||
#define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_FREEBLOCKDICTIONARY_HPP
|
||||
#ifndef SHARE_VM_MEMORY_FREEBLOCKDICTIONARY_HPP
|
||||
#define SHARE_VM_MEMORY_FREEBLOCKDICTIONARY_HPP
|
||||
|
||||
#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "memory/memRegion.hpp"
|
||||
#include "runtime/mutex.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
@ -35,6 +33,7 @@
|
|||
|
||||
// A FreeBlockDictionary is an abstract superclass that will allow
|
||||
// a number of alternative implementations in the future.
|
||||
template <class Chunk>
|
||||
class FreeBlockDictionary: public CHeapObj {
|
||||
public:
|
||||
enum Dither {
|
||||
|
@ -52,9 +51,9 @@ class FreeBlockDictionary: public CHeapObj {
|
|||
NOT_PRODUCT(Mutex* _lock;)
|
||||
|
||||
public:
|
||||
virtual void removeChunk(FreeChunk* fc) = 0;
|
||||
virtual FreeChunk* getChunk(size_t size, Dither dither = atLeast) = 0;
|
||||
virtual void returnChunk(FreeChunk* chunk) = 0;
|
||||
virtual void removeChunk(Chunk* fc) = 0;
|
||||
virtual Chunk* getChunk(size_t size, Dither dither = atLeast) = 0;
|
||||
virtual void returnChunk(Chunk* chunk) = 0;
|
||||
virtual size_t totalChunkSize(debug_only(const Mutex* lock)) const = 0;
|
||||
virtual size_t maxChunkSize() const = 0;
|
||||
virtual size_t minSize() const = 0;
|
||||
|
@ -69,14 +68,14 @@ class FreeBlockDictionary: public CHeapObj {
|
|||
float inter_sweep_current, float inter_sweep_estimate,
|
||||
float intra__sweep_current) = 0;
|
||||
virtual void endSweepDictCensus(double splitSurplusPercent) = 0;
|
||||
virtual FreeChunk* findLargestDict() const = 0;
|
||||
virtual Chunk* findLargestDict() const = 0;
|
||||
// verify that the given chunk is in the dictionary.
|
||||
virtual bool verifyChunkInFreeLists(FreeChunk* tc) const = 0;
|
||||
virtual bool verifyChunkInFreeLists(Chunk* tc) const = 0;
|
||||
|
||||
// Sigma_{all_free_blocks} (block_size^2)
|
||||
virtual double sum_of_squared_block_sizes() const = 0;
|
||||
|
||||
virtual FreeChunk* find_chunk_ends_at(HeapWord* target) const = 0;
|
||||
virtual Chunk* find_chunk_ends_at(HeapWord* target) const = 0;
|
||||
virtual void inc_totalSize(size_t v) = 0;
|
||||
virtual void dec_totalSize(size_t v) = 0;
|
||||
|
||||
|
@ -100,4 +99,4 @@ class FreeBlockDictionary: public CHeapObj {
|
|||
void verify_par_locked() const PRODUCT_RETURN;
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_FREEBLOCKDICTIONARY_HPP
|
||||
#endif // SHARE_VM_MEMORY_FREEBLOCKDICTIONARY_HPP
|
|
@ -23,20 +23,25 @@
|
|||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp"
|
||||
#include "gc_implementation/concurrentMarkSweep/freeList.hpp"
|
||||
#include "memory/freeBlockDictionary.hpp"
|
||||
#include "memory/freeList.hpp"
|
||||
#include "memory/sharedHeap.hpp"
|
||||
#include "runtime/globals.hpp"
|
||||
#include "runtime/mutex.hpp"
|
||||
#include "runtime/vmThread.hpp"
|
||||
|
||||
#ifndef SERIALGC
|
||||
#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
|
||||
#endif // SERIALGC
|
||||
|
||||
// Free list. A FreeList is used to access a linked list of chunks
|
||||
// of space in the heap. The head and tail are maintained so that
|
||||
// items can be (as in the current implementation) added at the
|
||||
// at the tail of the list and removed from the head of the list to
|
||||
// maintain a FIFO queue.
|
||||
|
||||
FreeList::FreeList() :
|
||||
template <class Chunk>
|
||||
FreeList<Chunk>::FreeList() :
|
||||
_head(NULL), _tail(NULL)
|
||||
#ifdef ASSERT
|
||||
, _protecting_lock(NULL)
|
||||
|
@ -48,7 +53,8 @@ FreeList::FreeList() :
|
|||
init_statistics();
|
||||
}
|
||||
|
||||
FreeList::FreeList(FreeChunk* fc) :
|
||||
template <class Chunk>
|
||||
FreeList<Chunk>::FreeList(Chunk* fc) :
|
||||
_head(fc), _tail(fc)
|
||||
#ifdef ASSERT
|
||||
, _protecting_lock(NULL)
|
||||
|
@ -63,40 +69,27 @@ FreeList::FreeList(FreeChunk* fc) :
|
|||
#endif
|
||||
}
|
||||
|
||||
FreeList::FreeList(HeapWord* addr, size_t size) :
|
||||
_head((FreeChunk*) addr), _tail((FreeChunk*) addr)
|
||||
#ifdef ASSERT
|
||||
, _protecting_lock(NULL)
|
||||
#endif
|
||||
{
|
||||
assert(size > sizeof(FreeChunk), "size is too small");
|
||||
head()->setSize(size);
|
||||
_size = size;
|
||||
_count = 1;
|
||||
init_statistics();
|
||||
#ifndef PRODUCT
|
||||
_allocation_stats.set_returnedBytes(_size * HeapWordSize);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FreeList::reset(size_t hint) {
|
||||
template <class Chunk>
|
||||
void FreeList<Chunk>::reset(size_t hint) {
|
||||
set_count(0);
|
||||
set_head(NULL);
|
||||
set_tail(NULL);
|
||||
set_hint(hint);
|
||||
}
|
||||
|
||||
void FreeList::init_statistics(bool split_birth) {
|
||||
template <class Chunk>
|
||||
void FreeList<Chunk>::init_statistics(bool split_birth) {
|
||||
_allocation_stats.initialize(split_birth);
|
||||
}
|
||||
|
||||
FreeChunk* FreeList::getChunkAtHead() {
|
||||
template <class Chunk>
|
||||
Chunk* FreeList<Chunk>::getChunkAtHead() {
|
||||
assert_proper_lock_protection();
|
||||
assert(head() == NULL || head()->prev() == NULL, "list invariant");
|
||||
assert(tail() == NULL || tail()->next() == NULL, "list invariant");
|
||||
FreeChunk* fc = head();
|
||||
Chunk* fc = head();
|
||||
if (fc != NULL) {
|
||||
FreeChunk* nextFC = fc->next();
|
||||
Chunk* nextFC = fc->next();
|
||||
if (nextFC != NULL) {
|
||||
// The chunk fc being removed has a "next". Set the "next" to the
|
||||
// "prev" of fc.
|
||||
|
@ -113,20 +106,21 @@ FreeChunk* FreeList::getChunkAtHead() {
|
|||
}
|
||||
|
||||
|
||||
void FreeList::getFirstNChunksFromList(size_t n, FreeList* fl) {
|
||||
template <class Chunk>
|
||||
void FreeList<Chunk>::getFirstNChunksFromList(size_t n, FreeList<Chunk>* fl) {
|
||||
assert_proper_lock_protection();
|
||||
assert(fl->count() == 0, "Precondition");
|
||||
if (count() > 0) {
|
||||
int k = 1;
|
||||
fl->set_head(head()); n--;
|
||||
FreeChunk* tl = head();
|
||||
Chunk* tl = head();
|
||||
while (tl->next() != NULL && n > 0) {
|
||||
tl = tl->next(); n--; k++;
|
||||
}
|
||||
assert(tl != NULL, "Loop Inv.");
|
||||
|
||||
// First, fix up the list we took from.
|
||||
FreeChunk* new_head = tl->next();
|
||||
Chunk* new_head = tl->next();
|
||||
set_head(new_head);
|
||||
set_count(count() - k);
|
||||
if (new_head == NULL) {
|
||||
|
@ -143,7 +137,8 @@ void FreeList::getFirstNChunksFromList(size_t n, FreeList* fl) {
|
|||
}
|
||||
|
||||
// Remove this chunk from the list
|
||||
void FreeList::removeChunk(FreeChunk*fc) {
|
||||
template <class Chunk>
|
||||
void FreeList<Chunk>::removeChunk(Chunk*fc) {
|
||||
assert_proper_lock_protection();
|
||||
assert(head() != NULL, "Remove from empty list");
|
||||
assert(fc != NULL, "Remove a NULL chunk");
|
||||
|
@ -151,8 +146,8 @@ void FreeList::removeChunk(FreeChunk*fc) {
|
|||
assert(head() == NULL || head()->prev() == NULL, "list invariant");
|
||||
assert(tail() == NULL || tail()->next() == NULL, "list invariant");
|
||||
|
||||
FreeChunk* prevFC = fc->prev();
|
||||
FreeChunk* nextFC = fc->next();
|
||||
Chunk* prevFC = fc->prev();
|
||||
Chunk* nextFC = fc->next();
|
||||
if (nextFC != NULL) {
|
||||
// The chunk fc being removed has a "next". Set the "next" to the
|
||||
// "prev" of fc.
|
||||
|
@ -185,14 +180,15 @@ void FreeList::removeChunk(FreeChunk*fc) {
|
|||
}
|
||||
|
||||
// Add this chunk at the head of the list.
|
||||
void FreeList::returnChunkAtHead(FreeChunk* chunk, bool record_return) {
|
||||
template <class Chunk>
|
||||
void FreeList<Chunk>::returnChunkAtHead(Chunk* chunk, bool record_return) {
|
||||
assert_proper_lock_protection();
|
||||
assert(chunk != NULL, "insert a NULL chunk");
|
||||
assert(size() == chunk->size(), "Wrong size");
|
||||
assert(head() == NULL || head()->prev() == NULL, "list invariant");
|
||||
assert(tail() == NULL || tail()->next() == NULL, "list invariant");
|
||||
|
||||
FreeChunk* oldHead = head();
|
||||
Chunk* oldHead = head();
|
||||
assert(chunk != oldHead, "double insertion");
|
||||
chunk->linkAfter(oldHead);
|
||||
link_head(chunk);
|
||||
|
@ -212,20 +208,22 @@ void FreeList::returnChunkAtHead(FreeChunk* chunk, bool record_return) {
|
|||
assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
|
||||
}
|
||||
|
||||
void FreeList::returnChunkAtHead(FreeChunk* chunk) {
|
||||
template <class Chunk>
|
||||
void FreeList<Chunk>::returnChunkAtHead(Chunk* chunk) {
|
||||
assert_proper_lock_protection();
|
||||
returnChunkAtHead(chunk, true);
|
||||
}
|
||||
|
||||
// Add this chunk at the tail of the list.
|
||||
void FreeList::returnChunkAtTail(FreeChunk* chunk, bool record_return) {
|
||||
template <class Chunk>
|
||||
void FreeList<Chunk>::returnChunkAtTail(Chunk* chunk, bool record_return) {
|
||||
assert_proper_lock_protection();
|
||||
assert(head() == NULL || head()->prev() == NULL, "list invariant");
|
||||
assert(tail() == NULL || tail()->next() == NULL, "list invariant");
|
||||
assert(chunk != NULL, "insert a NULL chunk");
|
||||
assert(size() == chunk->size(), "wrong size");
|
||||
|
||||
FreeChunk* oldTail = tail();
|
||||
Chunk* oldTail = tail();
|
||||
assert(chunk != oldTail, "double insertion");
|
||||
if (oldTail != NULL) {
|
||||
oldTail->linkAfter(chunk);
|
||||
|
@ -246,11 +244,13 @@ void FreeList::returnChunkAtTail(FreeChunk* chunk, bool record_return) {
|
|||
assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
|
||||
}
|
||||
|
||||
void FreeList::returnChunkAtTail(FreeChunk* chunk) {
|
||||
template <class Chunk>
|
||||
void FreeList<Chunk>::returnChunkAtTail(Chunk* chunk) {
|
||||
returnChunkAtTail(chunk, true);
|
||||
}
|
||||
|
||||
void FreeList::prepend(FreeList* fl) {
|
||||
template <class Chunk>
|
||||
void FreeList<Chunk>::prepend(FreeList<Chunk>* fl) {
|
||||
assert_proper_lock_protection();
|
||||
if (fl->count() > 0) {
|
||||
if (count() == 0) {
|
||||
|
@ -259,8 +259,8 @@ void FreeList::prepend(FreeList* fl) {
|
|||
set_count(fl->count());
|
||||
} else {
|
||||
// Both are non-empty.
|
||||
FreeChunk* fl_tail = fl->tail();
|
||||
FreeChunk* this_head = head();
|
||||
Chunk* fl_tail = fl->tail();
|
||||
Chunk* this_head = head();
|
||||
assert(fl_tail->next() == NULL, "Well-formedness of fl");
|
||||
fl_tail->linkNext(this_head);
|
||||
this_head->linkPrev(fl_tail);
|
||||
|
@ -275,11 +275,12 @@ void FreeList::prepend(FreeList* fl) {
|
|||
|
||||
// verifyChunkInFreeLists() is used to verify that an item is in this free list.
|
||||
// It is used as a debugging aid.
|
||||
bool FreeList::verifyChunkInFreeLists(FreeChunk* fc) const {
|
||||
template <class Chunk>
|
||||
bool FreeList<Chunk>::verifyChunkInFreeLists(Chunk* fc) const {
|
||||
// This is an internal consistency check, not part of the check that the
|
||||
// chunk is in the free lists.
|
||||
guarantee(fc->size() == size(), "Wrong list is being searched");
|
||||
FreeChunk* curFC = head();
|
||||
Chunk* curFC = head();
|
||||
while (curFC) {
|
||||
// This is an internal consistency check.
|
||||
guarantee(size() == curFC->size(), "Chunk is in wrong list.");
|
||||
|
@ -292,7 +293,8 @@ bool FreeList::verifyChunkInFreeLists(FreeChunk* fc) const {
|
|||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void FreeList::verify_stats() const {
|
||||
template <class Chunk>
|
||||
void FreeList<Chunk>::verify_stats() const {
|
||||
// The +1 of the LH comparand is to allow some "looseness" in
|
||||
// checking: we usually call this interface when adding a block
|
||||
// and we'll subsequently update the stats; we cannot update the
|
||||
|
@ -317,7 +319,8 @@ void FreeList::verify_stats() const {
|
|||
_allocation_stats.coalDeaths(), count()));
|
||||
}
|
||||
|
||||
void FreeList::assert_proper_lock_protection_work() const {
|
||||
template <class Chunk>
|
||||
void FreeList<Chunk>::assert_proper_lock_protection_work() const {
|
||||
assert(_protecting_lock != NULL, "Don't call this directly");
|
||||
assert(ParallelGCThreads > 0, "Don't call this directly");
|
||||
Thread* thr = Thread::current();
|
||||
|
@ -334,7 +337,8 @@ void FreeList::assert_proper_lock_protection_work() const {
|
|||
#endif
|
||||
|
||||
// Print the "label line" for free list stats.
|
||||
void FreeList::print_labels_on(outputStream* st, const char* c) {
|
||||
template <class Chunk>
|
||||
void FreeList<Chunk>::print_labels_on(outputStream* st, const char* c) {
|
||||
st->print("%16s\t", c);
|
||||
st->print("%14s\t" "%14s\t" "%14s\t" "%14s\t" "%14s\t"
|
||||
"%14s\t" "%14s\t" "%14s\t" "%14s\t" "%14s\t" "\n",
|
||||
|
@ -346,7 +350,8 @@ void FreeList::print_labels_on(outputStream* st, const char* c) {
|
|||
// to the call is a non-null string, it is printed in the first column;
|
||||
// otherwise, if the argument is null (the default), then the size of the
|
||||
// (free list) block is printed in the first column.
|
||||
void FreeList::print_on(outputStream* st, const char* c) const {
|
||||
template <class Chunk>
|
||||
void FreeList<Chunk>::print_on(outputStream* st, const char* c) const {
|
||||
if (c != NULL) {
|
||||
st->print("%16s", c);
|
||||
} else {
|
||||
|
@ -358,3 +363,8 @@ void FreeList::print_on(outputStream* st, const char* c) const {
|
|||
bfrSurp(), surplus(), desired(), prevSweep(), beforeSweep(),
|
||||
count(), coalBirths(), coalDeaths(), splitBirths(), splitDeaths());
|
||||
}
|
||||
|
||||
#ifndef SERIALGC
|
||||
// Needs to be after the definitions have been seen.
|
||||
template class FreeList<FreeChunk>;
|
||||
#endif // SERIALGC
|
|
@ -22,39 +22,36 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_FREELIST_HPP
|
||||
#define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_FREELIST_HPP
|
||||
#ifndef SHARE_VM_MEMORY_FREELIST_HPP
|
||||
#define SHARE_VM_MEMORY_FREELIST_HPP
|
||||
|
||||
#include "gc_implementation/shared/allocationStats.hpp"
|
||||
|
||||
class CompactibleFreeListSpace;
|
||||
|
||||
// A class for maintaining a free list of FreeChunk's. The FreeList
|
||||
// A class for maintaining a free list of Chunk's. The FreeList
|
||||
// maintains a the structure of the list (head, tail, etc.) plus
|
||||
// statistics for allocations from the list. The links between items
|
||||
// are not part of FreeList. The statistics are
|
||||
// used to make decisions about coalescing FreeChunk's when they
|
||||
// used to make decisions about coalescing Chunk's when they
|
||||
// are swept during collection.
|
||||
//
|
||||
// See the corresponding .cpp file for a description of the specifics
|
||||
// for that implementation.
|
||||
|
||||
class Mutex;
|
||||
class TreeList;
|
||||
template <class Chunk> class TreeList;
|
||||
template <class Chunk> class PrintTreeCensusClosure;
|
||||
|
||||
template <class Chunk>
|
||||
class FreeList VALUE_OBJ_CLASS_SPEC {
|
||||
friend class CompactibleFreeListSpace;
|
||||
friend class VMStructs;
|
||||
friend class PrintTreeCensusClosure;
|
||||
|
||||
protected:
|
||||
TreeList* _parent;
|
||||
TreeList* _left;
|
||||
TreeList* _right;
|
||||
friend class PrintTreeCensusClosure<Chunk>;
|
||||
|
||||
private:
|
||||
FreeChunk* _head; // Head of list of free chunks
|
||||
FreeChunk* _tail; // Tail of list of free chunks
|
||||
Chunk* _head; // Head of list of free chunks
|
||||
Chunk* _tail; // Tail of list of free chunks
|
||||
size_t _size; // Size in Heap words of each chunk
|
||||
ssize_t _count; // Number of entries in list
|
||||
size_t _hint; // next larger size list with a positive surplus
|
||||
|
@ -92,10 +89,7 @@ class FreeList VALUE_OBJ_CLASS_SPEC {
|
|||
// Construct a list without any entries.
|
||||
FreeList();
|
||||
// Construct a list with "fc" as the first (and lone) entry in the list.
|
||||
FreeList(FreeChunk* fc);
|
||||
// Construct a list which will have a FreeChunk at address "addr" and
|
||||
// of size "size" as the first (and lone) entry in the list.
|
||||
FreeList(HeapWord* addr, size_t size);
|
||||
FreeList(Chunk* fc);
|
||||
|
||||
// Reset the head, tail, hint, and count of a free list.
|
||||
void reset(size_t hint);
|
||||
|
@ -108,18 +102,18 @@ class FreeList VALUE_OBJ_CLASS_SPEC {
|
|||
#endif
|
||||
|
||||
// Accessors.
|
||||
FreeChunk* head() const {
|
||||
Chunk* head() const {
|
||||
assert_proper_lock_protection();
|
||||
return _head;
|
||||
}
|
||||
void set_head(FreeChunk* v) {
|
||||
void set_head(Chunk* v) {
|
||||
assert_proper_lock_protection();
|
||||
_head = v;
|
||||
assert(!_head || _head->size() == _size, "bad chunk size");
|
||||
}
|
||||
// Set the head of the list and set the prev field of non-null
|
||||
// values to NULL.
|
||||
void link_head(FreeChunk* v) {
|
||||
void link_head(Chunk* v) {
|
||||
assert_proper_lock_protection();
|
||||
set_head(v);
|
||||
// If this method is not used (just set the head instead),
|
||||
|
@ -129,18 +123,18 @@ class FreeList VALUE_OBJ_CLASS_SPEC {
|
|||
}
|
||||
}
|
||||
|
||||
FreeChunk* tail() const {
|
||||
Chunk* tail() const {
|
||||
assert_proper_lock_protection();
|
||||
return _tail;
|
||||
}
|
||||
void set_tail(FreeChunk* v) {
|
||||
void set_tail(Chunk* v) {
|
||||
assert_proper_lock_protection();
|
||||
_tail = v;
|
||||
assert(!_tail || _tail->size() == _size, "bad chunk size");
|
||||
}
|
||||
// Set the tail of the list and set the next field of non-null
|
||||
// values to NULL.
|
||||
void link_tail(FreeChunk* v) {
|
||||
void link_tail(Chunk* v) {
|
||||
assert_proper_lock_protection();
|
||||
set_tail(v);
|
||||
if (v != NULL) {
|
||||
|
@ -298,31 +292,31 @@ class FreeList VALUE_OBJ_CLASS_SPEC {
|
|||
|
||||
// Unlink head of list and return it. Returns NULL if
|
||||
// the list is empty.
|
||||
FreeChunk* getChunkAtHead();
|
||||
Chunk* getChunkAtHead();
|
||||
|
||||
// Remove the first "n" or "count", whichever is smaller, chunks from the
|
||||
// list, setting "fl", which is required to be empty, to point to them.
|
||||
void getFirstNChunksFromList(size_t n, FreeList* fl);
|
||||
void getFirstNChunksFromList(size_t n, FreeList<Chunk>* fl);
|
||||
|
||||
// Unlink this chunk from it's free list
|
||||
void removeChunk(FreeChunk* fc);
|
||||
void removeChunk(Chunk* fc);
|
||||
|
||||
// Add this chunk to this free list.
|
||||
void returnChunkAtHead(FreeChunk* fc);
|
||||
void returnChunkAtTail(FreeChunk* fc);
|
||||
void returnChunkAtHead(Chunk* fc);
|
||||
void returnChunkAtTail(Chunk* fc);
|
||||
|
||||
// Similar to returnChunk* but also records some diagnostic
|
||||
// information.
|
||||
void returnChunkAtHead(FreeChunk* fc, bool record_return);
|
||||
void returnChunkAtTail(FreeChunk* fc, bool record_return);
|
||||
void returnChunkAtHead(Chunk* fc, bool record_return);
|
||||
void returnChunkAtTail(Chunk* fc, bool record_return);
|
||||
|
||||
// Prepend "fl" (whose size is required to be the same as that of "this")
|
||||
// to the front of "this" list.
|
||||
void prepend(FreeList* fl);
|
||||
void prepend(FreeList<Chunk>* fl);
|
||||
|
||||
// Verify that the chunk is in the list.
|
||||
// found. Return NULL if "fc" is not found.
|
||||
bool verifyChunkInFreeLists(FreeChunk* fc) const;
|
||||
bool verifyChunkInFreeLists(Chunk* fc) const;
|
||||
|
||||
// Stats verification
|
||||
void verify_stats() const PRODUCT_RETURN;
|
||||
|
@ -332,4 +326,4 @@ class FreeList VALUE_OBJ_CLASS_SPEC {
|
|||
void print_on(outputStream* st, const char* c = NULL) const;
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_FREELIST_HPP
|
||||
#endif // SHARE_VM_MEMORY_FREELIST_HPP
|
|
@ -68,7 +68,7 @@ Generation* GenerationSpec::init(ReservedSpace rs, int level,
|
|||
ConcurrentMarkSweepGeneration* g = NULL;
|
||||
g = new ConcurrentMarkSweepGeneration(rs,
|
||||
init_size(), level, ctrs, UseCMSAdaptiveFreeLists,
|
||||
(FreeBlockDictionary::DictionaryChoice)CMSDictionaryChoice);
|
||||
(FreeBlockDictionary<FreeChunk>::DictionaryChoice)CMSDictionaryChoice);
|
||||
|
||||
g->initialize_performance_counters();
|
||||
|
||||
|
@ -88,7 +88,7 @@ Generation* GenerationSpec::init(ReservedSpace rs, int level,
|
|||
ASConcurrentMarkSweepGeneration* g = NULL;
|
||||
g = new ASConcurrentMarkSweepGeneration(rs,
|
||||
init_size(), level, ctrs, UseCMSAdaptiveFreeLists,
|
||||
(FreeBlockDictionary::DictionaryChoice)CMSDictionaryChoice);
|
||||
(FreeBlockDictionary<FreeChunk>::DictionaryChoice)CMSDictionaryChoice);
|
||||
|
||||
g->initialize_performance_counters();
|
||||
|
||||
|
@ -175,7 +175,7 @@ PermGen* PermanentGenerationSpec::init(ReservedSpace rs,
|
|||
}
|
||||
// XXXPERM
|
||||
return new CMSPermGen(perm_rs, init_size, ctrs,
|
||||
(FreeBlockDictionary::DictionaryChoice)CMSDictionaryChoice);
|
||||
(FreeBlockDictionary<FreeChunk>::DictionaryChoice)CMSDictionaryChoice);
|
||||
}
|
||||
#endif // SERIALGC
|
||||
default:
|
||||
|
|
|
@ -293,13 +293,10 @@
|
|||
# include "c1/c1_globals.hpp"
|
||||
#endif // COMPILER1
|
||||
#ifndef SERIALGC
|
||||
# include "gc_implementation/concurrentMarkSweep/binaryTreeDictionary.hpp"
|
||||
# include "gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp"
|
||||
# include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp"
|
||||
# include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp"
|
||||
# include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp"
|
||||
# include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
|
||||
# include "gc_implementation/concurrentMarkSweep/freeList.hpp"
|
||||
# include "gc_implementation/concurrentMarkSweep/promotionInfo.hpp"
|
||||
# include "gc_implementation/g1/dirtyCardQueue.hpp"
|
||||
# include "gc_implementation/g1/g1BlockOffsetTable.hpp"
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
#include "code/vmreg.hpp"
|
||||
#include "compiler/oopMap.hpp"
|
||||
#include "compiler/compileBroker.hpp"
|
||||
#include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp"
|
||||
#include "gc_implementation/shared/immutableSpace.hpp"
|
||||
#include "gc_implementation/shared/markSweep.hpp"
|
||||
#include "gc_implementation/shared/mutableSpace.hpp"
|
||||
|
@ -55,6 +54,7 @@
|
|||
#include "memory/cardTableRS.hpp"
|
||||
#include "memory/compactPermGen.hpp"
|
||||
#include "memory/defNewGeneration.hpp"
|
||||
#include "memory/freeBlockDictionary.hpp"
|
||||
#include "memory/genCollectedHeap.hpp"
|
||||
#include "memory/generation.hpp"
|
||||
#include "memory/generationSpec.hpp"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue