Mercurial > hg > graal-jvmci-8
comparison src/share/vm/memory/metaspace.cpp @ 7446:e51c9860cf66
8005082: NPG: Add specialized Metachunk sizes for reflection and anonymous classloaders
Reviewed-by: johnc, coleenp
author | jmasa |
---|---|
date | Mon, 03 Dec 2012 15:09:39 -0800 |
parents | c71879335291 |
children | 1de1b145f6bc |
comparison
equal
deleted
inserted
replaced
7445:cd962e15c08e | 7446:e51c9860cf66 |
---|---|
56 | 56 |
57 MetaWord* last_allocated = 0; | 57 MetaWord* last_allocated = 0; |
58 | 58 |
59 // Used in declarations in SpaceManager and ChunkManager | 59 // Used in declarations in SpaceManager and ChunkManager |
60 enum ChunkIndex { | 60 enum ChunkIndex { |
61 SmallIndex = 0, | 61 ZeroIndex = 0, |
62 MediumIndex = 1, | 62 SpecializedIndex = ZeroIndex, |
63 HumongousIndex = 2, | 63 SmallIndex = SpecializedIndex + 1, |
64 NumberOfFreeLists = 2, | 64 MediumIndex = SmallIndex + 1, |
65 NumberOfInUseLists = 3 | 65 HumongousIndex = MediumIndex + 1, |
66 NumberOfFreeLists = 3, | |
67 NumberOfInUseLists = 4 | |
68 }; | |
69 | |
70 enum ChunkSizes { // in words. | |
71 ClassSpecializedChunk = 128, | |
72 SpecializedChunk = 128, | |
73 ClassSmallChunk = 256, | |
74 SmallChunk = 512, | |
75 ClassMediumChunk = 1 * K, | |
76 MediumChunk = 8 * K, | |
77 HumongousChunkGranularity = 8 | |
66 }; | 78 }; |
67 | 79 |
68 static ChunkIndex next_chunk_index(ChunkIndex i) { | 80 static ChunkIndex next_chunk_index(ChunkIndex i) { |
69 assert(i < NumberOfInUseLists, "Out of bound"); | 81 assert(i < NumberOfInUseLists, "Out of bound"); |
70 return (ChunkIndex) (i+1); | 82 return (ChunkIndex) (i+1); |
124 // SmallChunk | 136 // SmallChunk |
125 // MediumChunk | 137 // MediumChunk |
126 // HumongousChunk | 138 // HumongousChunk |
127 ChunkList _free_chunks[NumberOfFreeLists]; | 139 ChunkList _free_chunks[NumberOfFreeLists]; |
128 | 140 |
141 | |
129 // HumongousChunk | 142 // HumongousChunk |
130 ChunkTreeDictionary _humongous_dictionary; | 143 ChunkTreeDictionary _humongous_dictionary; |
131 | 144 |
132 // ChunkManager in all lists of this type | 145 // ChunkManager in all lists of this type |
133 size_t _free_chunks_total; | 146 size_t _free_chunks_total; |
167 | 180 |
168 // add or delete (return) a chunk to the global freelist. | 181 // add or delete (return) a chunk to the global freelist. |
169 Metachunk* chunk_freelist_allocate(size_t word_size); | 182 Metachunk* chunk_freelist_allocate(size_t word_size); |
170 void chunk_freelist_deallocate(Metachunk* chunk); | 183 void chunk_freelist_deallocate(Metachunk* chunk); |
171 | 184 |
185 // Map a size to a list index assuming that there are lists | |
186 // for special, small, medium, and humongous chunks. | |
187 static ChunkIndex list_index(size_t size); | |
188 | |
172 // Total of the space in the free chunks list | 189 // Total of the space in the free chunks list |
173 size_t free_chunks_total(); | 190 size_t free_chunks_total(); |
174 size_t free_chunks_total_in_bytes(); | 191 size_t free_chunks_total_in_bytes(); |
175 | 192 |
176 // Number of chunks in the free chunks list | 193 // Number of chunks in the free chunks list |
178 | 195 |
179 void inc_free_chunks_total(size_t v, size_t count = 1) { | 196 void inc_free_chunks_total(size_t v, size_t count = 1) { |
180 Atomic::add_ptr(count, &_free_chunks_count); | 197 Atomic::add_ptr(count, &_free_chunks_count); |
181 Atomic::add_ptr(v, &_free_chunks_total); | 198 Atomic::add_ptr(v, &_free_chunks_total); |
182 } | 199 } |
183 ChunkList* free_medium_chunks() { return &_free_chunks[1]; } | |
184 ChunkList* free_small_chunks() { return &_free_chunks[0]; } | |
185 ChunkTreeDictionary* humongous_dictionary() { | 200 ChunkTreeDictionary* humongous_dictionary() { |
186 return &_humongous_dictionary; | 201 return &_humongous_dictionary; |
187 } | 202 } |
188 | 203 |
189 ChunkList* free_chunks(ChunkIndex index); | 204 ChunkList* free_chunks(ChunkIndex index); |
398 | 413 |
399 public: | 414 public: |
400 VirtualSpaceList(size_t word_size); | 415 VirtualSpaceList(size_t word_size); |
401 VirtualSpaceList(ReservedSpace rs); | 416 VirtualSpaceList(ReservedSpace rs); |
402 | 417 |
403 Metachunk* get_new_chunk(size_t word_size, size_t grow_chunks_by_words); | 418 Metachunk* get_new_chunk(size_t word_size, |
419 size_t grow_chunks_by_words, | |
420 size_t medium_chunk_bunch); | |
421 | |
422 // Get the first chunk for a Metaspace. Used for | |
423 // special cases such as the boot class loader, reflection | |
424 // class loader and anonymous class loader. | |
425 Metachunk* get_initialization_chunk(size_t word_size, size_t chunk_bunch); | |
404 | 426 |
405 VirtualSpaceNode* current_virtual_space() { | 427 VirtualSpaceNode* current_virtual_space() { |
406 return _current_virtual_space; | 428 return _current_virtual_space; |
407 } | 429 } |
408 | 430 |
499 class SpaceManager : public CHeapObj<mtClass> { | 521 class SpaceManager : public CHeapObj<mtClass> { |
500 friend class Metaspace; | 522 friend class Metaspace; |
501 friend class Metadebug; | 523 friend class Metadebug; |
502 | 524 |
503 private: | 525 private: |
526 | |
504 // protects allocations and contains. | 527 // protects allocations and contains. |
505 Mutex* const _lock; | 528 Mutex* const _lock; |
529 | |
530 // Chunk related size | |
531 size_t _medium_chunk_bunch; | |
506 | 532 |
507 // List of chunks in use by this SpaceManager. Allocations | 533 // List of chunks in use by this SpaceManager. Allocations |
508 // are done from the current chunk. The list is used for deallocating | 534 // are done from the current chunk. The list is used for deallocating |
509 // chunks when the SpaceManager is freed. | 535 // chunks when the SpaceManager is freed. |
510 Metachunk* _chunks_in_use[NumberOfInUseLists]; | 536 Metachunk* _chunks_in_use[NumberOfInUseLists]; |
530 // protects virtualspace and chunk expansions | 556 // protects virtualspace and chunk expansions |
531 static const char* _expand_lock_name; | 557 static const char* _expand_lock_name; |
532 static const int _expand_lock_rank; | 558 static const int _expand_lock_rank; |
533 static Mutex* const _expand_lock; | 559 static Mutex* const _expand_lock; |
534 | 560 |
561 private: | |
535 // Accessors | 562 // Accessors |
536 Metachunk* chunks_in_use(ChunkIndex index) const { return _chunks_in_use[index]; } | 563 Metachunk* chunks_in_use(ChunkIndex index) const { return _chunks_in_use[index]; } |
537 void set_chunks_in_use(ChunkIndex index, Metachunk* v) { _chunks_in_use[index] = v; } | 564 void set_chunks_in_use(ChunkIndex index, Metachunk* v) { _chunks_in_use[index] = v; } |
538 | 565 |
539 BlockFreelist* block_freelists() const { | 566 BlockFreelist* block_freelists() const { |
552 // Add chunk to the list of chunks in use | 579 // Add chunk to the list of chunks in use |
553 void add_chunk(Metachunk* v, bool make_current); | 580 void add_chunk(Metachunk* v, bool make_current); |
554 | 581 |
555 Mutex* lock() const { return _lock; } | 582 Mutex* lock() const { return _lock; } |
556 | 583 |
584 const char* chunk_size_name(ChunkIndex index) const; | |
585 | |
586 protected: | |
587 void initialize(); | |
588 | |
557 public: | 589 public: |
558 SpaceManager(Mutex* lock, VirtualSpaceList* vs_list); | 590 SpaceManager(Mutex* lock, |
591 VirtualSpaceList* vs_list); | |
559 ~SpaceManager(); | 592 ~SpaceManager(); |
560 | 593 |
561 enum ChunkSizes { // in words. | 594 enum ChunkMultiples { |
562 SmallChunk = 512, | 595 MediumChunkMultiple = 4 |
563 MediumChunk = 8 * K, | |
564 MediumChunkBunch = 4 * MediumChunk | |
565 }; | 596 }; |
566 | 597 |
567 // Accessors | 598 // Accessors |
599 size_t specialized_chunk_size() { return SpecializedChunk; } | |
600 size_t small_chunk_size() { return (size_t) vs_list()->is_class() ? ClassSmallChunk : SmallChunk; } | |
601 size_t medium_chunk_size() { return (size_t) vs_list()->is_class() ? ClassMediumChunk : MediumChunk; } | |
602 size_t medium_chunk_bunch() { return medium_chunk_size() * MediumChunkMultiple; } | |
603 | |
568 size_t allocation_total() const { return _allocation_total; } | 604 size_t allocation_total() const { return _allocation_total; } |
569 void inc_allocation_total(size_t v) { Atomic::add_ptr(v, &_allocation_total); } | 605 void inc_allocation_total(size_t v) { Atomic::add_ptr(v, &_allocation_total); } |
570 static bool is_humongous(size_t word_size) { return word_size > MediumChunk; } | 606 bool is_humongous(size_t word_size) { return word_size > medium_chunk_size(); } |
571 | 607 |
572 static Mutex* expand_lock() { return _expand_lock; } | 608 static Mutex* expand_lock() { return _expand_lock; } |
609 | |
610 // Set the sizes for the initial chunks. | |
611 void get_initial_chunk_sizes(Metaspace::MetaspaceType type, | |
612 size_t* chunk_word_size, | |
613 size_t* class_chunk_word_size); | |
573 | 614 |
574 size_t sum_capacity_in_chunks_in_use() const; | 615 size_t sum_capacity_in_chunks_in_use() const; |
575 size_t sum_used_in_chunks_in_use() const; | 616 size_t sum_used_in_chunks_in_use() const; |
576 size_t sum_free_in_chunks_in_use() const; | 617 size_t sum_free_in_chunks_in_use() const; |
577 size_t sum_waste_in_chunks_in_use() const; | 618 size_t sum_waste_in_chunks_in_use() const; |
578 size_t sum_waste_in_chunks_in_use(ChunkIndex index ) const; | 619 size_t sum_waste_in_chunks_in_use(ChunkIndex index ) const; |
579 | 620 |
580 size_t sum_count_in_chunks_in_use(); | 621 size_t sum_count_in_chunks_in_use(); |
581 size_t sum_count_in_chunks_in_use(ChunkIndex i); | 622 size_t sum_count_in_chunks_in_use(ChunkIndex i); |
623 | |
624 Metachunk* get_new_chunk(size_t word_size, size_t grow_chunks_by_words); | |
582 | 625 |
583 // Block allocation and deallocation. | 626 // Block allocation and deallocation. |
584 // Allocates a block from the current chunk | 627 // Allocates a block from the current chunk |
585 MetaWord* allocate(size_t word_size); | 628 MetaWord* allocate(size_t word_size); |
586 | 629 |
770 | 813 |
771 if (!_rs.is_reserved()) { | 814 if (!_rs.is_reserved()) { |
772 return false; | 815 return false; |
773 } | 816 } |
774 | 817 |
775 // Commit only 1 page instead of the whole reserved space _rs.size() | 818 // An allocation out of this Virtualspace that is larger |
776 size_t committed_byte_size = os::vm_page_size(); | 819 // than an initial commit size can waste that initial committed |
820 // space. | |
821 size_t committed_byte_size = 0; | |
777 bool result = virtual_space()->initialize(_rs, committed_byte_size); | 822 bool result = virtual_space()->initialize(_rs, committed_byte_size); |
778 if (result) { | 823 if (result) { |
779 set_top((MetaWord*)virtual_space()->low()); | 824 set_top((MetaWord*)virtual_space()->low()); |
780 set_reserved(MemRegion((HeapWord*)_rs.base(), | 825 set_reserved(MemRegion((HeapWord*)_rs.base(), |
781 (HeapWord*)(_rs.base() + _rs.size()))); | 826 (HeapWord*)(_rs.base() + _rs.size()))); |
797 size_t capacity = capacity_words_in_vs(); | 842 size_t capacity = capacity_words_in_vs(); |
798 VirtualSpace* vs = virtual_space(); | 843 VirtualSpace* vs = virtual_space(); |
799 st->print_cr(" space @ " PTR_FORMAT " " SIZE_FORMAT "K, %3d%% used " | 844 st->print_cr(" space @ " PTR_FORMAT " " SIZE_FORMAT "K, %3d%% used " |
800 "[" PTR_FORMAT ", " PTR_FORMAT ", " | 845 "[" PTR_FORMAT ", " PTR_FORMAT ", " |
801 PTR_FORMAT ", " PTR_FORMAT ")", | 846 PTR_FORMAT ", " PTR_FORMAT ")", |
802 vs, capacity / K, used * 100 / capacity, | 847 vs, capacity / K, |
848 capacity == 0 ? 0 : used * 100 / capacity, | |
803 bottom(), top(), end(), | 849 bottom(), top(), end(), |
804 vs->high_boundary()); | 850 vs->high_boundary()); |
805 } | 851 } |
806 | 852 |
807 #ifdef ASSERT | 853 #ifdef ASSERT |
920 vsl->print_on(tty); | 966 vsl->print_on(tty); |
921 } | 967 } |
922 } | 968 } |
923 | 969 |
924 Metachunk* VirtualSpaceList::get_new_chunk(size_t word_size, | 970 Metachunk* VirtualSpaceList::get_new_chunk(size_t word_size, |
925 size_t grow_chunks_by_words) { | 971 size_t grow_chunks_by_words, |
972 size_t medium_chunk_bunch) { | |
926 | 973 |
927 // Get a chunk from the chunk freelist | 974 // Get a chunk from the chunk freelist |
928 Metachunk* next = chunk_manager()->chunk_freelist_allocate(grow_chunks_by_words); | 975 Metachunk* next = chunk_manager()->chunk_freelist_allocate(grow_chunks_by_words); |
929 | 976 |
930 // Allocate a chunk out of the current virtual space. | 977 // Allocate a chunk out of the current virtual space. |
933 } | 980 } |
934 | 981 |
935 if (next == NULL) { | 982 if (next == NULL) { |
936 // Not enough room in current virtual space. Try to commit | 983 // Not enough room in current virtual space. Try to commit |
937 // more space. | 984 // more space. |
938 size_t expand_vs_by_words = MAX2((size_t)SpaceManager::MediumChunkBunch, | 985 size_t expand_vs_by_words = MAX2(medium_chunk_bunch, |
939 grow_chunks_by_words); | 986 grow_chunks_by_words); |
940 size_t page_size_words = os::vm_page_size() / BytesPerWord; | 987 size_t page_size_words = os::vm_page_size() / BytesPerWord; |
941 size_t aligned_expand_vs_by_words = align_size_up(expand_vs_by_words, | 988 size_t aligned_expand_vs_by_words = align_size_up(expand_vs_by_words, |
942 page_size_words); | 989 page_size_words); |
943 bool vs_expanded = | 990 bool vs_expanded = |
944 current_virtual_space()->expand_by(aligned_expand_vs_by_words, false); | 991 current_virtual_space()->expand_by(aligned_expand_vs_by_words, false); |
952 MAX2((size_t)VirtualSpaceSize, aligned_expand_vs_by_words); | 999 MAX2((size_t)VirtualSpaceSize, aligned_expand_vs_by_words); |
953 if (grow_vs(grow_vs_words)) { | 1000 if (grow_vs(grow_vs_words)) { |
954 // Got it. It's on the list now. Get a chunk from it. | 1001 // Got it. It's on the list now. Get a chunk from it. |
955 next = current_virtual_space()->get_chunk_vs_with_expand(grow_chunks_by_words); | 1002 next = current_virtual_space()->get_chunk_vs_with_expand(grow_chunks_by_words); |
956 } | 1003 } |
957 if (TraceMetadataHumongousAllocation && SpaceManager::is_humongous(word_size)) { | |
958 gclog_or_tty->print_cr(" aligned_expand_vs_by_words " PTR_FORMAT, | |
959 aligned_expand_vs_by_words); | |
960 gclog_or_tty->print_cr(" grow_vs_words " PTR_FORMAT, | |
961 grow_vs_words); | |
962 } | |
963 } else { | 1004 } else { |
964 // Allocation will fail and induce a GC | 1005 // Allocation will fail and induce a GC |
965 if (TraceMetadataChunkAllocation && Verbose) { | 1006 if (TraceMetadataChunkAllocation && Verbose) { |
966 gclog_or_tty->print_cr("VirtualSpaceList::get_new_chunk():" | 1007 gclog_or_tty->print_cr("VirtualSpaceList::get_new_chunk():" |
967 " Fail instead of expand the metaspace"); | 1008 " Fail instead of expand the metaspace"); |
972 next = current_virtual_space()->get_chunk_vs(grow_chunks_by_words); | 1013 next = current_virtual_space()->get_chunk_vs(grow_chunks_by_words); |
973 assert(next != NULL, "Just expanded, should succeed"); | 1014 assert(next != NULL, "Just expanded, should succeed"); |
974 } | 1015 } |
975 } | 1016 } |
976 | 1017 |
1018 assert(next == NULL || (next->next() == NULL && next->prev() == NULL), | |
1019 "New chunk is still on some list"); | |
977 return next; | 1020 return next; |
1021 } | |
1022 | |
1023 Metachunk* VirtualSpaceList::get_initialization_chunk(size_t chunk_word_size, | |
1024 size_t chunk_bunch) { | |
1025 // Get a chunk from the chunk freelist | |
1026 Metachunk* new_chunk = get_new_chunk(chunk_word_size, | |
1027 chunk_word_size, | |
1028 chunk_bunch); | |
1029 return new_chunk; | |
978 } | 1030 } |
979 | 1031 |
980 void VirtualSpaceList::print_on(outputStream* st) const { | 1032 void VirtualSpaceList::print_on(outputStream* st) const { |
981 if (TraceMetadataChunkAllocation && Verbose) { | 1033 if (TraceMetadataChunkAllocation && Verbose) { |
982 VirtualSpaceListIterator iter(virtual_space_list()); | 1034 VirtualSpaceListIterator iter(virtual_space_list()); |
1371 return result; | 1423 return result; |
1372 } | 1424 } |
1373 | 1425 |
1374 void ChunkList::add_at_head(Metachunk* head, Metachunk* tail) { | 1426 void ChunkList::add_at_head(Metachunk* head, Metachunk* tail) { |
1375 assert_lock_strong(SpaceManager::expand_lock()); | 1427 assert_lock_strong(SpaceManager::expand_lock()); |
1376 assert(tail->next() == NULL, "Not the tail"); | 1428 assert(head == tail || tail->next() == NULL, |
1429 "Not the tail or the head has already been added to a list"); | |
1377 | 1430 |
1378 if (TraceMetadataChunkAllocation && Verbose) { | 1431 if (TraceMetadataChunkAllocation && Verbose) { |
1379 tty->print("ChunkList::add_at_head: "); | 1432 gclog_or_tty->print("ChunkList::add_at_head(head, tail): "); |
1380 Metachunk* cur = head; | 1433 Metachunk* cur = head; |
1381 while (cur != NULL) { | 1434 while (cur != NULL) { |
1382 tty->print(PTR_FORMAT " (" SIZE_FORMAT ") ", cur, cur->word_size()); | 1435 gclog_or_tty->print(PTR_FORMAT " (" SIZE_FORMAT ") ", cur, cur->word_size()); |
1383 cur = cur->next(); | 1436 cur = cur->next(); |
1384 } | 1437 } |
1385 tty->print_cr(""); | 1438 gclog_or_tty->print_cr(""); |
1386 } | 1439 } |
1387 | 1440 |
1388 if (tail != NULL) { | 1441 if (tail != NULL) { |
1389 tail->set_next(_head); | 1442 tail->set_next(_head); |
1390 } | 1443 } |
1484 locked_verify_free_chunks_total(); | 1537 locked_verify_free_chunks_total(); |
1485 } | 1538 } |
1486 | 1539 |
1487 void ChunkManager::locked_print_free_chunks(outputStream* st) { | 1540 void ChunkManager::locked_print_free_chunks(outputStream* st) { |
1488 assert_lock_strong(SpaceManager::expand_lock()); | 1541 assert_lock_strong(SpaceManager::expand_lock()); |
1489 st->print_cr("Free chunk total 0x%x count 0x%x", | 1542 st->print_cr("Free chunk total " SIZE_FORMAT " count " SIZE_FORMAT, |
1490 _free_chunks_total, _free_chunks_count); | 1543 _free_chunks_total, _free_chunks_count); |
1491 } | 1544 } |
1492 | 1545 |
1493 void ChunkManager::locked_print_sum_free_chunks(outputStream* st) { | 1546 void ChunkManager::locked_print_sum_free_chunks(outputStream* st) { |
1494 assert_lock_strong(SpaceManager::expand_lock()); | 1547 assert_lock_strong(SpaceManager::expand_lock()); |
1495 st->print_cr("Sum free chunk total 0x%x count 0x%x", | 1548 st->print_cr("Sum free chunk total " SIZE_FORMAT " count " SIZE_FORMAT, |
1496 sum_free_chunks(), sum_free_chunks_count()); | 1549 sum_free_chunks(), sum_free_chunks_count()); |
1497 } | 1550 } |
1498 ChunkList* ChunkManager::free_chunks(ChunkIndex index) { | 1551 ChunkList* ChunkManager::free_chunks(ChunkIndex index) { |
1499 return &_free_chunks[index]; | 1552 return &_free_chunks[index]; |
1500 } | 1553 } |
1502 // These methods that sum the free chunk lists are used in printing | 1555 // These methods that sum the free chunk lists are used in printing |
1503 // methods that are used in product builds. | 1556 // methods that are used in product builds. |
1504 size_t ChunkManager::sum_free_chunks() { | 1557 size_t ChunkManager::sum_free_chunks() { |
1505 assert_lock_strong(SpaceManager::expand_lock()); | 1558 assert_lock_strong(SpaceManager::expand_lock()); |
1506 size_t result = 0; | 1559 size_t result = 0; |
1507 for (ChunkIndex i = SmallIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) { | 1560 for (ChunkIndex i = ZeroIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) { |
1508 ChunkList* list = free_chunks(i); | 1561 ChunkList* list = free_chunks(i); |
1509 | 1562 |
1510 if (list == NULL) { | 1563 if (list == NULL) { |
1511 continue; | 1564 continue; |
1512 } | 1565 } |
1518 } | 1571 } |
1519 | 1572 |
1520 size_t ChunkManager::sum_free_chunks_count() { | 1573 size_t ChunkManager::sum_free_chunks_count() { |
1521 assert_lock_strong(SpaceManager::expand_lock()); | 1574 assert_lock_strong(SpaceManager::expand_lock()); |
1522 size_t count = 0; | 1575 size_t count = 0; |
1523 for (ChunkIndex i = SmallIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) { | 1576 for (ChunkIndex i = ZeroIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) { |
1524 ChunkList* list = free_chunks(i); | 1577 ChunkList* list = free_chunks(i); |
1525 if (list == NULL) { | 1578 if (list == NULL) { |
1526 continue; | 1579 continue; |
1527 } | 1580 } |
1528 count = count + list->sum_list_count(); | 1581 count = count + list->sum_list_count(); |
1530 count = count + humongous_dictionary()->total_free_blocks(); | 1583 count = count + humongous_dictionary()->total_free_blocks(); |
1531 return count; | 1584 return count; |
1532 } | 1585 } |
1533 | 1586 |
1534 ChunkList* ChunkManager::find_free_chunks_list(size_t word_size) { | 1587 ChunkList* ChunkManager::find_free_chunks_list(size_t word_size) { |
1535 switch (word_size) { | 1588 ChunkIndex index = list_index(word_size); |
1536 case SpaceManager::SmallChunk : | 1589 assert(index < HumongousIndex, "No humongous list"); |
1537 return &_free_chunks[0]; | 1590 return free_chunks(index); |
1538 case SpaceManager::MediumChunk : | |
1539 return &_free_chunks[1]; | |
1540 default: | |
1541 assert(word_size > SpaceManager::MediumChunk, "List inconsistency"); | |
1542 return &_free_chunks[2]; | |
1543 } | |
1544 } | 1591 } |
1545 | 1592 |
1546 void ChunkManager::free_chunks_put(Metachunk* chunk) { | 1593 void ChunkManager::free_chunks_put(Metachunk* chunk) { |
1547 assert_lock_strong(SpaceManager::expand_lock()); | 1594 assert_lock_strong(SpaceManager::expand_lock()); |
1548 ChunkList* free_list = find_free_chunks_list(chunk->word_size()); | 1595 ChunkList* free_list = find_free_chunks_list(chunk->word_size()); |
1572 assert_lock_strong(SpaceManager::expand_lock()); | 1619 assert_lock_strong(SpaceManager::expand_lock()); |
1573 | 1620 |
1574 slow_locked_verify(); | 1621 slow_locked_verify(); |
1575 | 1622 |
1576 Metachunk* chunk = NULL; | 1623 Metachunk* chunk = NULL; |
1577 if (!SpaceManager::is_humongous(word_size)) { | 1624 if (list_index(word_size) != HumongousIndex) { |
1578 ChunkList* free_list = find_free_chunks_list(word_size); | 1625 ChunkList* free_list = find_free_chunks_list(word_size); |
1579 assert(free_list != NULL, "Sanity check"); | 1626 assert(free_list != NULL, "Sanity check"); |
1580 | 1627 |
1581 chunk = free_list->head(); | 1628 chunk = free_list->head(); |
1582 debug_only(Metachunk* debug_head = chunk;) | 1629 debug_only(Metachunk* debug_head = chunk;) |
1585 return NULL; | 1632 return NULL; |
1586 } | 1633 } |
1587 | 1634 |
1588 // Remove the chunk as the head of the list. | 1635 // Remove the chunk as the head of the list. |
1589 free_list->set_head(chunk->next()); | 1636 free_list->set_head(chunk->next()); |
1590 chunk->set_next(NULL); | 1637 |
1591 // Chunk has been removed from the chunks free list. | 1638 // Chunk is being removed from the chunks free list. |
1592 dec_free_chunks_total(chunk->capacity_word_size()); | 1639 dec_free_chunks_total(chunk->capacity_word_size()); |
1593 | 1640 |
1594 if (TraceMetadataChunkAllocation && Verbose) { | 1641 if (TraceMetadataChunkAllocation && Verbose) { |
1595 tty->print_cr("ChunkManager::free_chunks_get: free_list " | 1642 tty->print_cr("ChunkManager::free_chunks_get: free_list " |
1596 PTR_FORMAT " head " PTR_FORMAT " size " SIZE_FORMAT, | 1643 PTR_FORMAT " head " PTR_FORMAT " size " SIZE_FORMAT, |
1612 // Chunk is being removed from the chunks free list. | 1659 // Chunk is being removed from the chunks free list. |
1613 dec_free_chunks_total(chunk->capacity_word_size()); | 1660 dec_free_chunks_total(chunk->capacity_word_size()); |
1614 #ifdef ASSERT | 1661 #ifdef ASSERT |
1615 chunk->set_is_free(false); | 1662 chunk->set_is_free(false); |
1616 #endif | 1663 #endif |
1617 } | 1664 } else { |
1618 } | 1665 return NULL; |
1666 } | |
1667 } | |
1668 | |
1669 // Remove it from the links to this freelist | |
1670 chunk->set_next(NULL); | |
1671 chunk->set_prev(NULL); | |
1619 slow_locked_verify(); | 1672 slow_locked_verify(); |
1620 return chunk; | 1673 return chunk; |
1621 } | 1674 } |
1622 | 1675 |
1623 Metachunk* ChunkManager::chunk_freelist_allocate(size_t word_size) { | 1676 Metachunk* ChunkManager::chunk_freelist_allocate(size_t word_size) { |
1628 Metachunk* chunk = free_chunks_get(word_size); | 1681 Metachunk* chunk = free_chunks_get(word_size); |
1629 if (chunk == NULL) { | 1682 if (chunk == NULL) { |
1630 return NULL; | 1683 return NULL; |
1631 } | 1684 } |
1632 | 1685 |
1633 assert(word_size <= chunk->word_size() || | 1686 assert((word_size <= chunk->word_size()) || |
1634 SpaceManager::is_humongous(chunk->word_size()), | 1687 list_index(chunk->word_size() == HumongousIndex), |
1635 "Non-humongous variable sized chunk"); | 1688 "Non-humongous variable sized chunk"); |
1636 if (TraceMetadataChunkAllocation) { | 1689 if (TraceMetadataChunkAllocation) { |
1637 tty->print("ChunkManager::chunk_freelist_allocate: chunk " | 1690 size_t list_count; |
1638 PTR_FORMAT " size " SIZE_FORMAT " ", | 1691 if (list_index(word_size) < HumongousIndex) { |
1639 chunk, chunk->word_size()); | 1692 ChunkList* list = find_free_chunks_list(word_size); |
1693 list_count = list->sum_list_count(); | |
1694 } else { | |
1695 list_count = humongous_dictionary()->total_count(); | |
1696 } | |
1697 tty->print("ChunkManager::chunk_freelist_allocate: " PTR_FORMAT " chunk " | |
1698 PTR_FORMAT " size " SIZE_FORMAT " count " SIZE_FORMAT " ", | |
1699 this, chunk, chunk->word_size(), list_count); | |
1640 locked_print_free_chunks(tty); | 1700 locked_print_free_chunks(tty); |
1641 } | 1701 } |
1642 | 1702 |
1643 return chunk; | 1703 return chunk; |
1644 } | 1704 } |
1649 } | 1709 } |
1650 } | 1710 } |
1651 | 1711 |
1652 // SpaceManager methods | 1712 // SpaceManager methods |
1653 | 1713 |
1714 void SpaceManager::get_initial_chunk_sizes(Metaspace::MetaspaceType type, | |
1715 size_t* chunk_word_size, | |
1716 size_t* class_chunk_word_size) { | |
1717 switch (type) { | |
1718 case Metaspace::BootMetaspaceType: | |
1719 *chunk_word_size = Metaspace::first_chunk_word_size(); | |
1720 *class_chunk_word_size = Metaspace::first_class_chunk_word_size(); | |
1721 break; | |
1722 case Metaspace::ROMetaspaceType: | |
1723 *chunk_word_size = SharedReadOnlySize / wordSize; | |
1724 *class_chunk_word_size = ClassSpecializedChunk; | |
1725 break; | |
1726 case Metaspace::ReadWriteMetaspaceType: | |
1727 *chunk_word_size = SharedReadWriteSize / wordSize; | |
1728 *class_chunk_word_size = ClassSpecializedChunk; | |
1729 break; | |
1730 case Metaspace::AnonymousMetaspaceType: | |
1731 case Metaspace::ReflectionMetaspaceType: | |
1732 *chunk_word_size = SpecializedChunk; | |
1733 *class_chunk_word_size = ClassSpecializedChunk; | |
1734 break; | |
1735 default: | |
1736 *chunk_word_size = SmallChunk; | |
1737 *class_chunk_word_size = ClassSmallChunk; | |
1738 break; | |
1739 } | |
1740 assert(chunk_word_size != 0 && class_chunk_word_size != 0, | |
1741 err_msg("Initial chunks sizes bad: data " SIZE_FORMAT | |
1742 " class " SIZE_FORMAT, | |
1743 chunk_word_size, class_chunk_word_size)); | |
1744 } | |
1745 | |
1654 size_t SpaceManager::sum_free_in_chunks_in_use() const { | 1746 size_t SpaceManager::sum_free_in_chunks_in_use() const { |
1655 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); | 1747 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); |
1656 size_t free = 0; | 1748 size_t free = 0; |
1657 for (ChunkIndex i = SmallIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { | 1749 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { |
1658 Metachunk* chunk = chunks_in_use(i); | 1750 Metachunk* chunk = chunks_in_use(i); |
1659 while (chunk != NULL) { | 1751 while (chunk != NULL) { |
1660 free += chunk->free_word_size(); | 1752 free += chunk->free_word_size(); |
1661 chunk = chunk->next(); | 1753 chunk = chunk->next(); |
1662 } | 1754 } |
1665 } | 1757 } |
1666 | 1758 |
1667 size_t SpaceManager::sum_waste_in_chunks_in_use() const { | 1759 size_t SpaceManager::sum_waste_in_chunks_in_use() const { |
1668 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); | 1760 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); |
1669 size_t result = 0; | 1761 size_t result = 0; |
1670 for (ChunkIndex i = SmallIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { | 1762 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { |
1671 | |
1672 | |
1673 result += sum_waste_in_chunks_in_use(i); | 1763 result += sum_waste_in_chunks_in_use(i); |
1674 } | 1764 } |
1675 | 1765 |
1676 return result; | 1766 return result; |
1677 } | 1767 } |
1678 | 1768 |
1679 size_t SpaceManager::sum_waste_in_chunks_in_use(ChunkIndex index) const { | 1769 size_t SpaceManager::sum_waste_in_chunks_in_use(ChunkIndex index) const { |
1680 size_t result = 0; | 1770 size_t result = 0; |
1681 size_t count = 0; | |
1682 Metachunk* chunk = chunks_in_use(index); | 1771 Metachunk* chunk = chunks_in_use(index); |
1683 // Count the free space in all the chunk but not the | 1772 // Count the free space in all the chunk but not the |
1684 // current chunk from which allocations are still being done. | 1773 // current chunk from which allocations are still being done. |
1685 if (chunk != NULL) { | 1774 if (chunk != NULL) { |
1686 Metachunk* prev = chunk; | 1775 Metachunk* prev = chunk; |
1687 while (chunk != NULL && chunk != current_chunk()) { | 1776 while (chunk != NULL && chunk != current_chunk()) { |
1688 result += chunk->free_word_size(); | 1777 result += chunk->free_word_size(); |
1689 prev = chunk; | 1778 prev = chunk; |
1690 chunk = chunk->next(); | 1779 chunk = chunk->next(); |
1691 count++; | |
1692 } | 1780 } |
1693 } | 1781 } |
1694 return result; | 1782 return result; |
1695 } | 1783 } |
1696 | 1784 |
1697 size_t SpaceManager::sum_capacity_in_chunks_in_use() const { | 1785 size_t SpaceManager::sum_capacity_in_chunks_in_use() const { |
1698 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); | 1786 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); |
1699 size_t sum = 0; | 1787 size_t sum = 0; |
1700 for (ChunkIndex i = SmallIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { | 1788 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { |
1701 Metachunk* chunk = chunks_in_use(i); | 1789 Metachunk* chunk = chunks_in_use(i); |
1702 while (chunk != NULL) { | 1790 while (chunk != NULL) { |
1703 // Just changed this sum += chunk->capacity_word_size(); | 1791 // Just changed this sum += chunk->capacity_word_size(); |
1704 // sum += chunk->word_size() - Metachunk::overhead(); | 1792 // sum += chunk->word_size() - Metachunk::overhead(); |
1705 sum += chunk->capacity_word_size(); | 1793 sum += chunk->capacity_word_size(); |
1709 return sum; | 1797 return sum; |
1710 } | 1798 } |
1711 | 1799 |
1712 size_t SpaceManager::sum_count_in_chunks_in_use() { | 1800 size_t SpaceManager::sum_count_in_chunks_in_use() { |
1713 size_t count = 0; | 1801 size_t count = 0; |
1714 for (ChunkIndex i = SmallIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { | 1802 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { |
1715 count = count + sum_count_in_chunks_in_use(i); | 1803 count = count + sum_count_in_chunks_in_use(i); |
1716 } | 1804 } |
1717 | 1805 |
1718 return count; | 1806 return count; |
1719 } | 1807 } |
1730 | 1818 |
1731 | 1819 |
1732 size_t SpaceManager::sum_used_in_chunks_in_use() const { | 1820 size_t SpaceManager::sum_used_in_chunks_in_use() const { |
1733 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); | 1821 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); |
1734 size_t used = 0; | 1822 size_t used = 0; |
1735 for (ChunkIndex i = SmallIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { | 1823 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { |
1736 Metachunk* chunk = chunks_in_use(i); | 1824 Metachunk* chunk = chunks_in_use(i); |
1737 while (chunk != NULL) { | 1825 while (chunk != NULL) { |
1738 used += chunk->used_word_size(); | 1826 used += chunk->used_word_size(); |
1739 chunk = chunk->next(); | 1827 chunk = chunk->next(); |
1740 } | 1828 } |
1742 return used; | 1830 return used; |
1743 } | 1831 } |
1744 | 1832 |
1745 void SpaceManager::locked_print_chunks_in_use_on(outputStream* st) const { | 1833 void SpaceManager::locked_print_chunks_in_use_on(outputStream* st) const { |
1746 | 1834 |
1747 Metachunk* small_chunk = chunks_in_use(SmallIndex); | 1835 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { |
1748 st->print_cr("SpaceManager: small chunk " PTR_FORMAT | 1836 Metachunk* chunk = chunks_in_use(i); |
1749 " free " SIZE_FORMAT, | 1837 st->print("SpaceManager: %s " PTR_FORMAT, |
1750 small_chunk, | 1838 chunk_size_name(i), chunk); |
1751 small_chunk->free_word_size()); | 1839 if (chunk != NULL) { |
1752 | 1840 st->print_cr(" free " SIZE_FORMAT, |
1753 Metachunk* medium_chunk = chunks_in_use(MediumIndex); | 1841 chunk->free_word_size()); |
1754 st->print("medium chunk " PTR_FORMAT, medium_chunk); | 1842 } else { |
1755 Metachunk* tail = current_chunk(); | 1843 st->print_cr(""); |
1756 st->print_cr(" current chunk " PTR_FORMAT, tail); | 1844 } |
1757 | 1845 } |
1758 Metachunk* head = chunks_in_use(HumongousIndex); | |
1759 st->print_cr("humongous chunk " PTR_FORMAT, head); | |
1760 | 1846 |
1761 vs_list()->chunk_manager()->locked_print_free_chunks(st); | 1847 vs_list()->chunk_manager()->locked_print_free_chunks(st); |
1762 vs_list()->chunk_manager()->locked_print_sum_free_chunks(st); | 1848 vs_list()->chunk_manager()->locked_print_sum_free_chunks(st); |
1763 } | 1849 } |
1764 | 1850 |
1770 // chunks will be allocated. | 1856 // chunks will be allocated. |
1771 size_t chunk_word_size; | 1857 size_t chunk_word_size; |
1772 if (chunks_in_use(MediumIndex) == NULL && | 1858 if (chunks_in_use(MediumIndex) == NULL && |
1773 (!has_small_chunk_limit() || | 1859 (!has_small_chunk_limit() || |
1774 sum_count_in_chunks_in_use(SmallIndex) < _small_chunk_limit)) { | 1860 sum_count_in_chunks_in_use(SmallIndex) < _small_chunk_limit)) { |
1775 chunk_word_size = (size_t) SpaceManager::SmallChunk; | 1861 chunk_word_size = (size_t) small_chunk_size(); |
1776 if (word_size + Metachunk::overhead() > SpaceManager::SmallChunk) { | 1862 if (word_size + Metachunk::overhead() > small_chunk_size()) { |
1777 chunk_word_size = MediumChunk; | 1863 chunk_word_size = medium_chunk_size(); |
1778 } | 1864 } |
1779 } else { | 1865 } else { |
1780 chunk_word_size = MediumChunk; | 1866 chunk_word_size = medium_chunk_size(); |
1781 } | 1867 } |
1782 | 1868 |
1783 // Might still need a humongous chunk | 1869 // Might still need a humongous chunk. Enforce an |
1870 // eight word granularity to facilitate reuse (some | |
1871 // wastage but better chance of reuse). | |
1872 size_t if_humongous_sized_chunk = | |
1873 align_size_up(word_size + Metachunk::overhead(), | |
1874 HumongousChunkGranularity); | |
1784 chunk_word_size = | 1875 chunk_word_size = |
1785 MAX2((size_t) chunk_word_size, word_size + Metachunk::overhead()); | 1876 MAX2((size_t) chunk_word_size, if_humongous_sized_chunk); |
1786 | 1877 |
1878 assert(!SpaceManager::is_humongous(word_size) || | |
1879 chunk_word_size == if_humongous_sized_chunk, | |
1880 err_msg("Size calculation is wrong, word_size " SIZE_FORMAT | |
1881 " chunk_word_size " SIZE_FORMAT, | |
1882 word_size, chunk_word_size)); | |
1787 if (TraceMetadataHumongousAllocation && | 1883 if (TraceMetadataHumongousAllocation && |
1788 SpaceManager::is_humongous(word_size)) { | 1884 SpaceManager::is_humongous(word_size)) { |
1789 gclog_or_tty->print_cr("Metadata humongous allocation:"); | 1885 gclog_or_tty->print_cr("Metadata humongous allocation:"); |
1790 gclog_or_tty->print_cr(" word_size " PTR_FORMAT, word_size); | 1886 gclog_or_tty->print_cr(" word_size " PTR_FORMAT, word_size); |
1791 gclog_or_tty->print_cr(" chunk_word_size " PTR_FORMAT, | 1887 gclog_or_tty->print_cr(" chunk_word_size " PTR_FORMAT, |
1803 current_chunk()->allocate(word_size) == NULL, | 1899 current_chunk()->allocate(word_size) == NULL, |
1804 "Don't need to expand"); | 1900 "Don't need to expand"); |
1805 MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag); | 1901 MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag); |
1806 | 1902 |
1807 if (TraceMetadataChunkAllocation && Verbose) { | 1903 if (TraceMetadataChunkAllocation && Verbose) { |
1904 size_t words_left = 0; | |
1905 size_t words_used = 0; | |
1906 if (current_chunk() != NULL) { | |
1907 words_left = current_chunk()->free_word_size(); | |
1908 words_used = current_chunk()->used_word_size(); | |
1909 } | |
1808 gclog_or_tty->print_cr("SpaceManager::grow_and_allocate for " SIZE_FORMAT | 1910 gclog_or_tty->print_cr("SpaceManager::grow_and_allocate for " SIZE_FORMAT |
1809 " words " SIZE_FORMAT " space left", | 1911 " words " SIZE_FORMAT " words used " SIZE_FORMAT |
1810 word_size, current_chunk() != NULL ? | 1912 " words left", |
1811 current_chunk()->free_word_size() : 0); | 1913 word_size, words_used, words_left); |
1812 } | 1914 } |
1813 | 1915 |
1814 // Get another chunk out of the virtual space | 1916 // Get another chunk out of the virtual space |
1815 size_t grow_chunks_by_words = calc_chunk_size(word_size); | 1917 size_t grow_chunks_by_words = calc_chunk_size(word_size); |
1816 Metachunk* next = vs_list()->get_new_chunk(word_size, grow_chunks_by_words); | 1918 Metachunk* next = get_new_chunk(word_size, grow_chunks_by_words); |
1817 | 1919 |
1818 // If a chunk was available, add it to the in-use chunk list | 1920 // If a chunk was available, add it to the in-use chunk list |
1819 // and do an allocation from it. | 1921 // and do an allocation from it. |
1820 if (next != NULL) { | 1922 if (next != NULL) { |
1821 Metadebug::deallocate_chunk_a_lot(this, grow_chunks_by_words); | 1923 Metadebug::deallocate_chunk_a_lot(this, grow_chunks_by_words); |
1826 return NULL; | 1928 return NULL; |
1827 } | 1929 } |
1828 | 1930 |
1829 void SpaceManager::print_on(outputStream* st) const { | 1931 void SpaceManager::print_on(outputStream* st) const { |
1830 | 1932 |
1831 for (ChunkIndex i = SmallIndex; | 1933 for (ChunkIndex i = ZeroIndex; |
1832 i < NumberOfInUseLists ; | 1934 i < NumberOfInUseLists ; |
1833 i = next_chunk_index(i) ) { | 1935 i = next_chunk_index(i) ) { |
1834 st->print_cr(" chunks_in_use " PTR_FORMAT " chunk size " PTR_FORMAT, | 1936 st->print_cr(" chunks_in_use " PTR_FORMAT " chunk size " PTR_FORMAT, |
1835 chunks_in_use(i), | 1937 chunks_in_use(i), |
1836 chunks_in_use(i) == NULL ? 0 : chunks_in_use(i)->word_size()); | 1938 chunks_in_use(i) == NULL ? 0 : chunks_in_use(i)->word_size()); |
1845 st->print_cr("total in block free lists " SIZE_FORMAT, | 1947 st->print_cr("total in block free lists " SIZE_FORMAT, |
1846 block_freelists()->total_size()); | 1948 block_freelists()->total_size()); |
1847 } | 1949 } |
1848 } | 1950 } |
1849 | 1951 |
1850 SpaceManager::SpaceManager(Mutex* lock, VirtualSpaceList* vs_list) : | 1952 SpaceManager::SpaceManager(Mutex* lock, |
1953 VirtualSpaceList* vs_list) : | |
1851 _vs_list(vs_list), | 1954 _vs_list(vs_list), |
1852 _allocation_total(0), | 1955 _allocation_total(0), |
1853 _lock(lock) { | 1956 _lock(lock) |
1957 { | |
1958 initialize(); | |
1959 } | |
1960 | |
1961 void SpaceManager::initialize() { | |
1854 Metadebug::init_allocation_fail_alot_count(); | 1962 Metadebug::init_allocation_fail_alot_count(); |
1855 for (ChunkIndex i = SmallIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { | 1963 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { |
1856 _chunks_in_use[i] = NULL; | 1964 _chunks_in_use[i] = NULL; |
1857 } | 1965 } |
1858 _current_chunk = NULL; | 1966 _current_chunk = NULL; |
1859 if (TraceMetadataChunkAllocation && Verbose) { | 1967 if (TraceMetadataChunkAllocation && Verbose) { |
1860 gclog_or_tty->print_cr("SpaceManager(): " PTR_FORMAT, this); | 1968 gclog_or_tty->print_cr("SpaceManager(): " PTR_FORMAT, this); |
1883 sum_count_in_chunks_in_use()); | 1991 sum_count_in_chunks_in_use()); |
1884 | 1992 |
1885 // Add all the chunks in use by this space manager | 1993 // Add all the chunks in use by this space manager |
1886 // to the global list of free chunks. | 1994 // to the global list of free chunks. |
1887 | 1995 |
1888 // Small chunks. There is one _current_chunk for each | 1996 // Follow each list of chunks-in-use and add them to the |
1889 // Metaspace. It could point to a small or medium chunk. | 1997 // free lists. Each list is NULL terminated. |
1890 // Rather than determine which it is, follow the list of | 1998 |
1891 // small chunks to add them to the free list | 1999 for (ChunkIndex i = ZeroIndex; i < HumongousIndex; i = next_chunk_index(i)) { |
1892 Metachunk* small_chunk = chunks_in_use(SmallIndex); | 2000 if (TraceMetadataChunkAllocation && Verbose) { |
1893 chunk_manager->free_small_chunks()->add_at_head(small_chunk); | 2001 gclog_or_tty->print_cr("returned %d %s chunks to freelist", |
1894 set_chunks_in_use(SmallIndex, NULL); | 2002 sum_count_in_chunks_in_use(i), |
1895 | 2003 chunk_size_name(i)); |
1896 // After the small chunk are the medium chunks | 2004 } |
1897 Metachunk* medium_chunk = chunks_in_use(MediumIndex); | 2005 Metachunk* chunks = chunks_in_use(i); |
1898 assert(medium_chunk == NULL || | 2006 chunk_manager->free_chunks(i)->add_at_head(chunks); |
1899 medium_chunk->word_size() == MediumChunk, | 2007 set_chunks_in_use(i, NULL); |
1900 "Chunk is on the wrong list"); | 2008 if (TraceMetadataChunkAllocation && Verbose) { |
1901 | 2009 gclog_or_tty->print_cr("updated freelist count %d %s", |
1902 if (medium_chunk != NULL) { | 2010 chunk_manager->free_chunks(i)->sum_list_count(), |
1903 Metachunk* head = medium_chunk; | 2011 chunk_size_name(i)); |
1904 // If there is a medium chunk then the _current_chunk can only | 2012 } |
1905 // point to the last medium chunk. | 2013 assert(i != HumongousIndex, "Humongous chunks are handled explicitly later"); |
1906 Metachunk* tail = current_chunk(); | 2014 } |
1907 chunk_manager->free_medium_chunks()->add_at_head(head, tail); | 2015 |
1908 set_chunks_in_use(MediumIndex, NULL); | 2016 // The medium chunk case may be optimized by passing the head and |
1909 } | 2017 // tail of the medium chunk list to add_at_head(). The tail is often |
2018 // the current chunk but there are probably exceptions. | |
1910 | 2019 |
1911 // Humongous chunks | 2020 // Humongous chunks |
2021 if (TraceMetadataChunkAllocation && Verbose) { | |
2022 gclog_or_tty->print_cr("returned %d %s humongous chunks to dictionary", | |
2023 sum_count_in_chunks_in_use(HumongousIndex), | |
2024 chunk_size_name(HumongousIndex)); | |
2025 gclog_or_tty->print("Humongous chunk dictionary: "); | |
2026 } | |
1912 // Humongous chunks are never the current chunk. | 2027 // Humongous chunks are never the current chunk. |
1913 Metachunk* humongous_chunks = chunks_in_use(HumongousIndex); | 2028 Metachunk* humongous_chunks = chunks_in_use(HumongousIndex); |
1914 | 2029 |
1915 while (humongous_chunks != NULL) { | 2030 while (humongous_chunks != NULL) { |
1916 #ifdef ASSERT | 2031 #ifdef ASSERT |
1917 humongous_chunks->set_is_free(true); | 2032 humongous_chunks->set_is_free(true); |
1918 #endif | 2033 #endif |
2034 if (TraceMetadataChunkAllocation && Verbose) { | |
2035 gclog_or_tty->print(PTR_FORMAT " (" SIZE_FORMAT ") ", | |
2036 humongous_chunks, | |
2037 humongous_chunks->word_size()); | |
2038 } | |
2039 assert(humongous_chunks->word_size() == (size_t) | |
2040 align_size_up(humongous_chunks->word_size(), | |
2041 HumongousChunkGranularity), | |
2042 err_msg("Humongous chunk size is wrong: word size " SIZE_FORMAT | |
2043 " granularity " SIZE_FORMAT, | |
2044 humongous_chunks->word_size(), HumongousChunkGranularity)); | |
1919 Metachunk* next_humongous_chunks = humongous_chunks->next(); | 2045 Metachunk* next_humongous_chunks = humongous_chunks->next(); |
1920 chunk_manager->humongous_dictionary()->return_chunk(humongous_chunks); | 2046 chunk_manager->humongous_dictionary()->return_chunk(humongous_chunks); |
1921 humongous_chunks = next_humongous_chunks; | 2047 humongous_chunks = next_humongous_chunks; |
1922 } | 2048 } |
2049 if (TraceMetadataChunkAllocation && Verbose) { | |
2050 gclog_or_tty->print_cr(""); | |
2051 gclog_or_tty->print_cr("updated dictionary count %d %s", | |
2052 chunk_manager->humongous_dictionary()->total_count(), | |
2053 chunk_size_name(HumongousIndex)); | |
2054 } | |
1923 set_chunks_in_use(HumongousIndex, NULL); | 2055 set_chunks_in_use(HumongousIndex, NULL); |
1924 chunk_manager->slow_locked_verify(); | 2056 chunk_manager->slow_locked_verify(); |
2057 } | |
2058 | |
2059 const char* SpaceManager::chunk_size_name(ChunkIndex index) const { | |
2060 switch (index) { | |
2061 case SpecializedIndex: | |
2062 return "Specialized"; | |
2063 case SmallIndex: | |
2064 return "Small"; | |
2065 case MediumIndex: | |
2066 return "Medium"; | |
2067 case HumongousIndex: | |
2068 return "Humongous"; | |
2069 default: | |
2070 return NULL; | |
2071 } | |
2072 } | |
2073 | |
2074 ChunkIndex ChunkManager::list_index(size_t size) { | |
2075 switch (size) { | |
2076 case SpecializedChunk: | |
2077 assert(SpecializedChunk == ClassSpecializedChunk, | |
2078 "Need branch for ClassSpecializedChunk"); | |
2079 return SpecializedIndex; | |
2080 case SmallChunk: | |
2081 case ClassSmallChunk: | |
2082 return SmallIndex; | |
2083 case MediumChunk: | |
2084 case ClassMediumChunk: | |
2085 return MediumIndex; | |
2086 default: | |
2087 assert(size > MediumChunk && size > ClassMediumChunk, | |
2088 "Not a humongous chunk"); | |
2089 return HumongousIndex; | |
2090 } | |
1925 } | 2091 } |
1926 | 2092 |
1927 void SpaceManager::deallocate(MetaWord* p, size_t word_size) { | 2093 void SpaceManager::deallocate(MetaWord* p, size_t word_size) { |
1928 assert_lock_strong(_lock); | 2094 assert_lock_strong(_lock); |
1929 size_t min_size = TreeChunk<Metablock, FreeList>::min_size(); | 2095 size_t min_size = TreeChunk<Metablock, FreeList>::min_size(); |
1940 | 2106 |
1941 new_chunk->reset_empty(); | 2107 new_chunk->reset_empty(); |
1942 | 2108 |
1943 // Find the correct list and and set the current | 2109 // Find the correct list and and set the current |
1944 // chunk for that list. | 2110 // chunk for that list. |
1945 switch (new_chunk->word_size()) { | 2111 ChunkIndex index = ChunkManager::list_index(new_chunk->word_size()); |
1946 case SpaceManager::SmallChunk : | 2112 |
1947 if (chunks_in_use(SmallIndex) == NULL) { | 2113 if (index != HumongousIndex) { |
1948 // First chunk to add to the list | |
1949 set_chunks_in_use(SmallIndex, new_chunk); | |
1950 } else { | |
1951 assert(current_chunk()->word_size() == SpaceManager::SmallChunk, | |
1952 err_msg( "Incorrect mix of sizes in chunk list " | |
1953 SIZE_FORMAT " new chunk " SIZE_FORMAT, | |
1954 current_chunk()->word_size(), new_chunk->word_size())); | |
1955 current_chunk()->set_next(new_chunk); | |
1956 } | |
1957 // Make current chunk | |
1958 set_current_chunk(new_chunk); | 2114 set_current_chunk(new_chunk); |
1959 break; | 2115 new_chunk->set_next(chunks_in_use(index)); |
1960 case SpaceManager::MediumChunk : | 2116 set_chunks_in_use(index, new_chunk); |
1961 if (chunks_in_use(MediumIndex) == NULL) { | 2117 } else { |
1962 // About to add the first medium chunk so teminate the | |
1963 // small chunk list. In general once medium chunks are | |
1964 // being added, we're past the need for small chunks. | |
1965 if (current_chunk() != NULL) { | |
1966 // Only a small chunk or the initial chunk could be | |
1967 // the current chunk if this is the first medium chunk. | |
1968 assert(current_chunk()->word_size() == SpaceManager::SmallChunk || | |
1969 chunks_in_use(SmallIndex) == NULL, | |
1970 err_msg("Should be a small chunk or initial chunk, current chunk " | |
1971 SIZE_FORMAT " new chunk " SIZE_FORMAT, | |
1972 current_chunk()->word_size(), new_chunk->word_size())); | |
1973 current_chunk()->set_next(NULL); | |
1974 } | |
1975 // First chunk to add to the list | |
1976 set_chunks_in_use(MediumIndex, new_chunk); | |
1977 | |
1978 } else { | |
1979 // As a minimum the first medium chunk added would | |
1980 // have become the _current_chunk | |
1981 // so the _current_chunk has to be non-NULL here | |
1982 // (although not necessarily still the first medium chunk). | |
1983 assert(current_chunk()->word_size() == SpaceManager::MediumChunk, | |
1984 "A medium chunk should the current chunk"); | |
1985 current_chunk()->set_next(new_chunk); | |
1986 } | |
1987 // Make current chunk | |
1988 set_current_chunk(new_chunk); | |
1989 break; | |
1990 default: { | |
1991 // For null class loader data and DumpSharedSpaces, the first chunk isn't | 2118 // For null class loader data and DumpSharedSpaces, the first chunk isn't |
1992 // small, so small will be null. Link this first chunk as the current | 2119 // small, so small will be null. Link this first chunk as the current |
1993 // chunk. | 2120 // chunk. |
1994 if (make_current) { | 2121 if (make_current) { |
1995 // Set as the current chunk but otherwise treat as a humongous chunk. | 2122 // Set as the current chunk but otherwise treat as a humongous chunk. |
2002 new_chunk->set_next(chunks_in_use(HumongousIndex)); | 2129 new_chunk->set_next(chunks_in_use(HumongousIndex)); |
2003 set_chunks_in_use(HumongousIndex, new_chunk); | 2130 set_chunks_in_use(HumongousIndex, new_chunk); |
2004 | 2131 |
2005 assert(new_chunk->word_size() > MediumChunk, "List inconsistency"); | 2132 assert(new_chunk->word_size() > MediumChunk, "List inconsistency"); |
2006 } | 2133 } |
2007 } | |
2008 | 2134 |
2009 assert(new_chunk->is_empty(), "Not ready for reuse"); | 2135 assert(new_chunk->is_empty(), "Not ready for reuse"); |
2010 if (TraceMetadataChunkAllocation && Verbose) { | 2136 if (TraceMetadataChunkAllocation && Verbose) { |
2011 gclog_or_tty->print("SpaceManager::add_chunk: %d) ", | 2137 gclog_or_tty->print("SpaceManager::add_chunk: %d) ", |
2012 sum_count_in_chunks_in_use()); | 2138 sum_count_in_chunks_in_use()); |
2013 new_chunk->print_on(gclog_or_tty); | 2139 new_chunk->print_on(gclog_or_tty); |
2014 vs_list()->chunk_manager()->locked_print_free_chunks(tty); | 2140 vs_list()->chunk_manager()->locked_print_free_chunks(tty); |
2015 } | 2141 } |
2142 } | |
2143 | |
2144 Metachunk* SpaceManager::get_new_chunk(size_t word_size, | |
2145 size_t grow_chunks_by_words) { | |
2146 | |
2147 Metachunk* next = vs_list()->get_new_chunk(word_size, | |
2148 grow_chunks_by_words, | |
2149 medium_chunk_bunch()); | |
2150 | |
2151 if (TraceMetadataHumongousAllocation && | |
2152 SpaceManager::is_humongous(next->word_size())) { | |
2153 gclog_or_tty->print_cr(" new humongous chunk word size " PTR_FORMAT, | |
2154 next->word_size()); | |
2155 } | |
2156 | |
2157 return next; | |
2016 } | 2158 } |
2017 | 2159 |
2018 MetaWord* SpaceManager::allocate(size_t word_size) { | 2160 MetaWord* SpaceManager::allocate(size_t word_size) { |
2019 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); | 2161 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); |
2020 | 2162 |
2088 void SpaceManager::verify() { | 2230 void SpaceManager::verify() { |
2089 // If there are blocks in the dictionary, then | 2231 // If there are blocks in the dictionary, then |
2090 // verfication of chunks does not work since | 2232 // verfication of chunks does not work since |
2091 // being in the dictionary alters a chunk. | 2233 // being in the dictionary alters a chunk. |
2092 if (block_freelists()->total_size() == 0) { | 2234 if (block_freelists()->total_size() == 0) { |
2093 // Skip the small chunks because their next link points to | 2235 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { |
2094 // medium chunks. This is because the small chunk is the | |
2095 // current chunk (for allocations) until it is full and the | |
2096 // the addition of the next chunk does not NULL the next | |
2097 // like of the small chunk. | |
2098 for (ChunkIndex i = MediumIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { | |
2099 Metachunk* curr = chunks_in_use(i); | 2236 Metachunk* curr = chunks_in_use(i); |
2100 while (curr != NULL) { | 2237 while (curr != NULL) { |
2101 curr->verify(); | 2238 curr->verify(); |
2102 verify_chunk_size(curr); | 2239 verify_chunk_size(curr); |
2103 curr = curr->next(); | 2240 curr = curr->next(); |
2106 } | 2243 } |
2107 } | 2244 } |
2108 | 2245 |
2109 void SpaceManager::verify_chunk_size(Metachunk* chunk) { | 2246 void SpaceManager::verify_chunk_size(Metachunk* chunk) { |
2110 assert(is_humongous(chunk->word_size()) || | 2247 assert(is_humongous(chunk->word_size()) || |
2111 chunk->word_size() == MediumChunk || | 2248 chunk->word_size() == medium_chunk_size() || |
2112 chunk->word_size() == SmallChunk, | 2249 chunk->word_size() == small_chunk_size() || |
2250 chunk->word_size() == specialized_chunk_size(), | |
2113 "Chunk size is wrong"); | 2251 "Chunk size is wrong"); |
2114 return; | 2252 return; |
2115 } | 2253 } |
2116 | 2254 |
2117 #ifdef ASSERT | 2255 #ifdef ASSERT |
2118 void SpaceManager::verify_allocation_total() { | 2256 void SpaceManager::verify_allocation_total() { |
2119 #if 0 | |
2120 // Verification is only guaranteed at a safepoint. | 2257 // Verification is only guaranteed at a safepoint. |
2121 if (SafepointSynchronize::is_at_safepoint()) { | 2258 if (SafepointSynchronize::is_at_safepoint()) { |
2122 gclog_or_tty->print_cr("Chunk " PTR_FORMAT " allocation_total " SIZE_FORMAT | 2259 gclog_or_tty->print_cr("Chunk " PTR_FORMAT " allocation_total " SIZE_FORMAT |
2123 " sum_used_in_chunks_in_use " SIZE_FORMAT, | 2260 " sum_used_in_chunks_in_use " SIZE_FORMAT, |
2124 this, | 2261 this, |
2127 } | 2264 } |
2128 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); | 2265 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); |
2129 assert(allocation_total() == sum_used_in_chunks_in_use(), | 2266 assert(allocation_total() == sum_used_in_chunks_in_use(), |
2130 err_msg("allocation total is not consistent %d vs %d", | 2267 err_msg("allocation total is not consistent %d vs %d", |
2131 allocation_total(), sum_used_in_chunks_in_use())); | 2268 allocation_total(), sum_used_in_chunks_in_use())); |
2132 #endif | |
2133 } | 2269 } |
2134 | 2270 |
2135 #endif | 2271 #endif |
2136 | 2272 |
2137 void SpaceManager::dump(outputStream* const out) const { | 2273 void SpaceManager::dump(outputStream* const out) const { |
2140 uint i = 0; | 2276 uint i = 0; |
2141 size_t used = 0; | 2277 size_t used = 0; |
2142 size_t capacity = 0; | 2278 size_t capacity = 0; |
2143 | 2279 |
2144 // Add up statistics for all chunks in this SpaceManager. | 2280 // Add up statistics for all chunks in this SpaceManager. |
2145 for (ChunkIndex index = SmallIndex; | 2281 for (ChunkIndex index = ZeroIndex; |
2146 index < NumberOfInUseLists; | 2282 index < NumberOfInUseLists; |
2147 index = next_chunk_index(index)) { | 2283 index = next_chunk_index(index)) { |
2148 for (Metachunk* curr = chunks_in_use(index); | 2284 for (Metachunk* curr = chunks_in_use(index); |
2149 curr != NULL; | 2285 curr != NULL; |
2150 curr = curr->next()) { | 2286 curr = curr->next()) { |
2158 capacity += curr->capacity_word_size(); | 2294 capacity += curr->capacity_word_size(); |
2159 waste += curr->free_word_size() + curr->overhead();; | 2295 waste += curr->free_word_size() + curr->overhead();; |
2160 } | 2296 } |
2161 } | 2297 } |
2162 | 2298 |
2163 size_t free = current_chunk()->free_word_size(); | 2299 size_t free = current_chunk() == NULL ? 0 : current_chunk()->free_word_size(); |
2164 // Free space isn't wasted. | 2300 // Free space isn't wasted. |
2165 waste -= free; | 2301 waste -= free; |
2166 | 2302 |
2167 out->print_cr("total of all chunks " SIZE_FORMAT " used " SIZE_FORMAT | 2303 out->print_cr("total of all chunks " SIZE_FORMAT " used " SIZE_FORMAT |
2168 " free " SIZE_FORMAT " capacity " SIZE_FORMAT | 2304 " free " SIZE_FORMAT " capacity " SIZE_FORMAT |
2169 " waste " SIZE_FORMAT, curr_total, used, free, capacity, waste); | 2305 " waste " SIZE_FORMAT, curr_total, used, free, capacity, waste); |
2170 } | 2306 } |
2171 | 2307 |
2172 #ifndef PRODUCT | 2308 #ifndef PRODUCT |
2173 void SpaceManager::mangle_freed_chunks() { | 2309 void SpaceManager::mangle_freed_chunks() { |
2174 for (ChunkIndex index = SmallIndex; | 2310 for (ChunkIndex index = ZeroIndex; |
2175 index < NumberOfInUseLists; | 2311 index < NumberOfInUseLists; |
2176 index = next_chunk_index(index)) { | 2312 index = next_chunk_index(index)) { |
2177 for (Metachunk* curr = chunks_in_use(index); | 2313 for (Metachunk* curr = chunks_in_use(index); |
2178 curr != NULL; | 2314 curr != NULL; |
2179 curr = curr->next()) { | 2315 curr = curr->next()) { |
2180 // Try to detect incorrectly terminated small chunk | |
2181 // list. | |
2182 assert(index == MediumIndex || curr != chunks_in_use(MediumIndex), | |
2183 err_msg("Mangling medium chunks in small chunks? " | |
2184 "curr " PTR_FORMAT " medium list " PTR_FORMAT, | |
2185 curr, chunks_in_use(MediumIndex))); | |
2186 curr->mangle(); | 2316 curr->mangle(); |
2187 } | 2317 } |
2188 } | 2318 } |
2189 } | 2319 } |
2190 #endif // PRODUCT | 2320 #endif // PRODUCT |
2191 | |
2192 | 2321 |
2193 // MetaspaceAux | 2322 // MetaspaceAux |
2194 | 2323 |
2195 size_t MetaspaceAux::used_in_bytes(Metaspace::MetadataType mdtype) { | 2324 size_t MetaspaceAux::used_in_bytes(Metaspace::MetadataType mdtype) { |
2196 size_t used = 0; | 2325 size_t used = 0; |
2234 Metaspace::class_space_list()->virtual_space_total() : | 2363 Metaspace::class_space_list()->virtual_space_total() : |
2235 Metaspace::space_list()->virtual_space_total(); | 2364 Metaspace::space_list()->virtual_space_total(); |
2236 return reserved * BytesPerWord; | 2365 return reserved * BytesPerWord; |
2237 } | 2366 } |
2238 | 2367 |
2239 size_t MetaspaceAux::min_chunk_size() { return SpaceManager::MediumChunk; } | 2368 size_t MetaspaceAux::min_chunk_size() { return Metaspace::first_chunk_word_size(); } |
2240 | 2369 |
2241 size_t MetaspaceAux::free_chunks_total(Metaspace::MetadataType mdtype) { | 2370 size_t MetaspaceAux::free_chunks_total(Metaspace::MetadataType mdtype) { |
2242 ChunkManager* chunk = (mdtype == Metaspace::ClassType) ? | 2371 ChunkManager* chunk = (mdtype == Metaspace::ClassType) ? |
2243 Metaspace::class_space_list()->chunk_manager() : | 2372 Metaspace::class_space_list()->chunk_manager() : |
2244 Metaspace::space_list()->chunk_manager(); | 2373 Metaspace::space_list()->chunk_manager(); |
2314 } | 2443 } |
2315 | 2444 |
2316 // Print total fragmentation for class and data metaspaces separately | 2445 // Print total fragmentation for class and data metaspaces separately |
2317 void MetaspaceAux::print_waste(outputStream* out) { | 2446 void MetaspaceAux::print_waste(outputStream* out) { |
2318 | 2447 |
2319 size_t small_waste = 0, medium_waste = 0, large_waste = 0; | 2448 size_t specialized_waste = 0, small_waste = 0, medium_waste = 0, large_waste = 0; |
2320 size_t cls_small_waste = 0, cls_medium_waste = 0, cls_large_waste = 0; | 2449 size_t specialized_count = 0, small_count = 0, medium_count = 0, large_count = 0; |
2450 size_t cls_specialized_waste = 0, cls_small_waste = 0, cls_medium_waste = 0, cls_large_waste = 0; | |
2451 size_t cls_specialized_count = 0, cls_small_count = 0, cls_medium_count = 0, cls_large_count = 0; | |
2321 | 2452 |
2322 ClassLoaderDataGraphMetaspaceIterator iter; | 2453 ClassLoaderDataGraphMetaspaceIterator iter; |
2323 while (iter.repeat()) { | 2454 while (iter.repeat()) { |
2324 Metaspace* msp = iter.get_next(); | 2455 Metaspace* msp = iter.get_next(); |
2325 if (msp != NULL) { | 2456 if (msp != NULL) { |
2457 specialized_waste += msp->vsm()->sum_waste_in_chunks_in_use(SpecializedIndex); | |
2458 specialized_count += msp->vsm()->sum_count_in_chunks_in_use(SpecializedIndex); | |
2326 small_waste += msp->vsm()->sum_waste_in_chunks_in_use(SmallIndex); | 2459 small_waste += msp->vsm()->sum_waste_in_chunks_in_use(SmallIndex); |
2460 small_count += msp->vsm()->sum_count_in_chunks_in_use(SmallIndex); | |
2327 medium_waste += msp->vsm()->sum_waste_in_chunks_in_use(MediumIndex); | 2461 medium_waste += msp->vsm()->sum_waste_in_chunks_in_use(MediumIndex); |
2462 medium_count += msp->vsm()->sum_count_in_chunks_in_use(MediumIndex); | |
2328 large_waste += msp->vsm()->sum_waste_in_chunks_in_use(HumongousIndex); | 2463 large_waste += msp->vsm()->sum_waste_in_chunks_in_use(HumongousIndex); |
2329 | 2464 large_count += msp->vsm()->sum_count_in_chunks_in_use(HumongousIndex); |
2465 | |
2466 cls_specialized_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(SpecializedIndex); | |
2467 cls_specialized_count += msp->class_vsm()->sum_count_in_chunks_in_use(SpecializedIndex); | |
2330 cls_small_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(SmallIndex); | 2468 cls_small_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(SmallIndex); |
2469 cls_small_count += msp->class_vsm()->sum_count_in_chunks_in_use(SmallIndex); | |
2331 cls_medium_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(MediumIndex); | 2470 cls_medium_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(MediumIndex); |
2471 cls_medium_count += msp->class_vsm()->sum_count_in_chunks_in_use(MediumIndex); | |
2332 cls_large_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(HumongousIndex); | 2472 cls_large_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(HumongousIndex); |
2473 cls_large_count += msp->class_vsm()->sum_count_in_chunks_in_use(HumongousIndex); | |
2333 } | 2474 } |
2334 } | 2475 } |
2335 out->print_cr("Total fragmentation waste (words) doesn't count free space"); | 2476 out->print_cr("Total fragmentation waste (words) doesn't count free space"); |
2336 out->print(" data: small " SIZE_FORMAT " medium " SIZE_FORMAT, | 2477 out->print_cr(" data: " SIZE_FORMAT " specialized(s) " SIZE_FORMAT ", " |
2337 small_waste, medium_waste); | 2478 SIZE_FORMAT " small(s) " SIZE_FORMAT ", " |
2338 out->print_cr(" class: small " SIZE_FORMAT, cls_small_waste); | 2479 SIZE_FORMAT " medium(s) " SIZE_FORMAT, |
2480 specialized_count, specialized_waste, small_count, | |
2481 small_waste, medium_count, medium_waste); | |
2482 out->print_cr(" class: " SIZE_FORMAT " specialized(s) " SIZE_FORMAT ", " | |
2483 SIZE_FORMAT " small(s) " SIZE_FORMAT, | |
2484 cls_specialized_count, cls_specialized_waste, | |
2485 cls_small_count, cls_small_waste); | |
2339 } | 2486 } |
2340 | 2487 |
2341 // Dump global metaspace things from the end of ClassLoaderDataGraph | 2488 // Dump global metaspace things from the end of ClassLoaderDataGraph |
2342 void MetaspaceAux::dump(outputStream* out) { | 2489 void MetaspaceAux::dump(outputStream* out) { |
2343 out->print_cr("All Metaspace:"); | 2490 out->print_cr("All Metaspace:"); |
2352 } | 2499 } |
2353 | 2500 |
2354 // Metaspace methods | 2501 // Metaspace methods |
2355 | 2502 |
2356 size_t Metaspace::_first_chunk_word_size = 0; | 2503 size_t Metaspace::_first_chunk_word_size = 0; |
2357 | 2504 size_t Metaspace::_first_class_chunk_word_size = 0; |
2358 Metaspace::Metaspace(Mutex* lock, size_t word_size) { | 2505 |
2359 initialize(lock, word_size); | 2506 Metaspace::Metaspace(Mutex* lock, MetaspaceType type) { |
2360 } | 2507 initialize(lock, type); |
2361 | |
2362 Metaspace::Metaspace(Mutex* lock) { | |
2363 initialize(lock); | |
2364 } | 2508 } |
2365 | 2509 |
2366 Metaspace::~Metaspace() { | 2510 Metaspace::~Metaspace() { |
2367 delete _vsm; | 2511 delete _vsm; |
2368 delete _class_vsm; | 2512 delete _class_vsm; |
2410 assert(!mapinfo->is_open() && !UseSharedSpaces, | 2554 assert(!mapinfo->is_open() && !UseSharedSpaces, |
2411 "archive file not closed or shared spaces not disabled."); | 2555 "archive file not closed or shared spaces not disabled."); |
2412 } | 2556 } |
2413 } | 2557 } |
2414 | 2558 |
2415 // Initialize this before initializing the VirtualSpaceList | 2559 // Initialize these before initializing the VirtualSpaceList |
2416 _first_chunk_word_size = InitialBootClassLoaderMetaspaceSize / BytesPerWord; | 2560 _first_chunk_word_size = InitialBootClassLoaderMetaspaceSize / BytesPerWord; |
2561 _first_chunk_word_size = align_word_size_up(_first_chunk_word_size); | |
2562 // Make the first class chunk bigger than a medium chunk so it's not put | |
2563 // on the medium chunk list. The next chunk will be small and progress | |
2564 // from there. This size calculated by -version. | |
2565 _first_class_chunk_word_size = MIN2((size_t)MediumChunk*6, | |
2566 (ClassMetaspaceSize/BytesPerWord)*2); | |
2567 _first_class_chunk_word_size = align_word_size_up(_first_class_chunk_word_size); | |
2417 // Arbitrarily set the initial virtual space to a multiple | 2568 // Arbitrarily set the initial virtual space to a multiple |
2418 // of the boot class loader size. | 2569 // of the boot class loader size. |
2419 size_t word_size = VIRTUALSPACEMULTIPLIER * Metaspace::first_chunk_word_size(); | 2570 size_t word_size = VIRTUALSPACEMULTIPLIER * first_chunk_word_size(); |
2420 // Initialize the list of virtual spaces. | 2571 // Initialize the list of virtual spaces. |
2421 _space_list = new VirtualSpaceList(word_size); | 2572 _space_list = new VirtualSpaceList(word_size); |
2422 } | 2573 } |
2423 } | 2574 } |
2424 | 2575 |
2429 // The reserved space size may be bigger because of alignment, esp with UseLargePages | 2580 // The reserved space size may be bigger because of alignment, esp with UseLargePages |
2430 assert(rs.size() >= ClassMetaspaceSize, err_msg("%d != %d", rs.size(), ClassMetaspaceSize)); | 2581 assert(rs.size() >= ClassMetaspaceSize, err_msg("%d != %d", rs.size(), ClassMetaspaceSize)); |
2431 _class_space_list = new VirtualSpaceList(rs); | 2582 _class_space_list = new VirtualSpaceList(rs); |
2432 } | 2583 } |
2433 | 2584 |
2434 | 2585 void Metaspace::initialize(Mutex* lock, |
2435 void Metaspace::initialize(Mutex* lock, size_t initial_size) { | 2586 MetaspaceType type) { |
2436 // Use SmallChunk size if not specified. If specified, use this size for | |
2437 // the data metaspace. | |
2438 size_t word_size; | |
2439 size_t class_word_size; | |
2440 if (initial_size == 0) { | |
2441 word_size = (size_t) SpaceManager::SmallChunk; | |
2442 class_word_size = (size_t) SpaceManager::SmallChunk; | |
2443 } else { | |
2444 word_size = initial_size; | |
2445 // Make the first class chunk bigger than a medium chunk so it's not put | |
2446 // on the medium chunk list. The next chunk will be small and progress | |
2447 // from there. This size calculated by -version. | |
2448 class_word_size = MIN2((size_t)SpaceManager::MediumChunk*5, | |
2449 (ClassMetaspaceSize/BytesPerWord)*2); | |
2450 } | |
2451 | 2587 |
2452 assert(space_list() != NULL, | 2588 assert(space_list() != NULL, |
2453 "Metadata VirtualSpaceList has not been initialized"); | 2589 "Metadata VirtualSpaceList has not been initialized"); |
2454 | 2590 |
2455 _vsm = new SpaceManager(lock, space_list()); | 2591 _vsm = new SpaceManager(lock, space_list()); |
2456 if (_vsm == NULL) { | 2592 if (_vsm == NULL) { |
2457 return; | 2593 return; |
2458 } | 2594 } |
2595 size_t word_size; | |
2596 size_t class_word_size; | |
2597 vsm()->get_initial_chunk_sizes(type, | |
2598 &word_size, | |
2599 &class_word_size); | |
2459 | 2600 |
2460 assert(class_space_list() != NULL, | 2601 assert(class_space_list() != NULL, |
2461 "Class VirtualSpaceList has not been initialized"); | 2602 "Class VirtualSpaceList has not been initialized"); |
2462 | 2603 |
2463 // Allocate SpaceManager for classes. | 2604 // Allocate SpaceManager for classes. |
2468 | 2609 |
2469 MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag); | 2610 MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag); |
2470 | 2611 |
2471 // Allocate chunk for metadata objects | 2612 // Allocate chunk for metadata objects |
2472 Metachunk* new_chunk = | 2613 Metachunk* new_chunk = |
2473 space_list()->current_virtual_space()->get_chunk_vs_with_expand(word_size); | 2614 space_list()->get_initialization_chunk(word_size, |
2615 vsm()->medium_chunk_bunch()); | |
2474 assert(!DumpSharedSpaces || new_chunk != NULL, "should have enough space for both chunks"); | 2616 assert(!DumpSharedSpaces || new_chunk != NULL, "should have enough space for both chunks"); |
2475 if (new_chunk != NULL) { | 2617 if (new_chunk != NULL) { |
2476 // Add to this manager's list of chunks in use and current_chunk(). | 2618 // Add to this manager's list of chunks in use and current_chunk(). |
2477 vsm()->add_chunk(new_chunk, true); | 2619 vsm()->add_chunk(new_chunk, true); |
2478 } | 2620 } |
2479 | 2621 |
2480 // Allocate chunk for class metadata objects | 2622 // Allocate chunk for class metadata objects |
2481 Metachunk* class_chunk = | 2623 Metachunk* class_chunk = |
2482 class_space_list()->current_virtual_space()->get_chunk_vs_with_expand(class_word_size); | 2624 class_space_list()->get_initialization_chunk(class_word_size, |
2625 class_vsm()->medium_chunk_bunch()); | |
2483 if (class_chunk != NULL) { | 2626 if (class_chunk != NULL) { |
2484 class_vsm()->add_chunk(class_chunk, true); | 2627 class_vsm()->add_chunk(class_chunk, true); |
2485 } | 2628 } |
2629 } | |
2630 | |
2631 size_t Metaspace::align_word_size_up(size_t word_size) { | |
2632 size_t byte_size = word_size * wordSize; | |
2633 return ReservedSpace::allocation_align_size_up(byte_size) / wordSize; | |
2486 } | 2634 } |
2487 | 2635 |
2488 MetaWord* Metaspace::allocate(size_t word_size, MetadataType mdtype) { | 2636 MetaWord* Metaspace::allocate(size_t word_size, MetadataType mdtype) { |
2489 // DumpSharedSpaces doesn't use class metadata area (yet) | 2637 // DumpSharedSpaces doesn't use class metadata area (yet) |
2490 if (mdtype == ClassType && !DumpSharedSpaces) { | 2638 if (mdtype == ClassType && !DumpSharedSpaces) { |
2608 Universe::heap()->collector_policy()->satisfy_failed_metadata_allocation( | 2756 Universe::heap()->collector_policy()->satisfy_failed_metadata_allocation( |
2609 loader_data, word_size, mdtype); | 2757 loader_data, word_size, mdtype); |
2610 | 2758 |
2611 // If result is still null, we are out of memory. | 2759 // If result is still null, we are out of memory. |
2612 if (result == NULL) { | 2760 if (result == NULL) { |
2761 if (Verbose && TraceMetadataChunkAllocation) { | |
2762 gclog_or_tty->print_cr("Metaspace allocation failed for size " | |
2763 SIZE_FORMAT, word_size); | |
2764 if (loader_data->metaspace_or_null() != NULL) loader_data->metaspace_or_null()->dump(gclog_or_tty); | |
2765 MetaspaceAux::dump(gclog_or_tty); | |
2766 } | |
2613 // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support | 2767 // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support |
2614 report_java_out_of_memory("Metadata space"); | 2768 report_java_out_of_memory("Metadata space"); |
2615 | 2769 |
2616 if (JvmtiExport::should_post_resource_exhausted()) { | 2770 if (JvmtiExport::should_post_resource_exhausted()) { |
2617 JvmtiExport::post_resource_exhausted( | 2771 JvmtiExport::post_resource_exhausted( |