mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 11:34:38 +02:00
8025096: Move the ChunkManager instances out of the VirtualSpaceLists
Reviewed-by: coleenp, mgerdin, jmasa
This commit is contained in:
parent
bbb009b580
commit
22272f5043
2 changed files with 116 additions and 127 deletions
|
@ -23,6 +23,7 @@
|
||||||
*/
|
*/
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "gc_interface/collectedHeap.hpp"
|
#include "gc_interface/collectedHeap.hpp"
|
||||||
|
#include "memory/allocation.hpp"
|
||||||
#include "memory/binaryTreeDictionary.hpp"
|
#include "memory/binaryTreeDictionary.hpp"
|
||||||
#include "memory/freeList.hpp"
|
#include "memory/freeList.hpp"
|
||||||
#include "memory/collectorPolicy.hpp"
|
#include "memory/collectorPolicy.hpp"
|
||||||
|
@ -111,7 +112,7 @@ typedef class FreeList<Metachunk> ChunkList;
|
||||||
// Has three lists of free chunks, and a total size and
|
// Has three lists of free chunks, and a total size and
|
||||||
// count that includes all three
|
// count that includes all three
|
||||||
|
|
||||||
class ChunkManager VALUE_OBJ_CLASS_SPEC {
|
class ChunkManager : public CHeapObj<mtInternal> {
|
||||||
|
|
||||||
// Free list of chunks of different sizes.
|
// Free list of chunks of different sizes.
|
||||||
// SpecializedChunk
|
// SpecializedChunk
|
||||||
|
@ -158,7 +159,12 @@ class ChunkManager VALUE_OBJ_CLASS_SPEC {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ChunkManager() : _free_chunks_total(0), _free_chunks_count(0) {}
|
ChunkManager(size_t specialized_size, size_t small_size, size_t medium_size)
|
||||||
|
: _free_chunks_total(0), _free_chunks_count(0) {
|
||||||
|
_free_chunks[SpecializedIndex].set_size(specialized_size);
|
||||||
|
_free_chunks[SmallIndex].set_size(small_size);
|
||||||
|
_free_chunks[MediumIndex].set_size(medium_size);
|
||||||
|
}
|
||||||
|
|
||||||
// add or delete (return) a chunk to the global freelist.
|
// add or delete (return) a chunk to the global freelist.
|
||||||
Metachunk* chunk_freelist_allocate(size_t word_size);
|
Metachunk* chunk_freelist_allocate(size_t word_size);
|
||||||
|
@ -219,7 +225,7 @@ class ChunkManager VALUE_OBJ_CLASS_SPEC {
|
||||||
void locked_print_free_chunks(outputStream* st);
|
void locked_print_free_chunks(outputStream* st);
|
||||||
void locked_print_sum_free_chunks(outputStream* st);
|
void locked_print_sum_free_chunks(outputStream* st);
|
||||||
|
|
||||||
void print_on(outputStream* st);
|
void print_on(outputStream* st) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Used to manage the free list of Metablocks (a block corresponds
|
// Used to manage the free list of Metablocks (a block corresponds
|
||||||
|
@ -276,11 +282,6 @@ class VirtualSpaceNode : public CHeapObj<mtClass> {
|
||||||
// VirtualSpace
|
// VirtualSpace
|
||||||
Metachunk* first_chunk() { return (Metachunk*) bottom(); }
|
Metachunk* first_chunk() { return (Metachunk*) bottom(); }
|
||||||
|
|
||||||
void inc_container_count();
|
|
||||||
#ifdef ASSERT
|
|
||||||
uint container_count_slow();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
VirtualSpaceNode(size_t byte_size);
|
VirtualSpaceNode(size_t byte_size);
|
||||||
|
@ -314,8 +315,10 @@ class VirtualSpaceNode : public CHeapObj<mtClass> {
|
||||||
void inc_top(size_t word_size) { _top += word_size; }
|
void inc_top(size_t word_size) { _top += word_size; }
|
||||||
|
|
||||||
uintx container_count() { return _container_count; }
|
uintx container_count() { return _container_count; }
|
||||||
|
void inc_container_count();
|
||||||
void dec_container_count();
|
void dec_container_count();
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
|
uint container_count_slow();
|
||||||
void verify_container_count();
|
void verify_container_count();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -421,8 +424,6 @@ class VirtualSpaceList : public CHeapObj<mtClass> {
|
||||||
VirtualSpaceNode* _virtual_space_list;
|
VirtualSpaceNode* _virtual_space_list;
|
||||||
// virtual space currently being used for allocations
|
// virtual space currently being used for allocations
|
||||||
VirtualSpaceNode* _current_virtual_space;
|
VirtualSpaceNode* _current_virtual_space;
|
||||||
// Free chunk list for all other metadata
|
|
||||||
ChunkManager _chunk_manager;
|
|
||||||
|
|
||||||
// Can this virtual list allocate >1 spaces? Also, used to determine
|
// Can this virtual list allocate >1 spaces? Also, used to determine
|
||||||
// whether to allocate unlimited small chunks in this virtual space
|
// whether to allocate unlimited small chunks in this virtual space
|
||||||
|
@ -475,7 +476,6 @@ class VirtualSpaceList : public CHeapObj<mtClass> {
|
||||||
return _current_virtual_space;
|
return _current_virtual_space;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChunkManager* chunk_manager() { return &_chunk_manager; }
|
|
||||||
bool is_class() const { return _is_class; }
|
bool is_class() const { return _is_class; }
|
||||||
|
|
||||||
// Allocate the first virtualspace.
|
// Allocate the first virtualspace.
|
||||||
|
@ -494,14 +494,7 @@ class VirtualSpaceList : public CHeapObj<mtClass> {
|
||||||
void dec_virtual_space_count();
|
void dec_virtual_space_count();
|
||||||
|
|
||||||
// Unlink empty VirtualSpaceNodes and free it.
|
// Unlink empty VirtualSpaceNodes and free it.
|
||||||
void purge();
|
void purge(ChunkManager* chunk_manager);
|
||||||
|
|
||||||
// Used and capacity in the entire list of virtual spaces.
|
|
||||||
// These are global values shared by all Metaspaces
|
|
||||||
size_t capacity_words_sum();
|
|
||||||
size_t capacity_bytes_sum() { return capacity_words_sum() * BytesPerWord; }
|
|
||||||
size_t used_words_sum();
|
|
||||||
size_t used_bytes_sum() { return used_words_sum() * BytesPerWord; }
|
|
||||||
|
|
||||||
bool contains(const void *ptr);
|
bool contains(const void *ptr);
|
||||||
|
|
||||||
|
@ -582,18 +575,12 @@ class SpaceManager : public CHeapObj<mtClass> {
|
||||||
// Type of metadata allocated.
|
// Type of metadata allocated.
|
||||||
Metaspace::MetadataType _mdtype;
|
Metaspace::MetadataType _mdtype;
|
||||||
|
|
||||||
// Chunk related size
|
|
||||||
size_t _medium_chunk_bunch;
|
|
||||||
|
|
||||||
// List of chunks in use by this SpaceManager. Allocations
|
// List of chunks in use by this SpaceManager. Allocations
|
||||||
// are done from the current chunk. The list is used for deallocating
|
// are done from the current chunk. The list is used for deallocating
|
||||||
// chunks when the SpaceManager is freed.
|
// chunks when the SpaceManager is freed.
|
||||||
Metachunk* _chunks_in_use[NumberOfInUseLists];
|
Metachunk* _chunks_in_use[NumberOfInUseLists];
|
||||||
Metachunk* _current_chunk;
|
Metachunk* _current_chunk;
|
||||||
|
|
||||||
// Virtual space where allocation comes from.
|
|
||||||
VirtualSpaceList* _vs_list;
|
|
||||||
|
|
||||||
// Number of small chunks to allocate to a manager
|
// Number of small chunks to allocate to a manager
|
||||||
// If class space manager, small chunks are unlimited
|
// If class space manager, small chunks are unlimited
|
||||||
static uint const _small_chunk_limit;
|
static uint const _small_chunk_limit;
|
||||||
|
@ -626,7 +613,9 @@ class SpaceManager : public CHeapObj<mtClass> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Metaspace::MetadataType mdtype() { return _mdtype; }
|
Metaspace::MetadataType mdtype() { return _mdtype; }
|
||||||
VirtualSpaceList* vs_list() const { return _vs_list; }
|
|
||||||
|
VirtualSpaceList* vs_list() const { return Metaspace::get_space_list(_mdtype); }
|
||||||
|
ChunkManager* chunk_manager() const { return Metaspace::get_chunk_manager(_mdtype); }
|
||||||
|
|
||||||
Metachunk* current_chunk() const { return _current_chunk; }
|
Metachunk* current_chunk() const { return _current_chunk; }
|
||||||
void set_current_chunk(Metachunk* v) {
|
void set_current_chunk(Metachunk* v) {
|
||||||
|
@ -648,18 +637,19 @@ class SpaceManager : public CHeapObj<mtClass> {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SpaceManager(Metaspace::MetadataType mdtype,
|
SpaceManager(Metaspace::MetadataType mdtype,
|
||||||
Mutex* lock,
|
Mutex* lock);
|
||||||
VirtualSpaceList* vs_list);
|
|
||||||
~SpaceManager();
|
~SpaceManager();
|
||||||
|
|
||||||
enum ChunkMultiples {
|
enum ChunkMultiples {
|
||||||
MediumChunkMultiple = 4
|
MediumChunkMultiple = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool is_class() { return _mdtype == Metaspace::ClassType; }
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
size_t specialized_chunk_size() { return SpecializedChunk; }
|
size_t specialized_chunk_size() { return SpecializedChunk; }
|
||||||
size_t small_chunk_size() { return (size_t) vs_list()->is_class() ? ClassSmallChunk : SmallChunk; }
|
size_t small_chunk_size() { return (size_t) is_class() ? ClassSmallChunk : SmallChunk; }
|
||||||
size_t medium_chunk_size() { return (size_t) vs_list()->is_class() ? ClassMediumChunk : MediumChunk; }
|
size_t medium_chunk_size() { return (size_t) is_class() ? ClassMediumChunk : MediumChunk; }
|
||||||
size_t medium_chunk_bunch() { return medium_chunk_size() * MediumChunkMultiple; }
|
size_t medium_chunk_bunch() { return medium_chunk_size() * MediumChunkMultiple; }
|
||||||
|
|
||||||
size_t allocated_blocks_words() const { return _allocated_blocks_words; }
|
size_t allocated_blocks_words() const { return _allocated_blocks_words; }
|
||||||
|
@ -1020,7 +1010,7 @@ void ChunkManager::remove_chunk(Metachunk* chunk) {
|
||||||
// Walk the list of VirtualSpaceNodes and delete
|
// Walk the list of VirtualSpaceNodes and delete
|
||||||
// nodes with a 0 container_count. Remove Metachunks in
|
// nodes with a 0 container_count. Remove Metachunks in
|
||||||
// the node from their respective freelists.
|
// the node from their respective freelists.
|
||||||
void VirtualSpaceList::purge() {
|
void VirtualSpaceList::purge(ChunkManager* chunk_manager) {
|
||||||
assert_lock_strong(SpaceManager::expand_lock());
|
assert_lock_strong(SpaceManager::expand_lock());
|
||||||
// Don't use a VirtualSpaceListIterator because this
|
// Don't use a VirtualSpaceListIterator because this
|
||||||
// list is being changed and a straightforward use of an iterator is not safe.
|
// list is being changed and a straightforward use of an iterator is not safe.
|
||||||
|
@ -1042,7 +1032,7 @@ void VirtualSpaceList::purge() {
|
||||||
prev_vsl->set_next(vsl->next());
|
prev_vsl->set_next(vsl->next());
|
||||||
}
|
}
|
||||||
|
|
||||||
vsl->purge(chunk_manager());
|
vsl->purge(chunk_manager);
|
||||||
dec_reserved_words(vsl->reserved_words());
|
dec_reserved_words(vsl->reserved_words());
|
||||||
dec_committed_words(vsl->committed_words());
|
dec_committed_words(vsl->committed_words());
|
||||||
dec_virtual_space_count();
|
dec_virtual_space_count();
|
||||||
|
@ -1064,36 +1054,6 @@ void VirtualSpaceList::purge() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t VirtualSpaceList::used_words_sum() {
|
|
||||||
size_t allocated_by_vs = 0;
|
|
||||||
VirtualSpaceListIterator iter(virtual_space_list());
|
|
||||||
while (iter.repeat()) {
|
|
||||||
VirtualSpaceNode* vsl = iter.get_next();
|
|
||||||
// Sum used region [bottom, top) in each virtualspace
|
|
||||||
allocated_by_vs += vsl->used_words_in_vs();
|
|
||||||
}
|
|
||||||
assert(allocated_by_vs >= chunk_manager()->free_chunks_total_words(),
|
|
||||||
err_msg("Total in free chunks " SIZE_FORMAT
|
|
||||||
" greater than total from virtual_spaces " SIZE_FORMAT,
|
|
||||||
allocated_by_vs, chunk_manager()->free_chunks_total_words()));
|
|
||||||
size_t used =
|
|
||||||
allocated_by_vs - chunk_manager()->free_chunks_total_words();
|
|
||||||
return used;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Space available in all MetadataVirtualspaces allocated
|
|
||||||
// for metadata. This is the upper limit on the capacity
|
|
||||||
// of chunks allocated out of all the MetadataVirtualspaces.
|
|
||||||
size_t VirtualSpaceList::capacity_words_sum() {
|
|
||||||
size_t capacity = 0;
|
|
||||||
VirtualSpaceListIterator iter(virtual_space_list());
|
|
||||||
while (iter.repeat()) {
|
|
||||||
VirtualSpaceNode* vsl = iter.get_next();
|
|
||||||
capacity += vsl->capacity_words_in_vs();
|
|
||||||
}
|
|
||||||
return capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
VirtualSpaceList::VirtualSpaceList(size_t word_size ) :
|
VirtualSpaceList::VirtualSpaceList(size_t word_size ) :
|
||||||
_is_class(false),
|
_is_class(false),
|
||||||
_virtual_space_list(NULL),
|
_virtual_space_list(NULL),
|
||||||
|
@ -1104,10 +1064,6 @@ VirtualSpaceList::VirtualSpaceList(size_t word_size ) :
|
||||||
MutexLockerEx cl(SpaceManager::expand_lock(),
|
MutexLockerEx cl(SpaceManager::expand_lock(),
|
||||||
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");
|
||||||
}
|
}
|
||||||
|
@ -1123,9 +1079,6 @@ 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);
|
link_vs(class_entry);
|
||||||
}
|
}
|
||||||
|
@ -1195,15 +1148,8 @@ Metachunk* VirtualSpaceList::get_new_chunk(size_t word_size,
|
||||||
size_t grow_chunks_by_words,
|
size_t grow_chunks_by_words,
|
||||||
size_t medium_chunk_bunch) {
|
size_t medium_chunk_bunch) {
|
||||||
|
|
||||||
// Get a chunk from the chunk freelist
|
|
||||||
Metachunk* next = chunk_manager()->chunk_freelist_allocate(grow_chunks_by_words);
|
|
||||||
|
|
||||||
if (next != NULL) {
|
|
||||||
next->container()->inc_container_count();
|
|
||||||
} else {
|
|
||||||
// Allocate a chunk out of the current virtual space.
|
// Allocate a chunk out of the current virtual space.
|
||||||
next = current_virtual_space()->get_chunk_vs(grow_chunks_by_words);
|
Metachunk* next = current_virtual_space()->get_chunk_vs(grow_chunks_by_words);
|
||||||
}
|
|
||||||
|
|
||||||
if (next == NULL) {
|
if (next == NULL) {
|
||||||
// Not enough room in current virtual space. Try to commit
|
// Not enough room in current virtual space. Try to commit
|
||||||
|
@ -1537,15 +1483,15 @@ void Metadebug::deallocate_chunk_a_lot(SpaceManager* sm,
|
||||||
if (dummy_chunk == NULL) {
|
if (dummy_chunk == NULL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
vsl->chunk_manager()->chunk_freelist_deallocate(dummy_chunk);
|
sm->chunk_manager()->chunk_freelist_deallocate(dummy_chunk);
|
||||||
|
|
||||||
if (TraceMetadataChunkAllocation && Verbose) {
|
if (TraceMetadataChunkAllocation && Verbose) {
|
||||||
gclog_or_tty->print("Metadebug::deallocate_chunk_a_lot: %d) ",
|
gclog_or_tty->print("Metadebug::deallocate_chunk_a_lot: %d) ",
|
||||||
sm->sum_count_in_chunks_in_use());
|
sm->sum_count_in_chunks_in_use());
|
||||||
dummy_chunk->print_on(gclog_or_tty);
|
dummy_chunk->print_on(gclog_or_tty);
|
||||||
gclog_or_tty->print_cr(" Free chunks total %d count %d",
|
gclog_or_tty->print_cr(" Free chunks total %d count %d",
|
||||||
vsl->chunk_manager()->free_chunks_total_words(),
|
sm->chunk_manager()->free_chunks_total_words(),
|
||||||
vsl->chunk_manager()->free_chunks_count());
|
sm->chunk_manager()->free_chunks_count());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1797,6 +1743,8 @@ Metachunk* ChunkManager::free_chunks_get(size_t word_size) {
|
||||||
// work.
|
// work.
|
||||||
chunk->set_is_free(false);
|
chunk->set_is_free(false);
|
||||||
#endif
|
#endif
|
||||||
|
chunk->container()->inc_container_count();
|
||||||
|
|
||||||
slow_locked_verify();
|
slow_locked_verify();
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
|
@ -1831,9 +1779,9 @@ Metachunk* ChunkManager::chunk_freelist_allocate(size_t word_size) {
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChunkManager::print_on(outputStream* out) {
|
void ChunkManager::print_on(outputStream* out) const {
|
||||||
if (PrintFLSStatistics != 0) {
|
if (PrintFLSStatistics != 0) {
|
||||||
humongous_dictionary()->report_statistics();
|
const_cast<ChunkManager *>(this)->humongous_dictionary()->report_statistics();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1980,8 +1928,8 @@ void SpaceManager::locked_print_chunks_in_use_on(outputStream* st) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vs_list()->chunk_manager()->locked_print_free_chunks(st);
|
chunk_manager()->locked_print_free_chunks(st);
|
||||||
vs_list()->chunk_manager()->locked_print_sum_free_chunks(st);
|
chunk_manager()->locked_print_sum_free_chunks(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t SpaceManager::calc_chunk_size(size_t word_size) {
|
size_t SpaceManager::calc_chunk_size(size_t word_size) {
|
||||||
|
@ -2085,9 +2033,7 @@ void SpaceManager::print_on(outputStream* st) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
SpaceManager::SpaceManager(Metaspace::MetadataType mdtype,
|
SpaceManager::SpaceManager(Metaspace::MetadataType mdtype,
|
||||||
Mutex* lock,
|
Mutex* lock) :
|
||||||
VirtualSpaceList* vs_list) :
|
|
||||||
_vs_list(vs_list),
|
|
||||||
_mdtype(mdtype),
|
_mdtype(mdtype),
|
||||||
_allocated_blocks_words(0),
|
_allocated_blocks_words(0),
|
||||||
_allocated_chunks_words(0),
|
_allocated_chunks_words(0),
|
||||||
|
@ -2173,9 +2119,7 @@ SpaceManager::~SpaceManager() {
|
||||||
MutexLockerEx fcl(SpaceManager::expand_lock(),
|
MutexLockerEx fcl(SpaceManager::expand_lock(),
|
||||||
Mutex::_no_safepoint_check_flag);
|
Mutex::_no_safepoint_check_flag);
|
||||||
|
|
||||||
ChunkManager* chunk_manager = vs_list()->chunk_manager();
|
chunk_manager()->slow_locked_verify();
|
||||||
|
|
||||||
chunk_manager->slow_locked_verify();
|
|
||||||
|
|
||||||
dec_total_from_size_metrics();
|
dec_total_from_size_metrics();
|
||||||
|
|
||||||
|
@ -2189,7 +2133,7 @@ SpaceManager::~SpaceManager() {
|
||||||
|
|
||||||
// Have to update before the chunks_in_use lists are emptied
|
// Have to update before the chunks_in_use lists are emptied
|
||||||
// below.
|
// below.
|
||||||
chunk_manager->inc_free_chunks_total(allocated_chunks_words(),
|
chunk_manager()->inc_free_chunks_total(allocated_chunks_words(),
|
||||||
sum_count_in_chunks_in_use());
|
sum_count_in_chunks_in_use());
|
||||||
|
|
||||||
// Add all the chunks in use by this space manager
|
// Add all the chunks in use by this space manager
|
||||||
|
@ -2205,11 +2149,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->return_chunks(i, 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)->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");
|
||||||
|
@ -2246,16 +2190,16 @@ SpaceManager::~SpaceManager() {
|
||||||
humongous_chunks->word_size(), HumongousChunkGranularity));
|
humongous_chunks->word_size(), HumongousChunkGranularity));
|
||||||
Metachunk* next_humongous_chunks = humongous_chunks->next();
|
Metachunk* next_humongous_chunks = humongous_chunks->next();
|
||||||
humongous_chunks->container()->dec_container_count();
|
humongous_chunks->container()->dec_container_count();
|
||||||
chunk_manager->humongous_dictionary()->return_chunk(humongous_chunks);
|
chunk_manager()->humongous_dictionary()->return_chunk(humongous_chunks);
|
||||||
humongous_chunks = next_humongous_chunks;
|
humongous_chunks = next_humongous_chunks;
|
||||||
}
|
}
|
||||||
if (TraceMetadataChunkAllocation && Verbose) {
|
if (TraceMetadataChunkAllocation && Verbose) {
|
||||||
gclog_or_tty->print_cr("");
|
gclog_or_tty->print_cr("");
|
||||||
gclog_or_tty->print_cr("updated dictionary count %d %s",
|
gclog_or_tty->print_cr("updated dictionary count %d %s",
|
||||||
chunk_manager->humongous_dictionary()->total_count(),
|
chunk_manager()->humongous_dictionary()->total_count(),
|
||||||
chunk_size_name(HumongousIndex));
|
chunk_size_name(HumongousIndex));
|
||||||
}
|
}
|
||||||
chunk_manager->slow_locked_verify();
|
chunk_manager()->slow_locked_verify();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* SpaceManager::chunk_size_name(ChunkIndex index) const {
|
const char* SpaceManager::chunk_size_name(ChunkIndex index) const {
|
||||||
|
@ -2344,9 +2288,7 @@ void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) {
|
||||||
gclog_or_tty->print("SpaceManager::add_chunk: %d) ",
|
gclog_or_tty->print("SpaceManager::add_chunk: %d) ",
|
||||||
sum_count_in_chunks_in_use());
|
sum_count_in_chunks_in_use());
|
||||||
new_chunk->print_on(gclog_or_tty);
|
new_chunk->print_on(gclog_or_tty);
|
||||||
if (vs_list() != NULL) {
|
chunk_manager()->locked_print_free_chunks(gclog_or_tty);
|
||||||
vs_list()->chunk_manager()->locked_print_free_chunks(gclog_or_tty);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2362,10 +2304,14 @@ void SpaceManager::retire_current_chunk() {
|
||||||
|
|
||||||
Metachunk* SpaceManager::get_new_chunk(size_t word_size,
|
Metachunk* SpaceManager::get_new_chunk(size_t word_size,
|
||||||
size_t grow_chunks_by_words) {
|
size_t grow_chunks_by_words) {
|
||||||
|
// Get a chunk from the chunk freelist
|
||||||
|
Metachunk* next = chunk_manager()->chunk_freelist_allocate(grow_chunks_by_words);
|
||||||
|
|
||||||
Metachunk* next = vs_list()->get_new_chunk(word_size,
|
if (next == NULL) {
|
||||||
|
next = vs_list()->get_new_chunk(word_size,
|
||||||
grow_chunks_by_words,
|
grow_chunks_by_words,
|
||||||
medium_chunk_bunch());
|
medium_chunk_bunch());
|
||||||
|
}
|
||||||
|
|
||||||
if (TraceMetadataHumongousAllocation && next != NULL &&
|
if (TraceMetadataHumongousAllocation && next != NULL &&
|
||||||
SpaceManager::is_humongous(next->word_size())) {
|
SpaceManager::is_humongous(next->word_size())) {
|
||||||
|
@ -2645,13 +2591,12 @@ size_t MetaspaceAux::committed_bytes(Metaspace::MetadataType mdtype) {
|
||||||
size_t MetaspaceAux::min_chunk_size_words() { return Metaspace::first_chunk_word_size(); }
|
size_t MetaspaceAux::min_chunk_size_words() { return Metaspace::first_chunk_word_size(); }
|
||||||
|
|
||||||
size_t MetaspaceAux::free_chunks_total_words(Metaspace::MetadataType mdtype) {
|
size_t MetaspaceAux::free_chunks_total_words(Metaspace::MetadataType mdtype) {
|
||||||
VirtualSpaceList* list = Metaspace::get_space_list(mdtype);
|
ChunkManager* chunk_manager = Metaspace::get_chunk_manager(mdtype);
|
||||||
if (list == NULL) {
|
if (chunk_manager == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ChunkManager* chunk = list->chunk_manager();
|
chunk_manager->slow_verify();
|
||||||
chunk->slow_verify();
|
return chunk_manager->free_chunks_total_words();
|
||||||
return chunk->free_chunks_total_words();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t MetaspaceAux::free_chunks_total_bytes(Metaspace::MetadataType mdtype) {
|
size_t MetaspaceAux::free_chunks_total_bytes(Metaspace::MetadataType mdtype) {
|
||||||
|
@ -2802,9 +2747,9 @@ void MetaspaceAux::dump(outputStream* out) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetaspaceAux::verify_free_chunks() {
|
void MetaspaceAux::verify_free_chunks() {
|
||||||
Metaspace::space_list()->chunk_manager()->verify();
|
Metaspace::chunk_manager_metadata()->verify();
|
||||||
if (Metaspace::using_class_space()) {
|
if (Metaspace::using_class_space()) {
|
||||||
Metaspace::class_space_list()->chunk_manager()->verify();
|
Metaspace::chunk_manager_class()->verify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2875,6 +2820,9 @@ Metaspace::~Metaspace() {
|
||||||
VirtualSpaceList* Metaspace::_space_list = NULL;
|
VirtualSpaceList* Metaspace::_space_list = NULL;
|
||||||
VirtualSpaceList* Metaspace::_class_space_list = NULL;
|
VirtualSpaceList* Metaspace::_class_space_list = NULL;
|
||||||
|
|
||||||
|
ChunkManager* Metaspace::_chunk_manager_metadata = NULL;
|
||||||
|
ChunkManager* Metaspace::_chunk_manager_class = NULL;
|
||||||
|
|
||||||
#define VIRTUALSPACEMULTIPLIER 2
|
#define VIRTUALSPACEMULTIPLIER 2
|
||||||
|
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
|
@ -2982,6 +2930,7 @@ void Metaspace::initialize_class_space(ReservedSpace rs) {
|
||||||
err_msg(SIZE_FORMAT " != " UINTX_FORMAT, rs.size(), CompressedClassSpaceSize));
|
err_msg(SIZE_FORMAT " != " UINTX_FORMAT, rs.size(), CompressedClassSpaceSize));
|
||||||
assert(using_class_space(), "Must be using class space");
|
assert(using_class_space(), "Must be using class space");
|
||||||
_class_space_list = new VirtualSpaceList(rs);
|
_class_space_list = new VirtualSpaceList(rs);
|
||||||
|
_chunk_manager_class = new ChunkManager(SpecializedChunk, ClassSmallChunk, ClassMediumChunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -3007,6 +2956,7 @@ void Metaspace::global_initialize() {
|
||||||
// remainder is the misc code and data chunks.
|
// remainder is the misc code and data chunks.
|
||||||
cds_total = FileMapInfo::shared_spaces_size();
|
cds_total = FileMapInfo::shared_spaces_size();
|
||||||
_space_list = new VirtualSpaceList(cds_total/wordSize);
|
_space_list = new VirtualSpaceList(cds_total/wordSize);
|
||||||
|
_chunk_manager_metadata = new ChunkManager(SpecializedChunk, SmallChunk, MediumChunk);
|
||||||
|
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
// Set the compressed klass pointer base so that decoding of these pointers works
|
// Set the compressed klass pointer base so that decoding of these pointers works
|
||||||
|
@ -3074,15 +3024,30 @@ void Metaspace::global_initialize() {
|
||||||
size_t word_size = VIRTUALSPACEMULTIPLIER * first_chunk_word_size();
|
size_t word_size = VIRTUALSPACEMULTIPLIER * first_chunk_word_size();
|
||||||
// Initialize the list of virtual spaces.
|
// Initialize the list of virtual spaces.
|
||||||
_space_list = new VirtualSpaceList(word_size);
|
_space_list = new VirtualSpaceList(word_size);
|
||||||
|
_chunk_manager_metadata = new ChunkManager(SpecializedChunk, SmallChunk, MediumChunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Metachunk* Metaspace::get_initialization_chunk(MetadataType mdtype,
|
||||||
|
size_t chunk_word_size,
|
||||||
|
size_t chunk_bunch) {
|
||||||
|
// Get a chunk from the chunk freelist
|
||||||
|
Metachunk* chunk = get_chunk_manager(mdtype)->chunk_freelist_allocate(chunk_word_size);
|
||||||
|
if (chunk != NULL) {
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
return get_space_list(mdtype)->get_initialization_chunk(chunk_word_size, chunk_bunch);
|
||||||
|
}
|
||||||
|
|
||||||
void Metaspace::initialize(Mutex* lock, MetaspaceType type) {
|
void Metaspace::initialize(Mutex* lock, MetaspaceType type) {
|
||||||
|
|
||||||
assert(space_list() != NULL,
|
assert(space_list() != NULL,
|
||||||
"Metadata VirtualSpaceList has not been initialized");
|
"Metadata VirtualSpaceList has not been initialized");
|
||||||
|
assert(chunk_manager_metadata() != NULL,
|
||||||
|
"Metadata ChunkManager has not been initialized");
|
||||||
|
|
||||||
_vsm = new SpaceManager(NonClassType, lock, space_list());
|
_vsm = new SpaceManager(NonClassType, lock);
|
||||||
if (_vsm == NULL) {
|
if (_vsm == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3093,9 +3058,11 @@ void Metaspace::initialize(Mutex* lock, MetaspaceType type) {
|
||||||
if (using_class_space()) {
|
if (using_class_space()) {
|
||||||
assert(class_space_list() != NULL,
|
assert(class_space_list() != NULL,
|
||||||
"Class VirtualSpaceList has not been initialized");
|
"Class VirtualSpaceList has not been initialized");
|
||||||
|
assert(chunk_manager_class() != NULL,
|
||||||
|
"Class ChunkManager has not been initialized");
|
||||||
|
|
||||||
// Allocate SpaceManager for classes.
|
// Allocate SpaceManager for classes.
|
||||||
_class_vsm = new SpaceManager(ClassType, lock, class_space_list());
|
_class_vsm = new SpaceManager(ClassType, lock);
|
||||||
if (_class_vsm == NULL) {
|
if (_class_vsm == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3104,8 +3071,8 @@ void Metaspace::initialize(Mutex* lock, MetaspaceType type) {
|
||||||
MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag);
|
MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag);
|
||||||
|
|
||||||
// Allocate chunk for metadata objects
|
// Allocate chunk for metadata objects
|
||||||
Metachunk* new_chunk =
|
Metachunk* new_chunk = get_initialization_chunk(NonClassType,
|
||||||
space_list()->get_initialization_chunk(word_size,
|
word_size,
|
||||||
vsm()->medium_chunk_bunch());
|
vsm()->medium_chunk_bunch());
|
||||||
assert(!DumpSharedSpaces || new_chunk != NULL, "should have enough space for both chunks");
|
assert(!DumpSharedSpaces || new_chunk != NULL, "should have enough space for both chunks");
|
||||||
if (new_chunk != NULL) {
|
if (new_chunk != NULL) {
|
||||||
|
@ -3115,8 +3082,8 @@ void Metaspace::initialize(Mutex* lock, MetaspaceType type) {
|
||||||
|
|
||||||
// Allocate chunk for class metadata objects
|
// Allocate chunk for class metadata objects
|
||||||
if (using_class_space()) {
|
if (using_class_space()) {
|
||||||
Metachunk* class_chunk =
|
Metachunk* class_chunk = get_initialization_chunk(ClassType,
|
||||||
class_space_list()->get_initialization_chunk(class_word_size,
|
class_word_size,
|
||||||
class_vsm()->medium_chunk_bunch());
|
class_vsm()->medium_chunk_bunch());
|
||||||
if (class_chunk != NULL) {
|
if (class_chunk != NULL) {
|
||||||
class_vsm()->add_chunk(class_chunk, true);
|
class_vsm()->add_chunk(class_chunk, true);
|
||||||
|
@ -3334,12 +3301,16 @@ void Metaspace::iterate(Metaspace::AllocRecordClosure *closure) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Metaspace::purge(MetadataType mdtype) {
|
||||||
|
get_space_list(mdtype)->purge(get_chunk_manager(mdtype));
|
||||||
|
}
|
||||||
|
|
||||||
void Metaspace::purge() {
|
void Metaspace::purge() {
|
||||||
MutexLockerEx cl(SpaceManager::expand_lock(),
|
MutexLockerEx cl(SpaceManager::expand_lock(),
|
||||||
Mutex::_no_safepoint_check_flag);
|
Mutex::_no_safepoint_check_flag);
|
||||||
space_list()->purge();
|
purge(NonClassType);
|
||||||
if (using_class_space()) {
|
if (using_class_space()) {
|
||||||
class_space_list()->purge();
|
purge(ClassType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,12 +56,15 @@
|
||||||
// +-------------------+
|
// +-------------------+
|
||||||
//
|
//
|
||||||
|
|
||||||
|
class ChunkManager;
|
||||||
class ClassLoaderData;
|
class ClassLoaderData;
|
||||||
class Metablock;
|
class Metablock;
|
||||||
|
class Metachunk;
|
||||||
class MetaWord;
|
class MetaWord;
|
||||||
class Mutex;
|
class Mutex;
|
||||||
class outputStream;
|
class outputStream;
|
||||||
class SpaceManager;
|
class SpaceManager;
|
||||||
|
class VirtualSpaceList;
|
||||||
|
|
||||||
// Metaspaces each have a SpaceManager and allocations
|
// Metaspaces each have a SpaceManager and allocations
|
||||||
// are done by the SpaceManager. Allocations are done
|
// are done by the SpaceManager. Allocations are done
|
||||||
|
@ -76,8 +79,6 @@ class SpaceManager;
|
||||||
// allocate() method returns a block for use as a
|
// allocate() method returns a block for use as a
|
||||||
// quantum of metadata.
|
// quantum of metadata.
|
||||||
|
|
||||||
class VirtualSpaceList;
|
|
||||||
|
|
||||||
class Metaspace : public CHeapObj<mtClass> {
|
class Metaspace : public CHeapObj<mtClass> {
|
||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
friend class SpaceManager;
|
friend class SpaceManager;
|
||||||
|
@ -102,6 +103,10 @@ class Metaspace : public CHeapObj<mtClass> {
|
||||||
private:
|
private:
|
||||||
void initialize(Mutex* lock, MetaspaceType type);
|
void initialize(Mutex* lock, MetaspaceType type);
|
||||||
|
|
||||||
|
Metachunk* get_initialization_chunk(MetadataType mdtype,
|
||||||
|
size_t chunk_word_size,
|
||||||
|
size_t chunk_bunch);
|
||||||
|
|
||||||
// Align up the word size to the allocation word size
|
// Align up the word size to the allocation word size
|
||||||
static size_t align_word_size_up(size_t);
|
static size_t align_word_size_up(size_t);
|
||||||
|
|
||||||
|
@ -134,6 +139,10 @@ class Metaspace : public CHeapObj<mtClass> {
|
||||||
static VirtualSpaceList* _space_list;
|
static VirtualSpaceList* _space_list;
|
||||||
static VirtualSpaceList* _class_space_list;
|
static VirtualSpaceList* _class_space_list;
|
||||||
|
|
||||||
|
static ChunkManager* _chunk_manager_metadata;
|
||||||
|
static ChunkManager* _chunk_manager_class;
|
||||||
|
|
||||||
|
public:
|
||||||
static VirtualSpaceList* space_list() { return _space_list; }
|
static VirtualSpaceList* space_list() { return _space_list; }
|
||||||
static VirtualSpaceList* class_space_list() { return _class_space_list; }
|
static VirtualSpaceList* class_space_list() { return _class_space_list; }
|
||||||
static VirtualSpaceList* get_space_list(MetadataType mdtype) {
|
static VirtualSpaceList* get_space_list(MetadataType mdtype) {
|
||||||
|
@ -141,6 +150,14 @@ class Metaspace : public CHeapObj<mtClass> {
|
||||||
return mdtype == ClassType ? class_space_list() : space_list();
|
return mdtype == ClassType ? class_space_list() : space_list();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ChunkManager* chunk_manager_metadata() { return _chunk_manager_metadata; }
|
||||||
|
static ChunkManager* chunk_manager_class() { return _chunk_manager_class; }
|
||||||
|
static ChunkManager* get_chunk_manager(MetadataType mdtype) {
|
||||||
|
assert(mdtype != MetadataTypeCount, "MetadaTypeCount can't be used as mdtype");
|
||||||
|
return mdtype == ClassType ? chunk_manager_class() : chunk_manager_metadata();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
// This is used by DumpSharedSpaces only, where only _vsm is used. So we will
|
// This is used by DumpSharedSpaces only, where only _vsm is used. So we will
|
||||||
// maintain a single list for now.
|
// maintain a single list for now.
|
||||||
void record_allocation(void* ptr, MetaspaceObj::Type type, size_t word_size);
|
void record_allocation(void* ptr, MetaspaceObj::Type type, size_t word_size);
|
||||||
|
@ -199,6 +216,7 @@ class Metaspace : public CHeapObj<mtClass> {
|
||||||
void dump(outputStream* const out) const;
|
void dump(outputStream* const out) const;
|
||||||
|
|
||||||
// Free empty virtualspaces
|
// Free empty virtualspaces
|
||||||
|
static void purge(MetadataType mdtype);
|
||||||
static void purge();
|
static void purge();
|
||||||
|
|
||||||
void print_on(outputStream* st) const;
|
void print_on(outputStream* st) const;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue