Merge

Mon, 21 Oct 2013 01:04:01 -0700

author
stefank
date
Mon, 21 Oct 2013 01:04:01 -0700
changeset 6007
3dd24766da44
parent 6006
a1b05d4a6fd0
parent 6005
91a88c8450f4
child 6008
2fab5b7e6140

Merge

     1.1 --- a/src/share/vm/gc_implementation/shared/vmGCOperations.cpp	Mon Oct 21 09:34:10 2013 +0200
     1.2 +++ b/src/share/vm/gc_implementation/shared/vmGCOperations.cpp	Mon Oct 21 01:04:01 2013 -0700
     1.3 @@ -211,7 +211,7 @@
     1.4    // a GC that freed space for the allocation.
     1.5    if (!MetadataAllocationFailALot) {
     1.6      _result = _loader_data->metaspace_non_null()->allocate(_size, _mdtype);
     1.7 -    }
     1.8 +  }
     1.9  
    1.10    if (_result == NULL) {
    1.11      if (UseConcMarkSweepGC) {
    1.12 @@ -223,9 +223,7 @@
    1.13          _loader_data->metaspace_non_null()->expand_and_allocate(_size, _mdtype);
    1.14      }
    1.15      if (_result == NULL) {
    1.16 -      // Don't clear the soft refs.  This GC is for reclaiming metadata
    1.17 -      // and is unrelated to the fullness of the Java heap which should
    1.18 -      // be the criteria for clearing SoftReferences.
    1.19 +      // Don't clear the soft refs yet.
    1.20        if (Verbose && PrintGCDetails && UseConcMarkSweepGC) {
    1.21          gclog_or_tty->print_cr("\nCMS full GC for Metaspace");
    1.22        }
    1.23 @@ -235,7 +233,7 @@
    1.24        _result =
    1.25          _loader_data->metaspace_non_null()->allocate(_size, _mdtype);
    1.26      }
    1.27 -    if (_result == NULL && !UseConcMarkSweepGC /* CMS already tried */) {
    1.28 +    if (_result == NULL) {
    1.29        // If still failing, allow the Metaspace to expand.
    1.30        // See delta_capacity_until_GC() for explanation of the
    1.31        // amount of the expansion.
    1.32 @@ -243,7 +241,16 @@
    1.33        // or a MaxMetaspaceSize has been specified on the command line.
    1.34        _result =
    1.35          _loader_data->metaspace_non_null()->expand_and_allocate(_size, _mdtype);
    1.36 -
    1.37 +      if (_result == NULL) {
    1.38 +        // If expansion failed, do a last-ditch collection and try allocating
    1.39 +        // again.  A last-ditch collection will clear softrefs.  This
    1.40 +        // behavior is similar to the last-ditch collection done for perm
    1.41 +        // gen when it was full and a collection for failed allocation
    1.42 +        // did not free perm gen space.
    1.43 +        heap->collect_as_vm_thread(GCCause::_last_ditch_collection);
    1.44 +        _result =
    1.45 +          _loader_data->metaspace_non_null()->allocate(_size, _mdtype);
    1.46 +      }
    1.47      }
    1.48      if (Verbose && PrintGCDetails && _result == NULL) {
    1.49        gclog_or_tty->print_cr("\nAfter Metaspace GC failed to allocate size "
     2.1 --- a/src/share/vm/memory/metaspace.cpp	Mon Oct 21 09:34:10 2013 +0200
     2.2 +++ b/src/share/vm/memory/metaspace.cpp	Mon Oct 21 01:04:01 2013 -0700
     2.3 @@ -75,8 +75,7 @@
     2.4    ClassSmallChunk = 256,
     2.5    SmallChunk = 512,
     2.6    ClassMediumChunk = 4 * K,
     2.7 -  MediumChunk = 8 * K,
     2.8 -  HumongousChunkGranularity = 8
     2.9 +  MediumChunk = 8 * K
    2.10  };
    2.11  
    2.12  static ChunkIndex next_chunk_index(ChunkIndex i) {
    2.13 @@ -92,6 +91,7 @@
    2.14  
    2.15  // Manages the global free lists of chunks.
    2.16  class ChunkManager : public CHeapObj<mtInternal> {
    2.17 +  friend class TestVirtualSpaceNodeTest;
    2.18  
    2.19    // Free list of chunks of different sizes.
    2.20    //   SpecializedChunk
    2.21 @@ -257,6 +257,8 @@
    2.22    // VirtualSpace
    2.23    Metachunk* first_chunk() { return (Metachunk*) bottom(); }
    2.24  
    2.25 +  // Committed but unused space in the virtual space
    2.26 +  size_t free_words_in_vs() const;
    2.27   public:
    2.28  
    2.29    VirtualSpaceNode(size_t byte_size);
    2.30 @@ -301,7 +303,6 @@
    2.31    // used and capacity in this single entry in the list
    2.32    size_t used_words_in_vs() const;
    2.33    size_t capacity_words_in_vs() const;
    2.34 -  size_t free_words_in_vs() const;
    2.35  
    2.36    bool initialize();
    2.37  
    2.38 @@ -319,6 +320,13 @@
    2.39    // in the node from any freelist.
    2.40    void purge(ChunkManager* chunk_manager);
    2.41  
    2.42 +  // If an allocation doesn't fit in the current node a new node is created.
    2.43 +  // Allocate chunks out of the remaining committed space in this node
    2.44 +  // to avoid wasting that memory.
    2.45 +  // This always adds up because all the chunk sizes are multiples of
    2.46 +  // the smallest chunk size.
    2.47 +  void retire(ChunkManager* chunk_manager);
    2.48 +
    2.49  #ifdef ASSERT
    2.50    // Debug support
    2.51    void mangle();
    2.52 @@ -461,6 +469,10 @@
    2.53    // and is typically followed by the allocation of a chunk.
    2.54    bool create_new_virtual_space(size_t vs_word_size);
    2.55  
    2.56 +  // Chunk up the unused committed space in the current
    2.57 +  // virtual space and add the chunks to the free list.
    2.58 +  void retire_current_virtual_space();
    2.59 +
    2.60   public:
    2.61    VirtualSpaceList(size_t word_size);
    2.62    VirtualSpaceList(ReservedSpace rs);
    2.63 @@ -624,10 +636,12 @@
    2.64    bool is_class() { return _mdtype == Metaspace::ClassType; }
    2.65  
    2.66    // Accessors
    2.67 -  size_t specialized_chunk_size() { return SpecializedChunk; }
    2.68 -  size_t small_chunk_size() { return (size_t) is_class() ? ClassSmallChunk : SmallChunk; }
    2.69 -  size_t medium_chunk_size() { return (size_t) is_class() ? ClassMediumChunk : MediumChunk; }
    2.70 -  size_t medium_chunk_bunch() { return medium_chunk_size() * MediumChunkMultiple; }
    2.71 +  size_t specialized_chunk_size() { return (size_t) is_class() ? ClassSpecializedChunk : SpecializedChunk; }
    2.72 +  size_t small_chunk_size()       { return (size_t) is_class() ? ClassSmallChunk : SmallChunk; }
    2.73 +  size_t medium_chunk_size()      { return (size_t) is_class() ? ClassMediumChunk : MediumChunk; }
    2.74 +  size_t medium_chunk_bunch()     { return medium_chunk_size() * MediumChunkMultiple; }
    2.75 +
    2.76 +  size_t smallest_chunk_size()  { return specialized_chunk_size(); }
    2.77  
    2.78    size_t allocated_blocks_words() const { return _allocated_blocks_words; }
    2.79    size_t allocated_blocks_bytes() const { return _allocated_blocks_words * BytesPerWord; }
    2.80 @@ -1056,6 +1070,35 @@
    2.81  #endif
    2.82  }
    2.83  
    2.84 +void VirtualSpaceList::retire_current_virtual_space() {
    2.85 +  assert_lock_strong(SpaceManager::expand_lock());
    2.86 +
    2.87 +  VirtualSpaceNode* vsn = current_virtual_space();
    2.88 +
    2.89 +  ChunkManager* cm = is_class() ? Metaspace::chunk_manager_class() :
    2.90 +                                  Metaspace::chunk_manager_metadata();
    2.91 +
    2.92 +  vsn->retire(cm);
    2.93 +}
    2.94 +
    2.95 +void VirtualSpaceNode::retire(ChunkManager* chunk_manager) {
    2.96 +  for (int i = (int)MediumIndex; i >= (int)ZeroIndex; --i) {
    2.97 +    ChunkIndex index = (ChunkIndex)i;
    2.98 +    size_t chunk_size = chunk_manager->free_chunks(index)->size();
    2.99 +
   2.100 +    while (free_words_in_vs() >= chunk_size) {
   2.101 +      DEBUG_ONLY(verify_container_count();)
   2.102 +      Metachunk* chunk = get_chunk_vs(chunk_size);
   2.103 +      assert(chunk != NULL, "allocation should have been successful");
   2.104 +
   2.105 +      chunk_manager->return_chunks(index, chunk);
   2.106 +      chunk_manager->inc_free_chunks_total(chunk_size);
   2.107 +      DEBUG_ONLY(verify_container_count();)
   2.108 +    }
   2.109 +  }
   2.110 +  assert(free_words_in_vs() == 0, "should be empty now");
   2.111 +}
   2.112 +
   2.113  VirtualSpaceList::VirtualSpaceList(size_t word_size) :
   2.114                                     _is_class(false),
   2.115                                     _virtual_space_list(NULL),
   2.116 @@ -1181,6 +1224,7 @@
   2.117    if (vs_expanded) {
   2.118      return true;
   2.119    }
   2.120 +  retire_current_virtual_space();
   2.121  
   2.122    // Get another virtual space.
   2.123    size_t grow_vs_words = MAX2((size_t)VirtualSpaceSize, preferred_words);
   2.124 @@ -1902,12 +1946,12 @@
   2.125      chunk_word_size = medium_chunk_size();
   2.126    }
   2.127  
   2.128 -  // Might still need a humongous chunk.  Enforce an
   2.129 -  // eight word granularity to facilitate reuse (some
   2.130 -  // wastage but better chance of reuse).
   2.131 +  // Might still need a humongous chunk.  Enforce
   2.132 +  // humongous allocations sizes to be aligned up to
   2.133 +  // the smallest chunk size.
   2.134    size_t if_humongous_sized_chunk =
   2.135      align_size_up(word_size + Metachunk::overhead(),
   2.136 -                  HumongousChunkGranularity);
   2.137 +                  smallest_chunk_size());
   2.138    chunk_word_size =
   2.139      MAX2((size_t) chunk_word_size, if_humongous_sized_chunk);
   2.140  
   2.141 @@ -2151,10 +2195,10 @@
   2.142      }
   2.143      assert(humongous_chunks->word_size() == (size_t)
   2.144             align_size_up(humongous_chunks->word_size(),
   2.145 -                             HumongousChunkGranularity),
   2.146 +                             smallest_chunk_size()),
   2.147             err_msg("Humongous chunk size is wrong: word size " SIZE_FORMAT
   2.148                     " granularity %d",
   2.149 -                   humongous_chunks->word_size(), HumongousChunkGranularity));
   2.150 +                   humongous_chunks->word_size(), smallest_chunk_size()));
   2.151      Metachunk* next_humongous_chunks = humongous_chunks->next();
   2.152      humongous_chunks->container()->dec_container_count();
   2.153      chunk_manager()->humongous_dictionary()->return_chunk(humongous_chunks);
   2.154 @@ -3301,9 +3345,7 @@
   2.155    }
   2.156  
   2.157    if (result == NULL) {
   2.158 -    report_metadata_oome(loader_data, word_size, mdtype, THREAD);
   2.159 -    // Will not reach here.
   2.160 -    return NULL;
   2.161 +    report_metadata_oome(loader_data, word_size, mdtype, CHECK_NULL);
   2.162    }
   2.163  
   2.164    // Zero initialize.
   2.165 @@ -3494,4 +3536,94 @@
   2.166    TestMetaspaceAuxTest::test();
   2.167  }
   2.168  
   2.169 +class TestVirtualSpaceNodeTest {
   2.170 +  static void chunk_up(size_t words_left, size_t& num_medium_chunks,
   2.171 +                                          size_t& num_small_chunks,
   2.172 +                                          size_t& num_specialized_chunks) {
   2.173 +    num_medium_chunks = words_left / MediumChunk;
   2.174 +    words_left = words_left % MediumChunk;
   2.175 +
   2.176 +    num_small_chunks = words_left / SmallChunk;
   2.177 +    words_left = words_left % SmallChunk;
   2.178 +    // how many specialized chunks can we get?
   2.179 +    num_specialized_chunks = words_left / SpecializedChunk;
   2.180 +    assert(words_left % SpecializedChunk == 0, "should be nothing left");
   2.181 +  }
   2.182 +
   2.183 + public:
   2.184 +  static void test() {
   2.185 +    MutexLockerEx ml(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag);
   2.186 +    const size_t vsn_test_size_words = MediumChunk  * 4;
   2.187 +    const size_t vsn_test_size_bytes = vsn_test_size_words * BytesPerWord;
   2.188 +
   2.189 +    // The chunk sizes must be multiples of eachother, or this will fail
   2.190 +    STATIC_ASSERT(MediumChunk % SmallChunk == 0);
   2.191 +    STATIC_ASSERT(SmallChunk % SpecializedChunk == 0);
   2.192 +
   2.193 +    { // No committed memory in VSN
   2.194 +      ChunkManager cm(SpecializedChunk, SmallChunk, MediumChunk);
   2.195 +      VirtualSpaceNode vsn(vsn_test_size_bytes);
   2.196 +      vsn.initialize();
   2.197 +      vsn.retire(&cm);
   2.198 +      assert(cm.sum_free_chunks_count() == 0, "did not commit any memory in the VSN");
   2.199 +    }
   2.200 +
   2.201 +    { // All of VSN is committed, half is used by chunks
   2.202 +      ChunkManager cm(SpecializedChunk, SmallChunk, MediumChunk);
   2.203 +      VirtualSpaceNode vsn(vsn_test_size_bytes);
   2.204 +      vsn.initialize();
   2.205 +      vsn.expand_by(vsn_test_size_words, vsn_test_size_words);
   2.206 +      vsn.get_chunk_vs(MediumChunk);
   2.207 +      vsn.get_chunk_vs(MediumChunk);
   2.208 +      vsn.retire(&cm);
   2.209 +      assert(cm.sum_free_chunks_count() == 2, "should have been memory left for 2 medium chunks");
   2.210 +      assert(cm.sum_free_chunks() == 2*MediumChunk, "sizes should add up");
   2.211 +    }
   2.212 +
   2.213 +    { // 4 pages of VSN is committed, some is used by chunks
   2.214 +      ChunkManager cm(SpecializedChunk, SmallChunk, MediumChunk);
   2.215 +      VirtualSpaceNode vsn(vsn_test_size_bytes);
   2.216 +      const size_t page_chunks = 4 * (size_t)os::vm_page_size() / BytesPerWord;
   2.217 +      assert(page_chunks < MediumChunk, "Test expects medium chunks to be at least 4*page_size");
   2.218 +      vsn.initialize();
   2.219 +      vsn.expand_by(page_chunks, page_chunks);
   2.220 +      vsn.get_chunk_vs(SmallChunk);
   2.221 +      vsn.get_chunk_vs(SpecializedChunk);
   2.222 +      vsn.retire(&cm);
   2.223 +
   2.224 +      // committed - used = words left to retire
   2.225 +      const size_t words_left = page_chunks - SmallChunk - SpecializedChunk;
   2.226 +
   2.227 +      size_t num_medium_chunks, num_small_chunks, num_spec_chunks;
   2.228 +      chunk_up(words_left, num_medium_chunks, num_small_chunks, num_spec_chunks);
   2.229 +
   2.230 +      assert(num_medium_chunks == 0, "should not get any medium chunks");
   2.231 +      assert(cm.sum_free_chunks_count() == (num_small_chunks + num_spec_chunks), "should be space for 3 chunks");
   2.232 +      assert(cm.sum_free_chunks() == words_left, "sizes should add up");
   2.233 +    }
   2.234 +
   2.235 +    { // Half of VSN is committed, a humongous chunk is used
   2.236 +      ChunkManager cm(SpecializedChunk, SmallChunk, MediumChunk);
   2.237 +      VirtualSpaceNode vsn(vsn_test_size_bytes);
   2.238 +      vsn.initialize();
   2.239 +      vsn.expand_by(MediumChunk * 2, MediumChunk * 2);
   2.240 +      vsn.get_chunk_vs(MediumChunk + SpecializedChunk); // Humongous chunks will be aligned up to MediumChunk + SpecializedChunk
   2.241 +      vsn.retire(&cm);
   2.242 +
   2.243 +      const size_t words_left = MediumChunk * 2 - (MediumChunk + SpecializedChunk);
   2.244 +      size_t num_medium_chunks, num_small_chunks, num_spec_chunks;
   2.245 +      chunk_up(words_left, num_medium_chunks, num_small_chunks, num_spec_chunks);
   2.246 +
   2.247 +      assert(num_medium_chunks == 0, "should not get any medium chunks");
   2.248 +      assert(cm.sum_free_chunks_count() == (num_small_chunks + num_spec_chunks), "should be space for 3 chunks");
   2.249 +      assert(cm.sum_free_chunks() == words_left, "sizes should add up");
   2.250 +    }
   2.251 +
   2.252 +  }
   2.253 +};
   2.254 +
   2.255 +void TestVirtualSpaceNode_test() {
   2.256 +  TestVirtualSpaceNodeTest::test();
   2.257 +}
   2.258 +
   2.259  #endif
     3.1 --- a/src/share/vm/prims/jni.cpp	Mon Oct 21 09:34:10 2013 +0200
     3.2 +++ b/src/share/vm/prims/jni.cpp	Mon Oct 21 01:04:01 2013 -0700
     3.3 @@ -5060,6 +5060,7 @@
     3.4  void TestVirtualSpace_test();
     3.5  void TestMetaspaceAux_test();
     3.6  void TestMetachunk_test();
     3.7 +void TestVirtualSpaceNode_test();
     3.8  #if INCLUDE_ALL_GCS
     3.9  void TestG1BiasedArray_test();
    3.10  #endif
    3.11 @@ -5072,6 +5073,7 @@
    3.12      run_unit_test(TestVirtualSpace_test());
    3.13      run_unit_test(TestMetaspaceAux_test());
    3.14      run_unit_test(TestMetachunk_test());
    3.15 +    run_unit_test(TestVirtualSpaceNode_test());
    3.16      run_unit_test(GlobalDefinitions::test_globals());
    3.17      run_unit_test(GCTimerAllTest::all());
    3.18      run_unit_test(arrayOopDesc::test_max_array_length());

mercurial