67 } |
67 } |
68 |
68 |
69 // Constructor |
69 // Constructor |
70 CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, |
70 CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, |
71 MemRegion mr, bool use_adaptive_freelists, |
71 MemRegion mr, bool use_adaptive_freelists, |
72 FreeBlockDictionary::DictionaryChoice dictionaryChoice) : |
72 FreeBlockDictionary<FreeChunk>::DictionaryChoice dictionaryChoice) : |
73 _dictionaryChoice(dictionaryChoice), |
73 _dictionaryChoice(dictionaryChoice), |
74 _adaptive_freelists(use_adaptive_freelists), |
74 _adaptive_freelists(use_adaptive_freelists), |
75 _bt(bs, mr), |
75 _bt(bs, mr), |
76 // free list locks are in the range of values taken by _lockRank |
76 // free list locks are in the range of values taken by _lockRank |
77 // This range currently is [_leaf+2, _leaf+3] |
77 // This range currently is [_leaf+2, _leaf+3] |
85 CMSRescanMultiple), |
85 CMSRescanMultiple), |
86 _marking_task_size(CardTableModRefBS::card_size_in_words * BitsPerWord * |
86 _marking_task_size(CardTableModRefBS::card_size_in_words * BitsPerWord * |
87 CMSConcMarkMultiple), |
87 CMSConcMarkMultiple), |
88 _collector(NULL) |
88 _collector(NULL) |
89 { |
89 { |
|
90 assert(sizeof(FreeChunk) / BytesPerWord <= MinChunkSize, |
|
91 "FreeChunk is larger than expected"); |
90 _bt.set_space(this); |
92 _bt.set_space(this); |
91 initialize(mr, SpaceDecorator::Clear, SpaceDecorator::Mangle); |
93 initialize(mr, SpaceDecorator::Clear, SpaceDecorator::Mangle); |
92 // We have all of "mr", all of which we place in the dictionary |
94 // We have all of "mr", all of which we place in the dictionary |
93 // as one big chunk. We'll need to decide here which of several |
95 // as one big chunk. We'll need to decide here which of several |
94 // possible alternative dictionary implementations to use. For |
96 // possible alternative dictionary implementations to use. For |
95 // now the choice is easy, since we have only one working |
97 // now the choice is easy, since we have only one working |
96 // implementation, namely, the simple binary tree (splaying |
98 // implementation, namely, the simple binary tree (splaying |
97 // temporarily disabled). |
99 // temporarily disabled). |
98 switch (dictionaryChoice) { |
100 switch (dictionaryChoice) { |
99 case FreeBlockDictionary::dictionarySplayTree: |
101 case FreeBlockDictionary<FreeChunk>::dictionarySplayTree: |
100 case FreeBlockDictionary::dictionarySkipList: |
102 case FreeBlockDictionary<FreeChunk>::dictionarySkipList: |
101 default: |
103 default: |
102 warning("dictionaryChoice: selected option not understood; using" |
104 warning("dictionaryChoice: selected option not understood; using" |
103 " default BinaryTreeDictionary implementation instead."); |
105 " default BinaryTreeDictionary implementation instead."); |
104 case FreeBlockDictionary::dictionaryBinaryTree: |
106 case FreeBlockDictionary<FreeChunk>::dictionaryBinaryTree: |
105 _dictionary = new BinaryTreeDictionary(mr); |
107 _dictionary = new BinaryTreeDictionary<FreeChunk>(mr, use_adaptive_freelists); |
106 break; |
108 break; |
107 } |
109 } |
108 assert(_dictionary != NULL, "CMS dictionary initialization"); |
110 assert(_dictionary != NULL, "CMS dictionary initialization"); |
109 // The indexed free lists are initially all empty and are lazily |
111 // The indexed free lists are initially all empty and are lazily |
110 // filled in on demand. Initialize the array elements to NULL. |
112 // filled in on demand. Initialize the array elements to NULL. |
446 void CompactibleFreeListSpace::print_indexed_free_lists(outputStream* st) |
448 void CompactibleFreeListSpace::print_indexed_free_lists(outputStream* st) |
447 const { |
449 const { |
448 reportIndexedFreeListStatistics(); |
450 reportIndexedFreeListStatistics(); |
449 gclog_or_tty->print_cr("Layout of Indexed Freelists"); |
451 gclog_or_tty->print_cr("Layout of Indexed Freelists"); |
450 gclog_or_tty->print_cr("---------------------------"); |
452 gclog_or_tty->print_cr("---------------------------"); |
451 FreeList::print_labels_on(st, "size"); |
453 FreeList<FreeChunk>::print_labels_on(st, "size"); |
452 for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { |
454 for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { |
453 _indexedFreeList[i].print_on(gclog_or_tty); |
455 _indexedFreeList[i].print_on(gclog_or_tty); |
454 for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL; |
456 for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL; |
455 fc = fc->next()) { |
457 fc = fc->next()) { |
456 gclog_or_tty->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ") %s", |
458 gclog_or_tty->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ") %s", |
1329 |
1331 |
1330 size_t i; |
1332 size_t i; |
1331 size_t currSize = numWords + MinChunkSize; |
1333 size_t currSize = numWords + MinChunkSize; |
1332 assert(currSize % MinObjAlignment == 0, "currSize should be aligned"); |
1334 assert(currSize % MinObjAlignment == 0, "currSize should be aligned"); |
1333 for (i = currSize; i < IndexSetSize; i += IndexSetStride) { |
1335 for (i = currSize; i < IndexSetSize; i += IndexSetStride) { |
1334 FreeList* fl = &_indexedFreeList[i]; |
1336 FreeList<FreeChunk>* fl = &_indexedFreeList[i]; |
1335 if (fl->head()) { |
1337 if (fl->head()) { |
1336 ret = getFromListGreater(fl, numWords); |
1338 ret = getFromListGreater(fl, numWords); |
1337 assert(ret == NULL || ret->isFree(), "Should be returning a free chunk"); |
1339 assert(ret == NULL || ret->isFree(), "Should be returning a free chunk"); |
1338 return ret; |
1340 return ret; |
1339 } |
1341 } |
1712 // adjust _unallocated_block downward, as necessary |
1714 // adjust _unallocated_block downward, as necessary |
1713 _bt.freed((HeapWord*)chunk, size); |
1715 _bt.freed((HeapWord*)chunk, size); |
1714 _dictionary->returnChunk(chunk); |
1716 _dictionary->returnChunk(chunk); |
1715 #ifndef PRODUCT |
1717 #ifndef PRODUCT |
1716 if (CMSCollector::abstract_state() != CMSCollector::Sweeping) { |
1718 if (CMSCollector::abstract_state() != CMSCollector::Sweeping) { |
1717 TreeChunk::as_TreeChunk(chunk)->list()->verify_stats(); |
1719 TreeChunk<FreeChunk>::as_TreeChunk(chunk)->list()->verify_stats(); |
1718 } |
1720 } |
1719 #endif // PRODUCT |
1721 #endif // PRODUCT |
1720 } |
1722 } |
1721 |
1723 |
1722 void |
1724 void |
1860 /* A hint is the next larger size that has a surplus. |
1862 /* A hint is the next larger size that has a surplus. |
1861 Start search at a size large enough to guarantee that |
1863 Start search at a size large enough to guarantee that |
1862 the excess is >= MIN_CHUNK. */ |
1864 the excess is >= MIN_CHUNK. */ |
1863 size_t start = align_object_size(numWords + MinChunkSize); |
1865 size_t start = align_object_size(numWords + MinChunkSize); |
1864 if (start < IndexSetSize) { |
1866 if (start < IndexSetSize) { |
1865 FreeList* it = _indexedFreeList; |
1867 FreeList<FreeChunk>* it = _indexedFreeList; |
1866 size_t hint = _indexedFreeList[start].hint(); |
1868 size_t hint = _indexedFreeList[start].hint(); |
1867 while (hint < IndexSetSize) { |
1869 while (hint < IndexSetSize) { |
1868 assert(hint % MinObjAlignment == 0, "hint should be aligned"); |
1870 assert(hint % MinObjAlignment == 0, "hint should be aligned"); |
1869 FreeList *fl = &_indexedFreeList[hint]; |
1871 FreeList<FreeChunk> *fl = &_indexedFreeList[hint]; |
1870 if (fl->surplus() > 0 && fl->head() != NULL) { |
1872 if (fl->surplus() > 0 && fl->head() != NULL) { |
1871 // Found a list with surplus, reset original hint |
1873 // Found a list with surplus, reset original hint |
1872 // and split out a free chunk which is returned. |
1874 // and split out a free chunk which is returned. |
1873 _indexedFreeList[start].set_hint(hint); |
1875 _indexedFreeList[start].set_hint(hint); |
1874 FreeChunk* res = getFromListGreater(fl, numWords); |
1876 FreeChunk* res = getFromListGreater(fl, numWords); |
1883 } |
1885 } |
1884 return NULL; |
1886 return NULL; |
1885 } |
1887 } |
1886 |
1888 |
1887 /* Requires fl->size >= numWords + MinChunkSize */ |
1889 /* Requires fl->size >= numWords + MinChunkSize */ |
1888 FreeChunk* CompactibleFreeListSpace::getFromListGreater(FreeList* fl, |
1890 FreeChunk* CompactibleFreeListSpace::getFromListGreater(FreeList<FreeChunk>* fl, |
1889 size_t numWords) { |
1891 size_t numWords) { |
1890 FreeChunk *curr = fl->head(); |
1892 FreeChunk *curr = fl->head(); |
1891 size_t oldNumWords = curr->size(); |
1893 size_t oldNumWords = curr->size(); |
1892 assert(numWords >= MinChunkSize, "Word size is too small"); |
1894 assert(numWords >= MinChunkSize, "Word size is too small"); |
1893 assert(curr != NULL, "List is empty"); |
1895 assert(curr != NULL, "List is empty"); |
2165 float inter_sweep_estimate, |
2167 float inter_sweep_estimate, |
2166 float intra_sweep_estimate) { |
2168 float intra_sweep_estimate) { |
2167 assert_locked(); |
2169 assert_locked(); |
2168 size_t i; |
2170 size_t i; |
2169 for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { |
2171 for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { |
2170 FreeList* fl = &_indexedFreeList[i]; |
2172 FreeList<FreeChunk>* fl = &_indexedFreeList[i]; |
2171 if (PrintFLSStatistics > 1) { |
2173 if (PrintFLSStatistics > 1) { |
2172 gclog_or_tty->print("size[%d] : ", i); |
2174 gclog_or_tty->print("size[%d] : ", i); |
2173 } |
2175 } |
2174 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); |
2175 fl->set_coalDesired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent)); |
2177 fl->set_coalDesired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent)); |
2184 |
2186 |
2185 void CompactibleFreeListSpace::setFLSurplus() { |
2187 void CompactibleFreeListSpace::setFLSurplus() { |
2186 assert_locked(); |
2188 assert_locked(); |
2187 size_t i; |
2189 size_t i; |
2188 for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { |
2190 for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { |
2189 FreeList *fl = &_indexedFreeList[i]; |
2191 FreeList<FreeChunk> *fl = &_indexedFreeList[i]; |
2190 fl->set_surplus(fl->count() - |
2192 fl->set_surplus(fl->count() - |
2191 (ssize_t)((double)fl->desired() * CMSSmallSplitSurplusPercent)); |
2193 (ssize_t)((double)fl->desired() * CMSSmallSplitSurplusPercent)); |
2192 } |
2194 } |
2193 } |
2195 } |
2194 |
2196 |
2195 void CompactibleFreeListSpace::setFLHints() { |
2197 void CompactibleFreeListSpace::setFLHints() { |
2196 assert_locked(); |
2198 assert_locked(); |
2197 size_t i; |
2199 size_t i; |
2198 size_t h = IndexSetSize; |
2200 size_t h = IndexSetSize; |
2199 for (i = IndexSetSize - 1; i != 0; i -= IndexSetStride) { |
2201 for (i = IndexSetSize - 1; i != 0; i -= IndexSetStride) { |
2200 FreeList *fl = &_indexedFreeList[i]; |
2202 FreeList<FreeChunk> *fl = &_indexedFreeList[i]; |
2201 fl->set_hint(h); |
2203 fl->set_hint(h); |
2202 if (fl->surplus() > 0) { |
2204 if (fl->surplus() > 0) { |
2203 h = i; |
2205 h = i; |
2204 } |
2206 } |
2205 } |
2207 } |
2207 |
2209 |
2208 void CompactibleFreeListSpace::clearFLCensus() { |
2210 void CompactibleFreeListSpace::clearFLCensus() { |
2209 assert_locked(); |
2211 assert_locked(); |
2210 size_t i; |
2212 size_t i; |
2211 for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { |
2213 for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { |
2212 FreeList *fl = &_indexedFreeList[i]; |
2214 FreeList<FreeChunk> *fl = &_indexedFreeList[i]; |
2213 fl->set_prevSweep(fl->count()); |
2215 fl->set_prevSweep(fl->count()); |
2214 fl->set_coalBirths(0); |
2216 fl->set_coalBirths(0); |
2215 fl->set_coalDeaths(0); |
2217 fl->set_coalDeaths(0); |
2216 fl->set_splitBirths(0); |
2218 fl->set_splitBirths(0); |
2217 fl->set_splitDeaths(0); |
2219 fl->set_splitDeaths(0); |
2234 _dictionary->endSweepDictCensus(CMSLargeSplitSurplusPercent); |
2236 _dictionary->endSweepDictCensus(CMSLargeSplitSurplusPercent); |
2235 } |
2237 } |
2236 |
2238 |
2237 bool CompactibleFreeListSpace::coalOverPopulated(size_t size) { |
2239 bool CompactibleFreeListSpace::coalOverPopulated(size_t size) { |
2238 if (size < SmallForDictionary) { |
2240 if (size < SmallForDictionary) { |
2239 FreeList *fl = &_indexedFreeList[size]; |
2241 FreeList<FreeChunk> *fl = &_indexedFreeList[size]; |
2240 return (fl->coalDesired() < 0) || |
2242 return (fl->coalDesired() < 0) || |
2241 ((int)fl->count() > fl->coalDesired()); |
2243 ((int)fl->count() > fl->coalDesired()); |
2242 } else { |
2244 } else { |
2243 return dictionary()->coalDictOverPopulated(size); |
2245 return dictionary()->coalDictOverPopulated(size); |
2244 } |
2246 } |
2245 } |
2247 } |
2246 |
2248 |
2247 void CompactibleFreeListSpace::smallCoalBirth(size_t size) { |
2249 void CompactibleFreeListSpace::smallCoalBirth(size_t size) { |
2248 assert(size < SmallForDictionary, "Size too large for indexed list"); |
2250 assert(size < SmallForDictionary, "Size too large for indexed list"); |
2249 FreeList *fl = &_indexedFreeList[size]; |
2251 FreeList<FreeChunk> *fl = &_indexedFreeList[size]; |
2250 fl->increment_coalBirths(); |
2252 fl->increment_coalBirths(); |
2251 fl->increment_surplus(); |
2253 fl->increment_surplus(); |
2252 } |
2254 } |
2253 |
2255 |
2254 void CompactibleFreeListSpace::smallCoalDeath(size_t size) { |
2256 void CompactibleFreeListSpace::smallCoalDeath(size_t size) { |
2255 assert(size < SmallForDictionary, "Size too large for indexed list"); |
2257 assert(size < SmallForDictionary, "Size too large for indexed list"); |
2256 FreeList *fl = &_indexedFreeList[size]; |
2258 FreeList<FreeChunk> *fl = &_indexedFreeList[size]; |
2257 fl->increment_coalDeaths(); |
2259 fl->increment_coalDeaths(); |
2258 fl->decrement_surplus(); |
2260 fl->decrement_surplus(); |
2259 } |
2261 } |
2260 |
2262 |
2261 void CompactibleFreeListSpace::coalBirth(size_t size) { |
2263 void CompactibleFreeListSpace::coalBirth(size_t size) { |
2278 } |
2280 } |
2279 } |
2281 } |
2280 |
2282 |
2281 void CompactibleFreeListSpace::smallSplitBirth(size_t size) { |
2283 void CompactibleFreeListSpace::smallSplitBirth(size_t size) { |
2282 assert(size < SmallForDictionary, "Size too large for indexed list"); |
2284 assert(size < SmallForDictionary, "Size too large for indexed list"); |
2283 FreeList *fl = &_indexedFreeList[size]; |
2285 FreeList<FreeChunk> *fl = &_indexedFreeList[size]; |
2284 fl->increment_splitBirths(); |
2286 fl->increment_splitBirths(); |
2285 fl->increment_surplus(); |
2287 fl->increment_surplus(); |
2286 } |
2288 } |
2287 |
2289 |
2288 void CompactibleFreeListSpace::smallSplitDeath(size_t size) { |
2290 void CompactibleFreeListSpace::smallSplitDeath(size_t size) { |
2289 assert(size < SmallForDictionary, "Size too large for indexed list"); |
2291 assert(size < SmallForDictionary, "Size too large for indexed list"); |
2290 FreeList *fl = &_indexedFreeList[size]; |
2292 FreeList<FreeChunk> *fl = &_indexedFreeList[size]; |
2291 fl->increment_splitDeaths(); |
2293 fl->increment_splitDeaths(); |
2292 fl->decrement_surplus(); |
2294 fl->decrement_surplus(); |
2293 } |
2295 } |
2294 |
2296 |
2295 void CompactibleFreeListSpace::splitBirth(size_t size) { |
2297 void CompactibleFreeListSpace::splitBirth(size_t size) { |
2528 #ifndef PRODUCT |
2530 #ifndef PRODUCT |
2529 void CompactibleFreeListSpace::check_free_list_consistency() const { |
2531 void CompactibleFreeListSpace::check_free_list_consistency() const { |
2530 assert(_dictionary->minSize() <= IndexSetSize, |
2532 assert(_dictionary->minSize() <= IndexSetSize, |
2531 "Some sizes can't be allocated without recourse to" |
2533 "Some sizes can't be allocated without recourse to" |
2532 " linear allocation buffers"); |
2534 " linear allocation buffers"); |
2533 assert(MIN_TREE_CHUNK_SIZE*HeapWordSize == sizeof(TreeChunk), |
2535 assert(BinaryTreeDictionary<FreeChunk>::min_tree_chunk_size*HeapWordSize == sizeof(TreeChunk<FreeChunk>), |
2534 "else MIN_TREE_CHUNK_SIZE is wrong"); |
2536 "else MIN_TREE_CHUNK_SIZE is wrong"); |
2535 assert((IndexSetStride == 2 && IndexSetStart == 4) || // 32-bit |
2537 assert((IndexSetStride == 2 && IndexSetStart == 4) || // 32-bit |
2536 (IndexSetStride == 1 && IndexSetStart == 3), "just checking"); // 64-bit |
2538 (IndexSetStride == 1 && IndexSetStart == 3), "just checking"); // 64-bit |
2537 assert((IndexSetStride != 2) || (IndexSetStart % 2 == 0), |
2539 assert((IndexSetStride != 2) || (IndexSetStart % 2 == 0), |
2538 "Some for-loops may be incorrectly initialized"); |
2540 "Some for-loops may be incorrectly initialized"); |
2541 } |
2543 } |
2542 #endif |
2544 #endif |
2543 |
2545 |
2544 void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const { |
2546 void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const { |
2545 assert_lock_strong(&_freelistLock); |
2547 assert_lock_strong(&_freelistLock); |
2546 FreeList total; |
2548 FreeList<FreeChunk> total; |
2547 gclog_or_tty->print("end sweep# " SIZE_FORMAT "\n", sweep_count); |
2549 gclog_or_tty->print("end sweep# " SIZE_FORMAT "\n", sweep_count); |
2548 FreeList::print_labels_on(gclog_or_tty, "size"); |
2550 FreeList<FreeChunk>::print_labels_on(gclog_or_tty, "size"); |
2549 size_t totalFree = 0; |
2551 size_t totalFree = 0; |
2550 for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { |
2552 for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { |
2551 const FreeList *fl = &_indexedFreeList[i]; |
2553 const FreeList<FreeChunk> *fl = &_indexedFreeList[i]; |
2552 totalFree += fl->count() * fl->size(); |
2554 totalFree += fl->count() * fl->size(); |
2553 if (i % (40*IndexSetStride) == 0) { |
2555 if (i % (40*IndexSetStride) == 0) { |
2554 FreeList::print_labels_on(gclog_or_tty, "size"); |
2556 FreeList<FreeChunk>::print_labels_on(gclog_or_tty, "size"); |
2555 } |
2557 } |
2556 fl->print_on(gclog_or_tty); |
2558 fl->print_on(gclog_or_tty); |
2557 total.set_bfrSurp( total.bfrSurp() + fl->bfrSurp() ); |
2559 total.set_bfrSurp( total.bfrSurp() + fl->bfrSurp() ); |
2558 total.set_surplus( total.surplus() + fl->surplus() ); |
2560 total.set_surplus( total.surplus() + fl->surplus() ); |
2559 total.set_desired( total.desired() + fl->desired() ); |
2561 total.set_desired( total.desired() + fl->desired() ); |
2632 MutexLockerEx x(_cfls->parDictionaryAllocLock(), |
2634 MutexLockerEx x(_cfls->parDictionaryAllocLock(), |
2633 Mutex::_no_safepoint_check_flag); |
2635 Mutex::_no_safepoint_check_flag); |
2634 res = _cfls->getChunkFromDictionaryExact(word_sz); |
2636 res = _cfls->getChunkFromDictionaryExact(word_sz); |
2635 if (res == NULL) return NULL; |
2637 if (res == NULL) return NULL; |
2636 } else { |
2638 } else { |
2637 FreeList* fl = &_indexedFreeList[word_sz]; |
2639 FreeList<FreeChunk>* fl = &_indexedFreeList[word_sz]; |
2638 if (fl->count() == 0) { |
2640 if (fl->count() == 0) { |
2639 // Attempt to refill this local free list. |
2641 // Attempt to refill this local free list. |
2640 get_from_global_pool(word_sz, fl); |
2642 get_from_global_pool(word_sz, fl); |
2641 // If it didn't work, give up. |
2643 // If it didn't work, give up. |
2642 if (fl->count() == 0) return NULL; |
2644 if (fl->count() == 0) return NULL; |
2652 return (HeapWord*)res; |
2654 return (HeapWord*)res; |
2653 } |
2655 } |
2654 |
2656 |
2655 // Get a chunk of blocks of the right size and update related |
2657 // Get a chunk of blocks of the right size and update related |
2656 // book-keeping stats |
2658 // book-keeping stats |
2657 void CFLS_LAB::get_from_global_pool(size_t word_sz, FreeList* fl) { |
2659 void CFLS_LAB::get_from_global_pool(size_t word_sz, FreeList<FreeChunk>* fl) { |
2658 // Get the #blocks we want to claim |
2660 // Get the #blocks we want to claim |
2659 size_t n_blks = (size_t)_blocks_to_claim[word_sz].average(); |
2661 size_t n_blks = (size_t)_blocks_to_claim[word_sz].average(); |
2660 assert(n_blks > 0, "Error"); |
2662 assert(n_blks > 0, "Error"); |
2661 assert(ResizePLAB || n_blks == OldPLABSize, "Error"); |
2663 assert(ResizePLAB || n_blks == OldPLABSize, "Error"); |
2662 // In some cases, when the application has a phase change, |
2664 // In some cases, when the application has a phase change, |
2734 _global_num_workers[i]++; |
2736 _global_num_workers[i]++; |
2735 assert(_global_num_workers[i] <= ParallelGCThreads, "Too big"); |
2737 assert(_global_num_workers[i] <= ParallelGCThreads, "Too big"); |
2736 if (num_retire > 0) { |
2738 if (num_retire > 0) { |
2737 _cfls->_indexedFreeList[i].prepend(&_indexedFreeList[i]); |
2739 _cfls->_indexedFreeList[i].prepend(&_indexedFreeList[i]); |
2738 // Reset this list. |
2740 // Reset this list. |
2739 _indexedFreeList[i] = FreeList(); |
2741 _indexedFreeList[i] = FreeList<FreeChunk>(); |
2740 _indexedFreeList[i].set_size(i); |
2742 _indexedFreeList[i].set_size(i); |
2741 } |
2743 } |
2742 } |
2744 } |
2743 if (PrintOldPLAB) { |
2745 if (PrintOldPLAB) { |
2744 gclog_or_tty->print_cr("%d[%d]: %d/%d/%d", |
2746 gclog_or_tty->print_cr("%d[%d]: %d/%d/%d", |
2748 _num_blocks[i] = 0; |
2750 _num_blocks[i] = 0; |
2749 } |
2751 } |
2750 } |
2752 } |
2751 } |
2753 } |
2752 |
2754 |
2753 void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl) { |
2755 void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList<FreeChunk>* fl) { |
2754 assert(fl->count() == 0, "Precondition."); |
2756 assert(fl->count() == 0, "Precondition."); |
2755 assert(word_sz < CompactibleFreeListSpace::IndexSetSize, |
2757 assert(word_sz < CompactibleFreeListSpace::IndexSetSize, |
2756 "Precondition"); |
2758 "Precondition"); |
2757 |
2759 |
2758 // We'll try all multiples of word_sz in the indexed set, starting with |
2760 // We'll try all multiples of word_sz in the indexed set, starting with |
2764 size_t cur_sz; |
2766 size_t cur_sz; |
2765 for (k = 1, cur_sz = k * word_sz, found = false; |
2767 for (k = 1, cur_sz = k * word_sz, found = false; |
2766 (cur_sz < CompactibleFreeListSpace::IndexSetSize) && |
2768 (cur_sz < CompactibleFreeListSpace::IndexSetSize) && |
2767 (CMSSplitIndexedFreeListBlocks || k <= 1); |
2769 (CMSSplitIndexedFreeListBlocks || k <= 1); |
2768 k++, cur_sz = k * word_sz) { |
2770 k++, cur_sz = k * word_sz) { |
2769 FreeList fl_for_cur_sz; // Empty. |
2771 FreeList<FreeChunk> fl_for_cur_sz; // Empty. |
2770 fl_for_cur_sz.set_size(cur_sz); |
2772 fl_for_cur_sz.set_size(cur_sz); |
2771 { |
2773 { |
2772 MutexLockerEx x(_indexedFreeListParLocks[cur_sz], |
2774 MutexLockerEx x(_indexedFreeListParLocks[cur_sz], |
2773 Mutex::_no_safepoint_check_flag); |
2775 Mutex::_no_safepoint_check_flag); |
2774 FreeList* gfl = &_indexedFreeList[cur_sz]; |
2776 FreeList<FreeChunk>* gfl = &_indexedFreeList[cur_sz]; |
2775 if (gfl->count() != 0) { |
2777 if (gfl->count() != 0) { |
2776 // nn is the number of chunks of size cur_sz that |
2778 // nn is the number of chunks of size cur_sz that |
2777 // we'd need to split k-ways each, in order to create |
2779 // we'd need to split k-ways each, in order to create |
2778 // "n" chunks of size word_sz each. |
2780 // "n" chunks of size word_sz each. |
2779 const size_t nn = MAX2(n/k, (size_t)1); |
2781 const size_t nn = MAX2(n/k, (size_t)1); |
2846 MutexLockerEx x(parDictionaryAllocLock(), |
2848 MutexLockerEx x(parDictionaryAllocLock(), |
2847 Mutex::_no_safepoint_check_flag); |
2849 Mutex::_no_safepoint_check_flag); |
2848 while (n > 0) { |
2850 while (n > 0) { |
2849 fc = dictionary()->getChunk(MAX2(n * word_sz, |
2851 fc = dictionary()->getChunk(MAX2(n * word_sz, |
2850 _dictionary->minSize()), |
2852 _dictionary->minSize()), |
2851 FreeBlockDictionary::atLeast); |
2853 FreeBlockDictionary<FreeChunk>::atLeast); |
2852 if (fc != NULL) { |
2854 if (fc != NULL) { |
2853 _bt.allocated((HeapWord*)fc, fc->size(), true /* reducing */); // update _unallocated_blk |
2855 _bt.allocated((HeapWord*)fc, fc->size(), true /* reducing */); // update _unallocated_blk |
2854 dictionary()->dictCensusUpdate(fc->size(), |
2856 dictionary()->dictCensusUpdate(fc->size(), |
2855 true /*split*/, |
2857 true /*split*/, |
2856 false /*birth*/); |
2858 false /*birth*/); |