comparison src/share/vm/memory/metaspace.cpp @ 12902:bdfbb1fb19ca

8026391: The Metachunk header wastes memory Reviewed-by: coleenp, jmasa
author stefank
date Tue, 15 Oct 2013 14:28:51 +0200
parents a6414751d537
children 94c0343b1887
comparison
equal deleted inserted replaced
12901:f16726924734 12902:bdfbb1fb19ca
28 #include "memory/freeList.hpp" 28 #include "memory/freeList.hpp"
29 #include "memory/collectorPolicy.hpp" 29 #include "memory/collectorPolicy.hpp"
30 #include "memory/filemap.hpp" 30 #include "memory/filemap.hpp"
31 #include "memory/freeList.hpp" 31 #include "memory/freeList.hpp"
32 #include "memory/gcLocker.hpp" 32 #include "memory/gcLocker.hpp"
33 #include "memory/metablock.hpp"
34 #include "memory/metachunk.hpp" 33 #include "memory/metachunk.hpp"
35 #include "memory/metaspace.hpp" 34 #include "memory/metaspace.hpp"
36 #include "memory/metaspaceShared.hpp" 35 #include "memory/metaspaceShared.hpp"
37 #include "memory/resourceArea.hpp" 36 #include "memory/resourceArea.hpp"
38 #include "memory/universe.hpp" 37 #include "memory/universe.hpp"
47 #include "utilities/copy.hpp" 46 #include "utilities/copy.hpp"
48 #include "utilities/debug.hpp" 47 #include "utilities/debug.hpp"
49 48
50 typedef BinaryTreeDictionary<Metablock, FreeList> BlockTreeDictionary; 49 typedef BinaryTreeDictionary<Metablock, FreeList> BlockTreeDictionary;
51 typedef BinaryTreeDictionary<Metachunk, FreeList> ChunkTreeDictionary; 50 typedef BinaryTreeDictionary<Metachunk, FreeList> ChunkTreeDictionary;
52 // Define this macro to enable slow integrity checking of 51
53 // the free chunk lists 52 // Set this constant to enable slow integrity checking of the free chunk lists
54 const bool metaspace_slow_verify = false; 53 const bool metaspace_slow_verify = false;
55 54
56 // Parameters for stress mode testing 55 // Parameters for stress mode testing
57 const uint metadata_deallocate_a_lot_block = 10; 56 const uint metadata_deallocate_a_lot_block = 10;
58 const uint metadata_deallocate_a_lock_chunk = 3; 57 const uint metadata_deallocate_a_lock_chunk = 3;
90 89
91 volatile intptr_t MetaspaceGC::_capacity_until_GC = 0; 90 volatile intptr_t MetaspaceGC::_capacity_until_GC = 0;
92 uint MetaspaceGC::_shrink_factor = 0; 91 uint MetaspaceGC::_shrink_factor = 0;
93 bool MetaspaceGC::_should_concurrent_collect = false; 92 bool MetaspaceGC::_should_concurrent_collect = false;
94 93
95 // Blocks of space for metadata are allocated out of Metachunks.
96 //
97 // Metachunk are allocated out of MetadataVirtualspaces and once
98 // allocated there is no explicit link between a Metachunk and
99 // the MetadataVirtualspaces from which it was allocated.
100 //
101 // Each SpaceManager maintains a
102 // list of the chunks it is using and the current chunk. The current
103 // chunk is the chunk from which allocations are done. Space freed in
104 // a chunk is placed on the free list of blocks (BlockFreelist) and
105 // reused from there.
106
107 typedef class FreeList<Metachunk> ChunkList; 94 typedef class FreeList<Metachunk> ChunkList;
108 95
109 // Manages the global free lists of chunks. 96 // Manages the global free lists of chunks.
110 // Has three lists of free chunks, and a total size and
111 // count that includes all three
112
113 class ChunkManager : public CHeapObj<mtInternal> { 97 class ChunkManager : public CHeapObj<mtInternal> {
114 98
115 // Free list of chunks of different sizes. 99 // Free list of chunks of different sizes.
116 // SpecializedChunk 100 // SpecializedChunk
117 // SmallChunk 101 // SmallChunk
118 // MediumChunk 102 // MediumChunk
119 // HumongousChunk 103 // HumongousChunk
120 ChunkList _free_chunks[NumberOfFreeLists]; 104 ChunkList _free_chunks[NumberOfFreeLists];
121
122 105
123 // HumongousChunk 106 // HumongousChunk
124 ChunkTreeDictionary _humongous_dictionary; 107 ChunkTreeDictionary _humongous_dictionary;
125 108
126 // ChunkManager in all lists of this type 109 // ChunkManager in all lists of this type
228 211
229 // Used to manage the free list of Metablocks (a block corresponds 212 // Used to manage the free list of Metablocks (a block corresponds
230 // to the allocation of a quantum of metadata). 213 // to the allocation of a quantum of metadata).
231 class BlockFreelist VALUE_OBJ_CLASS_SPEC { 214 class BlockFreelist VALUE_OBJ_CLASS_SPEC {
232 BlockTreeDictionary* _dictionary; 215 BlockTreeDictionary* _dictionary;
233 static Metablock* initialize_free_chunk(MetaWord* p, size_t word_size);
234 216
235 // Only allocate and split from freelist if the size of the allocation 217 // Only allocate and split from freelist if the size of the allocation
236 // is at least 1/4th the size of the available block. 218 // is at least 1/4th the size of the available block.
237 const static int WasteMultiplier = 4; 219 const static int WasteMultiplier = 4;
238 220
256 } 238 }
257 239
258 void print_on(outputStream* st) const; 240 void print_on(outputStream* st) const;
259 }; 241 };
260 242
243 // A VirtualSpaceList node.
261 class VirtualSpaceNode : public CHeapObj<mtClass> { 244 class VirtualSpaceNode : public CHeapObj<mtClass> {
262 friend class VirtualSpaceList; 245 friend class VirtualSpaceList;
263 246
264 // Link to next VirtualSpaceNode 247 // Link to next VirtualSpaceNode
265 VirtualSpaceNode* _next; 248 VirtualSpaceNode* _next;
412 395
413 void VirtualSpaceNode::purge(ChunkManager* chunk_manager) { 396 void VirtualSpaceNode::purge(ChunkManager* chunk_manager) {
414 Metachunk* chunk = first_chunk(); 397 Metachunk* chunk = first_chunk();
415 Metachunk* invalid_chunk = (Metachunk*) top(); 398 Metachunk* invalid_chunk = (Metachunk*) top();
416 while (chunk < invalid_chunk ) { 399 while (chunk < invalid_chunk ) {
417 assert(chunk->is_free(), "Should be marked free"); 400 assert(chunk->is_tagged_free(), "Should be tagged free");
418 MetaWord* next = ((MetaWord*)chunk) + chunk->word_size(); 401 MetaWord* next = ((MetaWord*)chunk) + chunk->word_size();
419 chunk_manager->remove_chunk(chunk); 402 chunk_manager->remove_chunk(chunk);
420 assert(chunk->next() == NULL && 403 assert(chunk->next() == NULL &&
421 chunk->prev() == NULL, 404 chunk->prev() == NULL,
422 "Was not removed from its list"); 405 "Was not removed from its list");
423 chunk = (Metachunk*) next; 406 chunk = (Metachunk*) next;
424 } 407 }
425 } 408 }
426 409
427 #ifdef ASSERT 410 #ifdef ASSERT
428 uint VirtualSpaceNode::container_count_slow() { 411 uint VirtualSpaceNode::container_count_slow() {
432 while (chunk < invalid_chunk ) { 415 while (chunk < invalid_chunk ) {
433 MetaWord* next = ((MetaWord*)chunk) + chunk->word_size(); 416 MetaWord* next = ((MetaWord*)chunk) + chunk->word_size();
434 // Don't count the chunks on the free lists. Those are 417 // Don't count the chunks on the free lists. Those are
435 // still part of the VirtualSpaceNode but not currently 418 // still part of the VirtualSpaceNode but not currently
436 // counted. 419 // counted.
437 if (!chunk->is_free()) { 420 if (!chunk->is_tagged_free()) {
438 count++; 421 count++;
439 } 422 }
440 chunk = (Metachunk*) next; 423 chunk = (Metachunk*) next;
441 } 424 }
442 return count; 425 return count;
751 #ifdef ASSERT 734 #ifdef ASSERT
752 void verify_allocated_blocks_words(); 735 void verify_allocated_blocks_words();
753 #endif 736 #endif
754 737
755 size_t get_raw_word_size(size_t word_size) { 738 size_t get_raw_word_size(size_t word_size) {
756 // If only the dictionary is going to be used (i.e., no
757 // indexed free list), then there is a minimum size requirement.
758 // MinChunkSize is a placeholder for the real minimum size JJJ
759 size_t byte_size = word_size * BytesPerWord; 739 size_t byte_size = word_size * BytesPerWord;
760 740
761 size_t raw_bytes_size = MAX2(byte_size, 741 size_t raw_bytes_size = MAX2(byte_size, sizeof(Metablock));
762 Metablock::min_block_byte_size()); 742 raw_bytes_size = align_size_up(raw_bytes_size, Metachunk::object_alignment());
763 raw_bytes_size = ARENA_ALIGN(raw_bytes_size); 743
764 size_t raw_word_size = raw_bytes_size / BytesPerWord; 744 size_t raw_word_size = raw_bytes_size / BytesPerWord;
765 assert(raw_word_size * BytesPerWord == raw_bytes_size, "Size problem"); 745 assert(raw_word_size * BytesPerWord == raw_bytes_size, "Size problem");
766 746
767 return raw_word_size; 747 return raw_word_size;
768 } 748 }
811 } 791 }
812 delete _dictionary; 792 delete _dictionary;
813 } 793 }
814 } 794 }
815 795
816 Metablock* BlockFreelist::initialize_free_chunk(MetaWord* p, size_t word_size) {
817 Metablock* block = (Metablock*) p;
818 block->set_word_size(word_size);
819 block->set_prev(NULL);
820 block->set_next(NULL);
821
822 return block;
823 }
824
825 void BlockFreelist::return_block(MetaWord* p, size_t word_size) { 796 void BlockFreelist::return_block(MetaWord* p, size_t word_size) {
826 Metablock* free_chunk = initialize_free_chunk(p, word_size); 797 Metablock* free_chunk = ::new (p) Metablock(word_size);
827 if (dictionary() == NULL) { 798 if (dictionary() == NULL) {
828 _dictionary = new BlockTreeDictionary(); 799 _dictionary = new BlockTreeDictionary();
829 } 800 }
830 dictionary()->return_chunk(free_chunk); 801 dictionary()->return_chunk(free_chunk);
831 } 802 }
1067 } else { 1038 } else {
1068 humongous_dictionary()->remove_chunk(chunk); 1039 humongous_dictionary()->remove_chunk(chunk);
1069 } 1040 }
1070 1041
1071 // Chunk is being removed from the chunks free list. 1042 // Chunk is being removed from the chunks free list.
1072 dec_free_chunks_total(chunk->capacity_word_size()); 1043 dec_free_chunks_total(chunk->word_size());
1073 } 1044 }
1074 1045
1075 // Walk the list of VirtualSpaceNodes and delete 1046 // Walk the list of VirtualSpaceNodes and delete
1076 // nodes with a 0 container_count. Remove Metachunks in 1047 // nodes with a 0 container_count. Remove Metachunks in
1077 // the node from their respective freelists. 1048 // the node from their respective freelists.
1758 assert_lock_strong(SpaceManager::expand_lock()); 1729 assert_lock_strong(SpaceManager::expand_lock());
1759 ChunkList* free_list = find_free_chunks_list(chunk->word_size()); 1730 ChunkList* free_list = find_free_chunks_list(chunk->word_size());
1760 chunk->set_next(free_list->head()); 1731 chunk->set_next(free_list->head());
1761 free_list->set_head(chunk); 1732 free_list->set_head(chunk);
1762 // chunk is being returned to the chunk free list 1733 // chunk is being returned to the chunk free list
1763 inc_free_chunks_total(chunk->capacity_word_size()); 1734 inc_free_chunks_total(chunk->word_size());
1764 slow_locked_verify(); 1735 slow_locked_verify();
1765 } 1736 }
1766 1737
1767 void ChunkManager::chunk_freelist_deallocate(Metachunk* chunk) { 1738 void ChunkManager::chunk_freelist_deallocate(Metachunk* chunk) {
1768 // The deallocation of a chunk originates in the freelist 1739 // The deallocation of a chunk originates in the freelist
1820 chunk->word_size(), word_size, waste); 1791 chunk->word_size(), word_size, waste);
1821 } 1792 }
1822 } 1793 }
1823 1794
1824 // Chunk is being removed from the chunks free list. 1795 // Chunk is being removed from the chunks free list.
1825 dec_free_chunks_total(chunk->capacity_word_size()); 1796 dec_free_chunks_total(chunk->word_size());
1826 1797
1827 // Remove it from the links to this freelist 1798 // Remove it from the links to this freelist
1828 chunk->set_next(NULL); 1799 chunk->set_next(NULL);
1829 chunk->set_prev(NULL); 1800 chunk->set_prev(NULL);
1830 #ifdef ASSERT 1801 #ifdef ASSERT
1831 // Chunk is no longer on any freelist. Setting to false make container_count_slow() 1802 // Chunk is no longer on any freelist. Setting to false make container_count_slow()
1832 // work. 1803 // work.
1833 chunk->set_is_free(false); 1804 chunk->set_is_tagged_free(false);
1834 #endif 1805 #endif
1835 chunk->container()->inc_container_count(); 1806 chunk->container()->inc_container_count();
1836 1807
1837 slow_locked_verify(); 1808 slow_locked_verify();
1838 return chunk; 1809 return chunk;
1960 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); 1931 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
1961 size_t sum = 0; 1932 size_t sum = 0;
1962 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { 1933 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) {
1963 Metachunk* chunk = chunks_in_use(i); 1934 Metachunk* chunk = chunks_in_use(i);
1964 while (chunk != NULL) { 1935 while (chunk != NULL) {
1965 sum += chunk->capacity_word_size(); 1936 sum += chunk->word_size();
1966 chunk = chunk->next(); 1937 chunk = chunk->next();
1967 } 1938 }
1968 } 1939 }
1969 return sum; 1940 return sum;
1970 } 1941 }
2208 assert(cur->container() != NULL, "Container should have been set"); 2179 assert(cur->container() != NULL, "Container should have been set");
2209 cur->container()->dec_container_count(); 2180 cur->container()->dec_container_count();
2210 // Capture the next link before it is changed 2181 // Capture the next link before it is changed
2211 // by the call to return_chunk_at_head(); 2182 // by the call to return_chunk_at_head();
2212 Metachunk* next = cur->next(); 2183 Metachunk* next = cur->next();
2213 cur->set_is_free(true); 2184 DEBUG_ONLY(cur->set_is_tagged_free(true);)
2214 list->return_chunk_at_head(cur); 2185 list->return_chunk_at_head(cur);
2215 cur = next; 2186 cur = next;
2216 } 2187 }
2217 } 2188 }
2218 2189
2280 // Humongous chunks are never the current chunk. 2251 // Humongous chunks are never the current chunk.
2281 Metachunk* humongous_chunks = chunks_in_use(HumongousIndex); 2252 Metachunk* humongous_chunks = chunks_in_use(HumongousIndex);
2282 2253
2283 while (humongous_chunks != NULL) { 2254 while (humongous_chunks != NULL) {
2284 #ifdef ASSERT 2255 #ifdef ASSERT
2285 humongous_chunks->set_is_free(true); 2256 humongous_chunks->set_is_tagged_free(true);
2286 #endif 2257 #endif
2287 if (TraceMetadataChunkAllocation && Verbose) { 2258 if (TraceMetadataChunkAllocation && Verbose) {
2288 gclog_or_tty->print(PTR_FORMAT " (" SIZE_FORMAT ") ", 2259 gclog_or_tty->print(PTR_FORMAT " (" SIZE_FORMAT ") ",
2289 humongous_chunks, 2260 humongous_chunks,
2290 humongous_chunks->word_size()); 2261 humongous_chunks->word_size());
2543 curr = curr->next()) { 2514 curr = curr->next()) {
2544 out->print("%d) ", i++); 2515 out->print("%d) ", i++);
2545 curr->print_on(out); 2516 curr->print_on(out);
2546 curr_total += curr->word_size(); 2517 curr_total += curr->word_size();
2547 used += curr->used_word_size(); 2518 used += curr->used_word_size();
2548 capacity += curr->capacity_word_size(); 2519 capacity += curr->word_size();
2549 waste += curr->free_word_size() + curr->overhead();; 2520 waste += curr->free_word_size() + curr->overhead();;
2550 } 2521 }
2551 } 2522 }
2552 2523
2553 if (TraceMetadataChunkAllocation && Verbose) { 2524 if (TraceMetadataChunkAllocation && Verbose) {
3394 } 3365 }
3395 } 3366 }
3396 } 3367 }
3397 3368
3398 3369
3399 Metablock* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size, 3370 MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size,
3400 bool read_only, MetaspaceObj::Type type, TRAPS) { 3371 bool read_only, MetaspaceObj::Type type, TRAPS) {
3401 if (HAS_PENDING_EXCEPTION) { 3372 if (HAS_PENDING_EXCEPTION) {
3402 assert(false, "Should not allocate with exception pending"); 3373 assert(false, "Should not allocate with exception pending");
3403 return NULL; // caller does a CHECK_NULL too 3374 return NULL; // caller does a CHECK_NULL too
3404 } 3375 }
3413 assert(type > MetaspaceObj::UnknownType && type < MetaspaceObj::_number_of_types, "sanity"); 3384 assert(type > MetaspaceObj::UnknownType && type < MetaspaceObj::_number_of_types, "sanity");
3414 Metaspace* space = read_only ? loader_data->ro_metaspace() : loader_data->rw_metaspace(); 3385 Metaspace* space = read_only ? loader_data->ro_metaspace() : loader_data->rw_metaspace();
3415 MetaWord* result = space->allocate(word_size, NonClassType); 3386 MetaWord* result = space->allocate(word_size, NonClassType);
3416 if (result == NULL) { 3387 if (result == NULL) {
3417 report_out_of_shared_space(read_only ? SharedReadOnly : SharedReadWrite); 3388 report_out_of_shared_space(read_only ? SharedReadOnly : SharedReadWrite);
3418 } else { 3389 }
3419 space->record_allocation(result, type, space->vsm()->get_raw_word_size(word_size)); 3390
3420 } 3391 space->record_allocation(result, type, space->vsm()->get_raw_word_size(word_size));
3421 return Metablock::initialize(result, word_size); 3392
3393 // Zero initialize.
3394 Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0);
3395
3396 return result;
3422 } 3397 }
3423 3398
3424 MetadataType mdtype = (type == MetaspaceObj::ClassType) ? ClassType : NonClassType; 3399 MetadataType mdtype = (type == MetaspaceObj::ClassType) ? ClassType : NonClassType;
3425 3400
3426 // Try to allocate metadata. 3401 // Try to allocate metadata.
3441 report_metadata_oome(loader_data, word_size, mdtype, THREAD); 3416 report_metadata_oome(loader_data, word_size, mdtype, THREAD);
3442 // Will not reach here. 3417 // Will not reach here.
3443 return NULL; 3418 return NULL;
3444 } 3419 }
3445 3420
3446 return Metablock::initialize(result, word_size); 3421 // Zero initialize.
3422 Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0);
3423
3424 return result;
3447 } 3425 }
3448 3426
3449 void Metaspace::report_metadata_oome(ClassLoaderData* loader_data, size_t word_size, MetadataType mdtype, TRAPS) { 3427 void Metaspace::report_metadata_oome(ClassLoaderData* loader_data, size_t word_size, MetadataType mdtype, TRAPS) {
3450 // If result is still null, we are out of memory. 3428 // If result is still null, we are out of memory.
3451 if (Verbose && TraceMetadataChunkAllocation) { 3429 if (Verbose && TraceMetadataChunkAllocation) {