annotate src/share/vm/memory/metaspace.cpp @ 4369:91bf0bdae37b

8008217: CDS: Class data sharing limits the malloc heap on Solaris Summary: In 64bit VM move CDS archive address to 32G on all platforms using new flag SharedBaseAddress. In 32bit VM set CDS archive address to 3Gb on Linux and let other OSs pick the address. Reviewed-by: kvn, dcubed, zgu, hseigel
author coleenp
date Wed, 20 Mar 2013 08:04:54 -0400
parents 82ab039b9680
children 6574f999e0cf
rev   line source
coleenp@3602 1 /*
coleenp@4277 2 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
coleenp@3602 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
coleenp@3602 4 *
coleenp@3602 5 * This code is free software; you can redistribute it and/or modify it
coleenp@3602 6 * under the terms of the GNU General Public License version 2 only, as
coleenp@3602 7 * published by the Free Software Foundation.
coleenp@3602 8 *
coleenp@3602 9 * This code is distributed in the hope that it will be useful, but WITHOUT
coleenp@3602 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
coleenp@3602 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
coleenp@3602 12 * version 2 for more details (a copy is included in the LICENSE file that
coleenp@3602 13 * accompanied this code).
coleenp@3602 14 *
coleenp@3602 15 * You should have received a copy of the GNU General Public License version
coleenp@3602 16 * 2 along with this work; if not, write to the Free Software Foundation,
coleenp@3602 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
coleenp@3602 18 *
coleenp@3602 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
coleenp@3602 20 * or visit www.oracle.com if you need additional information or have any
coleenp@3602 21 * questions.
coleenp@3602 22 *
coleenp@3602 23 */
coleenp@3602 24 #include "precompiled.hpp"
coleenp@3602 25 #include "gc_interface/collectedHeap.hpp"
coleenp@3602 26 #include "memory/binaryTreeDictionary.hpp"
jmasa@3761 27 #include "memory/freeList.hpp"
coleenp@3602 28 #include "memory/collectorPolicy.hpp"
coleenp@3602 29 #include "memory/filemap.hpp"
coleenp@3602 30 #include "memory/freeList.hpp"
jmasa@3761 31 #include "memory/metablock.hpp"
jmasa@3761 32 #include "memory/metachunk.hpp"
coleenp@3602 33 #include "memory/metaspace.hpp"
coleenp@3602 34 #include "memory/metaspaceShared.hpp"
coleenp@3602 35 #include "memory/resourceArea.hpp"
coleenp@3602 36 #include "memory/universe.hpp"
coleenp@3602 37 #include "runtime/globals.hpp"
coleenp@3602 38 #include "runtime/mutex.hpp"
coleenp@3860 39 #include "runtime/orderAccess.hpp"
coleenp@3602 40 #include "services/memTracker.hpp"
coleenp@3602 41 #include "utilities/copy.hpp"
coleenp@3602 42 #include "utilities/debug.hpp"
coleenp@3602 43
jmasa@3761 44 typedef BinaryTreeDictionary<Metablock, FreeList> BlockTreeDictionary;
jmasa@3761 45 typedef BinaryTreeDictionary<Metachunk, FreeList> ChunkTreeDictionary;
mgerdin@3829 46 // Define this macro to enable slow integrity checking of
mgerdin@3829 47 // the free chunk lists
mgerdin@3829 48 const bool metaspace_slow_verify = false;
mgerdin@3829 49
coleenp@3602 50
coleenp@3602 51 // Parameters for stress mode testing
coleenp@3602 52 const uint metadata_deallocate_a_lot_block = 10;
coleenp@3602 53 const uint metadata_deallocate_a_lock_chunk = 3;
coleenp@3602 54 size_t const allocation_from_dictionary_limit = 64 * K;
coleenp@3602 55
coleenp@3602 56 MetaWord* last_allocated = 0;
coleenp@3602 57
coleenp@3602 58 // Used in declarations in SpaceManager and ChunkManager
coleenp@3602 59 enum ChunkIndex {
jmasa@3947 60 ZeroIndex = 0,
jmasa@3947 61 SpecializedIndex = ZeroIndex,
jmasa@3947 62 SmallIndex = SpecializedIndex + 1,
jmasa@3947 63 MediumIndex = SmallIndex + 1,
jmasa@3947 64 HumongousIndex = MediumIndex + 1,
jmasa@3947 65 NumberOfFreeLists = 3,
jmasa@3947 66 NumberOfInUseLists = 4
jmasa@3947 67 };
jmasa@3947 68
jmasa@3947 69 enum ChunkSizes { // in words.
jmasa@3947 70 ClassSpecializedChunk = 128,
jmasa@3947 71 SpecializedChunk = 128,
jmasa@3947 72 ClassSmallChunk = 256,
jmasa@3947 73 SmallChunk = 512,
jmasa@3947 74 ClassMediumChunk = 1 * K,
jmasa@3947 75 MediumChunk = 8 * K,
jmasa@3947 76 HumongousChunkGranularity = 8
coleenp@3602 77 };
coleenp@3602 78
coleenp@3602 79 static ChunkIndex next_chunk_index(ChunkIndex i) {
jmasa@3761 80 assert(i < NumberOfInUseLists, "Out of bound");
coleenp@3602 81 return (ChunkIndex) (i+1);
coleenp@3602 82 }
coleenp@3602 83
coleenp@3602 84 // Originally _capacity_until_GC was set to MetaspaceSize here but
coleenp@3602 85 // the default MetaspaceSize before argument processing was being
coleenp@3602 86 // used which was not the desired value. See the code
coleenp@3602 87 // in should_expand() to see how the initialization is handled
coleenp@3602 88 // now.
coleenp@3602 89 size_t MetaspaceGC::_capacity_until_GC = 0;
coleenp@3602 90 bool MetaspaceGC::_expand_after_GC = false;
coleenp@3602 91 uint MetaspaceGC::_shrink_factor = 0;
coleenp@3602 92 bool MetaspaceGC::_should_concurrent_collect = false;
coleenp@3602 93
coleenp@3602 94 // Blocks of space for metadata are allocated out of Metachunks.
coleenp@3602 95 //
coleenp@3602 96 // Metachunk are allocated out of MetadataVirtualspaces and once
coleenp@3602 97 // allocated there is no explicit link between a Metachunk and
coleenp@3602 98 // the MetadataVirtualspaces from which it was allocated.
coleenp@3602 99 //
coleenp@3602 100 // Each SpaceManager maintains a
coleenp@3602 101 // list of the chunks it is using and the current chunk. The current
coleenp@3602 102 // chunk is the chunk from which allocations are done. Space freed in
coleenp@3602 103 // a chunk is placed on the free list of blocks (BlockFreelist) and
coleenp@3602 104 // reused from there.
coleenp@3602 105
coleenp@3602 106 // Pointer to list of Metachunks.
coleenp@3602 107 class ChunkList VALUE_OBJ_CLASS_SPEC {
coleenp@3602 108 // List of free chunks
coleenp@3602 109 Metachunk* _head;
coleenp@3602 110
coleenp@3602 111 public:
coleenp@3602 112 // Constructor
coleenp@3602 113 ChunkList() : _head(NULL) {}
coleenp@3602 114
coleenp@3602 115 // Accessors
coleenp@3602 116 Metachunk* head() { return _head; }
coleenp@3602 117 void set_head(Metachunk* v) { _head = v; }
coleenp@3602 118
coleenp@3602 119 // Link at head of the list
coleenp@3602 120 void add_at_head(Metachunk* head, Metachunk* tail);
coleenp@3602 121 void add_at_head(Metachunk* head);
coleenp@3602 122
coleenp@3602 123 size_t sum_list_size();
coleenp@3602 124 size_t sum_list_count();
coleenp@3602 125 size_t sum_list_capacity();
coleenp@3602 126 };
coleenp@3602 127
coleenp@3602 128 // Manages the global free lists of chunks.
coleenp@3602 129 // Has three lists of free chunks, and a total size and
coleenp@3602 130 // count that includes all three
coleenp@3602 131
coleenp@3602 132 class ChunkManager VALUE_OBJ_CLASS_SPEC {
coleenp@3602 133
coleenp@3602 134 // Free list of chunks of different sizes.
coleenp@3602 135 // SmallChunk
coleenp@3602 136 // MediumChunk
coleenp@3602 137 // HumongousChunk
jmasa@3761 138 ChunkList _free_chunks[NumberOfFreeLists];
jmasa@3761 139
jmasa@3947 140
jmasa@3761 141 // HumongousChunk
jmasa@3761 142 ChunkTreeDictionary _humongous_dictionary;
coleenp@3602 143
coleenp@3602 144 // ChunkManager in all lists of this type
coleenp@3602 145 size_t _free_chunks_total;
coleenp@3602 146 size_t _free_chunks_count;
coleenp@3602 147
coleenp@3602 148 void dec_free_chunks_total(size_t v) {
coleenp@3602 149 assert(_free_chunks_count > 0 &&
coleenp@3602 150 _free_chunks_total > 0,
coleenp@3602 151 "About to go negative");
coleenp@3602 152 Atomic::add_ptr(-1, &_free_chunks_count);
coleenp@3602 153 jlong minus_v = (jlong) - (jlong) v;
coleenp@3602 154 Atomic::add_ptr(minus_v, &_free_chunks_total);
coleenp@3602 155 }
coleenp@3602 156
coleenp@3602 157 // Debug support
coleenp@3602 158
coleenp@3602 159 size_t sum_free_chunks();
coleenp@3602 160 size_t sum_free_chunks_count();
coleenp@3602 161
coleenp@3602 162 void locked_verify_free_chunks_total();
mgerdin@3829 163 void slow_locked_verify_free_chunks_total() {
mgerdin@3829 164 if (metaspace_slow_verify) {
mgerdin@3829 165 locked_verify_free_chunks_total();
mgerdin@3829 166 }
mgerdin@3829 167 }
coleenp@3602 168 void locked_verify_free_chunks_count();
mgerdin@3829 169 void slow_locked_verify_free_chunks_count() {
mgerdin@3829 170 if (metaspace_slow_verify) {
mgerdin@3829 171 locked_verify_free_chunks_count();
mgerdin@3829 172 }
mgerdin@3829 173 }
coleenp@3602 174 void verify_free_chunks_count();
coleenp@3602 175
coleenp@3602 176 public:
coleenp@3602 177
coleenp@3602 178 ChunkManager() : _free_chunks_total(0), _free_chunks_count(0) {}
coleenp@3602 179
coleenp@3602 180 // add or delete (return) a chunk to the global freelist.
coleenp@3602 181 Metachunk* chunk_freelist_allocate(size_t word_size);
coleenp@3602 182 void chunk_freelist_deallocate(Metachunk* chunk);
coleenp@3602 183
jmasa@3947 184 // Map a size to a list index assuming that there are lists
jmasa@3947 185 // for special, small, medium, and humongous chunks.
jmasa@3947 186 static ChunkIndex list_index(size_t size);
jmasa@3947 187
coleenp@3602 188 // Total of the space in the free chunks list
coleenp@3602 189 size_t free_chunks_total();
coleenp@3602 190 size_t free_chunks_total_in_bytes();
coleenp@3602 191
coleenp@3602 192 // Number of chunks in the free chunks list
coleenp@3602 193 size_t free_chunks_count();
coleenp@3602 194
coleenp@3602 195 void inc_free_chunks_total(size_t v, size_t count = 1) {
coleenp@3602 196 Atomic::add_ptr(count, &_free_chunks_count);
coleenp@3602 197 Atomic::add_ptr(v, &_free_chunks_total);
coleenp@3602 198 }
jmasa@3761 199 ChunkTreeDictionary* humongous_dictionary() {
jmasa@3761 200 return &_humongous_dictionary;
jmasa@3761 201 }
coleenp@3602 202
coleenp@3602 203 ChunkList* free_chunks(ChunkIndex index);
coleenp@3602 204
coleenp@3602 205 // Returns the list for the given chunk word size.
coleenp@3602 206 ChunkList* find_free_chunks_list(size_t word_size);
coleenp@3602 207
coleenp@3602 208 // Add and remove from a list by size. Selects
coleenp@3602 209 // list based on size of chunk.
coleenp@3602 210 void free_chunks_put(Metachunk* chuck);
coleenp@3602 211 Metachunk* free_chunks_get(size_t chunk_word_size);
coleenp@3602 212
coleenp@3602 213 // Debug support
coleenp@3602 214 void verify();
mgerdin@3829 215 void slow_verify() {
mgerdin@3829 216 if (metaspace_slow_verify) {
mgerdin@3829 217 verify();
mgerdin@3829 218 }
mgerdin@3829 219 }
coleenp@3602 220 void locked_verify();
mgerdin@3829 221 void slow_locked_verify() {
mgerdin@3829 222 if (metaspace_slow_verify) {
mgerdin@3829 223 locked_verify();
mgerdin@3829 224 }
mgerdin@3829 225 }
coleenp@3602 226 void verify_free_chunks_total();
coleenp@3602 227
coleenp@3602 228 void locked_print_free_chunks(outputStream* st);
coleenp@3602 229 void locked_print_sum_free_chunks(outputStream* st);
jmasa@3761 230
jmasa@3761 231 void print_on(outputStream* st);
coleenp@3602 232 };
coleenp@3602 233
coleenp@3602 234
coleenp@3602 235 // Used to manage the free list of Metablocks (a block corresponds
coleenp@3602 236 // to the allocation of a quantum of metadata).
coleenp@3602 237 class BlockFreelist VALUE_OBJ_CLASS_SPEC {
jmasa@3761 238 BlockTreeDictionary* _dictionary;
jmasa@3761 239 static Metablock* initialize_free_chunk(MetaWord* p, size_t word_size);
jmasa@3761 240
coleenp@3602 241 // Accessors
jmasa@3761 242 BlockTreeDictionary* dictionary() const { return _dictionary; }
coleenp@3602 243
coleenp@3602 244 public:
coleenp@3602 245 BlockFreelist();
coleenp@3602 246 ~BlockFreelist();
coleenp@3602 247
coleenp@3602 248 // Get and return a block to the free list
jmasa@3761 249 MetaWord* get_block(size_t word_size);
jmasa@3761 250 void return_block(MetaWord* p, size_t word_size);
jmasa@3761 251
jmasa@3761 252 size_t total_size() {
jmasa@3761 253 if (dictionary() == NULL) {
coleenp@3602 254 return 0;
jmasa@3761 255 } else {
jmasa@3761 256 return dictionary()->total_size();
coleenp@3602 257 }
jmasa@3761 258 }
coleenp@3602 259
coleenp@3602 260 void print_on(outputStream* st) const;
coleenp@3602 261 };
coleenp@3602 262
coleenp@3602 263 class VirtualSpaceNode : public CHeapObj<mtClass> {
coleenp@3602 264 friend class VirtualSpaceList;
coleenp@3602 265
coleenp@3602 266 // Link to next VirtualSpaceNode
coleenp@3602 267 VirtualSpaceNode* _next;
coleenp@3602 268
coleenp@3602 269 // total in the VirtualSpace
coleenp@3602 270 MemRegion _reserved;
coleenp@3602 271 ReservedSpace _rs;
coleenp@3602 272 VirtualSpace _virtual_space;
coleenp@3602 273 MetaWord* _top;
coleenp@3602 274
coleenp@3602 275 // Convenience functions for logical bottom and end
coleenp@3602 276 MetaWord* bottom() const { return (MetaWord*) _virtual_space.low(); }
coleenp@3602 277 MetaWord* end() const { return (MetaWord*) _virtual_space.high(); }
coleenp@3602 278
coleenp@3602 279 // Convenience functions to access the _virtual_space
coleenp@3602 280 char* low() const { return virtual_space()->low(); }
coleenp@3602 281 char* high() const { return virtual_space()->high(); }
coleenp@3602 282
coleenp@3602 283 public:
coleenp@3602 284
coleenp@3602 285 VirtualSpaceNode(size_t byte_size);
coleenp@3602 286 VirtualSpaceNode(ReservedSpace rs) : _top(NULL), _next(NULL), _rs(rs) {}
coleenp@3602 287 ~VirtualSpaceNode();
coleenp@3602 288
coleenp@3602 289 // address of next available space in _virtual_space;
coleenp@3602 290 // Accessors
coleenp@3602 291 VirtualSpaceNode* next() { return _next; }
coleenp@3602 292 void set_next(VirtualSpaceNode* v) { _next = v; }
coleenp@3602 293
coleenp@3602 294 void set_reserved(MemRegion const v) { _reserved = v; }
coleenp@3602 295 void set_top(MetaWord* v) { _top = v; }
coleenp@3602 296
coleenp@3602 297 // Accessors
coleenp@3602 298 MemRegion* reserved() { return &_reserved; }
coleenp@3602 299 VirtualSpace* virtual_space() const { return (VirtualSpace*) &_virtual_space; }
coleenp@3602 300
coleenp@3602 301 // Returns true if "word_size" is available in the virtual space
coleenp@3602 302 bool is_available(size_t word_size) { return _top + word_size <= end(); }
coleenp@3602 303
coleenp@3602 304 MetaWord* top() const { return _top; }
coleenp@3602 305 void inc_top(size_t word_size) { _top += word_size; }
coleenp@3602 306
coleenp@3602 307 // used and capacity in this single entry in the list
coleenp@3602 308 size_t used_words_in_vs() const;
coleenp@3602 309 size_t capacity_words_in_vs() const;
coleenp@3602 310
coleenp@3602 311 bool initialize();
coleenp@3602 312
coleenp@3602 313 // get space from the virtual space
coleenp@3602 314 Metachunk* take_from_committed(size_t chunk_word_size);
coleenp@3602 315
coleenp@3602 316 // Allocate a chunk from the virtual space and return it.
coleenp@3602 317 Metachunk* get_chunk_vs(size_t chunk_word_size);
coleenp@3602 318 Metachunk* get_chunk_vs_with_expand(size_t chunk_word_size);
coleenp@3602 319
coleenp@3602 320 // Expands/shrinks the committed space in a virtual space. Delegates
coleenp@3602 321 // to Virtualspace
coleenp@3602 322 bool expand_by(size_t words, bool pre_touch = false);
coleenp@3602 323 bool shrink_by(size_t words);
coleenp@3602 324
coleenp@3869 325 #ifdef ASSERT
coleenp@3602 326 // Debug support
coleenp@3602 327 static void verify_virtual_space_total();
coleenp@3602 328 static void verify_virtual_space_count();
coleenp@3602 329 void mangle();
coleenp@3869 330 #endif
coleenp@3602 331
coleenp@3602 332 void print_on(outputStream* st) const;
coleenp@3602 333 };
coleenp@3602 334
coleenp@3602 335 // byte_size is the size of the associated virtualspace.
coleenp@3602 336 VirtualSpaceNode::VirtualSpaceNode(size_t byte_size) : _top(NULL), _next(NULL), _rs(0) {
zgu@4317 337 // align up to vm allocation granularity
zgu@4317 338 byte_size = align_size_up(byte_size, os::vm_allocation_granularity());
zgu@4317 339
coleenp@4369 340 // This allocates memory with mmap. For DumpSharedspaces, try to reserve
coleenp@4369 341 // configurable address, generally at the top of the Java heap so other
coleenp@4369 342 // memory addresses don't conflict.
coleenp@3602 343 if (DumpSharedSpaces) {
coleenp@4369 344 char* shared_base = (char*)SharedBaseAddress;
coleenp@3602 345 _rs = ReservedSpace(byte_size, 0, false, shared_base, 0);
coleenp@3602 346 if (_rs.is_reserved()) {
coleenp@4369 347 assert(shared_base == 0 || _rs.base() == shared_base, "should match");
coleenp@3602 348 } else {
coleenp@4369 349 // Get a mmap region anywhere if the SharedBaseAddress fails.
coleenp@3602 350 _rs = ReservedSpace(byte_size);
coleenp@3602 351 }
coleenp@3602 352 MetaspaceShared::set_shared_rs(&_rs);
coleenp@3602 353 } else {
coleenp@3602 354 _rs = ReservedSpace(byte_size);
coleenp@3602 355 }
coleenp@3602 356
coleenp@3602 357 MemTracker::record_virtual_memory_type((address)_rs.base(), mtClass);
coleenp@3602 358 }
coleenp@3602 359
coleenp@3602 360 // List of VirtualSpaces for metadata allocation.
coleenp@3602 361 // It has a _next link for singly linked list and a MemRegion
coleenp@3602 362 // for total space in the VirtualSpace.
coleenp@3602 363 class VirtualSpaceList : public CHeapObj<mtClass> {
coleenp@3602 364 friend class VirtualSpaceNode;
coleenp@3602 365
coleenp@3602 366 enum VirtualSpaceSizes {
coleenp@3602 367 VirtualSpaceSize = 256 * K
coleenp@3602 368 };
coleenp@3602 369
coleenp@3602 370 // Global list of virtual spaces
coleenp@3602 371 // Head of the list
coleenp@3602 372 VirtualSpaceNode* _virtual_space_list;
coleenp@3602 373 // virtual space currently being used for allocations
coleenp@3602 374 VirtualSpaceNode* _current_virtual_space;
coleenp@3602 375 // Free chunk list for all other metadata
coleenp@3602 376 ChunkManager _chunk_manager;
coleenp@3602 377
coleenp@3602 378 // Can this virtual list allocate >1 spaces? Also, used to determine
coleenp@3602 379 // whether to allocate unlimited small chunks in this virtual space
coleenp@3602 380 bool _is_class;
coleenp@3602 381 bool can_grow() const { return !is_class() || !UseCompressedKlassPointers; }
coleenp@3602 382
coleenp@3602 383 // Sum of space in all virtual spaces and number of virtual spaces
coleenp@3602 384 size_t _virtual_space_total;
coleenp@3602 385 size_t _virtual_space_count;
coleenp@3602 386
coleenp@3602 387 ~VirtualSpaceList();
coleenp@3602 388
coleenp@3602 389 VirtualSpaceNode* virtual_space_list() const { return _virtual_space_list; }
coleenp@3602 390
coleenp@3602 391 void set_virtual_space_list(VirtualSpaceNode* v) {
coleenp@3602 392 _virtual_space_list = v;
coleenp@3602 393 }
coleenp@3602 394 void set_current_virtual_space(VirtualSpaceNode* v) {
coleenp@3602 395 _current_virtual_space = v;
coleenp@3602 396 }
coleenp@3602 397
coleenp@3602 398 void link_vs(VirtualSpaceNode* new_entry, size_t vs_word_size);
coleenp@3602 399
coleenp@3602 400 // Get another virtual space and add it to the list. This
coleenp@3602 401 // is typically prompted by a failed attempt to allocate a chunk
coleenp@3602 402 // and is typically followed by the allocation of a chunk.
coleenp@3602 403 bool grow_vs(size_t vs_word_size);
coleenp@3602 404
coleenp@3602 405 public:
coleenp@3602 406 VirtualSpaceList(size_t word_size);
coleenp@3602 407 VirtualSpaceList(ReservedSpace rs);
coleenp@3602 408
jmasa@3947 409 Metachunk* get_new_chunk(size_t word_size,
jmasa@3947 410 size_t grow_chunks_by_words,
jmasa@3947 411 size_t medium_chunk_bunch);
jmasa@3947 412
jmasa@3947 413 // Get the first chunk for a Metaspace. Used for
jmasa@3947 414 // special cases such as the boot class loader, reflection
jmasa@3947 415 // class loader and anonymous class loader.
jmasa@3947 416 Metachunk* get_initialization_chunk(size_t word_size, size_t chunk_bunch);
coleenp@3602 417
coleenp@3602 418 VirtualSpaceNode* current_virtual_space() {
coleenp@3602 419 return _current_virtual_space;
coleenp@3602 420 }
coleenp@3602 421
coleenp@3602 422 ChunkManager* chunk_manager() { return &_chunk_manager; }
coleenp@3602 423 bool is_class() const { return _is_class; }
coleenp@3602 424
coleenp@3602 425 // Allocate the first virtualspace.
coleenp@3602 426 void initialize(size_t word_size);
coleenp@3602 427
coleenp@3602 428 size_t virtual_space_total() { return _virtual_space_total; }
coleenp@3602 429 void inc_virtual_space_total(size_t v) {
coleenp@3602 430 Atomic::add_ptr(v, &_virtual_space_total);
coleenp@3602 431 }
coleenp@3602 432
coleenp@3602 433 size_t virtual_space_count() { return _virtual_space_count; }
coleenp@3602 434 void inc_virtual_space_count() {
coleenp@3602 435 Atomic::inc_ptr(&_virtual_space_count);
coleenp@3602 436 }
coleenp@3602 437
coleenp@3602 438 // Used and capacity in the entire list of virtual spaces.
coleenp@3602 439 // These are global values shared by all Metaspaces
coleenp@3602 440 size_t capacity_words_sum();
coleenp@3602 441 size_t capacity_bytes_sum() { return capacity_words_sum() * BytesPerWord; }
coleenp@3602 442 size_t used_words_sum();
coleenp@3602 443 size_t used_bytes_sum() { return used_words_sum() * BytesPerWord; }
coleenp@3602 444
coleenp@3602 445 bool contains(const void *ptr);
coleenp@3602 446
coleenp@3602 447 void print_on(outputStream* st) const;
coleenp@3602 448
coleenp@3602 449 class VirtualSpaceListIterator : public StackObj {
coleenp@3602 450 VirtualSpaceNode* _virtual_spaces;
coleenp@3602 451 public:
coleenp@3602 452 VirtualSpaceListIterator(VirtualSpaceNode* virtual_spaces) :
coleenp@3602 453 _virtual_spaces(virtual_spaces) {}
coleenp@3602 454
coleenp@3602 455 bool repeat() {
coleenp@3602 456 return _virtual_spaces != NULL;
coleenp@3602 457 }
coleenp@3602 458
coleenp@3602 459 VirtualSpaceNode* get_next() {
coleenp@3602 460 VirtualSpaceNode* result = _virtual_spaces;
coleenp@3602 461 if (_virtual_spaces != NULL) {
coleenp@3602 462 _virtual_spaces = _virtual_spaces->next();
coleenp@3602 463 }
coleenp@3602 464 return result;
coleenp@3602 465 }
coleenp@3602 466 };
coleenp@3602 467 };
coleenp@3602 468
coleenp@3602 469 class Metadebug : AllStatic {
coleenp@3602 470 // Debugging support for Metaspaces
coleenp@3602 471 static int _deallocate_block_a_lot_count;
coleenp@3602 472 static int _deallocate_chunk_a_lot_count;
coleenp@3602 473 static int _allocation_fail_alot_count;
coleenp@3602 474
coleenp@3602 475 public:
coleenp@3602 476 static int deallocate_block_a_lot_count() {
coleenp@3602 477 return _deallocate_block_a_lot_count;
coleenp@3602 478 }
coleenp@3602 479 static void set_deallocate_block_a_lot_count(int v) {
coleenp@3602 480 _deallocate_block_a_lot_count = v;
coleenp@3602 481 }
coleenp@3602 482 static void inc_deallocate_block_a_lot_count() {
coleenp@3602 483 _deallocate_block_a_lot_count++;
coleenp@3602 484 }
coleenp@3602 485 static int deallocate_chunk_a_lot_count() {
coleenp@3602 486 return _deallocate_chunk_a_lot_count;
coleenp@3602 487 }
coleenp@3602 488 static void reset_deallocate_chunk_a_lot_count() {
coleenp@3602 489 _deallocate_chunk_a_lot_count = 1;
coleenp@3602 490 }
coleenp@3602 491 static void inc_deallocate_chunk_a_lot_count() {
coleenp@3602 492 _deallocate_chunk_a_lot_count++;
coleenp@3602 493 }
coleenp@3602 494
coleenp@3602 495 static void init_allocation_fail_alot_count();
coleenp@3602 496 #ifdef ASSERT
coleenp@3602 497 static bool test_metadata_failure();
coleenp@3602 498 #endif
coleenp@3602 499
coleenp@3602 500 static void deallocate_chunk_a_lot(SpaceManager* sm,
coleenp@3602 501 size_t chunk_word_size);
coleenp@3602 502 static void deallocate_block_a_lot(SpaceManager* sm,
coleenp@3602 503 size_t chunk_word_size);
coleenp@3602 504
coleenp@3602 505 };
coleenp@3602 506
coleenp@3602 507 int Metadebug::_deallocate_block_a_lot_count = 0;
coleenp@3602 508 int Metadebug::_deallocate_chunk_a_lot_count = 0;
coleenp@3602 509 int Metadebug::_allocation_fail_alot_count = 0;
coleenp@3602 510
coleenp@3602 511 // SpaceManager - used by Metaspace to handle allocations
coleenp@3602 512 class SpaceManager : public CHeapObj<mtClass> {
coleenp@3602 513 friend class Metaspace;
coleenp@3602 514 friend class Metadebug;
coleenp@3602 515
coleenp@3602 516 private:
jmasa@3947 517
coleenp@3602 518 // protects allocations and contains.
coleenp@3602 519 Mutex* const _lock;
coleenp@3602 520
jmasa@3947 521 // Chunk related size
jmasa@3947 522 size_t _medium_chunk_bunch;
jmasa@3947 523
coleenp@3602 524 // List of chunks in use by this SpaceManager. Allocations
coleenp@3602 525 // are done from the current chunk. The list is used for deallocating
coleenp@3602 526 // chunks when the SpaceManager is freed.
jmasa@3761 527 Metachunk* _chunks_in_use[NumberOfInUseLists];
coleenp@3602 528 Metachunk* _current_chunk;
coleenp@3602 529
coleenp@3602 530 // Virtual space where allocation comes from.
coleenp@3602 531 VirtualSpaceList* _vs_list;
coleenp@3602 532
coleenp@3602 533 // Number of small chunks to allocate to a manager
coleenp@3602 534 // If class space manager, small chunks are unlimited
coleenp@3602 535 static uint const _small_chunk_limit;
coleenp@3602 536 bool has_small_chunk_limit() { return !vs_list()->is_class(); }
coleenp@3602 537
coleenp@3602 538 // Sum of all space in allocated chunks
coleenp@3602 539 size_t _allocation_total;
coleenp@3602 540
coleenp@3602 541 // Free lists of blocks are per SpaceManager since they
coleenp@3602 542 // are assumed to be in chunks in use by the SpaceManager
coleenp@3602 543 // and all chunks in use by a SpaceManager are freed when
coleenp@3602 544 // the class loader using the SpaceManager is collected.
coleenp@3602 545 BlockFreelist _block_freelists;
coleenp@3602 546
coleenp@3602 547 // protects virtualspace and chunk expansions
coleenp@3602 548 static const char* _expand_lock_name;
coleenp@3602 549 static const int _expand_lock_rank;
coleenp@3602 550 static Mutex* const _expand_lock;
coleenp@3602 551
jmasa@3947 552 private:
coleenp@3602 553 // Accessors
coleenp@3602 554 Metachunk* chunks_in_use(ChunkIndex index) const { return _chunks_in_use[index]; }
coleenp@3602 555 void set_chunks_in_use(ChunkIndex index, Metachunk* v) { _chunks_in_use[index] = v; }
coleenp@3602 556
coleenp@3602 557 BlockFreelist* block_freelists() const {
coleenp@3602 558 return (BlockFreelist*) &_block_freelists;
coleenp@3602 559 }
coleenp@3602 560
coleenp@3602 561 VirtualSpaceList* vs_list() const { return _vs_list; }
coleenp@3602 562
coleenp@3602 563 Metachunk* current_chunk() const { return _current_chunk; }
coleenp@3602 564 void set_current_chunk(Metachunk* v) {
coleenp@3602 565 _current_chunk = v;
coleenp@3602 566 }
coleenp@3602 567
coleenp@3602 568 Metachunk* find_current_chunk(size_t word_size);
coleenp@3602 569
coleenp@3602 570 // Add chunk to the list of chunks in use
coleenp@3602 571 void add_chunk(Metachunk* v, bool make_current);
coleenp@3602 572
coleenp@3602 573 Mutex* lock() const { return _lock; }
coleenp@3602 574
jmasa@3947 575 const char* chunk_size_name(ChunkIndex index) const;
jmasa@3947 576
jmasa@3947 577 protected:
jmasa@3947 578 void initialize();
jmasa@3947 579
coleenp@3602 580 public:
jmasa@3947 581 SpaceManager(Mutex* lock,
jmasa@3947 582 VirtualSpaceList* vs_list);
coleenp@3602 583 ~SpaceManager();
coleenp@3602 584
jmasa@3947 585 enum ChunkMultiples {
jmasa@3947 586 MediumChunkMultiple = 4
coleenp@3602 587 };
coleenp@3602 588
coleenp@3602 589 // Accessors
jmasa@3947 590 size_t specialized_chunk_size() { return SpecializedChunk; }
jmasa@3947 591 size_t small_chunk_size() { return (size_t) vs_list()->is_class() ? ClassSmallChunk : SmallChunk; }
jmasa@3947 592 size_t medium_chunk_size() { return (size_t) vs_list()->is_class() ? ClassMediumChunk : MediumChunk; }
jmasa@3947 593 size_t medium_chunk_bunch() { return medium_chunk_size() * MediumChunkMultiple; }
jmasa@3947 594
coleenp@3602 595 size_t allocation_total() const { return _allocation_total; }
coleenp@3602 596 void inc_allocation_total(size_t v) { Atomic::add_ptr(v, &_allocation_total); }
jmasa@3947 597 bool is_humongous(size_t word_size) { return word_size > medium_chunk_size(); }
coleenp@3602 598
coleenp@3602 599 static Mutex* expand_lock() { return _expand_lock; }
coleenp@3602 600
jmasa@3947 601 // Set the sizes for the initial chunks.
jmasa@3947 602 void get_initial_chunk_sizes(Metaspace::MetaspaceType type,
jmasa@3947 603 size_t* chunk_word_size,
jmasa@3947 604 size_t* class_chunk_word_size);
jmasa@3947 605
coleenp@3602 606 size_t sum_capacity_in_chunks_in_use() const;
coleenp@3602 607 size_t sum_used_in_chunks_in_use() const;
coleenp@3602 608 size_t sum_free_in_chunks_in_use() const;
coleenp@3602 609 size_t sum_waste_in_chunks_in_use() const;
coleenp@3602 610 size_t sum_waste_in_chunks_in_use(ChunkIndex index ) const;
coleenp@3602 611
coleenp@3602 612 size_t sum_count_in_chunks_in_use();
coleenp@3602 613 size_t sum_count_in_chunks_in_use(ChunkIndex i);
coleenp@3602 614
jmasa@3947 615 Metachunk* get_new_chunk(size_t word_size, size_t grow_chunks_by_words);
jmasa@3947 616
coleenp@3602 617 // Block allocation and deallocation.
coleenp@3602 618 // Allocates a block from the current chunk
coleenp@3602 619 MetaWord* allocate(size_t word_size);
coleenp@3602 620
coleenp@3602 621 // Helper for allocations
jmasa@3761 622 MetaWord* allocate_work(size_t word_size);
coleenp@3602 623
coleenp@3602 624 // Returns a block to the per manager freelist
jmasa@3761 625 void deallocate(MetaWord* p, size_t word_size);
coleenp@3602 626
coleenp@3602 627 // Based on the allocation size and a minimum chunk size,
coleenp@3602 628 // returned chunk size (for expanding space for chunk allocation).
coleenp@3602 629 size_t calc_chunk_size(size_t allocation_word_size);
coleenp@3602 630
coleenp@3602 631 // Called when an allocation from the current chunk fails.
coleenp@3602 632 // Gets a new chunk (may require getting a new virtual space),
coleenp@3602 633 // and allocates from that chunk.
jmasa@3761 634 MetaWord* grow_and_allocate(size_t word_size);
coleenp@3602 635
coleenp@3602 636 // debugging support.
coleenp@3602 637
coleenp@3602 638 void dump(outputStream* const out) const;
coleenp@3602 639 void print_on(outputStream* st) const;
coleenp@3602 640 void locked_print_chunks_in_use_on(outputStream* st) const;
coleenp@3602 641
coleenp@3602 642 void verify();
jmasa@3892 643 void verify_chunk_size(Metachunk* chunk);
coleenp@3869 644 NOT_PRODUCT(void mangle_freed_chunks();)
coleenp@3602 645 #ifdef ASSERT
coleenp@3602 646 void verify_allocation_total();
coleenp@3602 647 #endif
coleenp@3602 648 };
coleenp@3602 649
coleenp@3602 650 uint const SpaceManager::_small_chunk_limit = 4;
coleenp@3602 651
coleenp@3602 652 const char* SpaceManager::_expand_lock_name =
coleenp@3602 653 "SpaceManager chunk allocation lock";
coleenp@3602 654 const int SpaceManager::_expand_lock_rank = Monitor::leaf - 1;
coleenp@3602 655 Mutex* const SpaceManager::_expand_lock =
coleenp@3602 656 new Mutex(SpaceManager::_expand_lock_rank,
coleenp@3602 657 SpaceManager::_expand_lock_name,
coleenp@3602 658 Mutex::_allow_vm_block_flag);
coleenp@3602 659
coleenp@3602 660 // BlockFreelist methods
coleenp@3602 661
coleenp@3602 662 BlockFreelist::BlockFreelist() : _dictionary(NULL) {}
coleenp@3602 663
coleenp@3602 664 BlockFreelist::~BlockFreelist() {
coleenp@3602 665 if (_dictionary != NULL) {
coleenp@3602 666 if (Verbose && TraceMetadataChunkAllocation) {
coleenp@3602 667 _dictionary->print_free_lists(gclog_or_tty);
coleenp@3602 668 }
coleenp@3602 669 delete _dictionary;
coleenp@3602 670 }
coleenp@3602 671 }
coleenp@3602 672
jmasa@3761 673 Metablock* BlockFreelist::initialize_free_chunk(MetaWord* p, size_t word_size) {
jmasa@3761 674 Metablock* block = (Metablock*) p;
jmasa@3761 675 block->set_word_size(word_size);
jmasa@3761 676 block->set_prev(NULL);
jmasa@3761 677 block->set_next(NULL);
jmasa@3761 678
coleenp@3602 679 return block;
coleenp@3602 680 }
coleenp@3602 681
jmasa@3761 682 void BlockFreelist::return_block(MetaWord* p, size_t word_size) {
jmasa@3761 683 Metablock* free_chunk = initialize_free_chunk(p, word_size);
coleenp@3602 684 if (dictionary() == NULL) {
jmasa@3761 685 _dictionary = new BlockTreeDictionary();
coleenp@3602 686 }
jmasa@3761 687 dictionary()->return_chunk(free_chunk);
coleenp@3602 688 }
coleenp@3602 689
jmasa@3761 690 MetaWord* BlockFreelist::get_block(size_t word_size) {
coleenp@3602 691 if (dictionary() == NULL) {
coleenp@3602 692 return NULL;
coleenp@3602 693 }
coleenp@3602 694
jmasa@3761 695 if (word_size < TreeChunk<Metablock, FreeList>::min_size()) {
jmasa@3761 696 // Dark matter. Too small for dictionary.
coleenp@3602 697 return NULL;
coleenp@3602 698 }
jmasa@3761 699
jmasa@3761 700 Metablock* free_block =
jmasa@3761 701 dictionary()->get_chunk(word_size, FreeBlockDictionary<Metablock>::exactly);
jmasa@3761 702 if (free_block == NULL) {
jmasa@3761 703 return NULL;
jmasa@3761 704 }
jmasa@3761 705
jmasa@3761 706 return (MetaWord*) free_block;
coleenp@3602 707 }
coleenp@3602 708
coleenp@3602 709 void BlockFreelist::print_on(outputStream* st) const {
coleenp@3602 710 if (dictionary() == NULL) {
coleenp@3602 711 return;
coleenp@3602 712 }
coleenp@3602 713 dictionary()->print_free_lists(st);
coleenp@3602 714 }
coleenp@3602 715
coleenp@3602 716 // VirtualSpaceNode methods
coleenp@3602 717
coleenp@3602 718 VirtualSpaceNode::~VirtualSpaceNode() {
coleenp@3602 719 _rs.release();
coleenp@3602 720 }
coleenp@3602 721
coleenp@3602 722 size_t VirtualSpaceNode::used_words_in_vs() const {
coleenp@3602 723 return pointer_delta(top(), bottom(), sizeof(MetaWord));
coleenp@3602 724 }
coleenp@3602 725
coleenp@3602 726 // Space committed in the VirtualSpace
coleenp@3602 727 size_t VirtualSpaceNode::capacity_words_in_vs() const {
coleenp@3602 728 return pointer_delta(end(), bottom(), sizeof(MetaWord));
coleenp@3602 729 }
coleenp@3602 730
coleenp@3602 731
coleenp@3602 732 // Allocates the chunk from the virtual space only.
coleenp@3602 733 // This interface is also used internally for debugging. Not all
coleenp@3602 734 // chunks removed here are necessarily used for allocation.
coleenp@3602 735 Metachunk* VirtualSpaceNode::take_from_committed(size_t chunk_word_size) {
coleenp@3602 736 // Bottom of the new chunk
coleenp@3602 737 MetaWord* chunk_limit = top();
coleenp@3602 738 assert(chunk_limit != NULL, "Not safe to call this method");
coleenp@3602 739
coleenp@3602 740 if (!is_available(chunk_word_size)) {
coleenp@3602 741 if (TraceMetadataChunkAllocation) {
coleenp@3602 742 tty->print("VirtualSpaceNode::take_from_committed() not available %d words ", chunk_word_size);
coleenp@3602 743 // Dump some information about the virtual space that is nearly full
coleenp@3602 744 print_on(tty);
coleenp@3602 745 }
coleenp@3602 746 return NULL;
coleenp@3602 747 }
coleenp@3602 748
coleenp@3602 749 // Take the space (bump top on the current virtual space).
coleenp@3602 750 inc_top(chunk_word_size);
coleenp@3602 751
coleenp@3602 752 // Point the chunk at the space
coleenp@3602 753 Metachunk* result = Metachunk::initialize(chunk_limit, chunk_word_size);
coleenp@3602 754 return result;
coleenp@3602 755 }
coleenp@3602 756
coleenp@3602 757
coleenp@3602 758 // Expand the virtual space (commit more of the reserved space)
coleenp@3602 759 bool VirtualSpaceNode::expand_by(size_t words, bool pre_touch) {
coleenp@3602 760 size_t bytes = words * BytesPerWord;
coleenp@3602 761 bool result = virtual_space()->expand_by(bytes, pre_touch);
coleenp@3602 762 if (TraceMetavirtualspaceAllocation && !result) {
coleenp@3602 763 gclog_or_tty->print_cr("VirtualSpaceNode::expand_by() failed "
coleenp@3602 764 "for byte size " SIZE_FORMAT, bytes);
coleenp@3602 765 virtual_space()->print();
coleenp@3602 766 }
coleenp@3602 767 return result;
coleenp@3602 768 }
coleenp@3602 769
coleenp@3602 770 // Shrink the virtual space (commit more of the reserved space)
coleenp@3602 771 bool VirtualSpaceNode::shrink_by(size_t words) {
coleenp@3602 772 size_t bytes = words * BytesPerWord;
coleenp@3602 773 virtual_space()->shrink_by(bytes);
coleenp@3602 774 return true;
coleenp@3602 775 }
coleenp@3602 776
coleenp@3602 777 // Add another chunk to the chunk list.
coleenp@3602 778
coleenp@3602 779 Metachunk* VirtualSpaceNode::get_chunk_vs(size_t chunk_word_size) {
coleenp@3602 780 assert_lock_strong(SpaceManager::expand_lock());
coleenp@3602 781 Metachunk* result = NULL;
coleenp@3602 782
coleenp@3602 783 return take_from_committed(chunk_word_size);
coleenp@3602 784 }
coleenp@3602 785
coleenp@3602 786 Metachunk* VirtualSpaceNode::get_chunk_vs_with_expand(size_t chunk_word_size) {
coleenp@3602 787 assert_lock_strong(SpaceManager::expand_lock());
coleenp@3602 788
coleenp@3602 789 Metachunk* new_chunk = get_chunk_vs(chunk_word_size);
coleenp@3602 790
coleenp@3602 791 if (new_chunk == NULL) {
coleenp@3602 792 // Only a small part of the virtualspace is committed when first
coleenp@3602 793 // allocated so committing more here can be expected.
coleenp@3602 794 size_t page_size_words = os::vm_page_size() / BytesPerWord;
coleenp@3602 795 size_t aligned_expand_vs_by_words = align_size_up(chunk_word_size,
coleenp@3602 796 page_size_words);
coleenp@3602 797 expand_by(aligned_expand_vs_by_words, false);
coleenp@3602 798 new_chunk = get_chunk_vs(chunk_word_size);
coleenp@3602 799 }
coleenp@3602 800 return new_chunk;
coleenp@3602 801 }
coleenp@3602 802
coleenp@3602 803 bool VirtualSpaceNode::initialize() {
coleenp@3602 804
coleenp@3602 805 if (!_rs.is_reserved()) {
coleenp@3602 806 return false;
coleenp@3602 807 }
coleenp@3602 808
jmasa@3947 809 // An allocation out of this Virtualspace that is larger
jmasa@3947 810 // than an initial commit size can waste that initial committed
jmasa@3947 811 // space.
jmasa@3947 812 size_t committed_byte_size = 0;
coleenp@3602 813 bool result = virtual_space()->initialize(_rs, committed_byte_size);
coleenp@3602 814 if (result) {
coleenp@3602 815 set_top((MetaWord*)virtual_space()->low());
coleenp@3602 816 set_reserved(MemRegion((HeapWord*)_rs.base(),
coleenp@3602 817 (HeapWord*)(_rs.base() + _rs.size())));
coleenp@3603 818
coleenp@3603 819 assert(reserved()->start() == (HeapWord*) _rs.base(),
coleenp@3603 820 err_msg("Reserved start was not set properly " PTR_FORMAT
coleenp@3603 821 " != " PTR_FORMAT, reserved()->start(), _rs.base()));
coleenp@3603 822 assert(reserved()->word_size() == _rs.size() / BytesPerWord,
coleenp@3603 823 err_msg("Reserved size was not set properly " SIZE_FORMAT
coleenp@3603 824 " != " SIZE_FORMAT, reserved()->word_size(),
coleenp@3603 825 _rs.size() / BytesPerWord));
coleenp@3602 826 }
coleenp@3602 827
coleenp@3602 828 return result;
coleenp@3602 829 }
coleenp@3602 830
coleenp@3602 831 void VirtualSpaceNode::print_on(outputStream* st) const {
coleenp@3602 832 size_t used = used_words_in_vs();
coleenp@3602 833 size_t capacity = capacity_words_in_vs();
coleenp@3602 834 VirtualSpace* vs = virtual_space();
coleenp@3602 835 st->print_cr(" space @ " PTR_FORMAT " " SIZE_FORMAT "K, %3d%% used "
coleenp@3602 836 "[" PTR_FORMAT ", " PTR_FORMAT ", "
coleenp@3602 837 PTR_FORMAT ", " PTR_FORMAT ")",
jmasa@3947 838 vs, capacity / K,
jmasa@3947 839 capacity == 0 ? 0 : used * 100 / capacity,
coleenp@3602 840 bottom(), top(), end(),
coleenp@3602 841 vs->high_boundary());
coleenp@3602 842 }
coleenp@3602 843
coleenp@3869 844 #ifdef ASSERT
coleenp@3602 845 void VirtualSpaceNode::mangle() {
coleenp@3602 846 size_t word_size = capacity_words_in_vs();
coleenp@3602 847 Copy::fill_to_words((HeapWord*) low(), word_size, 0xf1f1f1f1);
coleenp@3602 848 }
coleenp@3869 849 #endif // ASSERT
coleenp@3602 850
coleenp@3602 851 // VirtualSpaceList methods
coleenp@3602 852 // Space allocated from the VirtualSpace
coleenp@3602 853
coleenp@3602 854 VirtualSpaceList::~VirtualSpaceList() {
coleenp@3602 855 VirtualSpaceListIterator iter(virtual_space_list());
coleenp@3602 856 while (iter.repeat()) {
coleenp@3602 857 VirtualSpaceNode* vsl = iter.get_next();
coleenp@3602 858 delete vsl;
coleenp@3602 859 }
coleenp@3602 860 }
coleenp@3602 861
coleenp@3602 862 size_t VirtualSpaceList::used_words_sum() {
coleenp@3602 863 size_t allocated_by_vs = 0;
coleenp@3602 864 VirtualSpaceListIterator iter(virtual_space_list());
coleenp@3602 865 while (iter.repeat()) {
coleenp@3602 866 VirtualSpaceNode* vsl = iter.get_next();
coleenp@3602 867 // Sum used region [bottom, top) in each virtualspace
coleenp@3602 868 allocated_by_vs += vsl->used_words_in_vs();
coleenp@3602 869 }
coleenp@3602 870 assert(allocated_by_vs >= chunk_manager()->free_chunks_total(),
coleenp@3602 871 err_msg("Total in free chunks " SIZE_FORMAT
coleenp@3602 872 " greater than total from virtual_spaces " SIZE_FORMAT,
coleenp@3602 873 allocated_by_vs, chunk_manager()->free_chunks_total()));
coleenp@3602 874 size_t used =
coleenp@3602 875 allocated_by_vs - chunk_manager()->free_chunks_total();
coleenp@3602 876 return used;
coleenp@3602 877 }
coleenp@3602 878
coleenp@3602 879 // Space available in all MetadataVirtualspaces allocated
coleenp@3602 880 // for metadata. This is the upper limit on the capacity
coleenp@3602 881 // of chunks allocated out of all the MetadataVirtualspaces.
coleenp@3602 882 size_t VirtualSpaceList::capacity_words_sum() {
coleenp@3602 883 size_t capacity = 0;
coleenp@3602 884 VirtualSpaceListIterator iter(virtual_space_list());
coleenp@3602 885 while (iter.repeat()) {
coleenp@3602 886 VirtualSpaceNode* vsl = iter.get_next();
coleenp@3602 887 capacity += vsl->capacity_words_in_vs();
coleenp@3602 888 }
coleenp@3602 889 return capacity;
coleenp@3602 890 }
coleenp@3602 891
coleenp@3602 892 VirtualSpaceList::VirtualSpaceList(size_t word_size ) :
coleenp@3602 893 _is_class(false),
coleenp@3602 894 _virtual_space_list(NULL),
coleenp@3602 895 _current_virtual_space(NULL),
coleenp@3602 896 _virtual_space_total(0),
coleenp@3602 897 _virtual_space_count(0) {
coleenp@3602 898 MutexLockerEx cl(SpaceManager::expand_lock(),
coleenp@3602 899 Mutex::_no_safepoint_check_flag);
coleenp@3602 900 bool initialization_succeeded = grow_vs(word_size);
coleenp@3602 901
coleenp@3602 902 assert(initialization_succeeded,
coleenp@3602 903 " VirtualSpaceList initialization should not fail");
coleenp@3602 904 }
coleenp@3602 905
coleenp@3602 906 VirtualSpaceList::VirtualSpaceList(ReservedSpace rs) :
coleenp@3602 907 _is_class(true),
coleenp@3602 908 _virtual_space_list(NULL),
coleenp@3602 909 _current_virtual_space(NULL),
coleenp@3602 910 _virtual_space_total(0),
coleenp@3602 911 _virtual_space_count(0) {
coleenp@3602 912 MutexLockerEx cl(SpaceManager::expand_lock(),
coleenp@3602 913 Mutex::_no_safepoint_check_flag);
coleenp@3602 914 VirtualSpaceNode* class_entry = new VirtualSpaceNode(rs);
coleenp@3602 915 bool succeeded = class_entry->initialize();
coleenp@3602 916 assert(succeeded, " VirtualSpaceList initialization should not fail");
coleenp@3602 917 link_vs(class_entry, rs.size()/BytesPerWord);
coleenp@3602 918 }
coleenp@3602 919
coleenp@3602 920 // Allocate another meta virtual space and add it to the list.
coleenp@3602 921 bool VirtualSpaceList::grow_vs(size_t vs_word_size) {
coleenp@3602 922 assert_lock_strong(SpaceManager::expand_lock());
coleenp@3602 923 if (vs_word_size == 0) {
coleenp@3602 924 return false;
coleenp@3602 925 }
coleenp@3602 926 // Reserve the space
coleenp@3602 927 size_t vs_byte_size = vs_word_size * BytesPerWord;
coleenp@3602 928 assert(vs_byte_size % os::vm_page_size() == 0, "Not aligned");
coleenp@3602 929
coleenp@3602 930 // Allocate the meta virtual space and initialize it.
coleenp@3602 931 VirtualSpaceNode* new_entry = new VirtualSpaceNode(vs_byte_size);
coleenp@3602 932 if (!new_entry->initialize()) {
coleenp@3602 933 delete new_entry;
coleenp@3602 934 return false;
coleenp@3602 935 } else {
coleenp@3860 936 // ensure lock-free iteration sees fully initialized node
coleenp@3860 937 OrderAccess::storestore();
coleenp@3602 938 link_vs(new_entry, vs_word_size);
coleenp@3602 939 return true;
coleenp@3602 940 }
coleenp@3602 941 }
coleenp@3602 942
coleenp@3602 943 void VirtualSpaceList::link_vs(VirtualSpaceNode* new_entry, size_t vs_word_size) {
coleenp@3602 944 if (virtual_space_list() == NULL) {
coleenp@3602 945 set_virtual_space_list(new_entry);
coleenp@3602 946 } else {
coleenp@3602 947 current_virtual_space()->set_next(new_entry);
coleenp@3602 948 }
coleenp@3602 949 set_current_virtual_space(new_entry);
coleenp@3602 950 inc_virtual_space_total(vs_word_size);
coleenp@3602 951 inc_virtual_space_count();
coleenp@3602 952 #ifdef ASSERT
coleenp@3602 953 new_entry->mangle();
coleenp@3602 954 #endif
coleenp@3602 955 if (TraceMetavirtualspaceAllocation && Verbose) {
coleenp@3602 956 VirtualSpaceNode* vsl = current_virtual_space();
coleenp@3602 957 vsl->print_on(tty);
coleenp@3602 958 }
coleenp@3602 959 }
coleenp@3602 960
coleenp@3602 961 Metachunk* VirtualSpaceList::get_new_chunk(size_t word_size,
jmasa@3947 962 size_t grow_chunks_by_words,
jmasa@3947 963 size_t medium_chunk_bunch) {
coleenp@3602 964
coleenp@3602 965 // Get a chunk from the chunk freelist
coleenp@3602 966 Metachunk* next = chunk_manager()->chunk_freelist_allocate(grow_chunks_by_words);
coleenp@3602 967
coleenp@3602 968 // Allocate a chunk out of the current virtual space.
coleenp@3602 969 if (next == NULL) {
coleenp@3602 970 next = current_virtual_space()->get_chunk_vs(grow_chunks_by_words);
coleenp@3602 971 }
coleenp@3602 972
coleenp@3602 973 if (next == NULL) {
coleenp@3602 974 // Not enough room in current virtual space. Try to commit
coleenp@3602 975 // more space.
jmasa@3947 976 size_t expand_vs_by_words = MAX2(medium_chunk_bunch,
jmasa@3947 977 grow_chunks_by_words);
coleenp@3602 978 size_t page_size_words = os::vm_page_size() / BytesPerWord;
coleenp@3602 979 size_t aligned_expand_vs_by_words = align_size_up(expand_vs_by_words,
coleenp@3602 980 page_size_words);
coleenp@3602 981 bool vs_expanded =
coleenp@3602 982 current_virtual_space()->expand_by(aligned_expand_vs_by_words, false);
coleenp@3602 983 if (!vs_expanded) {
coleenp@3602 984 // Should the capacity of the metaspaces be expanded for
coleenp@3602 985 // this allocation? If it's the virtual space for classes and is
coleenp@3602 986 // being used for CompressedHeaders, don't allocate a new virtualspace.
coleenp@3602 987 if (can_grow() && MetaspaceGC::should_expand(this, word_size)) {
coleenp@3602 988 // Get another virtual space.
coleenp@3602 989 size_t grow_vs_words =
coleenp@3602 990 MAX2((size_t)VirtualSpaceSize, aligned_expand_vs_by_words);
coleenp@3602 991 if (grow_vs(grow_vs_words)) {
coleenp@3602 992 // Got it. It's on the list now. Get a chunk from it.
coleenp@3602 993 next = current_virtual_space()->get_chunk_vs_with_expand(grow_chunks_by_words);
coleenp@3602 994 }
coleenp@3602 995 } else {
coleenp@3602 996 // Allocation will fail and induce a GC
coleenp@3602 997 if (TraceMetadataChunkAllocation && Verbose) {
coleenp@3602 998 gclog_or_tty->print_cr("VirtualSpaceList::get_new_chunk():"
coleenp@3602 999 " Fail instead of expand the metaspace");
coleenp@3602 1000 }
coleenp@3602 1001 }
coleenp@3602 1002 } else {
coleenp@3602 1003 // The virtual space expanded, get a new chunk
coleenp@3602 1004 next = current_virtual_space()->get_chunk_vs(grow_chunks_by_words);
coleenp@3602 1005 assert(next != NULL, "Just expanded, should succeed");
coleenp@3602 1006 }
coleenp@3602 1007 }
coleenp@3602 1008
jmasa@3947 1009 assert(next == NULL || (next->next() == NULL && next->prev() == NULL),
jmasa@3947 1010 "New chunk is still on some list");
coleenp@3602 1011 return next;
coleenp@3602 1012 }
coleenp@3602 1013
jmasa@3947 1014 Metachunk* VirtualSpaceList::get_initialization_chunk(size_t chunk_word_size,
jmasa@3947 1015 size_t chunk_bunch) {
jmasa@3947 1016 // Get a chunk from the chunk freelist
jmasa@3947 1017 Metachunk* new_chunk = get_new_chunk(chunk_word_size,
jmasa@3947 1018 chunk_word_size,
jmasa@3947 1019 chunk_bunch);
jmasa@3947 1020 return new_chunk;
jmasa@3947 1021 }
jmasa@3947 1022
coleenp@3602 1023 void VirtualSpaceList::print_on(outputStream* st) const {
coleenp@3602 1024 if (TraceMetadataChunkAllocation && Verbose) {
coleenp@3602 1025 VirtualSpaceListIterator iter(virtual_space_list());
coleenp@3602 1026 while (iter.repeat()) {
coleenp@3602 1027 VirtualSpaceNode* node = iter.get_next();
coleenp@3602 1028 node->print_on(st);
coleenp@3602 1029 }
coleenp@3602 1030 }
coleenp@3602 1031 }
coleenp@3602 1032
coleenp@3602 1033 bool VirtualSpaceList::contains(const void *ptr) {
coleenp@3602 1034 VirtualSpaceNode* list = virtual_space_list();
coleenp@3602 1035 VirtualSpaceListIterator iter(list);
coleenp@3602 1036 while (iter.repeat()) {
coleenp@3602 1037 VirtualSpaceNode* node = iter.get_next();
coleenp@3602 1038 if (node->reserved()->contains(ptr)) {
coleenp@3602 1039 return true;
coleenp@3602 1040 }
coleenp@3602 1041 }
coleenp@3602 1042 return false;
coleenp@3602 1043 }
coleenp@3602 1044
coleenp@3602 1045
coleenp@3602 1046 // MetaspaceGC methods
coleenp@3602 1047
coleenp@3602 1048 // VM_CollectForMetadataAllocation is the vm operation used to GC.
coleenp@3602 1049 // Within the VM operation after the GC the attempt to allocate the metadata
coleenp@3602 1050 // should succeed. If the GC did not free enough space for the metaspace
coleenp@3602 1051 // allocation, the HWM is increased so that another virtualspace will be
coleenp@3602 1052 // allocated for the metadata. With perm gen the increase in the perm
coleenp@3602 1053 // gen had bounds, MinMetaspaceExpansion and MaxMetaspaceExpansion. The
coleenp@3602 1054 // metaspace policy uses those as the small and large steps for the HWM.
coleenp@3602 1055 //
coleenp@3602 1056 // After the GC the compute_new_size() for MetaspaceGC is called to
coleenp@3602 1057 // resize the capacity of the metaspaces. The current implementation
jmasa@4146 1058 // is based on the flags MinMetaspaceFreeRatio and MaxHeapFreeRatio used
coleenp@3602 1059 // to resize the Java heap by some GC's. New flags can be implemented
coleenp@3602 1060 // if really needed. MinHeapFreeRatio is used to calculate how much
coleenp@3602 1061 // free space is desirable in the metaspace capacity to decide how much
jmasa@4146 1062 // to increase the HWM. MaxMetaspaceFreeRatio is used to decide how much
coleenp@3602 1063 // free space is desirable in the metaspace capacity before decreasing
coleenp@3602 1064 // the HWM.
coleenp@3602 1065
coleenp@3602 1066 // Calculate the amount to increase the high water mark (HWM).
coleenp@3602 1067 // Increase by a minimum amount (MinMetaspaceExpansion) so that
coleenp@3602 1068 // another expansion is not requested too soon. If that is not
coleenp@3602 1069 // enough to satisfy the allocation (i.e. big enough for a word_size
coleenp@3602 1070 // allocation), increase by MaxMetaspaceExpansion. If that is still
coleenp@3602 1071 // not enough, expand by the size of the allocation (word_size) plus
coleenp@3602 1072 // some.
coleenp@3602 1073 size_t MetaspaceGC::delta_capacity_until_GC(size_t word_size) {
coleenp@3602 1074 size_t before_inc = MetaspaceGC::capacity_until_GC();
coleenp@3602 1075 size_t min_delta_words = MinMetaspaceExpansion / BytesPerWord;
coleenp@3602 1076 size_t max_delta_words = MaxMetaspaceExpansion / BytesPerWord;
coleenp@3602 1077 size_t page_size_words = os::vm_page_size() / BytesPerWord;
coleenp@3602 1078 size_t size_delta_words = align_size_up(word_size, page_size_words);
coleenp@3602 1079 size_t delta_words = MAX2(size_delta_words, min_delta_words);
coleenp@3602 1080 if (delta_words > min_delta_words) {
coleenp@3602 1081 // Don't want to hit the high water mark on the next
coleenp@3602 1082 // allocation so make the delta greater than just enough
coleenp@3602 1083 // for this allocation.
coleenp@3602 1084 delta_words = MAX2(delta_words, max_delta_words);
coleenp@3602 1085 if (delta_words > max_delta_words) {
coleenp@3602 1086 // This allocation is large but the next ones are probably not
coleenp@3602 1087 // so increase by the minimum.
coleenp@3602 1088 delta_words = delta_words + min_delta_words;
coleenp@3602 1089 }
coleenp@3602 1090 }
coleenp@3602 1091 return delta_words;
coleenp@3602 1092 }
coleenp@3602 1093
coleenp@3602 1094 bool MetaspaceGC::should_expand(VirtualSpaceList* vsl, size_t word_size) {
coleenp@3602 1095
coleenp@3602 1096 // Class virtual space should always be expanded. Call GC for the other
coleenp@3602 1097 // metadata virtual space.
coleenp@3602 1098 if (vsl == Metaspace::class_space_list()) return true;
coleenp@3602 1099
coleenp@3602 1100 // If the user wants a limit, impose one.
coleenp@3602 1101 size_t max_metaspace_size_words = MaxMetaspaceSize / BytesPerWord;
coleenp@3602 1102 size_t metaspace_size_words = MetaspaceSize / BytesPerWord;
coleenp@3602 1103 if (!FLAG_IS_DEFAULT(MaxMetaspaceSize) &&
coleenp@3602 1104 vsl->capacity_words_sum() >= max_metaspace_size_words) {
coleenp@3602 1105 return false;
coleenp@3602 1106 }
coleenp@3602 1107
coleenp@3602 1108 // If this is part of an allocation after a GC, expand
coleenp@3602 1109 // unconditionally.
coleenp@3602 1110 if(MetaspaceGC::expand_after_GC()) {
coleenp@3602 1111 return true;
coleenp@3602 1112 }
coleenp@3602 1113
coleenp@3602 1114 // If the capacity is below the minimum capacity, allow the
coleenp@3602 1115 // expansion. Also set the high-water-mark (capacity_until_GC)
coleenp@3602 1116 // to that minimum capacity so that a GC will not be induced
coleenp@3602 1117 // until that minimum capacity is exceeded.
coleenp@3602 1118 if (vsl->capacity_words_sum() < metaspace_size_words ||
coleenp@3602 1119 capacity_until_GC() == 0) {
coleenp@3602 1120 set_capacity_until_GC(metaspace_size_words);
coleenp@3602 1121 return true;
coleenp@3602 1122 } else {
coleenp@3602 1123 if (vsl->capacity_words_sum() < capacity_until_GC()) {
coleenp@3602 1124 return true;
coleenp@3602 1125 } else {
coleenp@3602 1126 if (TraceMetadataChunkAllocation && Verbose) {
coleenp@3602 1127 gclog_or_tty->print_cr(" allocation request size " SIZE_FORMAT
coleenp@3602 1128 " capacity_until_GC " SIZE_FORMAT
coleenp@3602 1129 " capacity_words_sum " SIZE_FORMAT
coleenp@3602 1130 " used_words_sum " SIZE_FORMAT
coleenp@3602 1131 " free chunks " SIZE_FORMAT
coleenp@3602 1132 " free chunks count %d",
coleenp@3602 1133 word_size,
coleenp@3602 1134 capacity_until_GC(),
coleenp@3602 1135 vsl->capacity_words_sum(),
coleenp@3602 1136 vsl->used_words_sum(),
coleenp@3602 1137 vsl->chunk_manager()->free_chunks_total(),
coleenp@3602 1138 vsl->chunk_manager()->free_chunks_count());
coleenp@3602 1139 }
coleenp@3602 1140 return false;
coleenp@3602 1141 }
coleenp@3602 1142 }
coleenp@3602 1143 }
coleenp@3602 1144
coleenp@3602 1145 // Variables are in bytes
coleenp@3602 1146
coleenp@3602 1147 void MetaspaceGC::compute_new_size() {
coleenp@3602 1148 assert(_shrink_factor <= 100, "invalid shrink factor");
coleenp@3602 1149 uint current_shrink_factor = _shrink_factor;
coleenp@3602 1150 _shrink_factor = 0;
coleenp@3602 1151
coleenp@3602 1152 VirtualSpaceList *vsl = Metaspace::space_list();
coleenp@3602 1153
coleenp@3602 1154 size_t capacity_after_gc = vsl->capacity_bytes_sum();
coleenp@3602 1155 // Check to see if these two can be calculated without walking the CLDG
coleenp@3602 1156 size_t used_after_gc = vsl->used_bytes_sum();
coleenp@3602 1157 size_t capacity_until_GC = vsl->capacity_bytes_sum();
coleenp@3602 1158 size_t free_after_gc = capacity_until_GC - used_after_gc;
coleenp@3602 1159
jmasa@4146 1160 const double minimum_free_percentage = MinMetaspaceFreeRatio / 100.0;
coleenp@3602 1161 const double maximum_used_percentage = 1.0 - minimum_free_percentage;
coleenp@3602 1162
coleenp@3602 1163 const double min_tmp = used_after_gc / maximum_used_percentage;
coleenp@3602 1164 size_t minimum_desired_capacity =
coleenp@3602 1165 (size_t)MIN2(min_tmp, double(max_uintx));
coleenp@3602 1166 // Don't shrink less than the initial generation size
coleenp@3602 1167 minimum_desired_capacity = MAX2(minimum_desired_capacity,
coleenp@3602 1168 MetaspaceSize);
coleenp@3602 1169
coleenp@3602 1170 if (PrintGCDetails && Verbose) {
coleenp@3602 1171 const double free_percentage = ((double)free_after_gc) / capacity_until_GC;
coleenp@3602 1172 gclog_or_tty->print_cr("\nMetaspaceGC::compute_new_size: ");
coleenp@3602 1173 gclog_or_tty->print_cr(" "
coleenp@3602 1174 " minimum_free_percentage: %6.2f"
coleenp@3602 1175 " maximum_used_percentage: %6.2f",
coleenp@3602 1176 minimum_free_percentage,
coleenp@3602 1177 maximum_used_percentage);
coleenp@3602 1178 double d_free_after_gc = free_after_gc / (double) K;
coleenp@3602 1179 gclog_or_tty->print_cr(" "
coleenp@3602 1180 " free_after_gc : %6.1fK"
coleenp@3602 1181 " used_after_gc : %6.1fK"
coleenp@3602 1182 " capacity_after_gc : %6.1fK"
coleenp@3602 1183 " metaspace HWM : %6.1fK",
coleenp@3602 1184 free_after_gc / (double) K,
coleenp@3602 1185 used_after_gc / (double) K,
coleenp@3602 1186 capacity_after_gc / (double) K,
coleenp@3602 1187 capacity_until_GC / (double) K);
coleenp@3602 1188 gclog_or_tty->print_cr(" "
coleenp@3602 1189 " free_percentage: %6.2f",
coleenp@3602 1190 free_percentage);
coleenp@3602 1191 }
coleenp@3602 1192
coleenp@3602 1193
coleenp@3602 1194 if (capacity_until_GC < minimum_desired_capacity) {
coleenp@3602 1195 // If we have less capacity below the metaspace HWM, then
coleenp@3602 1196 // increment the HWM.
coleenp@3602 1197 size_t expand_bytes = minimum_desired_capacity - capacity_until_GC;
coleenp@3602 1198 // Don't expand unless it's significant
coleenp@3602 1199 if (expand_bytes >= MinMetaspaceExpansion) {
coleenp@3602 1200 size_t expand_words = expand_bytes / BytesPerWord;
coleenp@3602 1201 MetaspaceGC::inc_capacity_until_GC(expand_words);
coleenp@3602 1202 }
coleenp@3602 1203 if (PrintGCDetails && Verbose) {
coleenp@3602 1204 size_t new_capacity_until_GC = MetaspaceGC::capacity_until_GC_in_bytes();
coleenp@3602 1205 gclog_or_tty->print_cr(" expanding:"
coleenp@3602 1206 " minimum_desired_capacity: %6.1fK"
coleenp@3602 1207 " expand_words: %6.1fK"
coleenp@3602 1208 " MinMetaspaceExpansion: %6.1fK"
coleenp@3602 1209 " new metaspace HWM: %6.1fK",
coleenp@3602 1210 minimum_desired_capacity / (double) K,
coleenp@3602 1211 expand_bytes / (double) K,
coleenp@3602 1212 MinMetaspaceExpansion / (double) K,
coleenp@3602 1213 new_capacity_until_GC / (double) K);
coleenp@3602 1214 }
coleenp@3602 1215 return;
coleenp@3602 1216 }
coleenp@3602 1217
coleenp@3602 1218 // No expansion, now see if we want to shrink
coleenp@3602 1219 size_t shrink_words = 0;
coleenp@3602 1220 // We would never want to shrink more than this
coleenp@3602 1221 size_t max_shrink_words = capacity_until_GC - minimum_desired_capacity;
coleenp@3602 1222 assert(max_shrink_words >= 0, err_msg("max_shrink_words " SIZE_FORMAT,
coleenp@3602 1223 max_shrink_words));
coleenp@3602 1224
coleenp@3602 1225 // Should shrinking be considered?
jmasa@4146 1226 if (MaxMetaspaceFreeRatio < 100) {
jmasa@4146 1227 const double maximum_free_percentage = MaxMetaspaceFreeRatio / 100.0;
coleenp@3602 1228 const double minimum_used_percentage = 1.0 - maximum_free_percentage;
coleenp@3602 1229 const double max_tmp = used_after_gc / minimum_used_percentage;
coleenp@3602 1230 size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx));
coleenp@3602 1231 maximum_desired_capacity = MAX2(maximum_desired_capacity,
coleenp@3602 1232 MetaspaceSize);
coleenp@3602 1233 if (PrintGC && Verbose) {
coleenp@3602 1234 gclog_or_tty->print_cr(" "
coleenp@3602 1235 " maximum_free_percentage: %6.2f"
coleenp@3602 1236 " minimum_used_percentage: %6.2f",
coleenp@3602 1237 maximum_free_percentage,
coleenp@3602 1238 minimum_used_percentage);
coleenp@3602 1239 gclog_or_tty->print_cr(" "
coleenp@3602 1240 " capacity_until_GC: %6.1fK"
coleenp@3602 1241 " minimum_desired_capacity: %6.1fK"
coleenp@3602 1242 " maximum_desired_capacity: %6.1fK",
coleenp@3602 1243 capacity_until_GC / (double) K,
coleenp@3602 1244 minimum_desired_capacity / (double) K,
coleenp@3602 1245 maximum_desired_capacity / (double) K);
coleenp@3602 1246 }
coleenp@3602 1247
coleenp@3602 1248 assert(minimum_desired_capacity <= maximum_desired_capacity,
coleenp@3602 1249 "sanity check");
coleenp@3602 1250
coleenp@3602 1251 if (capacity_until_GC > maximum_desired_capacity) {
coleenp@3602 1252 // Capacity too large, compute shrinking size
coleenp@3602 1253 shrink_words = capacity_until_GC - maximum_desired_capacity;
coleenp@3602 1254 // We don't want shrink all the way back to initSize if people call
coleenp@3602 1255 // System.gc(), because some programs do that between "phases" and then
coleenp@3602 1256 // we'd just have to grow the heap up again for the next phase. So we
coleenp@3602 1257 // damp the shrinking: 0% on the first call, 10% on the second call, 40%
coleenp@3602 1258 // on the third call, and 100% by the fourth call. But if we recompute
coleenp@3602 1259 // size without shrinking, it goes back to 0%.
coleenp@3602 1260 shrink_words = shrink_words / 100 * current_shrink_factor;
coleenp@3602 1261 assert(shrink_words <= max_shrink_words,
coleenp@3602 1262 err_msg("invalid shrink size " SIZE_FORMAT " not <= " SIZE_FORMAT,
coleenp@3602 1263 shrink_words, max_shrink_words));
coleenp@3602 1264 if (current_shrink_factor == 0) {
coleenp@3602 1265 _shrink_factor = 10;
coleenp@3602 1266 } else {
coleenp@3602 1267 _shrink_factor = MIN2(current_shrink_factor * 4, (uint) 100);
coleenp@3602 1268 }
coleenp@3602 1269 if (PrintGCDetails && Verbose) {
coleenp@3602 1270 gclog_or_tty->print_cr(" "
coleenp@3602 1271 " shrinking:"
coleenp@3602 1272 " initSize: %.1fK"
coleenp@3602 1273 " maximum_desired_capacity: %.1fK",
coleenp@3602 1274 MetaspaceSize / (double) K,
coleenp@3602 1275 maximum_desired_capacity / (double) K);
coleenp@3602 1276 gclog_or_tty->print_cr(" "
coleenp@3602 1277 " shrink_words: %.1fK"
coleenp@3602 1278 " current_shrink_factor: %d"
coleenp@3602 1279 " new shrink factor: %d"
coleenp@3602 1280 " MinMetaspaceExpansion: %.1fK",
coleenp@3602 1281 shrink_words / (double) K,
coleenp@3602 1282 current_shrink_factor,
coleenp@3602 1283 _shrink_factor,
coleenp@3602 1284 MinMetaspaceExpansion / (double) K);
coleenp@3602 1285 }
coleenp@3602 1286 }
coleenp@3602 1287 }
coleenp@3602 1288
coleenp@3602 1289
coleenp@3602 1290 // Don't shrink unless it's significant
coleenp@3602 1291 if (shrink_words >= MinMetaspaceExpansion) {
coleenp@3602 1292 VirtualSpaceNode* csp = vsl->current_virtual_space();
coleenp@3602 1293 size_t available_to_shrink = csp->capacity_words_in_vs() -
coleenp@3602 1294 csp->used_words_in_vs();
coleenp@3602 1295 shrink_words = MIN2(shrink_words, available_to_shrink);
coleenp@3602 1296 csp->shrink_by(shrink_words);
coleenp@3602 1297 MetaspaceGC::dec_capacity_until_GC(shrink_words);
coleenp@3602 1298 if (PrintGCDetails && Verbose) {
coleenp@3602 1299 size_t new_capacity_until_GC = MetaspaceGC::capacity_until_GC_in_bytes();
coleenp@3602 1300 gclog_or_tty->print_cr(" metaspace HWM: %.1fK", new_capacity_until_GC / (double) K);
coleenp@3602 1301 }
coleenp@3602 1302 }
coleenp@3602 1303 assert(vsl->used_bytes_sum() == used_after_gc &&
coleenp@3602 1304 used_after_gc <= vsl->capacity_bytes_sum(),
coleenp@3602 1305 "sanity check");
coleenp@3602 1306
coleenp@3602 1307 }
coleenp@3602 1308
coleenp@3602 1309 // Metadebug methods
coleenp@3602 1310
coleenp@3602 1311 void Metadebug::deallocate_chunk_a_lot(SpaceManager* sm,
coleenp@3602 1312 size_t chunk_word_size){
coleenp@3602 1313 #ifdef ASSERT
coleenp@3602 1314 VirtualSpaceList* vsl = sm->vs_list();
coleenp@3602 1315 if (MetaDataDeallocateALot &&
coleenp@3602 1316 Metadebug::deallocate_chunk_a_lot_count() % MetaDataDeallocateALotInterval == 0 ) {
coleenp@3602 1317 Metadebug::reset_deallocate_chunk_a_lot_count();
coleenp@3602 1318 for (uint i = 0; i < metadata_deallocate_a_lock_chunk; i++) {
coleenp@3602 1319 Metachunk* dummy_chunk = vsl->current_virtual_space()->take_from_committed(chunk_word_size);
coleenp@3602 1320 if (dummy_chunk == NULL) {
coleenp@3602 1321 break;
coleenp@3602 1322 }
coleenp@3602 1323 vsl->chunk_manager()->chunk_freelist_deallocate(dummy_chunk);
coleenp@3602 1324
coleenp@3602 1325 if (TraceMetadataChunkAllocation && Verbose) {
coleenp@3602 1326 gclog_or_tty->print("Metadebug::deallocate_chunk_a_lot: %d) ",
coleenp@3602 1327 sm->sum_count_in_chunks_in_use());
coleenp@3602 1328 dummy_chunk->print_on(gclog_or_tty);
coleenp@3602 1329 gclog_or_tty->print_cr(" Free chunks total %d count %d",
coleenp@3602 1330 vsl->chunk_manager()->free_chunks_total(),
coleenp@3602 1331 vsl->chunk_manager()->free_chunks_count());
coleenp@3602 1332 }
coleenp@3602 1333 }
coleenp@3602 1334 } else {
coleenp@3602 1335 Metadebug::inc_deallocate_chunk_a_lot_count();
coleenp@3602 1336 }
coleenp@3602 1337 #endif
coleenp@3602 1338 }
coleenp@3602 1339
coleenp@3602 1340 void Metadebug::deallocate_block_a_lot(SpaceManager* sm,
coleenp@3602 1341 size_t raw_word_size){
coleenp@3602 1342 #ifdef ASSERT
coleenp@3602 1343 if (MetaDataDeallocateALot &&
coleenp@3602 1344 Metadebug::deallocate_block_a_lot_count() % MetaDataDeallocateALotInterval == 0 ) {
coleenp@3602 1345 Metadebug::set_deallocate_block_a_lot_count(0);
coleenp@3602 1346 for (uint i = 0; i < metadata_deallocate_a_lot_block; i++) {
jmasa@3761 1347 MetaWord* dummy_block = sm->allocate_work(raw_word_size);
coleenp@3602 1348 if (dummy_block == 0) {
coleenp@3602 1349 break;
coleenp@3602 1350 }
jmasa@3761 1351 sm->deallocate(dummy_block, raw_word_size);
coleenp@3602 1352 }
coleenp@3602 1353 } else {
coleenp@3602 1354 Metadebug::inc_deallocate_block_a_lot_count();
coleenp@3602 1355 }
coleenp@3602 1356 #endif
coleenp@3602 1357 }
coleenp@3602 1358
coleenp@3602 1359 void Metadebug::init_allocation_fail_alot_count() {
coleenp@3602 1360 if (MetadataAllocationFailALot) {
coleenp@3602 1361 _allocation_fail_alot_count =
coleenp@3602 1362 1+(long)((double)MetadataAllocationFailALotInterval*os::random()/(max_jint+1.0));
coleenp@3602 1363 }
coleenp@3602 1364 }
coleenp@3602 1365
coleenp@3602 1366 #ifdef ASSERT
coleenp@3602 1367 bool Metadebug::test_metadata_failure() {
coleenp@3602 1368 if (MetadataAllocationFailALot &&
coleenp@3602 1369 Threads::is_vm_complete()) {
coleenp@3602 1370 if (_allocation_fail_alot_count > 0) {
coleenp@3602 1371 _allocation_fail_alot_count--;
coleenp@3602 1372 } else {
coleenp@3602 1373 if (TraceMetadataChunkAllocation && Verbose) {
coleenp@3602 1374 gclog_or_tty->print_cr("Metadata allocation failing for "
coleenp@3602 1375 "MetadataAllocationFailALot");
coleenp@3602 1376 }
coleenp@3602 1377 init_allocation_fail_alot_count();
coleenp@3602 1378 return true;
coleenp@3602 1379 }
coleenp@3602 1380 }
coleenp@3602 1381 return false;
coleenp@3602 1382 }
coleenp@3602 1383 #endif
coleenp@3602 1384
coleenp@3602 1385 // ChunkList methods
coleenp@3602 1386
coleenp@3602 1387 size_t ChunkList::sum_list_size() {
coleenp@3602 1388 size_t result = 0;
coleenp@3602 1389 Metachunk* cur = head();
coleenp@3602 1390 while (cur != NULL) {
coleenp@3602 1391 result += cur->word_size();
coleenp@3602 1392 cur = cur->next();
coleenp@3602 1393 }
coleenp@3602 1394 return result;
coleenp@3602 1395 }
coleenp@3602 1396
coleenp@3602 1397 size_t ChunkList::sum_list_count() {
coleenp@3602 1398 size_t result = 0;
coleenp@3602 1399 Metachunk* cur = head();
coleenp@3602 1400 while (cur != NULL) {
coleenp@3602 1401 result++;
coleenp@3602 1402 cur = cur->next();
coleenp@3602 1403 }
coleenp@3602 1404 return result;
coleenp@3602 1405 }
coleenp@3602 1406
coleenp@3602 1407 size_t ChunkList::sum_list_capacity() {
coleenp@3602 1408 size_t result = 0;
coleenp@3602 1409 Metachunk* cur = head();
coleenp@3602 1410 while (cur != NULL) {
coleenp@3602 1411 result += cur->capacity_word_size();
coleenp@3602 1412 cur = cur->next();
coleenp@3602 1413 }
coleenp@3602 1414 return result;
coleenp@3602 1415 }
coleenp@3602 1416
coleenp@3602 1417 void ChunkList::add_at_head(Metachunk* head, Metachunk* tail) {
coleenp@3602 1418 assert_lock_strong(SpaceManager::expand_lock());
jmasa@3947 1419 assert(head == tail || tail->next() == NULL,
jmasa@3947 1420 "Not the tail or the head has already been added to a list");
coleenp@3602 1421
coleenp@3602 1422 if (TraceMetadataChunkAllocation && Verbose) {
jmasa@3947 1423 gclog_or_tty->print("ChunkList::add_at_head(head, tail): ");
coleenp@3602 1424 Metachunk* cur = head;
coleenp@3602 1425 while (cur != NULL) {
jmasa@3947 1426 gclog_or_tty->print(PTR_FORMAT " (" SIZE_FORMAT ") ", cur, cur->word_size());
coleenp@3602 1427 cur = cur->next();
coleenp@3602 1428 }
jmasa@3947 1429 gclog_or_tty->print_cr("");
coleenp@3602 1430 }
coleenp@3602 1431
coleenp@3602 1432 if (tail != NULL) {
coleenp@3602 1433 tail->set_next(_head);
coleenp@3602 1434 }
coleenp@3602 1435 set_head(head);
coleenp@3602 1436 }
coleenp@3602 1437
coleenp@3602 1438 void ChunkList::add_at_head(Metachunk* list) {
coleenp@3602 1439 if (list == NULL) {
coleenp@3602 1440 // Nothing to add
coleenp@3602 1441 return;
coleenp@3602 1442 }
coleenp@3602 1443 assert_lock_strong(SpaceManager::expand_lock());
coleenp@3602 1444 Metachunk* head = list;
coleenp@3602 1445 Metachunk* tail = list;
coleenp@3602 1446 Metachunk* cur = head->next();
coleenp@3602 1447 // Search for the tail since it is not passed.
coleenp@3602 1448 while (cur != NULL) {
coleenp@3602 1449 tail = cur;
coleenp@3602 1450 cur = cur->next();
coleenp@3602 1451 }
coleenp@3602 1452 add_at_head(head, tail);
coleenp@3602 1453 }
coleenp@3602 1454
coleenp@3602 1455 // ChunkManager methods
coleenp@3602 1456
coleenp@3602 1457 // Verification of _free_chunks_total and _free_chunks_count does not
coleenp@3602 1458 // work with the CMS collector because its use of additional locks
coleenp@3602 1459 // complicate the mutex deadlock detection but it can still be useful
coleenp@3602 1460 // for detecting errors in the chunk accounting with other collectors.
coleenp@3602 1461
coleenp@3602 1462 size_t ChunkManager::free_chunks_total() {
coleenp@3602 1463 #ifdef ASSERT
coleenp@3602 1464 if (!UseConcMarkSweepGC && !SpaceManager::expand_lock()->is_locked()) {
coleenp@3602 1465 MutexLockerEx cl(SpaceManager::expand_lock(),
coleenp@3602 1466 Mutex::_no_safepoint_check_flag);
mgerdin@3829 1467 slow_locked_verify_free_chunks_total();
coleenp@3602 1468 }
coleenp@3602 1469 #endif
coleenp@3602 1470 return _free_chunks_total;
coleenp@3602 1471 }
coleenp@3602 1472
coleenp@3602 1473 size_t ChunkManager::free_chunks_total_in_bytes() {
coleenp@3602 1474 return free_chunks_total() * BytesPerWord;
coleenp@3602 1475 }
coleenp@3602 1476
coleenp@3602 1477 size_t ChunkManager::free_chunks_count() {
coleenp@3602 1478 #ifdef ASSERT
coleenp@3602 1479 if (!UseConcMarkSweepGC && !SpaceManager::expand_lock()->is_locked()) {
coleenp@3602 1480 MutexLockerEx cl(SpaceManager::expand_lock(),
coleenp@3602 1481 Mutex::_no_safepoint_check_flag);
coleenp@3602 1482 // This lock is only needed in debug because the verification
coleenp@3602 1483 // of the _free_chunks_totals walks the list of free chunks
mgerdin@3829 1484 slow_locked_verify_free_chunks_count();
coleenp@3602 1485 }
coleenp@3602 1486 #endif
mgerdin@3829 1487 return _free_chunks_count;
coleenp@3602 1488 }
coleenp@3602 1489
coleenp@3602 1490 void ChunkManager::locked_verify_free_chunks_total() {
coleenp@3602 1491 assert_lock_strong(SpaceManager::expand_lock());
coleenp@3602 1492 assert(sum_free_chunks() == _free_chunks_total,
coleenp@3602 1493 err_msg("_free_chunks_total " SIZE_FORMAT " is not the"
coleenp@3602 1494 " same as sum " SIZE_FORMAT, _free_chunks_total,
coleenp@3602 1495 sum_free_chunks()));
coleenp@3602 1496 }
coleenp@3602 1497
coleenp@3602 1498 void ChunkManager::verify_free_chunks_total() {
coleenp@3602 1499 MutexLockerEx cl(SpaceManager::expand_lock(),
coleenp@3602 1500 Mutex::_no_safepoint_check_flag);
coleenp@3602 1501 locked_verify_free_chunks_total();
coleenp@3602 1502 }
coleenp@3602 1503
coleenp@3602 1504 void ChunkManager::locked_verify_free_chunks_count() {
coleenp@3602 1505 assert_lock_strong(SpaceManager::expand_lock());
coleenp@3602 1506 assert(sum_free_chunks_count() == _free_chunks_count,
coleenp@3602 1507 err_msg("_free_chunks_count " SIZE_FORMAT " is not the"
coleenp@3602 1508 " same as sum " SIZE_FORMAT, _free_chunks_count,
coleenp@3602 1509 sum_free_chunks_count()));
coleenp@3602 1510 }
coleenp@3602 1511
coleenp@3602 1512 void ChunkManager::verify_free_chunks_count() {
coleenp@3602 1513 #ifdef ASSERT
coleenp@3602 1514 MutexLockerEx cl(SpaceManager::expand_lock(),
coleenp@3602 1515 Mutex::_no_safepoint_check_flag);
coleenp@3602 1516 locked_verify_free_chunks_count();
coleenp@3602 1517 #endif
coleenp@3602 1518 }
coleenp@3602 1519
coleenp@3602 1520 void ChunkManager::verify() {
mgerdin@3829 1521 MutexLockerEx cl(SpaceManager::expand_lock(),
mgerdin@3829 1522 Mutex::_no_safepoint_check_flag);
mgerdin@3829 1523 locked_verify();
coleenp@3602 1524 }
coleenp@3602 1525
coleenp@3602 1526 void ChunkManager::locked_verify() {
jmasa@3761 1527 locked_verify_free_chunks_count();
coleenp@3602 1528 locked_verify_free_chunks_total();
coleenp@3602 1529 }
coleenp@3602 1530
coleenp@3602 1531 void ChunkManager::locked_print_free_chunks(outputStream* st) {
coleenp@3602 1532 assert_lock_strong(SpaceManager::expand_lock());
jmasa@3947 1533 st->print_cr("Free chunk total " SIZE_FORMAT " count " SIZE_FORMAT,
coleenp@3602 1534 _free_chunks_total, _free_chunks_count);
coleenp@3602 1535 }
coleenp@3602 1536
coleenp@3602 1537 void ChunkManager::locked_print_sum_free_chunks(outputStream* st) {
coleenp@3602 1538 assert_lock_strong(SpaceManager::expand_lock());
jmasa@3947 1539 st->print_cr("Sum free chunk total " SIZE_FORMAT " count " SIZE_FORMAT,
coleenp@3602 1540 sum_free_chunks(), sum_free_chunks_count());
coleenp@3602 1541 }
coleenp@3602 1542 ChunkList* ChunkManager::free_chunks(ChunkIndex index) {
coleenp@3602 1543 return &_free_chunks[index];
coleenp@3602 1544 }
coleenp@3602 1545
coleenp@3602 1546 // These methods that sum the free chunk lists are used in printing
coleenp@3602 1547 // methods that are used in product builds.
coleenp@3602 1548 size_t ChunkManager::sum_free_chunks() {
coleenp@3602 1549 assert_lock_strong(SpaceManager::expand_lock());
coleenp@3602 1550 size_t result = 0;
jmasa@3947 1551 for (ChunkIndex i = ZeroIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) {
coleenp@3602 1552 ChunkList* list = free_chunks(i);
coleenp@3602 1553
coleenp@3602 1554 if (list == NULL) {
coleenp@3602 1555 continue;
coleenp@3602 1556 }
coleenp@3602 1557
coleenp@3602 1558 result = result + list->sum_list_capacity();
coleenp@3602 1559 }
jmasa@3761 1560 result = result + humongous_dictionary()->total_size();
coleenp@3602 1561 return result;
coleenp@3602 1562 }
coleenp@3602 1563
coleenp@3602 1564 size_t ChunkManager::sum_free_chunks_count() {
coleenp@3602 1565 assert_lock_strong(SpaceManager::expand_lock());
coleenp@3602 1566 size_t count = 0;
jmasa@3947 1567 for (ChunkIndex i = ZeroIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) {
coleenp@3602 1568 ChunkList* list = free_chunks(i);
coleenp@3602 1569 if (list == NULL) {
coleenp@3602 1570 continue;
coleenp@3602 1571 }
coleenp@3602 1572 count = count + list->sum_list_count();
coleenp@3602 1573 }
jmasa@3761 1574 count = count + humongous_dictionary()->total_free_blocks();
coleenp@3602 1575 return count;
coleenp@3602 1576 }
coleenp@3602 1577
coleenp@3602 1578 ChunkList* ChunkManager::find_free_chunks_list(size_t word_size) {
jmasa@3947 1579 ChunkIndex index = list_index(word_size);
jmasa@3947 1580 assert(index < HumongousIndex, "No humongous list");
jmasa@3947 1581 return free_chunks(index);
coleenp@3602 1582 }
coleenp@3602 1583
coleenp@3602 1584 void ChunkManager::free_chunks_put(Metachunk* chunk) {
coleenp@3602 1585 assert_lock_strong(SpaceManager::expand_lock());
coleenp@3602 1586 ChunkList* free_list = find_free_chunks_list(chunk->word_size());
coleenp@3602 1587 chunk->set_next(free_list->head());
coleenp@3602 1588 free_list->set_head(chunk);
coleenp@3602 1589 // chunk is being returned to the chunk free list
coleenp@3602 1590 inc_free_chunks_total(chunk->capacity_word_size());
mgerdin@3829 1591 slow_locked_verify();
coleenp@3602 1592 }
coleenp@3602 1593
coleenp@3602 1594 void ChunkManager::chunk_freelist_deallocate(Metachunk* chunk) {
coleenp@3602 1595 // The deallocation of a chunk originates in the freelist
coleenp@3602 1596 // manangement code for a Metaspace and does not hold the
coleenp@3602 1597 // lock.
coleenp@3602 1598 assert(chunk != NULL, "Deallocating NULL");
mgerdin@3829 1599 assert_lock_strong(SpaceManager::expand_lock());
mgerdin@3829 1600 slow_locked_verify();
coleenp@3602 1601 if (TraceMetadataChunkAllocation) {
coleenp@3602 1602 tty->print_cr("ChunkManager::chunk_freelist_deallocate: chunk "
coleenp@3602 1603 PTR_FORMAT " size " SIZE_FORMAT,
coleenp@3602 1604 chunk, chunk->word_size());
coleenp@3602 1605 }
coleenp@3602 1606 free_chunks_put(chunk);
coleenp@3602 1607 }
coleenp@3602 1608
coleenp@3602 1609 Metachunk* ChunkManager::free_chunks_get(size_t word_size) {
coleenp@3602 1610 assert_lock_strong(SpaceManager::expand_lock());
coleenp@3602 1611
mgerdin@3829 1612 slow_locked_verify();
jmasa@3761 1613
jmasa@3761 1614 Metachunk* chunk = NULL;
jmasa@3947 1615 if (list_index(word_size) != HumongousIndex) {
jmasa@3761 1616 ChunkList* free_list = find_free_chunks_list(word_size);
jmasa@3761 1617 assert(free_list != NULL, "Sanity check");
jmasa@3761 1618
jmasa@3761 1619 chunk = free_list->head();
jmasa@3761 1620 debug_only(Metachunk* debug_head = chunk;)
jmasa@3761 1621
jmasa@3761 1622 if (chunk == NULL) {
jmasa@3761 1623 return NULL;
jmasa@3761 1624 }
jmasa@3761 1625
coleenp@3602 1626 // Remove the chunk as the head of the list.
coleenp@3602 1627 free_list->set_head(chunk->next());
jmasa@3947 1628
jmasa@3947 1629 // Chunk is being removed from the chunks free list.
jmasa@3761 1630 dec_free_chunks_total(chunk->capacity_word_size());
coleenp@3602 1631
coleenp@3602 1632 if (TraceMetadataChunkAllocation && Verbose) {
coleenp@3602 1633 tty->print_cr("ChunkManager::free_chunks_get: free_list "
coleenp@3602 1634 PTR_FORMAT " head " PTR_FORMAT " size " SIZE_FORMAT,
coleenp@3602 1635 free_list, chunk, chunk->word_size());
coleenp@3602 1636 }
coleenp@3602 1637 } else {
jmasa@3761 1638 chunk = humongous_dictionary()->get_chunk(
jmasa@3761 1639 word_size,
jmasa@3761 1640 FreeBlockDictionary<Metachunk>::atLeast);
jmasa@3761 1641
jmasa@3761 1642 if (chunk != NULL) {
jmasa@3761 1643 if (TraceMetadataHumongousAllocation) {
jmasa@3761 1644 size_t waste = chunk->word_size() - word_size;
jmasa@3761 1645 tty->print_cr("Free list allocate humongous chunk size " SIZE_FORMAT
jmasa@3761 1646 " for requested size " SIZE_FORMAT
jmasa@3761 1647 " waste " SIZE_FORMAT,
jmasa@3761 1648 chunk->word_size(), word_size, waste);
coleenp@3602 1649 }
jmasa@3761 1650 // Chunk is being removed from the chunks free list.
jmasa@3761 1651 dec_free_chunks_total(chunk->capacity_word_size());
jmasa@3761 1652 #ifdef ASSERT
jmasa@3761 1653 chunk->set_is_free(false);
jmasa@3761 1654 #endif
jmasa@3947 1655 } else {
jmasa@3947 1656 return NULL;
coleenp@3602 1657 }
coleenp@3602 1658 }
jmasa@3947 1659
jmasa@3947 1660 // Remove it from the links to this freelist
jmasa@3947 1661 chunk->set_next(NULL);
jmasa@3947 1662 chunk->set_prev(NULL);
mgerdin@3829 1663 slow_locked_verify();
coleenp@3602 1664 return chunk;
coleenp@3602 1665 }
coleenp@3602 1666
coleenp@3602 1667 Metachunk* ChunkManager::chunk_freelist_allocate(size_t word_size) {
coleenp@3602 1668 assert_lock_strong(SpaceManager::expand_lock());
mgerdin@3829 1669 slow_locked_verify();
coleenp@3602 1670
coleenp@3602 1671 // Take from the beginning of the list
coleenp@3602 1672 Metachunk* chunk = free_chunks_get(word_size);
coleenp@3602 1673 if (chunk == NULL) {
coleenp@3602 1674 return NULL;
coleenp@3602 1675 }
coleenp@3602 1676
jmasa@3947 1677 assert((word_size <= chunk->word_size()) ||
jmasa@3947 1678 list_index(chunk->word_size() == HumongousIndex),
jmasa@3947 1679 "Non-humongous variable sized chunk");
coleenp@3602 1680 if (TraceMetadataChunkAllocation) {
jmasa@3947 1681 size_t list_count;
jmasa@3947 1682 if (list_index(word_size) < HumongousIndex) {
jmasa@3947 1683 ChunkList* list = find_free_chunks_list(word_size);
jmasa@3947 1684 list_count = list->sum_list_count();
jmasa@3947 1685 } else {
jmasa@3947 1686 list_count = humongous_dictionary()->total_count();
jmasa@3947 1687 }
jmasa@3947 1688 tty->print("ChunkManager::chunk_freelist_allocate: " PTR_FORMAT " chunk "
jmasa@3947 1689 PTR_FORMAT " size " SIZE_FORMAT " count " SIZE_FORMAT " ",
jmasa@3947 1690 this, chunk, chunk->word_size(), list_count);
coleenp@3602 1691 locked_print_free_chunks(tty);
coleenp@3602 1692 }
coleenp@3602 1693
coleenp@3602 1694 return chunk;
coleenp@3602 1695 }
coleenp@3602 1696
jmasa@3761 1697 void ChunkManager::print_on(outputStream* out) {
jmasa@3761 1698 if (PrintFLSStatistics != 0) {
jmasa@3761 1699 humongous_dictionary()->report_statistics();
jmasa@3761 1700 }
jmasa@3761 1701 }
jmasa@3761 1702
coleenp@3602 1703 // SpaceManager methods
coleenp@3602 1704
jmasa@3947 1705 void SpaceManager::get_initial_chunk_sizes(Metaspace::MetaspaceType type,
jmasa@3947 1706 size_t* chunk_word_size,
jmasa@3947 1707 size_t* class_chunk_word_size) {
jmasa@3947 1708 switch (type) {
jmasa@3947 1709 case Metaspace::BootMetaspaceType:
jmasa@3947 1710 *chunk_word_size = Metaspace::first_chunk_word_size();
jmasa@3947 1711 *class_chunk_word_size = Metaspace::first_class_chunk_word_size();
jmasa@3947 1712 break;
jmasa@3947 1713 case Metaspace::ROMetaspaceType:
jmasa@3947 1714 *chunk_word_size = SharedReadOnlySize / wordSize;
jmasa@3947 1715 *class_chunk_word_size = ClassSpecializedChunk;
jmasa@3947 1716 break;
jmasa@3947 1717 case Metaspace::ReadWriteMetaspaceType:
jmasa@3947 1718 *chunk_word_size = SharedReadWriteSize / wordSize;
jmasa@3947 1719 *class_chunk_word_size = ClassSpecializedChunk;
jmasa@3947 1720 break;
jmasa@3947 1721 case Metaspace::AnonymousMetaspaceType:
jmasa@3947 1722 case Metaspace::ReflectionMetaspaceType:
jmasa@3947 1723 *chunk_word_size = SpecializedChunk;
jmasa@3947 1724 *class_chunk_word_size = ClassSpecializedChunk;
jmasa@3947 1725 break;
jmasa@3947 1726 default:
jmasa@3947 1727 *chunk_word_size = SmallChunk;
jmasa@3947 1728 *class_chunk_word_size = ClassSmallChunk;
jmasa@3947 1729 break;
jmasa@3947 1730 }
mikael@4113 1731 assert(*chunk_word_size != 0 && *class_chunk_word_size != 0,
jmasa@3947 1732 err_msg("Initial chunks sizes bad: data " SIZE_FORMAT
jmasa@3947 1733 " class " SIZE_FORMAT,
mikael@4113 1734 *chunk_word_size, *class_chunk_word_size));
jmasa@3947 1735 }
jmasa@3947 1736
coleenp@3602 1737 size_t SpaceManager::sum_free_in_chunks_in_use() const {
coleenp@3602 1738 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
coleenp@3602 1739 size_t free = 0;
jmasa@3947 1740 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) {
coleenp@3602 1741 Metachunk* chunk = chunks_in_use(i);
coleenp@3602 1742 while (chunk != NULL) {
coleenp@3602 1743 free += chunk->free_word_size();
coleenp@3602 1744 chunk = chunk->next();
coleenp@3602 1745 }
coleenp@3602 1746 }
coleenp@3602 1747 return free;
coleenp@3602 1748 }
coleenp@3602 1749
coleenp@3602 1750 size_t SpaceManager::sum_waste_in_chunks_in_use() const {
coleenp@3602 1751 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
coleenp@3602 1752 size_t result = 0;
jmasa@3947 1753 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) {
coleenp@3602 1754 result += sum_waste_in_chunks_in_use(i);
coleenp@3602 1755 }
jmasa@3761 1756
coleenp@3602 1757 return result;
coleenp@3602 1758 }
coleenp@3602 1759
coleenp@3602 1760 size_t SpaceManager::sum_waste_in_chunks_in_use(ChunkIndex index) const {
coleenp@3602 1761 size_t result = 0;
coleenp@3602 1762 Metachunk* chunk = chunks_in_use(index);
coleenp@3602 1763 // Count the free space in all the chunk but not the
coleenp@3602 1764 // current chunk from which allocations are still being done.
coleenp@3602 1765 if (chunk != NULL) {
jmasa@3761 1766 Metachunk* prev = chunk;
jmasa@3761 1767 while (chunk != NULL && chunk != current_chunk()) {
jmasa@3761 1768 result += chunk->free_word_size();
jmasa@3761 1769 prev = chunk;
coleenp@3602 1770 chunk = chunk->next();
coleenp@3602 1771 }
coleenp@3602 1772 }
coleenp@3602 1773 return result;
coleenp@3602 1774 }
coleenp@3602 1775
coleenp@3602 1776 size_t SpaceManager::sum_capacity_in_chunks_in_use() const {
coleenp@3602 1777 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
coleenp@3602 1778 size_t sum = 0;
jmasa@3947 1779 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) {
coleenp@3602 1780 Metachunk* chunk = chunks_in_use(i);
coleenp@3602 1781 while (chunk != NULL) {
coleenp@3602 1782 // Just changed this sum += chunk->capacity_word_size();
coleenp@3602 1783 // sum += chunk->word_size() - Metachunk::overhead();
coleenp@3602 1784 sum += chunk->capacity_word_size();
coleenp@3602 1785 chunk = chunk->next();
coleenp@3602 1786 }
coleenp@3602 1787 }
coleenp@3602 1788 return sum;
coleenp@3602 1789 }
coleenp@3602 1790
coleenp@3602 1791 size_t SpaceManager::sum_count_in_chunks_in_use() {
coleenp@3602 1792 size_t count = 0;
jmasa@3947 1793 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) {
coleenp@3602 1794 count = count + sum_count_in_chunks_in_use(i);
coleenp@3602 1795 }
jmasa@3761 1796
coleenp@3602 1797 return count;
coleenp@3602 1798 }
coleenp@3602 1799
coleenp@3602 1800 size_t SpaceManager::sum_count_in_chunks_in_use(ChunkIndex i) {
coleenp@3602 1801 size_t count = 0;
coleenp@3602 1802 Metachunk* chunk = chunks_in_use(i);
coleenp@3602 1803 while (chunk != NULL) {
coleenp@3602 1804 count++;
coleenp@3602 1805 chunk = chunk->next();
coleenp@3602 1806 }
coleenp@3602 1807 return count;
coleenp@3602 1808 }
coleenp@3602 1809
coleenp@3602 1810
coleenp@3602 1811 size_t SpaceManager::sum_used_in_chunks_in_use() const {
coleenp@3602 1812 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
coleenp@3602 1813 size_t used = 0;
jmasa@3947 1814 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) {
coleenp@3602 1815 Metachunk* chunk = chunks_in_use(i);
coleenp@3602 1816 while (chunk != NULL) {
coleenp@3602 1817 used += chunk->used_word_size();
coleenp@3602 1818 chunk = chunk->next();
coleenp@3602 1819 }
coleenp@3602 1820 }
coleenp@3602 1821 return used;
coleenp@3602 1822 }
coleenp@3602 1823
coleenp@3602 1824 void SpaceManager::locked_print_chunks_in_use_on(outputStream* st) const {
coleenp@3602 1825
jmasa@3947 1826 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) {
jmasa@3947 1827 Metachunk* chunk = chunks_in_use(i);
jmasa@3947 1828 st->print("SpaceManager: %s " PTR_FORMAT,
jmasa@3947 1829 chunk_size_name(i), chunk);
jmasa@3947 1830 if (chunk != NULL) {
jmasa@3947 1831 st->print_cr(" free " SIZE_FORMAT,
jmasa@3947 1832 chunk->free_word_size());
jmasa@3947 1833 } else {
jmasa@3947 1834 st->print_cr("");
jmasa@3947 1835 }
jmasa@3947 1836 }
coleenp@3602 1837
coleenp@3602 1838 vs_list()->chunk_manager()->locked_print_free_chunks(st);
coleenp@3602 1839 vs_list()->chunk_manager()->locked_print_sum_free_chunks(st);
coleenp@3602 1840 }
coleenp@3602 1841
coleenp@3602 1842 size_t SpaceManager::calc_chunk_size(size_t word_size) {
coleenp@3602 1843
coleenp@3602 1844 // Decide between a small chunk and a medium chunk. Up to
coleenp@3602 1845 // _small_chunk_limit small chunks can be allocated but
coleenp@3602 1846 // once a medium chunk has been allocated, no more small
coleenp@3602 1847 // chunks will be allocated.
coleenp@3602 1848 size_t chunk_word_size;
coleenp@3602 1849 if (chunks_in_use(MediumIndex) == NULL &&
coleenp@3602 1850 (!has_small_chunk_limit() ||
coleenp@3602 1851 sum_count_in_chunks_in_use(SmallIndex) < _small_chunk_limit)) {
jmasa@3947 1852 chunk_word_size = (size_t) small_chunk_size();
jmasa@3947 1853 if (word_size + Metachunk::overhead() > small_chunk_size()) {
jmasa@3947 1854 chunk_word_size = medium_chunk_size();
coleenp@3602 1855 }
coleenp@3602 1856 } else {
jmasa@3947 1857 chunk_word_size = medium_chunk_size();
coleenp@3602 1858 }
coleenp@3602 1859
jmasa@3947 1860 // Might still need a humongous chunk. Enforce an
jmasa@3947 1861 // eight word granularity to facilitate reuse (some
jmasa@3947 1862 // wastage but better chance of reuse).
jmasa@3947 1863 size_t if_humongous_sized_chunk =
jmasa@3947 1864 align_size_up(word_size + Metachunk::overhead(),
jmasa@3947 1865 HumongousChunkGranularity);
coleenp@3602 1866 chunk_word_size =
jmasa@3947 1867 MAX2((size_t) chunk_word_size, if_humongous_sized_chunk);
jmasa@3947 1868
jmasa@3947 1869 assert(!SpaceManager::is_humongous(word_size) ||
jmasa@3947 1870 chunk_word_size == if_humongous_sized_chunk,
jmasa@3947 1871 err_msg("Size calculation is wrong, word_size " SIZE_FORMAT
jmasa@3947 1872 " chunk_word_size " SIZE_FORMAT,
jmasa@3947 1873 word_size, chunk_word_size));
coleenp@3602 1874 if (TraceMetadataHumongousAllocation &&
coleenp@3602 1875 SpaceManager::is_humongous(word_size)) {
coleenp@3602 1876 gclog_or_tty->print_cr("Metadata humongous allocation:");
coleenp@3602 1877 gclog_or_tty->print_cr(" word_size " PTR_FORMAT, word_size);
coleenp@3602 1878 gclog_or_tty->print_cr(" chunk_word_size " PTR_FORMAT,
coleenp@3602 1879 chunk_word_size);
jmasa@3761 1880 gclog_or_tty->print_cr(" chunk overhead " PTR_FORMAT,
coleenp@3602 1881 Metachunk::overhead());
coleenp@3602 1882 }
coleenp@3602 1883 return chunk_word_size;
coleenp@3602 1884 }
coleenp@3602 1885
jmasa@3761 1886 MetaWord* SpaceManager::grow_and_allocate(size_t word_size) {
coleenp@3602 1887 assert(vs_list()->current_virtual_space() != NULL,
coleenp@3602 1888 "Should have been set");
coleenp@3602 1889 assert(current_chunk() == NULL ||
coleenp@3602 1890 current_chunk()->allocate(word_size) == NULL,
coleenp@3602 1891 "Don't need to expand");
coleenp@3602 1892 MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag);
coleenp@3602 1893
coleenp@3602 1894 if (TraceMetadataChunkAllocation && Verbose) {
jmasa@3947 1895 size_t words_left = 0;
jmasa@3947 1896 size_t words_used = 0;
jmasa@3947 1897 if (current_chunk() != NULL) {
jmasa@3947 1898 words_left = current_chunk()->free_word_size();
jmasa@3947 1899 words_used = current_chunk()->used_word_size();
jmasa@3947 1900 }
coleenp@3602 1901 gclog_or_tty->print_cr("SpaceManager::grow_and_allocate for " SIZE_FORMAT
jmasa@3947 1902 " words " SIZE_FORMAT " words used " SIZE_FORMAT
jmasa@3947 1903 " words left",
jmasa@3947 1904 word_size, words_used, words_left);
coleenp@3602 1905 }
coleenp@3602 1906
coleenp@3602 1907 // Get another chunk out of the virtual space
coleenp@3602 1908 size_t grow_chunks_by_words = calc_chunk_size(word_size);
jmasa@3947 1909 Metachunk* next = get_new_chunk(word_size, grow_chunks_by_words);
coleenp@3602 1910
coleenp@3602 1911 // If a chunk was available, add it to the in-use chunk list
coleenp@3602 1912 // and do an allocation from it.
coleenp@3602 1913 if (next != NULL) {
coleenp@3602 1914 Metadebug::deallocate_chunk_a_lot(this, grow_chunks_by_words);
coleenp@3602 1915 // Add to this manager's list of chunks in use.
coleenp@3602 1916 add_chunk(next, false);
coleenp@3602 1917 return next->allocate(word_size);
coleenp@3602 1918 }
coleenp@3602 1919 return NULL;
coleenp@3602 1920 }
coleenp@3602 1921
coleenp@3602 1922 void SpaceManager::print_on(outputStream* st) const {
coleenp@3602 1923
jmasa@3947 1924 for (ChunkIndex i = ZeroIndex;
jmasa@3761 1925 i < NumberOfInUseLists ;
coleenp@3602 1926 i = next_chunk_index(i) ) {
coleenp@3602 1927 st->print_cr(" chunks_in_use " PTR_FORMAT " chunk size " PTR_FORMAT,
coleenp@3602 1928 chunks_in_use(i),
coleenp@3602 1929 chunks_in_use(i) == NULL ? 0 : chunks_in_use(i)->word_size());
coleenp@3602 1930 }
coleenp@3602 1931 st->print_cr(" waste: Small " SIZE_FORMAT " Medium " SIZE_FORMAT
coleenp@3602 1932 " Humongous " SIZE_FORMAT,
coleenp@3602 1933 sum_waste_in_chunks_in_use(SmallIndex),
coleenp@3602 1934 sum_waste_in_chunks_in_use(MediumIndex),
coleenp@3602 1935 sum_waste_in_chunks_in_use(HumongousIndex));
jmasa@3761 1936 // block free lists
jmasa@3761 1937 if (block_freelists() != NULL) {
jmasa@3761 1938 st->print_cr("total in block free lists " SIZE_FORMAT,
jmasa@3761 1939 block_freelists()->total_size());
jmasa@3761 1940 }
coleenp@3602 1941 }
coleenp@3602 1942
jmasa@3947 1943 SpaceManager::SpaceManager(Mutex* lock,
jmasa@3947 1944 VirtualSpaceList* vs_list) :
coleenp@3602 1945 _vs_list(vs_list),
coleenp@3602 1946 _allocation_total(0),
jmasa@3947 1947 _lock(lock)
jmasa@3947 1948 {
jmasa@3947 1949 initialize();
jmasa@3947 1950 }
jmasa@3947 1951
jmasa@3947 1952 void SpaceManager::initialize() {
coleenp@3602 1953 Metadebug::init_allocation_fail_alot_count();
jmasa@3947 1954 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) {
coleenp@3602 1955 _chunks_in_use[i] = NULL;
coleenp@3602 1956 }
coleenp@3602 1957 _current_chunk = NULL;
coleenp@3602 1958 if (TraceMetadataChunkAllocation && Verbose) {
coleenp@3602 1959 gclog_or_tty->print_cr("SpaceManager(): " PTR_FORMAT, this);
coleenp@3602 1960 }
coleenp@3602 1961 }
coleenp@3602 1962
coleenp@3602 1963 SpaceManager::~SpaceManager() {
coleenp@3602 1964 MutexLockerEx fcl(SpaceManager::expand_lock(),
coleenp@3602 1965 Mutex::_no_safepoint_check_flag);
coleenp@3602 1966
coleenp@3602 1967 ChunkManager* chunk_manager = vs_list()->chunk_manager();
coleenp@3602 1968
mgerdin@3829 1969 chunk_manager->slow_locked_verify();
coleenp@3602 1970
coleenp@3602 1971 if (TraceMetadataChunkAllocation && Verbose) {
coleenp@3602 1972 gclog_or_tty->print_cr("~SpaceManager(): " PTR_FORMAT, this);
coleenp@3602 1973 locked_print_chunks_in_use_on(gclog_or_tty);
coleenp@3602 1974 }
coleenp@3602 1975
coleenp@3869 1976 // Mangle freed memory.
coleenp@3869 1977 NOT_PRODUCT(mangle_freed_chunks();)
coleenp@3869 1978
coleenp@3602 1979 // Have to update before the chunks_in_use lists are emptied
coleenp@3602 1980 // below.
coleenp@3602 1981 chunk_manager->inc_free_chunks_total(sum_capacity_in_chunks_in_use(),
coleenp@3602 1982 sum_count_in_chunks_in_use());
coleenp@3602 1983
coleenp@3602 1984 // Add all the chunks in use by this space manager
coleenp@3602 1985 // to the global list of free chunks.
coleenp@3602 1986
jmasa@3947 1987 // Follow each list of chunks-in-use and add them to the
jmasa@3947 1988 // free lists. Each list is NULL terminated.
jmasa@3947 1989
jmasa@3947 1990 for (ChunkIndex i = ZeroIndex; i < HumongousIndex; i = next_chunk_index(i)) {
jmasa@3947 1991 if (TraceMetadataChunkAllocation && Verbose) {
jmasa@3947 1992 gclog_or_tty->print_cr("returned %d %s chunks to freelist",
jmasa@3947 1993 sum_count_in_chunks_in_use(i),
jmasa@3947 1994 chunk_size_name(i));
jmasa@3947 1995 }
jmasa@3947 1996 Metachunk* chunks = chunks_in_use(i);
jmasa@3947 1997 chunk_manager->free_chunks(i)->add_at_head(chunks);
jmasa@3947 1998 set_chunks_in_use(i, NULL);
jmasa@3947 1999 if (TraceMetadataChunkAllocation && Verbose) {
jmasa@3947 2000 gclog_or_tty->print_cr("updated freelist count %d %s",
jmasa@3947 2001 chunk_manager->free_chunks(i)->sum_list_count(),
jmasa@3947 2002 chunk_size_name(i));
jmasa@3947 2003 }
jmasa@3947 2004 assert(i != HumongousIndex, "Humongous chunks are handled explicitly later");
coleenp@3602 2005 }
coleenp@3602 2006
jmasa@3947 2007 // The medium chunk case may be optimized by passing the head and
jmasa@3947 2008 // tail of the medium chunk list to add_at_head(). The tail is often
jmasa@3947 2009 // the current chunk but there are probably exceptions.
jmasa@3947 2010
coleenp@3602 2011 // Humongous chunks
jmasa@3947 2012 if (TraceMetadataChunkAllocation && Verbose) {
jmasa@3947 2013 gclog_or_tty->print_cr("returned %d %s humongous chunks to dictionary",
jmasa@3947 2014 sum_count_in_chunks_in_use(HumongousIndex),
jmasa@3947 2015 chunk_size_name(HumongousIndex));
jmasa@3947 2016 gclog_or_tty->print("Humongous chunk dictionary: ");
jmasa@3947 2017 }
coleenp@3602 2018 // Humongous chunks are never the current chunk.
coleenp@3602 2019 Metachunk* humongous_chunks = chunks_in_use(HumongousIndex);
coleenp@3602 2020
jmasa@3761 2021 while (humongous_chunks != NULL) {
jmasa@3761 2022 #ifdef ASSERT
jmasa@3761 2023 humongous_chunks->set_is_free(true);
jmasa@3761 2024 #endif
jmasa@3947 2025 if (TraceMetadataChunkAllocation && Verbose) {
jmasa@3947 2026 gclog_or_tty->print(PTR_FORMAT " (" SIZE_FORMAT ") ",
jmasa@3947 2027 humongous_chunks,
jmasa@3947 2028 humongous_chunks->word_size());
jmasa@3947 2029 }
jmasa@3947 2030 assert(humongous_chunks->word_size() == (size_t)
jmasa@3947 2031 align_size_up(humongous_chunks->word_size(),
jmasa@3947 2032 HumongousChunkGranularity),
jmasa@3947 2033 err_msg("Humongous chunk size is wrong: word size " SIZE_FORMAT
mikael@4113 2034 " granularity %d",
jmasa@3947 2035 humongous_chunks->word_size(), HumongousChunkGranularity));
jmasa@3761 2036 Metachunk* next_humongous_chunks = humongous_chunks->next();
jmasa@3761 2037 chunk_manager->humongous_dictionary()->return_chunk(humongous_chunks);
jmasa@3761 2038 humongous_chunks = next_humongous_chunks;
coleenp@3602 2039 }
jmasa@3947 2040 if (TraceMetadataChunkAllocation && Verbose) {
jmasa@3947 2041 gclog_or_tty->print_cr("");
jmasa@3947 2042 gclog_or_tty->print_cr("updated dictionary count %d %s",
jmasa@3947 2043 chunk_manager->humongous_dictionary()->total_count(),
jmasa@3947 2044 chunk_size_name(HumongousIndex));
jmasa@3947 2045 }
jmasa@3761 2046 set_chunks_in_use(HumongousIndex, NULL);
mgerdin@3829 2047 chunk_manager->slow_locked_verify();
coleenp@3602 2048 }
coleenp@3602 2049
jmasa@3947 2050 const char* SpaceManager::chunk_size_name(ChunkIndex index) const {
jmasa@3947 2051 switch (index) {
jmasa@3947 2052 case SpecializedIndex:
jmasa@3947 2053 return "Specialized";
jmasa@3947 2054 case SmallIndex:
jmasa@3947 2055 return "Small";
jmasa@3947 2056 case MediumIndex:
jmasa@3947 2057 return "Medium";
jmasa@3947 2058 case HumongousIndex:
jmasa@3947 2059 return "Humongous";
jmasa@3947 2060 default:
jmasa@3947 2061 return NULL;
jmasa@3947 2062 }
jmasa@3947 2063 }
jmasa@3947 2064
jmasa@3947 2065 ChunkIndex ChunkManager::list_index(size_t size) {
jmasa@3947 2066 switch (size) {
jmasa@3947 2067 case SpecializedChunk:
jmasa@3947 2068 assert(SpecializedChunk == ClassSpecializedChunk,
jmasa@3947 2069 "Need branch for ClassSpecializedChunk");
jmasa@3947 2070 return SpecializedIndex;
jmasa@3947 2071 case SmallChunk:
jmasa@3947 2072 case ClassSmallChunk:
jmasa@3947 2073 return SmallIndex;
jmasa@3947 2074 case MediumChunk:
jmasa@3947 2075 case ClassMediumChunk:
jmasa@3947 2076 return MediumIndex;
jmasa@3947 2077 default:
jmasa@3948 2078 assert(size > MediumChunk || size > ClassMediumChunk,
jmasa@3947 2079 "Not a humongous chunk");
jmasa@3947 2080 return HumongousIndex;
jmasa@3947 2081 }
jmasa@3947 2082 }
jmasa@3947 2083
jmasa@3761 2084 void SpaceManager::deallocate(MetaWord* p, size_t word_size) {
coleenp@3602 2085 assert_lock_strong(_lock);
jmasa@3761 2086 size_t min_size = TreeChunk<Metablock, FreeList>::min_size();
jmasa@3761 2087 assert(word_size >= min_size,
jmasa@3761 2088 err_msg("Should not deallocate dark matter " SIZE_FORMAT, word_size));
jmasa@3761 2089 block_freelists()->return_block(p, word_size);
coleenp@3602 2090 }
coleenp@3602 2091
coleenp@3602 2092 // Adds a chunk to the list of chunks in use.
coleenp@3602 2093 void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) {
coleenp@3602 2094
coleenp@3602 2095 assert(new_chunk != NULL, "Should not be NULL");
coleenp@3602 2096 assert(new_chunk->next() == NULL, "Should not be on a list");
coleenp@3602 2097
coleenp@3602 2098 new_chunk->reset_empty();
coleenp@3602 2099
coleenp@3602 2100 // Find the correct list and and set the current
coleenp@3602 2101 // chunk for that list.
jmasa@3947 2102 ChunkIndex index = ChunkManager::list_index(new_chunk->word_size());
jmasa@3947 2103
jmasa@3947 2104 if (index != HumongousIndex) {
coleenp@3602 2105 set_current_chunk(new_chunk);
jmasa@3947 2106 new_chunk->set_next(chunks_in_use(index));
jmasa@3947 2107 set_chunks_in_use(index, new_chunk);
jmasa@3947 2108 } else {
coleenp@3602 2109 // For null class loader data and DumpSharedSpaces, the first chunk isn't
coleenp@3602 2110 // small, so small will be null. Link this first chunk as the current
coleenp@3602 2111 // chunk.
coleenp@3602 2112 if (make_current) {
coleenp@3602 2113 // Set as the current chunk but otherwise treat as a humongous chunk.
coleenp@3602 2114 set_current_chunk(new_chunk);
coleenp@3602 2115 }
coleenp@3602 2116 // Link at head. The _current_chunk only points to a humongous chunk for
coleenp@3602 2117 // the null class loader metaspace (class and data virtual space managers)
coleenp@3602 2118 // any humongous chunks so will not point to the tail
coleenp@3602 2119 // of the humongous chunks list.
coleenp@3602 2120 new_chunk->set_next(chunks_in_use(HumongousIndex));
coleenp@3602 2121 set_chunks_in_use(HumongousIndex, new_chunk);
coleenp@3602 2122
jmasa@3948 2123 assert(new_chunk->word_size() > medium_chunk_size(), "List inconsistency");
coleenp@3602 2124 }
coleenp@3602 2125
coleenp@3602 2126 assert(new_chunk->is_empty(), "Not ready for reuse");
coleenp@3602 2127 if (TraceMetadataChunkAllocation && Verbose) {
coleenp@3602 2128 gclog_or_tty->print("SpaceManager::add_chunk: %d) ",
coleenp@3602 2129 sum_count_in_chunks_in_use());
coleenp@3602 2130 new_chunk->print_on(gclog_or_tty);
coleenp@3602 2131 vs_list()->chunk_manager()->locked_print_free_chunks(tty);
coleenp@3602 2132 }
coleenp@3602 2133 }
coleenp@3602 2134
jmasa@3947 2135 Metachunk* SpaceManager::get_new_chunk(size_t word_size,
jmasa@3947 2136 size_t grow_chunks_by_words) {
jmasa@3947 2137
jmasa@3947 2138 Metachunk* next = vs_list()->get_new_chunk(word_size,
jmasa@3947 2139 grow_chunks_by_words,
jmasa@3947 2140 medium_chunk_bunch());
jmasa@3947 2141
jmasa@3947 2142 if (TraceMetadataHumongousAllocation &&
jmasa@3947 2143 SpaceManager::is_humongous(next->word_size())) {
jmasa@3947 2144 gclog_or_tty->print_cr(" new humongous chunk word size " PTR_FORMAT,
jmasa@3947 2145 next->word_size());
jmasa@3947 2146 }
jmasa@3947 2147
jmasa@3947 2148 return next;
jmasa@3947 2149 }
jmasa@3947 2150
coleenp@3602 2151 MetaWord* SpaceManager::allocate(size_t word_size) {
coleenp@3602 2152 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
coleenp@3602 2153
coleenp@3602 2154 // If only the dictionary is going to be used (i.e., no
coleenp@3602 2155 // indexed free list), then there is a minimum size requirement.
coleenp@3602 2156 // MinChunkSize is a placeholder for the real minimum size JJJ
jmasa@3761 2157 size_t byte_size = word_size * BytesPerWord;
jmasa@3761 2158
jmasa@3761 2159 size_t byte_size_with_overhead = byte_size + Metablock::overhead();
jmasa@3761 2160
jmasa@3761 2161 size_t raw_bytes_size = MAX2(byte_size_with_overhead,
jmasa@3761 2162 Metablock::min_block_byte_size());
jmasa@3761 2163 raw_bytes_size = ARENA_ALIGN(raw_bytes_size);
coleenp@3602 2164 size_t raw_word_size = raw_bytes_size / BytesPerWord;
coleenp@3602 2165 assert(raw_word_size * BytesPerWord == raw_bytes_size, "Size problem");
coleenp@3602 2166
coleenp@3602 2167 BlockFreelist* fl = block_freelists();
jmasa@3761 2168 MetaWord* p = NULL;
coleenp@3602 2169 // Allocation from the dictionary is expensive in the sense that
coleenp@3602 2170 // the dictionary has to be searched for a size. Don't allocate
coleenp@3602 2171 // from the dictionary until it starts to get fat. Is this
coleenp@3602 2172 // a reasonable policy? Maybe an skinny dictionary is fast enough
coleenp@3602 2173 // for allocations. Do some profiling. JJJ
jmasa@3761 2174 if (fl->total_size() > allocation_from_dictionary_limit) {
jmasa@3761 2175 p = fl->get_block(raw_word_size);
coleenp@3602 2176 }
jmasa@3761 2177 if (p == NULL) {
jmasa@3761 2178 p = allocate_work(raw_word_size);
coleenp@3602 2179 }
coleenp@3602 2180 Metadebug::deallocate_block_a_lot(this, raw_word_size);
coleenp@3602 2181
jmasa@3761 2182 return p;
coleenp@3602 2183 }
coleenp@3602 2184
coleenp@3602 2185 // Returns the address of spaced allocated for "word_size".
coleenp@3602 2186 // This methods does not know about blocks (Metablocks)
jmasa@3761 2187 MetaWord* SpaceManager::allocate_work(size_t word_size) {
coleenp@3602 2188 assert_lock_strong(_lock);
coleenp@3602 2189 #ifdef ASSERT
coleenp@3602 2190 if (Metadebug::test_metadata_failure()) {
coleenp@3602 2191 return NULL;
coleenp@3602 2192 }
coleenp@3602 2193 #endif
coleenp@3602 2194 // Is there space in the current chunk?
jmasa@3761 2195 MetaWord* result = NULL;
coleenp@3602 2196
coleenp@3602 2197 // For DumpSharedSpaces, only allocate out of the current chunk which is
coleenp@3602 2198 // never null because we gave it the size we wanted. Caller reports out
coleenp@3602 2199 // of memory if this returns null.
coleenp@3602 2200 if (DumpSharedSpaces) {
coleenp@3602 2201 assert(current_chunk() != NULL, "should never happen");
coleenp@3602 2202 inc_allocation_total(word_size);
coleenp@3602 2203 return current_chunk()->allocate(word_size); // caller handles null result
coleenp@3602 2204 }
coleenp@3602 2205 if (current_chunk() != NULL) {
coleenp@3602 2206 result = current_chunk()->allocate(word_size);
coleenp@3602 2207 }
coleenp@3602 2208
coleenp@3602 2209 if (result == NULL) {
coleenp@3602 2210 result = grow_and_allocate(word_size);
coleenp@3602 2211 }
coleenp@3602 2212 if (result > 0) {
coleenp@3602 2213 inc_allocation_total(word_size);
jmasa@3761 2214 assert(result != (MetaWord*) chunks_in_use(MediumIndex),
jmasa@3761 2215 "Head of the list is being allocated");
coleenp@3602 2216 }
coleenp@3602 2217
coleenp@3602 2218 return result;
coleenp@3602 2219 }
coleenp@3602 2220
coleenp@3602 2221 void SpaceManager::verify() {
coleenp@3602 2222 // If there are blocks in the dictionary, then
coleenp@3602 2223 // verfication of chunks does not work since
coleenp@3602 2224 // being in the dictionary alters a chunk.
jmasa@3761 2225 if (block_freelists()->total_size() == 0) {
jmasa@3947 2226 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) {
coleenp@3602 2227 Metachunk* curr = chunks_in_use(i);
coleenp@3602 2228 while (curr != NULL) {
coleenp@3602 2229 curr->verify();
jmasa@3892 2230 verify_chunk_size(curr);
coleenp@3602 2231 curr = curr->next();
coleenp@3602 2232 }
coleenp@3602 2233 }
coleenp@3602 2234 }
coleenp@3602 2235 }
coleenp@3602 2236
jmasa@3892 2237 void SpaceManager::verify_chunk_size(Metachunk* chunk) {
jmasa@3892 2238 assert(is_humongous(chunk->word_size()) ||
jmasa@3947 2239 chunk->word_size() == medium_chunk_size() ||
jmasa@3947 2240 chunk->word_size() == small_chunk_size() ||
jmasa@3947 2241 chunk->word_size() == specialized_chunk_size(),
jmasa@3892 2242 "Chunk size is wrong");
jmasa@3892 2243 return;
jmasa@3892 2244 }
jmasa@3892 2245
coleenp@3602 2246 #ifdef ASSERT
coleenp@3602 2247 void SpaceManager::verify_allocation_total() {
coleenp@3602 2248 // Verification is only guaranteed at a safepoint.
coleenp@3602 2249 if (SafepointSynchronize::is_at_safepoint()) {
coleenp@3602 2250 gclog_or_tty->print_cr("Chunk " PTR_FORMAT " allocation_total " SIZE_FORMAT
coleenp@3602 2251 " sum_used_in_chunks_in_use " SIZE_FORMAT,
coleenp@3602 2252 this,
coleenp@3602 2253 allocation_total(),
coleenp@3602 2254 sum_used_in_chunks_in_use());
coleenp@3602 2255 }
coleenp@3602 2256 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
coleenp@3602 2257 assert(allocation_total() == sum_used_in_chunks_in_use(),
mikael@4113 2258 err_msg("allocation total is not consistent " SIZE_FORMAT
mikael@4113 2259 " vs " SIZE_FORMAT,
coleenp@3602 2260 allocation_total(), sum_used_in_chunks_in_use()));
coleenp@3602 2261 }
coleenp@3602 2262
coleenp@3602 2263 #endif
coleenp@3602 2264
coleenp@3602 2265 void SpaceManager::dump(outputStream* const out) const {
coleenp@3602 2266 size_t curr_total = 0;
coleenp@3602 2267 size_t waste = 0;
coleenp@3602 2268 uint i = 0;
coleenp@3602 2269 size_t used = 0;
coleenp@3602 2270 size_t capacity = 0;
coleenp@3602 2271
coleenp@3602 2272 // Add up statistics for all chunks in this SpaceManager.
jmasa@3947 2273 for (ChunkIndex index = ZeroIndex;
jmasa@3761 2274 index < NumberOfInUseLists;
coleenp@3602 2275 index = next_chunk_index(index)) {
coleenp@3602 2276 for (Metachunk* curr = chunks_in_use(index);
coleenp@3602 2277 curr != NULL;
coleenp@3602 2278 curr = curr->next()) {
coleenp@3602 2279 out->print("%d) ", i++);
coleenp@3602 2280 curr->print_on(out);
coleenp@3602 2281 if (TraceMetadataChunkAllocation && Verbose) {
coleenp@3602 2282 block_freelists()->print_on(out);
coleenp@3602 2283 }
coleenp@3602 2284 curr_total += curr->word_size();
coleenp@3602 2285 used += curr->used_word_size();
coleenp@3602 2286 capacity += curr->capacity_word_size();
coleenp@3602 2287 waste += curr->free_word_size() + curr->overhead();;
coleenp@3602 2288 }
coleenp@3602 2289 }
coleenp@3602 2290
jmasa@3947 2291 size_t free = current_chunk() == NULL ? 0 : current_chunk()->free_word_size();
coleenp@3602 2292 // Free space isn't wasted.
coleenp@3602 2293 waste -= free;
coleenp@3602 2294
coleenp@3602 2295 out->print_cr("total of all chunks " SIZE_FORMAT " used " SIZE_FORMAT
coleenp@3602 2296 " free " SIZE_FORMAT " capacity " SIZE_FORMAT
coleenp@3602 2297 " waste " SIZE_FORMAT, curr_total, used, free, capacity, waste);
coleenp@3602 2298 }
coleenp@3602 2299
coleenp@3869 2300 #ifndef PRODUCT
coleenp@3602 2301 void SpaceManager::mangle_freed_chunks() {
jmasa@3947 2302 for (ChunkIndex index = ZeroIndex;
jmasa@3761 2303 index < NumberOfInUseLists;
coleenp@3602 2304 index = next_chunk_index(index)) {
coleenp@3602 2305 for (Metachunk* curr = chunks_in_use(index);
coleenp@3602 2306 curr != NULL;
coleenp@3602 2307 curr = curr->next()) {
coleenp@3602 2308 curr->mangle();
coleenp@3602 2309 }
coleenp@3602 2310 }
coleenp@3602 2311 }
coleenp@3869 2312 #endif // PRODUCT
coleenp@3602 2313
coleenp@3602 2314 // MetaspaceAux
coleenp@3602 2315
jmasa@3611 2316 size_t MetaspaceAux::used_in_bytes(Metaspace::MetadataType mdtype) {
jmasa@3607 2317 size_t used = 0;
jmasa@3607 2318 ClassLoaderDataGraphMetaspaceIterator iter;
jmasa@3607 2319 while (iter.repeat()) {
jmasa@3607 2320 Metaspace* msp = iter.get_next();
jmasa@3607 2321 // Sum allocation_total for each metaspace
jmasa@3607 2322 if (msp != NULL) {
jmasa@3607 2323 used += msp->used_words(mdtype);
jmasa@3607 2324 }
jmasa@3607 2325 }
jmasa@3607 2326 return used * BytesPerWord;
jmasa@3607 2327 }
jmasa@3607 2328
coleenp@3602 2329 size_t MetaspaceAux::free_in_bytes(Metaspace::MetadataType mdtype) {
coleenp@3602 2330 size_t free = 0;
coleenp@3602 2331 ClassLoaderDataGraphMetaspaceIterator iter;
coleenp@3602 2332 while (iter.repeat()) {
coleenp@3602 2333 Metaspace* msp = iter.get_next();
coleenp@3602 2334 if (msp != NULL) {
coleenp@3602 2335 free += msp->free_words(mdtype);
coleenp@3602 2336 }
coleenp@3602 2337 }
coleenp@3602 2338 return free * BytesPerWord;
coleenp@3602 2339 }
coleenp@3602 2340
coleenp@3602 2341 size_t MetaspaceAux::capacity_in_bytes(Metaspace::MetadataType mdtype) {
coleenp@3602 2342 size_t capacity = free_chunks_total(mdtype);
coleenp@3602 2343 ClassLoaderDataGraphMetaspaceIterator iter;
coleenp@3602 2344 while (iter.repeat()) {
coleenp@3602 2345 Metaspace* msp = iter.get_next();
coleenp@3602 2346 if (msp != NULL) {
coleenp@3602 2347 capacity += msp->capacity_words(mdtype);
coleenp@3602 2348 }
coleenp@3602 2349 }
coleenp@3602 2350 return capacity * BytesPerWord;
coleenp@3602 2351 }
coleenp@3602 2352
coleenp@3602 2353 size_t MetaspaceAux::reserved_in_bytes(Metaspace::MetadataType mdtype) {
coleenp@3602 2354 size_t reserved = (mdtype == Metaspace::ClassType) ?
coleenp@3602 2355 Metaspace::class_space_list()->virtual_space_total() :
coleenp@3602 2356 Metaspace::space_list()->virtual_space_total();
coleenp@3602 2357 return reserved * BytesPerWord;
coleenp@3602 2358 }
coleenp@3602 2359
jmasa@3947 2360 size_t MetaspaceAux::min_chunk_size() { return Metaspace::first_chunk_word_size(); }
coleenp@3602 2361
coleenp@3602 2362 size_t MetaspaceAux::free_chunks_total(Metaspace::MetadataType mdtype) {
coleenp@3602 2363 ChunkManager* chunk = (mdtype == Metaspace::ClassType) ?
coleenp@3602 2364 Metaspace::class_space_list()->chunk_manager() :
coleenp@3602 2365 Metaspace::space_list()->chunk_manager();
mgerdin@3829 2366 chunk->slow_verify();
coleenp@3602 2367 return chunk->free_chunks_total();
coleenp@3602 2368 }
coleenp@3602 2369
coleenp@3602 2370 size_t MetaspaceAux::free_chunks_total_in_bytes(Metaspace::MetadataType mdtype) {
coleenp@3602 2371 return free_chunks_total(mdtype) * BytesPerWord;
coleenp@3602 2372 }
coleenp@3602 2373
coleenp@3602 2374 void MetaspaceAux::print_metaspace_change(size_t prev_metadata_used) {
coleenp@3602 2375 gclog_or_tty->print(", [Metaspace:");
coleenp@3602 2376 if (PrintGCDetails && Verbose) {
coleenp@3602 2377 gclog_or_tty->print(" " SIZE_FORMAT
coleenp@3602 2378 "->" SIZE_FORMAT
coleenp@3602 2379 "(" SIZE_FORMAT "/" SIZE_FORMAT ")",
coleenp@3602 2380 prev_metadata_used,
coleenp@3602 2381 used_in_bytes(),
coleenp@3602 2382 capacity_in_bytes(),
coleenp@3602 2383 reserved_in_bytes());
coleenp@3602 2384 } else {
coleenp@3602 2385 gclog_or_tty->print(" " SIZE_FORMAT "K"
coleenp@3602 2386 "->" SIZE_FORMAT "K"
coleenp@3602 2387 "(" SIZE_FORMAT "K/" SIZE_FORMAT "K)",
coleenp@3602 2388 prev_metadata_used / K,
coleenp@3602 2389 used_in_bytes()/ K,
coleenp@3602 2390 capacity_in_bytes()/K,
coleenp@3602 2391 reserved_in_bytes()/ K);
coleenp@3602 2392 }
coleenp@3602 2393
coleenp@3602 2394 gclog_or_tty->print("]");
coleenp@3602 2395 }
coleenp@3602 2396
coleenp@3602 2397 // This is printed when PrintGCDetails
coleenp@3602 2398 void MetaspaceAux::print_on(outputStream* out) {
coleenp@3602 2399 Metaspace::MetadataType ct = Metaspace::ClassType;
coleenp@3602 2400 Metaspace::MetadataType nct = Metaspace::NonClassType;
coleenp@3602 2401
coleenp@3602 2402 out->print_cr(" Metaspace total "
coleenp@3602 2403 SIZE_FORMAT "K, used " SIZE_FORMAT "K,"
coleenp@3602 2404 " reserved " SIZE_FORMAT "K",
jmasa@3611 2405 capacity_in_bytes()/K, used_in_bytes()/K, reserved_in_bytes()/K);
coleenp@3602 2406 out->print_cr(" data space "
coleenp@3602 2407 SIZE_FORMAT "K, used " SIZE_FORMAT "K,"
coleenp@3602 2408 " reserved " SIZE_FORMAT "K",
jmasa@3611 2409 capacity_in_bytes(nct)/K, used_in_bytes(nct)/K, reserved_in_bytes(nct)/K);
coleenp@3602 2410 out->print_cr(" class space "
coleenp@3602 2411 SIZE_FORMAT "K, used " SIZE_FORMAT "K,"
coleenp@3602 2412 " reserved " SIZE_FORMAT "K",
jmasa@3611 2413 capacity_in_bytes(ct)/K, used_in_bytes(ct)/K, reserved_in_bytes(ct)/K);
coleenp@3602 2414 }
coleenp@3602 2415
coleenp@3602 2416 // Print information for class space and data space separately.
coleenp@3602 2417 // This is almost the same as above.
coleenp@3602 2418 void MetaspaceAux::print_on(outputStream* out, Metaspace::MetadataType mdtype) {
coleenp@3602 2419 size_t free_chunks_capacity_bytes = free_chunks_total_in_bytes(mdtype);
coleenp@3602 2420 size_t capacity_bytes = capacity_in_bytes(mdtype);
coleenp@3602 2421 size_t used_bytes = used_in_bytes(mdtype);
coleenp@3602 2422 size_t free_bytes = free_in_bytes(mdtype);
coleenp@3602 2423 size_t used_and_free = used_bytes + free_bytes +
coleenp@3602 2424 free_chunks_capacity_bytes;
coleenp@3602 2425 out->print_cr(" Chunk accounting: used in chunks " SIZE_FORMAT
coleenp@3602 2426 "K + unused in chunks " SIZE_FORMAT "K + "
coleenp@3602 2427 " capacity in free chunks " SIZE_FORMAT "K = " SIZE_FORMAT
coleenp@3602 2428 "K capacity in allocated chunks " SIZE_FORMAT "K",
coleenp@3602 2429 used_bytes / K,
coleenp@3602 2430 free_bytes / K,
coleenp@3602 2431 free_chunks_capacity_bytes / K,
coleenp@3602 2432 used_and_free / K,
coleenp@3602 2433 capacity_bytes / K);
mgerdin@4303 2434 // Accounting can only be correct if we got the values during a safepoint
mgerdin@4303 2435 assert(!SafepointSynchronize::is_at_safepoint() || used_and_free == capacity_bytes, "Accounting is wrong");
coleenp@3602 2436 }
coleenp@3602 2437
coleenp@3602 2438 // Print total fragmentation for class and data metaspaces separately
coleenp@3602 2439 void MetaspaceAux::print_waste(outputStream* out) {
coleenp@3602 2440
jmasa@3947 2441 size_t specialized_waste = 0, small_waste = 0, medium_waste = 0, large_waste = 0;
jmasa@3947 2442 size_t specialized_count = 0, small_count = 0, medium_count = 0, large_count = 0;
jmasa@3947 2443 size_t cls_specialized_waste = 0, cls_small_waste = 0, cls_medium_waste = 0, cls_large_waste = 0;
jmasa@3947 2444 size_t cls_specialized_count = 0, cls_small_count = 0, cls_medium_count = 0, cls_large_count = 0;
coleenp@3602 2445
coleenp@3602 2446 ClassLoaderDataGraphMetaspaceIterator iter;
coleenp@3602 2447 while (iter.repeat()) {
coleenp@3602 2448 Metaspace* msp = iter.get_next();
coleenp@3602 2449 if (msp != NULL) {
jmasa@3947 2450 specialized_waste += msp->vsm()->sum_waste_in_chunks_in_use(SpecializedIndex);
jmasa@3947 2451 specialized_count += msp->vsm()->sum_count_in_chunks_in_use(SpecializedIndex);
coleenp@3602 2452 small_waste += msp->vsm()->sum_waste_in_chunks_in_use(SmallIndex);
jmasa@3947 2453 small_count += msp->vsm()->sum_count_in_chunks_in_use(SmallIndex);
coleenp@3602 2454 medium_waste += msp->vsm()->sum_waste_in_chunks_in_use(MediumIndex);
jmasa@3947 2455 medium_count += msp->vsm()->sum_count_in_chunks_in_use(MediumIndex);
coleenp@3602 2456 large_waste += msp->vsm()->sum_waste_in_chunks_in_use(HumongousIndex);
jmasa@3947 2457 large_count += msp->vsm()->sum_count_in_chunks_in_use(HumongousIndex);
jmasa@3947 2458
jmasa@3947 2459 cls_specialized_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(SpecializedIndex);
jmasa@3947 2460 cls_specialized_count += msp->class_vsm()->sum_count_in_chunks_in_use(SpecializedIndex);
coleenp@3602 2461 cls_small_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(SmallIndex);
jmasa@3947 2462 cls_small_count += msp->class_vsm()->sum_count_in_chunks_in_use(SmallIndex);
coleenp@3602 2463 cls_medium_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(MediumIndex);
jmasa@3947 2464 cls_medium_count += msp->class_vsm()->sum_count_in_chunks_in_use(MediumIndex);
coleenp@3602 2465 cls_large_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(HumongousIndex);
jmasa@3947 2466 cls_large_count += msp->class_vsm()->sum_count_in_chunks_in_use(HumongousIndex);
coleenp@3602 2467 }
coleenp@3602 2468 }
coleenp@3602 2469 out->print_cr("Total fragmentation waste (words) doesn't count free space");
jmasa@3947 2470 out->print_cr(" data: " SIZE_FORMAT " specialized(s) " SIZE_FORMAT ", "
jmasa@3947 2471 SIZE_FORMAT " small(s) " SIZE_FORMAT ", "
jmasa@3947 2472 SIZE_FORMAT " medium(s) " SIZE_FORMAT,
jmasa@3947 2473 specialized_count, specialized_waste, small_count,
jmasa@3947 2474 small_waste, medium_count, medium_waste);
jmasa@3947 2475 out->print_cr(" class: " SIZE_FORMAT " specialized(s) " SIZE_FORMAT ", "
jmasa@3947 2476 SIZE_FORMAT " small(s) " SIZE_FORMAT,
jmasa@3947 2477 cls_specialized_count, cls_specialized_waste,
jmasa@3947 2478 cls_small_count, cls_small_waste);
coleenp@3602 2479 }
coleenp@3602 2480
coleenp@3602 2481 // Dump global metaspace things from the end of ClassLoaderDataGraph
coleenp@3602 2482 void MetaspaceAux::dump(outputStream* out) {
coleenp@3602 2483 out->print_cr("All Metaspace:");
coleenp@3602 2484 out->print("data space: "); print_on(out, Metaspace::NonClassType);
coleenp@3602 2485 out->print("class space: "); print_on(out, Metaspace::ClassType);
coleenp@3602 2486 print_waste(out);
coleenp@3602 2487 }
coleenp@3602 2488
mgerdin@3829 2489 void MetaspaceAux::verify_free_chunks() {
mgerdin@3829 2490 Metaspace::space_list()->chunk_manager()->verify();
mgerdin@3829 2491 Metaspace::class_space_list()->chunk_manager()->verify();
mgerdin@3829 2492 }
mgerdin@3829 2493
coleenp@3602 2494 // Metaspace methods
coleenp@3602 2495
coleenp@3602 2496 size_t Metaspace::_first_chunk_word_size = 0;
jmasa@3947 2497 size_t Metaspace::_first_class_chunk_word_size = 0;
jmasa@3947 2498
jmasa@3947 2499 Metaspace::Metaspace(Mutex* lock, MetaspaceType type) {
jmasa@3947 2500 initialize(lock, type);
coleenp@3602 2501 }
coleenp@3602 2502
coleenp@3602 2503 Metaspace::~Metaspace() {
coleenp@3602 2504 delete _vsm;
coleenp@3602 2505 delete _class_vsm;
coleenp@3602 2506 }
coleenp@3602 2507
coleenp@3602 2508 VirtualSpaceList* Metaspace::_space_list = NULL;
coleenp@3602 2509 VirtualSpaceList* Metaspace::_class_space_list = NULL;
coleenp@3602 2510
coleenp@3602 2511 #define VIRTUALSPACEMULTIPLIER 2
coleenp@3602 2512
coleenp@3602 2513 void Metaspace::global_initialize() {
coleenp@3602 2514 // Initialize the alignment for shared spaces.
coleenp@3602 2515 int max_alignment = os::vm_page_size();
coleenp@3602 2516 MetaspaceShared::set_max_alignment(max_alignment);
coleenp@3602 2517
coleenp@3602 2518 if (DumpSharedSpaces) {
coleenp@3602 2519 SharedReadOnlySize = align_size_up(SharedReadOnlySize, max_alignment);
coleenp@3602 2520 SharedReadWriteSize = align_size_up(SharedReadWriteSize, max_alignment);
coleenp@3602 2521 SharedMiscDataSize = align_size_up(SharedMiscDataSize, max_alignment);
coleenp@3602 2522 SharedMiscCodeSize = align_size_up(SharedMiscCodeSize, max_alignment);
coleenp@3602 2523
coleenp@3602 2524 // Initialize with the sum of the shared space sizes. The read-only
coleenp@3602 2525 // and read write metaspace chunks will be allocated out of this and the
coleenp@3602 2526 // remainder is the misc code and data chunks.
coleenp@3602 2527 size_t total = align_size_up(SharedReadOnlySize + SharedReadWriteSize +
coleenp@3602 2528 SharedMiscDataSize + SharedMiscCodeSize,
coleenp@3602 2529 os::vm_allocation_granularity());
coleenp@3602 2530 size_t word_size = total/wordSize;
coleenp@3602 2531 _space_list = new VirtualSpaceList(word_size);
coleenp@3602 2532 } else {
coleenp@3602 2533 // If using shared space, open the file that contains the shared space
coleenp@3602 2534 // and map in the memory before initializing the rest of metaspace (so
coleenp@3602 2535 // the addresses don't conflict)
coleenp@3602 2536 if (UseSharedSpaces) {
coleenp@3602 2537 FileMapInfo* mapinfo = new FileMapInfo();
coleenp@3602 2538 memset(mapinfo, 0, sizeof(FileMapInfo));
coleenp@3602 2539
coleenp@3602 2540 // Open the shared archive file, read and validate the header. If
coleenp@3602 2541 // initialization fails, shared spaces [UseSharedSpaces] are
coleenp@3602 2542 // disabled and the file is closed.
coleenp@3602 2543 // Map in spaces now also
coleenp@3602 2544 if (mapinfo->initialize() && MetaspaceShared::map_shared_spaces(mapinfo)) {
coleenp@3602 2545 FileMapInfo::set_current_info(mapinfo);
coleenp@3602 2546 } else {
coleenp@3602 2547 assert(!mapinfo->is_open() && !UseSharedSpaces,
coleenp@3602 2548 "archive file not closed or shared spaces not disabled.");
coleenp@3602 2549 }
coleenp@3602 2550 }
coleenp@3602 2551
jmasa@3947 2552 // Initialize these before initializing the VirtualSpaceList
coleenp@3602 2553 _first_chunk_word_size = InitialBootClassLoaderMetaspaceSize / BytesPerWord;
jmasa@3947 2554 _first_chunk_word_size = align_word_size_up(_first_chunk_word_size);
jmasa@3947 2555 // Make the first class chunk bigger than a medium chunk so it's not put
jmasa@3947 2556 // on the medium chunk list. The next chunk will be small and progress
jmasa@3947 2557 // from there. This size calculated by -version.
jmasa@3947 2558 _first_class_chunk_word_size = MIN2((size_t)MediumChunk*6,
jmasa@3947 2559 (ClassMetaspaceSize/BytesPerWord)*2);
jmasa@3947 2560 _first_class_chunk_word_size = align_word_size_up(_first_class_chunk_word_size);
coleenp@3602 2561 // Arbitrarily set the initial virtual space to a multiple
coleenp@3602 2562 // of the boot class loader size.
jmasa@3947 2563 size_t word_size = VIRTUALSPACEMULTIPLIER * first_chunk_word_size();
coleenp@3602 2564 // Initialize the list of virtual spaces.
coleenp@3602 2565 _space_list = new VirtualSpaceList(word_size);
coleenp@3602 2566 }
coleenp@3602 2567 }
coleenp@3602 2568
coleenp@3602 2569 // For UseCompressedKlassPointers the class space is reserved as a piece of the
coleenp@3602 2570 // Java heap because the compression algorithm is the same for each. The
coleenp@3602 2571 // argument passed in is at the top of the compressed space
coleenp@3602 2572 void Metaspace::initialize_class_space(ReservedSpace rs) {
coleenp@3602 2573 // The reserved space size may be bigger because of alignment, esp with UseLargePages
mikael@4113 2574 assert(rs.size() >= ClassMetaspaceSize,
mikael@4113 2575 err_msg(SIZE_FORMAT " != " UINTX_FORMAT, rs.size(), ClassMetaspaceSize));
coleenp@3602 2576 _class_space_list = new VirtualSpaceList(rs);
coleenp@3602 2577 }
coleenp@3602 2578
jmasa@3947 2579 void Metaspace::initialize(Mutex* lock,
jmasa@3947 2580 MetaspaceType type) {
coleenp@3602 2581
coleenp@3602 2582 assert(space_list() != NULL,
coleenp@3602 2583 "Metadata VirtualSpaceList has not been initialized");
coleenp@3602 2584
coleenp@3602 2585 _vsm = new SpaceManager(lock, space_list());
coleenp@3602 2586 if (_vsm == NULL) {
coleenp@3602 2587 return;
coleenp@3602 2588 }
jmasa@3947 2589 size_t word_size;
jmasa@3947 2590 size_t class_word_size;
jmasa@3947 2591 vsm()->get_initial_chunk_sizes(type,
jmasa@3947 2592 &word_size,
jmasa@3947 2593 &class_word_size);
coleenp@3602 2594
coleenp@3602 2595 assert(class_space_list() != NULL,
coleenp@3602 2596 "Class VirtualSpaceList has not been initialized");
coleenp@3602 2597
coleenp@3602 2598 // Allocate SpaceManager for classes.
coleenp@3602 2599 _class_vsm = new SpaceManager(lock, class_space_list());
coleenp@3602 2600 if (_class_vsm == NULL) {
coleenp@3602 2601 return;
coleenp@3602 2602 }
coleenp@3602 2603
coleenp@3602 2604 MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag);
coleenp@3602 2605
coleenp@3602 2606 // Allocate chunk for metadata objects
coleenp@3602 2607 Metachunk* new_chunk =
jmasa@3947 2608 space_list()->get_initialization_chunk(word_size,
jmasa@3947 2609 vsm()->medium_chunk_bunch());
coleenp@3602 2610 assert(!DumpSharedSpaces || new_chunk != NULL, "should have enough space for both chunks");
coleenp@3602 2611 if (new_chunk != NULL) {
coleenp@3602 2612 // Add to this manager's list of chunks in use and current_chunk().
coleenp@3602 2613 vsm()->add_chunk(new_chunk, true);
coleenp@3602 2614 }
coleenp@3602 2615
coleenp@3602 2616 // Allocate chunk for class metadata objects
coleenp@3602 2617 Metachunk* class_chunk =
jmasa@3947 2618 class_space_list()->get_initialization_chunk(class_word_size,
jmasa@3947 2619 class_vsm()->medium_chunk_bunch());
coleenp@3602 2620 if (class_chunk != NULL) {
coleenp@3602 2621 class_vsm()->add_chunk(class_chunk, true);
coleenp@3602 2622 }
coleenp@3602 2623 }
coleenp@3602 2624
jmasa@3947 2625 size_t Metaspace::align_word_size_up(size_t word_size) {
jmasa@3947 2626 size_t byte_size = word_size * wordSize;
jmasa@3947 2627 return ReservedSpace::allocation_align_size_up(byte_size) / wordSize;
jmasa@3947 2628 }
jmasa@3947 2629
coleenp@3602 2630 MetaWord* Metaspace::allocate(size_t word_size, MetadataType mdtype) {
coleenp@3602 2631 // DumpSharedSpaces doesn't use class metadata area (yet)
coleenp@3602 2632 if (mdtype == ClassType && !DumpSharedSpaces) {
jmasa@3761 2633 return class_vsm()->allocate(word_size);
coleenp@3602 2634 } else {
jmasa@3761 2635 return vsm()->allocate(word_size);
coleenp@3602 2636 }
coleenp@3602 2637 }
coleenp@3602 2638
jmasa@3629 2639 MetaWord* Metaspace::expand_and_allocate(size_t word_size, MetadataType mdtype) {
jmasa@3629 2640 MetaWord* result;
jmasa@3629 2641 MetaspaceGC::set_expand_after_GC(true);
jmasa@3629 2642 size_t before_inc = MetaspaceGC::capacity_until_GC();
jmasa@3629 2643 size_t delta_words = MetaspaceGC::delta_capacity_until_GC(word_size);
jmasa@3629 2644 MetaspaceGC::inc_capacity_until_GC(delta_words);
jmasa@3629 2645 if (PrintGCDetails && Verbose) {
jmasa@3629 2646 gclog_or_tty->print_cr("Increase capacity to GC from " SIZE_FORMAT
jmasa@3629 2647 " to " SIZE_FORMAT, before_inc, MetaspaceGC::capacity_until_GC());
jmasa@3629 2648 }
jmasa@3761 2649
jmasa@3629 2650 result = allocate(word_size, mdtype);
jmasa@3629 2651
jmasa@3629 2652 return result;
jmasa@3629 2653 }
jmasa@3629 2654
coleenp@3602 2655 // Space allocated in the Metaspace. This may
coleenp@3602 2656 // be across several metadata virtual spaces.
coleenp@3602 2657 char* Metaspace::bottom() const {
coleenp@3602 2658 assert(DumpSharedSpaces, "only useful and valid for dumping shared spaces");
coleenp@3602 2659 return (char*)vsm()->current_chunk()->bottom();
coleenp@3602 2660 }
coleenp@3602 2661
coleenp@3602 2662 size_t Metaspace::used_words(MetadataType mdtype) const {
coleenp@3602 2663 // return vsm()->allocation_total();
coleenp@3602 2664 return mdtype == ClassType ? class_vsm()->sum_used_in_chunks_in_use() :
coleenp@3602 2665 vsm()->sum_used_in_chunks_in_use(); // includes overhead!
coleenp@3602 2666 }
coleenp@3602 2667
coleenp@3602 2668 size_t Metaspace::free_words(MetadataType mdtype) const {
coleenp@3602 2669 return mdtype == ClassType ? class_vsm()->sum_free_in_chunks_in_use() :
coleenp@3602 2670 vsm()->sum_free_in_chunks_in_use();
coleenp@3602 2671 }
coleenp@3602 2672
coleenp@3602 2673 // Space capacity in the Metaspace. It includes
coleenp@3602 2674 // space in the list of chunks from which allocations
coleenp@3602 2675 // have been made. Don't include space in the global freelist and
coleenp@3602 2676 // in the space available in the dictionary which
coleenp@3602 2677 // is already counted in some chunk.
coleenp@3602 2678 size_t Metaspace::capacity_words(MetadataType mdtype) const {
coleenp@3602 2679 return mdtype == ClassType ? class_vsm()->sum_capacity_in_chunks_in_use() :
coleenp@3602 2680 vsm()->sum_capacity_in_chunks_in_use();
coleenp@3602 2681 }
coleenp@3602 2682
coleenp@3602 2683 void Metaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) {
coleenp@3602 2684 if (SafepointSynchronize::is_at_safepoint()) {
coleenp@3602 2685 assert(Thread::current()->is_VM_thread(), "should be the VM thread");
jmasa@3761 2686 // Don't take Heap_lock
jmasa@3761 2687 MutexLocker ml(vsm()->lock());
jmasa@3761 2688 if (word_size < TreeChunk<Metablock, FreeList>::min_size()) {
jmasa@3761 2689 // Dark matter. Too small for dictionary.
jmasa@3761 2690 #ifdef ASSERT
jmasa@3761 2691 Copy::fill_to_words((HeapWord*)ptr, word_size, 0xf5f5f5f5);
jmasa@3761 2692 #endif
jmasa@3761 2693 return;
jmasa@3761 2694 }
coleenp@3602 2695 if (is_class) {
jmasa@3761 2696 class_vsm()->deallocate(ptr, word_size);
coleenp@3602 2697 } else {
jmasa@3761 2698 vsm()->deallocate(ptr, word_size);
coleenp@3602 2699 }
coleenp@3602 2700 } else {
coleenp@3602 2701 MutexLocker ml(vsm()->lock());
coleenp@3602 2702
jmasa@3761 2703 if (word_size < TreeChunk<Metablock, FreeList>::min_size()) {
jmasa@3761 2704 // Dark matter. Too small for dictionary.
jmasa@3761 2705 #ifdef ASSERT
jmasa@3761 2706 Copy::fill_to_words((HeapWord*)ptr, word_size, 0xf5f5f5f5);
jmasa@3761 2707 #endif
jmasa@3761 2708 return;
jmasa@3761 2709 }
coleenp@3602 2710 if (is_class) {
jmasa@3761 2711 class_vsm()->deallocate(ptr, word_size);
coleenp@3602 2712 } else {
jmasa@3761 2713 vsm()->deallocate(ptr, word_size);
coleenp@3602 2714 }
coleenp@3602 2715 }
coleenp@3602 2716 }
coleenp@3602 2717
jmasa@3761 2718 Metablock* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size,
coleenp@3602 2719 bool read_only, MetadataType mdtype, TRAPS) {
coleenp@3602 2720 if (HAS_PENDING_EXCEPTION) {
coleenp@3602 2721 assert(false, "Should not allocate with exception pending");
coleenp@3602 2722 return NULL; // caller does a CHECK_NULL too
coleenp@3602 2723 }
coleenp@3602 2724
coleenp@3602 2725 // SSS: Should we align the allocations and make sure the sizes are aligned.
coleenp@3602 2726 MetaWord* result = NULL;
coleenp@3602 2727
coleenp@3602 2728 assert(loader_data != NULL, "Should never pass around a NULL loader_data. "
coleenp@3602 2729 "ClassLoaderData::the_null_class_loader_data() should have been used.");
coleenp@3602 2730 // Allocate in metaspaces without taking out a lock, because it deadlocks
coleenp@3602 2731 // with the SymbolTable_lock. Dumping is single threaded for now. We'll have
coleenp@3602 2732 // to revisit this for application class data sharing.
coleenp@3602 2733 if (DumpSharedSpaces) {
coleenp@3602 2734 if (read_only) {
coleenp@3602 2735 result = loader_data->ro_metaspace()->allocate(word_size, NonClassType);
coleenp@3602 2736 } else {
coleenp@3602 2737 result = loader_data->rw_metaspace()->allocate(word_size, NonClassType);
coleenp@3602 2738 }
coleenp@3602 2739 if (result == NULL) {
coleenp@3602 2740 report_out_of_shared_space(read_only ? SharedReadOnly : SharedReadWrite);
coleenp@3602 2741 }
jmasa@3761 2742 return Metablock::initialize(result, word_size);
coleenp@3602 2743 }
coleenp@3602 2744
coleenp@3602 2745 result = loader_data->metaspace_non_null()->allocate(word_size, mdtype);
coleenp@3602 2746
coleenp@3602 2747 if (result == NULL) {
coleenp@3602 2748 // Try to clean out some memory and retry.
coleenp@3602 2749 result =
jmasa@3761 2750 Universe::heap()->collector_policy()->satisfy_failed_metadata_allocation(
coleenp@3602 2751 loader_data, word_size, mdtype);
coleenp@3602 2752
coleenp@3602 2753 // If result is still null, we are out of memory.
coleenp@3602 2754 if (result == NULL) {
jmasa@3947 2755 if (Verbose && TraceMetadataChunkAllocation) {
jmasa@3947 2756 gclog_or_tty->print_cr("Metaspace allocation failed for size "
jmasa@3947 2757 SIZE_FORMAT, word_size);
jmasa@3947 2758 if (loader_data->metaspace_or_null() != NULL) loader_data->metaspace_or_null()->dump(gclog_or_tty);
jmasa@3947 2759 MetaspaceAux::dump(gclog_or_tty);
jmasa@3947 2760 }
coleenp@3602 2761 // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support
coleenp@3602 2762 report_java_out_of_memory("Metadata space");
coleenp@3602 2763
coleenp@3602 2764 if (JvmtiExport::should_post_resource_exhausted()) {
coleenp@3602 2765 JvmtiExport::post_resource_exhausted(
coleenp@3602 2766 JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR,
coleenp@3602 2767 "Metadata space");
coleenp@3602 2768 }
coleenp@3602 2769 THROW_OOP_0(Universe::out_of_memory_error_perm_gen());
coleenp@3602 2770 }
coleenp@3602 2771 }
jmasa@3761 2772 return Metablock::initialize(result, word_size);
coleenp@3602 2773 }
coleenp@3602 2774
coleenp@3602 2775 void Metaspace::print_on(outputStream* out) const {
coleenp@3602 2776 // Print both class virtual space counts and metaspace.
coleenp@3602 2777 if (Verbose) {
coleenp@3602 2778 vsm()->print_on(out);
coleenp@3602 2779 class_vsm()->print_on(out);
coleenp@3602 2780 }
coleenp@3602 2781 }
coleenp@3602 2782
coleenp@3860 2783 bool Metaspace::contains(const void * ptr) {
coleenp@3602 2784 if (MetaspaceShared::is_in_shared_space(ptr)) {
coleenp@3602 2785 return true;
coleenp@3602 2786 }
coleenp@3860 2787 // This is checked while unlocked. As long as the virtualspaces are added
coleenp@3860 2788 // at the end, the pointer will be in one of them. The virtual spaces
coleenp@3860 2789 // aren't deleted presently. When they are, some sort of locking might
coleenp@3860 2790 // be needed. Note, locking this can cause inversion problems with the
coleenp@3860 2791 // caller in MetaspaceObj::is_metadata() function.
coleenp@3602 2792 return space_list()->contains(ptr) || class_space_list()->contains(ptr);
coleenp@3602 2793 }
coleenp@3602 2794
coleenp@3602 2795 void Metaspace::verify() {
coleenp@3602 2796 vsm()->verify();
coleenp@3602 2797 class_vsm()->verify();
coleenp@3602 2798 }
coleenp@3602 2799
coleenp@3602 2800 void Metaspace::dump(outputStream* const out) const {
coleenp@3602 2801 if (UseMallocOnly) {
coleenp@3602 2802 // Just print usage for now
coleenp@3602 2803 out->print_cr("usage %d", used_words(Metaspace::NonClassType));
coleenp@3602 2804 }
coleenp@3602 2805 out->print_cr("\nVirtual space manager: " INTPTR_FORMAT, vsm());
coleenp@3602 2806 vsm()->dump(out);
coleenp@3602 2807 out->print_cr("\nClass space manager: " INTPTR_FORMAT, class_vsm());
coleenp@3602 2808 class_vsm()->dump(out);
coleenp@3602 2809 }