comparison src/share/vm/memory/metaspace.cpp @ 13001:b4aa8fc5d0d5

Merge
author ccheung
date Fri, 25 Oct 2013 22:06:43 -0700
parents 209aa13ab8c0 91a88c8450f4
children c8fc12209830 610be0309a79
comparison
equal deleted inserted replaced
13000:209aa13ab8c0 13001:b4aa8fc5d0d5
73 ClassSpecializedChunk = 128, 73 ClassSpecializedChunk = 128,
74 SpecializedChunk = 128, 74 SpecializedChunk = 128,
75 ClassSmallChunk = 256, 75 ClassSmallChunk = 256,
76 SmallChunk = 512, 76 SmallChunk = 512,
77 ClassMediumChunk = 4 * K, 77 ClassMediumChunk = 4 * K,
78 MediumChunk = 8 * K, 78 MediumChunk = 8 * K
79 HumongousChunkGranularity = 8
80 }; 79 };
81 80
82 static ChunkIndex next_chunk_index(ChunkIndex i) { 81 static ChunkIndex next_chunk_index(ChunkIndex i) {
83 assert(i < NumberOfInUseLists, "Out of bound"); 82 assert(i < NumberOfInUseLists, "Out of bound");
84 return (ChunkIndex) (i+1); 83 return (ChunkIndex) (i+1);
90 89
91 typedef class FreeList<Metachunk> ChunkList; 90 typedef class FreeList<Metachunk> ChunkList;
92 91
93 // Manages the global free lists of chunks. 92 // Manages the global free lists of chunks.
94 class ChunkManager : public CHeapObj<mtInternal> { 93 class ChunkManager : public CHeapObj<mtInternal> {
94 friend class TestVirtualSpaceNodeTest;
95 95
96 // Free list of chunks of different sizes. 96 // Free list of chunks of different sizes.
97 // SpecializedChunk 97 // SpecializedChunk
98 // SmallChunk 98 // SmallChunk
99 // MediumChunk 99 // MediumChunk
255 255
256 // The first Metachunk will be allocated at the bottom of the 256 // The first Metachunk will be allocated at the bottom of the
257 // VirtualSpace 257 // VirtualSpace
258 Metachunk* first_chunk() { return (Metachunk*) bottom(); } 258 Metachunk* first_chunk() { return (Metachunk*) bottom(); }
259 259
260 // Committed but unused space in the virtual space
261 size_t free_words_in_vs() const;
260 public: 262 public:
261 263
262 VirtualSpaceNode(size_t byte_size); 264 VirtualSpaceNode(size_t byte_size);
263 VirtualSpaceNode(ReservedSpace rs) : _top(NULL), _next(NULL), _rs(rs), _container_count(0) {} 265 VirtualSpaceNode(ReservedSpace rs) : _top(NULL), _next(NULL), _rs(rs), _container_count(0) {}
264 ~VirtualSpaceNode(); 266 ~VirtualSpaceNode();
299 #endif 301 #endif
300 302
301 // used and capacity in this single entry in the list 303 // used and capacity in this single entry in the list
302 size_t used_words_in_vs() const; 304 size_t used_words_in_vs() const;
303 size_t capacity_words_in_vs() const; 305 size_t capacity_words_in_vs() const;
304 size_t free_words_in_vs() const;
305 306
306 bool initialize(); 307 bool initialize();
307 308
308 // get space from the virtual space 309 // get space from the virtual space
309 Metachunk* take_from_committed(size_t chunk_word_size); 310 Metachunk* take_from_committed(size_t chunk_word_size);
316 bool expand_by(size_t min_words, size_t preferred_words); 317 bool expand_by(size_t min_words, size_t preferred_words);
317 318
318 // In preparation for deleting this node, remove all the chunks 319 // In preparation for deleting this node, remove all the chunks
319 // in the node from any freelist. 320 // in the node from any freelist.
320 void purge(ChunkManager* chunk_manager); 321 void purge(ChunkManager* chunk_manager);
322
323 // If an allocation doesn't fit in the current node a new node is created.
324 // Allocate chunks out of the remaining committed space in this node
325 // to avoid wasting that memory.
326 // This always adds up because all the chunk sizes are multiples of
327 // the smallest chunk size.
328 void retire(ChunkManager* chunk_manager);
321 329
322 #ifdef ASSERT 330 #ifdef ASSERT
323 // Debug support 331 // Debug support
324 void mangle(); 332 void mangle();
325 #endif 333 #endif
459 // Get another virtual space and add it to the list. This 467 // Get another virtual space and add it to the list. This
460 // is typically prompted by a failed attempt to allocate a chunk 468 // is typically prompted by a failed attempt to allocate a chunk
461 // and is typically followed by the allocation of a chunk. 469 // and is typically followed by the allocation of a chunk.
462 bool create_new_virtual_space(size_t vs_word_size); 470 bool create_new_virtual_space(size_t vs_word_size);
463 471
472 // Chunk up the unused committed space in the current
473 // virtual space and add the chunks to the free list.
474 void retire_current_virtual_space();
475
464 public: 476 public:
465 VirtualSpaceList(size_t word_size); 477 VirtualSpaceList(size_t word_size);
466 VirtualSpaceList(ReservedSpace rs); 478 VirtualSpaceList(ReservedSpace rs);
467 479
468 size_t free_bytes(); 480 size_t free_bytes();
622 }; 634 };
623 635
624 bool is_class() { return _mdtype == Metaspace::ClassType; } 636 bool is_class() { return _mdtype == Metaspace::ClassType; }
625 637
626 // Accessors 638 // Accessors
627 size_t specialized_chunk_size() { return SpecializedChunk; } 639 size_t specialized_chunk_size() { return (size_t) is_class() ? ClassSpecializedChunk : SpecializedChunk; }
628 size_t small_chunk_size() { return (size_t) is_class() ? ClassSmallChunk : SmallChunk; } 640 size_t small_chunk_size() { return (size_t) is_class() ? ClassSmallChunk : SmallChunk; }
629 size_t medium_chunk_size() { return (size_t) is_class() ? ClassMediumChunk : MediumChunk; } 641 size_t medium_chunk_size() { return (size_t) is_class() ? ClassMediumChunk : MediumChunk; }
630 size_t medium_chunk_bunch() { return medium_chunk_size() * MediumChunkMultiple; } 642 size_t medium_chunk_bunch() { return medium_chunk_size() * MediumChunkMultiple; }
643
644 size_t smallest_chunk_size() { return specialized_chunk_size(); }
631 645
632 size_t allocated_blocks_words() const { return _allocated_blocks_words; } 646 size_t allocated_blocks_words() const { return _allocated_blocks_words; }
633 size_t allocated_blocks_bytes() const { return _allocated_blocks_words * BytesPerWord; } 647 size_t allocated_blocks_bytes() const { return _allocated_blocks_words * BytesPerWord; }
634 size_t allocated_chunks_words() const { return _allocated_chunks_words; } 648 size_t allocated_chunks_words() const { return _allocated_chunks_words; }
635 size_t allocated_chunks_count() const { return _allocated_chunks_count; } 649 size_t allocated_chunks_count() const { return _allocated_chunks_count; }
1054 } 1068 }
1055 } 1069 }
1056 #endif 1070 #endif
1057 } 1071 }
1058 1072
1073 void VirtualSpaceList::retire_current_virtual_space() {
1074 assert_lock_strong(SpaceManager::expand_lock());
1075
1076 VirtualSpaceNode* vsn = current_virtual_space();
1077
1078 ChunkManager* cm = is_class() ? Metaspace::chunk_manager_class() :
1079 Metaspace::chunk_manager_metadata();
1080
1081 vsn->retire(cm);
1082 }
1083
1084 void VirtualSpaceNode::retire(ChunkManager* chunk_manager) {
1085 for (int i = (int)MediumIndex; i >= (int)ZeroIndex; --i) {
1086 ChunkIndex index = (ChunkIndex)i;
1087 size_t chunk_size = chunk_manager->free_chunks(index)->size();
1088
1089 while (free_words_in_vs() >= chunk_size) {
1090 DEBUG_ONLY(verify_container_count();)
1091 Metachunk* chunk = get_chunk_vs(chunk_size);
1092 assert(chunk != NULL, "allocation should have been successful");
1093
1094 chunk_manager->return_chunks(index, chunk);
1095 chunk_manager->inc_free_chunks_total(chunk_size);
1096 DEBUG_ONLY(verify_container_count();)
1097 }
1098 }
1099 assert(free_words_in_vs() == 0, "should be empty now");
1100 }
1101
1059 VirtualSpaceList::VirtualSpaceList(size_t word_size) : 1102 VirtualSpaceList::VirtualSpaceList(size_t word_size) :
1060 _is_class(false), 1103 _is_class(false),
1061 _virtual_space_list(NULL), 1104 _virtual_space_list(NULL),
1062 _current_virtual_space(NULL), 1105 _current_virtual_space(NULL),
1063 _reserved_words(0), 1106 _reserved_words(0),
1179 min_words, 1222 min_words,
1180 max_expansion_words); 1223 max_expansion_words);
1181 if (vs_expanded) { 1224 if (vs_expanded) {
1182 return true; 1225 return true;
1183 } 1226 }
1227 retire_current_virtual_space();
1184 1228
1185 // Get another virtual space. 1229 // Get another virtual space.
1186 size_t grow_vs_words = MAX2((size_t)VirtualSpaceSize, preferred_words); 1230 size_t grow_vs_words = MAX2((size_t)VirtualSpaceSize, preferred_words);
1187 grow_vs_words = align_size_up(grow_vs_words, Metaspace::reserve_alignment_words()); 1231 grow_vs_words = align_size_up(grow_vs_words, Metaspace::reserve_alignment_words());
1188 1232
1900 } 1944 }
1901 } else { 1945 } else {
1902 chunk_word_size = medium_chunk_size(); 1946 chunk_word_size = medium_chunk_size();
1903 } 1947 }
1904 1948
1905 // Might still need a humongous chunk. Enforce an 1949 // Might still need a humongous chunk. Enforce
1906 // eight word granularity to facilitate reuse (some 1950 // humongous allocations sizes to be aligned up to
1907 // wastage but better chance of reuse). 1951 // the smallest chunk size.
1908 size_t if_humongous_sized_chunk = 1952 size_t if_humongous_sized_chunk =
1909 align_size_up(word_size + Metachunk::overhead(), 1953 align_size_up(word_size + Metachunk::overhead(),
1910 HumongousChunkGranularity); 1954 smallest_chunk_size());
1911 chunk_word_size = 1955 chunk_word_size =
1912 MAX2((size_t) chunk_word_size, if_humongous_sized_chunk); 1956 MAX2((size_t) chunk_word_size, if_humongous_sized_chunk);
1913 1957
1914 assert(!SpaceManager::is_humongous(word_size) || 1958 assert(!SpaceManager::is_humongous(word_size) ||
1915 chunk_word_size == if_humongous_sized_chunk, 1959 chunk_word_size == if_humongous_sized_chunk,
2149 humongous_chunks, 2193 humongous_chunks,
2150 humongous_chunks->word_size()); 2194 humongous_chunks->word_size());
2151 } 2195 }
2152 assert(humongous_chunks->word_size() == (size_t) 2196 assert(humongous_chunks->word_size() == (size_t)
2153 align_size_up(humongous_chunks->word_size(), 2197 align_size_up(humongous_chunks->word_size(),
2154 HumongousChunkGranularity), 2198 smallest_chunk_size()),
2155 err_msg("Humongous chunk size is wrong: word size " SIZE_FORMAT 2199 err_msg("Humongous chunk size is wrong: word size " SIZE_FORMAT
2156 " granularity %d", 2200 " granularity %d",
2157 humongous_chunks->word_size(), HumongousChunkGranularity)); 2201 humongous_chunks->word_size(), smallest_chunk_size()));
2158 Metachunk* next_humongous_chunks = humongous_chunks->next(); 2202 Metachunk* next_humongous_chunks = humongous_chunks->next();
2159 humongous_chunks->container()->dec_container_count(); 2203 humongous_chunks->container()->dec_container_count();
2160 chunk_manager()->humongous_dictionary()->return_chunk(humongous_chunks); 2204 chunk_manager()->humongous_dictionary()->return_chunk(humongous_chunks);
2161 humongous_chunks = next_humongous_chunks; 2205 humongous_chunks = next_humongous_chunks;
2162 } 2206 }
3310 loader_data, word_size, mdtype); 3354 loader_data, word_size, mdtype);
3311 } 3355 }
3312 } 3356 }
3313 3357
3314 if (result == NULL) { 3358 if (result == NULL) {
3315 report_metadata_oome(loader_data, word_size, mdtype, THREAD); 3359 report_metadata_oome(loader_data, word_size, mdtype, CHECK_NULL);
3316 // Will not reach here.
3317 return NULL;
3318 } 3360 }
3319 3361
3320 // Zero initialize. 3362 // Zero initialize.
3321 Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0); 3363 Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0);
3322 3364
3518 3560
3519 void TestMetaspaceAux_test() { 3561 void TestMetaspaceAux_test() {
3520 TestMetaspaceAuxTest::test(); 3562 TestMetaspaceAuxTest::test();
3521 } 3563 }
3522 3564
3565 class TestVirtualSpaceNodeTest {
3566 static void chunk_up(size_t words_left, size_t& num_medium_chunks,
3567 size_t& num_small_chunks,
3568 size_t& num_specialized_chunks) {
3569 num_medium_chunks = words_left / MediumChunk;
3570 words_left = words_left % MediumChunk;
3571
3572 num_small_chunks = words_left / SmallChunk;
3573 words_left = words_left % SmallChunk;
3574 // how many specialized chunks can we get?
3575 num_specialized_chunks = words_left / SpecializedChunk;
3576 assert(words_left % SpecializedChunk == 0, "should be nothing left");
3577 }
3578
3579 public:
3580 static void test() {
3581 MutexLockerEx ml(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag);
3582 const size_t vsn_test_size_words = MediumChunk * 4;
3583 const size_t vsn_test_size_bytes = vsn_test_size_words * BytesPerWord;
3584
3585 // The chunk sizes must be multiples of eachother, or this will fail
3586 STATIC_ASSERT(MediumChunk % SmallChunk == 0);
3587 STATIC_ASSERT(SmallChunk % SpecializedChunk == 0);
3588
3589 { // No committed memory in VSN
3590 ChunkManager cm(SpecializedChunk, SmallChunk, MediumChunk);
3591 VirtualSpaceNode vsn(vsn_test_size_bytes);
3592 vsn.initialize();
3593 vsn.retire(&cm);
3594 assert(cm.sum_free_chunks_count() == 0, "did not commit any memory in the VSN");
3595 }
3596
3597 { // All of VSN is committed, half is used by chunks
3598 ChunkManager cm(SpecializedChunk, SmallChunk, MediumChunk);
3599 VirtualSpaceNode vsn(vsn_test_size_bytes);
3600 vsn.initialize();
3601 vsn.expand_by(vsn_test_size_words, vsn_test_size_words);
3602 vsn.get_chunk_vs(MediumChunk);
3603 vsn.get_chunk_vs(MediumChunk);
3604 vsn.retire(&cm);
3605 assert(cm.sum_free_chunks_count() == 2, "should have been memory left for 2 medium chunks");
3606 assert(cm.sum_free_chunks() == 2*MediumChunk, "sizes should add up");
3607 }
3608
3609 { // 4 pages of VSN is committed, some is used by chunks
3610 ChunkManager cm(SpecializedChunk, SmallChunk, MediumChunk);
3611 VirtualSpaceNode vsn(vsn_test_size_bytes);
3612 const size_t page_chunks = 4 * (size_t)os::vm_page_size() / BytesPerWord;
3613 assert(page_chunks < MediumChunk, "Test expects medium chunks to be at least 4*page_size");
3614 vsn.initialize();
3615 vsn.expand_by(page_chunks, page_chunks);
3616 vsn.get_chunk_vs(SmallChunk);
3617 vsn.get_chunk_vs(SpecializedChunk);
3618 vsn.retire(&cm);
3619
3620 // committed - used = words left to retire
3621 const size_t words_left = page_chunks - SmallChunk - SpecializedChunk;
3622
3623 size_t num_medium_chunks, num_small_chunks, num_spec_chunks;
3624 chunk_up(words_left, num_medium_chunks, num_small_chunks, num_spec_chunks);
3625
3626 assert(num_medium_chunks == 0, "should not get any medium chunks");
3627 assert(cm.sum_free_chunks_count() == (num_small_chunks + num_spec_chunks), "should be space for 3 chunks");
3628 assert(cm.sum_free_chunks() == words_left, "sizes should add up");
3629 }
3630
3631 { // Half of VSN is committed, a humongous chunk is used
3632 ChunkManager cm(SpecializedChunk, SmallChunk, MediumChunk);
3633 VirtualSpaceNode vsn(vsn_test_size_bytes);
3634 vsn.initialize();
3635 vsn.expand_by(MediumChunk * 2, MediumChunk * 2);
3636 vsn.get_chunk_vs(MediumChunk + SpecializedChunk); // Humongous chunks will be aligned up to MediumChunk + SpecializedChunk
3637 vsn.retire(&cm);
3638
3639 const size_t words_left = MediumChunk * 2 - (MediumChunk + SpecializedChunk);
3640 size_t num_medium_chunks, num_small_chunks, num_spec_chunks;
3641 chunk_up(words_left, num_medium_chunks, num_small_chunks, num_spec_chunks);
3642
3643 assert(num_medium_chunks == 0, "should not get any medium chunks");
3644 assert(cm.sum_free_chunks_count() == (num_small_chunks + num_spec_chunks), "should be space for 3 chunks");
3645 assert(cm.sum_free_chunks() == words_left, "sizes should add up");
3646 }
3647
3648 }
3649 };
3650
3651 void TestVirtualSpaceNode_test() {
3652 TestVirtualSpaceNodeTest::test();
3653 }
3654
3523 #endif 3655 #endif