src/share/vm/memory/metaspace.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
hsx-gc Cdiff src/share/vm/memory/metaspace.cpp
src/share/vm/memory/metaspace.cpp
Print this page
*** 21,30 ****
--- 21,31 ----
* questions.
*
*/
#include "precompiled.hpp"
#include "gc_interface/collectedHeap.hpp"
+ #include "memory/allocation.hpp"
#include "memory/binaryTreeDictionary.hpp"
#include "memory/freeList.hpp"
#include "memory/collectorPolicy.hpp"
#include "memory/filemap.hpp"
#include "memory/freeList.hpp"
*** 109,119 ****
// Manages the global free lists of chunks.
// Has three lists of free chunks, and a total size and
// count that includes all three
! class ChunkManager VALUE_OBJ_CLASS_SPEC {
// Free list of chunks of different sizes.
// SpecializedChunk
// SmallChunk
// MediumChunk
--- 110,120 ----
// Manages the global free lists of chunks.
// Has three lists of free chunks, and a total size and
// count that includes all three
! class ChunkManager : public CHeapObj<mtInternal> {
// Free list of chunks of different sizes.
// SpecializedChunk
// SmallChunk
// MediumChunk
*** 156,166 ****
}
void verify_free_chunks_count();
public:
! ChunkManager() : _free_chunks_total(0), _free_chunks_count(0) {}
// add or delete (return) a chunk to the global freelist.
Metachunk* chunk_freelist_allocate(size_t word_size);
void chunk_freelist_deallocate(Metachunk* chunk);
--- 157,172 ----
}
void verify_free_chunks_count();
public:
! ChunkManager(size_t specialized, size_t small, size_t medium)
! : _free_chunks_total(0), _free_chunks_count(0) {
! free_chunks(SpecializedIndex)->set_size(specialized);
! free_chunks(SmallIndex)->set_size(small);
! free_chunks(MediumIndex)->set_size(medium);
! }
// add or delete (return) a chunk to the global freelist.
Metachunk* chunk_freelist_allocate(size_t word_size);
void chunk_freelist_deallocate(Metachunk* chunk);
*** 274,288 ****
// The first Metachunk will be allocated at the bottom of the
// VirtualSpace
Metachunk* first_chunk() { return (Metachunk*) bottom(); }
- void inc_container_count();
- #ifdef ASSERT
- uint container_count_slow();
- #endif
-
public:
VirtualSpaceNode(size_t byte_size);
VirtualSpaceNode(ReservedSpace rs) : _top(NULL), _next(NULL), _rs(rs), _container_count(0) {}
~VirtualSpaceNode();
--- 280,289 ----
*** 312,323 ****
--- 313,326 ----
MetaWord* top() const { return _top; }
void inc_top(size_t word_size) { _top += word_size; }
uintx container_count() { return _container_count; }
+ void inc_container_count();
void dec_container_count();
#ifdef ASSERT
+ uint container_count_slow();
void verify_container_count();
#endif
// used and capacity in this single entry in the list
size_t used_words_in_vs() const;
*** 419,430 ****
// Global list of virtual spaces
// Head of the list
VirtualSpaceNode* _virtual_space_list;
// virtual space currently being used for allocations
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
// whether to allocate unlimited small chunks in this virtual space
bool _is_class;
bool can_grow() const { return !is_class() || !UseCompressedClassPointers; }
--- 422,431 ----
*** 473,483 ****
VirtualSpaceNode* current_virtual_space() {
return _current_virtual_space;
}
- ChunkManager* chunk_manager() { return &_chunk_manager; }
bool is_class() const { return _is_class; }
// Allocate the first virtualspace.
void initialize(size_t word_size);
--- 474,483 ----
*** 492,509 ****
void dec_committed_words(size_t v);
void inc_virtual_space_count();
void dec_virtual_space_count();
// Unlink empty VirtualSpaceNodes and free it.
! void purge();
!
! // 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);
void print_on(outputStream* st) const;
--- 492,502 ----
void dec_committed_words(size_t v);
void inc_virtual_space_count();
void dec_virtual_space_count();
// Unlink empty VirtualSpaceNodes and free it.
! void purge(ChunkManager* chunk_manager);
bool contains(const void *ptr);
void print_on(outputStream* st) const;
*** 580,601 ****
Mutex* const _lock;
// Type of metadata allocated.
Metaspace::MetadataType _mdtype;
- // Chunk related size
- size_t _medium_chunk_bunch;
-
// List of chunks in use by this SpaceManager. Allocations
// are done from the current chunk. The list is used for deallocating
// chunks when the SpaceManager is freed.
Metachunk* _chunks_in_use[NumberOfInUseLists];
Metachunk* _current_chunk;
- // Virtual space where allocation comes from.
- VirtualSpaceList* _vs_list;
-
// Number of small chunks to allocate to a manager
// If class space manager, small chunks are unlimited
static uint const _small_chunk_limit;
// Sum of all space in allocated chunks
--- 573,588 ----
*** 624,634 ****
BlockFreelist* block_freelists() const {
return (BlockFreelist*) &_block_freelists;
}
Metaspace::MetadataType mdtype() { return _mdtype; }
! VirtualSpaceList* vs_list() const { return _vs_list; }
Metachunk* current_chunk() const { return _current_chunk; }
void set_current_chunk(Metachunk* v) {
_current_chunk = v;
}
--- 611,623 ----
BlockFreelist* block_freelists() const {
return (BlockFreelist*) &_block_freelists;
}
Metaspace::MetadataType mdtype() { return _mdtype; }
!
! 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; }
void set_current_chunk(Metachunk* v) {
_current_chunk = v;
}
*** 646,667 ****
protected:
void initialize();
public:
SpaceManager(Metaspace::MetadataType mdtype,
! Mutex* lock,
! VirtualSpaceList* vs_list);
~SpaceManager();
enum ChunkMultiples {
MediumChunkMultiple = 4
};
// Accessors
size_t specialized_chunk_size() { return SpecializedChunk; }
! size_t small_chunk_size() { return (size_t) vs_list()->is_class() ? ClassSmallChunk : SmallChunk; }
! size_t medium_chunk_size() { return (size_t) vs_list()->is_class() ? ClassMediumChunk : MediumChunk; }
size_t medium_chunk_bunch() { return medium_chunk_size() * MediumChunkMultiple; }
size_t allocated_blocks_words() const { return _allocated_blocks_words; }
size_t allocated_blocks_bytes() const { return _allocated_blocks_words * BytesPerWord; }
size_t allocated_chunks_words() const { return _allocated_chunks_words; }
--- 635,657 ----
protected:
void initialize();
public:
SpaceManager(Metaspace::MetadataType mdtype,
! Mutex* lock);
~SpaceManager();
enum ChunkMultiples {
MediumChunkMultiple = 4
};
+ bool is_class() { return _mdtype == Metaspace::ClassType; }
+
// Accessors
size_t specialized_chunk_size() { return SpecializedChunk; }
! size_t small_chunk_size() { return (size_t) is_class() ? ClassSmallChunk : SmallChunk; }
! size_t medium_chunk_size() { return (size_t) is_class() ? ClassMediumChunk : MediumChunk; }
size_t medium_chunk_bunch() { return medium_chunk_size() * MediumChunkMultiple; }
size_t allocated_blocks_words() const { return _allocated_blocks_words; }
size_t allocated_blocks_bytes() const { return _allocated_blocks_words * BytesPerWord; }
size_t allocated_chunks_words() const { return _allocated_chunks_words; }
*** 760,770 ****
void VirtualSpaceNode::inc_container_count() {
assert_lock_strong(SpaceManager::expand_lock());
_container_count++;
assert(_container_count == container_count_slow(),
err_msg("Inconsistency in countainer_count _container_count " SIZE_FORMAT
! "container_count_slow() " SIZE_FORMAT,
_container_count, container_count_slow()));
}
void VirtualSpaceNode::dec_container_count() {
assert_lock_strong(SpaceManager::expand_lock());
--- 750,760 ----
void VirtualSpaceNode::inc_container_count() {
assert_lock_strong(SpaceManager::expand_lock());
_container_count++;
assert(_container_count == container_count_slow(),
err_msg("Inconsistency in countainer_count _container_count " SIZE_FORMAT
! " container_count_slow() " SIZE_FORMAT,
_container_count, container_count_slow()));
}
void VirtualSpaceNode::dec_container_count() {
assert_lock_strong(SpaceManager::expand_lock());
*** 773,783 ****
#ifdef ASSERT
void VirtualSpaceNode::verify_container_count() {
assert(_container_count == container_count_slow(),
err_msg("Inconsistency in countainer_count _container_count " SIZE_FORMAT
! "container_count_slow() " SIZE_FORMAT, _container_count, container_count_slow()));
}
#endif
// BlockFreelist methods
--- 763,773 ----
#ifdef ASSERT
void VirtualSpaceNode::verify_container_count() {
assert(_container_count == container_count_slow(),
err_msg("Inconsistency in countainer_count _container_count " SIZE_FORMAT
! " container_count_slow() " SIZE_FORMAT, _container_count, container_count_slow()));
}
#endif
// BlockFreelist methods
*** 1018,1028 ****
}
// Walk the list of VirtualSpaceNodes and delete
// nodes with a 0 container_count. Remove Metachunks in
// the node from their respective freelists.
! void VirtualSpaceList::purge() {
assert_lock_strong(SpaceManager::expand_lock());
// Don't use a VirtualSpaceListIterator because this
// list is being changed and a straightforward use of an iterator is not safe.
VirtualSpaceNode* purged_vsl = NULL;
VirtualSpaceNode* prev_vsl = virtual_space_list();
--- 1008,1018 ----
}
// Walk the list of VirtualSpaceNodes and delete
// nodes with a 0 container_count. Remove Metachunks in
// the node from their respective freelists.
! void VirtualSpaceList::purge(ChunkManager* chunk_manager) {
assert_lock_strong(SpaceManager::expand_lock());
// Don't use a VirtualSpaceListIterator because this
// list is being changed and a straightforward use of an iterator is not safe.
VirtualSpaceNode* purged_vsl = NULL;
VirtualSpaceNode* prev_vsl = virtual_space_list();
*** 1040,1050 ****
set_virtual_space_list(vsl->next());
} else {
prev_vsl->set_next(vsl->next());
}
! vsl->purge(chunk_manager());
dec_reserved_words(vsl->reserved_words());
dec_committed_words(vsl->committed_words());
dec_virtual_space_count();
purged_vsl = vsl;
delete vsl;
--- 1030,1040 ----
set_virtual_space_list(vsl->next());
} else {
prev_vsl->set_next(vsl->next());
}
! vsl->purge(chunk_manager);
dec_reserved_words(vsl->reserved_words());
dec_committed_words(vsl->committed_words());
dec_virtual_space_count();
purged_vsl = vsl;
delete vsl;
*** 1062,1115 ****
}
}
#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 ) :
_is_class(false),
_virtual_space_list(NULL),
_current_virtual_space(NULL),
_reserved_words(0),
_committed_words(0),
_virtual_space_count(0) {
MutexLockerEx cl(SpaceManager::expand_lock(),
Mutex::_no_safepoint_check_flag);
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,
" VirtualSpaceList initialization should not fail");
}
VirtualSpaceList::VirtualSpaceList(ReservedSpace rs) :
--- 1052,1071 ----
*** 1121,1133 ****
_virtual_space_count(0) {
MutexLockerEx cl(SpaceManager::expand_lock(),
Mutex::_no_safepoint_check_flag);
VirtualSpaceNode* class_entry = new VirtualSpaceNode(rs);
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");
link_vs(class_entry);
}
size_t VirtualSpaceList::free_bytes() {
--- 1077,1086 ----
*** 1193,1211 ****
Metachunk* VirtualSpaceList::get_new_chunk(size_t word_size,
size_t grow_chunks_by_words,
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.
! next = current_virtual_space()->get_chunk_vs(grow_chunks_by_words);
! }
if (next == NULL) {
// Not enough room in current virtual space. Try to commit
// more space.
size_t expand_vs_by_words = MAX2(medium_chunk_bunch,
--- 1146,1157 ----
Metachunk* VirtualSpaceList::get_new_chunk(size_t word_size,
size_t grow_chunks_by_words,
size_t medium_chunk_bunch) {
// Allocate a chunk out of the current virtual space.
! Metachunk* next = current_virtual_space()->get_chunk_vs(grow_chunks_by_words);
if (next == NULL) {
// Not enough room in current virtual space. Try to commit
// more space.
size_t expand_vs_by_words = MAX2(medium_chunk_bunch,
*** 1535,1553 ****
for (uint i = 0; i < metadata_deallocate_a_lock_chunk; i++) {
Metachunk* dummy_chunk = vsl->current_virtual_space()->take_from_committed(chunk_word_size);
if (dummy_chunk == NULL) {
break;
}
! vsl->chunk_manager()->chunk_freelist_deallocate(dummy_chunk);
if (TraceMetadataChunkAllocation && Verbose) {
gclog_or_tty->print("Metadebug::deallocate_chunk_a_lot: %d) ",
sm->sum_count_in_chunks_in_use());
dummy_chunk->print_on(gclog_or_tty);
gclog_or_tty->print_cr(" Free chunks total %d count %d",
! vsl->chunk_manager()->free_chunks_total_words(),
! vsl->chunk_manager()->free_chunks_count());
}
}
} else {
Metadebug::inc_deallocate_chunk_a_lot_count();
}
--- 1481,1499 ----
for (uint i = 0; i < metadata_deallocate_a_lock_chunk; i++) {
Metachunk* dummy_chunk = vsl->current_virtual_space()->take_from_committed(chunk_word_size);
if (dummy_chunk == NULL) {
break;
}
! sm->chunk_manager()->chunk_freelist_deallocate(dummy_chunk);
if (TraceMetadataChunkAllocation && Verbose) {
gclog_or_tty->print("Metadebug::deallocate_chunk_a_lot: %d) ",
sm->sum_count_in_chunks_in_use());
dummy_chunk->print_on(gclog_or_tty);
gclog_or_tty->print_cr(" Free chunks total %d count %d",
! sm->chunk_manager()->free_chunks_total_words(),
! sm->chunk_manager()->free_chunks_count());
}
}
} else {
Metadebug::inc_deallocate_chunk_a_lot_count();
}
*** 1795,1804 ****
--- 1741,1752 ----
#ifdef ASSERT
// Chunk is no longer on any freelist. Setting to false make container_count_slow()
// work.
chunk->set_is_free(false);
#endif
+ chunk->container()->inc_container_count();
+
slow_locked_verify();
return chunk;
}
Metachunk* ChunkManager::chunk_freelist_allocate(size_t word_size) {
*** 1978,1989 ****
} else {
st->print_cr("");
}
}
! vs_list()->chunk_manager()->locked_print_free_chunks(st);
! vs_list()->chunk_manager()->locked_print_sum_free_chunks(st);
}
size_t SpaceManager::calc_chunk_size(size_t word_size) {
// Decide between a small chunk and a medium chunk. Up to
--- 1926,1937 ----
} else {
st->print_cr("");
}
}
! chunk_manager()->locked_print_free_chunks(st);
! chunk_manager()->locked_print_sum_free_chunks(st);
}
size_t SpaceManager::calc_chunk_size(size_t word_size) {
// Decide between a small chunk and a medium chunk. Up to
*** 2083,2095 ****
block_freelists()->total_size());
}
}
SpaceManager::SpaceManager(Metaspace::MetadataType mdtype,
! Mutex* lock,
! VirtualSpaceList* vs_list) :
! _vs_list(vs_list),
_mdtype(mdtype),
_allocated_blocks_words(0),
_allocated_chunks_words(0),
_allocated_chunks_count(0),
_lock(lock)
--- 2031,2041 ----
block_freelists()->total_size());
}
}
SpaceManager::SpaceManager(Metaspace::MetadataType mdtype,
! Mutex* lock) :
_mdtype(mdtype),
_allocated_blocks_words(0),
_allocated_chunks_words(0),
_allocated_chunks_count(0),
_lock(lock)
*** 2171,2183 ****
sum_capacity_in_chunks_in_use(), allocated_chunks_words()));
MutexLockerEx fcl(SpaceManager::expand_lock(),
Mutex::_no_safepoint_check_flag);
! ChunkManager* chunk_manager = vs_list()->chunk_manager();
!
! chunk_manager->slow_locked_verify();
dec_total_from_size_metrics();
if (TraceMetadataChunkAllocation && Verbose) {
gclog_or_tty->print_cr("~SpaceManager(): " PTR_FORMAT, this);
--- 2117,2127 ----
sum_capacity_in_chunks_in_use(), allocated_chunks_words()));
MutexLockerEx fcl(SpaceManager::expand_lock(),
Mutex::_no_safepoint_check_flag);
! chunk_manager()->slow_locked_verify();
dec_total_from_size_metrics();
if (TraceMetadataChunkAllocation && Verbose) {
gclog_or_tty->print_cr("~SpaceManager(): " PTR_FORMAT, this);
*** 2187,2197 ****
// Do not mangle freed Metachunks. The chunk size inside Metachunks
// is during the freeing of a VirtualSpaceNodes.
// Have to update before the chunks_in_use lists are emptied
// below.
! chunk_manager->inc_free_chunks_total(allocated_chunks_words(),
sum_count_in_chunks_in_use());
// Add all the chunks in use by this space manager
// to the global list of free chunks.
--- 2131,2141 ----
// Do not mangle freed Metachunks. The chunk size inside Metachunks
// is during the freeing of a VirtualSpaceNodes.
// Have to update before the chunks_in_use lists are emptied
// below.
! chunk_manager()->inc_free_chunks_total(allocated_chunks_words(),
sum_count_in_chunks_in_use());
// Add all the chunks in use by this space manager
// to the global list of free chunks.
*** 2203,2217 ****
gclog_or_tty->print_cr("returned %d %s chunks to freelist",
sum_count_in_chunks_in_use(i),
chunk_size_name(i));
}
Metachunk* chunks = chunks_in_use(i);
! chunk_manager->return_chunks(i, chunks);
set_chunks_in_use(i, NULL);
if (TraceMetadataChunkAllocation && Verbose) {
gclog_or_tty->print_cr("updated freelist count %d %s",
! chunk_manager->free_chunks(i)->count(),
chunk_size_name(i));
}
assert(i != HumongousIndex, "Humongous chunks are handled explicitly later");
}
--- 2147,2161 ----
gclog_or_tty->print_cr("returned %d %s chunks to freelist",
sum_count_in_chunks_in_use(i),
chunk_size_name(i));
}
Metachunk* chunks = chunks_in_use(i);
! chunk_manager()->return_chunks(i, chunks);
set_chunks_in_use(i, NULL);
if (TraceMetadataChunkAllocation && Verbose) {
gclog_or_tty->print_cr("updated freelist count %d %s",
! chunk_manager()->free_chunks(i)->count(),
chunk_size_name(i));
}
assert(i != HumongousIndex, "Humongous chunks are handled explicitly later");
}
*** 2244,2263 ****
err_msg("Humongous chunk size is wrong: word size " SIZE_FORMAT
" granularity %d",
humongous_chunks->word_size(), HumongousChunkGranularity));
Metachunk* next_humongous_chunks = humongous_chunks->next();
humongous_chunks->container()->dec_container_count();
! chunk_manager->humongous_dictionary()->return_chunk(humongous_chunks);
humongous_chunks = next_humongous_chunks;
}
if (TraceMetadataChunkAllocation && Verbose) {
gclog_or_tty->print_cr("");
gclog_or_tty->print_cr("updated dictionary count %d %s",
! chunk_manager->humongous_dictionary()->total_count(),
chunk_size_name(HumongousIndex));
}
! chunk_manager->slow_locked_verify();
}
const char* SpaceManager::chunk_size_name(ChunkIndex index) const {
switch (index) {
case SpecializedIndex:
--- 2188,2207 ----
err_msg("Humongous chunk size is wrong: word size " SIZE_FORMAT
" granularity %d",
humongous_chunks->word_size(), HumongousChunkGranularity));
Metachunk* next_humongous_chunks = humongous_chunks->next();
humongous_chunks->container()->dec_container_count();
! chunk_manager()->humongous_dictionary()->return_chunk(humongous_chunks);
humongous_chunks = next_humongous_chunks;
}
if (TraceMetadataChunkAllocation && Verbose) {
gclog_or_tty->print_cr("");
gclog_or_tty->print_cr("updated dictionary count %d %s",
! chunk_manager()->humongous_dictionary()->total_count(),
chunk_size_name(HumongousIndex));
}
! chunk_manager()->slow_locked_verify();
}
const char* SpaceManager::chunk_size_name(ChunkIndex index) const {
switch (index) {
case SpecializedIndex:
*** 2342,2354 ****
assert(new_chunk->is_empty(), "Not ready for reuse");
if (TraceMetadataChunkAllocation && Verbose) {
gclog_or_tty->print("SpaceManager::add_chunk: %d) ",
sum_count_in_chunks_in_use());
new_chunk->print_on(gclog_or_tty);
! if (vs_list() != NULL) {
! vs_list()->chunk_manager()->locked_print_free_chunks(gclog_or_tty);
! }
}
}
void SpaceManager::retire_current_chunk() {
if (current_chunk() != NULL) {
--- 2286,2296 ----
assert(new_chunk->is_empty(), "Not ready for reuse");
if (TraceMetadataChunkAllocation && Verbose) {
gclog_or_tty->print("SpaceManager::add_chunk: %d) ",
sum_count_in_chunks_in_use());
new_chunk->print_on(gclog_or_tty);
! chunk_manager()->locked_print_free_chunks(gclog_or_tty);
}
}
void SpaceManager::retire_current_chunk() {
if (current_chunk() != NULL) {
*** 2360,2373 ****
}
}
Metachunk* SpaceManager::get_new_chunk(size_t word_size,
size_t grow_chunks_by_words) {
! Metachunk* next = vs_list()->get_new_chunk(word_size,
grow_chunks_by_words,
medium_chunk_bunch());
if (TraceMetadataHumongousAllocation && next != NULL &&
SpaceManager::is_humongous(next->word_size())) {
gclog_or_tty->print_cr(" new humongous chunk word size "
PTR_FORMAT, next->word_size());
--- 2302,2319 ----
}
}
Metachunk* SpaceManager::get_new_chunk(size_t word_size,
size_t grow_chunks_by_words) {
+ // Get a chunk from the chunk freelist
+ Metachunk* next = chunk_manager()->chunk_freelist_allocate(grow_chunks_by_words);
! if (next == NULL) {
! next = vs_list()->get_new_chunk(word_size,
grow_chunks_by_words,
medium_chunk_bunch());
+ }
if (TraceMetadataHumongousAllocation && next != NULL &&
SpaceManager::is_humongous(next->word_size())) {
gclog_or_tty->print_cr(" new humongous chunk word size "
PTR_FORMAT, next->word_size());
*** 2643,2659 ****
}
size_t MetaspaceAux::min_chunk_size_words() { return Metaspace::first_chunk_word_size(); }
size_t MetaspaceAux::free_chunks_total_words(Metaspace::MetadataType mdtype) {
! VirtualSpaceList* list = Metaspace::get_space_list(mdtype);
! if (list == NULL) {
return 0;
}
! ChunkManager* chunk = list->chunk_manager();
! chunk->slow_verify();
! return chunk->free_chunks_total_words();
}
size_t MetaspaceAux::free_chunks_total_bytes(Metaspace::MetadataType mdtype) {
return free_chunks_total_words(mdtype) * BytesPerWord;
}
--- 2589,2604 ----
}
size_t MetaspaceAux::min_chunk_size_words() { return Metaspace::first_chunk_word_size(); }
size_t MetaspaceAux::free_chunks_total_words(Metaspace::MetadataType mdtype) {
! ChunkManager* chunk_manager = Metaspace::get_chunk_manager(mdtype);
! if (chunk_manager == NULL) {
return 0;
}
! chunk_manager->slow_verify();
! return chunk_manager->free_chunks_total_words();
}
size_t MetaspaceAux::free_chunks_total_bytes(Metaspace::MetadataType mdtype) {
return free_chunks_total_words(mdtype) * BytesPerWord;
}
*** 2800,2812 ****
out->print("class space: "); print_on(out, Metaspace::ClassType);
print_waste(out);
}
void MetaspaceAux::verify_free_chunks() {
! Metaspace::space_list()->chunk_manager()->verify();
if (Metaspace::using_class_space()) {
! Metaspace::class_space_list()->chunk_manager()->verify();
}
}
void MetaspaceAux::verify_capacity() {
#ifdef ASSERT
--- 2745,2757 ----
out->print("class space: "); print_on(out, Metaspace::ClassType);
print_waste(out);
}
void MetaspaceAux::verify_free_chunks() {
! Metaspace::chunk_manager_metadata()->verify();
if (Metaspace::using_class_space()) {
! Metaspace::chunk_manager_class()->verify();
}
}
void MetaspaceAux::verify_capacity() {
#ifdef ASSERT
*** 2873,2882 ****
--- 2818,2830 ----
}
VirtualSpaceList* Metaspace::_space_list = NULL;
VirtualSpaceList* Metaspace::_class_space_list = NULL;
+ ChunkManager* Metaspace::_chunk_manager_metadata = NULL;
+ ChunkManager* Metaspace::_chunk_manager_class = NULL;
+
#define VIRTUALSPACEMULTIPLIER 2
#ifdef _LP64
void Metaspace::set_narrow_klass_base_and_shift(address metaspace_base, address cds_base) {
// Figure out the narrow_klass_base and the narrow_klass_shift. The
*** 2980,2989 ****
--- 2928,2938 ----
// The reserved space size may be bigger because of alignment, esp with UseLargePages
assert(rs.size() >= CompressedClassSpaceSize,
err_msg(SIZE_FORMAT " != " UINTX_FORMAT, rs.size(), CompressedClassSpaceSize));
assert(using_class_space(), "Must be using class space");
_class_space_list = new VirtualSpaceList(rs);
+ _chunk_manager_class = new ChunkManager(SpecializedChunk, ClassSmallChunk, ClassMediumChunk);
}
#endif
void Metaspace::global_initialize() {
*** 3005,3014 ****
--- 2954,2964 ----
// Initialize with the sum of the shared space sizes. The read-only
// and read write metaspace chunks will be allocated out of this and the
// remainder is the misc code and data chunks.
cds_total = FileMapInfo::shared_spaces_size();
_space_list = new VirtualSpaceList(cds_total/wordSize);
+ _chunk_manager_metadata = new ChunkManager(SpecializedChunk, SmallChunk, MediumChunk);
#ifdef _LP64
// Set the compressed klass pointer base so that decoding of these pointers works
// properly when creating the shared archive.
assert(UseCompressedOops && UseCompressedClassPointers,
*** 3072,3124 ****
// Arbitrarily set the initial virtual space to a multiple
// of the boot class loader size.
size_t word_size = VIRTUALSPACEMULTIPLIER * first_chunk_word_size();
// Initialize the list of virtual spaces.
_space_list = new VirtualSpaceList(word_size);
}
}
void Metaspace::initialize(Mutex* lock, MetaspaceType type) {
assert(space_list() != NULL,
"Metadata VirtualSpaceList has not been initialized");
! _vsm = new SpaceManager(NonClassType, lock, space_list());
if (_vsm == NULL) {
return;
}
size_t word_size;
size_t class_word_size;
vsm()->get_initial_chunk_sizes(type, &word_size, &class_word_size);
if (using_class_space()) {
assert(class_space_list() != NULL,
"Class VirtualSpaceList has not been initialized");
// Allocate SpaceManager for classes.
! _class_vsm = new SpaceManager(ClassType, lock, class_space_list());
if (_class_vsm == NULL) {
return;
}
}
MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag);
// Allocate chunk for metadata objects
! Metachunk* new_chunk =
! space_list()->get_initialization_chunk(word_size,
vsm()->medium_chunk_bunch());
assert(!DumpSharedSpaces || new_chunk != NULL, "should have enough space for both chunks");
if (new_chunk != NULL) {
// Add to this manager's list of chunks in use and current_chunk().
vsm()->add_chunk(new_chunk, true);
}
// Allocate chunk for class metadata objects
if (using_class_space()) {
! Metachunk* class_chunk =
! class_space_list()->get_initialization_chunk(class_word_size,
class_vsm()->medium_chunk_bunch());
if (class_chunk != NULL) {
class_vsm()->add_chunk(class_chunk, true);
}
}
--- 3022,3091 ----
// Arbitrarily set the initial virtual space to a multiple
// of the boot class loader size.
size_t word_size = VIRTUALSPACEMULTIPLIER * first_chunk_word_size();
// Initialize the list of virtual spaces.
_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) {
assert(space_list() != NULL,
"Metadata VirtualSpaceList has not been initialized");
+ assert(chunk_manager_metadata() != NULL,
+ "Metadata ChunkManager has not been initialized");
! _vsm = new SpaceManager(NonClassType, lock);
if (_vsm == NULL) {
return;
}
size_t word_size;
size_t class_word_size;
vsm()->get_initial_chunk_sizes(type, &word_size, &class_word_size);
if (using_class_space()) {
assert(class_space_list() != NULL,
"Class VirtualSpaceList has not been initialized");
+ assert(chunk_manager_class() != NULL,
+ "Class ChunkManager has not been initialized");
// Allocate SpaceManager for classes.
! _class_vsm = new SpaceManager(ClassType, lock);
if (_class_vsm == NULL) {
return;
}
}
MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag);
// Allocate chunk for metadata objects
! Metachunk* new_chunk = get_initialization_chunk(NonClassType,
! word_size,
vsm()->medium_chunk_bunch());
assert(!DumpSharedSpaces || new_chunk != NULL, "should have enough space for both chunks");
if (new_chunk != NULL) {
// Add to this manager's list of chunks in use and current_chunk().
vsm()->add_chunk(new_chunk, true);
}
// Allocate chunk for class metadata objects
if (using_class_space()) {
! Metachunk* class_chunk = get_initialization_chunk(ClassType,
! class_word_size,
class_vsm()->medium_chunk_bunch());
if (class_chunk != NULL) {
class_vsm()->add_chunk(class_chunk, true);
}
}
*** 3332,3347 ****
if (last_addr < top) {
closure->doit(last_addr, MetaspaceObj::UnknownType, top - last_addr);
}
}
void Metaspace::purge() {
MutexLockerEx cl(SpaceManager::expand_lock(),
Mutex::_no_safepoint_check_flag);
! space_list()->purge();
if (using_class_space()) {
! class_space_list()->purge();
}
}
void Metaspace::print_on(outputStream* out) const {
// Print both class virtual space counts and metaspace.
--- 3299,3318 ----
if (last_addr < top) {
closure->doit(last_addr, MetaspaceObj::UnknownType, top - last_addr);
}
}
+ void Metaspace::purge(MetadataType mdtype) {
+ get_space_list(mdtype)->purge(get_chunk_manager(mdtype));
+ }
+
void Metaspace::purge() {
MutexLockerEx cl(SpaceManager::expand_lock(),
Mutex::_no_safepoint_check_flag);
! purge(NonClassType);
if (using_class_space()) {
! purge(ClassType);
}
}
void Metaspace::print_on(outputStream* out) const {
// Print both class virtual space counts and metaspace.
src/share/vm/memory/metaspace.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File