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); |
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), |
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 } |
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 |