117 // has to have the klass's klassKlass allocated at a lower |
117 // has to have the klass's klassKlass allocated at a lower |
118 // address in the heap than the klass so that the klassKlass is |
118 // address in the heap than the klass so that the klassKlass is |
119 // moved to its new location before the klass is moved. |
119 // moved to its new location before the klass is moved. |
120 // Set the _refillSize for the linear allocation blocks |
120 // Set the _refillSize for the linear allocation blocks |
121 if (!use_adaptive_freelists) { |
121 if (!use_adaptive_freelists) { |
122 FreeChunk* fc = _dictionary->getChunk(mr.word_size()); |
122 FreeChunk* fc = _dictionary->get_chunk(mr.word_size()); |
123 // The small linAB initially has all the space and will allocate |
123 // The small linAB initially has all the space and will allocate |
124 // a chunk of any size. |
124 // a chunk of any size. |
125 HeapWord* addr = (HeapWord*) fc; |
125 HeapWord* addr = (HeapWord*) fc; |
126 _smallLinearAllocBlock.set(addr, fc->size() , |
126 _smallLinearAllocBlock.set(addr, fc->size() , |
127 1024*SmallForLinearAlloc, fc->size()); |
127 1024*SmallForLinearAlloc, fc->size()); |
391 // correct actual value. However, for instance, this is |
391 // correct actual value. However, for instance, this is |
392 // also read completely asynchronously by the "perf-sampler" |
392 // also read completely asynchronously by the "perf-sampler" |
393 // that supports jvmstat, and you are apt to see the values |
393 // that supports jvmstat, and you are apt to see the values |
394 // flicker in such cases. |
394 // flicker in such cases. |
395 assert(_dictionary != NULL, "No _dictionary?"); |
395 assert(_dictionary != NULL, "No _dictionary?"); |
396 return (_dictionary->totalChunkSize(DEBUG_ONLY(freelistLock())) + |
396 return (_dictionary->total_chunk_size(DEBUG_ONLY(freelistLock())) + |
397 totalSizeInIndexedFreeLists() + |
397 totalSizeInIndexedFreeLists() + |
398 _smallLinearAllocBlock._word_size) * HeapWordSize; |
398 _smallLinearAllocBlock._word_size) * HeapWordSize; |
399 } |
399 } |
400 |
400 |
401 size_t CompactibleFreeListSpace::max_alloc_in_words() const { |
401 size_t CompactibleFreeListSpace::max_alloc_in_words() const { |
402 assert(_dictionary != NULL, "No _dictionary?"); |
402 assert(_dictionary != NULL, "No _dictionary?"); |
403 assert_locked(); |
403 assert_locked(); |
404 size_t res = _dictionary->maxChunkSize(); |
404 size_t res = _dictionary->max_chunk_size(); |
405 res = MAX2(res, MIN2(_smallLinearAllocBlock._word_size, |
405 res = MAX2(res, MIN2(_smallLinearAllocBlock._word_size, |
406 (size_t) SmallForLinearAlloc - 1)); |
406 (size_t) SmallForLinearAlloc - 1)); |
407 // XXX the following could potentially be pretty slow; |
407 // XXX the following could potentially be pretty slow; |
408 // should one, pesimally for the rare cases when res |
408 // should one, pesimally for the rare cases when res |
409 // caclulated above is less than IndexSetSize, |
409 // caclulated above is less than IndexSetSize, |
545 |
545 |
546 |
546 |
547 void CompactibleFreeListSpace::reportFreeListStatistics() const { |
547 void CompactibleFreeListSpace::reportFreeListStatistics() const { |
548 assert_lock_strong(&_freelistLock); |
548 assert_lock_strong(&_freelistLock); |
549 assert(PrintFLSStatistics != 0, "Reporting error"); |
549 assert(PrintFLSStatistics != 0, "Reporting error"); |
550 _dictionary->reportStatistics(); |
550 _dictionary->report_statistics(); |
551 if (PrintFLSStatistics > 1) { |
551 if (PrintFLSStatistics > 1) { |
552 reportIndexedFreeListStatistics(); |
552 reportIndexedFreeListStatistics(); |
553 size_t totalSize = totalSizeInIndexedFreeLists() + |
553 size_t total_size = totalSizeInIndexedFreeLists() + |
554 _dictionary->totalChunkSize(DEBUG_ONLY(freelistLock())); |
554 _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock())); |
555 gclog_or_tty->print(" free=%ld frag=%1.4f\n", totalSize, flsFrag()); |
555 gclog_or_tty->print(" free=%ld frag=%1.4f\n", total_size, flsFrag()); |
556 } |
556 } |
557 } |
557 } |
558 |
558 |
559 void CompactibleFreeListSpace::reportIndexedFreeListStatistics() const { |
559 void CompactibleFreeListSpace::reportIndexedFreeListStatistics() const { |
560 assert_lock_strong(&_freelistLock); |
560 assert_lock_strong(&_freelistLock); |
561 gclog_or_tty->print("Statistics for IndexedFreeLists:\n" |
561 gclog_or_tty->print("Statistics for IndexedFreeLists:\n" |
562 "--------------------------------\n"); |
562 "--------------------------------\n"); |
563 size_t totalSize = totalSizeInIndexedFreeLists(); |
563 size_t total_size = totalSizeInIndexedFreeLists(); |
564 size_t freeBlocks = numFreeBlocksInIndexedFreeLists(); |
564 size_t free_blocks = numFreeBlocksInIndexedFreeLists(); |
565 gclog_or_tty->print("Total Free Space: %d\n", totalSize); |
565 gclog_or_tty->print("Total Free Space: %d\n", total_size); |
566 gclog_or_tty->print("Max Chunk Size: %d\n", maxChunkSizeInIndexedFreeLists()); |
566 gclog_or_tty->print("Max Chunk Size: %d\n", maxChunkSizeInIndexedFreeLists()); |
567 gclog_or_tty->print("Number of Blocks: %d\n", freeBlocks); |
567 gclog_or_tty->print("Number of Blocks: %d\n", free_blocks); |
568 if (freeBlocks != 0) { |
568 if (free_blocks != 0) { |
569 gclog_or_tty->print("Av. Block Size: %d\n", totalSize/freeBlocks); |
569 gclog_or_tty->print("Av. Block Size: %d\n", total_size/free_blocks); |
570 } |
570 } |
571 } |
571 } |
572 |
572 |
573 size_t CompactibleFreeListSpace::numFreeBlocksInIndexedFreeLists() const { |
573 size_t CompactibleFreeListSpace::numFreeBlocksInIndexedFreeLists() const { |
574 size_t res = 0; |
574 size_t res = 0; |
1334 assert(currSize % MinObjAlignment == 0, "currSize should be aligned"); |
1334 assert(currSize % MinObjAlignment == 0, "currSize should be aligned"); |
1335 for (i = currSize; i < IndexSetSize; i += IndexSetStride) { |
1335 for (i = currSize; i < IndexSetSize; i += IndexSetStride) { |
1336 FreeList<FreeChunk>* fl = &_indexedFreeList[i]; |
1336 FreeList<FreeChunk>* fl = &_indexedFreeList[i]; |
1337 if (fl->head()) { |
1337 if (fl->head()) { |
1338 ret = getFromListGreater(fl, numWords); |
1338 ret = getFromListGreater(fl, numWords); |
1339 assert(ret == NULL || ret->isFree(), "Should be returning a free chunk"); |
1339 assert(ret == NULL || ret->is_free(), "Should be returning a free chunk"); |
1340 return ret; |
1340 return ret; |
1341 } |
1341 } |
1342 } |
1342 } |
1343 |
1343 |
1344 currSize = MAX2((size_t)SmallForDictionary, |
1344 currSize = MAX2((size_t)SmallForDictionary, |
1345 (size_t)(numWords + MinChunkSize)); |
1345 (size_t)(numWords + MinChunkSize)); |
1346 |
1346 |
1347 /* Try to get a chunk that satisfies request, while avoiding |
1347 /* Try to get a chunk that satisfies request, while avoiding |
1348 fragmentation that can't be handled. */ |
1348 fragmentation that can't be handled. */ |
1349 { |
1349 { |
1350 ret = dictionary()->getChunk(currSize); |
1350 ret = dictionary()->get_chunk(currSize); |
1351 if (ret != NULL) { |
1351 if (ret != NULL) { |
1352 assert(ret->size() - numWords >= MinChunkSize, |
1352 assert(ret->size() - numWords >= MinChunkSize, |
1353 "Chunk is too small"); |
1353 "Chunk is too small"); |
1354 _bt.allocated((HeapWord*)ret, ret->size()); |
1354 _bt.allocated((HeapWord*)ret, ret->size()); |
1355 /* Carve returned chunk. */ |
1355 /* Carve returned chunk. */ |
1356 (void) splitChunkAndReturnRemainder(ret, numWords); |
1356 (void) splitChunkAndReturnRemainder(ret, numWords); |
1357 /* Label this as no longer a free chunk. */ |
1357 /* Label this as no longer a free chunk. */ |
1358 assert(ret->isFree(), "This chunk should be free"); |
1358 assert(ret->is_free(), "This chunk should be free"); |
1359 ret->linkPrev(NULL); |
1359 ret->link_prev(NULL); |
1360 } |
1360 } |
1361 assert(ret == NULL || ret->isFree(), "Should be returning a free chunk"); |
1361 assert(ret == NULL || ret->is_free(), "Should be returning a free chunk"); |
1362 return ret; |
1362 return ret; |
1363 } |
1363 } |
1364 ShouldNotReachHere(); |
1364 ShouldNotReachHere(); |
1365 } |
1365 } |
1366 |
1366 |
1367 bool CompactibleFreeListSpace::verifyChunkInIndexedFreeLists(FreeChunk* fc) const { |
1367 bool CompactibleFreeListSpace::verifyChunkInIndexedFreeLists(FreeChunk* fc) const { |
1368 assert(fc->size() < IndexSetSize, "Size of chunk is too large"); |
1368 assert(fc->size() < IndexSetSize, "Size of chunk is too large"); |
1369 return _indexedFreeList[fc->size()].verifyChunkInFreeLists(fc); |
1369 return _indexedFreeList[fc->size()].verify_chunk_in_free_list(fc); |
1370 } |
1370 } |
1371 |
1371 |
1372 bool CompactibleFreeListSpace::verify_chunk_is_linear_alloc_block(FreeChunk* fc) const { |
1372 bool CompactibleFreeListSpace::verify_chunk_is_linear_alloc_block(FreeChunk* fc) const { |
1373 assert((_smallLinearAllocBlock._ptr != (HeapWord*)fc) || |
1373 assert((_smallLinearAllocBlock._ptr != (HeapWord*)fc) || |
1374 (_smallLinearAllocBlock._word_size == fc->size()), |
1374 (_smallLinearAllocBlock._word_size == fc->size()), |
1504 blk->_ptr = NULL; blk->_word_size = 0; |
1504 blk->_ptr = NULL; blk->_word_size = 0; |
1505 refillLinearAllocBlock(blk); |
1505 refillLinearAllocBlock(blk); |
1506 assert(blk->_ptr == NULL || blk->_word_size >= size + MinChunkSize, |
1506 assert(blk->_ptr == NULL || blk->_word_size >= size + MinChunkSize, |
1507 "block was replenished"); |
1507 "block was replenished"); |
1508 if (res != NULL) { |
1508 if (res != NULL) { |
1509 splitBirth(size); |
1509 split_birth(size); |
1510 repairLinearAllocBlock(blk); |
1510 repairLinearAllocBlock(blk); |
1511 } else if (blk->_ptr != NULL) { |
1511 } else if (blk->_ptr != NULL) { |
1512 res = blk->_ptr; |
1512 res = blk->_ptr; |
1513 size_t blk_size = blk->_word_size; |
1513 size_t blk_size = blk->_word_size; |
1514 blk->_word_size -= size; |
1514 blk->_word_size -= size; |
1515 blk->_ptr += size; |
1515 blk->_ptr += size; |
1516 splitBirth(size); |
1516 split_birth(size); |
1517 repairLinearAllocBlock(blk); |
1517 repairLinearAllocBlock(blk); |
1518 // Update BOT last so that other (parallel) GC threads see a consistent |
1518 // Update BOT last so that other (parallel) GC threads see a consistent |
1519 // view of the BOT and free blocks. |
1519 // view of the BOT and free blocks. |
1520 // Above must occur before BOT is updated below. |
1520 // Above must occur before BOT is updated below. |
1521 OrderAccess::storestore(); |
1521 OrderAccess::storestore(); |
1624 for (curFc = newFc, nextFc = (FreeChunk*)((HeapWord*)curFc + size), |
1624 for (curFc = newFc, nextFc = (FreeChunk*)((HeapWord*)curFc + size), |
1625 i = 0; |
1625 i = 0; |
1626 i < (num_blk - 1); |
1626 i < (num_blk - 1); |
1627 curFc = nextFc, nextFc = (FreeChunk*)((HeapWord*)nextFc + size), |
1627 curFc = nextFc, nextFc = (FreeChunk*)((HeapWord*)nextFc + size), |
1628 i++) { |
1628 i++) { |
1629 curFc->setSize(size); |
1629 curFc->set_size(size); |
1630 // Don't record this as a return in order to try and |
1630 // Don't record this as a return in order to try and |
1631 // determine the "returns" from a GC. |
1631 // determine the "returns" from a GC. |
1632 _bt.verify_not_unallocated((HeapWord*) fc, size); |
1632 _bt.verify_not_unallocated((HeapWord*) fc, size); |
1633 _indexedFreeList[size].returnChunkAtTail(curFc, false); |
1633 _indexedFreeList[size].return_chunk_at_tail(curFc, false); |
1634 _bt.mark_block((HeapWord*)curFc, size); |
1634 _bt.mark_block((HeapWord*)curFc, size); |
1635 splitBirth(size); |
1635 split_birth(size); |
1636 // Don't record the initial population of the indexed list |
1636 // Don't record the initial population of the indexed list |
1637 // as a split birth. |
1637 // as a split birth. |
1638 } |
1638 } |
1639 |
1639 |
1640 // check that the arithmetic was OK above |
1640 // check that the arithmetic was OK above |
1641 assert((HeapWord*)nextFc == (HeapWord*)newFc + num_blk*size, |
1641 assert((HeapWord*)nextFc == (HeapWord*)newFc + num_blk*size, |
1642 "inconsistency in carving newFc"); |
1642 "inconsistency in carving newFc"); |
1643 curFc->setSize(size); |
1643 curFc->set_size(size); |
1644 _bt.mark_block((HeapWord*)curFc, size); |
1644 _bt.mark_block((HeapWord*)curFc, size); |
1645 splitBirth(size); |
1645 split_birth(size); |
1646 fc = curFc; |
1646 fc = curFc; |
1647 } else { |
1647 } else { |
1648 // Return entire block to caller |
1648 // Return entire block to caller |
1649 fc = newFc; |
1649 fc = newFc; |
1650 } |
1650 } |
1756 lock = &_parDictionaryAllocLock; |
1756 lock = &_parDictionaryAllocLock; |
1757 } |
1757 } |
1758 FreeChunk* ec; |
1758 FreeChunk* ec; |
1759 { |
1759 { |
1760 MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag); |
1760 MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag); |
1761 ec = dictionary()->findLargestDict(); // get largest block |
1761 ec = dictionary()->find_largest_dict(); // get largest block |
1762 if (ec != NULL && ec->end() == chunk) { |
1762 if (ec != NULL && ec->end() == chunk) { |
1763 // It's a coterminal block - we can coalesce. |
1763 // It's a coterminal block - we can coalesce. |
1764 size_t old_size = ec->size(); |
1764 size_t old_size = ec->size(); |
1765 coalDeath(old_size); |
1765 coalDeath(old_size); |
1766 removeChunkFromDictionary(ec); |
1766 removeChunkFromDictionary(ec); |
1767 size += old_size; |
1767 size += old_size; |
1768 } else { |
1768 } else { |
1769 ec = (FreeChunk*)chunk; |
1769 ec = (FreeChunk*)chunk; |
1770 } |
1770 } |
1771 } |
1771 } |
1772 ec->setSize(size); |
1772 ec->set_size(size); |
1773 debug_only(ec->mangleFreed(size)); |
1773 debug_only(ec->mangleFreed(size)); |
1774 if (size < SmallForDictionary) { |
1774 if (size < SmallForDictionary) { |
1775 lock = _indexedFreeListParLocks[size]; |
1775 lock = _indexedFreeListParLocks[size]; |
1776 } |
1776 } |
1777 MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag); |
1777 MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag); |
1894 assert(numWords >= MinChunkSize, "Word size is too small"); |
1894 assert(numWords >= MinChunkSize, "Word size is too small"); |
1895 assert(curr != NULL, "List is empty"); |
1895 assert(curr != NULL, "List is empty"); |
1896 assert(oldNumWords >= numWords + MinChunkSize, |
1896 assert(oldNumWords >= numWords + MinChunkSize, |
1897 "Size of chunks in the list is too small"); |
1897 "Size of chunks in the list is too small"); |
1898 |
1898 |
1899 fl->removeChunk(curr); |
1899 fl->remove_chunk(curr); |
1900 // recorded indirectly by splitChunkAndReturnRemainder - |
1900 // recorded indirectly by splitChunkAndReturnRemainder - |
1901 // smallSplit(oldNumWords, numWords); |
1901 // smallSplit(oldNumWords, numWords); |
1902 FreeChunk* new_chunk = splitChunkAndReturnRemainder(curr, numWords); |
1902 FreeChunk* new_chunk = splitChunkAndReturnRemainder(curr, numWords); |
1903 // Does anything have to be done for the remainder in terms of |
1903 // Does anything have to be done for the remainder in terms of |
1904 // fixing the card table? |
1904 // fixing the card table? |
1905 assert(new_chunk == NULL || new_chunk->isFree(), |
1905 assert(new_chunk == NULL || new_chunk->is_free(), |
1906 "Should be returning a free chunk"); |
1906 "Should be returning a free chunk"); |
1907 return new_chunk; |
1907 return new_chunk; |
1908 } |
1908 } |
1909 |
1909 |
1910 FreeChunk* |
1910 FreeChunk* |
1918 size_t rem_size = size - new_size; |
1918 size_t rem_size = size - new_size; |
1919 assert(rem_size == adjustObjectSize(rem_size), "alignment problem"); |
1919 assert(rem_size == adjustObjectSize(rem_size), "alignment problem"); |
1920 assert(rem_size >= MinChunkSize, "Free chunk smaller than minimum"); |
1920 assert(rem_size >= MinChunkSize, "Free chunk smaller than minimum"); |
1921 FreeChunk* ffc = (FreeChunk*)((HeapWord*)chunk + new_size); |
1921 FreeChunk* ffc = (FreeChunk*)((HeapWord*)chunk + new_size); |
1922 assert(is_aligned(ffc), "alignment problem"); |
1922 assert(is_aligned(ffc), "alignment problem"); |
1923 ffc->setSize(rem_size); |
1923 ffc->set_size(rem_size); |
1924 ffc->linkNext(NULL); |
1924 ffc->link_next(NULL); |
1925 ffc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads. |
1925 ffc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads. |
1926 // Above must occur before BOT is updated below. |
1926 // Above must occur before BOT is updated below. |
1927 // adjust block offset table |
1927 // adjust block offset table |
1928 OrderAccess::storestore(); |
1928 OrderAccess::storestore(); |
1929 assert(chunk->isFree() && ffc->isFree(), "Error"); |
1929 assert(chunk->is_free() && ffc->is_free(), "Error"); |
1930 _bt.split_block((HeapWord*)chunk, chunk->size(), new_size); |
1930 _bt.split_block((HeapWord*)chunk, chunk->size(), new_size); |
1931 if (rem_size < SmallForDictionary) { |
1931 if (rem_size < SmallForDictionary) { |
1932 bool is_par = (SharedHeap::heap()->n_par_threads() > 0); |
1932 bool is_par = (SharedHeap::heap()->n_par_threads() > 0); |
1933 if (is_par) _indexedFreeListParLocks[rem_size]->lock(); |
1933 if (is_par) _indexedFreeListParLocks[rem_size]->lock(); |
1934 assert(!is_par || |
1934 assert(!is_par || |
2172 FreeList<FreeChunk>* fl = &_indexedFreeList[i]; |
2172 FreeList<FreeChunk>* fl = &_indexedFreeList[i]; |
2173 if (PrintFLSStatistics > 1) { |
2173 if (PrintFLSStatistics > 1) { |
2174 gclog_or_tty->print("size[%d] : ", i); |
2174 gclog_or_tty->print("size[%d] : ", i); |
2175 } |
2175 } |
2176 fl->compute_desired(inter_sweep_current, inter_sweep_estimate, intra_sweep_estimate); |
2176 fl->compute_desired(inter_sweep_current, inter_sweep_estimate, intra_sweep_estimate); |
2177 fl->set_coalDesired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent)); |
2177 fl->set_coal_desired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent)); |
2178 fl->set_beforeSweep(fl->count()); |
2178 fl->set_before_sweep(fl->count()); |
2179 fl->set_bfrSurp(fl->surplus()); |
2179 fl->set_bfr_surp(fl->surplus()); |
2180 } |
2180 } |
2181 _dictionary->beginSweepDictCensus(CMSLargeCoalSurplusPercent, |
2181 _dictionary->begin_sweep_dict_census(CMSLargeCoalSurplusPercent, |
2182 inter_sweep_current, |
2182 inter_sweep_current, |
2183 inter_sweep_estimate, |
2183 inter_sweep_estimate, |
2184 intra_sweep_estimate); |
2184 intra_sweep_estimate); |
2185 } |
2185 } |
2186 |
2186 |
2210 void CompactibleFreeListSpace::clearFLCensus() { |
2210 void CompactibleFreeListSpace::clearFLCensus() { |
2211 assert_locked(); |
2211 assert_locked(); |
2212 size_t i; |
2212 size_t i; |
2213 for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { |
2213 for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { |
2214 FreeList<FreeChunk> *fl = &_indexedFreeList[i]; |
2214 FreeList<FreeChunk> *fl = &_indexedFreeList[i]; |
2215 fl->set_prevSweep(fl->count()); |
2215 fl->set_prev_sweep(fl->count()); |
2216 fl->set_coalBirths(0); |
2216 fl->set_coal_births(0); |
2217 fl->set_coalDeaths(0); |
2217 fl->set_coal_deaths(0); |
2218 fl->set_splitBirths(0); |
2218 fl->set_split_births(0); |
2219 fl->set_splitDeaths(0); |
2219 fl->set_split_deaths(0); |
2220 } |
2220 } |
2221 } |
2221 } |
2222 |
2222 |
2223 void CompactibleFreeListSpace::endSweepFLCensus(size_t sweep_count) { |
2223 void CompactibleFreeListSpace::endSweepFLCensus(size_t sweep_count) { |
2224 if (PrintFLSStatistics > 0) { |
2224 if (PrintFLSStatistics > 0) { |
2225 HeapWord* largestAddr = (HeapWord*) dictionary()->findLargestDict(); |
2225 HeapWord* largestAddr = (HeapWord*) dictionary()->find_largest_dict(); |
2226 gclog_or_tty->print_cr("CMS: Large block " PTR_FORMAT, |
2226 gclog_or_tty->print_cr("CMS: Large block " PTR_FORMAT, |
2227 largestAddr); |
2227 largestAddr); |
2228 } |
2228 } |
2229 setFLSurplus(); |
2229 setFLSurplus(); |
2230 setFLHints(); |
2230 setFLHints(); |
2231 if (PrintGC && PrintFLSCensus > 0) { |
2231 if (PrintGC && PrintFLSCensus > 0) { |
2232 printFLCensus(sweep_count); |
2232 printFLCensus(sweep_count); |
2233 } |
2233 } |
2234 clearFLCensus(); |
2234 clearFLCensus(); |
2235 assert_locked(); |
2235 assert_locked(); |
2236 _dictionary->endSweepDictCensus(CMSLargeSplitSurplusPercent); |
2236 _dictionary->end_sweep_dict_census(CMSLargeSplitSurplusPercent); |
2237 } |
2237 } |
2238 |
2238 |
2239 bool CompactibleFreeListSpace::coalOverPopulated(size_t size) { |
2239 bool CompactibleFreeListSpace::coalOverPopulated(size_t size) { |
2240 if (size < SmallForDictionary) { |
2240 if (size < SmallForDictionary) { |
2241 FreeList<FreeChunk> *fl = &_indexedFreeList[size]; |
2241 FreeList<FreeChunk> *fl = &_indexedFreeList[size]; |
2242 return (fl->coalDesired() < 0) || |
2242 return (fl->coal_desired() < 0) || |
2243 ((int)fl->count() > fl->coalDesired()); |
2243 ((int)fl->count() > fl->coal_desired()); |
2244 } else { |
2244 } else { |
2245 return dictionary()->coalDictOverPopulated(size); |
2245 return dictionary()->coal_dict_over_populated(size); |
2246 } |
2246 } |
2247 } |
2247 } |
2248 |
2248 |
2249 void CompactibleFreeListSpace::smallCoalBirth(size_t size) { |
2249 void CompactibleFreeListSpace::smallCoalBirth(size_t size) { |
2250 assert(size < SmallForDictionary, "Size too large for indexed list"); |
2250 assert(size < SmallForDictionary, "Size too large for indexed list"); |
2251 FreeList<FreeChunk> *fl = &_indexedFreeList[size]; |
2251 FreeList<FreeChunk> *fl = &_indexedFreeList[size]; |
2252 fl->increment_coalBirths(); |
2252 fl->increment_coal_births(); |
2253 fl->increment_surplus(); |
2253 fl->increment_surplus(); |
2254 } |
2254 } |
2255 |
2255 |
2256 void CompactibleFreeListSpace::smallCoalDeath(size_t size) { |
2256 void CompactibleFreeListSpace::smallCoalDeath(size_t size) { |
2257 assert(size < SmallForDictionary, "Size too large for indexed list"); |
2257 assert(size < SmallForDictionary, "Size too large for indexed list"); |
2258 FreeList<FreeChunk> *fl = &_indexedFreeList[size]; |
2258 FreeList<FreeChunk> *fl = &_indexedFreeList[size]; |
2259 fl->increment_coalDeaths(); |
2259 fl->increment_coal_deaths(); |
2260 fl->decrement_surplus(); |
2260 fl->decrement_surplus(); |
2261 } |
2261 } |
2262 |
2262 |
2263 void CompactibleFreeListSpace::coalBirth(size_t size) { |
2263 void CompactibleFreeListSpace::coalBirth(size_t size) { |
2264 if (size < SmallForDictionary) { |
2264 if (size < SmallForDictionary) { |
2265 smallCoalBirth(size); |
2265 smallCoalBirth(size); |
2266 } else { |
2266 } else { |
2267 dictionary()->dictCensusUpdate(size, |
2267 dictionary()->dict_census_udpate(size, |
2268 false /* split */, |
2268 false /* split */, |
2269 true /* birth */); |
2269 true /* birth */); |
2270 } |
2270 } |
2271 } |
2271 } |
2272 |
2272 |
2273 void CompactibleFreeListSpace::coalDeath(size_t size) { |
2273 void CompactibleFreeListSpace::coalDeath(size_t size) { |
2274 if(size < SmallForDictionary) { |
2274 if(size < SmallForDictionary) { |
2275 smallCoalDeath(size); |
2275 smallCoalDeath(size); |
2276 } else { |
2276 } else { |
2277 dictionary()->dictCensusUpdate(size, |
2277 dictionary()->dict_census_udpate(size, |
2278 false /* split */, |
2278 false /* split */, |
2279 false /* birth */); |
2279 false /* birth */); |
2280 } |
2280 } |
2281 } |
2281 } |
2282 |
2282 |
2283 void CompactibleFreeListSpace::smallSplitBirth(size_t size) { |
2283 void CompactibleFreeListSpace::smallSplitBirth(size_t size) { |
2284 assert(size < SmallForDictionary, "Size too large for indexed list"); |
2284 assert(size < SmallForDictionary, "Size too large for indexed list"); |
2285 FreeList<FreeChunk> *fl = &_indexedFreeList[size]; |
2285 FreeList<FreeChunk> *fl = &_indexedFreeList[size]; |
2286 fl->increment_splitBirths(); |
2286 fl->increment_split_births(); |
2287 fl->increment_surplus(); |
2287 fl->increment_surplus(); |
2288 } |
2288 } |
2289 |
2289 |
2290 void CompactibleFreeListSpace::smallSplitDeath(size_t size) { |
2290 void CompactibleFreeListSpace::smallSplitDeath(size_t size) { |
2291 assert(size < SmallForDictionary, "Size too large for indexed list"); |
2291 assert(size < SmallForDictionary, "Size too large for indexed list"); |
2292 FreeList<FreeChunk> *fl = &_indexedFreeList[size]; |
2292 FreeList<FreeChunk> *fl = &_indexedFreeList[size]; |
2293 fl->increment_splitDeaths(); |
2293 fl->increment_split_deaths(); |
2294 fl->decrement_surplus(); |
2294 fl->decrement_surplus(); |
2295 } |
2295 } |
2296 |
2296 |
2297 void CompactibleFreeListSpace::splitBirth(size_t size) { |
2297 void CompactibleFreeListSpace::split_birth(size_t size) { |
2298 if (size < SmallForDictionary) { |
2298 if (size < SmallForDictionary) { |
2299 smallSplitBirth(size); |
2299 smallSplitBirth(size); |
2300 } else { |
2300 } else { |
2301 dictionary()->dictCensusUpdate(size, |
2301 dictionary()->dict_census_udpate(size, |
2302 true /* split */, |
2302 true /* split */, |
2303 true /* birth */); |
2303 true /* birth */); |
2304 } |
2304 } |
2305 } |
2305 } |
2306 |
2306 |
2307 void CompactibleFreeListSpace::splitDeath(size_t size) { |
2307 void CompactibleFreeListSpace::splitDeath(size_t size) { |
2308 if (size < SmallForDictionary) { |
2308 if (size < SmallForDictionary) { |
2309 smallSplitDeath(size); |
2309 smallSplitDeath(size); |
2310 } else { |
2310 } else { |
2311 dictionary()->dictCensusUpdate(size, |
2311 dictionary()->dict_census_udpate(size, |
2312 true /* split */, |
2312 true /* split */, |
2313 false /* birth */); |
2313 false /* birth */); |
2314 } |
2314 } |
2315 } |
2315 } |
2316 |
2316 |
2317 void CompactibleFreeListSpace::split(size_t from, size_t to1) { |
2317 void CompactibleFreeListSpace::split(size_t from, size_t to1) { |
2318 size_t to2 = from - to1; |
2318 size_t to2 = from - to1; |
2319 splitDeath(from); |
2319 splitDeath(from); |
2320 splitBirth(to1); |
2320 split_birth(to1); |
2321 splitBirth(to2); |
2321 split_birth(to2); |
2322 } |
2322 } |
2323 |
2323 |
2324 void CompactibleFreeListSpace::print() const { |
2324 void CompactibleFreeListSpace::print() const { |
2325 print_on(tty); |
2325 print_on(tty); |
2326 } |
2326 } |
2518 size_t n = 0; |
2518 size_t n = 0; |
2519 guarantee(((size >= IndexSetStart) && (size % IndexSetStride == 0)) || fc == NULL, |
2519 guarantee(((size >= IndexSetStart) && (size % IndexSetStride == 0)) || fc == NULL, |
2520 "Slot should have been empty"); |
2520 "Slot should have been empty"); |
2521 for (; fc != NULL; fc = fc->next(), n++) { |
2521 for (; fc != NULL; fc = fc->next(), n++) { |
2522 guarantee(fc->size() == size, "Size inconsistency"); |
2522 guarantee(fc->size() == size, "Size inconsistency"); |
2523 guarantee(fc->isFree(), "!free?"); |
2523 guarantee(fc->is_free(), "!free?"); |
2524 guarantee(fc->next() == NULL || fc->next()->prev() == fc, "Broken list"); |
2524 guarantee(fc->next() == NULL || fc->next()->prev() == fc, "Broken list"); |
2525 guarantee((fc->next() == NULL) == (fc == tail), "Incorrect tail"); |
2525 guarantee((fc->next() == NULL) == (fc == tail), "Incorrect tail"); |
2526 } |
2526 } |
2527 guarantee(n == num, "Incorrect count"); |
2527 guarantee(n == num, "Incorrect count"); |
2528 } |
2528 } |
2529 |
2529 |
2530 #ifndef PRODUCT |
2530 #ifndef PRODUCT |
2531 void CompactibleFreeListSpace::check_free_list_consistency() const { |
2531 void CompactibleFreeListSpace::check_free_list_consistency() const { |
2532 assert(_dictionary->minSize() <= IndexSetSize, |
2532 assert(_dictionary->min_size() <= IndexSetSize, |
2533 "Some sizes can't be allocated without recourse to" |
2533 "Some sizes can't be allocated without recourse to" |
2534 " linear allocation buffers"); |
2534 " linear allocation buffers"); |
2535 assert(BinaryTreeDictionary<FreeChunk>::min_tree_chunk_size*HeapWordSize == sizeof(TreeChunk<FreeChunk>), |
2535 assert(BinaryTreeDictionary<FreeChunk>::min_tree_chunk_size*HeapWordSize == sizeof(TreeChunk<FreeChunk>), |
2536 "else MIN_TREE_CHUNK_SIZE is wrong"); |
2536 "else MIN_TREE_CHUNK_SIZE is wrong"); |
2537 assert((IndexSetStride == 2 && IndexSetStart == 4) || // 32-bit |
2537 assert((IndexSetStride == 2 && IndexSetStart == 4) || // 32-bit |
2546 void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const { |
2546 void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const { |
2547 assert_lock_strong(&_freelistLock); |
2547 assert_lock_strong(&_freelistLock); |
2548 FreeList<FreeChunk> total; |
2548 FreeList<FreeChunk> total; |
2549 gclog_or_tty->print("end sweep# " SIZE_FORMAT "\n", sweep_count); |
2549 gclog_or_tty->print("end sweep# " SIZE_FORMAT "\n", sweep_count); |
2550 FreeList<FreeChunk>::print_labels_on(gclog_or_tty, "size"); |
2550 FreeList<FreeChunk>::print_labels_on(gclog_or_tty, "size"); |
2551 size_t totalFree = 0; |
2551 size_t total_free = 0; |
2552 for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { |
2552 for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { |
2553 const FreeList<FreeChunk> *fl = &_indexedFreeList[i]; |
2553 const FreeList<FreeChunk> *fl = &_indexedFreeList[i]; |
2554 totalFree += fl->count() * fl->size(); |
2554 total_free += fl->count() * fl->size(); |
2555 if (i % (40*IndexSetStride) == 0) { |
2555 if (i % (40*IndexSetStride) == 0) { |
2556 FreeList<FreeChunk>::print_labels_on(gclog_or_tty, "size"); |
2556 FreeList<FreeChunk>::print_labels_on(gclog_or_tty, "size"); |
2557 } |
2557 } |
2558 fl->print_on(gclog_or_tty); |
2558 fl->print_on(gclog_or_tty); |
2559 total.set_bfrSurp( total.bfrSurp() + fl->bfrSurp() ); |
2559 total.set_bfr_surp( total.bfr_surp() + fl->bfr_surp() ); |
2560 total.set_surplus( total.surplus() + fl->surplus() ); |
2560 total.set_surplus( total.surplus() + fl->surplus() ); |
2561 total.set_desired( total.desired() + fl->desired() ); |
2561 total.set_desired( total.desired() + fl->desired() ); |
2562 total.set_prevSweep( total.prevSweep() + fl->prevSweep() ); |
2562 total.set_prev_sweep( total.prev_sweep() + fl->prev_sweep() ); |
2563 total.set_beforeSweep(total.beforeSweep() + fl->beforeSweep()); |
2563 total.set_before_sweep(total.before_sweep() + fl->before_sweep()); |
2564 total.set_count( total.count() + fl->count() ); |
2564 total.set_count( total.count() + fl->count() ); |
2565 total.set_coalBirths( total.coalBirths() + fl->coalBirths() ); |
2565 total.set_coal_births( total.coal_births() + fl->coal_births() ); |
2566 total.set_coalDeaths( total.coalDeaths() + fl->coalDeaths() ); |
2566 total.set_coal_deaths( total.coal_deaths() + fl->coal_deaths() ); |
2567 total.set_splitBirths(total.splitBirths() + fl->splitBirths()); |
2567 total.set_split_births(total.split_births() + fl->split_births()); |
2568 total.set_splitDeaths(total.splitDeaths() + fl->splitDeaths()); |
2568 total.set_split_deaths(total.split_deaths() + fl->split_deaths()); |
2569 } |
2569 } |
2570 total.print_on(gclog_or_tty, "TOTAL"); |
2570 total.print_on(gclog_or_tty, "TOTAL"); |
2571 gclog_or_tty->print_cr("Total free in indexed lists " |
2571 gclog_or_tty->print_cr("Total free in indexed lists " |
2572 SIZE_FORMAT " words", totalFree); |
2572 SIZE_FORMAT " words", total_free); |
2573 gclog_or_tty->print("growth: %8.5f deficit: %8.5f\n", |
2573 gclog_or_tty->print("growth: %8.5f deficit: %8.5f\n", |
2574 (double)(total.splitBirths()+total.coalBirths()-total.splitDeaths()-total.coalDeaths())/ |
2574 (double)(total.split_births()+total.coal_births()-total.split_deaths()-total.coal_deaths())/ |
2575 (total.prevSweep() != 0 ? (double)total.prevSweep() : 1.0), |
2575 (total.prev_sweep() != 0 ? (double)total.prev_sweep() : 1.0), |
2576 (double)(total.desired() - total.count())/(total.desired() != 0 ? (double)total.desired() : 1.0)); |
2576 (double)(total.desired() - total.count())/(total.desired() != 0 ? (double)total.desired() : 1.0)); |
2577 _dictionary->printDictCensus(); |
2577 _dictionary->print_dict_census(); |
2578 } |
2578 } |
2579 |
2579 |
2580 /////////////////////////////////////////////////////////////////////////// |
2580 /////////////////////////////////////////////////////////////////////////// |
2581 // CFLS_LAB |
2581 // CFLS_LAB |
2582 /////////////////////////////////////////////////////////////////////////// |
2582 /////////////////////////////////////////////////////////////////////////// |
2641 // Attempt to refill this local free list. |
2641 // Attempt to refill this local free list. |
2642 get_from_global_pool(word_sz, fl); |
2642 get_from_global_pool(word_sz, fl); |
2643 // If it didn't work, give up. |
2643 // If it didn't work, give up. |
2644 if (fl->count() == 0) return NULL; |
2644 if (fl->count() == 0) return NULL; |
2645 } |
2645 } |
2646 res = fl->getChunkAtHead(); |
2646 res = fl->get_chunk_at_head(); |
2647 assert(res != NULL, "Why was count non-zero?"); |
2647 assert(res != NULL, "Why was count non-zero?"); |
2648 } |
2648 } |
2649 res->markNotFree(); |
2649 res->markNotFree(); |
2650 assert(!res->isFree(), "shouldn't be marked free"); |
2650 assert(!res->is_free(), "shouldn't be marked free"); |
2651 assert(oop(res)->klass_or_null() == NULL, "should look uninitialized"); |
2651 assert(oop(res)->klass_or_null() == NULL, "should look uninitialized"); |
2652 // mangle a just allocated object with a distinct pattern. |
2652 // mangle a just allocated object with a distinct pattern. |
2653 debug_only(res->mangleAllocated(word_sz)); |
2653 debug_only(res->mangleAllocated(word_sz)); |
2654 return (HeapWord*)res; |
2654 return (HeapWord*)res; |
2655 } |
2655 } |
2784 if (k > 1) { |
2784 if (k > 1) { |
2785 // Update split death stats for the cur_sz-size blocks list: |
2785 // Update split death stats for the cur_sz-size blocks list: |
2786 // we increment the split death count by the number of blocks |
2786 // we increment the split death count by the number of blocks |
2787 // we just took from the cur_sz-size blocks list and which |
2787 // we just took from the cur_sz-size blocks list and which |
2788 // we will be splitting below. |
2788 // we will be splitting below. |
2789 ssize_t deaths = gfl->splitDeaths() + |
2789 ssize_t deaths = gfl->split_deaths() + |
2790 fl_for_cur_sz.count(); |
2790 fl_for_cur_sz.count(); |
2791 gfl->set_splitDeaths(deaths); |
2791 gfl->set_split_deaths(deaths); |
2792 } |
2792 } |
2793 } |
2793 } |
2794 } |
2794 } |
2795 // Now transfer fl_for_cur_sz to fl. Common case, we hope, is k = 1. |
2795 // Now transfer fl_for_cur_sz to fl. Common case, we hope, is k = 1. |
2796 if (found) { |
2796 if (found) { |
2797 if (k == 1) { |
2797 if (k == 1) { |
2798 fl->prepend(&fl_for_cur_sz); |
2798 fl->prepend(&fl_for_cur_sz); |
2799 } else { |
2799 } else { |
2800 // Divide each block on fl_for_cur_sz up k ways. |
2800 // Divide each block on fl_for_cur_sz up k ways. |
2801 FreeChunk* fc; |
2801 FreeChunk* fc; |
2802 while ((fc = fl_for_cur_sz.getChunkAtHead()) != NULL) { |
2802 while ((fc = fl_for_cur_sz.get_chunk_at_head()) != NULL) { |
2803 // Must do this in reverse order, so that anybody attempting to |
2803 // Must do this in reverse order, so that anybody attempting to |
2804 // access the main chunk sees it as a single free block until we |
2804 // access the main chunk sees it as a single free block until we |
2805 // change it. |
2805 // change it. |
2806 size_t fc_size = fc->size(); |
2806 size_t fc_size = fc->size(); |
2807 assert(fc->isFree(), "Error"); |
2807 assert(fc->is_free(), "Error"); |
2808 for (int i = k-1; i >= 0; i--) { |
2808 for (int i = k-1; i >= 0; i--) { |
2809 FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz); |
2809 FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz); |
2810 assert((i != 0) || |
2810 assert((i != 0) || |
2811 ((fc == ffc) && ffc->isFree() && |
2811 ((fc == ffc) && ffc->is_free() && |
2812 (ffc->size() == k*word_sz) && (fc_size == word_sz)), |
2812 (ffc->size() == k*word_sz) && (fc_size == word_sz)), |
2813 "Counting error"); |
2813 "Counting error"); |
2814 ffc->setSize(word_sz); |
2814 ffc->set_size(word_sz); |
2815 ffc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads. |
2815 ffc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads. |
2816 ffc->linkNext(NULL); |
2816 ffc->link_next(NULL); |
2817 // Above must occur before BOT is updated below. |
2817 // Above must occur before BOT is updated below. |
2818 OrderAccess::storestore(); |
2818 OrderAccess::storestore(); |
2819 // splitting from the right, fc_size == i * word_sz |
2819 // splitting from the right, fc_size == i * word_sz |
2820 _bt.mark_block((HeapWord*)ffc, word_sz, true /* reducing */); |
2820 _bt.mark_block((HeapWord*)ffc, word_sz, true /* reducing */); |
2821 fc_size -= word_sz; |
2821 fc_size -= word_sz; |
2822 assert(fc_size == i*word_sz, "Error"); |
2822 assert(fc_size == i*word_sz, "Error"); |
2823 _bt.verify_not_unallocated((HeapWord*)ffc, word_sz); |
2823 _bt.verify_not_unallocated((HeapWord*)ffc, word_sz); |
2824 _bt.verify_single_block((HeapWord*)fc, fc_size); |
2824 _bt.verify_single_block((HeapWord*)fc, fc_size); |
2825 _bt.verify_single_block((HeapWord*)ffc, word_sz); |
2825 _bt.verify_single_block((HeapWord*)ffc, word_sz); |
2826 // Push this on "fl". |
2826 // Push this on "fl". |
2827 fl->returnChunkAtHead(ffc); |
2827 fl->return_chunk_at_head(ffc); |
2828 } |
2828 } |
2829 // TRAP |
2829 // TRAP |
2830 assert(fl->tail()->next() == NULL, "List invariant."); |
2830 assert(fl->tail()->next() == NULL, "List invariant."); |
2831 } |
2831 } |
2832 } |
2832 } |
2833 // Update birth stats for this block size. |
2833 // Update birth stats for this block size. |
2834 size_t num = fl->count(); |
2834 size_t num = fl->count(); |
2835 MutexLockerEx x(_indexedFreeListParLocks[word_sz], |
2835 MutexLockerEx x(_indexedFreeListParLocks[word_sz], |
2836 Mutex::_no_safepoint_check_flag); |
2836 Mutex::_no_safepoint_check_flag); |
2837 ssize_t births = _indexedFreeList[word_sz].splitBirths() + num; |
2837 ssize_t births = _indexedFreeList[word_sz].split_births() + num; |
2838 _indexedFreeList[word_sz].set_splitBirths(births); |
2838 _indexedFreeList[word_sz].set_split_births(births); |
2839 return; |
2839 return; |
2840 } |
2840 } |
2841 } |
2841 } |
2842 } |
2842 } |
2843 // Otherwise, we'll split a block from the dictionary. |
2843 // Otherwise, we'll split a block from the dictionary. |
2846 size_t rem; |
2846 size_t rem; |
2847 { |
2847 { |
2848 MutexLockerEx x(parDictionaryAllocLock(), |
2848 MutexLockerEx x(parDictionaryAllocLock(), |
2849 Mutex::_no_safepoint_check_flag); |
2849 Mutex::_no_safepoint_check_flag); |
2850 while (n > 0) { |
2850 while (n > 0) { |
2851 fc = dictionary()->getChunk(MAX2(n * word_sz, |
2851 fc = dictionary()->get_chunk(MAX2(n * word_sz, |
2852 _dictionary->minSize()), |
2852 _dictionary->min_size()), |
2853 FreeBlockDictionary<FreeChunk>::atLeast); |
2853 FreeBlockDictionary<FreeChunk>::atLeast); |
2854 if (fc != NULL) { |
2854 if (fc != NULL) { |
2855 _bt.allocated((HeapWord*)fc, fc->size(), true /* reducing */); // update _unallocated_blk |
2855 _bt.allocated((HeapWord*)fc, fc->size(), true /* reducing */); // update _unallocated_blk |
2856 dictionary()->dictCensusUpdate(fc->size(), |
2856 dictionary()->dict_census_udpate(fc->size(), |
2857 true /*split*/, |
2857 true /*split*/, |
2858 false /*birth*/); |
2858 false /*birth*/); |
2859 break; |
2859 break; |
2860 } else { |
2860 } else { |
2861 n--; |
2861 n--; |
2862 } |
2862 } |
2863 } |
2863 } |
2864 if (fc == NULL) return; |
2864 if (fc == NULL) return; |
2865 // Otherwise, split up that block. |
2865 // Otherwise, split up that block. |
2866 assert((ssize_t)n >= 1, "Control point invariant"); |
2866 assert((ssize_t)n >= 1, "Control point invariant"); |
2867 assert(fc->isFree(), "Error: should be a free block"); |
2867 assert(fc->is_free(), "Error: should be a free block"); |
2868 _bt.verify_single_block((HeapWord*)fc, fc->size()); |
2868 _bt.verify_single_block((HeapWord*)fc, fc->size()); |
2869 const size_t nn = fc->size() / word_sz; |
2869 const size_t nn = fc->size() / word_sz; |
2870 n = MIN2(nn, n); |
2870 n = MIN2(nn, n); |
2871 assert((ssize_t)n >= 1, "Control point invariant"); |
2871 assert((ssize_t)n >= 1, "Control point invariant"); |
2872 rem = fc->size() - n * word_sz; |
2872 rem = fc->size() - n * word_sz; |
2893 // may otherwise see the heap as empty. (We're willing to take that |
2893 // may otherwise see the heap as empty. (We're willing to take that |
2894 // hit if the block is a small block.) |
2894 // hit if the block is a small block.) |
2895 if (rem > 0) { |
2895 if (rem > 0) { |
2896 size_t prefix_size = n * word_sz; |
2896 size_t prefix_size = n * word_sz; |
2897 rem_fc = (FreeChunk*)((HeapWord*)fc + prefix_size); |
2897 rem_fc = (FreeChunk*)((HeapWord*)fc + prefix_size); |
2898 rem_fc->setSize(rem); |
2898 rem_fc->set_size(rem); |
2899 rem_fc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads. |
2899 rem_fc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads. |
2900 rem_fc->linkNext(NULL); |
2900 rem_fc->link_next(NULL); |
2901 // Above must occur before BOT is updated below. |
2901 // Above must occur before BOT is updated below. |
2902 assert((ssize_t)n > 0 && prefix_size > 0 && rem_fc > fc, "Error"); |
2902 assert((ssize_t)n > 0 && prefix_size > 0 && rem_fc > fc, "Error"); |
2903 OrderAccess::storestore(); |
2903 OrderAccess::storestore(); |
2904 _bt.split_block((HeapWord*)fc, fc->size(), prefix_size); |
2904 _bt.split_block((HeapWord*)fc, fc->size(), prefix_size); |
2905 assert(fc->isFree(), "Error"); |
2905 assert(fc->is_free(), "Error"); |
2906 fc->setSize(prefix_size); |
2906 fc->set_size(prefix_size); |
2907 if (rem >= IndexSetSize) { |
2907 if (rem >= IndexSetSize) { |
2908 returnChunkToDictionary(rem_fc); |
2908 returnChunkToDictionary(rem_fc); |
2909 dictionary()->dictCensusUpdate(rem, true /*split*/, true /*birth*/); |
2909 dictionary()->dict_census_udpate(rem, true /*split*/, true /*birth*/); |
2910 rem_fc = NULL; |
2910 rem_fc = NULL; |
2911 } |
2911 } |
2912 // Otherwise, return it to the small list below. |
2912 // Otherwise, return it to the small list below. |
2913 } |
2913 } |
2914 } |
2914 } |
2915 if (rem_fc != NULL) { |
2915 if (rem_fc != NULL) { |
2916 MutexLockerEx x(_indexedFreeListParLocks[rem], |
2916 MutexLockerEx x(_indexedFreeListParLocks[rem], |
2917 Mutex::_no_safepoint_check_flag); |
2917 Mutex::_no_safepoint_check_flag); |
2918 _bt.verify_not_unallocated((HeapWord*)rem_fc, rem_fc->size()); |
2918 _bt.verify_not_unallocated((HeapWord*)rem_fc, rem_fc->size()); |
2919 _indexedFreeList[rem].returnChunkAtHead(rem_fc); |
2919 _indexedFreeList[rem].return_chunk_at_head(rem_fc); |
2920 smallSplitBirth(rem); |
2920 smallSplitBirth(rem); |
2921 } |
2921 } |
2922 assert((ssize_t)n > 0 && fc != NULL, "Consistency"); |
2922 assert((ssize_t)n > 0 && fc != NULL, "Consistency"); |
2923 // Now do the splitting up. |
2923 // Now do the splitting up. |
2924 // Must do this in reverse order, so that anybody attempting to |
2924 // Must do this in reverse order, so that anybody attempting to |
2926 // change it. |
2926 // change it. |
2927 size_t fc_size = n * word_sz; |
2927 size_t fc_size = n * word_sz; |
2928 // All but first chunk in this loop |
2928 // All but first chunk in this loop |
2929 for (ssize_t i = n-1; i > 0; i--) { |
2929 for (ssize_t i = n-1; i > 0; i--) { |
2930 FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz); |
2930 FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz); |
2931 ffc->setSize(word_sz); |
2931 ffc->set_size(word_sz); |
2932 ffc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads. |
2932 ffc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads. |
2933 ffc->linkNext(NULL); |
2933 ffc->link_next(NULL); |
2934 // Above must occur before BOT is updated below. |
2934 // Above must occur before BOT is updated below. |
2935 OrderAccess::storestore(); |
2935 OrderAccess::storestore(); |
2936 // splitting from the right, fc_size == (n - i + 1) * wordsize |
2936 // splitting from the right, fc_size == (n - i + 1) * wordsize |
2937 _bt.mark_block((HeapWord*)ffc, word_sz, true /* reducing */); |
2937 _bt.mark_block((HeapWord*)ffc, word_sz, true /* reducing */); |
2938 fc_size -= word_sz; |
2938 fc_size -= word_sz; |
2939 _bt.verify_not_unallocated((HeapWord*)ffc, ffc->size()); |
2939 _bt.verify_not_unallocated((HeapWord*)ffc, ffc->size()); |
2940 _bt.verify_single_block((HeapWord*)ffc, ffc->size()); |
2940 _bt.verify_single_block((HeapWord*)ffc, ffc->size()); |
2941 _bt.verify_single_block((HeapWord*)fc, fc_size); |
2941 _bt.verify_single_block((HeapWord*)fc, fc_size); |
2942 // Push this on "fl". |
2942 // Push this on "fl". |
2943 fl->returnChunkAtHead(ffc); |
2943 fl->return_chunk_at_head(ffc); |
2944 } |
2944 } |
2945 // First chunk |
2945 // First chunk |
2946 assert(fc->isFree() && fc->size() == n*word_sz, "Error: should still be a free block"); |
2946 assert(fc->is_free() && fc->size() == n*word_sz, "Error: should still be a free block"); |
2947 // The blocks above should show their new sizes before the first block below |
2947 // The blocks above should show their new sizes before the first block below |
2948 fc->setSize(word_sz); |
2948 fc->set_size(word_sz); |
2949 fc->linkPrev(NULL); // idempotent wrt free-ness, see assert above |
2949 fc->link_prev(NULL); // idempotent wrt free-ness, see assert above |
2950 fc->linkNext(NULL); |
2950 fc->link_next(NULL); |
2951 _bt.verify_not_unallocated((HeapWord*)fc, fc->size()); |
2951 _bt.verify_not_unallocated((HeapWord*)fc, fc->size()); |
2952 _bt.verify_single_block((HeapWord*)fc, fc->size()); |
2952 _bt.verify_single_block((HeapWord*)fc, fc->size()); |
2953 fl->returnChunkAtHead(fc); |
2953 fl->return_chunk_at_head(fc); |
2954 |
2954 |
2955 assert((ssize_t)n > 0 && (ssize_t)n == fl->count(), "Incorrect number of blocks"); |
2955 assert((ssize_t)n > 0 && (ssize_t)n == fl->count(), "Incorrect number of blocks"); |
2956 { |
2956 { |
2957 // Update the stats for this block size. |
2957 // Update the stats for this block size. |
2958 MutexLockerEx x(_indexedFreeListParLocks[word_sz], |
2958 MutexLockerEx x(_indexedFreeListParLocks[word_sz], |
2959 Mutex::_no_safepoint_check_flag); |
2959 Mutex::_no_safepoint_check_flag); |
2960 const ssize_t births = _indexedFreeList[word_sz].splitBirths() + n; |
2960 const ssize_t births = _indexedFreeList[word_sz].split_births() + n; |
2961 _indexedFreeList[word_sz].set_splitBirths(births); |
2961 _indexedFreeList[word_sz].set_split_births(births); |
2962 // ssize_t new_surplus = _indexedFreeList[word_sz].surplus() + n; |
2962 // ssize_t new_surplus = _indexedFreeList[word_sz].surplus() + n; |
2963 // _indexedFreeList[word_sz].set_surplus(new_surplus); |
2963 // _indexedFreeList[word_sz].set_surplus(new_surplus); |
2964 } |
2964 } |
2965 |
2965 |
2966 // TRAP |
2966 // TRAP |