mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 19:14:38 +02:00
8011173: NPG: Replace the ChunkList implementation with class FreeList<Metachunk>
Reviewed-by: mgerdin, tschatzl, johnc, coleenp
This commit is contained in:
parent
bd3eb2abf6
commit
7f78a7f475
1 changed files with 40 additions and 97 deletions
|
@ -103,27 +103,7 @@ bool MetaspaceGC::_should_concurrent_collect = false;
|
||||||
// a chunk is placed on the free list of blocks (BlockFreelist) and
|
// a chunk is placed on the free list of blocks (BlockFreelist) and
|
||||||
// reused from there.
|
// reused from there.
|
||||||
|
|
||||||
// Pointer to list of Metachunks.
|
typedef class FreeList<Metachunk> ChunkList;
|
||||||
class ChunkList VALUE_OBJ_CLASS_SPEC {
|
|
||||||
// List of free chunks
|
|
||||||
Metachunk* _head;
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Constructor
|
|
||||||
ChunkList() : _head(NULL) {}
|
|
||||||
|
|
||||||
// Accessors
|
|
||||||
Metachunk* head() { return _head; }
|
|
||||||
void set_head(Metachunk* v) { _head = v; }
|
|
||||||
|
|
||||||
// Link at head of the list
|
|
||||||
void add_at_head(Metachunk* head, Metachunk* tail);
|
|
||||||
void add_at_head(Metachunk* head);
|
|
||||||
|
|
||||||
size_t sum_list_size();
|
|
||||||
size_t sum_list_count();
|
|
||||||
size_t sum_list_capacity();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Manages the global free lists of chunks.
|
// Manages the global free lists of chunks.
|
||||||
// Has three lists of free chunks, and a total size and
|
// Has three lists of free chunks, and a total size and
|
||||||
|
@ -185,6 +165,10 @@ class ChunkManager VALUE_OBJ_CLASS_SPEC {
|
||||||
// for special, small, medium, and humongous chunks.
|
// for special, small, medium, and humongous chunks.
|
||||||
static ChunkIndex list_index(size_t size);
|
static ChunkIndex list_index(size_t size);
|
||||||
|
|
||||||
|
// Add the simple linked list of chunks to the freelist of chunks
|
||||||
|
// of type index.
|
||||||
|
void return_chunks(ChunkIndex index, Metachunk* chunks);
|
||||||
|
|
||||||
// Total of the space in the free chunks list
|
// Total of the space in the free chunks list
|
||||||
size_t free_chunks_total();
|
size_t free_chunks_total();
|
||||||
size_t free_chunks_total_in_bytes();
|
size_t free_chunks_total_in_bytes();
|
||||||
|
@ -899,6 +883,9 @@ VirtualSpaceList::VirtualSpaceList(size_t word_size ) :
|
||||||
Mutex::_no_safepoint_check_flag);
|
Mutex::_no_safepoint_check_flag);
|
||||||
bool initialization_succeeded = grow_vs(word_size);
|
bool initialization_succeeded = grow_vs(word_size);
|
||||||
|
|
||||||
|
_chunk_manager.free_chunks(SpecializedIndex)->set_size(SpecializedChunk);
|
||||||
|
_chunk_manager.free_chunks(SmallIndex)->set_size(SmallChunk);
|
||||||
|
_chunk_manager.free_chunks(MediumIndex)->set_size(MediumChunk);
|
||||||
assert(initialization_succeeded,
|
assert(initialization_succeeded,
|
||||||
" VirtualSpaceList initialization should not fail");
|
" VirtualSpaceList initialization should not fail");
|
||||||
}
|
}
|
||||||
|
@ -913,6 +900,9 @@ VirtualSpaceList::VirtualSpaceList(ReservedSpace rs) :
|
||||||
Mutex::_no_safepoint_check_flag);
|
Mutex::_no_safepoint_check_flag);
|
||||||
VirtualSpaceNode* class_entry = new VirtualSpaceNode(rs);
|
VirtualSpaceNode* class_entry = new VirtualSpaceNode(rs);
|
||||||
bool succeeded = class_entry->initialize();
|
bool succeeded = class_entry->initialize();
|
||||||
|
_chunk_manager.free_chunks(SpecializedIndex)->set_size(SpecializedChunk);
|
||||||
|
_chunk_manager.free_chunks(SmallIndex)->set_size(ClassSmallChunk);
|
||||||
|
_chunk_manager.free_chunks(MediumIndex)->set_size(ClassMediumChunk);
|
||||||
assert(succeeded, " VirtualSpaceList initialization should not fail");
|
assert(succeeded, " VirtualSpaceList initialization should not fail");
|
||||||
link_vs(class_entry, rs.size()/BytesPerWord);
|
link_vs(class_entry, rs.size()/BytesPerWord);
|
||||||
}
|
}
|
||||||
|
@ -1380,76 +1370,6 @@ bool Metadebug::test_metadata_failure() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ChunkList methods
|
|
||||||
|
|
||||||
size_t ChunkList::sum_list_size() {
|
|
||||||
size_t result = 0;
|
|
||||||
Metachunk* cur = head();
|
|
||||||
while (cur != NULL) {
|
|
||||||
result += cur->word_size();
|
|
||||||
cur = cur->next();
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ChunkList::sum_list_count() {
|
|
||||||
size_t result = 0;
|
|
||||||
Metachunk* cur = head();
|
|
||||||
while (cur != NULL) {
|
|
||||||
result++;
|
|
||||||
cur = cur->next();
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ChunkList::sum_list_capacity() {
|
|
||||||
size_t result = 0;
|
|
||||||
Metachunk* cur = head();
|
|
||||||
while (cur != NULL) {
|
|
||||||
result += cur->capacity_word_size();
|
|
||||||
cur = cur->next();
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChunkList::add_at_head(Metachunk* head, Metachunk* tail) {
|
|
||||||
assert_lock_strong(SpaceManager::expand_lock());
|
|
||||||
assert(head == tail || tail->next() == NULL,
|
|
||||||
"Not the tail or the head has already been added to a list");
|
|
||||||
|
|
||||||
if (TraceMetadataChunkAllocation && Verbose) {
|
|
||||||
gclog_or_tty->print("ChunkList::add_at_head(head, tail): ");
|
|
||||||
Metachunk* cur = head;
|
|
||||||
while (cur != NULL) {
|
|
||||||
gclog_or_tty->print(PTR_FORMAT " (" SIZE_FORMAT ") ", cur, cur->word_size());
|
|
||||||
cur = cur->next();
|
|
||||||
}
|
|
||||||
gclog_or_tty->print_cr("");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tail != NULL) {
|
|
||||||
tail->set_next(_head);
|
|
||||||
}
|
|
||||||
set_head(head);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChunkList::add_at_head(Metachunk* list) {
|
|
||||||
if (list == NULL) {
|
|
||||||
// Nothing to add
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
assert_lock_strong(SpaceManager::expand_lock());
|
|
||||||
Metachunk* head = list;
|
|
||||||
Metachunk* tail = list;
|
|
||||||
Metachunk* cur = head->next();
|
|
||||||
// Search for the tail since it is not passed.
|
|
||||||
while (cur != NULL) {
|
|
||||||
tail = cur;
|
|
||||||
cur = cur->next();
|
|
||||||
}
|
|
||||||
add_at_head(head, tail);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChunkManager methods
|
// ChunkManager methods
|
||||||
|
|
||||||
// Verification of _free_chunks_total and _free_chunks_count does not
|
// Verification of _free_chunks_total and _free_chunks_count does not
|
||||||
|
@ -1553,7 +1473,7 @@ size_t ChunkManager::sum_free_chunks() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = result + list->sum_list_capacity();
|
result = result + list->count() * list->size();
|
||||||
}
|
}
|
||||||
result = result + humongous_dictionary()->total_size();
|
result = result + humongous_dictionary()->total_size();
|
||||||
return result;
|
return result;
|
||||||
|
@ -1567,7 +1487,7 @@ size_t ChunkManager::sum_free_chunks_count() {
|
||||||
if (list == NULL) {
|
if (list == NULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
count = count + list->sum_list_count();
|
count = count + list->count();
|
||||||
}
|
}
|
||||||
count = count + humongous_dictionary()->total_free_blocks();
|
count = count + humongous_dictionary()->total_free_blocks();
|
||||||
return count;
|
return count;
|
||||||
|
@ -1622,7 +1542,7 @@ Metachunk* ChunkManager::free_chunks_get(size_t word_size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the chunk as the head of the list.
|
// Remove the chunk as the head of the list.
|
||||||
free_list->set_head(chunk->next());
|
free_list->remove_chunk(chunk);
|
||||||
|
|
||||||
// Chunk is being removed from the chunks free list.
|
// Chunk is being removed from the chunks free list.
|
||||||
dec_free_chunks_total(chunk->capacity_word_size());
|
dec_free_chunks_total(chunk->capacity_word_size());
|
||||||
|
@ -1679,7 +1599,7 @@ Metachunk* ChunkManager::chunk_freelist_allocate(size_t word_size) {
|
||||||
size_t list_count;
|
size_t list_count;
|
||||||
if (list_index(word_size) < HumongousIndex) {
|
if (list_index(word_size) < HumongousIndex) {
|
||||||
ChunkList* list = find_free_chunks_list(word_size);
|
ChunkList* list = find_free_chunks_list(word_size);
|
||||||
list_count = list->sum_list_count();
|
list_count = list->count();
|
||||||
} else {
|
} else {
|
||||||
list_count = humongous_dictionary()->total_count();
|
list_count = humongous_dictionary()->total_count();
|
||||||
}
|
}
|
||||||
|
@ -1958,6 +1878,29 @@ void SpaceManager::initialize() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChunkManager::return_chunks(ChunkIndex index, Metachunk* chunks) {
|
||||||
|
if (chunks == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ChunkList* list = free_chunks(index);
|
||||||
|
assert(list->size() == chunks->word_size(), "Mismatch in chunk sizes");
|
||||||
|
assert_lock_strong(SpaceManager::expand_lock());
|
||||||
|
Metachunk* cur = chunks;
|
||||||
|
|
||||||
|
// This return chunks one at a time. If a new
|
||||||
|
// class List can be created that is a base class
|
||||||
|
// of FreeList then something like FreeList::prepend()
|
||||||
|
// can be used in place of this loop
|
||||||
|
while (cur != NULL) {
|
||||||
|
// Capture the next link before it is changed
|
||||||
|
// by the call to return_chunk_at_head();
|
||||||
|
Metachunk* next = cur->next();
|
||||||
|
cur->set_is_free(true);
|
||||||
|
list->return_chunk_at_head(cur);
|
||||||
|
cur = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SpaceManager::~SpaceManager() {
|
SpaceManager::~SpaceManager() {
|
||||||
// This call this->_lock which can't be done while holding expand_lock()
|
// This call this->_lock which can't be done while holding expand_lock()
|
||||||
const size_t in_use_before = sum_capacity_in_chunks_in_use();
|
const size_t in_use_before = sum_capacity_in_chunks_in_use();
|
||||||
|
@ -1995,11 +1938,11 @@ SpaceManager::~SpaceManager() {
|
||||||
chunk_size_name(i));
|
chunk_size_name(i));
|
||||||
}
|
}
|
||||||
Metachunk* chunks = chunks_in_use(i);
|
Metachunk* chunks = chunks_in_use(i);
|
||||||
chunk_manager->free_chunks(i)->add_at_head(chunks);
|
chunk_manager->return_chunks(i, chunks);
|
||||||
set_chunks_in_use(i, NULL);
|
set_chunks_in_use(i, NULL);
|
||||||
if (TraceMetadataChunkAllocation && Verbose) {
|
if (TraceMetadataChunkAllocation && Verbose) {
|
||||||
gclog_or_tty->print_cr("updated freelist count %d %s",
|
gclog_or_tty->print_cr("updated freelist count %d %s",
|
||||||
chunk_manager->free_chunks(i)->sum_list_count(),
|
chunk_manager->free_chunks(i)->count(),
|
||||||
chunk_size_name(i));
|
chunk_size_name(i));
|
||||||
}
|
}
|
||||||
assert(i != HumongousIndex, "Humongous chunks are handled explicitly later");
|
assert(i != HumongousIndex, "Humongous chunks are handled explicitly later");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue