< prev index next >

src/hotspot/share/memory/metaspace.cpp

Print this page
rev 49833 : [mq]: 8202074-metaspace-retire-after-humongous-chunks-are-allocated


3389     size_t words_left = 0;
3390     size_t words_used = 0;
3391     if (current_chunk() != NULL) {
3392       words_left = current_chunk()->free_word_size();
3393       words_used = current_chunk()->used_word_size();
3394     }
3395     log_trace(gc, metaspace, freelist)("SpaceManager::grow_and_allocate for " SIZE_FORMAT " words " SIZE_FORMAT " words used " SIZE_FORMAT " words left",
3396                                        word_size, words_used, words_left);
3397   }
3398 
3399   // Get another chunk
3400   size_t chunk_word_size = calc_chunk_size(word_size);
3401   Metachunk* next = get_new_chunk(chunk_word_size);
3402 
3403   MetaWord* mem = NULL;
3404 
3405   // If a chunk was available, add it to the in-use chunk list
3406   // and do an allocation from it.
3407   if (next != NULL) {
3408     // Add to this manager's list of chunks in use.
3409     add_chunk(next, false);









3410     mem = next->allocate(word_size);
3411   }
3412 
3413   // Track metaspace memory usage statistic.
3414   track_metaspace_memory_usage();
3415 
3416   return mem;
3417 }
3418 
3419 void SpaceManager::print_on(outputStream* st) const {
3420 
3421   for (ChunkIndex i = ZeroIndex;
3422        i < NumberOfInUseLists ;
3423        i = next_chunk_index(i) ) {
3424     st->print_cr("  chunks_in_use " PTR_FORMAT " chunk size " SIZE_FORMAT,
3425                  p2i(chunks_in_use(i)),
3426                  chunks_in_use(i) == NULL ? 0 : chunks_in_use(i)->word_size());
3427   }
3428   st->print_cr("    waste:  Small " SIZE_FORMAT " Medium " SIZE_FORMAT
3429                " Humongous " SIZE_FORMAT,


3545   size_t raw_word_size = get_allocation_word_size(word_size);
3546   // Lazily create a block_freelist
3547   if (block_freelists() == NULL) {
3548     _block_freelists = new BlockFreelist();
3549   }
3550   block_freelists()->return_block(p, raw_word_size);
3551 }
3552 
3553 // Adds a chunk to the list of chunks in use.
3554 void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) {
3555 
3556   assert(new_chunk != NULL, "Should not be NULL");
3557   assert(new_chunk->next() == NULL, "Should not be on a list");
3558 
3559   new_chunk->reset_empty();
3560 
3561   // Find the correct list and and set the current
3562   // chunk for that list.
3563   ChunkIndex index = chunk_manager()->list_index(new_chunk->word_size());
3564 
3565   if (index != HumongousIndex) {
3566     retire_current_chunk();
3567     set_current_chunk(new_chunk);
3568     new_chunk->set_next(chunks_in_use(index));
3569     set_chunks_in_use(index, new_chunk);
3570   } else {
3571     // For null class loader data and DumpSharedSpaces, the first chunk isn't
3572     // small, so small will be null.  Link this first chunk as the current
3573     // chunk.
3574     if (make_current) {
3575       // Set as the current chunk but otherwise treat as a humongous chunk.


3576       set_current_chunk(new_chunk);
3577     }
3578     // Link at head.  The _current_chunk only points to a humongous chunk for
3579     // the null class loader metaspace (class and data virtual space managers)
3580     // any humongous chunks so will not point to the tail
3581     // of the humongous chunks list.
3582     new_chunk->set_next(chunks_in_use(HumongousIndex));
3583     set_chunks_in_use(HumongousIndex, new_chunk);
3584 
3585     assert(new_chunk->word_size() > medium_chunk_size(), "List inconsistency");
3586   }

3587 
3588   // Add to the running sum of capacity
3589   inc_size_metrics(new_chunk->word_size());
3590 
3591   assert(new_chunk->is_empty(), "Not ready for reuse");
3592   Log(gc, metaspace, freelist) log;
3593   if (log.is_trace()) {
3594     log.trace("SpaceManager::add_chunk: " SIZE_FORMAT ") ", sum_count_in_chunks_in_use());
3595     ResourceMark rm;
3596     LogStream ls(log.trace());
3597     new_chunk->print_on(&ls);
3598     chunk_manager()->locked_print_free_chunks(&ls);
3599   }
3600 }
3601 
3602 void SpaceManager::retire_current_chunk() {
3603   if (current_chunk() != NULL) {
3604     size_t remaining_words = current_chunk()->free_word_size();
3605     if (remaining_words >= BlockFreelist::min_dictionary_size()) {
3606       MetaWord* ptr = current_chunk()->allocate(remaining_words);


4783   }
4784 
4785   return get_space_list(NonClassType)->contains(ptr);
4786 }
4787 
4788 // ClassLoaderMetaspace
4789 
4790 ClassLoaderMetaspace::ClassLoaderMetaspace(Mutex* lock, Metaspace::MetaspaceType type) {
4791   initialize(lock, type);
4792 }
4793 
4794 ClassLoaderMetaspace::~ClassLoaderMetaspace() {
4795   delete _vsm;
4796   if (Metaspace::using_class_space()) {
4797     delete _class_vsm;
4798   }
4799 }
4800 void ClassLoaderMetaspace::initialize_first_chunk(Metaspace::MetaspaceType type, Metaspace::MetadataType mdtype) {
4801   Metachunk* chunk = get_initialization_chunk(type, mdtype);
4802   if (chunk != NULL) {
4803     // Add to this manager's list of chunks in use and current_chunk().
4804     get_space_manager(mdtype)->add_chunk(chunk, true);
4805   }
4806 }
4807 
4808 Metachunk* ClassLoaderMetaspace::get_initialization_chunk(Metaspace::MetaspaceType type, Metaspace::MetadataType mdtype) {
4809   size_t chunk_word_size = get_space_manager(mdtype)->get_initial_chunk_size(type);
4810 
4811   // Get a chunk from the chunk freelist
4812   Metachunk* chunk = Metaspace::get_chunk_manager(mdtype)->chunk_freelist_allocate(chunk_word_size);
4813 
4814   if (chunk == NULL) {
4815     chunk = Metaspace::get_space_list(mdtype)->get_new_chunk(chunk_word_size,
4816                                                   get_space_manager(mdtype)->medium_chunk_bunch());
4817   }
4818 
4819   return chunk;
4820 }
4821 
4822 void ClassLoaderMetaspace::initialize(Mutex* lock, Metaspace::MetaspaceType type) {
4823   Metaspace::verify_global_initialization();




3389     size_t words_left = 0;
3390     size_t words_used = 0;
3391     if (current_chunk() != NULL) {
3392       words_left = current_chunk()->free_word_size();
3393       words_used = current_chunk()->used_word_size();
3394     }
3395     log_trace(gc, metaspace, freelist)("SpaceManager::grow_and_allocate for " SIZE_FORMAT " words " SIZE_FORMAT " words used " SIZE_FORMAT " words left",
3396                                        word_size, words_used, words_left);
3397   }
3398 
3399   // Get another chunk
3400   size_t chunk_word_size = calc_chunk_size(word_size);
3401   Metachunk* next = get_new_chunk(chunk_word_size);
3402 
3403   MetaWord* mem = NULL;
3404 
3405   // If a chunk was available, add it to the in-use chunk list
3406   // and do an allocation from it.
3407   if (next != NULL) {
3408     // Add to this manager's list of chunks in use.
3409     // If the new chunk is humongous, it was created to serve a single large allocation. In that
3410     // case it usually makes no sense to make it the current chunk, since the next allocation would
3411     // need to allocate a new chunk anyway, while we would now prematurely retire a perfectly
3412     // good chunk which could be used for more normal allocations.
3413     bool make_current_chunk = true;
3414     if (next->get_chunk_type() == HumongousIndex &&
3415         current_chunk() != NULL) {
3416       make_current_chunk = false;
3417     }
3418     add_chunk(next, make_current_chunk);
3419     mem = next->allocate(word_size);
3420   }
3421 
3422   // Track metaspace memory usage statistic.
3423   track_metaspace_memory_usage();
3424 
3425   return mem;
3426 }
3427 
3428 void SpaceManager::print_on(outputStream* st) const {
3429 
3430   for (ChunkIndex i = ZeroIndex;
3431        i < NumberOfInUseLists ;
3432        i = next_chunk_index(i) ) {
3433     st->print_cr("  chunks_in_use " PTR_FORMAT " chunk size " SIZE_FORMAT,
3434                  p2i(chunks_in_use(i)),
3435                  chunks_in_use(i) == NULL ? 0 : chunks_in_use(i)->word_size());
3436   }
3437   st->print_cr("    waste:  Small " SIZE_FORMAT " Medium " SIZE_FORMAT
3438                " Humongous " SIZE_FORMAT,


3554   size_t raw_word_size = get_allocation_word_size(word_size);
3555   // Lazily create a block_freelist
3556   if (block_freelists() == NULL) {
3557     _block_freelists = new BlockFreelist();
3558   }
3559   block_freelists()->return_block(p, raw_word_size);
3560 }
3561 
3562 // Adds a chunk to the list of chunks in use.
3563 void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) {
3564 
3565   assert(new_chunk != NULL, "Should not be NULL");
3566   assert(new_chunk->next() == NULL, "Should not be on a list");
3567 
3568   new_chunk->reset_empty();
3569 
3570   // Find the correct list and and set the current
3571   // chunk for that list.
3572   ChunkIndex index = chunk_manager()->list_index(new_chunk->word_size());
3573 









3574   if (make_current) {
3575     // If we are to make the chunk current, retire the old current chunk and replace
3576     // it with the new chunk.
3577     retire_current_chunk();
3578     set_current_chunk(new_chunk);
3579   }






3580 
3581   // Add the new chunk at the head of its respective chunk list.
3582   new_chunk->set_next(chunks_in_use(index));
3583   set_chunks_in_use(index, new_chunk);
3584 
3585   // Add to the running sum of capacity
3586   inc_size_metrics(new_chunk->word_size());
3587 
3588   assert(new_chunk->is_empty(), "Not ready for reuse");
3589   Log(gc, metaspace, freelist) log;
3590   if (log.is_trace()) {
3591     log.trace("SpaceManager::add_chunk: " SIZE_FORMAT ") ", sum_count_in_chunks_in_use());
3592     ResourceMark rm;
3593     LogStream ls(log.trace());
3594     new_chunk->print_on(&ls);
3595     chunk_manager()->locked_print_free_chunks(&ls);
3596   }
3597 }
3598 
3599 void SpaceManager::retire_current_chunk() {
3600   if (current_chunk() != NULL) {
3601     size_t remaining_words = current_chunk()->free_word_size();
3602     if (remaining_words >= BlockFreelist::min_dictionary_size()) {
3603       MetaWord* ptr = current_chunk()->allocate(remaining_words);


4780   }
4781 
4782   return get_space_list(NonClassType)->contains(ptr);
4783 }
4784 
4785 // ClassLoaderMetaspace
4786 
4787 ClassLoaderMetaspace::ClassLoaderMetaspace(Mutex* lock, Metaspace::MetaspaceType type) {
4788   initialize(lock, type);
4789 }
4790 
4791 ClassLoaderMetaspace::~ClassLoaderMetaspace() {
4792   delete _vsm;
4793   if (Metaspace::using_class_space()) {
4794     delete _class_vsm;
4795   }
4796 }
4797 void ClassLoaderMetaspace::initialize_first_chunk(Metaspace::MetaspaceType type, Metaspace::MetadataType mdtype) {
4798   Metachunk* chunk = get_initialization_chunk(type, mdtype);
4799   if (chunk != NULL) {
4800     // Add to this manager's list of chunks in use and make it the current_chunk().
4801     get_space_manager(mdtype)->add_chunk(chunk, true);
4802   }
4803 }
4804 
4805 Metachunk* ClassLoaderMetaspace::get_initialization_chunk(Metaspace::MetaspaceType type, Metaspace::MetadataType mdtype) {
4806   size_t chunk_word_size = get_space_manager(mdtype)->get_initial_chunk_size(type);
4807 
4808   // Get a chunk from the chunk freelist
4809   Metachunk* chunk = Metaspace::get_chunk_manager(mdtype)->chunk_freelist_allocate(chunk_word_size);
4810 
4811   if (chunk == NULL) {
4812     chunk = Metaspace::get_space_list(mdtype)->get_new_chunk(chunk_word_size,
4813                                                   get_space_manager(mdtype)->medium_chunk_bunch());
4814   }
4815 
4816   return chunk;
4817 }
4818 
4819 void ClassLoaderMetaspace::initialize(Mutex* lock, Metaspace::MetaspaceType type) {
4820   Metaspace::verify_global_initialization();


< prev index next >