comparison src/share/vm/memory/metaspace.cpp @ 10101:df254344edf1

8011173: NPG: Replace the ChunkList implementation with class FreeList<Metachunk> Reviewed-by: mgerdin, tschatzl, johnc, coleenp
author jmasa
date Mon, 01 Apr 2013 10:50:30 -0700
parents 6574f999e0cf
children c23dbf0e8ab7
comparison
equal deleted inserted replaced
10100:9aa8d8037ee3 10101:df254344edf1
101 // list of the chunks it is using and the current chunk. The current 101 // list of the chunks it is using and the current chunk. The current
102 // chunk is the chunk from which allocations are done. Space freed in 102 // chunk is the chunk from which allocations are done. Space freed in
103 // a chunk is placed on the free list of blocks (BlockFreelist) and 103 // a chunk is placed on the free list of blocks (BlockFreelist) and
104 // reused from there. 104 // reused from there.
105 105
106 // Pointer to list of Metachunks. 106 typedef class FreeList<Metachunk> ChunkList;
107 class ChunkList VALUE_OBJ_CLASS_SPEC {
108 // List of free chunks
109 Metachunk* _head;
110
111 public:
112 // Constructor
113 ChunkList() : _head(NULL) {}
114
115 // Accessors
116 Metachunk* head() { return _head; }
117 void set_head(Metachunk* v) { _head = v; }
118
119 // Link at head of the list
120 void add_at_head(Metachunk* head, Metachunk* tail);
121 void add_at_head(Metachunk* head);
122
123 size_t sum_list_size();
124 size_t sum_list_count();
125 size_t sum_list_capacity();
126 };
127 107
128 // Manages the global free lists of chunks. 108 // Manages the global free lists of chunks.
129 // Has three lists of free chunks, and a total size and 109 // Has three lists of free chunks, and a total size and
130 // count that includes all three 110 // count that includes all three
131 111
182 void chunk_freelist_deallocate(Metachunk* chunk); 162 void chunk_freelist_deallocate(Metachunk* chunk);
183 163
184 // Map a size to a list index assuming that there are lists 164 // Map a size to a list index assuming that there are lists
185 // for special, small, medium, and humongous chunks. 165 // for special, small, medium, and humongous chunks.
186 static ChunkIndex list_index(size_t size); 166 static ChunkIndex list_index(size_t size);
167
168 // Add the simple linked list of chunks to the freelist of chunks
169 // of type index.
170 void return_chunks(ChunkIndex index, Metachunk* chunks);
187 171
188 // Total of the space in the free chunks list 172 // Total of the space in the free chunks list
189 size_t free_chunks_total(); 173 size_t free_chunks_total();
190 size_t free_chunks_total_in_bytes(); 174 size_t free_chunks_total_in_bytes();
191 175
897 _virtual_space_count(0) { 881 _virtual_space_count(0) {
898 MutexLockerEx cl(SpaceManager::expand_lock(), 882 MutexLockerEx cl(SpaceManager::expand_lock(),
899 Mutex::_no_safepoint_check_flag); 883 Mutex::_no_safepoint_check_flag);
900 bool initialization_succeeded = grow_vs(word_size); 884 bool initialization_succeeded = grow_vs(word_size);
901 885
886 _chunk_manager.free_chunks(SpecializedIndex)->set_size(SpecializedChunk);
887 _chunk_manager.free_chunks(SmallIndex)->set_size(SmallChunk);
888 _chunk_manager.free_chunks(MediumIndex)->set_size(MediumChunk);
902 assert(initialization_succeeded, 889 assert(initialization_succeeded,
903 " VirtualSpaceList initialization should not fail"); 890 " VirtualSpaceList initialization should not fail");
904 } 891 }
905 892
906 VirtualSpaceList::VirtualSpaceList(ReservedSpace rs) : 893 VirtualSpaceList::VirtualSpaceList(ReservedSpace rs) :
911 _virtual_space_count(0) { 898 _virtual_space_count(0) {
912 MutexLockerEx cl(SpaceManager::expand_lock(), 899 MutexLockerEx cl(SpaceManager::expand_lock(),
913 Mutex::_no_safepoint_check_flag); 900 Mutex::_no_safepoint_check_flag);
914 VirtualSpaceNode* class_entry = new VirtualSpaceNode(rs); 901 VirtualSpaceNode* class_entry = new VirtualSpaceNode(rs);
915 bool succeeded = class_entry->initialize(); 902 bool succeeded = class_entry->initialize();
903 _chunk_manager.free_chunks(SpecializedIndex)->set_size(SpecializedChunk);
904 _chunk_manager.free_chunks(SmallIndex)->set_size(ClassSmallChunk);
905 _chunk_manager.free_chunks(MediumIndex)->set_size(ClassMediumChunk);
916 assert(succeeded, " VirtualSpaceList initialization should not fail"); 906 assert(succeeded, " VirtualSpaceList initialization should not fail");
917 link_vs(class_entry, rs.size()/BytesPerWord); 907 link_vs(class_entry, rs.size()/BytesPerWord);
918 } 908 }
919 909
920 // Allocate another meta virtual space and add it to the list. 910 // Allocate another meta virtual space and add it to the list.
1378 } 1368 }
1379 return false; 1369 return false;
1380 } 1370 }
1381 #endif 1371 #endif
1382 1372
1383 // ChunkList methods
1384
1385 size_t ChunkList::sum_list_size() {
1386 size_t result = 0;
1387 Metachunk* cur = head();
1388 while (cur != NULL) {
1389 result += cur->word_size();
1390 cur = cur->next();
1391 }
1392 return result;
1393 }
1394
1395 size_t ChunkList::sum_list_count() {
1396 size_t result = 0;
1397 Metachunk* cur = head();
1398 while (cur != NULL) {
1399 result++;
1400 cur = cur->next();
1401 }
1402 return result;
1403 }
1404
1405 size_t ChunkList::sum_list_capacity() {
1406 size_t result = 0;
1407 Metachunk* cur = head();
1408 while (cur != NULL) {
1409 result += cur->capacity_word_size();
1410 cur = cur->next();
1411 }
1412 return result;
1413 }
1414
1415 void ChunkList::add_at_head(Metachunk* head, Metachunk* tail) {
1416 assert_lock_strong(SpaceManager::expand_lock());
1417 assert(head == tail || tail->next() == NULL,
1418 "Not the tail or the head has already been added to a list");
1419
1420 if (TraceMetadataChunkAllocation && Verbose) {
1421 gclog_or_tty->print("ChunkList::add_at_head(head, tail): ");
1422 Metachunk* cur = head;
1423 while (cur != NULL) {
1424 gclog_or_tty->print(PTR_FORMAT " (" SIZE_FORMAT ") ", cur, cur->word_size());
1425 cur = cur->next();
1426 }
1427 gclog_or_tty->print_cr("");
1428 }
1429
1430 if (tail != NULL) {
1431 tail->set_next(_head);
1432 }
1433 set_head(head);
1434 }
1435
1436 void ChunkList::add_at_head(Metachunk* list) {
1437 if (list == NULL) {
1438 // Nothing to add
1439 return;
1440 }
1441 assert_lock_strong(SpaceManager::expand_lock());
1442 Metachunk* head = list;
1443 Metachunk* tail = list;
1444 Metachunk* cur = head->next();
1445 // Search for the tail since it is not passed.
1446 while (cur != NULL) {
1447 tail = cur;
1448 cur = cur->next();
1449 }
1450 add_at_head(head, tail);
1451 }
1452
1453 // ChunkManager methods 1373 // ChunkManager methods
1454 1374
1455 // Verification of _free_chunks_total and _free_chunks_count does not 1375 // Verification of _free_chunks_total and _free_chunks_count does not
1456 // work with the CMS collector because its use of additional locks 1376 // work with the CMS collector because its use of additional locks
1457 // complicate the mutex deadlock detection but it can still be useful 1377 // complicate the mutex deadlock detection but it can still be useful
1551 1471
1552 if (list == NULL) { 1472 if (list == NULL) {
1553 continue; 1473 continue;
1554 } 1474 }
1555 1475
1556 result = result + list->sum_list_capacity(); 1476 result = result + list->count() * list->size();
1557 } 1477 }
1558 result = result + humongous_dictionary()->total_size(); 1478 result = result + humongous_dictionary()->total_size();
1559 return result; 1479 return result;
1560 } 1480 }
1561 1481
1565 for (ChunkIndex i = ZeroIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) { 1485 for (ChunkIndex i = ZeroIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) {
1566 ChunkList* list = free_chunks(i); 1486 ChunkList* list = free_chunks(i);
1567 if (list == NULL) { 1487 if (list == NULL) {
1568 continue; 1488 continue;
1569 } 1489 }
1570 count = count + list->sum_list_count(); 1490 count = count + list->count();
1571 } 1491 }
1572 count = count + humongous_dictionary()->total_free_blocks(); 1492 count = count + humongous_dictionary()->total_free_blocks();
1573 return count; 1493 return count;
1574 } 1494 }
1575 1495
1620 if (chunk == NULL) { 1540 if (chunk == NULL) {
1621 return NULL; 1541 return NULL;
1622 } 1542 }
1623 1543
1624 // Remove the chunk as the head of the list. 1544 // Remove the chunk as the head of the list.
1625 free_list->set_head(chunk->next()); 1545 free_list->remove_chunk(chunk);
1626 1546
1627 // Chunk is being removed from the chunks free list. 1547 // Chunk is being removed from the chunks free list.
1628 dec_free_chunks_total(chunk->capacity_word_size()); 1548 dec_free_chunks_total(chunk->capacity_word_size());
1629 1549
1630 if (TraceMetadataChunkAllocation && Verbose) { 1550 if (TraceMetadataChunkAllocation && Verbose) {
1677 "Non-humongous variable sized chunk"); 1597 "Non-humongous variable sized chunk");
1678 if (TraceMetadataChunkAllocation) { 1598 if (TraceMetadataChunkAllocation) {
1679 size_t list_count; 1599 size_t list_count;
1680 if (list_index(word_size) < HumongousIndex) { 1600 if (list_index(word_size) < HumongousIndex) {
1681 ChunkList* list = find_free_chunks_list(word_size); 1601 ChunkList* list = find_free_chunks_list(word_size);
1682 list_count = list->sum_list_count(); 1602 list_count = list->count();
1683 } else { 1603 } else {
1684 list_count = humongous_dictionary()->total_count(); 1604 list_count = humongous_dictionary()->total_count();
1685 } 1605 }
1686 tty->print("ChunkManager::chunk_freelist_allocate: " PTR_FORMAT " chunk " 1606 tty->print("ChunkManager::chunk_freelist_allocate: " PTR_FORMAT " chunk "
1687 PTR_FORMAT " size " SIZE_FORMAT " count " SIZE_FORMAT " ", 1607 PTR_FORMAT " size " SIZE_FORMAT " count " SIZE_FORMAT " ",
1956 if (TraceMetadataChunkAllocation && Verbose) { 1876 if (TraceMetadataChunkAllocation && Verbose) {
1957 gclog_or_tty->print_cr("SpaceManager(): " PTR_FORMAT, this); 1877 gclog_or_tty->print_cr("SpaceManager(): " PTR_FORMAT, this);
1958 } 1878 }
1959 } 1879 }
1960 1880
1881 void ChunkManager::return_chunks(ChunkIndex index, Metachunk* chunks) {
1882 if (chunks == NULL) {
1883 return;
1884 }
1885 ChunkList* list = free_chunks(index);
1886 assert(list->size() == chunks->word_size(), "Mismatch in chunk sizes");
1887 assert_lock_strong(SpaceManager::expand_lock());
1888 Metachunk* cur = chunks;
1889
1890 // This return chunks one at a time. If a new
1891 // class List can be created that is a base class
1892 // of FreeList then something like FreeList::prepend()
1893 // can be used in place of this loop
1894 while (cur != NULL) {
1895 // Capture the next link before it is changed
1896 // by the call to return_chunk_at_head();
1897 Metachunk* next = cur->next();
1898 cur->set_is_free(true);
1899 list->return_chunk_at_head(cur);
1900 cur = next;
1901 }
1902 }
1903
1961 SpaceManager::~SpaceManager() { 1904 SpaceManager::~SpaceManager() {
1962 // This call this->_lock which can't be done while holding expand_lock() 1905 // This call this->_lock which can't be done while holding expand_lock()
1963 const size_t in_use_before = sum_capacity_in_chunks_in_use(); 1906 const size_t in_use_before = sum_capacity_in_chunks_in_use();
1964 1907
1965 MutexLockerEx fcl(SpaceManager::expand_lock(), 1908 MutexLockerEx fcl(SpaceManager::expand_lock(),
1993 gclog_or_tty->print_cr("returned %d %s chunks to freelist", 1936 gclog_or_tty->print_cr("returned %d %s chunks to freelist",
1994 sum_count_in_chunks_in_use(i), 1937 sum_count_in_chunks_in_use(i),
1995 chunk_size_name(i)); 1938 chunk_size_name(i));
1996 } 1939 }
1997 Metachunk* chunks = chunks_in_use(i); 1940 Metachunk* chunks = chunks_in_use(i);
1998 chunk_manager->free_chunks(i)->add_at_head(chunks); 1941 chunk_manager->return_chunks(i, chunks);
1999 set_chunks_in_use(i, NULL); 1942 set_chunks_in_use(i, NULL);
2000 if (TraceMetadataChunkAllocation && Verbose) { 1943 if (TraceMetadataChunkAllocation && Verbose) {
2001 gclog_or_tty->print_cr("updated freelist count %d %s", 1944 gclog_or_tty->print_cr("updated freelist count %d %s",
2002 chunk_manager->free_chunks(i)->sum_list_count(), 1945 chunk_manager->free_chunks(i)->count(),
2003 chunk_size_name(i)); 1946 chunk_size_name(i));
2004 } 1947 }
2005 assert(i != HumongousIndex, "Humongous chunks are handled explicitly later"); 1948 assert(i != HumongousIndex, "Humongous chunks are handled explicitly later");
2006 } 1949 }
2007 1950