Mercurial > hg > truffle
comparison src/share/vm/memory/metaspace.cpp @ 6885:685df3c6f84b
7045397: NPG: Add freelists to class loader arenas.
Reviewed-by: coleenp, stefank, jprovino, ohair
author | jmasa |
---|---|
date | Tue, 18 Sep 2012 23:35:42 -0700 |
parents | 5baec2e69518 |
children | 6bc207d87e5d |
comparison
equal
deleted
inserted
replaced
6877:d0e7716b179e | 6885:685df3c6f84b |
---|---|
22 * | 22 * |
23 */ | 23 */ |
24 #include "precompiled.hpp" | 24 #include "precompiled.hpp" |
25 #include "gc_interface/collectedHeap.hpp" | 25 #include "gc_interface/collectedHeap.hpp" |
26 #include "memory/binaryTreeDictionary.hpp" | 26 #include "memory/binaryTreeDictionary.hpp" |
27 #include "memory/freeList.hpp" | |
27 #include "memory/collectorPolicy.hpp" | 28 #include "memory/collectorPolicy.hpp" |
28 #include "memory/filemap.hpp" | 29 #include "memory/filemap.hpp" |
29 #include "memory/freeList.hpp" | 30 #include "memory/freeList.hpp" |
31 #include "memory/metablock.hpp" | |
32 #include "memory/metachunk.hpp" | |
30 #include "memory/metaspace.hpp" | 33 #include "memory/metaspace.hpp" |
31 #include "memory/metaspaceShared.hpp" | 34 #include "memory/metaspaceShared.hpp" |
32 #include "memory/resourceArea.hpp" | 35 #include "memory/resourceArea.hpp" |
33 #include "memory/universe.hpp" | 36 #include "memory/universe.hpp" |
34 #include "runtime/globals.hpp" | 37 #include "runtime/globals.hpp" |
35 #include "runtime/mutex.hpp" | 38 #include "runtime/mutex.hpp" |
36 #include "services/memTracker.hpp" | 39 #include "services/memTracker.hpp" |
37 #include "utilities/copy.hpp" | 40 #include "utilities/copy.hpp" |
38 #include "utilities/debug.hpp" | 41 #include "utilities/debug.hpp" |
39 | 42 |
40 // Define this macro to deallocate Metablock. If not defined, | 43 typedef BinaryTreeDictionary<Metablock, FreeList> BlockTreeDictionary; |
41 // blocks are not yet deallocated and are only mangled. | 44 typedef BinaryTreeDictionary<Metachunk, FreeList> ChunkTreeDictionary; |
42 #undef DEALLOCATE_BLOCKS | |
43 | |
44 // Easily recognizable patterns | |
45 // These patterns can be the same in 32bit or 64bit since | |
46 // they only have to be easily recognizable. | |
47 const void* metaspace_allocation_leader = (void*) 0X11111111; | |
48 const void* metaspace_allocation_trailer = (void*) 0X77777777; | |
49 | 45 |
50 // Parameters for stress mode testing | 46 // Parameters for stress mode testing |
51 const uint metadata_deallocate_a_lot_block = 10; | 47 const uint metadata_deallocate_a_lot_block = 10; |
52 const uint metadata_deallocate_a_lock_chunk = 3; | 48 const uint metadata_deallocate_a_lock_chunk = 3; |
53 size_t const allocation_from_dictionary_limit = 64 * K; | 49 size_t const allocation_from_dictionary_limit = 64 * K; |
54 const size_t metadata_chunk_initialize = 0xf7f7f7f7; | 50 const size_t metadata_chunk_initialize = 0xf7f7f7f7; |
55 const size_t metadata_deallocate = 0xf5f5f5f5; | 51 const size_t metadata_deallocate = 0xf5f5f5f5; |
56 const size_t metadata_space_manager_allocate = 0xf3f3f3f3; | |
57 | 52 |
58 MetaWord* last_allocated = 0; | 53 MetaWord* last_allocated = 0; |
59 | 54 |
60 // Used in declarations in SpaceManager and ChunkManager | 55 // Used in declarations in SpaceManager and ChunkManager |
61 enum ChunkIndex { | 56 enum ChunkIndex { |
62 SmallIndex = 0, | 57 SmallIndex = 0, |
63 MediumIndex = 1, | 58 MediumIndex = 1, |
64 HumongousIndex = 2, | 59 HumongousIndex = 2, |
65 NumberOfFreeLists = 3 | 60 NumberOfFreeLists = 2, |
61 NumberOfInUseLists = 3 | |
66 }; | 62 }; |
67 | 63 |
68 static ChunkIndex next_chunk_index(ChunkIndex i) { | 64 static ChunkIndex next_chunk_index(ChunkIndex i) { |
69 assert(i < NumberOfFreeLists, "Out of bound"); | 65 assert(i < NumberOfInUseLists, "Out of bound"); |
70 return (ChunkIndex) (i+1); | 66 return (ChunkIndex) (i+1); |
71 } | 67 } |
72 | 68 |
73 // Originally _capacity_until_GC was set to MetaspaceSize here but | 69 // Originally _capacity_until_GC was set to MetaspaceSize here but |
74 // the default MetaspaceSize before argument processing was being | 70 // the default MetaspaceSize before argument processing was being |
98 // allocation.hpp. Note that the latter Chunk is the space for | 94 // allocation.hpp. Note that the latter Chunk is the space for |
99 // allocation (allocations from the chunk are out of the space in | 95 // allocation (allocations from the chunk are out of the space in |
100 // the Chunk after the header for the Chunk) where as Metachunks | 96 // the Chunk after the header for the Chunk) where as Metachunks |
101 // point to space in a VirtualSpace. To replace Metachunks with | 97 // point to space in a VirtualSpace. To replace Metachunks with |
102 // Chunks, change Chunks so that they can be allocated out of a VirtualSpace. | 98 // Chunks, change Chunks so that they can be allocated out of a VirtualSpace. |
103 // | 99 size_t Metablock::_min_block_byte_size = sizeof(Metablock); |
104 | |
105 // Metablock are the unit of allocation from a Chunk. It contains | |
106 // the size of the requested allocation in a debug build. | |
107 // Also in a debug build it has a marker before and after the | |
108 // body of the block. The address of the body is the address returned | |
109 // by the allocation. | |
110 // | |
111 // Layout in a debug build. In a product build only the body is present. | |
112 // | |
113 // +-----------+-----------+------------+ +-----------+ | |
114 // | word size | leader | body | ... | trailer | | |
115 // +-----------+-----------+------------+ +-----------+ | |
116 // | |
117 // A Metablock may be reused by its SpaceManager but are never moved between | |
118 // SpaceManagers. There is no explicit link to the Metachunk | |
119 // from which it was allocated. Metablock are not deallocated, rather | |
120 // the Metachunk it is a part of will be deallocated when it's | |
121 // associated class loader is collected. | |
122 // | |
123 // When the word size of a block is passed in to the deallocation | |
124 // call the word size no longer needs to be part of a Metablock. | |
125 | |
126 class Metablock { | |
127 friend class VMStructs; | |
128 private: | |
129 // Used to align the allocation (see below) and for debugging. | |
130 #ifdef ASSERT | 100 #ifdef ASSERT |
131 struct { | 101 size_t Metablock::_overhead = |
132 size_t _word_size; | 102 Chunk::aligned_overhead_size(sizeof(Metablock)) / BytesPerWord; |
133 void* _leader; | 103 #else |
134 } _header; | 104 size_t Metablock::_overhead = 0; |
135 void* _data[1]; | |
136 #endif | 105 #endif |
137 static size_t _overhead; | |
138 | |
139 #ifdef ASSERT | |
140 void set_word_size(size_t v) { _header._word_size = v; } | |
141 void* leader() { return _header._leader; } | |
142 void* trailer() { | |
143 jlong index = (jlong) _header._word_size - sizeof(_header)/BytesPerWord - 1; | |
144 assert(index > 0, err_msg("Bad indexling of trailer %d", index)); | |
145 void** ptr = &_data[index]; | |
146 return *ptr; | |
147 } | |
148 void set_leader(void* v) { _header._leader = v; } | |
149 void set_trailer(void* v) { | |
150 void** ptr = &_data[_header._word_size - sizeof(_header)/BytesPerWord - 1]; | |
151 *ptr = v; | |
152 } | |
153 public: | |
154 size_t word_size() { return _header._word_size; } | |
155 #endif | |
156 public: | |
157 | |
158 static Metablock* initialize(MetaWord* p, size_t word_size); | |
159 | |
160 // This places the body of the block at a 2 word boundary | |
161 // because every block starts on a 2 word boundary. Work out | |
162 // how to make the body on a 2 word boundary if the block | |
163 // starts on a arbitrary boundary. JJJ | |
164 | |
165 #ifdef ASSERT | |
166 MetaWord* data() { return (MetaWord*) &_data[0]; } | |
167 #else | |
168 MetaWord* data() { return (MetaWord*) this; } | |
169 #endif | |
170 static Metablock* metablock_from_data(MetaWord* p) { | |
171 #ifdef ASSERT | |
172 size_t word_offset = offset_of(Metablock, _data)/BytesPerWord; | |
173 Metablock* result = (Metablock*) (p - word_offset); | |
174 return result; | |
175 #else | |
176 return (Metablock*) p; | |
177 #endif | |
178 } | |
179 | |
180 static size_t overhead() { return _overhead; } | |
181 void verify(); | |
182 }; | |
183 | |
184 // Metachunk - Quantum of allocation from a Virtualspace | |
185 // Metachunks are reused (when freed are put on a global freelist) and | |
186 // have no permanent association to a SpaceManager. | |
187 | |
188 // +--------------+ <- end | |
189 // | | --+ ---+ | |
190 // | | | free | | |
191 // | | | | | |
192 // | | | | capacity | |
193 // | | | | | |
194 // | | <- top --+ | | |
195 // | | ---+ | | |
196 // | | | used | | |
197 // | | | | | |
198 // | | | | | |
199 // +--------------+ <- bottom ---+ ---+ | |
200 | |
201 class Metachunk VALUE_OBJ_CLASS_SPEC { | |
202 // link to support lists of chunks | |
203 Metachunk* _next; | |
204 | |
205 MetaWord* _bottom; | |
206 MetaWord* _end; | |
207 MetaWord* _top; | |
208 size_t _word_size; | |
209 | |
210 // Metachunks are allocated out of a MetadataVirtualSpace and | |
211 // and use some of its space to describe itself (plus alignment | |
212 // considerations). Metadata is allocated in the rest of the chunk. | |
213 // This size is the overhead of maintaining the Metachunk within | |
214 // the space. | |
215 static size_t _overhead; | |
216 | |
217 void set_bottom(MetaWord* v) { _bottom = v; } | |
218 void set_end(MetaWord* v) { _end = v; } | |
219 void set_top(MetaWord* v) { _top = v; } | |
220 void set_word_size(size_t v) { _word_size = v; } | |
221 public: | |
222 | |
223 // Used to add a Metachunk to a list of Metachunks | |
224 void set_next(Metachunk* v) { _next = v; assert(v != this, "Boom");} | |
225 | |
226 Metablock* allocate(size_t word_size); | |
227 static Metachunk* initialize(MetaWord* ptr, size_t word_size); | |
228 | |
229 // Accessors | |
230 Metachunk* next() const { return _next; } | |
231 MetaWord* bottom() const { return _bottom; } | |
232 MetaWord* end() const { return _end; } | |
233 MetaWord* top() const { return _top; } | |
234 size_t word_size() const { return _word_size; } | |
235 static size_t overhead() { return _overhead; } | |
236 | |
237 // Reset top to bottom so chunk can be reused. | |
238 void reset_empty() { _top = (_bottom + _overhead); } | |
239 bool is_empty() { return _top == (_bottom + _overhead); } | |
240 | |
241 // used (has been allocated) | |
242 // free (available for future allocations) | |
243 // capacity (total size of chunk) | |
244 size_t used_word_size(); | |
245 size_t free_word_size(); | |
246 size_t capacity_word_size(); | |
247 | |
248 #ifdef ASSERT | |
249 void mangle() { | |
250 // Mangle the payload of the chunk and not the links that | |
251 // maintain list of chunks. | |
252 HeapWord* start = (HeapWord*)(bottom() + overhead()); | |
253 size_t word_size = capacity_word_size() - overhead(); | |
254 Copy::fill_to_words(start, word_size, metadata_chunk_initialize); | |
255 } | |
256 #endif // ASSERT | |
257 | |
258 void print_on(outputStream* st) const; | |
259 void verify(); | |
260 }; | |
261 | 106 |
262 | 107 |
263 // Pointer to list of Metachunks. | 108 // Pointer to list of Metachunks. |
264 class ChunkList VALUE_OBJ_CLASS_SPEC { | 109 class ChunkList VALUE_OBJ_CLASS_SPEC { |
265 // List of free chunks | 110 // List of free chunks |
290 | 135 |
291 // Free list of chunks of different sizes. | 136 // Free list of chunks of different sizes. |
292 // SmallChunk | 137 // SmallChunk |
293 // MediumChunk | 138 // MediumChunk |
294 // HumongousChunk | 139 // HumongousChunk |
295 ChunkList _free_chunks[3]; | 140 ChunkList _free_chunks[NumberOfFreeLists]; |
141 | |
142 // HumongousChunk | |
143 ChunkTreeDictionary _humongous_dictionary; | |
296 | 144 |
297 // ChunkManager in all lists of this type | 145 // ChunkManager in all lists of this type |
298 size_t _free_chunks_total; | 146 size_t _free_chunks_total; |
299 size_t _free_chunks_count; | 147 size_t _free_chunks_count; |
300 | 148 |
335 Atomic::add_ptr(count, &_free_chunks_count); | 183 Atomic::add_ptr(count, &_free_chunks_count); |
336 Atomic::add_ptr(v, &_free_chunks_total); | 184 Atomic::add_ptr(v, &_free_chunks_total); |
337 } | 185 } |
338 ChunkList* free_medium_chunks() { return &_free_chunks[1]; } | 186 ChunkList* free_medium_chunks() { return &_free_chunks[1]; } |
339 ChunkList* free_small_chunks() { return &_free_chunks[0]; } | 187 ChunkList* free_small_chunks() { return &_free_chunks[0]; } |
340 ChunkList* free_humongous_chunks() { return &_free_chunks[2]; } | 188 ChunkTreeDictionary* humongous_dictionary() { |
189 return &_humongous_dictionary; | |
190 } | |
341 | 191 |
342 ChunkList* free_chunks(ChunkIndex index); | 192 ChunkList* free_chunks(ChunkIndex index); |
343 | 193 |
344 // Returns the list for the given chunk word size. | 194 // Returns the list for the given chunk word size. |
345 ChunkList* find_free_chunks_list(size_t word_size); | 195 ChunkList* find_free_chunks_list(size_t word_size); |
354 void locked_verify(); | 204 void locked_verify(); |
355 void verify_free_chunks_total(); | 205 void verify_free_chunks_total(); |
356 | 206 |
357 void locked_print_free_chunks(outputStream* st); | 207 void locked_print_free_chunks(outputStream* st); |
358 void locked_print_sum_free_chunks(outputStream* st); | 208 void locked_print_sum_free_chunks(outputStream* st); |
209 | |
210 void print_on(outputStream* st); | |
359 }; | 211 }; |
360 | 212 |
361 | 213 |
362 // Used to manage the free list of Metablocks (a block corresponds | 214 // Used to manage the free list of Metablocks (a block corresponds |
363 // to the allocation of a quantum of metadata). | 215 // to the allocation of a quantum of metadata). |
364 class BlockFreelist VALUE_OBJ_CLASS_SPEC { | 216 class BlockFreelist VALUE_OBJ_CLASS_SPEC { |
365 #ifdef DEALLOCATE_BLOCKS | 217 BlockTreeDictionary* _dictionary; |
366 BinaryTreeDictionary<Metablock>* _dictionary; | 218 static Metablock* initialize_free_chunk(MetaWord* p, size_t word_size); |
367 #endif | 219 |
368 static Metablock* initialize_free_chunk(Metablock* block, size_t word_size); | |
369 | |
370 #ifdef DEALLOCATE_BLOCKS | |
371 // Accessors | 220 // Accessors |
372 BinaryTreeDictionary<Metablock>* dictionary() const { return _dictionary; } | 221 BlockTreeDictionary* dictionary() const { return _dictionary; } |
373 #endif | |
374 | 222 |
375 public: | 223 public: |
376 BlockFreelist(); | 224 BlockFreelist(); |
377 ~BlockFreelist(); | 225 ~BlockFreelist(); |
378 | 226 |
379 // Get and return a block to the free list | 227 // Get and return a block to the free list |
380 Metablock* get_block(size_t word_size); | 228 MetaWord* get_block(size_t word_size); |
381 void return_block(Metablock* block, size_t word_size); | 229 void return_block(MetaWord* p, size_t word_size); |
382 | 230 |
383 size_t totalSize() { | 231 size_t total_size() { |
384 #ifdef DEALLOCATE_BLOCKS | 232 if (dictionary() == NULL) { |
385 if (dictionary() == NULL) { | |
386 return 0; | |
387 } else { | |
388 return dictionary()->totalSize(); | |
389 } | |
390 #else | |
391 return 0; | 233 return 0; |
392 #endif | 234 } else { |
393 } | 235 return dictionary()->total_size(); |
236 } | |
237 } | |
394 | 238 |
395 void print_on(outputStream* st) const; | 239 void print_on(outputStream* st) const; |
396 }; | 240 }; |
397 | 241 |
398 class VirtualSpaceNode : public CHeapObj<mtClass> { | 242 class VirtualSpaceNode : public CHeapObj<mtClass> { |
598 return result; | 442 return result; |
599 } | 443 } |
600 }; | 444 }; |
601 }; | 445 }; |
602 | 446 |
603 | |
604 class Metadebug : AllStatic { | 447 class Metadebug : AllStatic { |
605 // Debugging support for Metaspaces | 448 // Debugging support for Metaspaces |
606 static int _deallocate_block_a_lot_count; | 449 static int _deallocate_block_a_lot_count; |
607 static int _deallocate_chunk_a_lot_count; | 450 static int _deallocate_chunk_a_lot_count; |
608 static int _allocation_fail_alot_count; | 451 static int _allocation_fail_alot_count; |
653 Mutex* const _lock; | 496 Mutex* const _lock; |
654 | 497 |
655 // List of chunks in use by this SpaceManager. Allocations | 498 // List of chunks in use by this SpaceManager. Allocations |
656 // are done from the current chunk. The list is used for deallocating | 499 // are done from the current chunk. The list is used for deallocating |
657 // chunks when the SpaceManager is freed. | 500 // chunks when the SpaceManager is freed. |
658 Metachunk* _chunks_in_use[NumberOfFreeLists]; | 501 Metachunk* _chunks_in_use[NumberOfInUseLists]; |
659 Metachunk* _current_chunk; | 502 Metachunk* _current_chunk; |
660 | 503 |
661 // Virtual space where allocation comes from. | 504 // Virtual space where allocation comes from. |
662 VirtualSpaceList* _vs_list; | 505 VirtualSpaceList* _vs_list; |
663 | 506 |
698 Metachunk* find_current_chunk(size_t word_size); | 541 Metachunk* find_current_chunk(size_t word_size); |
699 | 542 |
700 // Add chunk to the list of chunks in use | 543 // Add chunk to the list of chunks in use |
701 void add_chunk(Metachunk* v, bool make_current); | 544 void add_chunk(Metachunk* v, bool make_current); |
702 | 545 |
703 // Debugging support | |
704 void verify_chunks_in_use_index(ChunkIndex index, Metachunk* v) { | |
705 switch (index) { | |
706 case 0: | |
707 assert(v->word_size() == SmallChunk, "Not a SmallChunk"); | |
708 break; | |
709 case 1: | |
710 assert(v->word_size() == MediumChunk, "Not a MediumChunk"); | |
711 break; | |
712 case 2: | |
713 assert(v->word_size() > MediumChunk, "Not a HumongousChunk"); | |
714 break; | |
715 default: | |
716 assert(false, "Wrong list."); | |
717 } | |
718 } | |
719 | |
720 protected: | |
721 Mutex* lock() const { return _lock; } | 546 Mutex* lock() const { return _lock; } |
722 | 547 |
723 public: | 548 public: |
724 SpaceManager(Mutex* lock, VirtualSpaceList* vs_list); | 549 SpaceManager(Mutex* lock, VirtualSpaceList* vs_list); |
725 ~SpaceManager(); | 550 ~SpaceManager(); |
749 // Block allocation and deallocation. | 574 // Block allocation and deallocation. |
750 // Allocates a block from the current chunk | 575 // Allocates a block from the current chunk |
751 MetaWord* allocate(size_t word_size); | 576 MetaWord* allocate(size_t word_size); |
752 | 577 |
753 // Helper for allocations | 578 // Helper for allocations |
754 Metablock* allocate_work(size_t word_size); | 579 MetaWord* allocate_work(size_t word_size); |
755 | 580 |
756 // Returns a block to the per manager freelist | 581 // Returns a block to the per manager freelist |
757 void deallocate(MetaWord* p); | 582 void deallocate(MetaWord* p, size_t word_size); |
758 | 583 |
759 // Based on the allocation size and a minimum chunk size, | 584 // Based on the allocation size and a minimum chunk size, |
760 // returned chunk size (for expanding space for chunk allocation). | 585 // returned chunk size (for expanding space for chunk allocation). |
761 size_t calc_chunk_size(size_t allocation_word_size); | 586 size_t calc_chunk_size(size_t allocation_word_size); |
762 | 587 |
763 // Called when an allocation from the current chunk fails. | 588 // Called when an allocation from the current chunk fails. |
764 // Gets a new chunk (may require getting a new virtual space), | 589 // Gets a new chunk (may require getting a new virtual space), |
765 // and allocates from that chunk. | 590 // and allocates from that chunk. |
766 Metablock* grow_and_allocate(size_t word_size); | 591 MetaWord* grow_and_allocate(size_t word_size); |
767 | 592 |
768 // debugging support. | 593 // debugging support. |
769 | 594 |
770 void dump(outputStream* const out) const; | 595 void dump(outputStream* const out) const; |
771 void print_on(outputStream* st) const; | 596 void print_on(outputStream* st) const; |
777 void verify_allocation_total(); | 602 void verify_allocation_total(); |
778 #endif | 603 #endif |
779 }; | 604 }; |
780 | 605 |
781 uint const SpaceManager::_small_chunk_limit = 4; | 606 uint const SpaceManager::_small_chunk_limit = 4; |
607 | |
608 | |
782 | 609 |
783 const char* SpaceManager::_expand_lock_name = | 610 const char* SpaceManager::_expand_lock_name = |
784 "SpaceManager chunk allocation lock"; | 611 "SpaceManager chunk allocation lock"; |
785 const int SpaceManager::_expand_lock_rank = Monitor::leaf - 1; | 612 const int SpaceManager::_expand_lock_rank = Monitor::leaf - 1; |
786 Mutex* const SpaceManager::_expand_lock = | 613 Mutex* const SpaceManager::_expand_lock = |
787 new Mutex(SpaceManager::_expand_lock_rank, | 614 new Mutex(SpaceManager::_expand_lock_rank, |
788 SpaceManager::_expand_lock_name, | 615 SpaceManager::_expand_lock_name, |
789 Mutex::_allow_vm_block_flag); | 616 Mutex::_allow_vm_block_flag); |
790 | 617 |
791 #ifdef ASSERT | |
792 size_t Metablock::_overhead = | |
793 Chunk::aligned_overhead_size(sizeof(Metablock)) / BytesPerWord; | |
794 #else | |
795 size_t Metablock::_overhead = 0; | |
796 #endif | |
797 size_t Metachunk::_overhead = | 618 size_t Metachunk::_overhead = |
798 Chunk::aligned_overhead_size(sizeof(Metachunk)) / BytesPerWord; | 619 Chunk::aligned_overhead_size(sizeof(Metachunk)) / BytesPerWord; |
799 | 620 |
800 // New blocks returned by the Metaspace are zero initialized. | 621 // New blocks returned by the Metaspace are zero initialized. |
801 // We should fix the constructors to not assume this instead. | 622 // We should fix the constructors to not assume this instead. |
802 Metablock* Metablock::initialize(MetaWord* p, size_t word_size) { | 623 Metablock* Metablock::initialize(MetaWord* p, size_t word_size) { |
624 if (p == NULL) { | |
625 return NULL; | |
626 } | |
627 | |
803 Metablock* result = (Metablock*) p; | 628 Metablock* result = (Metablock*) p; |
804 | 629 |
805 // Clear the memory | 630 // Clear the memory |
806 Copy::fill_to_aligned_words((HeapWord*)result, word_size); | 631 Copy::fill_to_aligned_words((HeapWord*)result, word_size); |
807 #ifdef ASSERT | 632 #ifdef ASSERT |
808 result->set_word_size(word_size); | 633 result->set_word_size(word_size); |
809 // Check after work size is set. | |
810 result->set_leader((void*) metaspace_allocation_leader); | |
811 result->set_trailer((void*) metaspace_allocation_trailer); | |
812 #endif | 634 #endif |
813 return result; | 635 return result; |
814 } | |
815 | |
816 void Metablock::verify() { | |
817 #ifdef ASSERT | |
818 assert(leader() == metaspace_allocation_leader && | |
819 trailer() == metaspace_allocation_trailer, | |
820 "block has been corrupted"); | |
821 #endif | |
822 } | 636 } |
823 | 637 |
824 // Metachunk methods | 638 // Metachunk methods |
825 | 639 |
826 Metachunk* Metachunk::initialize(MetaWord* ptr, size_t word_size) { | 640 Metachunk* Metachunk::initialize(MetaWord* ptr, size_t word_size) { |
841 #endif | 655 #endif |
842 return chunk; | 656 return chunk; |
843 } | 657 } |
844 | 658 |
845 | 659 |
846 Metablock* Metachunk::allocate(size_t word_size) { | 660 MetaWord* Metachunk::allocate(size_t word_size) { |
847 Metablock* result = NULL; | 661 MetaWord* result = NULL; |
848 // If available, bump the pointer to allocate. | 662 // If available, bump the pointer to allocate. |
849 if (free_word_size() >= word_size) { | 663 if (free_word_size() >= word_size) { |
850 result = Metablock::initialize(_top, word_size); | 664 result = _top; |
851 _top = _top + word_size; | 665 _top = _top + word_size; |
852 } | 666 } |
853 #ifdef ASSERT | |
854 assert(result == NULL || | |
855 result->word_size() == word_size, | |
856 "Block size is not set correctly"); | |
857 #endif | |
858 return result; | 667 return result; |
859 } | 668 } |
860 | 669 |
861 // _bottom points to the start of the chunk including the overhead. | 670 // _bottom points to the start of the chunk including the overhead. |
862 size_t Metachunk::used_word_size() { | 671 size_t Metachunk::used_word_size() { |
876 " bottom " PTR_FORMAT " top " PTR_FORMAT | 685 " bottom " PTR_FORMAT " top " PTR_FORMAT |
877 " end " PTR_FORMAT " size " SIZE_FORMAT, | 686 " end " PTR_FORMAT " size " SIZE_FORMAT, |
878 bottom(), top(), end(), word_size()); | 687 bottom(), top(), end(), word_size()); |
879 } | 688 } |
880 | 689 |
690 #ifdef ASSERT | |
691 void Metachunk::mangle() { | |
692 // Mangle the payload of the chunk and not the links that | |
693 // maintain list of chunks. | |
694 HeapWord* start = (HeapWord*)(bottom() + overhead()); | |
695 size_t word_size = capacity_word_size() - overhead(); | |
696 Copy::fill_to_words(start, word_size, metadata_chunk_initialize); | |
697 } | |
698 #endif // ASSERT | |
881 | 699 |
882 void Metachunk::verify() { | 700 void Metachunk::verify() { |
883 #ifdef ASSERT | 701 #ifdef ASSERT |
884 // Cannot walk through the blocks unless the blocks have | 702 // Cannot walk through the blocks unless the blocks have |
885 // headers with sizes. | 703 // headers with sizes. |
886 MetaWord* curr = bottom() + overhead(); | 704 assert(_bottom <= _top && |
887 while (curr < top()) { | 705 _top <= _end, |
888 Metablock* block = (Metablock*) curr; | 706 "Chunk has been smashed"); |
889 size_t word_size = block->word_size(); | 707 assert(SpaceManager::is_humongous(_word_size) || |
890 block->verify(); | 708 _word_size == SpaceManager::MediumChunk || |
891 curr = curr + word_size; | 709 _word_size == SpaceManager::SmallChunk, |
892 } | 710 "Chunk size is wrong"); |
893 #endif | 711 #endif |
894 return; | 712 return; |
895 } | 713 } |
896 | 714 |
897 // BlockFreelist methods | 715 // BlockFreelist methods |
898 | 716 |
899 #ifdef DEALLOCATE_BLOCKS | |
900 BlockFreelist::BlockFreelist() : _dictionary(NULL) {} | 717 BlockFreelist::BlockFreelist() : _dictionary(NULL) {} |
901 #else | |
902 BlockFreelist::BlockFreelist() {} | |
903 #endif | |
904 | 718 |
905 BlockFreelist::~BlockFreelist() { | 719 BlockFreelist::~BlockFreelist() { |
906 #ifdef DEALLOCATE_BLOCKS | |
907 if (_dictionary != NULL) { | 720 if (_dictionary != NULL) { |
908 if (Verbose && TraceMetadataChunkAllocation) { | 721 if (Verbose && TraceMetadataChunkAllocation) { |
909 _dictionary->print_free_lists(gclog_or_tty); | 722 _dictionary->print_free_lists(gclog_or_tty); |
910 } | 723 } |
911 delete _dictionary; | 724 delete _dictionary; |
912 } | 725 } |
913 #endif | 726 } |
914 } | 727 |
915 | 728 Metablock* BlockFreelist::initialize_free_chunk(MetaWord* p, size_t word_size) { |
916 Metablock* BlockFreelist::initialize_free_chunk(Metablock* block, size_t word_size) { | 729 Metablock* block = (Metablock*) p; |
917 #ifdef DEALLOCATE_BLOCKS | 730 block->set_word_size(word_size); |
918 #ifdef ASSERT | 731 block->set_prev(NULL); |
919 assert(word_size = block->word_size(), "Wrong chunk size"); | 732 block->set_next(NULL); |
920 #endif | 733 |
921 Metablock* result = block; | |
922 result->setSize(word_size); | |
923 result->linkPrev(NULL); | |
924 result->linkNext(NULL); | |
925 | |
926 return result; | |
927 #else | |
928 ShouldNotReachHere(); | |
929 return block; | 734 return block; |
930 #endif | 735 } |
931 } | 736 |
932 | 737 void BlockFreelist::return_block(MetaWord* p, size_t word_size) { |
933 void BlockFreelist::return_block(Metablock* block, size_t word_size) { | 738 Metablock* free_chunk = initialize_free_chunk(p, word_size); |
934 #ifdef ASSERT | |
935 assert(word_size = block->word_size(), "Block size is wrong");; | |
936 #endif | |
937 Metablock* free_chunk = initialize_free_chunk(block, word_size); | |
938 #ifdef DEALLOCATE_BLOCKS | |
939 if (dictionary() == NULL) { | 739 if (dictionary() == NULL) { |
940 _dictionary = new BinaryTreeDictionary<Metablock>(false /* adaptive_freelists */); | 740 _dictionary = new BlockTreeDictionary(); |
941 } | 741 } |
942 dictionary()->returnChunk(free_chunk); | 742 dictionary()->return_chunk(free_chunk); |
943 #endif | 743 } |
944 } | 744 |
945 | 745 MetaWord* BlockFreelist::get_block(size_t word_size) { |
946 Metablock* BlockFreelist::get_block(size_t word_size) { | |
947 #ifdef DEALLOCATE_BLOCKS | |
948 if (dictionary() == NULL) { | 746 if (dictionary() == NULL) { |
949 return NULL; | 747 return NULL; |
950 } | 748 } |
951 | 749 |
952 Metablock* free_chunk = | 750 if (word_size < TreeChunk<Metablock, FreeList>::min_size()) { |
953 dictionary()->getChunk(word_size, FreeBlockDictionary<Metablock>::exactly); | 751 // Dark matter. Too small for dictionary. |
954 #else | |
955 Metablock* free_chunk = NULL; | |
956 #endif | |
957 if (free_chunk == NULL) { | |
958 return NULL; | 752 return NULL; |
959 } | 753 } |
960 assert(free_chunk->word_size() == word_size, "Size of chunk is incorrect"); | 754 |
961 Metablock* block = Metablock::initialize((MetaWord*) free_chunk, word_size); | 755 Metablock* free_block = |
962 #ifdef ASSERT | 756 dictionary()->get_chunk(word_size, FreeBlockDictionary<Metablock>::exactly); |
963 assert(block->word_size() == word_size, "Block size is not set correctly"); | 757 if (free_block == NULL) { |
964 #endif | 758 return NULL; |
965 | 759 } |
966 return block; | 760 |
761 return (MetaWord*) free_block; | |
967 } | 762 } |
968 | 763 |
969 void BlockFreelist::print_on(outputStream* st) const { | 764 void BlockFreelist::print_on(outputStream* st) const { |
970 #ifdef DEALLOCATE_BLOCKS | |
971 if (dictionary() == NULL) { | 765 if (dictionary() == NULL) { |
972 return; | 766 return; |
973 } | 767 } |
974 dictionary()->print_free_lists(st); | 768 dictionary()->print_free_lists(st); |
975 #else | |
976 return; | |
977 #endif | |
978 } | 769 } |
979 | 770 |
980 // VirtualSpaceNode methods | 771 // VirtualSpaceNode methods |
981 | 772 |
982 VirtualSpaceNode::~VirtualSpaceNode() { | 773 VirtualSpaceNode::~VirtualSpaceNode() { |
1595 #ifdef ASSERT | 1386 #ifdef ASSERT |
1596 if (MetaDataDeallocateALot && | 1387 if (MetaDataDeallocateALot && |
1597 Metadebug::deallocate_block_a_lot_count() % MetaDataDeallocateALotInterval == 0 ) { | 1388 Metadebug::deallocate_block_a_lot_count() % MetaDataDeallocateALotInterval == 0 ) { |
1598 Metadebug::set_deallocate_block_a_lot_count(0); | 1389 Metadebug::set_deallocate_block_a_lot_count(0); |
1599 for (uint i = 0; i < metadata_deallocate_a_lot_block; i++) { | 1390 for (uint i = 0; i < metadata_deallocate_a_lot_block; i++) { |
1600 Metablock* dummy_block = sm->allocate_work(raw_word_size); | 1391 MetaWord* dummy_block = sm->allocate_work(raw_word_size); |
1601 if (dummy_block == 0) { | 1392 if (dummy_block == 0) { |
1602 break; | 1393 break; |
1603 } | 1394 } |
1604 #ifdef ASSERT | 1395 sm->deallocate(dummy_block, raw_word_size); |
1605 assert(dummy_block->word_size() == raw_word_size, "Block size is not set correctly"); | |
1606 #endif | |
1607 sm->deallocate(dummy_block->data()); | |
1608 } | 1396 } |
1609 } else { | 1397 } else { |
1610 Metadebug::inc_deallocate_block_a_lot_count(); | 1398 Metadebug::inc_deallocate_block_a_lot_count(); |
1611 } | 1399 } |
1612 #endif | 1400 #endif |
1782 } | 1570 } |
1783 #endif | 1571 #endif |
1784 } | 1572 } |
1785 | 1573 |
1786 void ChunkManager::locked_verify() { | 1574 void ChunkManager::locked_verify() { |
1575 locked_verify_free_chunks_count(); | |
1787 locked_verify_free_chunks_total(); | 1576 locked_verify_free_chunks_total(); |
1788 locked_verify_free_chunks_count(); | |
1789 } | 1577 } |
1790 | 1578 |
1791 void ChunkManager::locked_print_free_chunks(outputStream* st) { | 1579 void ChunkManager::locked_print_free_chunks(outputStream* st) { |
1792 assert_lock_strong(SpaceManager::expand_lock()); | 1580 assert_lock_strong(SpaceManager::expand_lock()); |
1793 st->print_cr("Free chunk total 0x%x count 0x%x", | 1581 st->print_cr("Free chunk total 0x%x count 0x%x", |
1800 sum_free_chunks(), sum_free_chunks_count()); | 1588 sum_free_chunks(), sum_free_chunks_count()); |
1801 } | 1589 } |
1802 ChunkList* ChunkManager::free_chunks(ChunkIndex index) { | 1590 ChunkList* ChunkManager::free_chunks(ChunkIndex index) { |
1803 return &_free_chunks[index]; | 1591 return &_free_chunks[index]; |
1804 } | 1592 } |
1805 | |
1806 | 1593 |
1807 // These methods that sum the free chunk lists are used in printing | 1594 // These methods that sum the free chunk lists are used in printing |
1808 // methods that are used in product builds. | 1595 // methods that are used in product builds. |
1809 size_t ChunkManager::sum_free_chunks() { | 1596 size_t ChunkManager::sum_free_chunks() { |
1810 assert_lock_strong(SpaceManager::expand_lock()); | 1597 assert_lock_strong(SpaceManager::expand_lock()); |
1816 continue; | 1603 continue; |
1817 } | 1604 } |
1818 | 1605 |
1819 result = result + list->sum_list_capacity(); | 1606 result = result + list->sum_list_capacity(); |
1820 } | 1607 } |
1608 result = result + humongous_dictionary()->total_size(); | |
1821 return result; | 1609 return result; |
1822 } | 1610 } |
1823 | 1611 |
1824 size_t ChunkManager::sum_free_chunks_count() { | 1612 size_t ChunkManager::sum_free_chunks_count() { |
1825 assert_lock_strong(SpaceManager::expand_lock()); | 1613 assert_lock_strong(SpaceManager::expand_lock()); |
1829 if (list == NULL) { | 1617 if (list == NULL) { |
1830 continue; | 1618 continue; |
1831 } | 1619 } |
1832 count = count + list->sum_list_count(); | 1620 count = count + list->sum_list_count(); |
1833 } | 1621 } |
1622 count = count + humongous_dictionary()->total_free_blocks(); | |
1834 return count; | 1623 return count; |
1835 } | 1624 } |
1836 | 1625 |
1837 ChunkList* ChunkManager::find_free_chunks_list(size_t word_size) { | 1626 ChunkList* ChunkManager::find_free_chunks_list(size_t word_size) { |
1838 switch (word_size) { | 1627 switch (word_size) { |
1873 | 1662 |
1874 Metachunk* ChunkManager::free_chunks_get(size_t word_size) { | 1663 Metachunk* ChunkManager::free_chunks_get(size_t word_size) { |
1875 assert_lock_strong(SpaceManager::expand_lock()); | 1664 assert_lock_strong(SpaceManager::expand_lock()); |
1876 | 1665 |
1877 locked_verify(); | 1666 locked_verify(); |
1878 ChunkList* free_list = find_free_chunks_list(word_size); | 1667 |
1879 assert(free_list != NULL, "Sanity check"); | 1668 Metachunk* chunk = NULL; |
1880 | 1669 if (!SpaceManager::is_humongous(word_size)) { |
1881 Metachunk* chunk = free_list->head(); | 1670 ChunkList* free_list = find_free_chunks_list(word_size); |
1882 debug_only(Metachunk* debug_head = chunk;) | 1671 assert(free_list != NULL, "Sanity check"); |
1883 | 1672 |
1884 if (chunk == NULL) { | 1673 chunk = free_list->head(); |
1885 return NULL; | 1674 debug_only(Metachunk* debug_head = chunk;) |
1886 } | 1675 |
1887 | 1676 if (chunk == NULL) { |
1888 Metachunk* prev_chunk = chunk; | 1677 return NULL; |
1889 if (chunk->word_size() == word_size) { | 1678 } |
1890 // Chunk is being removed from the chunks free list. | 1679 |
1891 dec_free_chunks_total(chunk->capacity_word_size()); | |
1892 // Remove the chunk as the head of the list. | 1680 // Remove the chunk as the head of the list. |
1893 free_list->set_head(chunk->next()); | 1681 free_list->set_head(chunk->next()); |
1894 chunk->set_next(NULL); | 1682 chunk->set_next(NULL); |
1683 // Chunk has been removed from the chunks free list. | |
1684 dec_free_chunks_total(chunk->capacity_word_size()); | |
1895 | 1685 |
1896 if (TraceMetadataChunkAllocation && Verbose) { | 1686 if (TraceMetadataChunkAllocation && Verbose) { |
1897 tty->print_cr("ChunkManager::free_chunks_get: free_list " | 1687 tty->print_cr("ChunkManager::free_chunks_get: free_list " |
1898 PTR_FORMAT " head " PTR_FORMAT " size " SIZE_FORMAT, | 1688 PTR_FORMAT " head " PTR_FORMAT " size " SIZE_FORMAT, |
1899 free_list, chunk, chunk->word_size()); | 1689 free_list, chunk, chunk->word_size()); |
1900 } | 1690 } |
1901 } else { | 1691 } else { |
1902 assert(SpaceManager::is_humongous(word_size), | 1692 chunk = humongous_dictionary()->get_chunk( |
1903 "Should only need to check humongous"); | 1693 word_size, |
1904 // This code to find the best fit is just for purposes of | 1694 FreeBlockDictionary<Metachunk>::atLeast); |
1905 // investigating the loss due to fragmentation on a humongous | 1695 |
1906 // chunk. It will be replace by a binaryTreeDictionary for | 1696 if (chunk != NULL) { |
1907 // the humongous chunks. | 1697 if (TraceMetadataHumongousAllocation) { |
1908 uint count = 0; | 1698 size_t waste = chunk->word_size() - word_size; |
1909 Metachunk* best_fit = NULL; | 1699 tty->print_cr("Free list allocate humongous chunk size " SIZE_FORMAT |
1910 Metachunk* best_fit_prev = NULL; | 1700 " for requested size " SIZE_FORMAT |
1911 while (chunk != NULL) { | 1701 " waste " SIZE_FORMAT, |
1912 count++; | 1702 chunk->word_size(), word_size, waste); |
1913 if (chunk->word_size() < word_size) { | |
1914 prev_chunk = chunk; | |
1915 chunk = chunk->next(); | |
1916 } else if (chunk->word_size() == word_size) { | |
1917 break; | |
1918 } else { | |
1919 if (best_fit == NULL || | |
1920 best_fit->word_size() > chunk->word_size()) { | |
1921 best_fit_prev = prev_chunk; | |
1922 best_fit = chunk; | |
1923 } | |
1924 prev_chunk = chunk; | |
1925 chunk = chunk->next(); | |
1926 } | 1703 } |
1927 } | 1704 // Chunk is being removed from the chunks free list. |
1928 if (chunk == NULL) { | 1705 dec_free_chunks_total(chunk->capacity_word_size()); |
1929 prev_chunk = best_fit_prev; | 1706 #ifdef ASSERT |
1930 chunk = best_fit; | 1707 chunk->set_is_free(false); |
1931 } | 1708 #endif |
1932 if (chunk != NULL) { | 1709 } |
1933 if (TraceMetadataHumongousAllocation) { | |
1934 size_t waste = chunk->word_size() - word_size; | |
1935 tty->print_cr("Free list allocate humongous chunk size " SIZE_FORMAT | |
1936 " for requested size " SIZE_FORMAT | |
1937 " waste " SIZE_FORMAT | |
1938 " found at " SIZE_FORMAT " of " SIZE_FORMAT, | |
1939 chunk->word_size(), word_size, waste, | |
1940 count, free_list->sum_list_count()); | |
1941 } | |
1942 // Chunk is being removed from the chunks free list. | |
1943 dec_free_chunks_total(chunk->capacity_word_size()); | |
1944 // Remove the chunk if it is at the head of the list. | |
1945 if (chunk == free_list->head()) { | |
1946 free_list->set_head(chunk->next()); | |
1947 | |
1948 if (TraceMetadataHumongousAllocation) { | |
1949 tty->print_cr("ChunkManager::free_chunks_get: humongous free_list " | |
1950 PTR_FORMAT " chunk " PTR_FORMAT " size " SIZE_FORMAT | |
1951 " new head " PTR_FORMAT, | |
1952 free_list, chunk, chunk->word_size(), | |
1953 free_list->head()); | |
1954 } | |
1955 } else { | |
1956 // Remove a chunk in the interior of the list | |
1957 prev_chunk->set_next(chunk->next()); | |
1958 | |
1959 if (TraceMetadataHumongousAllocation) { | |
1960 tty->print_cr("ChunkManager::free_chunks_get: humongous free_list " | |
1961 PTR_FORMAT " chunk " PTR_FORMAT " size " SIZE_FORMAT | |
1962 PTR_FORMAT " prev " PTR_FORMAT " next " PTR_FORMAT, | |
1963 free_list, chunk, chunk->word_size(), | |
1964 prev_chunk, chunk->next()); | |
1965 } | |
1966 } | |
1967 chunk->set_next(NULL); | |
1968 } else { | |
1969 if (TraceMetadataHumongousAllocation) { | |
1970 tty->print_cr("ChunkManager::free_chunks_get: New humongous chunk of size " | |
1971 SIZE_FORMAT, | |
1972 word_size); | |
1973 } | |
1974 } | |
1975 } | 1710 } |
1976 locked_verify(); | 1711 locked_verify(); |
1977 return chunk; | 1712 return chunk; |
1978 } | 1713 } |
1979 | 1714 |
1998 } | 1733 } |
1999 | 1734 |
2000 return chunk; | 1735 return chunk; |
2001 } | 1736 } |
2002 | 1737 |
1738 void ChunkManager::print_on(outputStream* out) { | |
1739 if (PrintFLSStatistics != 0) { | |
1740 humongous_dictionary()->report_statistics(); | |
1741 } | |
1742 } | |
1743 | |
2003 // SpaceManager methods | 1744 // SpaceManager methods |
2004 | 1745 |
2005 size_t SpaceManager::sum_free_in_chunks_in_use() const { | 1746 size_t SpaceManager::sum_free_in_chunks_in_use() const { |
2006 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); | 1747 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); |
2007 size_t free = 0; | 1748 size_t free = 0; |
2008 for (ChunkIndex i = SmallIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) { | 1749 for (ChunkIndex i = SmallIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { |
2009 Metachunk* chunk = chunks_in_use(i); | 1750 Metachunk* chunk = chunks_in_use(i); |
2010 while (chunk != NULL) { | 1751 while (chunk != NULL) { |
2011 free += chunk->free_word_size(); | 1752 free += chunk->free_word_size(); |
2012 chunk = chunk->next(); | 1753 chunk = chunk->next(); |
2013 } | 1754 } |
2016 } | 1757 } |
2017 | 1758 |
2018 size_t SpaceManager::sum_waste_in_chunks_in_use() const { | 1759 size_t SpaceManager::sum_waste_in_chunks_in_use() const { |
2019 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); | 1760 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); |
2020 size_t result = 0; | 1761 size_t result = 0; |
2021 for (ChunkIndex i = SmallIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) { | 1762 for (ChunkIndex i = SmallIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { |
2022 // Count the free space in all the chunk but not the | 1763 |
2023 // current chunk from which allocations are still being done. | 1764 |
2024 result += sum_waste_in_chunks_in_use(i); | 1765 result += sum_waste_in_chunks_in_use(i); |
2025 } | 1766 } |
1767 | |
2026 return result; | 1768 return result; |
2027 } | 1769 } |
2028 | 1770 |
2029 size_t SpaceManager::sum_waste_in_chunks_in_use(ChunkIndex index) const { | 1771 size_t SpaceManager::sum_waste_in_chunks_in_use(ChunkIndex index) const { |
2030 size_t result = 0; | 1772 size_t result = 0; |
2031 size_t count = 0; | 1773 size_t count = 0; |
2032 Metachunk* chunk = chunks_in_use(index); | 1774 Metachunk* chunk = chunks_in_use(index); |
2033 // Count the free space in all the chunk but not the | 1775 // Count the free space in all the chunk but not the |
2034 // current chunk from which allocations are still being done. | 1776 // current chunk from which allocations are still being done. |
2035 if (chunk != NULL) { | 1777 if (chunk != NULL) { |
2036 while (chunk != NULL) { | 1778 Metachunk* prev = chunk; |
2037 if (chunk != current_chunk()) { | 1779 while (chunk != NULL && chunk != current_chunk()) { |
2038 result += chunk->free_word_size(); | 1780 result += chunk->free_word_size(); |
2039 } | 1781 prev = chunk; |
2040 chunk = chunk->next(); | 1782 chunk = chunk->next(); |
2041 count++; | 1783 count++; |
2042 } | 1784 } |
2043 } | 1785 } |
2044 return result; | 1786 return result; |
2045 } | 1787 } |
2046 | 1788 |
2047 size_t SpaceManager::sum_capacity_in_chunks_in_use() const { | 1789 size_t SpaceManager::sum_capacity_in_chunks_in_use() const { |
2048 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); | 1790 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); |
2049 size_t sum = 0; | 1791 size_t sum = 0; |
2050 for (ChunkIndex i = SmallIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) { | 1792 for (ChunkIndex i = SmallIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { |
2051 Metachunk* chunk = chunks_in_use(i); | 1793 Metachunk* chunk = chunks_in_use(i); |
2052 while (chunk != NULL) { | 1794 while (chunk != NULL) { |
2053 // Just changed this sum += chunk->capacity_word_size(); | 1795 // Just changed this sum += chunk->capacity_word_size(); |
2054 // sum += chunk->word_size() - Metachunk::overhead(); | 1796 // sum += chunk->word_size() - Metachunk::overhead(); |
2055 sum += chunk->capacity_word_size(); | 1797 sum += chunk->capacity_word_size(); |
2059 return sum; | 1801 return sum; |
2060 } | 1802 } |
2061 | 1803 |
2062 size_t SpaceManager::sum_count_in_chunks_in_use() { | 1804 size_t SpaceManager::sum_count_in_chunks_in_use() { |
2063 size_t count = 0; | 1805 size_t count = 0; |
2064 for (ChunkIndex i = SmallIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) { | 1806 for (ChunkIndex i = SmallIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { |
2065 count = count + sum_count_in_chunks_in_use(i); | 1807 count = count + sum_count_in_chunks_in_use(i); |
2066 } | 1808 } |
1809 | |
2067 return count; | 1810 return count; |
2068 } | 1811 } |
2069 | 1812 |
2070 size_t SpaceManager::sum_count_in_chunks_in_use(ChunkIndex i) { | 1813 size_t SpaceManager::sum_count_in_chunks_in_use(ChunkIndex i) { |
2071 size_t count = 0; | 1814 size_t count = 0; |
2079 | 1822 |
2080 | 1823 |
2081 size_t SpaceManager::sum_used_in_chunks_in_use() const { | 1824 size_t SpaceManager::sum_used_in_chunks_in_use() const { |
2082 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); | 1825 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); |
2083 size_t used = 0; | 1826 size_t used = 0; |
2084 for (ChunkIndex i = SmallIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) { | 1827 for (ChunkIndex i = SmallIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { |
2085 Metachunk* chunk = chunks_in_use(i); | 1828 Metachunk* chunk = chunks_in_use(i); |
2086 while (chunk != NULL) { | 1829 while (chunk != NULL) { |
2087 used += chunk->used_word_size(); | 1830 used += chunk->used_word_size(); |
2088 chunk = chunk->next(); | 1831 chunk = chunk->next(); |
2089 } | 1832 } |
2137 SpaceManager::is_humongous(word_size)) { | 1880 SpaceManager::is_humongous(word_size)) { |
2138 gclog_or_tty->print_cr("Metadata humongous allocation:"); | 1881 gclog_or_tty->print_cr("Metadata humongous allocation:"); |
2139 gclog_or_tty->print_cr(" word_size " PTR_FORMAT, word_size); | 1882 gclog_or_tty->print_cr(" word_size " PTR_FORMAT, word_size); |
2140 gclog_or_tty->print_cr(" chunk_word_size " PTR_FORMAT, | 1883 gclog_or_tty->print_cr(" chunk_word_size " PTR_FORMAT, |
2141 chunk_word_size); | 1884 chunk_word_size); |
2142 gclog_or_tty->print_cr(" block overhead " PTR_FORMAT | 1885 gclog_or_tty->print_cr(" chunk overhead " PTR_FORMAT, |
2143 " chunk overhead " PTR_FORMAT, | |
2144 Metablock::overhead(), | |
2145 Metachunk::overhead()); | 1886 Metachunk::overhead()); |
2146 } | 1887 } |
2147 return chunk_word_size; | 1888 return chunk_word_size; |
2148 } | 1889 } |
2149 | 1890 |
2150 Metablock* SpaceManager::grow_and_allocate(size_t word_size) { | 1891 MetaWord* SpaceManager::grow_and_allocate(size_t word_size) { |
2151 assert(vs_list()->current_virtual_space() != NULL, | 1892 assert(vs_list()->current_virtual_space() != NULL, |
2152 "Should have been set"); | 1893 "Should have been set"); |
2153 assert(current_chunk() == NULL || | 1894 assert(current_chunk() == NULL || |
2154 current_chunk()->allocate(word_size) == NULL, | 1895 current_chunk()->allocate(word_size) == NULL, |
2155 "Don't need to expand"); | 1896 "Don't need to expand"); |
2178 } | 1919 } |
2179 | 1920 |
2180 void SpaceManager::print_on(outputStream* st) const { | 1921 void SpaceManager::print_on(outputStream* st) const { |
2181 | 1922 |
2182 for (ChunkIndex i = SmallIndex; | 1923 for (ChunkIndex i = SmallIndex; |
2183 i < NumberOfFreeLists ; | 1924 i < NumberOfInUseLists ; |
2184 i = next_chunk_index(i) ) { | 1925 i = next_chunk_index(i) ) { |
2185 st->print_cr(" chunks_in_use " PTR_FORMAT " chunk size " PTR_FORMAT, | 1926 st->print_cr(" chunks_in_use " PTR_FORMAT " chunk size " PTR_FORMAT, |
2186 chunks_in_use(i), | 1927 chunks_in_use(i), |
2187 chunks_in_use(i) == NULL ? 0 : chunks_in_use(i)->word_size()); | 1928 chunks_in_use(i) == NULL ? 0 : chunks_in_use(i)->word_size()); |
2188 } | 1929 } |
2189 st->print_cr(" waste: Small " SIZE_FORMAT " Medium " SIZE_FORMAT | 1930 st->print_cr(" waste: Small " SIZE_FORMAT " Medium " SIZE_FORMAT |
2190 " Humongous " SIZE_FORMAT, | 1931 " Humongous " SIZE_FORMAT, |
2191 sum_waste_in_chunks_in_use(SmallIndex), | 1932 sum_waste_in_chunks_in_use(SmallIndex), |
2192 sum_waste_in_chunks_in_use(MediumIndex), | 1933 sum_waste_in_chunks_in_use(MediumIndex), |
2193 sum_waste_in_chunks_in_use(HumongousIndex)); | 1934 sum_waste_in_chunks_in_use(HumongousIndex)); |
2194 // Nothing in them yet | 1935 // block free lists |
2195 // block_freelists()->print_on(st); | 1936 if (block_freelists() != NULL) { |
1937 st->print_cr("total in block free lists " SIZE_FORMAT, | |
1938 block_freelists()->total_size()); | |
1939 } | |
2196 } | 1940 } |
2197 | 1941 |
2198 SpaceManager::SpaceManager(Mutex* lock, VirtualSpaceList* vs_list) : | 1942 SpaceManager::SpaceManager(Mutex* lock, VirtualSpaceList* vs_list) : |
2199 _vs_list(vs_list), | 1943 _vs_list(vs_list), |
2200 _allocation_total(0), | 1944 _allocation_total(0), |
2201 _lock(lock) { | 1945 _lock(lock) { |
2202 Metadebug::init_allocation_fail_alot_count(); | 1946 Metadebug::init_allocation_fail_alot_count(); |
2203 for (ChunkIndex i = SmallIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) { | 1947 for (ChunkIndex i = SmallIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { |
2204 _chunks_in_use[i] = NULL; | 1948 _chunks_in_use[i] = NULL; |
2205 } | 1949 } |
2206 _current_chunk = NULL; | 1950 _current_chunk = NULL; |
2207 if (TraceMetadataChunkAllocation && Verbose) { | 1951 if (TraceMetadataChunkAllocation && Verbose) { |
2208 gclog_or_tty->print_cr("SpaceManager(): " PTR_FORMAT, this); | 1952 gclog_or_tty->print_cr("SpaceManager(): " PTR_FORMAT, this); |
2260 | 2004 |
2261 // Humongous chunks | 2005 // Humongous chunks |
2262 // Humongous chunks are never the current chunk. | 2006 // Humongous chunks are never the current chunk. |
2263 Metachunk* humongous_chunks = chunks_in_use(HumongousIndex); | 2007 Metachunk* humongous_chunks = chunks_in_use(HumongousIndex); |
2264 | 2008 |
2265 if (humongous_chunks != NULL) { | 2009 while (humongous_chunks != NULL) { |
2266 chunk_manager->free_humongous_chunks()->add_at_head(humongous_chunks); | 2010 #ifdef ASSERT |
2267 set_chunks_in_use(HumongousIndex, NULL); | 2011 humongous_chunks->set_is_free(true); |
2268 } | 2012 #endif |
2013 Metachunk* next_humongous_chunks = humongous_chunks->next(); | |
2014 chunk_manager->humongous_dictionary()->return_chunk(humongous_chunks); | |
2015 humongous_chunks = next_humongous_chunks; | |
2016 } | |
2017 set_chunks_in_use(HumongousIndex, NULL); | |
2269 chunk_manager->locked_verify(); | 2018 chunk_manager->locked_verify(); |
2270 } | 2019 } |
2271 | 2020 |
2272 void SpaceManager::deallocate(MetaWord* p) { | 2021 void SpaceManager::deallocate(MetaWord* p, size_t word_size) { |
2273 assert_lock_strong(_lock); | 2022 assert_lock_strong(_lock); |
2274 ShouldNotReachHere(); // Where is this needed. | 2023 size_t min_size = TreeChunk<Metablock, FreeList>::min_size(); |
2275 #ifdef DEALLOCATE_BLOCKS | 2024 assert(word_size >= min_size, |
2276 Metablock* block = Metablock::metablock_from_data(p); | 2025 err_msg("Should not deallocate dark matter " SIZE_FORMAT, word_size)); |
2277 // This is expense but kept it until integration JJJ | 2026 block_freelists()->return_block(p, word_size); |
2278 assert(contains((address)block), "Block does not belong to this metaspace"); | |
2279 block_freelists()->return_block(block, word_size); | |
2280 #endif | |
2281 } | 2027 } |
2282 | 2028 |
2283 // Adds a chunk to the list of chunks in use. | 2029 // Adds a chunk to the list of chunks in use. |
2284 void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) { | 2030 void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) { |
2285 | 2031 |
2364 } | 2110 } |
2365 | 2111 |
2366 MetaWord* SpaceManager::allocate(size_t word_size) { | 2112 MetaWord* SpaceManager::allocate(size_t word_size) { |
2367 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); | 2113 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); |
2368 | 2114 |
2369 size_t block_overhead = Metablock::overhead(); | |
2370 // If only the dictionary is going to be used (i.e., no | 2115 // If only the dictionary is going to be used (i.e., no |
2371 // indexed free list), then there is a minimum size requirement. | 2116 // indexed free list), then there is a minimum size requirement. |
2372 // MinChunkSize is a placeholder for the real minimum size JJJ | 2117 // MinChunkSize is a placeholder for the real minimum size JJJ |
2373 size_t byte_size_with_overhead = (word_size + block_overhead) * BytesPerWord; | 2118 size_t byte_size = word_size * BytesPerWord; |
2374 #ifdef DEALLOCATE_BLOCKS | 2119 |
2375 size_t raw_bytes_size = MAX2(ARENA_ALIGN(byte_size_with_overhead), | 2120 size_t byte_size_with_overhead = byte_size + Metablock::overhead(); |
2376 MinChunkSize * BytesPerWord); | 2121 |
2377 #else | 2122 size_t raw_bytes_size = MAX2(byte_size_with_overhead, |
2378 size_t raw_bytes_size = ARENA_ALIGN(byte_size_with_overhead); | 2123 Metablock::min_block_byte_size()); |
2379 #endif | 2124 raw_bytes_size = ARENA_ALIGN(raw_bytes_size); |
2380 size_t raw_word_size = raw_bytes_size / BytesPerWord; | 2125 size_t raw_word_size = raw_bytes_size / BytesPerWord; |
2381 assert(raw_word_size * BytesPerWord == raw_bytes_size, "Size problem"); | 2126 assert(raw_word_size * BytesPerWord == raw_bytes_size, "Size problem"); |
2382 | 2127 |
2383 BlockFreelist* fl = block_freelists(); | 2128 BlockFreelist* fl = block_freelists(); |
2384 Metablock* block = NULL; | 2129 MetaWord* p = NULL; |
2385 // Allocation from the dictionary is expensive in the sense that | 2130 // Allocation from the dictionary is expensive in the sense that |
2386 // the dictionary has to be searched for a size. Don't allocate | 2131 // the dictionary has to be searched for a size. Don't allocate |
2387 // from the dictionary until it starts to get fat. Is this | 2132 // from the dictionary until it starts to get fat. Is this |
2388 // a reasonable policy? Maybe an skinny dictionary is fast enough | 2133 // a reasonable policy? Maybe an skinny dictionary is fast enough |
2389 // for allocations. Do some profiling. JJJ | 2134 // for allocations. Do some profiling. JJJ |
2390 if (fl->totalSize() > allocation_from_dictionary_limit) { | 2135 if (fl->total_size() > allocation_from_dictionary_limit) { |
2391 block = fl->get_block(raw_word_size); | 2136 p = fl->get_block(raw_word_size); |
2392 } | 2137 } |
2393 if (block == NULL) { | 2138 if (p == NULL) { |
2394 block = allocate_work(raw_word_size); | 2139 p = allocate_work(raw_word_size); |
2395 if (block == NULL) { | |
2396 return NULL; | |
2397 } | |
2398 } | 2140 } |
2399 Metadebug::deallocate_block_a_lot(this, raw_word_size); | 2141 Metadebug::deallocate_block_a_lot(this, raw_word_size); |
2400 | 2142 |
2401 // Push the allocation past the word containing the size and leader. | 2143 return p; |
2402 #ifdef ASSERT | |
2403 MetaWord* result = block->data(); | |
2404 return result; | |
2405 #else | |
2406 return (MetaWord*) block; | |
2407 #endif | |
2408 } | 2144 } |
2409 | 2145 |
2410 // Returns the address of spaced allocated for "word_size". | 2146 // Returns the address of spaced allocated for "word_size". |
2411 // This methods does not know about blocks (Metablocks) | 2147 // This methods does not know about blocks (Metablocks) |
2412 Metablock* SpaceManager::allocate_work(size_t word_size) { | 2148 MetaWord* SpaceManager::allocate_work(size_t word_size) { |
2413 assert_lock_strong(_lock); | 2149 assert_lock_strong(_lock); |
2414 #ifdef ASSERT | 2150 #ifdef ASSERT |
2415 if (Metadebug::test_metadata_failure()) { | 2151 if (Metadebug::test_metadata_failure()) { |
2416 return NULL; | 2152 return NULL; |
2417 } | 2153 } |
2418 #endif | 2154 #endif |
2419 // Is there space in the current chunk? | 2155 // Is there space in the current chunk? |
2420 Metablock* result = NULL; | 2156 MetaWord* result = NULL; |
2421 | 2157 |
2422 // For DumpSharedSpaces, only allocate out of the current chunk which is | 2158 // For DumpSharedSpaces, only allocate out of the current chunk which is |
2423 // never null because we gave it the size we wanted. Caller reports out | 2159 // never null because we gave it the size we wanted. Caller reports out |
2424 // of memory if this returns null. | 2160 // of memory if this returns null. |
2425 if (DumpSharedSpaces) { | 2161 if (DumpSharedSpaces) { |
2434 if (result == NULL) { | 2170 if (result == NULL) { |
2435 result = grow_and_allocate(word_size); | 2171 result = grow_and_allocate(word_size); |
2436 } | 2172 } |
2437 if (result > 0) { | 2173 if (result > 0) { |
2438 inc_allocation_total(word_size); | 2174 inc_allocation_total(word_size); |
2439 assert(result != (Metablock*) chunks_in_use(MediumIndex), "Head of the list is being allocated"); | 2175 assert(result != (MetaWord*) chunks_in_use(MediumIndex), |
2440 assert(result->word_size() == word_size, "Size not set correctly"); | 2176 "Head of the list is being allocated"); |
2441 } | 2177 } |
2442 | 2178 |
2443 return result; | 2179 return result; |
2444 } | 2180 } |
2445 | 2181 |
2446 void SpaceManager::verify() { | 2182 void SpaceManager::verify() { |
2447 // If there are blocks in the dictionary, then | 2183 // If there are blocks in the dictionary, then |
2448 // verfication of chunks does not work since | 2184 // verfication of chunks does not work since |
2449 // being in the dictionary alters a chunk. | 2185 // being in the dictionary alters a chunk. |
2450 if (block_freelists()->totalSize() == 0) { | 2186 if (block_freelists()->total_size() == 0) { |
2451 // Skip the small chunks because their next link points to | 2187 // Skip the small chunks because their next link points to |
2452 // medium chunks. This is because the small chunk is the | 2188 // medium chunks. This is because the small chunk is the |
2453 // current chunk (for allocations) until it is full and the | 2189 // current chunk (for allocations) until it is full and the |
2454 // the addition of the next chunk does not NULL the next | 2190 // the addition of the next chunk does not NULL the next |
2455 // like of the small chunk. | 2191 // like of the small chunk. |
2456 for (ChunkIndex i = MediumIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) { | 2192 for (ChunkIndex i = MediumIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { |
2457 Metachunk* curr = chunks_in_use(i); | 2193 Metachunk* curr = chunks_in_use(i); |
2458 while (curr != NULL) { | 2194 while (curr != NULL) { |
2459 curr->verify(); | 2195 curr->verify(); |
2460 curr = curr->next(); | 2196 curr = curr->next(); |
2461 } | 2197 } |
2490 size_t used = 0; | 2226 size_t used = 0; |
2491 size_t capacity = 0; | 2227 size_t capacity = 0; |
2492 | 2228 |
2493 // Add up statistics for all chunks in this SpaceManager. | 2229 // Add up statistics for all chunks in this SpaceManager. |
2494 for (ChunkIndex index = SmallIndex; | 2230 for (ChunkIndex index = SmallIndex; |
2495 index < NumberOfFreeLists; | 2231 index < NumberOfInUseLists; |
2496 index = next_chunk_index(index)) { | 2232 index = next_chunk_index(index)) { |
2497 for (Metachunk* curr = chunks_in_use(index); | 2233 for (Metachunk* curr = chunks_in_use(index); |
2498 curr != NULL; | 2234 curr != NULL; |
2499 curr = curr->next()) { | 2235 curr = curr->next()) { |
2500 out->print("%d) ", i++); | 2236 out->print("%d) ", i++); |
2519 } | 2255 } |
2520 | 2256 |
2521 #ifdef ASSERT | 2257 #ifdef ASSERT |
2522 void SpaceManager::mangle_freed_chunks() { | 2258 void SpaceManager::mangle_freed_chunks() { |
2523 for (ChunkIndex index = SmallIndex; | 2259 for (ChunkIndex index = SmallIndex; |
2524 index < NumberOfFreeLists; | 2260 index < NumberOfInUseLists; |
2525 index = next_chunk_index(index)) { | 2261 index = next_chunk_index(index)) { |
2526 for (Metachunk* curr = chunks_in_use(index); | 2262 for (Metachunk* curr = chunks_in_use(index); |
2527 curr != NULL; | 2263 curr != NULL; |
2528 curr = curr->next()) { | 2264 curr = curr->next()) { |
2529 // Try to detect incorrectly terminated small chunk | 2265 // Try to detect incorrectly terminated small chunk |
2831 if (class_chunk != NULL) { | 2567 if (class_chunk != NULL) { |
2832 class_vsm()->add_chunk(class_chunk, true); | 2568 class_vsm()->add_chunk(class_chunk, true); |
2833 } | 2569 } |
2834 } | 2570 } |
2835 | 2571 |
2836 | |
2837 MetaWord* Metaspace::allocate(size_t word_size, MetadataType mdtype) { | 2572 MetaWord* Metaspace::allocate(size_t word_size, MetadataType mdtype) { |
2838 // DumpSharedSpaces doesn't use class metadata area (yet) | 2573 // DumpSharedSpaces doesn't use class metadata area (yet) |
2839 if (mdtype == ClassType && !DumpSharedSpaces) { | 2574 if (mdtype == ClassType && !DumpSharedSpaces) { |
2840 return class_vsm()->allocate(word_size); | 2575 return class_vsm()->allocate(word_size); |
2841 } else { | 2576 } else { |
2842 return vsm()->allocate(word_size); | 2577 return vsm()->allocate(word_size); |
2843 } | 2578 } |
2844 } | 2579 } |
2845 | 2580 |
2846 MetaWord* Metaspace::expand_and_allocate(size_t word_size, MetadataType mdtype) { | 2581 MetaWord* Metaspace::expand_and_allocate(size_t word_size, MetadataType mdtype) { |
2847 MetaWord* result; | 2582 MetaWord* result; |
2851 MetaspaceGC::inc_capacity_until_GC(delta_words); | 2586 MetaspaceGC::inc_capacity_until_GC(delta_words); |
2852 if (PrintGCDetails && Verbose) { | 2587 if (PrintGCDetails && Verbose) { |
2853 gclog_or_tty->print_cr("Increase capacity to GC from " SIZE_FORMAT | 2588 gclog_or_tty->print_cr("Increase capacity to GC from " SIZE_FORMAT |
2854 " to " SIZE_FORMAT, before_inc, MetaspaceGC::capacity_until_GC()); | 2589 " to " SIZE_FORMAT, before_inc, MetaspaceGC::capacity_until_GC()); |
2855 } | 2590 } |
2591 | |
2856 result = allocate(word_size, mdtype); | 2592 result = allocate(word_size, mdtype); |
2857 | 2593 |
2858 return result; | 2594 return result; |
2859 } | 2595 } |
2860 | 2596 |
2887 } | 2623 } |
2888 | 2624 |
2889 void Metaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) { | 2625 void Metaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) { |
2890 if (SafepointSynchronize::is_at_safepoint()) { | 2626 if (SafepointSynchronize::is_at_safepoint()) { |
2891 assert(Thread::current()->is_VM_thread(), "should be the VM thread"); | 2627 assert(Thread::current()->is_VM_thread(), "should be the VM thread"); |
2892 // Don't take lock | 2628 // Don't take Heap_lock |
2893 #ifdef DEALLOCATE_BLOCKS | 2629 MutexLocker ml(vsm()->lock()); |
2630 if (word_size < TreeChunk<Metablock, FreeList>::min_size()) { | |
2631 // Dark matter. Too small for dictionary. | |
2632 #ifdef ASSERT | |
2633 Copy::fill_to_words((HeapWord*)ptr, word_size, 0xf5f5f5f5); | |
2634 #endif | |
2635 return; | |
2636 } | |
2894 if (is_class) { | 2637 if (is_class) { |
2895 class_vsm()->deallocate(ptr); | 2638 class_vsm()->deallocate(ptr, word_size); |
2896 } else { | 2639 } else { |
2897 vsm()->deallocate(ptr); | 2640 vsm()->deallocate(ptr, word_size); |
2898 } | 2641 } |
2899 #else | |
2900 #ifdef ASSERT | |
2901 Copy::fill_to_words((HeapWord*)ptr, word_size, metadata_deallocate); | |
2902 #endif | |
2903 #endif | |
2904 | |
2905 } else { | 2642 } else { |
2906 MutexLocker ml(vsm()->lock()); | 2643 MutexLocker ml(vsm()->lock()); |
2907 | 2644 |
2908 #ifdef DEALLOCATE_BLOCKS | 2645 if (word_size < TreeChunk<Metablock, FreeList>::min_size()) { |
2646 // Dark matter. Too small for dictionary. | |
2647 #ifdef ASSERT | |
2648 Copy::fill_to_words((HeapWord*)ptr, word_size, 0xf5f5f5f5); | |
2649 #endif | |
2650 return; | |
2651 } | |
2909 if (is_class) { | 2652 if (is_class) { |
2910 class_vsm()->deallocate(ptr); | 2653 class_vsm()->deallocate(ptr, word_size); |
2911 } else { | 2654 } else { |
2912 vsm()->deallocate(ptr); | 2655 vsm()->deallocate(ptr, word_size); |
2913 } | 2656 } |
2914 #else | 2657 } |
2915 #ifdef ASSERT | 2658 } |
2916 Copy::fill_to_words((HeapWord*)ptr, word_size, metadata_deallocate); | 2659 |
2917 #endif | 2660 Metablock* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size, |
2918 #endif | |
2919 } | |
2920 } | |
2921 | |
2922 MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size, | |
2923 bool read_only, MetadataType mdtype, TRAPS) { | 2661 bool read_only, MetadataType mdtype, TRAPS) { |
2924 if (HAS_PENDING_EXCEPTION) { | 2662 if (HAS_PENDING_EXCEPTION) { |
2925 assert(false, "Should not allocate with exception pending"); | 2663 assert(false, "Should not allocate with exception pending"); |
2926 return NULL; // caller does a CHECK_NULL too | 2664 return NULL; // caller does a CHECK_NULL too |
2927 } | 2665 } |
2941 result = loader_data->rw_metaspace()->allocate(word_size, NonClassType); | 2679 result = loader_data->rw_metaspace()->allocate(word_size, NonClassType); |
2942 } | 2680 } |
2943 if (result == NULL) { | 2681 if (result == NULL) { |
2944 report_out_of_shared_space(read_only ? SharedReadOnly : SharedReadWrite); | 2682 report_out_of_shared_space(read_only ? SharedReadOnly : SharedReadWrite); |
2945 } | 2683 } |
2946 return result; | 2684 return Metablock::initialize(result, word_size); |
2947 } | 2685 } |
2948 | 2686 |
2949 result = loader_data->metaspace_non_null()->allocate(word_size, mdtype); | 2687 result = loader_data->metaspace_non_null()->allocate(word_size, mdtype); |
2950 | 2688 |
2951 if (result == NULL) { | 2689 if (result == NULL) { |
2952 // Try to clean out some memory and retry. | 2690 // Try to clean out some memory and retry. |
2953 result = | 2691 result = |
2954 Universe::heap()->collector_policy()->satisfy_failed_metadata_allocation( | 2692 Universe::heap()->collector_policy()->satisfy_failed_metadata_allocation( |
2955 loader_data, word_size, mdtype); | 2693 loader_data, word_size, mdtype); |
2956 | 2694 |
2957 // If result is still null, we are out of memory. | 2695 // If result is still null, we are out of memory. |
2958 if (result == NULL) { | 2696 if (result == NULL) { |
2959 // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support | 2697 // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support |
2965 "Metadata space"); | 2703 "Metadata space"); |
2966 } | 2704 } |
2967 THROW_OOP_0(Universe::out_of_memory_error_perm_gen()); | 2705 THROW_OOP_0(Universe::out_of_memory_error_perm_gen()); |
2968 } | 2706 } |
2969 } | 2707 } |
2970 return result; | 2708 return Metablock::initialize(result, word_size); |
2971 } | 2709 } |
2972 | 2710 |
2973 void Metaspace::print_on(outputStream* out) const { | 2711 void Metaspace::print_on(outputStream* out) const { |
2974 // Print both class virtual space counts and metaspace. | 2712 // Print both class virtual space counts and metaspace. |
2975 if (Verbose) { | 2713 if (Verbose) { |