comparison src/share/vm/memory/metaspace.cpp @ 6969:6bc207d87e5d

7200229: NPG: possible performance issue exposed by closed/runtime/6559877/Test6559877.java Summary: Reduce the amount of calls to ChunkManager verification code Reviewed-by: jmasa, coleenp
author mgerdin
date Fri, 09 Nov 2012 00:38:31 +0100
parents 685df3c6f84b
children 59c790074993 90273fc0a981
comparison
equal deleted inserted replaced
6931:ca8168203393 6969:6bc207d87e5d
40 #include "utilities/copy.hpp" 40 #include "utilities/copy.hpp"
41 #include "utilities/debug.hpp" 41 #include "utilities/debug.hpp"
42 42
43 typedef BinaryTreeDictionary<Metablock, FreeList> BlockTreeDictionary; 43 typedef BinaryTreeDictionary<Metablock, FreeList> BlockTreeDictionary;
44 typedef BinaryTreeDictionary<Metachunk, FreeList> ChunkTreeDictionary; 44 typedef BinaryTreeDictionary<Metachunk, FreeList> ChunkTreeDictionary;
45 // Define this macro to enable slow integrity checking of
46 // the free chunk lists
47 const bool metaspace_slow_verify = false;
48
45 49
46 // Parameters for stress mode testing 50 // Parameters for stress mode testing
47 const uint metadata_deallocate_a_lot_block = 10; 51 const uint metadata_deallocate_a_lot_block = 10;
48 const uint metadata_deallocate_a_lock_chunk = 3; 52 const uint metadata_deallocate_a_lock_chunk = 3;
49 size_t const allocation_from_dictionary_limit = 64 * K; 53 size_t const allocation_from_dictionary_limit = 64 * K;
159 163
160 size_t sum_free_chunks(); 164 size_t sum_free_chunks();
161 size_t sum_free_chunks_count(); 165 size_t sum_free_chunks_count();
162 166
163 void locked_verify_free_chunks_total(); 167 void locked_verify_free_chunks_total();
168 void slow_locked_verify_free_chunks_total() {
169 if (metaspace_slow_verify) {
170 locked_verify_free_chunks_total();
171 }
172 }
164 void locked_verify_free_chunks_count(); 173 void locked_verify_free_chunks_count();
174 void slow_locked_verify_free_chunks_count() {
175 if (metaspace_slow_verify) {
176 locked_verify_free_chunks_count();
177 }
178 }
165 void verify_free_chunks_count(); 179 void verify_free_chunks_count();
166 180
167 public: 181 public:
168 182
169 ChunkManager() : _free_chunks_total(0), _free_chunks_count(0) {} 183 ChunkManager() : _free_chunks_total(0), _free_chunks_count(0) {}
199 void free_chunks_put(Metachunk* chuck); 213 void free_chunks_put(Metachunk* chuck);
200 Metachunk* free_chunks_get(size_t chunk_word_size); 214 Metachunk* free_chunks_get(size_t chunk_word_size);
201 215
202 // Debug support 216 // Debug support
203 void verify(); 217 void verify();
218 void slow_verify() {
219 if (metaspace_slow_verify) {
220 verify();
221 }
222 }
204 void locked_verify(); 223 void locked_verify();
224 void slow_locked_verify() {
225 if (metaspace_slow_verify) {
226 locked_verify();
227 }
228 }
205 void verify_free_chunks_total(); 229 void verify_free_chunks_total();
206 230
207 void locked_print_free_chunks(outputStream* st); 231 void locked_print_free_chunks(outputStream* st);
208 void locked_print_sum_free_chunks(outputStream* st); 232 void locked_print_sum_free_chunks(outputStream* st);
209 233
1505 size_t ChunkManager::free_chunks_total() { 1529 size_t ChunkManager::free_chunks_total() {
1506 #ifdef ASSERT 1530 #ifdef ASSERT
1507 if (!UseConcMarkSweepGC && !SpaceManager::expand_lock()->is_locked()) { 1531 if (!UseConcMarkSweepGC && !SpaceManager::expand_lock()->is_locked()) {
1508 MutexLockerEx cl(SpaceManager::expand_lock(), 1532 MutexLockerEx cl(SpaceManager::expand_lock(),
1509 Mutex::_no_safepoint_check_flag); 1533 Mutex::_no_safepoint_check_flag);
1510 locked_verify_free_chunks_total(); 1534 slow_locked_verify_free_chunks_total();
1511 } 1535 }
1512 #endif 1536 #endif
1513 return _free_chunks_total; 1537 return _free_chunks_total;
1514 } 1538 }
1515 1539
1522 if (!UseConcMarkSweepGC && !SpaceManager::expand_lock()->is_locked()) { 1546 if (!UseConcMarkSweepGC && !SpaceManager::expand_lock()->is_locked()) {
1523 MutexLockerEx cl(SpaceManager::expand_lock(), 1547 MutexLockerEx cl(SpaceManager::expand_lock(),
1524 Mutex::_no_safepoint_check_flag); 1548 Mutex::_no_safepoint_check_flag);
1525 // This lock is only needed in debug because the verification 1549 // This lock is only needed in debug because the verification
1526 // of the _free_chunks_totals walks the list of free chunks 1550 // of the _free_chunks_totals walks the list of free chunks
1527 locked_verify_free_chunks_count(); 1551 slow_locked_verify_free_chunks_count();
1528 } 1552 }
1529 #endif 1553 #endif
1530 return _free_chunks_count; 1554 return _free_chunks_count;
1531 } 1555 }
1532 1556
1533 void ChunkManager::locked_verify_free_chunks_total() { 1557 void ChunkManager::locked_verify_free_chunks_total() {
1534 assert_lock_strong(SpaceManager::expand_lock()); 1558 assert_lock_strong(SpaceManager::expand_lock());
1535 assert(sum_free_chunks() == _free_chunks_total, 1559 assert(sum_free_chunks() == _free_chunks_total,
1559 locked_verify_free_chunks_count(); 1583 locked_verify_free_chunks_count();
1560 #endif 1584 #endif
1561 } 1585 }
1562 1586
1563 void ChunkManager::verify() { 1587 void ChunkManager::verify() {
1564 #ifdef ASSERT 1588 MutexLockerEx cl(SpaceManager::expand_lock(),
1565 if (!UseConcMarkSweepGC) { 1589 Mutex::_no_safepoint_check_flag);
1566 MutexLockerEx cl(SpaceManager::expand_lock(), 1590 locked_verify();
1567 Mutex::_no_safepoint_check_flag);
1568 locked_verify_free_chunks_total();
1569 locked_verify_free_chunks_count();
1570 }
1571 #endif
1572 } 1591 }
1573 1592
1574 void ChunkManager::locked_verify() { 1593 void ChunkManager::locked_verify() {
1575 locked_verify_free_chunks_count(); 1594 locked_verify_free_chunks_count();
1576 locked_verify_free_chunks_total(); 1595 locked_verify_free_chunks_total();
1640 ChunkList* free_list = find_free_chunks_list(chunk->word_size()); 1659 ChunkList* free_list = find_free_chunks_list(chunk->word_size());
1641 chunk->set_next(free_list->head()); 1660 chunk->set_next(free_list->head());
1642 free_list->set_head(chunk); 1661 free_list->set_head(chunk);
1643 // chunk is being returned to the chunk free list 1662 // chunk is being returned to the chunk free list
1644 inc_free_chunks_total(chunk->capacity_word_size()); 1663 inc_free_chunks_total(chunk->capacity_word_size());
1645 locked_verify(); 1664 slow_locked_verify();
1646 } 1665 }
1647 1666
1648 void ChunkManager::chunk_freelist_deallocate(Metachunk* chunk) { 1667 void ChunkManager::chunk_freelist_deallocate(Metachunk* chunk) {
1649 // The deallocation of a chunk originates in the freelist 1668 // The deallocation of a chunk originates in the freelist
1650 // manangement code for a Metaspace and does not hold the 1669 // manangement code for a Metaspace and does not hold the
1651 // lock. 1670 // lock.
1652 assert(chunk != NULL, "Deallocating NULL"); 1671 assert(chunk != NULL, "Deallocating NULL");
1653 // MutexLockerEx fcl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag); 1672 assert_lock_strong(SpaceManager::expand_lock());
1654 locked_verify(); 1673 slow_locked_verify();
1655 if (TraceMetadataChunkAllocation) { 1674 if (TraceMetadataChunkAllocation) {
1656 tty->print_cr("ChunkManager::chunk_freelist_deallocate: chunk " 1675 tty->print_cr("ChunkManager::chunk_freelist_deallocate: chunk "
1657 PTR_FORMAT " size " SIZE_FORMAT, 1676 PTR_FORMAT " size " SIZE_FORMAT,
1658 chunk, chunk->word_size()); 1677 chunk, chunk->word_size());
1659 } 1678 }
1661 } 1680 }
1662 1681
1663 Metachunk* ChunkManager::free_chunks_get(size_t word_size) { 1682 Metachunk* ChunkManager::free_chunks_get(size_t word_size) {
1664 assert_lock_strong(SpaceManager::expand_lock()); 1683 assert_lock_strong(SpaceManager::expand_lock());
1665 1684
1666 locked_verify(); 1685 slow_locked_verify();
1667 1686
1668 Metachunk* chunk = NULL; 1687 Metachunk* chunk = NULL;
1669 if (!SpaceManager::is_humongous(word_size)) { 1688 if (!SpaceManager::is_humongous(word_size)) {
1670 ChunkList* free_list = find_free_chunks_list(word_size); 1689 ChunkList* free_list = find_free_chunks_list(word_size);
1671 assert(free_list != NULL, "Sanity check"); 1690 assert(free_list != NULL, "Sanity check");
1706 #ifdef ASSERT 1725 #ifdef ASSERT
1707 chunk->set_is_free(false); 1726 chunk->set_is_free(false);
1708 #endif 1727 #endif
1709 } 1728 }
1710 } 1729 }
1711 locked_verify(); 1730 slow_locked_verify();
1712 return chunk; 1731 return chunk;
1713 } 1732 }
1714 1733
1715 Metachunk* ChunkManager::chunk_freelist_allocate(size_t word_size) { 1734 Metachunk* ChunkManager::chunk_freelist_allocate(size_t word_size) {
1716 assert_lock_strong(SpaceManager::expand_lock()); 1735 assert_lock_strong(SpaceManager::expand_lock());
1717 locked_verify(); 1736 slow_locked_verify();
1718 1737
1719 // Take from the beginning of the list 1738 // Take from the beginning of the list
1720 Metachunk* chunk = free_chunks_get(word_size); 1739 Metachunk* chunk = free_chunks_get(word_size);
1721 if (chunk == NULL) { 1740 if (chunk == NULL) {
1722 return NULL; 1741 return NULL;
1957 MutexLockerEx fcl(SpaceManager::expand_lock(), 1976 MutexLockerEx fcl(SpaceManager::expand_lock(),
1958 Mutex::_no_safepoint_check_flag); 1977 Mutex::_no_safepoint_check_flag);
1959 1978
1960 ChunkManager* chunk_manager = vs_list()->chunk_manager(); 1979 ChunkManager* chunk_manager = vs_list()->chunk_manager();
1961 1980
1962 chunk_manager->locked_verify(); 1981 chunk_manager->slow_locked_verify();
1963 1982
1964 if (TraceMetadataChunkAllocation && Verbose) { 1983 if (TraceMetadataChunkAllocation && Verbose) {
1965 gclog_or_tty->print_cr("~SpaceManager(): " PTR_FORMAT, this); 1984 gclog_or_tty->print_cr("~SpaceManager(): " PTR_FORMAT, this);
1966 locked_print_chunks_in_use_on(gclog_or_tty); 1985 locked_print_chunks_in_use_on(gclog_or_tty);
1967 } 1986 }
2013 Metachunk* next_humongous_chunks = humongous_chunks->next(); 2032 Metachunk* next_humongous_chunks = humongous_chunks->next();
2014 chunk_manager->humongous_dictionary()->return_chunk(humongous_chunks); 2033 chunk_manager->humongous_dictionary()->return_chunk(humongous_chunks);
2015 humongous_chunks = next_humongous_chunks; 2034 humongous_chunks = next_humongous_chunks;
2016 } 2035 }
2017 set_chunks_in_use(HumongousIndex, NULL); 2036 set_chunks_in_use(HumongousIndex, NULL);
2018 chunk_manager->locked_verify(); 2037 chunk_manager->slow_locked_verify();
2019 } 2038 }
2020 2039
2021 void SpaceManager::deallocate(MetaWord* p, size_t word_size) { 2040 void SpaceManager::deallocate(MetaWord* p, size_t word_size) {
2022 assert_lock_strong(_lock); 2041 assert_lock_strong(_lock);
2023 size_t min_size = TreeChunk<Metablock, FreeList>::min_size(); 2042 size_t min_size = TreeChunk<Metablock, FreeList>::min_size();
2328 2347
2329 size_t MetaspaceAux::free_chunks_total(Metaspace::MetadataType mdtype) { 2348 size_t MetaspaceAux::free_chunks_total(Metaspace::MetadataType mdtype) {
2330 ChunkManager* chunk = (mdtype == Metaspace::ClassType) ? 2349 ChunkManager* chunk = (mdtype == Metaspace::ClassType) ?
2331 Metaspace::class_space_list()->chunk_manager() : 2350 Metaspace::class_space_list()->chunk_manager() :
2332 Metaspace::space_list()->chunk_manager(); 2351 Metaspace::space_list()->chunk_manager();
2333 2352 chunk->slow_verify();
2334 chunk->verify_free_chunks_total();
2335 return chunk->free_chunks_total(); 2353 return chunk->free_chunks_total();
2336 } 2354 }
2337 2355
2338 size_t MetaspaceAux::free_chunks_total_in_bytes(Metaspace::MetadataType mdtype) { 2356 size_t MetaspaceAux::free_chunks_total_in_bytes(Metaspace::MetadataType mdtype) {
2339 return free_chunks_total(mdtype) * BytesPerWord; 2357 return free_chunks_total(mdtype) * BytesPerWord;
2433 out->print("data space: "); print_on(out, Metaspace::NonClassType); 2451 out->print("data space: "); print_on(out, Metaspace::NonClassType);
2434 out->print("class space: "); print_on(out, Metaspace::ClassType); 2452 out->print("class space: "); print_on(out, Metaspace::ClassType);
2435 print_waste(out); 2453 print_waste(out);
2436 } 2454 }
2437 2455
2456 void MetaspaceAux::verify_free_chunks() {
2457 Metaspace::space_list()->chunk_manager()->verify();
2458 Metaspace::class_space_list()->chunk_manager()->verify();
2459 }
2460
2438 // Metaspace methods 2461 // Metaspace methods
2439 2462
2440 size_t Metaspace::_first_chunk_word_size = 0; 2463 size_t Metaspace::_first_chunk_word_size = 0;
2441 2464
2442 Metaspace::Metaspace(Mutex* lock, size_t word_size) { 2465 Metaspace::Metaspace(Mutex* lock, size_t word_size) {