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 |
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 |