50 typedef BinaryTreeDictionary<Metachunk, FreeList> ChunkTreeDictionary; |
50 typedef BinaryTreeDictionary<Metachunk, FreeList> ChunkTreeDictionary; |
51 |
51 |
52 // Set this constant to enable slow integrity checking of the free chunk lists |
52 // Set this constant to enable slow integrity checking of the free chunk lists |
53 const bool metaspace_slow_verify = false; |
53 const bool metaspace_slow_verify = false; |
54 |
54 |
55 // Parameters for stress mode testing |
|
56 const uint metadata_deallocate_a_lot_block = 10; |
|
57 const uint metadata_deallocate_a_lock_chunk = 3; |
|
58 size_t const allocation_from_dictionary_limit = 4 * K; |
55 size_t const allocation_from_dictionary_limit = 4 * K; |
59 |
56 |
60 MetaWord* last_allocated = 0; |
57 MetaWord* last_allocated = 0; |
61 |
58 |
62 size_t Metaspace::_class_metaspace_size; |
59 size_t Metaspace::_class_metaspace_size; |
147 _free_chunks[MediumIndex].set_size(medium_size); |
144 _free_chunks[MediumIndex].set_size(medium_size); |
148 } |
145 } |
149 |
146 |
150 // add or delete (return) a chunk to the global freelist. |
147 // add or delete (return) a chunk to the global freelist. |
151 Metachunk* chunk_freelist_allocate(size_t word_size); |
148 Metachunk* chunk_freelist_allocate(size_t word_size); |
152 void chunk_freelist_deallocate(Metachunk* chunk); |
|
153 |
149 |
154 // Map a size to a list index assuming that there are lists |
150 // Map a size to a list index assuming that there are lists |
155 // for special, small, medium, and humongous chunks. |
151 // for special, small, medium, and humongous chunks. |
156 static ChunkIndex list_index(size_t size); |
152 static ChunkIndex list_index(size_t size); |
157 |
153 |
181 ChunkList* free_chunks(ChunkIndex index); |
177 ChunkList* free_chunks(ChunkIndex index); |
182 |
178 |
183 // Returns the list for the given chunk word size. |
179 // Returns the list for the given chunk word size. |
184 ChunkList* find_free_chunks_list(size_t word_size); |
180 ChunkList* find_free_chunks_list(size_t word_size); |
185 |
181 |
186 // Add and remove from a list by size. Selects |
182 // Remove from a list by size. Selects list based on size of chunk. |
187 // list based on size of chunk. |
|
188 void free_chunks_put(Metachunk* chuck); |
|
189 Metachunk* free_chunks_get(size_t chunk_word_size); |
183 Metachunk* free_chunks_get(size_t chunk_word_size); |
190 |
184 |
191 // Debug support |
185 // Debug support |
192 void verify(); |
186 void verify(); |
193 void slow_verify() { |
187 void slow_verify() { |
531 }; |
525 }; |
532 }; |
526 }; |
533 |
527 |
534 class Metadebug : AllStatic { |
528 class Metadebug : AllStatic { |
535 // Debugging support for Metaspaces |
529 // Debugging support for Metaspaces |
536 static int _deallocate_block_a_lot_count; |
|
537 static int _deallocate_chunk_a_lot_count; |
|
538 static int _allocation_fail_alot_count; |
530 static int _allocation_fail_alot_count; |
539 |
531 |
540 public: |
532 public: |
541 static int deallocate_block_a_lot_count() { |
|
542 return _deallocate_block_a_lot_count; |
|
543 } |
|
544 static void set_deallocate_block_a_lot_count(int v) { |
|
545 _deallocate_block_a_lot_count = v; |
|
546 } |
|
547 static void inc_deallocate_block_a_lot_count() { |
|
548 _deallocate_block_a_lot_count++; |
|
549 } |
|
550 static int deallocate_chunk_a_lot_count() { |
|
551 return _deallocate_chunk_a_lot_count; |
|
552 } |
|
553 static void reset_deallocate_chunk_a_lot_count() { |
|
554 _deallocate_chunk_a_lot_count = 1; |
|
555 } |
|
556 static void inc_deallocate_chunk_a_lot_count() { |
|
557 _deallocate_chunk_a_lot_count++; |
|
558 } |
|
559 |
533 |
560 static void init_allocation_fail_alot_count(); |
534 static void init_allocation_fail_alot_count(); |
561 #ifdef ASSERT |
535 #ifdef ASSERT |
562 static bool test_metadata_failure(); |
536 static bool test_metadata_failure(); |
563 #endif |
537 #endif |
564 |
|
565 static void deallocate_chunk_a_lot(SpaceManager* sm, |
|
566 size_t chunk_word_size); |
|
567 static void deallocate_block_a_lot(SpaceManager* sm, |
|
568 size_t chunk_word_size); |
|
569 |
|
570 }; |
538 }; |
571 |
539 |
572 int Metadebug::_deallocate_block_a_lot_count = 0; |
|
573 int Metadebug::_deallocate_chunk_a_lot_count = 0; |
|
574 int Metadebug::_allocation_fail_alot_count = 0; |
540 int Metadebug::_allocation_fail_alot_count = 0; |
575 |
541 |
576 // SpaceManager - used by Metaspace to handle allocations |
542 // SpaceManager - used by Metaspace to handle allocations |
577 class SpaceManager : public CHeapObj<mtClass> { |
543 class SpaceManager : public CHeapObj<mtClass> { |
578 friend class Metaspace; |
544 friend class Metaspace; |
1532 } |
1498 } |
1533 } |
1499 } |
1534 |
1500 |
1535 // Metadebug methods |
1501 // Metadebug methods |
1536 |
1502 |
1537 void Metadebug::deallocate_chunk_a_lot(SpaceManager* sm, |
|
1538 size_t chunk_word_size){ |
|
1539 #ifdef ASSERT |
|
1540 VirtualSpaceList* vsl = sm->vs_list(); |
|
1541 if (MetaDataDeallocateALot && |
|
1542 Metadebug::deallocate_chunk_a_lot_count() % MetaDataDeallocateALotInterval == 0 ) { |
|
1543 Metadebug::reset_deallocate_chunk_a_lot_count(); |
|
1544 for (uint i = 0; i < metadata_deallocate_a_lock_chunk; i++) { |
|
1545 Metachunk* dummy_chunk = vsl->current_virtual_space()->take_from_committed(chunk_word_size); |
|
1546 if (dummy_chunk == NULL) { |
|
1547 break; |
|
1548 } |
|
1549 sm->chunk_manager()->chunk_freelist_deallocate(dummy_chunk); |
|
1550 |
|
1551 if (TraceMetadataChunkAllocation && Verbose) { |
|
1552 gclog_or_tty->print("Metadebug::deallocate_chunk_a_lot: %d) ", |
|
1553 sm->sum_count_in_chunks_in_use()); |
|
1554 dummy_chunk->print_on(gclog_or_tty); |
|
1555 gclog_or_tty->print_cr(" Free chunks total %d count %d", |
|
1556 sm->chunk_manager()->free_chunks_total_words(), |
|
1557 sm->chunk_manager()->free_chunks_count()); |
|
1558 } |
|
1559 } |
|
1560 } else { |
|
1561 Metadebug::inc_deallocate_chunk_a_lot_count(); |
|
1562 } |
|
1563 #endif |
|
1564 } |
|
1565 |
|
1566 void Metadebug::deallocate_block_a_lot(SpaceManager* sm, |
|
1567 size_t raw_word_size){ |
|
1568 #ifdef ASSERT |
|
1569 if (MetaDataDeallocateALot && |
|
1570 Metadebug::deallocate_block_a_lot_count() % MetaDataDeallocateALotInterval == 0 ) { |
|
1571 Metadebug::set_deallocate_block_a_lot_count(0); |
|
1572 for (uint i = 0; i < metadata_deallocate_a_lot_block; i++) { |
|
1573 MetaWord* dummy_block = sm->allocate_work(raw_word_size); |
|
1574 if (dummy_block == 0) { |
|
1575 break; |
|
1576 } |
|
1577 sm->deallocate(dummy_block, raw_word_size); |
|
1578 } |
|
1579 } else { |
|
1580 Metadebug::inc_deallocate_block_a_lot_count(); |
|
1581 } |
|
1582 #endif |
|
1583 } |
|
1584 |
|
1585 void Metadebug::init_allocation_fail_alot_count() { |
1503 void Metadebug::init_allocation_fail_alot_count() { |
1586 if (MetadataAllocationFailALot) { |
1504 if (MetadataAllocationFailALot) { |
1587 _allocation_fail_alot_count = |
1505 _allocation_fail_alot_count = |
1588 1+(long)((double)MetadataAllocationFailALotInterval*os::random()/(max_jint+1.0)); |
1506 1+(long)((double)MetadataAllocationFailALotInterval*os::random()/(max_jint+1.0)); |
1589 } |
1507 } |
1721 |
1639 |
1722 ChunkList* ChunkManager::find_free_chunks_list(size_t word_size) { |
1640 ChunkList* ChunkManager::find_free_chunks_list(size_t word_size) { |
1723 ChunkIndex index = list_index(word_size); |
1641 ChunkIndex index = list_index(word_size); |
1724 assert(index < HumongousIndex, "No humongous list"); |
1642 assert(index < HumongousIndex, "No humongous list"); |
1725 return free_chunks(index); |
1643 return free_chunks(index); |
1726 } |
|
1727 |
|
1728 void ChunkManager::free_chunks_put(Metachunk* chunk) { |
|
1729 assert_lock_strong(SpaceManager::expand_lock()); |
|
1730 ChunkList* free_list = find_free_chunks_list(chunk->word_size()); |
|
1731 chunk->set_next(free_list->head()); |
|
1732 free_list->set_head(chunk); |
|
1733 // chunk is being returned to the chunk free list |
|
1734 inc_free_chunks_total(chunk->word_size()); |
|
1735 slow_locked_verify(); |
|
1736 } |
|
1737 |
|
1738 void ChunkManager::chunk_freelist_deallocate(Metachunk* chunk) { |
|
1739 // The deallocation of a chunk originates in the freelist |
|
1740 // manangement code for a Metaspace and does not hold the |
|
1741 // lock. |
|
1742 assert(chunk != NULL, "Deallocating NULL"); |
|
1743 assert_lock_strong(SpaceManager::expand_lock()); |
|
1744 slow_locked_verify(); |
|
1745 if (TraceMetadataChunkAllocation) { |
|
1746 gclog_or_tty->print_cr("ChunkManager::chunk_freelist_deallocate: chunk " |
|
1747 PTR_FORMAT " size " SIZE_FORMAT, |
|
1748 chunk, chunk->word_size()); |
|
1749 } |
|
1750 free_chunks_put(chunk); |
|
1751 } |
1644 } |
1752 |
1645 |
1753 Metachunk* ChunkManager::free_chunks_get(size_t word_size) { |
1646 Metachunk* ChunkManager::free_chunks_get(size_t word_size) { |
1754 assert_lock_strong(SpaceManager::expand_lock()); |
1647 assert_lock_strong(SpaceManager::expand_lock()); |
1755 |
1648 |
2067 |
1960 |
2068 // Get another chunk out of the virtual space |
1961 // Get another chunk out of the virtual space |
2069 size_t grow_chunks_by_words = calc_chunk_size(word_size); |
1962 size_t grow_chunks_by_words = calc_chunk_size(word_size); |
2070 Metachunk* next = get_new_chunk(word_size, grow_chunks_by_words); |
1963 Metachunk* next = get_new_chunk(word_size, grow_chunks_by_words); |
2071 |
1964 |
2072 if (next != NULL) { |
|
2073 Metadebug::deallocate_chunk_a_lot(this, grow_chunks_by_words); |
|
2074 } |
|
2075 |
|
2076 MetaWord* mem = NULL; |
1965 MetaWord* mem = NULL; |
2077 |
1966 |
2078 // If a chunk was available, add it to the in-use chunk list |
1967 // If a chunk was available, add it to the in-use chunk list |
2079 // and do an allocation from it. |
1968 // and do an allocation from it. |
2080 if (next != NULL) { |
1969 if (next != NULL) { |