49 const bool metaspace_slow_verify = false; |
49 const bool metaspace_slow_verify = false; |
50 |
50 |
51 // Parameters for stress mode testing |
51 // Parameters for stress mode testing |
52 const uint metadata_deallocate_a_lot_block = 10; |
52 const uint metadata_deallocate_a_lot_block = 10; |
53 const uint metadata_deallocate_a_lock_chunk = 3; |
53 const uint metadata_deallocate_a_lock_chunk = 3; |
54 size_t const allocation_from_dictionary_limit = 64 * K; |
54 size_t const allocation_from_dictionary_limit = 4 * K; |
55 |
55 |
56 MetaWord* last_allocated = 0; |
56 MetaWord* last_allocated = 0; |
57 |
57 |
58 size_t Metaspace::_class_metaspace_size; |
58 size_t Metaspace::_class_metaspace_size; |
59 |
59 |
225 // Used to manage the free list of Metablocks (a block corresponds |
225 // Used to manage the free list of Metablocks (a block corresponds |
226 // to the allocation of a quantum of metadata). |
226 // to the allocation of a quantum of metadata). |
227 class BlockFreelist VALUE_OBJ_CLASS_SPEC { |
227 class BlockFreelist VALUE_OBJ_CLASS_SPEC { |
228 BlockTreeDictionary* _dictionary; |
228 BlockTreeDictionary* _dictionary; |
229 static Metablock* initialize_free_chunk(MetaWord* p, size_t word_size); |
229 static Metablock* initialize_free_chunk(MetaWord* p, size_t word_size); |
|
230 |
|
231 // Only allocate and split from freelist if the size of the allocation |
|
232 // is at least 1/4th the size of the available block. |
|
233 const static int WasteMultiplier = 4; |
230 |
234 |
231 // Accessors |
235 // Accessors |
232 BlockTreeDictionary* dictionary() const { return _dictionary; } |
236 BlockTreeDictionary* dictionary() const { return _dictionary; } |
233 |
237 |
234 public: |
238 public: |
621 |
625 |
622 Metachunk* find_current_chunk(size_t word_size); |
626 Metachunk* find_current_chunk(size_t word_size); |
623 |
627 |
624 // Add chunk to the list of chunks in use |
628 // Add chunk to the list of chunks in use |
625 void add_chunk(Metachunk* v, bool make_current); |
629 void add_chunk(Metachunk* v, bool make_current); |
|
630 void retire_current_chunk(); |
626 |
631 |
627 Mutex* lock() const { return _lock; } |
632 Mutex* lock() const { return _lock; } |
628 |
633 |
629 const char* chunk_size_name(ChunkIndex index) const; |
634 const char* chunk_size_name(ChunkIndex index) const; |
630 |
635 |
805 // Dark matter. Too small for dictionary. |
810 // Dark matter. Too small for dictionary. |
806 return NULL; |
811 return NULL; |
807 } |
812 } |
808 |
813 |
809 Metablock* free_block = |
814 Metablock* free_block = |
810 dictionary()->get_chunk(word_size, FreeBlockDictionary<Metablock>::exactly); |
815 dictionary()->get_chunk(word_size, FreeBlockDictionary<Metablock>::atLeast); |
811 if (free_block == NULL) { |
816 if (free_block == NULL) { |
812 return NULL; |
817 return NULL; |
813 } |
818 } |
814 |
819 |
815 return (MetaWord*) free_block; |
820 const size_t block_size = free_block->size(); |
|
821 if (block_size > WasteMultiplier * word_size) { |
|
822 return_block((MetaWord*)free_block, block_size); |
|
823 return NULL; |
|
824 } |
|
825 |
|
826 MetaWord* new_block = (MetaWord*)free_block; |
|
827 assert(block_size >= word_size, "Incorrect size of block from freelist"); |
|
828 const size_t unused = block_size - word_size; |
|
829 if (unused >= TreeChunk<Metablock, FreeList>::min_size()) { |
|
830 return_block(new_block + word_size, unused); |
|
831 } |
|
832 |
|
833 return new_block; |
816 } |
834 } |
817 |
835 |
818 void BlockFreelist::print_on(outputStream* st) const { |
836 void BlockFreelist::print_on(outputStream* st) const { |
819 if (dictionary() == NULL) { |
837 if (dictionary() == NULL) { |
820 return; |
838 return; |
2276 // Find the correct list and and set the current |
2294 // Find the correct list and and set the current |
2277 // chunk for that list. |
2295 // chunk for that list. |
2278 ChunkIndex index = ChunkManager::list_index(new_chunk->word_size()); |
2296 ChunkIndex index = ChunkManager::list_index(new_chunk->word_size()); |
2279 |
2297 |
2280 if (index != HumongousIndex) { |
2298 if (index != HumongousIndex) { |
|
2299 retire_current_chunk(); |
2281 set_current_chunk(new_chunk); |
2300 set_current_chunk(new_chunk); |
2282 new_chunk->set_next(chunks_in_use(index)); |
2301 new_chunk->set_next(chunks_in_use(index)); |
2283 set_chunks_in_use(index, new_chunk); |
2302 set_chunks_in_use(index, new_chunk); |
2284 } else { |
2303 } else { |
2285 // For null class loader data and DumpSharedSpaces, the first chunk isn't |
2304 // For null class loader data and DumpSharedSpaces, the first chunk isn't |
2307 gclog_or_tty->print("SpaceManager::add_chunk: %d) ", |
2326 gclog_or_tty->print("SpaceManager::add_chunk: %d) ", |
2308 sum_count_in_chunks_in_use()); |
2327 sum_count_in_chunks_in_use()); |
2309 new_chunk->print_on(gclog_or_tty); |
2328 new_chunk->print_on(gclog_or_tty); |
2310 if (vs_list() != NULL) { |
2329 if (vs_list() != NULL) { |
2311 vs_list()->chunk_manager()->locked_print_free_chunks(tty); |
2330 vs_list()->chunk_manager()->locked_print_free_chunks(tty); |
|
2331 } |
|
2332 } |
|
2333 } |
|
2334 |
|
2335 void SpaceManager::retire_current_chunk() { |
|
2336 if (current_chunk() != NULL) { |
|
2337 size_t remaining_words = current_chunk()->free_word_size(); |
|
2338 if (remaining_words >= TreeChunk<Metablock, FreeList>::min_size()) { |
|
2339 block_freelists()->return_block(current_chunk()->allocate(remaining_words), remaining_words); |
|
2340 inc_used_metrics(remaining_words); |
2312 } |
2341 } |
2313 } |
2342 } |
2314 } |
2343 } |
2315 |
2344 |
2316 Metachunk* SpaceManager::get_new_chunk(size_t word_size, |
2345 Metachunk* SpaceManager::get_new_chunk(size_t word_size, |