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();
|