Mercurial > hg > graal-jvmci-8
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) { |