Mercurial > hg > truffle
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) { |