90 // Each SpaceManager maintains a |
89 // Each SpaceManager maintains a |
91 // list of the chunks it is using and the current chunk. The current |
90 // list of the chunks it is using and the current chunk. The current |
92 // chunk is the chunk from which allocations are done. Space freed in |
91 // chunk is the chunk from which allocations are done. Space freed in |
93 // a chunk is placed on the free list of blocks (BlockFreelist) and |
92 // a chunk is placed on the free list of blocks (BlockFreelist) and |
94 // reused from there. |
93 // reused from there. |
95 // |
|
96 // Future modification |
|
97 // |
|
98 // The Metachunk can conceivable be replaced by the Chunk in |
|
99 // allocation.hpp. Note that the latter Chunk is the space for |
|
100 // allocation (allocations from the chunk are out of the space in |
|
101 // the Chunk after the header for the Chunk) where as Metachunks |
|
102 // point to space in a VirtualSpace. To replace Metachunks with |
|
103 // Chunks, change Chunks so that they can be allocated out of a VirtualSpace. |
|
104 size_t Metablock::_min_block_byte_size = sizeof(Metablock); |
|
105 #ifdef ASSERT |
|
106 size_t Metablock::_overhead = |
|
107 Chunk::aligned_overhead_size(sizeof(Metablock)) / BytesPerWord; |
|
108 #else |
|
109 size_t Metablock::_overhead = 0; |
|
110 #endif |
|
111 |
94 |
112 // Pointer to list of Metachunks. |
95 // Pointer to list of Metachunks. |
113 class ChunkList VALUE_OBJ_CLASS_SPEC { |
96 class ChunkList VALUE_OBJ_CLASS_SPEC { |
114 // List of free chunks |
97 // List of free chunks |
115 Metachunk* _head; |
98 Metachunk* _head; |
621 void dump(outputStream* const out) const; |
604 void dump(outputStream* const out) const; |
622 void print_on(outputStream* st) const; |
605 void print_on(outputStream* st) const; |
623 void locked_print_chunks_in_use_on(outputStream* st) const; |
606 void locked_print_chunks_in_use_on(outputStream* st) const; |
624 |
607 |
625 void verify(); |
608 void verify(); |
|
609 void verify_chunk_size(Metachunk* chunk); |
626 NOT_PRODUCT(void mangle_freed_chunks();) |
610 NOT_PRODUCT(void mangle_freed_chunks();) |
627 #ifdef ASSERT |
611 #ifdef ASSERT |
628 void verify_allocation_total(); |
612 void verify_allocation_total(); |
629 #endif |
613 #endif |
630 }; |
614 }; |
631 |
615 |
632 uint const SpaceManager::_small_chunk_limit = 4; |
616 uint const SpaceManager::_small_chunk_limit = 4; |
633 |
|
634 |
|
635 |
617 |
636 const char* SpaceManager::_expand_lock_name = |
618 const char* SpaceManager::_expand_lock_name = |
637 "SpaceManager chunk allocation lock"; |
619 "SpaceManager chunk allocation lock"; |
638 const int SpaceManager::_expand_lock_rank = Monitor::leaf - 1; |
620 const int SpaceManager::_expand_lock_rank = Monitor::leaf - 1; |
639 Mutex* const SpaceManager::_expand_lock = |
621 Mutex* const SpaceManager::_expand_lock = |
640 new Mutex(SpaceManager::_expand_lock_rank, |
622 new Mutex(SpaceManager::_expand_lock_rank, |
641 SpaceManager::_expand_lock_name, |
623 SpaceManager::_expand_lock_name, |
642 Mutex::_allow_vm_block_flag); |
624 Mutex::_allow_vm_block_flag); |
643 |
|
644 size_t Metachunk::_overhead = |
|
645 Chunk::aligned_overhead_size(sizeof(Metachunk)) / BytesPerWord; |
|
646 |
|
647 // New blocks returned by the Metaspace are zero initialized. |
|
648 // We should fix the constructors to not assume this instead. |
|
649 Metablock* Metablock::initialize(MetaWord* p, size_t word_size) { |
|
650 if (p == NULL) { |
|
651 return NULL; |
|
652 } |
|
653 |
|
654 Metablock* result = (Metablock*) p; |
|
655 |
|
656 // Clear the memory |
|
657 Copy::fill_to_aligned_words((HeapWord*)result, word_size); |
|
658 #ifdef ASSERT |
|
659 result->set_word_size(word_size); |
|
660 #endif |
|
661 return result; |
|
662 } |
|
663 |
|
664 // Metachunk methods |
|
665 |
|
666 Metachunk* Metachunk::initialize(MetaWord* ptr, size_t word_size) { |
|
667 // Set bottom, top, and end. Allow space for the Metachunk itself |
|
668 Metachunk* chunk = (Metachunk*) ptr; |
|
669 |
|
670 MetaWord* chunk_bottom = ptr + _overhead; |
|
671 chunk->set_bottom(ptr); |
|
672 chunk->set_top(chunk_bottom); |
|
673 MetaWord* chunk_end = ptr + word_size; |
|
674 assert(chunk_end > chunk_bottom, "Chunk must be too small"); |
|
675 chunk->set_end(chunk_end); |
|
676 chunk->set_next(NULL); |
|
677 chunk->set_word_size(word_size); |
|
678 #ifdef ASSERT |
|
679 size_t data_word_size = pointer_delta(chunk_end, chunk_bottom, sizeof(MetaWord)); |
|
680 Copy::fill_to_words((HeapWord*) chunk_bottom, data_word_size, metadata_chunk_initialize); |
|
681 #endif |
|
682 return chunk; |
|
683 } |
|
684 |
|
685 |
|
686 MetaWord* Metachunk::allocate(size_t word_size) { |
|
687 MetaWord* result = NULL; |
|
688 // If available, bump the pointer to allocate. |
|
689 if (free_word_size() >= word_size) { |
|
690 result = _top; |
|
691 _top = _top + word_size; |
|
692 } |
|
693 return result; |
|
694 } |
|
695 |
|
696 // _bottom points to the start of the chunk including the overhead. |
|
697 size_t Metachunk::used_word_size() { |
|
698 return pointer_delta(_top, _bottom, sizeof(MetaWord)); |
|
699 } |
|
700 |
|
701 size_t Metachunk::free_word_size() { |
|
702 return pointer_delta(_end, _top, sizeof(MetaWord)); |
|
703 } |
|
704 |
|
705 size_t Metachunk::capacity_word_size() { |
|
706 return pointer_delta(_end, _bottom, sizeof(MetaWord)); |
|
707 } |
|
708 |
|
709 void Metachunk::print_on(outputStream* st) const { |
|
710 st->print_cr("Metachunk:" |
|
711 " bottom " PTR_FORMAT " top " PTR_FORMAT |
|
712 " end " PTR_FORMAT " size " SIZE_FORMAT, |
|
713 bottom(), top(), end(), word_size()); |
|
714 } |
|
715 |
|
716 #ifndef PRODUCT |
|
717 void Metachunk::mangle() { |
|
718 // Mangle the payload of the chunk and not the links that |
|
719 // maintain list of chunks. |
|
720 HeapWord* start = (HeapWord*)(bottom() + overhead()); |
|
721 size_t word_size = capacity_word_size() - overhead(); |
|
722 Copy::fill_to_words(start, word_size, metadata_chunk_initialize); |
|
723 } |
|
724 #endif // PRODUCT |
|
725 |
|
726 void Metachunk::verify() { |
|
727 #ifdef ASSERT |
|
728 // Cannot walk through the blocks unless the blocks have |
|
729 // headers with sizes. |
|
730 assert(_bottom <= _top && |
|
731 _top <= _end, |
|
732 "Chunk has been smashed"); |
|
733 assert(SpaceManager::is_humongous(_word_size) || |
|
734 _word_size == SpaceManager::MediumChunk || |
|
735 _word_size == SpaceManager::SmallChunk, |
|
736 "Chunk size is wrong"); |
|
737 #endif |
|
738 return; |
|
739 } |
|
740 |
625 |
741 // BlockFreelist methods |
626 // BlockFreelist methods |
742 |
627 |
743 BlockFreelist::BlockFreelist() : _dictionary(NULL) {} |
628 BlockFreelist::BlockFreelist() : _dictionary(NULL) {} |
744 |
629 |