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

        

*** 28,38 **** #include "memory/freeList.hpp" #include "memory/collectorPolicy.hpp" #include "memory/filemap.hpp" #include "memory/freeList.hpp" #include "memory/gcLocker.hpp" - #include "memory/metablock.hpp" #include "memory/metachunk.hpp" #include "memory/metaspace.hpp" #include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" --- 28,37 ----
*** 47,58 **** #include "utilities/copy.hpp" #include "utilities/debug.hpp" typedef BinaryTreeDictionary<Metablock, FreeList> BlockTreeDictionary; typedef BinaryTreeDictionary<Metachunk, FreeList> ChunkTreeDictionary; ! // Define this macro to enable slow integrity checking of ! // the free chunk lists const bool metaspace_slow_verify = false; // Parameters for stress mode testing const uint metadata_deallocate_a_lot_block = 10; const uint metadata_deallocate_a_lock_chunk = 3; --- 46,57 ---- #include "utilities/copy.hpp" #include "utilities/debug.hpp" typedef BinaryTreeDictionary<Metablock, FreeList> BlockTreeDictionary; typedef BinaryTreeDictionary<Metachunk, FreeList> ChunkTreeDictionary; ! ! // Set this constant to enable slow integrity checking of the free chunk lists const bool metaspace_slow_verify = false; // Parameters for stress mode testing const uint metadata_deallocate_a_lot_block = 10; const uint metadata_deallocate_a_lock_chunk = 3;
*** 90,127 **** volatile intptr_t MetaspaceGC::_capacity_until_GC = 0; uint MetaspaceGC::_shrink_factor = 0; bool MetaspaceGC::_should_concurrent_collect = false; - // Blocks of space for metadata are allocated out of Metachunks. - // - // Metachunk are allocated out of MetadataVirtualspaces and once - // allocated there is no explicit link between a Metachunk and - // the MetadataVirtualspaces from which it was allocated. - // - // Each SpaceManager maintains a - // list of the chunks it is using and the current chunk. The current - // chunk is the chunk from which allocations are done. Space freed in - // a chunk is placed on the free list of blocks (BlockFreelist) and - // reused from there. - typedef class FreeList<Metachunk> ChunkList; // 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 // HumongousChunk ChunkList _free_chunks[NumberOfFreeLists]; - // HumongousChunk ChunkTreeDictionary _humongous_dictionary; // ChunkManager in all lists of this type size_t _free_chunks_total; --- 89,110 ----
*** 228,238 **** // Used to manage the free list of Metablocks (a block corresponds // to the allocation of a quantum of metadata). class BlockFreelist VALUE_OBJ_CLASS_SPEC { BlockTreeDictionary* _dictionary; - static Metablock* initialize_free_chunk(MetaWord* p, size_t word_size); // Only allocate and split from freelist if the size of the allocation // is at least 1/4th the size of the available block. const static int WasteMultiplier = 4; --- 211,220 ----
*** 256,265 **** --- 238,248 ---- } void print_on(outputStream* st) const; }; + // A VirtualSpaceList node. class VirtualSpaceNode : public CHeapObj<mtClass> { friend class VirtualSpaceList; // Link to next VirtualSpaceNode VirtualSpaceNode* _next;
*** 412,422 **** void VirtualSpaceNode::purge(ChunkManager* chunk_manager) { Metachunk* chunk = first_chunk(); Metachunk* invalid_chunk = (Metachunk*) top(); while (chunk < invalid_chunk ) { ! assert(chunk->is_free(), "Should be marked free"); MetaWord* next = ((MetaWord*)chunk) + chunk->word_size(); chunk_manager->remove_chunk(chunk); assert(chunk->next() == NULL && chunk->prev() == NULL, "Was not removed from its list"); --- 395,405 ---- void VirtualSpaceNode::purge(ChunkManager* chunk_manager) { Metachunk* chunk = first_chunk(); Metachunk* invalid_chunk = (Metachunk*) top(); while (chunk < invalid_chunk ) { ! assert(chunk->is_marked_free(), "Should be marked free"); MetaWord* next = ((MetaWord*)chunk) + chunk->word_size(); chunk_manager->remove_chunk(chunk); assert(chunk->next() == NULL && chunk->prev() == NULL, "Was not removed from its list");
*** 432,442 **** while (chunk < invalid_chunk ) { MetaWord* next = ((MetaWord*)chunk) + chunk->word_size(); // Don't count the chunks on the free lists. Those are // still part of the VirtualSpaceNode but not currently // counted. ! if (!chunk->is_free()) { count++; } chunk = (Metachunk*) next; } return count; --- 415,425 ---- while (chunk < invalid_chunk ) { MetaWord* next = ((MetaWord*)chunk) + chunk->word_size(); // Don't count the chunks on the free lists. Those are // still part of the VirtualSpaceNode but not currently // counted. ! if (!chunk->is_marked_free()) { count++; } chunk = (Metachunk*) next; } return count;
*** 751,768 **** #ifdef ASSERT void verify_allocated_blocks_words(); #endif size_t get_raw_word_size(size_t word_size) { - // If only the dictionary is going to be used (i.e., no - // indexed free list), then there is a minimum size requirement. - // MinChunkSize is a placeholder for the real minimum size JJJ size_t byte_size = word_size * BytesPerWord; ! size_t raw_bytes_size = MAX2(byte_size, ! Metablock::min_block_byte_size()); ! raw_bytes_size = ARENA_ALIGN(raw_bytes_size); size_t raw_word_size = raw_bytes_size / BytesPerWord; assert(raw_word_size * BytesPerWord == raw_bytes_size, "Size problem"); return raw_word_size; } --- 734,748 ---- #ifdef ASSERT void verify_allocated_blocks_words(); #endif size_t get_raw_word_size(size_t word_size) { size_t byte_size = word_size * BytesPerWord; ! size_t raw_bytes_size = MAX2(byte_size, sizeof(Metablock)); ! raw_bytes_size = align_size_up(raw_bytes_size, Metachunk::object_alignment()); ! size_t raw_word_size = raw_bytes_size / BytesPerWord; assert(raw_word_size * BytesPerWord == raw_bytes_size, "Size problem"); return raw_word_size; }
*** 811,831 **** } delete _dictionary; } } - Metablock* BlockFreelist::initialize_free_chunk(MetaWord* p, size_t word_size) { - Metablock* block = (Metablock*) p; - block->set_word_size(word_size); - block->set_prev(NULL); - block->set_next(NULL); - - return block; - } - void BlockFreelist::return_block(MetaWord* p, size_t word_size) { ! Metablock* free_chunk = initialize_free_chunk(p, word_size); if (dictionary() == NULL) { _dictionary = new BlockTreeDictionary(); } dictionary()->return_chunk(free_chunk); } --- 791,802 ---- } delete _dictionary; } } void BlockFreelist::return_block(MetaWord* p, size_t word_size) { ! Metablock* free_chunk = ::new (p) Metablock(word_size); if (dictionary() == NULL) { _dictionary = new BlockTreeDictionary(); } dictionary()->return_chunk(free_chunk); }
*** 1067,1077 **** } else { humongous_dictionary()->remove_chunk(chunk); } // Chunk is being removed from the chunks free list. ! dec_free_chunks_total(chunk->capacity_word_size()); } // Walk the list of VirtualSpaceNodes and delete // nodes with a 0 container_count. Remove Metachunks in // the node from their respective freelists. --- 1038,1048 ---- } else { humongous_dictionary()->remove_chunk(chunk); } // Chunk is being removed from the chunks free list. ! dec_free_chunks_total(chunk->word_size()); } // Walk the list of VirtualSpaceNodes and delete // nodes with a 0 container_count. Remove Metachunks in // the node from their respective freelists.
*** 1758,1768 **** assert_lock_strong(SpaceManager::expand_lock()); ChunkList* free_list = find_free_chunks_list(chunk->word_size()); chunk->set_next(free_list->head()); free_list->set_head(chunk); // chunk is being returned to the chunk free list ! inc_free_chunks_total(chunk->capacity_word_size()); slow_locked_verify(); } void ChunkManager::chunk_freelist_deallocate(Metachunk* chunk) { // The deallocation of a chunk originates in the freelist --- 1729,1739 ---- assert_lock_strong(SpaceManager::expand_lock()); ChunkList* free_list = find_free_chunks_list(chunk->word_size()); chunk->set_next(free_list->head()); free_list->set_head(chunk); // chunk is being returned to the chunk free list ! inc_free_chunks_total(chunk->word_size()); slow_locked_verify(); } void ChunkManager::chunk_freelist_deallocate(Metachunk* chunk) { // The deallocation of a chunk originates in the freelist
*** 1820,1838 **** chunk->word_size(), word_size, waste); } } // Chunk is being removed from the chunks free list. ! dec_free_chunks_total(chunk->capacity_word_size()); // Remove it from the links to this freelist chunk->set_next(NULL); chunk->set_prev(NULL); #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; --- 1791,1809 ---- chunk->word_size(), word_size, waste); } } // Chunk is being removed from the chunks free list. ! dec_free_chunks_total(chunk->word_size()); // Remove it from the links to this freelist chunk->set_next(NULL); chunk->set_prev(NULL); #ifdef ASSERT // Chunk is no longer on any freelist. Setting to false make container_count_slow() // work. ! chunk->set_is_marked_free(false); #endif chunk->container()->inc_container_count(); slow_locked_verify(); return chunk;
*** 1960,1970 **** MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); size_t sum = 0; for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { Metachunk* chunk = chunks_in_use(i); while (chunk != NULL) { ! sum += chunk->capacity_word_size(); chunk = chunk->next(); } } return sum; } --- 1931,1941 ---- MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); size_t sum = 0; for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { Metachunk* chunk = chunks_in_use(i); while (chunk != NULL) { ! sum += chunk->word_size(); chunk = chunk->next(); } } return sum; }
*** 2208,2218 **** assert(cur->container() != NULL, "Container should have been set"); cur->container()->dec_container_count(); // Capture the next link before it is changed // by the call to return_chunk_at_head(); Metachunk* next = cur->next(); ! cur->set_is_free(true); list->return_chunk_at_head(cur); cur = next; } } --- 2179,2189 ---- assert(cur->container() != NULL, "Container should have been set"); cur->container()->dec_container_count(); // Capture the next link before it is changed // by the call to return_chunk_at_head(); Metachunk* next = cur->next(); ! DEBUG_ONLY(cur->set_is_marked_free(true);) list->return_chunk_at_head(cur); cur = next; } }
*** 2280,2290 **** // Humongous chunks are never the current chunk. Metachunk* humongous_chunks = chunks_in_use(HumongousIndex); while (humongous_chunks != NULL) { #ifdef ASSERT ! humongous_chunks->set_is_free(true); #endif if (TraceMetadataChunkAllocation && Verbose) { gclog_or_tty->print(PTR_FORMAT " (" SIZE_FORMAT ") ", humongous_chunks, humongous_chunks->word_size()); --- 2251,2261 ---- // Humongous chunks are never the current chunk. Metachunk* humongous_chunks = chunks_in_use(HumongousIndex); while (humongous_chunks != NULL) { #ifdef ASSERT ! humongous_chunks->set_is_marked_free(true); #endif if (TraceMetadataChunkAllocation && Verbose) { gclog_or_tty->print(PTR_FORMAT " (" SIZE_FORMAT ") ", humongous_chunks, humongous_chunks->word_size());
*** 2543,2553 **** curr = curr->next()) { out->print("%d) ", i++); curr->print_on(out); curr_total += curr->word_size(); used += curr->used_word_size(); ! capacity += curr->capacity_word_size(); waste += curr->free_word_size() + curr->overhead();; } } if (TraceMetadataChunkAllocation && Verbose) { --- 2514,2524 ---- curr = curr->next()) { out->print("%d) ", i++); curr->print_on(out); curr_total += curr->word_size(); used += curr->used_word_size(); ! capacity += curr->word_size(); waste += curr->free_word_size() + curr->overhead();; } } if (TraceMetadataChunkAllocation && Verbose) {
*** 3394,3404 **** } } } ! Metablock* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size, bool read_only, MetaspaceObj::Type type, TRAPS) { if (HAS_PENDING_EXCEPTION) { assert(false, "Should not allocate with exception pending"); return NULL; // caller does a CHECK_NULL too } --- 3365,3375 ---- } } } ! MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size, bool read_only, MetaspaceObj::Type type, TRAPS) { if (HAS_PENDING_EXCEPTION) { assert(false, "Should not allocate with exception pending"); return NULL; // caller does a CHECK_NULL too }
*** 3413,3426 **** assert(type > MetaspaceObj::UnknownType && type < MetaspaceObj::_number_of_types, "sanity"); Metaspace* space = read_only ? loader_data->ro_metaspace() : loader_data->rw_metaspace(); MetaWord* result = space->allocate(word_size, NonClassType); if (result == NULL) { report_out_of_shared_space(read_only ? SharedReadOnly : SharedReadWrite); - } else { - space->record_allocation(result, type, space->vsm()->get_raw_word_size(word_size)); } ! return Metablock::initialize(result, word_size); } MetadataType mdtype = (type == MetaspaceObj::ClassType) ? ClassType : NonClassType; // Try to allocate metadata. --- 3384,3401 ---- assert(type > MetaspaceObj::UnknownType && type < MetaspaceObj::_number_of_types, "sanity"); Metaspace* space = read_only ? loader_data->ro_metaspace() : loader_data->rw_metaspace(); MetaWord* result = space->allocate(word_size, NonClassType); if (result == NULL) { report_out_of_shared_space(read_only ? SharedReadOnly : SharedReadWrite); } ! ! space->record_allocation(result, type, space->vsm()->get_raw_word_size(word_size)); ! ! // Zero initialize. ! Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0); ! ! return result; } MetadataType mdtype = (type == MetaspaceObj::ClassType) ? ClassType : NonClassType; // Try to allocate metadata.
*** 3441,3451 **** report_metadata_oome(loader_data, word_size, mdtype, THREAD); // Will not reach here. return NULL; } ! return Metablock::initialize(result, word_size); } void Metaspace::report_metadata_oome(ClassLoaderData* loader_data, size_t word_size, MetadataType mdtype, TRAPS) { // If result is still null, we are out of memory. if (Verbose && TraceMetadataChunkAllocation) { --- 3416,3429 ---- report_metadata_oome(loader_data, word_size, mdtype, THREAD); // Will not reach here. return NULL; } ! // Zero initialize. ! Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0); ! ! return result; } void Metaspace::report_metadata_oome(ClassLoaderData* loader_data, size_t word_size, MetadataType mdtype, TRAPS) { // If result is still null, we are out of memory. if (Verbose && TraceMetadataChunkAllocation) {
src/share/vm/memory/metaspace.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File