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;
*** 592,601 **** --- 585,596 ---- Metachunk* _current_chunk; // Virtual space where allocation comes from. VirtualSpaceList* _vs_list; + ChunkManager* _chunk_manager; + // 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
*** 626,635 **** --- 621,632 ---- } Metaspace::MetadataType mdtype() { return _mdtype; } VirtualSpaceList* vs_list() const { return _vs_list; } + ChunkManager* chunk_manager() const { return _chunk_manager; } + Metachunk* current_chunk() const { return _current_chunk; } void set_current_chunk(Metachunk* v) { _current_chunk = v; }
*** 647,667 **** 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; } --- 644,667 ---- void initialize(); public: SpaceManager(Metaspace::MetadataType mdtype, Mutex* lock, ! VirtualSpaceList* vs_list, ! ChunkManager* chunk_manager); ~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()); --- 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());
*** 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 --- 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
*** 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(); --- 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(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; --- 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;
*** 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) : --- 1062,1081 ----
*** 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() { --- 1087,1096 ----
*** 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, --- 1156,1167 ---- 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,
*** 1534,1552 **** 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(); } --- 1490,1508 ---- 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(); }
*** 1794,1803 **** --- 1750,1761 ---- #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) {
*** 1977,1988 **** } 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 --- 1935,1946 ---- } 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,2094 **** } } 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) --- 2041,2054 ---- } } SpaceManager::SpaceManager(Metaspace::MetadataType mdtype, Mutex* lock, ! VirtualSpaceList* vs_list, ! ChunkManager* chunk_manager) : _vs_list(vs_list), + _chunk_manager(chunk_manager), _mdtype(mdtype), _allocated_blocks_words(0), _allocated_chunks_words(0), _allocated_chunks_count(0), _lock(lock)
*** 2170,2182 **** 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); --- 2130,2140 ---- 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);
*** 2186,2196 **** // 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. --- 2144,2154 ---- // 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.
*** 2202,2216 **** 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"); } --- 2160,2174 ---- 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"); }
*** 2243,2262 **** 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: --- 2201,2220 ---- 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:
*** 2341,2353 **** 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) { --- 2299,2309 ---- 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) {
*** 2359,2372 **** } } 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()); --- 2315,2332 ---- } } 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());
*** 2642,2658 **** } 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; } --- 2602,2617 ---- } 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; }
*** 2799,2811 **** 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 --- 2758,2770 ---- 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
*** 2872,2881 **** --- 2831,2843 ---- } 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
*** 2979,2988 **** --- 2941,2951 ---- // 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() {
*** 3004,3013 **** --- 2967,2977 ---- // 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,
*** 3071,3123 **** // 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); } } --- 3035,3104 ---- // 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, space_list(), chunk_manager_metadata()); 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, class_space_list(), chunk_manager_class()); 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); } }
*** 3331,3346 **** 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. --- 3312,3331 ---- 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