Tue, 25 Oct 2011 20:15:41 -0700
7099817: CMS: +FLSVerifyLists +FLSVerifyIndexTable asserts: odd slot non-empty, chunk not on free list
Summary: Suitably weaken asserts that were in each case a tad too strong; fix up some loose uses of parameters in code related to size-indexed free list table.
Reviewed-by: jmasa, brutisso, stefank
1.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Sun Oct 23 23:06:06 2011 -0700 1.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Tue Oct 25 20:15:41 2011 -0700 1.3 @@ -62,7 +62,7 @@ 1.4 MinChunkSize = numQuanta(sizeof(FreeChunk), MinObjAlignmentInBytes) * MinObjAlignment; 1.5 1.6 assert(IndexSetStart == 0 && IndexSetStride == 0, "already set"); 1.7 - IndexSetStart = MinObjAlignment; 1.8 + IndexSetStart = (int) MinChunkSize; 1.9 IndexSetStride = MinObjAlignment; 1.10 } 1.11 1.12 @@ -138,7 +138,7 @@ 1.13 } else { 1.14 _fitStrategy = FreeBlockStrategyNone; 1.15 } 1.16 - checkFreeListConsistency(); 1.17 + check_free_list_consistency(); 1.18 1.19 // Initialize locks for parallel case. 1.20 1.21 @@ -1358,17 +1358,29 @@ 1.22 ShouldNotReachHere(); 1.23 } 1.24 1.25 -bool CompactibleFreeListSpace::verifyChunkInIndexedFreeLists(FreeChunk* fc) 1.26 - const { 1.27 +bool CompactibleFreeListSpace::verifyChunkInIndexedFreeLists(FreeChunk* fc) const { 1.28 assert(fc->size() < IndexSetSize, "Size of chunk is too large"); 1.29 return _indexedFreeList[fc->size()].verifyChunkInFreeLists(fc); 1.30 } 1.31 1.32 +bool CompactibleFreeListSpace::verify_chunk_is_linear_alloc_block(FreeChunk* fc) const { 1.33 + assert((_smallLinearAllocBlock._ptr != (HeapWord*)fc) || 1.34 + (_smallLinearAllocBlock._word_size == fc->size()), 1.35 + "Linear allocation block shows incorrect size"); 1.36 + return ((_smallLinearAllocBlock._ptr == (HeapWord*)fc) && 1.37 + (_smallLinearAllocBlock._word_size == fc->size())); 1.38 +} 1.39 + 1.40 +// Check if the purported free chunk is present either as a linear 1.41 +// allocation block, the size-indexed table of (smaller) free blocks, 1.42 +// or the larger free blocks kept in the binary tree dictionary. 1.43 bool CompactibleFreeListSpace::verifyChunkInFreeLists(FreeChunk* fc) const { 1.44 - if (fc->size() >= IndexSetSize) { 1.45 + if (verify_chunk_is_linear_alloc_block(fc)) { 1.46 + return true; 1.47 + } else if (fc->size() < IndexSetSize) { 1.48 + return verifyChunkInIndexedFreeLists(fc); 1.49 + } else { 1.50 return dictionary()->verifyChunkInFreeLists(fc); 1.51 - } else { 1.52 - return verifyChunkInIndexedFreeLists(fc); 1.53 } 1.54 } 1.55 1.56 @@ -2495,7 +2507,8 @@ 1.57 FreeChunk* tail = _indexedFreeList[size].tail(); 1.58 size_t num = _indexedFreeList[size].count(); 1.59 size_t n = 0; 1.60 - guarantee((size % 2 == 0) || fc == NULL, "Odd slots should be empty"); 1.61 + guarantee(((size >= MinChunkSize) && (size % IndexSetStride == 0)) || fc == NULL, 1.62 + "Slot should have been empty"); 1.63 for (; fc != NULL; fc = fc->next(), n++) { 1.64 guarantee(fc->size() == size, "Size inconsistency"); 1.65 guarantee(fc->isFree(), "!free?"); 1.66 @@ -2506,14 +2519,14 @@ 1.67 } 1.68 1.69 #ifndef PRODUCT 1.70 -void CompactibleFreeListSpace::checkFreeListConsistency() const { 1.71 +void CompactibleFreeListSpace::check_free_list_consistency() const { 1.72 assert(_dictionary->minSize() <= IndexSetSize, 1.73 "Some sizes can't be allocated without recourse to" 1.74 " linear allocation buffers"); 1.75 assert(MIN_TREE_CHUNK_SIZE*HeapWordSize == sizeof(TreeChunk), 1.76 "else MIN_TREE_CHUNK_SIZE is wrong"); 1.77 - assert((IndexSetStride == 2 && IndexSetStart == 2) || 1.78 - (IndexSetStride == 1 && IndexSetStart == 1), "just checking"); 1.79 + assert((IndexSetStride == 2 && IndexSetStart == 4) || // 32-bit 1.80 + (IndexSetStride == 1 && IndexSetStart == 3), "just checking"); // 64-bit 1.81 assert((IndexSetStride != 2) || (MinChunkSize % 2 == 0), 1.82 "Some for-loops may be incorrectly initialized"); 1.83 assert((IndexSetStride != 2) || (IndexSetSize % 2 == 1), 1.84 @@ -2688,33 +2701,27 @@ 1.85 } 1.86 } 1.87 1.88 +// If this is changed in the future to allow parallel 1.89 +// access, one would need to take the FL locks and, 1.90 +// depending on how it is used, stagger access from 1.91 +// parallel threads to reduce contention. 1.92 void CFLS_LAB::retire(int tid) { 1.93 // We run this single threaded with the world stopped; 1.94 // so no need for locks and such. 1.95 -#define CFLS_LAB_PARALLEL_ACCESS 0 1.96 NOT_PRODUCT(Thread* t = Thread::current();) 1.97 assert(Thread::current()->is_VM_thread(), "Error"); 1.98 - assert(CompactibleFreeListSpace::IndexSetStart == CompactibleFreeListSpace::IndexSetStride, 1.99 - "Will access to uninitialized slot below"); 1.100 -#if CFLS_LAB_PARALLEL_ACCESS 1.101 - for (size_t i = CompactibleFreeListSpace::IndexSetSize - 1; 1.102 - i > 0; 1.103 - i -= CompactibleFreeListSpace::IndexSetStride) { 1.104 -#else // CFLS_LAB_PARALLEL_ACCESS 1.105 for (size_t i = CompactibleFreeListSpace::IndexSetStart; 1.106 i < CompactibleFreeListSpace::IndexSetSize; 1.107 i += CompactibleFreeListSpace::IndexSetStride) { 1.108 -#endif // !CFLS_LAB_PARALLEL_ACCESS 1.109 assert(_num_blocks[i] >= (size_t)_indexedFreeList[i].count(), 1.110 "Can't retire more than what we obtained"); 1.111 if (_num_blocks[i] > 0) { 1.112 size_t num_retire = _indexedFreeList[i].count(); 1.113 assert(_num_blocks[i] > num_retire, "Should have used at least one"); 1.114 { 1.115 -#if CFLS_LAB_PARALLEL_ACCESS 1.116 - MutexLockerEx x(_cfls->_indexedFreeListParLocks[i], 1.117 - Mutex::_no_safepoint_check_flag); 1.118 -#endif // CFLS_LAB_PARALLEL_ACCESS 1.119 + // MutexLockerEx x(_cfls->_indexedFreeListParLocks[i], 1.120 + // Mutex::_no_safepoint_check_flag); 1.121 + 1.122 // Update globals stats for num_blocks used 1.123 _global_num_blocks[i] += (_num_blocks[i] - num_retire); 1.124 _global_num_workers[i]++;
2.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp Sun Oct 23 23:06:06 2011 -0700 2.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp Tue Oct 25 20:15:41 2011 -0700 2.3 @@ -502,10 +502,14 @@ 2.4 void verifyFreeLists() const PRODUCT_RETURN; 2.5 void verifyIndexedFreeLists() const; 2.6 void verifyIndexedFreeList(size_t size) const; 2.7 - // verify that the given chunk is in the free lists. 2.8 + // Verify that the given chunk is in the free lists: 2.9 + // i.e. either the binary tree dictionary, the indexed free lists 2.10 + // or the linear allocation block. 2.11 bool verifyChunkInFreeLists(FreeChunk* fc) const; 2.12 + // Verify that the given chunk is the linear allocation block 2.13 + bool verify_chunk_is_linear_alloc_block(FreeChunk* fc) const; 2.14 // Do some basic checks on the the free lists. 2.15 - void checkFreeListConsistency() const PRODUCT_RETURN; 2.16 + void check_free_list_consistency() const PRODUCT_RETURN; 2.17 2.18 // Printing support 2.19 void dump_at_safepoint_with_locks(CMSCollector* c, outputStream* st);