提交 6c74417c 编写于 作者: S stefank

8025096: Move the ChunkManager instances out of the VirtualSpaceLists

Reviewed-by: coleenp, mgerdin, jmasa
上级 17f44793
...@@ -23,6 +23,7 @@ ...@@ -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; ...@@ -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 { ...@@ -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 { ...@@ -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> { ...@@ -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> { ...@@ -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> { ...@@ -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> { ...@@ -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> { ...@@ -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> { ...@@ -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> { ...@@ -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> { ...@@ -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; }
...@@ -762,7 +752,7 @@ void VirtualSpaceNode::inc_container_count() { ...@@ -762,7 +752,7 @@ void VirtualSpaceNode::inc_container_count() {
_container_count++; _container_count++;
assert(_container_count == container_count_slow(), assert(_container_count == container_count_slow(),
err_msg("Inconsistency in countainer_count _container_count " SIZE_FORMAT err_msg("Inconsistency in countainer_count _container_count " SIZE_FORMAT
"container_count_slow() " SIZE_FORMAT, " container_count_slow() " SIZE_FORMAT,
_container_count, container_count_slow())); _container_count, container_count_slow()));
} }
...@@ -775,7 +765,7 @@ void VirtualSpaceNode::dec_container_count() { ...@@ -775,7 +765,7 @@ void VirtualSpaceNode::dec_container_count() {
void VirtualSpaceNode::verify_container_count() { void VirtualSpaceNode::verify_container_count() {
assert(_container_count == container_count_slow(), assert(_container_count == container_count_slow(),
err_msg("Inconsistency in countainer_count _container_count " SIZE_FORMAT err_msg("Inconsistency in countainer_count _container_count " SIZE_FORMAT
"container_count_slow() " SIZE_FORMAT, _container_count, container_count_slow())); " container_count_slow() " SIZE_FORMAT, _container_count, container_count_slow()));
} }
#endif #endif
...@@ -1020,7 +1010,7 @@ void ChunkManager::remove_chunk(Metachunk* chunk) { ...@@ -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() { ...@@ -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() { ...@@ -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 ) : ...@@ -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) : ...@@ -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, ...@@ -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, ...@@ -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) { ...@@ -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) { ...@@ -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 { ...@@ -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 { ...@@ -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() { ...@@ -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() { ...@@ -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() { ...@@ -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() { ...@@ -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) { ...@@ -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() { ...@@ -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) { ...@@ -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) { ...@@ -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() { ...@@ -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) { ...@@ -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() { ...@@ -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() { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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 @@ ...@@ -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; ...@@ -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> { ...@@ -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> { ...@@ -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> { ...@@ -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> { ...@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册