src/share/vm/memory/metaspace.cpp

changeset 7860
afc7b3416dc6
parent 7300
03e6d34be1f5
child 7867
57d4971ff1df
     1.1 --- a/src/share/vm/memory/metaspace.cpp	Wed Jun 03 14:22:57 2015 +0200
     1.2 +++ b/src/share/vm/memory/metaspace.cpp	Tue Jun 02 10:09:08 2015 -0400
     1.3 @@ -622,8 +622,7 @@
     1.4    Metachunk* _chunks_in_use[NumberOfInUseLists];
     1.5    Metachunk* _current_chunk;
     1.6  
     1.7 -  // Number of small chunks to allocate to a manager
     1.8 -  // If class space manager, small chunks are unlimited
     1.9 +  // Maximum number of small chunks to allocate to a SpaceManager
    1.10    static uint const _small_chunk_limit;
    1.11  
    1.12    // Sum of all space in allocated chunks
    1.13 @@ -737,6 +736,8 @@
    1.14    // Block allocation and deallocation.
    1.15    // Allocates a block from the current chunk
    1.16    MetaWord* allocate(size_t word_size);
    1.17 +  // Allocates a block from a small chunk
    1.18 +  MetaWord* get_small_chunk_and_allocate(size_t word_size);
    1.19  
    1.20    // Helper for allocations
    1.21    MetaWord* allocate_work(size_t word_size);
    1.22 @@ -2031,9 +2032,8 @@
    1.23  size_t SpaceManager::calc_chunk_size(size_t word_size) {
    1.24  
    1.25    // Decide between a small chunk and a medium chunk.  Up to
    1.26 -  // _small_chunk_limit small chunks can be allocated but
    1.27 -  // once a medium chunk has been allocated, no more small
    1.28 -  // chunks will be allocated.
    1.29 +  // _small_chunk_limit small chunks can be allocated.
    1.30 +  // After that a medium chunk is preferred.
    1.31    size_t chunk_word_size;
    1.32    if (chunks_in_use(MediumIndex) == NULL &&
    1.33        sum_count_in_chunks_in_use(SmallIndex) < _small_chunk_limit) {
    1.34 @@ -2101,7 +2101,7 @@
    1.35                              word_size, words_used, words_left);
    1.36    }
    1.37  
    1.38 -  // Get another chunk out of the virtual space
    1.39 +  // Get another chunk
    1.40    size_t grow_chunks_by_words = calc_chunk_size(word_size);
    1.41    Metachunk* next = get_new_chunk(word_size, grow_chunks_by_words);
    1.42  
    1.43 @@ -2432,6 +2432,43 @@
    1.44    return next;
    1.45  }
    1.46  
    1.47 +/*
    1.48 + * The policy is to allocate up to _small_chunk_limit small chunks
    1.49 + * after which only medium chunks are allocated.  This is done to
    1.50 + * reduce fragmentation.  In some cases, this can result in a lot
    1.51 + * of small chunks being allocated to the point where it's not
    1.52 + * possible to expand.  If this happens, there may be no medium chunks
    1.53 + * available and OOME would be thrown.  Instead of doing that,
    1.54 + * if the allocation request size fits in a small chunk, an attempt
    1.55 + * will be made to allocate a small chunk.
    1.56 + */
    1.57 +MetaWord* SpaceManager::get_small_chunk_and_allocate(size_t word_size) {
    1.58 +  if (word_size + Metachunk::overhead() > small_chunk_size()) {
    1.59 +    return NULL;
    1.60 +  }
    1.61 +
    1.62 +  MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
    1.63 +  MutexLockerEx cl1(expand_lock(), Mutex::_no_safepoint_check_flag);
    1.64 +
    1.65 +  Metachunk* chunk = chunk_manager()->chunk_freelist_allocate(small_chunk_size());
    1.66 +
    1.67 +  MetaWord* mem = NULL;
    1.68 +
    1.69 +  if (chunk != NULL) {
    1.70 +    // Add chunk to the in-use chunk list and do an allocation from it.
    1.71 +    // Add to this manager's list of chunks in use.
    1.72 +    add_chunk(chunk, false);
    1.73 +    mem = chunk->allocate(word_size);
    1.74 +
    1.75 +    inc_used_metrics(word_size);
    1.76 +
    1.77 +    // Track metaspace memory usage statistic.
    1.78 +    track_metaspace_memory_usage();
    1.79 +  }
    1.80 +
    1.81 +  return mem;
    1.82 +}
    1.83 +
    1.84  MetaWord* SpaceManager::allocate(size_t word_size) {
    1.85    MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
    1.86  
    1.87 @@ -3511,7 +3548,18 @@
    1.88    }
    1.89  
    1.90    if (result == NULL) {
    1.91 -    report_metadata_oome(loader_data, word_size, type, mdtype, CHECK_NULL);
    1.92 +    SpaceManager* sm;
    1.93 +    if (is_class_space_allocation(mdtype)) {
    1.94 +      sm = loader_data->metaspace_non_null()->class_vsm();
    1.95 +    } else {
    1.96 +      sm = loader_data->metaspace_non_null()->vsm();
    1.97 +    }
    1.98 +
    1.99 +    result = sm->get_small_chunk_and_allocate(word_size);
   1.100 +
   1.101 +    if (result == NULL) {
   1.102 +      report_metadata_oome(loader_data, word_size, type, mdtype, CHECK_NULL);
   1.103 +    }
   1.104    }
   1.105  
   1.106    // Zero initialize.

mercurial