comparison src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp @ 6885:685df3c6f84b

7045397: NPG: Add freelists to class loader arenas. Reviewed-by: coleenp, stefank, jprovino, ohair
author jmasa
date Tue, 18 Sep 2012 23:35:42 -0700
parents da91efe96a93
children b735136e0d82 203f64878aab
comparison
equal deleted inserted replaced
6877:d0e7716b179e 6885:685df3c6f84b
89 _marking_task_size(CardTableModRefBS::card_size_in_words * BitsPerWord * 89 _marking_task_size(CardTableModRefBS::card_size_in_words * BitsPerWord *
90 CMSConcMarkMultiple), 90 CMSConcMarkMultiple),
91 _collector(NULL) 91 _collector(NULL)
92 { 92 {
93 assert(sizeof(FreeChunk) / BytesPerWord <= MinChunkSize, 93 assert(sizeof(FreeChunk) / BytesPerWord <= MinChunkSize,
94 "FreeChunk is larger than expected"); 94 "FreeChunk is larger than expected");
95 _bt.set_space(this); 95 _bt.set_space(this);
96 initialize(mr, SpaceDecorator::Clear, SpaceDecorator::Mangle); 96 initialize(mr, SpaceDecorator::Clear, SpaceDecorator::Mangle);
97 // We have all of "mr", all of which we place in the dictionary 97 // We have all of "mr", all of which we place in the dictionary
98 // as one big chunk. We'll need to decide here which of several 98 // as one big chunk. We'll need to decide here which of several
99 // possible alternative dictionary implementations to use. For 99 // possible alternative dictionary implementations to use. For
100 // now the choice is easy, since we have only one working 100 // now the choice is easy, since we have only one working
101 // implementation, namely, the simple binary tree (splaying 101 // implementation, namely, the simple binary tree (splaying
102 // temporarily disabled). 102 // temporarily disabled).
103 switch (dictionaryChoice) { 103 switch (dictionaryChoice) {
104 case FreeBlockDictionary<FreeChunk>::dictionaryBinaryTree:
105 _dictionary = new BinaryTreeDictionary<FreeChunk, AdaptiveFreeList>(mr);
106 break;
104 case FreeBlockDictionary<FreeChunk>::dictionarySplayTree: 107 case FreeBlockDictionary<FreeChunk>::dictionarySplayTree:
105 case FreeBlockDictionary<FreeChunk>::dictionarySkipList: 108 case FreeBlockDictionary<FreeChunk>::dictionarySkipList:
106 default: 109 default:
107 warning("dictionaryChoice: selected option not understood; using" 110 warning("dictionaryChoice: selected option not understood; using"
108 " default BinaryTreeDictionary implementation instead."); 111 " default BinaryTreeDictionary implementation instead.");
109 case FreeBlockDictionary<FreeChunk>::dictionaryBinaryTree:
110 _dictionary = new BinaryTreeDictionary<FreeChunk>(mr, use_adaptive_freelists);
111 break;
112 } 112 }
113 assert(_dictionary != NULL, "CMS dictionary initialization"); 113 assert(_dictionary != NULL, "CMS dictionary initialization");
114 // The indexed free lists are initially all empty and are lazily 114 // The indexed free lists are initially all empty and are lazily
115 // filled in on demand. Initialize the array elements to NULL. 115 // filled in on demand. Initialize the array elements to NULL.
116 initializeIndexedFreeListArray(); 116 initializeIndexedFreeListArray();
451 void CompactibleFreeListSpace::print_indexed_free_lists(outputStream* st) 451 void CompactibleFreeListSpace::print_indexed_free_lists(outputStream* st)
452 const { 452 const {
453 reportIndexedFreeListStatistics(); 453 reportIndexedFreeListStatistics();
454 gclog_or_tty->print_cr("Layout of Indexed Freelists"); 454 gclog_or_tty->print_cr("Layout of Indexed Freelists");
455 gclog_or_tty->print_cr("---------------------------"); 455 gclog_or_tty->print_cr("---------------------------");
456 FreeList<FreeChunk>::print_labels_on(st, "size"); 456 AdaptiveFreeList<FreeChunk>::print_labels_on(st, "size");
457 for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { 457 for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
458 _indexedFreeList[i].print_on(gclog_or_tty); 458 _indexedFreeList[i].print_on(gclog_or_tty);
459 for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL; 459 for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL;
460 fc = fc->next()) { 460 fc = fc->next()) {
461 gclog_or_tty->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ") %s", 461 gclog_or_tty->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ") %s",
1317 1317
1318 size_t i; 1318 size_t i;
1319 size_t currSize = numWords + MinChunkSize; 1319 size_t currSize = numWords + MinChunkSize;
1320 assert(currSize % MinObjAlignment == 0, "currSize should be aligned"); 1320 assert(currSize % MinObjAlignment == 0, "currSize should be aligned");
1321 for (i = currSize; i < IndexSetSize; i += IndexSetStride) { 1321 for (i = currSize; i < IndexSetSize; i += IndexSetStride) {
1322 FreeList<FreeChunk>* fl = &_indexedFreeList[i]; 1322 AdaptiveFreeList<FreeChunk>* fl = &_indexedFreeList[i];
1323 if (fl->head()) { 1323 if (fl->head()) {
1324 ret = getFromListGreater(fl, numWords); 1324 ret = getFromListGreater(fl, numWords);
1325 assert(ret == NULL || ret->is_free(), "Should be returning a free chunk"); 1325 assert(ret == NULL || ret->is_free(), "Should be returning a free chunk");
1326 return ret; 1326 return ret;
1327 } 1327 }
1700 // adjust _unallocated_block downward, as necessary 1700 // adjust _unallocated_block downward, as necessary
1701 _bt.freed((HeapWord*)chunk, size); 1701 _bt.freed((HeapWord*)chunk, size);
1702 _dictionary->return_chunk(chunk); 1702 _dictionary->return_chunk(chunk);
1703 #ifndef PRODUCT 1703 #ifndef PRODUCT
1704 if (CMSCollector::abstract_state() != CMSCollector::Sweeping) { 1704 if (CMSCollector::abstract_state() != CMSCollector::Sweeping) {
1705 TreeChunk<FreeChunk>::as_TreeChunk(chunk)->list()->verify_stats(); 1705 TreeChunk<FreeChunk, AdaptiveFreeList>* tc = TreeChunk<FreeChunk, AdaptiveFreeList>::as_TreeChunk(chunk);
1706 TreeList<FreeChunk, AdaptiveFreeList>* tl = tc->list();
1707 tl->verify_stats();
1706 } 1708 }
1707 #endif // PRODUCT 1709 #endif // PRODUCT
1708 } 1710 }
1709 1711
1710 void 1712 void
1743 } 1745 }
1744 FreeChunk* ec; 1746 FreeChunk* ec;
1745 { 1747 {
1746 MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag); 1748 MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag);
1747 ec = dictionary()->find_largest_dict(); // get largest block 1749 ec = dictionary()->find_largest_dict(); // get largest block
1748 if (ec != NULL && ec->end() == chunk) { 1750 if (ec != NULL && ec->end() == (uintptr_t*) chunk) {
1749 // It's a coterminal block - we can coalesce. 1751 // It's a coterminal block - we can coalesce.
1750 size_t old_size = ec->size(); 1752 size_t old_size = ec->size();
1751 coalDeath(old_size); 1753 coalDeath(old_size);
1752 removeChunkFromDictionary(ec); 1754 removeChunkFromDictionary(ec);
1753 size += old_size; 1755 size += old_size;
1848 /* A hint is the next larger size that has a surplus. 1850 /* A hint is the next larger size that has a surplus.
1849 Start search at a size large enough to guarantee that 1851 Start search at a size large enough to guarantee that
1850 the excess is >= MIN_CHUNK. */ 1852 the excess is >= MIN_CHUNK. */
1851 size_t start = align_object_size(numWords + MinChunkSize); 1853 size_t start = align_object_size(numWords + MinChunkSize);
1852 if (start < IndexSetSize) { 1854 if (start < IndexSetSize) {
1853 FreeList<FreeChunk>* it = _indexedFreeList; 1855 AdaptiveFreeList<FreeChunk>* it = _indexedFreeList;
1854 size_t hint = _indexedFreeList[start].hint(); 1856 size_t hint = _indexedFreeList[start].hint();
1855 while (hint < IndexSetSize) { 1857 while (hint < IndexSetSize) {
1856 assert(hint % MinObjAlignment == 0, "hint should be aligned"); 1858 assert(hint % MinObjAlignment == 0, "hint should be aligned");
1857 FreeList<FreeChunk> *fl = &_indexedFreeList[hint]; 1859 AdaptiveFreeList<FreeChunk> *fl = &_indexedFreeList[hint];
1858 if (fl->surplus() > 0 && fl->head() != NULL) { 1860 if (fl->surplus() > 0 && fl->head() != NULL) {
1859 // Found a list with surplus, reset original hint 1861 // Found a list with surplus, reset original hint
1860 // and split out a free chunk which is returned. 1862 // and split out a free chunk which is returned.
1861 _indexedFreeList[start].set_hint(hint); 1863 _indexedFreeList[start].set_hint(hint);
1862 FreeChunk* res = getFromListGreater(fl, numWords); 1864 FreeChunk* res = getFromListGreater(fl, numWords);
1871 } 1873 }
1872 return NULL; 1874 return NULL;
1873 } 1875 }
1874 1876
1875 /* Requires fl->size >= numWords + MinChunkSize */ 1877 /* Requires fl->size >= numWords + MinChunkSize */
1876 FreeChunk* CompactibleFreeListSpace::getFromListGreater(FreeList<FreeChunk>* fl, 1878 FreeChunk* CompactibleFreeListSpace::getFromListGreater(AdaptiveFreeList<FreeChunk>* fl,
1877 size_t numWords) { 1879 size_t numWords) {
1878 FreeChunk *curr = fl->head(); 1880 FreeChunk *curr = fl->head();
1879 size_t oldNumWords = curr->size(); 1881 size_t oldNumWords = curr->size();
1880 assert(numWords >= MinChunkSize, "Word size is too small"); 1882 assert(numWords >= MinChunkSize, "Word size is too small");
1881 assert(curr != NULL, "List is empty"); 1883 assert(curr != NULL, "List is empty");
2153 float inter_sweep_estimate, 2155 float inter_sweep_estimate,
2154 float intra_sweep_estimate) { 2156 float intra_sweep_estimate) {
2155 assert_locked(); 2157 assert_locked();
2156 size_t i; 2158 size_t i;
2157 for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { 2159 for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
2158 FreeList<FreeChunk>* fl = &_indexedFreeList[i]; 2160 AdaptiveFreeList<FreeChunk>* fl = &_indexedFreeList[i];
2159 if (PrintFLSStatistics > 1) { 2161 if (PrintFLSStatistics > 1) {
2160 gclog_or_tty->print("size[%d] : ", i); 2162 gclog_or_tty->print("size[%d] : ", i);
2161 } 2163 }
2162 fl->compute_desired(inter_sweep_current, inter_sweep_estimate, intra_sweep_estimate); 2164 fl->compute_desired(inter_sweep_current, inter_sweep_estimate, intra_sweep_estimate);
2163 fl->set_coal_desired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent)); 2165 fl->set_coal_desired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent));
2172 2174
2173 void CompactibleFreeListSpace::setFLSurplus() { 2175 void CompactibleFreeListSpace::setFLSurplus() {
2174 assert_locked(); 2176 assert_locked();
2175 size_t i; 2177 size_t i;
2176 for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { 2178 for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
2177 FreeList<FreeChunk> *fl = &_indexedFreeList[i]; 2179 AdaptiveFreeList<FreeChunk> *fl = &_indexedFreeList[i];
2178 fl->set_surplus(fl->count() - 2180 fl->set_surplus(fl->count() -
2179 (ssize_t)((double)fl->desired() * CMSSmallSplitSurplusPercent)); 2181 (ssize_t)((double)fl->desired() * CMSSmallSplitSurplusPercent));
2180 } 2182 }
2181 } 2183 }
2182 2184
2183 void CompactibleFreeListSpace::setFLHints() { 2185 void CompactibleFreeListSpace::setFLHints() {
2184 assert_locked(); 2186 assert_locked();
2185 size_t i; 2187 size_t i;
2186 size_t h = IndexSetSize; 2188 size_t h = IndexSetSize;
2187 for (i = IndexSetSize - 1; i != 0; i -= IndexSetStride) { 2189 for (i = IndexSetSize - 1; i != 0; i -= IndexSetStride) {
2188 FreeList<FreeChunk> *fl = &_indexedFreeList[i]; 2190 AdaptiveFreeList<FreeChunk> *fl = &_indexedFreeList[i];
2189 fl->set_hint(h); 2191 fl->set_hint(h);
2190 if (fl->surplus() > 0) { 2192 if (fl->surplus() > 0) {
2191 h = i; 2193 h = i;
2192 } 2194 }
2193 } 2195 }
2195 2197
2196 void CompactibleFreeListSpace::clearFLCensus() { 2198 void CompactibleFreeListSpace::clearFLCensus() {
2197 assert_locked(); 2199 assert_locked();
2198 size_t i; 2200 size_t i;
2199 for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { 2201 for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
2200 FreeList<FreeChunk> *fl = &_indexedFreeList[i]; 2202 AdaptiveFreeList<FreeChunk> *fl = &_indexedFreeList[i];
2201 fl->set_prev_sweep(fl->count()); 2203 fl->set_prev_sweep(fl->count());
2202 fl->set_coal_births(0); 2204 fl->set_coal_births(0);
2203 fl->set_coal_deaths(0); 2205 fl->set_coal_deaths(0);
2204 fl->set_split_births(0); 2206 fl->set_split_births(0);
2205 fl->set_split_deaths(0); 2207 fl->set_split_deaths(0);
2222 _dictionary->end_sweep_dict_census(CMSLargeSplitSurplusPercent); 2224 _dictionary->end_sweep_dict_census(CMSLargeSplitSurplusPercent);
2223 } 2225 }
2224 2226
2225 bool CompactibleFreeListSpace::coalOverPopulated(size_t size) { 2227 bool CompactibleFreeListSpace::coalOverPopulated(size_t size) {
2226 if (size < SmallForDictionary) { 2228 if (size < SmallForDictionary) {
2227 FreeList<FreeChunk> *fl = &_indexedFreeList[size]; 2229 AdaptiveFreeList<FreeChunk> *fl = &_indexedFreeList[size];
2228 return (fl->coal_desired() < 0) || 2230 return (fl->coal_desired() < 0) ||
2229 ((int)fl->count() > fl->coal_desired()); 2231 ((int)fl->count() > fl->coal_desired());
2230 } else { 2232 } else {
2231 return dictionary()->coal_dict_over_populated(size); 2233 return dictionary()->coal_dict_over_populated(size);
2232 } 2234 }
2233 } 2235 }
2234 2236
2235 void CompactibleFreeListSpace::smallCoalBirth(size_t size) { 2237 void CompactibleFreeListSpace::smallCoalBirth(size_t size) {
2236 assert(size < SmallForDictionary, "Size too large for indexed list"); 2238 assert(size < SmallForDictionary, "Size too large for indexed list");
2237 FreeList<FreeChunk> *fl = &_indexedFreeList[size]; 2239 AdaptiveFreeList<FreeChunk> *fl = &_indexedFreeList[size];
2238 fl->increment_coal_births(); 2240 fl->increment_coal_births();
2239 fl->increment_surplus(); 2241 fl->increment_surplus();
2240 } 2242 }
2241 2243
2242 void CompactibleFreeListSpace::smallCoalDeath(size_t size) { 2244 void CompactibleFreeListSpace::smallCoalDeath(size_t size) {
2243 assert(size < SmallForDictionary, "Size too large for indexed list"); 2245 assert(size < SmallForDictionary, "Size too large for indexed list");
2244 FreeList<FreeChunk> *fl = &_indexedFreeList[size]; 2246 AdaptiveFreeList<FreeChunk> *fl = &_indexedFreeList[size];
2245 fl->increment_coal_deaths(); 2247 fl->increment_coal_deaths();
2246 fl->decrement_surplus(); 2248 fl->decrement_surplus();
2247 } 2249 }
2248 2250
2249 void CompactibleFreeListSpace::coalBirth(size_t size) { 2251 void CompactibleFreeListSpace::coalBirth(size_t size) {
2250 if (size < SmallForDictionary) { 2252 if (size < SmallForDictionary) {
2251 smallCoalBirth(size); 2253 smallCoalBirth(size);
2252 } else { 2254 } else {
2253 dictionary()->dict_census_udpate(size, 2255 dictionary()->dict_census_update(size,
2254 false /* split */, 2256 false /* split */,
2255 true /* birth */); 2257 true /* birth */);
2256 } 2258 }
2257 } 2259 }
2258 2260
2259 void CompactibleFreeListSpace::coalDeath(size_t size) { 2261 void CompactibleFreeListSpace::coalDeath(size_t size) {
2260 if(size < SmallForDictionary) { 2262 if(size < SmallForDictionary) {
2261 smallCoalDeath(size); 2263 smallCoalDeath(size);
2262 } else { 2264 } else {
2263 dictionary()->dict_census_udpate(size, 2265 dictionary()->dict_census_update(size,
2264 false /* split */, 2266 false /* split */,
2265 false /* birth */); 2267 false /* birth */);
2266 } 2268 }
2267 } 2269 }
2268 2270
2269 void CompactibleFreeListSpace::smallSplitBirth(size_t size) { 2271 void CompactibleFreeListSpace::smallSplitBirth(size_t size) {
2270 assert(size < SmallForDictionary, "Size too large for indexed list"); 2272 assert(size < SmallForDictionary, "Size too large for indexed list");
2271 FreeList<FreeChunk> *fl = &_indexedFreeList[size]; 2273 AdaptiveFreeList<FreeChunk> *fl = &_indexedFreeList[size];
2272 fl->increment_split_births(); 2274 fl->increment_split_births();
2273 fl->increment_surplus(); 2275 fl->increment_surplus();
2274 } 2276 }
2275 2277
2276 void CompactibleFreeListSpace::smallSplitDeath(size_t size) { 2278 void CompactibleFreeListSpace::smallSplitDeath(size_t size) {
2277 assert(size < SmallForDictionary, "Size too large for indexed list"); 2279 assert(size < SmallForDictionary, "Size too large for indexed list");
2278 FreeList<FreeChunk> *fl = &_indexedFreeList[size]; 2280 AdaptiveFreeList<FreeChunk> *fl = &_indexedFreeList[size];
2279 fl->increment_split_deaths(); 2281 fl->increment_split_deaths();
2280 fl->decrement_surplus(); 2282 fl->decrement_surplus();
2281 } 2283 }
2282 2284
2283 void CompactibleFreeListSpace::split_birth(size_t size) { 2285 void CompactibleFreeListSpace::split_birth(size_t size) {
2284 if (size < SmallForDictionary) { 2286 if (size < SmallForDictionary) {
2285 smallSplitBirth(size); 2287 smallSplitBirth(size);
2286 } else { 2288 } else {
2287 dictionary()->dict_census_udpate(size, 2289 dictionary()->dict_census_update(size,
2288 true /* split */, 2290 true /* split */,
2289 true /* birth */); 2291 true /* birth */);
2290 } 2292 }
2291 } 2293 }
2292 2294
2293 void CompactibleFreeListSpace::splitDeath(size_t size) { 2295 void CompactibleFreeListSpace::splitDeath(size_t size) {
2294 if (size < SmallForDictionary) { 2296 if (size < SmallForDictionary) {
2295 smallSplitDeath(size); 2297 smallSplitDeath(size);
2296 } else { 2298 } else {
2297 dictionary()->dict_census_udpate(size, 2299 dictionary()->dict_census_update(size,
2298 true /* split */, 2300 true /* split */,
2299 false /* birth */); 2301 false /* birth */);
2300 } 2302 }
2301 } 2303 }
2302 2304
2515 guarantee(n == num, "Incorrect count"); 2517 guarantee(n == num, "Incorrect count");
2516 } 2518 }
2517 2519
2518 #ifndef PRODUCT 2520 #ifndef PRODUCT
2519 void CompactibleFreeListSpace::check_free_list_consistency() const { 2521 void CompactibleFreeListSpace::check_free_list_consistency() const {
2520 assert(_dictionary->min_size() <= IndexSetSize, 2522 assert((TreeChunk<FreeChunk, AdaptiveFreeList>::min_size() <= IndexSetSize),
2521 "Some sizes can't be allocated without recourse to" 2523 "Some sizes can't be allocated without recourse to"
2522 " linear allocation buffers"); 2524 " linear allocation buffers");
2523 assert(BinaryTreeDictionary<FreeChunk>::min_tree_chunk_size*HeapWordSize == sizeof(TreeChunk<FreeChunk>), 2525 assert((TreeChunk<FreeChunk, AdaptiveFreeList>::min_size()*HeapWordSize == sizeof(TreeChunk<FreeChunk, AdaptiveFreeList>)),
2524 "else MIN_TREE_CHUNK_SIZE is wrong"); 2526 "else MIN_TREE_CHUNK_SIZE is wrong");
2525 assert(IndexSetStart != 0, "IndexSetStart not initialized"); 2527 assert(IndexSetStart != 0, "IndexSetStart not initialized");
2526 assert(IndexSetStride != 0, "IndexSetStride not initialized"); 2528 assert(IndexSetStride != 0, "IndexSetStride not initialized");
2527 } 2529 }
2528 #endif 2530 #endif
2529 2531
2530 void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const { 2532 void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const {
2531 assert_lock_strong(&_freelistLock); 2533 assert_lock_strong(&_freelistLock);
2532 FreeList<FreeChunk> total; 2534 AdaptiveFreeList<FreeChunk> total;
2533 gclog_or_tty->print("end sweep# " SIZE_FORMAT "\n", sweep_count); 2535 gclog_or_tty->print("end sweep# " SIZE_FORMAT "\n", sweep_count);
2534 FreeList<FreeChunk>::print_labels_on(gclog_or_tty, "size"); 2536 AdaptiveFreeList<FreeChunk>::print_labels_on(gclog_or_tty, "size");
2535 size_t total_free = 0; 2537 size_t total_free = 0;
2536 for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { 2538 for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
2537 const FreeList<FreeChunk> *fl = &_indexedFreeList[i]; 2539 const AdaptiveFreeList<FreeChunk> *fl = &_indexedFreeList[i];
2538 total_free += fl->count() * fl->size(); 2540 total_free += fl->count() * fl->size();
2539 if (i % (40*IndexSetStride) == 0) { 2541 if (i % (40*IndexSetStride) == 0) {
2540 FreeList<FreeChunk>::print_labels_on(gclog_or_tty, "size"); 2542 AdaptiveFreeList<FreeChunk>::print_labels_on(gclog_or_tty, "size");
2541 } 2543 }
2542 fl->print_on(gclog_or_tty); 2544 fl->print_on(gclog_or_tty);
2543 total.set_bfr_surp( total.bfr_surp() + fl->bfr_surp() ); 2545 total.set_bfr_surp( total.bfr_surp() + fl->bfr_surp() );
2544 total.set_surplus( total.surplus() + fl->surplus() ); 2546 total.set_surplus( total.surplus() + fl->surplus() );
2545 total.set_desired( total.desired() + fl->desired() ); 2547 total.set_desired( total.desired() + fl->desired() );
2618 MutexLockerEx x(_cfls->parDictionaryAllocLock(), 2620 MutexLockerEx x(_cfls->parDictionaryAllocLock(),
2619 Mutex::_no_safepoint_check_flag); 2621 Mutex::_no_safepoint_check_flag);
2620 res = _cfls->getChunkFromDictionaryExact(word_sz); 2622 res = _cfls->getChunkFromDictionaryExact(word_sz);
2621 if (res == NULL) return NULL; 2623 if (res == NULL) return NULL;
2622 } else { 2624 } else {
2623 FreeList<FreeChunk>* fl = &_indexedFreeList[word_sz]; 2625 AdaptiveFreeList<FreeChunk>* fl = &_indexedFreeList[word_sz];
2624 if (fl->count() == 0) { 2626 if (fl->count() == 0) {
2625 // Attempt to refill this local free list. 2627 // Attempt to refill this local free list.
2626 get_from_global_pool(word_sz, fl); 2628 get_from_global_pool(word_sz, fl);
2627 // If it didn't work, give up. 2629 // If it didn't work, give up.
2628 if (fl->count() == 0) return NULL; 2630 if (fl->count() == 0) return NULL;
2638 return (HeapWord*)res; 2640 return (HeapWord*)res;
2639 } 2641 }
2640 2642
2641 // Get a chunk of blocks of the right size and update related 2643 // Get a chunk of blocks of the right size and update related
2642 // book-keeping stats 2644 // book-keeping stats
2643 void CFLS_LAB::get_from_global_pool(size_t word_sz, FreeList<FreeChunk>* fl) { 2645 void CFLS_LAB::get_from_global_pool(size_t word_sz, AdaptiveFreeList<FreeChunk>* fl) {
2644 // Get the #blocks we want to claim 2646 // Get the #blocks we want to claim
2645 size_t n_blks = (size_t)_blocks_to_claim[word_sz].average(); 2647 size_t n_blks = (size_t)_blocks_to_claim[word_sz].average();
2646 assert(n_blks > 0, "Error"); 2648 assert(n_blks > 0, "Error");
2647 assert(ResizePLAB || n_blks == OldPLABSize, "Error"); 2649 assert(ResizePLAB || n_blks == OldPLABSize, "Error");
2648 // In some cases, when the application has a phase change, 2650 // In some cases, when the application has a phase change,
2720 _global_num_workers[i]++; 2722 _global_num_workers[i]++;
2721 assert(_global_num_workers[i] <= ParallelGCThreads, "Too big"); 2723 assert(_global_num_workers[i] <= ParallelGCThreads, "Too big");
2722 if (num_retire > 0) { 2724 if (num_retire > 0) {
2723 _cfls->_indexedFreeList[i].prepend(&_indexedFreeList[i]); 2725 _cfls->_indexedFreeList[i].prepend(&_indexedFreeList[i]);
2724 // Reset this list. 2726 // Reset this list.
2725 _indexedFreeList[i] = FreeList<FreeChunk>(); 2727 _indexedFreeList[i] = AdaptiveFreeList<FreeChunk>();
2726 _indexedFreeList[i].set_size(i); 2728 _indexedFreeList[i].set_size(i);
2727 } 2729 }
2728 } 2730 }
2729 if (PrintOldPLAB) { 2731 if (PrintOldPLAB) {
2730 gclog_or_tty->print_cr("%d[%d]: %d/%d/%d", 2732 gclog_or_tty->print_cr("%d[%d]: %d/%d/%d",
2734 _num_blocks[i] = 0; 2736 _num_blocks[i] = 0;
2735 } 2737 }
2736 } 2738 }
2737 } 2739 }
2738 2740
2739 void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList<FreeChunk>* fl) { 2741 void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, AdaptiveFreeList<FreeChunk>* fl) {
2740 assert(fl->count() == 0, "Precondition."); 2742 assert(fl->count() == 0, "Precondition.");
2741 assert(word_sz < CompactibleFreeListSpace::IndexSetSize, 2743 assert(word_sz < CompactibleFreeListSpace::IndexSetSize,
2742 "Precondition"); 2744 "Precondition");
2743 2745
2744 // We'll try all multiples of word_sz in the indexed set, starting with 2746 // We'll try all multiples of word_sz in the indexed set, starting with
2750 size_t cur_sz; 2752 size_t cur_sz;
2751 for (k = 1, cur_sz = k * word_sz, found = false; 2753 for (k = 1, cur_sz = k * word_sz, found = false;
2752 (cur_sz < CompactibleFreeListSpace::IndexSetSize) && 2754 (cur_sz < CompactibleFreeListSpace::IndexSetSize) &&
2753 (CMSSplitIndexedFreeListBlocks || k <= 1); 2755 (CMSSplitIndexedFreeListBlocks || k <= 1);
2754 k++, cur_sz = k * word_sz) { 2756 k++, cur_sz = k * word_sz) {
2755 FreeList<FreeChunk> fl_for_cur_sz; // Empty. 2757 AdaptiveFreeList<FreeChunk> fl_for_cur_sz; // Empty.
2756 fl_for_cur_sz.set_size(cur_sz); 2758 fl_for_cur_sz.set_size(cur_sz);
2757 { 2759 {
2758 MutexLockerEx x(_indexedFreeListParLocks[cur_sz], 2760 MutexLockerEx x(_indexedFreeListParLocks[cur_sz],
2759 Mutex::_no_safepoint_check_flag); 2761 Mutex::_no_safepoint_check_flag);
2760 FreeList<FreeChunk>* gfl = &_indexedFreeList[cur_sz]; 2762 AdaptiveFreeList<FreeChunk>* gfl = &_indexedFreeList[cur_sz];
2761 if (gfl->count() != 0) { 2763 if (gfl->count() != 0) {
2762 // nn is the number of chunks of size cur_sz that 2764 // nn is the number of chunks of size cur_sz that
2763 // we'd need to split k-ways each, in order to create 2765 // we'd need to split k-ways each, in order to create
2764 // "n" chunks of size word_sz each. 2766 // "n" chunks of size word_sz each.
2765 const size_t nn = MAX2(n/k, (size_t)1); 2767 const size_t nn = MAX2(n/k, (size_t)1);
2830 size_t rem; 2832 size_t rem;
2831 { 2833 {
2832 MutexLockerEx x(parDictionaryAllocLock(), 2834 MutexLockerEx x(parDictionaryAllocLock(),
2833 Mutex::_no_safepoint_check_flag); 2835 Mutex::_no_safepoint_check_flag);
2834 while (n > 0) { 2836 while (n > 0) {
2835 fc = dictionary()->get_chunk(MAX2(n * word_sz, 2837 fc = dictionary()->get_chunk(MAX2(n * word_sz, _dictionary->min_size()),
2836 _dictionary->min_size()),
2837 FreeBlockDictionary<FreeChunk>::atLeast); 2838 FreeBlockDictionary<FreeChunk>::atLeast);
2838 if (fc != NULL) { 2839 if (fc != NULL) {
2839 _bt.allocated((HeapWord*)fc, fc->size(), true /* reducing */); // update _unallocated_blk 2840 _bt.allocated((HeapWord*)fc, fc->size(), true /* reducing */); // update _unallocated_blk
2840 dictionary()->dict_census_udpate(fc->size(), 2841 dictionary()->dict_census_update(fc->size(),
2841 true /*split*/, 2842 true /*split*/,
2842 false /*birth*/); 2843 false /*birth*/);
2843 break; 2844 break;
2844 } else { 2845 } else {
2845 n--; 2846 n--;
2888 _bt.split_block((HeapWord*)fc, fc->size(), prefix_size); 2889 _bt.split_block((HeapWord*)fc, fc->size(), prefix_size);
2889 assert(fc->is_free(), "Error"); 2890 assert(fc->is_free(), "Error");
2890 fc->set_size(prefix_size); 2891 fc->set_size(prefix_size);
2891 if (rem >= IndexSetSize) { 2892 if (rem >= IndexSetSize) {
2892 returnChunkToDictionary(rem_fc); 2893 returnChunkToDictionary(rem_fc);
2893 dictionary()->dict_census_udpate(rem, true /*split*/, true /*birth*/); 2894 dictionary()->dict_census_update(rem, true /*split*/, true /*birth*/);
2894 rem_fc = NULL; 2895 rem_fc = NULL;
2895 } 2896 }
2896 // Otherwise, return it to the small list below. 2897 // Otherwise, return it to the small list below.
2897 } 2898 }
2898 } 2899 }