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