src/share/vm/memory/metaspace.cpp

changeset 5775
461159cd7a91
parent 5774
03f493ce3a71
child 5808
bc918fd1e584
     1.1 --- a/src/share/vm/memory/metaspace.cpp	Wed Sep 25 13:03:21 2013 -0400
     1.2 +++ b/src/share/vm/memory/metaspace.cpp	Thu Sep 26 12:18:21 2013 +0200
     1.3 @@ -23,6 +23,7 @@
     1.4   */
     1.5  #include "precompiled.hpp"
     1.6  #include "gc_interface/collectedHeap.hpp"
     1.7 +#include "memory/allocation.hpp"
     1.8  #include "memory/binaryTreeDictionary.hpp"
     1.9  #include "memory/freeList.hpp"
    1.10  #include "memory/collectorPolicy.hpp"
    1.11 @@ -111,7 +112,7 @@
    1.12  // Has three lists of free chunks, and a total size and
    1.13  // count that includes all three
    1.14  
    1.15 -class ChunkManager VALUE_OBJ_CLASS_SPEC {
    1.16 +class ChunkManager : public CHeapObj<mtInternal> {
    1.17  
    1.18    // Free list of chunks of different sizes.
    1.19    //   SpecializedChunk
    1.20 @@ -158,7 +159,12 @@
    1.21  
    1.22   public:
    1.23  
    1.24 -  ChunkManager() : _free_chunks_total(0), _free_chunks_count(0) {}
    1.25 +  ChunkManager(size_t specialized_size, size_t small_size, size_t medium_size)
    1.26 +      : _free_chunks_total(0), _free_chunks_count(0) {
    1.27 +    _free_chunks[SpecializedIndex].set_size(specialized_size);
    1.28 +    _free_chunks[SmallIndex].set_size(small_size);
    1.29 +    _free_chunks[MediumIndex].set_size(medium_size);
    1.30 +  }
    1.31  
    1.32    // add or delete (return) a chunk to the global freelist.
    1.33    Metachunk* chunk_freelist_allocate(size_t word_size);
    1.34 @@ -219,7 +225,7 @@
    1.35    void locked_print_free_chunks(outputStream* st);
    1.36    void locked_print_sum_free_chunks(outputStream* st);
    1.37  
    1.38 -  void print_on(outputStream* st);
    1.39 +  void print_on(outputStream* st) const;
    1.40  };
    1.41  
    1.42  // Used to manage the free list of Metablocks (a block corresponds
    1.43 @@ -276,11 +282,6 @@
    1.44    // VirtualSpace
    1.45    Metachunk* first_chunk() { return (Metachunk*) bottom(); }
    1.46  
    1.47 -  void inc_container_count();
    1.48 -#ifdef ASSERT
    1.49 -  uint container_count_slow();
    1.50 -#endif
    1.51 -
    1.52   public:
    1.53  
    1.54    VirtualSpaceNode(size_t byte_size);
    1.55 @@ -314,8 +315,10 @@
    1.56    void inc_top(size_t word_size) { _top += word_size; }
    1.57  
    1.58    uintx container_count() { return _container_count; }
    1.59 +  void inc_container_count();
    1.60    void dec_container_count();
    1.61  #ifdef ASSERT
    1.62 +  uint container_count_slow();
    1.63    void verify_container_count();
    1.64  #endif
    1.65  
    1.66 @@ -421,8 +424,6 @@
    1.67    VirtualSpaceNode* _virtual_space_list;
    1.68    // virtual space currently being used for allocations
    1.69    VirtualSpaceNode* _current_virtual_space;
    1.70 -  // Free chunk list for all other metadata
    1.71 -  ChunkManager      _chunk_manager;
    1.72  
    1.73    // Can this virtual list allocate >1 spaces?  Also, used to determine
    1.74    // whether to allocate unlimited small chunks in this virtual space
    1.75 @@ -475,7 +476,6 @@
    1.76      return _current_virtual_space;
    1.77    }
    1.78  
    1.79 -  ChunkManager* chunk_manager() { return &_chunk_manager; }
    1.80    bool is_class() const { return _is_class; }
    1.81  
    1.82    // Allocate the first virtualspace.
    1.83 @@ -494,14 +494,7 @@
    1.84    void dec_virtual_space_count();
    1.85  
    1.86    // Unlink empty VirtualSpaceNodes and free it.
    1.87 -  void purge();
    1.88 -
    1.89 -  // Used and capacity in the entire list of virtual spaces.
    1.90 -  // These are global values shared by all Metaspaces
    1.91 -  size_t capacity_words_sum();
    1.92 -  size_t capacity_bytes_sum() { return capacity_words_sum() * BytesPerWord; }
    1.93 -  size_t used_words_sum();
    1.94 -  size_t used_bytes_sum() { return used_words_sum() * BytesPerWord; }
    1.95 +  void purge(ChunkManager* chunk_manager);
    1.96  
    1.97    bool contains(const void *ptr);
    1.98  
    1.99 @@ -582,18 +575,12 @@
   1.100    // Type of metadata allocated.
   1.101    Metaspace::MetadataType _mdtype;
   1.102  
   1.103 -  // Chunk related size
   1.104 -  size_t _medium_chunk_bunch;
   1.105 -
   1.106    // List of chunks in use by this SpaceManager.  Allocations
   1.107    // are done from the current chunk.  The list is used for deallocating
   1.108    // chunks when the SpaceManager is freed.
   1.109    Metachunk* _chunks_in_use[NumberOfInUseLists];
   1.110    Metachunk* _current_chunk;
   1.111  
   1.112 -  // Virtual space where allocation comes from.
   1.113 -  VirtualSpaceList* _vs_list;
   1.114 -
   1.115    // Number of small chunks to allocate to a manager
   1.116    // If class space manager, small chunks are unlimited
   1.117    static uint const _small_chunk_limit;
   1.118 @@ -626,7 +613,9 @@
   1.119    }
   1.120  
   1.121    Metaspace::MetadataType mdtype() { return _mdtype; }
   1.122 -  VirtualSpaceList* vs_list() const    { return _vs_list; }
   1.123 +
   1.124 +  VirtualSpaceList* vs_list()   const { return Metaspace::get_space_list(_mdtype); }
   1.125 +  ChunkManager* chunk_manager() const { return Metaspace::get_chunk_manager(_mdtype); }
   1.126  
   1.127    Metachunk* current_chunk() const { return _current_chunk; }
   1.128    void set_current_chunk(Metachunk* v) {
   1.129 @@ -648,18 +637,19 @@
   1.130  
   1.131   public:
   1.132    SpaceManager(Metaspace::MetadataType mdtype,
   1.133 -               Mutex* lock,
   1.134 -               VirtualSpaceList* vs_list);
   1.135 +               Mutex* lock);
   1.136    ~SpaceManager();
   1.137  
   1.138    enum ChunkMultiples {
   1.139      MediumChunkMultiple = 4
   1.140    };
   1.141  
   1.142 +  bool is_class() { return _mdtype == Metaspace::ClassType; }
   1.143 +
   1.144    // Accessors
   1.145    size_t specialized_chunk_size() { return SpecializedChunk; }
   1.146 -  size_t small_chunk_size() { return (size_t) vs_list()->is_class() ? ClassSmallChunk : SmallChunk; }
   1.147 -  size_t medium_chunk_size() { return (size_t) vs_list()->is_class() ? ClassMediumChunk : MediumChunk; }
   1.148 +  size_t small_chunk_size() { return (size_t) is_class() ? ClassSmallChunk : SmallChunk; }
   1.149 +  size_t medium_chunk_size() { return (size_t) is_class() ? ClassMediumChunk : MediumChunk; }
   1.150    size_t medium_chunk_bunch() { return medium_chunk_size() * MediumChunkMultiple; }
   1.151  
   1.152    size_t allocated_blocks_words() const { return _allocated_blocks_words; }
   1.153 @@ -762,7 +752,7 @@
   1.154    _container_count++;
   1.155    assert(_container_count == container_count_slow(),
   1.156           err_msg("Inconsistency in countainer_count _container_count " SIZE_FORMAT
   1.157 -                 "container_count_slow() " SIZE_FORMAT,
   1.158 +                 " container_count_slow() " SIZE_FORMAT,
   1.159                   _container_count, container_count_slow()));
   1.160  }
   1.161  
   1.162 @@ -775,7 +765,7 @@
   1.163  void VirtualSpaceNode::verify_container_count() {
   1.164    assert(_container_count == container_count_slow(),
   1.165      err_msg("Inconsistency in countainer_count _container_count " SIZE_FORMAT
   1.166 -            "container_count_slow() " SIZE_FORMAT, _container_count, container_count_slow()));
   1.167 +            " container_count_slow() " SIZE_FORMAT, _container_count, container_count_slow()));
   1.168  }
   1.169  #endif
   1.170  
   1.171 @@ -1020,7 +1010,7 @@
   1.172  // Walk the list of VirtualSpaceNodes and delete
   1.173  // nodes with a 0 container_count.  Remove Metachunks in
   1.174  // the node from their respective freelists.
   1.175 -void VirtualSpaceList::purge() {
   1.176 +void VirtualSpaceList::purge(ChunkManager* chunk_manager) {
   1.177    assert_lock_strong(SpaceManager::expand_lock());
   1.178    // Don't use a VirtualSpaceListIterator because this
   1.179    // list is being changed and a straightforward use of an iterator is not safe.
   1.180 @@ -1042,7 +1032,7 @@
   1.181          prev_vsl->set_next(vsl->next());
   1.182        }
   1.183  
   1.184 -      vsl->purge(chunk_manager());
   1.185 +      vsl->purge(chunk_manager);
   1.186        dec_reserved_words(vsl->reserved_words());
   1.187        dec_committed_words(vsl->committed_words());
   1.188        dec_virtual_space_count();
   1.189 @@ -1064,36 +1054,6 @@
   1.190  #endif
   1.191  }
   1.192  
   1.193 -size_t VirtualSpaceList::used_words_sum() {
   1.194 -  size_t allocated_by_vs = 0;
   1.195 -  VirtualSpaceListIterator iter(virtual_space_list());
   1.196 -  while (iter.repeat()) {
   1.197 -    VirtualSpaceNode* vsl = iter.get_next();
   1.198 -    // Sum used region [bottom, top) in each virtualspace
   1.199 -    allocated_by_vs += vsl->used_words_in_vs();
   1.200 -  }
   1.201 -  assert(allocated_by_vs >= chunk_manager()->free_chunks_total_words(),
   1.202 -    err_msg("Total in free chunks " SIZE_FORMAT
   1.203 -            " greater than total from virtual_spaces " SIZE_FORMAT,
   1.204 -            allocated_by_vs, chunk_manager()->free_chunks_total_words()));
   1.205 -  size_t used =
   1.206 -    allocated_by_vs - chunk_manager()->free_chunks_total_words();
   1.207 -  return used;
   1.208 -}
   1.209 -
   1.210 -// Space available in all MetadataVirtualspaces allocated
   1.211 -// for metadata.  This is the upper limit on the capacity
   1.212 -// of chunks allocated out of all the MetadataVirtualspaces.
   1.213 -size_t VirtualSpaceList::capacity_words_sum() {
   1.214 -  size_t capacity = 0;
   1.215 -  VirtualSpaceListIterator iter(virtual_space_list());
   1.216 -  while (iter.repeat()) {
   1.217 -    VirtualSpaceNode* vsl = iter.get_next();
   1.218 -    capacity += vsl->capacity_words_in_vs();
   1.219 -  }
   1.220 -  return capacity;
   1.221 -}
   1.222 -
   1.223  VirtualSpaceList::VirtualSpaceList(size_t word_size ) :
   1.224                                     _is_class(false),
   1.225                                     _virtual_space_list(NULL),
   1.226 @@ -1104,10 +1064,6 @@
   1.227    MutexLockerEx cl(SpaceManager::expand_lock(),
   1.228                     Mutex::_no_safepoint_check_flag);
   1.229    bool initialization_succeeded = grow_vs(word_size);
   1.230 -
   1.231 -  _chunk_manager.free_chunks(SpecializedIndex)->set_size(SpecializedChunk);
   1.232 -  _chunk_manager.free_chunks(SmallIndex)->set_size(SmallChunk);
   1.233 -  _chunk_manager.free_chunks(MediumIndex)->set_size(MediumChunk);
   1.234    assert(initialization_succeeded,
   1.235      " VirtualSpaceList initialization should not fail");
   1.236  }
   1.237 @@ -1123,9 +1079,6 @@
   1.238                     Mutex::_no_safepoint_check_flag);
   1.239    VirtualSpaceNode* class_entry = new VirtualSpaceNode(rs);
   1.240    bool succeeded = class_entry->initialize();
   1.241 -  _chunk_manager.free_chunks(SpecializedIndex)->set_size(SpecializedChunk);
   1.242 -  _chunk_manager.free_chunks(SmallIndex)->set_size(ClassSmallChunk);
   1.243 -  _chunk_manager.free_chunks(MediumIndex)->set_size(ClassMediumChunk);
   1.244    assert(succeeded, " VirtualSpaceList initialization should not fail");
   1.245    link_vs(class_entry);
   1.246  }
   1.247 @@ -1142,7 +1095,7 @@
   1.248    }
   1.249    // Reserve the space
   1.250    size_t vs_byte_size = vs_word_size * BytesPerWord;
   1.251 -  assert(vs_byte_size % os::vm_page_size() == 0, "Not aligned");
   1.252 +  assert(vs_byte_size % os::vm_allocation_granularity() == 0, "Not aligned");
   1.253  
   1.254    // Allocate the meta virtual space and initialize it.
   1.255    VirtualSpaceNode* new_entry = new VirtualSpaceNode(vs_byte_size);
   1.256 @@ -1195,15 +1148,8 @@
   1.257                                             size_t grow_chunks_by_words,
   1.258                                             size_t medium_chunk_bunch) {
   1.259  
   1.260 -  // Get a chunk from the chunk freelist
   1.261 -  Metachunk* next = chunk_manager()->chunk_freelist_allocate(grow_chunks_by_words);
   1.262 -
   1.263 -  if (next != NULL) {
   1.264 -    next->container()->inc_container_count();
   1.265 -  } else {
   1.266 -    // Allocate a chunk out of the current virtual space.
   1.267 -    next = current_virtual_space()->get_chunk_vs(grow_chunks_by_words);
   1.268 -  }
   1.269 +  // Allocate a chunk out of the current virtual space.
   1.270 +  Metachunk* next = current_virtual_space()->get_chunk_vs(grow_chunks_by_words);
   1.271  
   1.272    if (next == NULL) {
   1.273      // Not enough room in current virtual space.  Try to commit
   1.274 @@ -1221,12 +1167,14 @@
   1.275        // being used for CompressedHeaders, don't allocate a new virtualspace.
   1.276        if (can_grow() && MetaspaceGC::should_expand(this, word_size)) {
   1.277          // Get another virtual space.
   1.278 -          size_t grow_vs_words =
   1.279 -            MAX2((size_t)VirtualSpaceSize, aligned_expand_vs_by_words);
   1.280 +        size_t allocation_aligned_expand_words =
   1.281 +            align_size_up(aligned_expand_vs_by_words, os::vm_allocation_granularity() / BytesPerWord);
   1.282 +        size_t grow_vs_words =
   1.283 +            MAX2((size_t)VirtualSpaceSize, allocation_aligned_expand_words);
   1.284          if (grow_vs(grow_vs_words)) {
   1.285            // Got it.  It's on the list now.  Get a chunk from it.
   1.286            assert(current_virtual_space()->expanded_words() == 0,
   1.287 -              "New virtuals space nodes should not have expanded");
   1.288 +              "New virtual space nodes should not have expanded");
   1.289  
   1.290            size_t grow_chunks_by_words_aligned = align_size_up(grow_chunks_by_words,
   1.291                                                                page_size_words);
   1.292 @@ -1342,8 +1290,9 @@
   1.293    // reserved space, because this is a larger space prereserved for compressed
   1.294    // class pointers.
   1.295    if (!FLAG_IS_DEFAULT(MaxMetaspaceSize)) {
   1.296 -    size_t real_allocated = Metaspace::space_list()->reserved_words() +
   1.297 -              MetaspaceAux::allocated_capacity_bytes(Metaspace::ClassType);
   1.298 +    size_t nonclass_allocated = MetaspaceAux::reserved_bytes(Metaspace::NonClassType);
   1.299 +    size_t class_allocated    = MetaspaceAux::allocated_capacity_bytes(Metaspace::ClassType);
   1.300 +    size_t real_allocated     = nonclass_allocated + class_allocated;
   1.301      if (real_allocated >= MaxMetaspaceSize) {
   1.302        return false;
   1.303      }
   1.304 @@ -1536,15 +1485,15 @@
   1.305        if (dummy_chunk == NULL) {
   1.306          break;
   1.307        }
   1.308 -      vsl->chunk_manager()->chunk_freelist_deallocate(dummy_chunk);
   1.309 +      sm->chunk_manager()->chunk_freelist_deallocate(dummy_chunk);
   1.310  
   1.311        if (TraceMetadataChunkAllocation && Verbose) {
   1.312          gclog_or_tty->print("Metadebug::deallocate_chunk_a_lot: %d) ",
   1.313                                 sm->sum_count_in_chunks_in_use());
   1.314          dummy_chunk->print_on(gclog_or_tty);
   1.315          gclog_or_tty->print_cr("  Free chunks total %d  count %d",
   1.316 -                               vsl->chunk_manager()->free_chunks_total_words(),
   1.317 -                               vsl->chunk_manager()->free_chunks_count());
   1.318 +                               sm->chunk_manager()->free_chunks_total_words(),
   1.319 +                               sm->chunk_manager()->free_chunks_count());
   1.320        }
   1.321      }
   1.322    } else {
   1.323 @@ -1796,6 +1745,8 @@
   1.324    // work.
   1.325    chunk->set_is_free(false);
   1.326  #endif
   1.327 +  chunk->container()->inc_container_count();
   1.328 +
   1.329    slow_locked_verify();
   1.330    return chunk;
   1.331  }
   1.332 @@ -1830,9 +1781,9 @@
   1.333    return chunk;
   1.334  }
   1.335  
   1.336 -void ChunkManager::print_on(outputStream* out) {
   1.337 +void ChunkManager::print_on(outputStream* out) const {
   1.338    if (PrintFLSStatistics != 0) {
   1.339 -    humongous_dictionary()->report_statistics();
   1.340 +    const_cast<ChunkManager *>(this)->humongous_dictionary()->report_statistics();
   1.341    }
   1.342  }
   1.343  
   1.344 @@ -1979,8 +1930,8 @@
   1.345      }
   1.346    }
   1.347  
   1.348 -  vs_list()->chunk_manager()->locked_print_free_chunks(st);
   1.349 -  vs_list()->chunk_manager()->locked_print_sum_free_chunks(st);
   1.350 +  chunk_manager()->locked_print_free_chunks(st);
   1.351 +  chunk_manager()->locked_print_sum_free_chunks(st);
   1.352  }
   1.353  
   1.354  size_t SpaceManager::calc_chunk_size(size_t word_size) {
   1.355 @@ -2084,9 +2035,7 @@
   1.356  }
   1.357  
   1.358  SpaceManager::SpaceManager(Metaspace::MetadataType mdtype,
   1.359 -                           Mutex* lock,
   1.360 -                           VirtualSpaceList* vs_list) :
   1.361 -  _vs_list(vs_list),
   1.362 +                           Mutex* lock) :
   1.363    _mdtype(mdtype),
   1.364    _allocated_blocks_words(0),
   1.365    _allocated_chunks_words(0),
   1.366 @@ -2172,9 +2121,7 @@
   1.367    MutexLockerEx fcl(SpaceManager::expand_lock(),
   1.368                      Mutex::_no_safepoint_check_flag);
   1.369  
   1.370 -  ChunkManager* chunk_manager = vs_list()->chunk_manager();
   1.371 -
   1.372 -  chunk_manager->slow_locked_verify();
   1.373 +  chunk_manager()->slow_locked_verify();
   1.374  
   1.375    dec_total_from_size_metrics();
   1.376  
   1.377 @@ -2188,8 +2135,8 @@
   1.378  
   1.379    // Have to update before the chunks_in_use lists are emptied
   1.380    // below.
   1.381 -  chunk_manager->inc_free_chunks_total(allocated_chunks_words(),
   1.382 -                                       sum_count_in_chunks_in_use());
   1.383 +  chunk_manager()->inc_free_chunks_total(allocated_chunks_words(),
   1.384 +                                         sum_count_in_chunks_in_use());
   1.385  
   1.386    // Add all the chunks in use by this space manager
   1.387    // to the global list of free chunks.
   1.388 @@ -2204,11 +2151,11 @@
   1.389                               chunk_size_name(i));
   1.390      }
   1.391      Metachunk* chunks = chunks_in_use(i);
   1.392 -    chunk_manager->return_chunks(i, chunks);
   1.393 +    chunk_manager()->return_chunks(i, chunks);
   1.394      set_chunks_in_use(i, NULL);
   1.395      if (TraceMetadataChunkAllocation && Verbose) {
   1.396        gclog_or_tty->print_cr("updated freelist count %d %s",
   1.397 -                             chunk_manager->free_chunks(i)->count(),
   1.398 +                             chunk_manager()->free_chunks(i)->count(),
   1.399                               chunk_size_name(i));
   1.400      }
   1.401      assert(i != HumongousIndex, "Humongous chunks are handled explicitly later");
   1.402 @@ -2245,16 +2192,16 @@
   1.403                     humongous_chunks->word_size(), HumongousChunkGranularity));
   1.404      Metachunk* next_humongous_chunks = humongous_chunks->next();
   1.405      humongous_chunks->container()->dec_container_count();
   1.406 -    chunk_manager->humongous_dictionary()->return_chunk(humongous_chunks);
   1.407 +    chunk_manager()->humongous_dictionary()->return_chunk(humongous_chunks);
   1.408      humongous_chunks = next_humongous_chunks;
   1.409    }
   1.410    if (TraceMetadataChunkAllocation && Verbose) {
   1.411      gclog_or_tty->print_cr("");
   1.412      gclog_or_tty->print_cr("updated dictionary count %d %s",
   1.413 -                     chunk_manager->humongous_dictionary()->total_count(),
   1.414 +                     chunk_manager()->humongous_dictionary()->total_count(),
   1.415                       chunk_size_name(HumongousIndex));
   1.416    }
   1.417 -  chunk_manager->slow_locked_verify();
   1.418 +  chunk_manager()->slow_locked_verify();
   1.419  }
   1.420  
   1.421  const char* SpaceManager::chunk_size_name(ChunkIndex index) const {
   1.422 @@ -2343,9 +2290,7 @@
   1.423      gclog_or_tty->print("SpaceManager::add_chunk: %d) ",
   1.424                          sum_count_in_chunks_in_use());
   1.425      new_chunk->print_on(gclog_or_tty);
   1.426 -    if (vs_list() != NULL) {
   1.427 -      vs_list()->chunk_manager()->locked_print_free_chunks(gclog_or_tty);
   1.428 -    }
   1.429 +    chunk_manager()->locked_print_free_chunks(gclog_or_tty);
   1.430    }
   1.431  }
   1.432  
   1.433 @@ -2361,10 +2306,14 @@
   1.434  
   1.435  Metachunk* SpaceManager::get_new_chunk(size_t word_size,
   1.436                                         size_t grow_chunks_by_words) {
   1.437 -
   1.438 -  Metachunk* next = vs_list()->get_new_chunk(word_size,
   1.439 -                                             grow_chunks_by_words,
   1.440 -                                             medium_chunk_bunch());
   1.441 +  // Get a chunk from the chunk freelist
   1.442 +  Metachunk* next = chunk_manager()->chunk_freelist_allocate(grow_chunks_by_words);
   1.443 +
   1.444 +  if (next == NULL) {
   1.445 +    next = vs_list()->get_new_chunk(word_size,
   1.446 +                                    grow_chunks_by_words,
   1.447 +                                    medium_chunk_bunch());
   1.448 +  }
   1.449  
   1.450    if (TraceMetadataHumongousAllocation && next != NULL &&
   1.451        SpaceManager::is_humongous(next->word_size())) {
   1.452 @@ -2644,13 +2593,12 @@
   1.453  size_t MetaspaceAux::min_chunk_size_words() { return Metaspace::first_chunk_word_size(); }
   1.454  
   1.455  size_t MetaspaceAux::free_chunks_total_words(Metaspace::MetadataType mdtype) {
   1.456 -  VirtualSpaceList* list = Metaspace::get_space_list(mdtype);
   1.457 -  if (list == NULL) {
   1.458 +  ChunkManager* chunk_manager = Metaspace::get_chunk_manager(mdtype);
   1.459 +  if (chunk_manager == NULL) {
   1.460      return 0;
   1.461    }
   1.462 -  ChunkManager* chunk = list->chunk_manager();
   1.463 -  chunk->slow_verify();
   1.464 -  return chunk->free_chunks_total_words();
   1.465 +  chunk_manager->slow_verify();
   1.466 +  return chunk_manager->free_chunks_total_words();
   1.467  }
   1.468  
   1.469  size_t MetaspaceAux::free_chunks_total_bytes(Metaspace::MetadataType mdtype) {
   1.470 @@ -2801,9 +2749,9 @@
   1.471  }
   1.472  
   1.473  void MetaspaceAux::verify_free_chunks() {
   1.474 -  Metaspace::space_list()->chunk_manager()->verify();
   1.475 +  Metaspace::chunk_manager_metadata()->verify();
   1.476    if (Metaspace::using_class_space()) {
   1.477 -    Metaspace::class_space_list()->chunk_manager()->verify();
   1.478 +    Metaspace::chunk_manager_class()->verify();
   1.479    }
   1.480  }
   1.481  
   1.482 @@ -2874,6 +2822,9 @@
   1.483  VirtualSpaceList* Metaspace::_space_list = NULL;
   1.484  VirtualSpaceList* Metaspace::_class_space_list = NULL;
   1.485  
   1.486 +ChunkManager* Metaspace::_chunk_manager_metadata = NULL;
   1.487 +ChunkManager* Metaspace::_chunk_manager_class = NULL;
   1.488 +
   1.489  #define VIRTUALSPACEMULTIPLIER 2
   1.490  
   1.491  #ifdef _LP64
   1.492 @@ -2981,6 +2932,7 @@
   1.493           err_msg(SIZE_FORMAT " != " UINTX_FORMAT, rs.size(), CompressedClassSpaceSize));
   1.494    assert(using_class_space(), "Must be using class space");
   1.495    _class_space_list = new VirtualSpaceList(rs);
   1.496 +  _chunk_manager_class = new ChunkManager(SpecializedChunk, ClassSmallChunk, ClassMediumChunk);
   1.497  }
   1.498  
   1.499  #endif
   1.500 @@ -3006,6 +2958,7 @@
   1.501      // remainder is the misc code and data chunks.
   1.502      cds_total = FileMapInfo::shared_spaces_size();
   1.503      _space_list = new VirtualSpaceList(cds_total/wordSize);
   1.504 +    _chunk_manager_metadata = new ChunkManager(SpecializedChunk, SmallChunk, MediumChunk);
   1.505  
   1.506  #ifdef _LP64
   1.507      // Set the compressed klass pointer base so that decoding of these pointers works
   1.508 @@ -3073,15 +3026,30 @@
   1.509      size_t word_size = VIRTUALSPACEMULTIPLIER * first_chunk_word_size();
   1.510      // Initialize the list of virtual spaces.
   1.511      _space_list = new VirtualSpaceList(word_size);
   1.512 +    _chunk_manager_metadata = new ChunkManager(SpecializedChunk, SmallChunk, MediumChunk);
   1.513    }
   1.514  }
   1.515  
   1.516 +Metachunk* Metaspace::get_initialization_chunk(MetadataType mdtype,
   1.517 +                                               size_t chunk_word_size,
   1.518 +                                               size_t chunk_bunch) {
   1.519 +  // Get a chunk from the chunk freelist
   1.520 +  Metachunk* chunk = get_chunk_manager(mdtype)->chunk_freelist_allocate(chunk_word_size);
   1.521 +  if (chunk != NULL) {
   1.522 +    return chunk;
   1.523 +  }
   1.524 +
   1.525 +  return get_space_list(mdtype)->get_initialization_chunk(chunk_word_size, chunk_bunch);
   1.526 +}
   1.527 +
   1.528  void Metaspace::initialize(Mutex* lock, MetaspaceType type) {
   1.529  
   1.530    assert(space_list() != NULL,
   1.531      "Metadata VirtualSpaceList has not been initialized");
   1.532 -
   1.533 -  _vsm = new SpaceManager(NonClassType, lock, space_list());
   1.534 +  assert(chunk_manager_metadata() != NULL,
   1.535 +    "Metadata ChunkManager has not been initialized");
   1.536 +
   1.537 +  _vsm = new SpaceManager(NonClassType, lock);
   1.538    if (_vsm == NULL) {
   1.539      return;
   1.540    }
   1.541 @@ -3090,11 +3058,13 @@
   1.542    vsm()->get_initial_chunk_sizes(type, &word_size, &class_word_size);
   1.543  
   1.544    if (using_class_space()) {
   1.545 -    assert(class_space_list() != NULL,
   1.546 -      "Class VirtualSpaceList has not been initialized");
   1.547 +  assert(class_space_list() != NULL,
   1.548 +    "Class VirtualSpaceList has not been initialized");
   1.549 +  assert(chunk_manager_class() != NULL,
   1.550 +    "Class ChunkManager has not been initialized");
   1.551  
   1.552      // Allocate SpaceManager for classes.
   1.553 -    _class_vsm = new SpaceManager(ClassType, lock, class_space_list());
   1.554 +    _class_vsm = new SpaceManager(ClassType, lock);
   1.555      if (_class_vsm == NULL) {
   1.556        return;
   1.557      }
   1.558 @@ -3103,9 +3073,9 @@
   1.559    MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag);
   1.560  
   1.561    // Allocate chunk for metadata objects
   1.562 -  Metachunk* new_chunk =
   1.563 -     space_list()->get_initialization_chunk(word_size,
   1.564 -                                            vsm()->medium_chunk_bunch());
   1.565 +  Metachunk* new_chunk = get_initialization_chunk(NonClassType,
   1.566 +                                                  word_size,
   1.567 +                                                  vsm()->medium_chunk_bunch());
   1.568    assert(!DumpSharedSpaces || new_chunk != NULL, "should have enough space for both chunks");
   1.569    if (new_chunk != NULL) {
   1.570      // Add to this manager's list of chunks in use and current_chunk().
   1.571 @@ -3114,9 +3084,9 @@
   1.572  
   1.573    // Allocate chunk for class metadata objects
   1.574    if (using_class_space()) {
   1.575 -    Metachunk* class_chunk =
   1.576 -       class_space_list()->get_initialization_chunk(class_word_size,
   1.577 -                                                    class_vsm()->medium_chunk_bunch());
   1.578 +    Metachunk* class_chunk = get_initialization_chunk(ClassType,
   1.579 +                                                      class_word_size,
   1.580 +                                                      class_vsm()->medium_chunk_bunch());
   1.581      if (class_chunk != NULL) {
   1.582        class_vsm()->add_chunk(class_chunk, true);
   1.583      }
   1.584 @@ -3333,12 +3303,16 @@
   1.585    }
   1.586  }
   1.587  
   1.588 +void Metaspace::purge(MetadataType mdtype) {
   1.589 +  get_space_list(mdtype)->purge(get_chunk_manager(mdtype));
   1.590 +}
   1.591 +
   1.592  void Metaspace::purge() {
   1.593    MutexLockerEx cl(SpaceManager::expand_lock(),
   1.594                     Mutex::_no_safepoint_check_flag);
   1.595 -  space_list()->purge();
   1.596 +  purge(NonClassType);
   1.597    if (using_class_space()) {
   1.598 -    class_space_list()->purge();
   1.599 +    purge(ClassType);
   1.600    }
   1.601  }
   1.602  
   1.603 @@ -3385,7 +3359,7 @@
   1.604  
   1.605  #ifndef PRODUCT
   1.606  
   1.607 -class MetaspaceAuxTest : AllStatic {
   1.608 +class TestMetaspaceAuxTest : AllStatic {
   1.609   public:
   1.610    static void test_reserved() {
   1.611      size_t reserved = MetaspaceAux::reserved_bytes();
   1.612 @@ -3425,14 +3399,25 @@
   1.613      }
   1.614    }
   1.615  
   1.616 +  static void test_virtual_space_list_large_chunk() {
   1.617 +    VirtualSpaceList* vs_list = new VirtualSpaceList(os::vm_allocation_granularity());
   1.618 +    MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag);
   1.619 +    // A size larger than VirtualSpaceSize (256k) and add one page to make it _not_ be
   1.620 +    // vm_allocation_granularity aligned on Windows.
   1.621 +    size_t large_size = (size_t)(2*256*K + (os::vm_page_size()/BytesPerWord));
   1.622 +    large_size += (os::vm_page_size()/BytesPerWord);
   1.623 +    vs_list->get_new_chunk(large_size, large_size, 0);
   1.624 +  }
   1.625 +
   1.626    static void test() {
   1.627      test_reserved();
   1.628      test_committed();
   1.629 +    test_virtual_space_list_large_chunk();
   1.630    }
   1.631  };
   1.632  
   1.633 -void MetaspaceAux_test() {
   1.634 -  MetaspaceAuxTest::test();
   1.635 +void TestMetaspaceAux_test() {
   1.636 +  TestMetaspaceAuxTest::test();
   1.637  }
   1.638  
   1.639  #endif

mercurial