1.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Mon May 03 20:19:05 2010 -0700 1.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Mon May 10 12:31:52 2010 -0700 1.3 @@ -1926,59 +1926,6 @@ 1.4 1.5 ALL_SINCE_SAVE_MARKS_CLOSURES(CFLS_OOP_SINCE_SAVE_MARKS_DEFN) 1.6 1.7 -////////////////////////////////////////////////////////////////////////////// 1.8 -// We go over the list of promoted objects, removing each from the list, 1.9 -// and applying the closure (this may, in turn, add more elements to 1.10 -// the tail of the promoted list, and these newly added objects will 1.11 -// also be processed) until the list is empty. 1.12 -// To aid verification and debugging, in the non-product builds 1.13 -// we actually forward _promoHead each time we process a promoted oop. 1.14 -// Note that this is not necessary in general (i.e. when we don't need to 1.15 -// call PromotionInfo::verify()) because oop_iterate can only add to the 1.16 -// end of _promoTail, and never needs to look at _promoHead. 1.17 - 1.18 -#define PROMOTED_OOPS_ITERATE_DEFN(OopClosureType, nv_suffix) \ 1.19 - \ 1.20 -void PromotionInfo::promoted_oops_iterate##nv_suffix(OopClosureType* cl) { \ 1.21 - NOT_PRODUCT(verify()); \ 1.22 - PromotedObject *curObj, *nextObj; \ 1.23 - for (curObj = _promoHead; curObj != NULL; curObj = nextObj) { \ 1.24 - if ((nextObj = curObj->next()) == NULL) { \ 1.25 - /* protect ourselves against additions due to closure application \ 1.26 - below by resetting the list. */ \ 1.27 - assert(_promoTail == curObj, "Should have been the tail"); \ 1.28 - _promoHead = _promoTail = NULL; \ 1.29 - } \ 1.30 - if (curObj->hasDisplacedMark()) { \ 1.31 - /* restore displaced header */ \ 1.32 - oop(curObj)->set_mark(nextDisplacedHeader()); \ 1.33 - } else { \ 1.34 - /* restore prototypical header */ \ 1.35 - oop(curObj)->init_mark(); \ 1.36 - } \ 1.37 - /* The "promoted_mark" should now not be set */ \ 1.38 - assert(!curObj->hasPromotedMark(), \ 1.39 - "Should have been cleared by restoring displaced mark-word"); \ 1.40 - NOT_PRODUCT(_promoHead = nextObj); \ 1.41 - if (cl != NULL) oop(curObj)->oop_iterate(cl); \ 1.42 - if (nextObj == NULL) { /* start at head of list reset above */ \ 1.43 - nextObj = _promoHead; \ 1.44 - } \ 1.45 - } \ 1.46 - assert(noPromotions(), "post-condition violation"); \ 1.47 - assert(_promoHead == NULL && _promoTail == NULL, "emptied promoted list");\ 1.48 - assert(_spoolHead == _spoolTail, "emptied spooling buffers"); \ 1.49 - assert(_firstIndex == _nextIndex, "empty buffer"); \ 1.50 -} 1.51 - 1.52 -// This should have been ALL_SINCE_...() just like the others, 1.53 -// but, because the body of the method above is somehwat longer, 1.54 -// the MSVC compiler cannot cope; as a workaround, we split the 1.55 -// macro into its 3 constituent parts below (see original macro 1.56 -// definition in specializedOopClosures.hpp). 1.57 -SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG(PROMOTED_OOPS_ITERATE_DEFN) 1.58 -PROMOTED_OOPS_ITERATE_DEFN(OopsInGenClosure,_v) 1.59 - 1.60 1.61 void CompactibleFreeListSpace::object_iterate_since_last_GC(ObjectClosure* cl) { 1.62 // ugghh... how would one do this efficiently for a non-contiguous space? 1.63 @@ -2506,281 +2453,6 @@ 1.64 _dictionary->printDictCensus(); 1.65 } 1.66 1.67 -// Return the next displaced header, incrementing the pointer and 1.68 -// recycling spool area as necessary. 1.69 -markOop PromotionInfo::nextDisplacedHeader() { 1.70 - assert(_spoolHead != NULL, "promotionInfo inconsistency"); 1.71 - assert(_spoolHead != _spoolTail || _firstIndex < _nextIndex, 1.72 - "Empty spool space: no displaced header can be fetched"); 1.73 - assert(_spoolHead->bufferSize > _firstIndex, "Off by one error at head?"); 1.74 - markOop hdr = _spoolHead->displacedHdr[_firstIndex]; 1.75 - // Spool forward 1.76 - if (++_firstIndex == _spoolHead->bufferSize) { // last location in this block 1.77 - // forward to next block, recycling this block into spare spool buffer 1.78 - SpoolBlock* tmp = _spoolHead->nextSpoolBlock; 1.79 - assert(_spoolHead != _spoolTail, "Spooling storage mix-up"); 1.80 - _spoolHead->nextSpoolBlock = _spareSpool; 1.81 - _spareSpool = _spoolHead; 1.82 - _spoolHead = tmp; 1.83 - _firstIndex = 1; 1.84 - NOT_PRODUCT( 1.85 - if (_spoolHead == NULL) { // all buffers fully consumed 1.86 - assert(_spoolTail == NULL && _nextIndex == 1, 1.87 - "spool buffers processing inconsistency"); 1.88 - } 1.89 - ) 1.90 - } 1.91 - return hdr; 1.92 -} 1.93 - 1.94 -void PromotionInfo::track(PromotedObject* trackOop) { 1.95 - track(trackOop, oop(trackOop)->klass()); 1.96 -} 1.97 - 1.98 -void PromotionInfo::track(PromotedObject* trackOop, klassOop klassOfOop) { 1.99 - // make a copy of header as it may need to be spooled 1.100 - markOop mark = oop(trackOop)->mark(); 1.101 - trackOop->clearNext(); 1.102 - if (mark->must_be_preserved_for_cms_scavenge(klassOfOop)) { 1.103 - // save non-prototypical header, and mark oop 1.104 - saveDisplacedHeader(mark); 1.105 - trackOop->setDisplacedMark(); 1.106 - } else { 1.107 - // we'd like to assert something like the following: 1.108 - // assert(mark == markOopDesc::prototype(), "consistency check"); 1.109 - // ... but the above won't work because the age bits have not (yet) been 1.110 - // cleared. The remainder of the check would be identical to the 1.111 - // condition checked in must_be_preserved() above, so we don't really 1.112 - // have anything useful to check here! 1.113 - } 1.114 - if (_promoTail != NULL) { 1.115 - assert(_promoHead != NULL, "List consistency"); 1.116 - _promoTail->setNext(trackOop); 1.117 - _promoTail = trackOop; 1.118 - } else { 1.119 - assert(_promoHead == NULL, "List consistency"); 1.120 - _promoHead = _promoTail = trackOop; 1.121 - } 1.122 - // Mask as newly promoted, so we can skip over such objects 1.123 - // when scanning dirty cards 1.124 - assert(!trackOop->hasPromotedMark(), "Should not have been marked"); 1.125 - trackOop->setPromotedMark(); 1.126 -} 1.127 - 1.128 -// Save the given displaced header, incrementing the pointer and 1.129 -// obtaining more spool area as necessary. 1.130 -void PromotionInfo::saveDisplacedHeader(markOop hdr) { 1.131 - assert(_spoolHead != NULL && _spoolTail != NULL, 1.132 - "promotionInfo inconsistency"); 1.133 - assert(_spoolTail->bufferSize > _nextIndex, "Off by one error at tail?"); 1.134 - _spoolTail->displacedHdr[_nextIndex] = hdr; 1.135 - // Spool forward 1.136 - if (++_nextIndex == _spoolTail->bufferSize) { // last location in this block 1.137 - // get a new spooling block 1.138 - assert(_spoolTail->nextSpoolBlock == NULL, "tail should terminate spool list"); 1.139 - _splice_point = _spoolTail; // save for splicing 1.140 - _spoolTail->nextSpoolBlock = getSpoolBlock(); // might fail 1.141 - _spoolTail = _spoolTail->nextSpoolBlock; // might become NULL ... 1.142 - // ... but will attempt filling before next promotion attempt 1.143 - _nextIndex = 1; 1.144 - } 1.145 -} 1.146 - 1.147 -// Ensure that spooling space exists. Return false if spooling space 1.148 -// could not be obtained. 1.149 -bool PromotionInfo::ensure_spooling_space_work() { 1.150 - assert(!has_spooling_space(), "Only call when there is no spooling space"); 1.151 - // Try and obtain more spooling space 1.152 - SpoolBlock* newSpool = getSpoolBlock(); 1.153 - assert(newSpool == NULL || 1.154 - (newSpool->bufferSize != 0 && newSpool->nextSpoolBlock == NULL), 1.155 - "getSpoolBlock() sanity check"); 1.156 - if (newSpool == NULL) { 1.157 - return false; 1.158 - } 1.159 - _nextIndex = 1; 1.160 - if (_spoolTail == NULL) { 1.161 - _spoolTail = newSpool; 1.162 - if (_spoolHead == NULL) { 1.163 - _spoolHead = newSpool; 1.164 - _firstIndex = 1; 1.165 - } else { 1.166 - assert(_splice_point != NULL && _splice_point->nextSpoolBlock == NULL, 1.167 - "Splice point invariant"); 1.168 - // Extra check that _splice_point is connected to list 1.169 - #ifdef ASSERT 1.170 - { 1.171 - SpoolBlock* blk = _spoolHead; 1.172 - for (; blk->nextSpoolBlock != NULL; 1.173 - blk = blk->nextSpoolBlock); 1.174 - assert(blk != NULL && blk == _splice_point, 1.175 - "Splice point incorrect"); 1.176 - } 1.177 - #endif // ASSERT 1.178 - _splice_point->nextSpoolBlock = newSpool; 1.179 - } 1.180 - } else { 1.181 - assert(_spoolHead != NULL, "spool list consistency"); 1.182 - _spoolTail->nextSpoolBlock = newSpool; 1.183 - _spoolTail = newSpool; 1.184 - } 1.185 - return true; 1.186 -} 1.187 - 1.188 -// Get a free spool buffer from the free pool, getting a new block 1.189 -// from the heap if necessary. 1.190 -SpoolBlock* PromotionInfo::getSpoolBlock() { 1.191 - SpoolBlock* res; 1.192 - if ((res = _spareSpool) != NULL) { 1.193 - _spareSpool = _spareSpool->nextSpoolBlock; 1.194 - res->nextSpoolBlock = NULL; 1.195 - } else { // spare spool exhausted, get some from heap 1.196 - res = (SpoolBlock*)(space()->allocateScratch(refillSize())); 1.197 - if (res != NULL) { 1.198 - res->init(); 1.199 - } 1.200 - } 1.201 - assert(res == NULL || res->nextSpoolBlock == NULL, "postcondition"); 1.202 - return res; 1.203 -} 1.204 - 1.205 -void PromotionInfo::startTrackingPromotions() { 1.206 - assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex, 1.207 - "spooling inconsistency?"); 1.208 - _firstIndex = _nextIndex = 1; 1.209 - _tracking = true; 1.210 -} 1.211 - 1.212 -#define CMSPrintPromoBlockInfo 1 1.213 - 1.214 -void PromotionInfo::stopTrackingPromotions(uint worker_id) { 1.215 - assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex, 1.216 - "spooling inconsistency?"); 1.217 - _firstIndex = _nextIndex = 1; 1.218 - _tracking = false; 1.219 - if (CMSPrintPromoBlockInfo > 1) { 1.220 - print_statistics(worker_id); 1.221 - } 1.222 -} 1.223 - 1.224 -void PromotionInfo::print_statistics(uint worker_id) const { 1.225 - assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex, 1.226 - "Else will undercount"); 1.227 - assert(CMSPrintPromoBlockInfo > 0, "Else unnecessary call"); 1.228 - // Count the number of blocks and slots in the free pool 1.229 - size_t slots = 0; 1.230 - size_t blocks = 0; 1.231 - for (SpoolBlock* cur_spool = _spareSpool; 1.232 - cur_spool != NULL; 1.233 - cur_spool = cur_spool->nextSpoolBlock) { 1.234 - // the first entry is just a self-pointer; indices 1 through 1.235 - // bufferSize - 1 are occupied (thus, bufferSize - 1 slots). 1.236 - guarantee((void*)cur_spool->displacedHdr == (void*)&cur_spool->displacedHdr, 1.237 - "first entry of displacedHdr should be self-referential"); 1.238 - slots += cur_spool->bufferSize - 1; 1.239 - blocks++; 1.240 - } 1.241 - if (_spoolHead != NULL) { 1.242 - slots += _spoolHead->bufferSize - 1; 1.243 - blocks++; 1.244 - } 1.245 - gclog_or_tty->print_cr(" [worker %d] promo_blocks = %d, promo_slots = %d ", 1.246 - worker_id, blocks, slots); 1.247 -} 1.248 - 1.249 -// When _spoolTail is not NULL, then the slot <_spoolTail, _nextIndex> 1.250 -// points to the next slot available for filling. 1.251 -// The set of slots holding displaced headers are then all those in the 1.252 -// right-open interval denoted by: 1.253 -// 1.254 -// [ <_spoolHead, _firstIndex>, <_spoolTail, _nextIndex> ) 1.255 -// 1.256 -// When _spoolTail is NULL, then the set of slots with displaced headers 1.257 -// is all those starting at the slot <_spoolHead, _firstIndex> and 1.258 -// going up to the last slot of last block in the linked list. 1.259 -// In this lartter case, _splice_point points to the tail block of 1.260 -// this linked list of blocks holding displaced headers. 1.261 -void PromotionInfo::verify() const { 1.262 - // Verify the following: 1.263 - // 1. the number of displaced headers matches the number of promoted 1.264 - // objects that have displaced headers 1.265 - // 2. each promoted object lies in this space 1.266 - debug_only( 1.267 - PromotedObject* junk = NULL; 1.268 - assert(junk->next_addr() == (void*)(oop(junk)->mark_addr()), 1.269 - "Offset of PromotedObject::_next is expected to align with " 1.270 - " the OopDesc::_mark within OopDesc"); 1.271 - ) 1.272 - // FIXME: guarantee???? 1.273 - guarantee(_spoolHead == NULL || _spoolTail != NULL || 1.274 - _splice_point != NULL, "list consistency"); 1.275 - guarantee(_promoHead == NULL || _promoTail != NULL, "list consistency"); 1.276 - // count the number of objects with displaced headers 1.277 - size_t numObjsWithDisplacedHdrs = 0; 1.278 - for (PromotedObject* curObj = _promoHead; curObj != NULL; curObj = curObj->next()) { 1.279 - guarantee(space()->is_in_reserved((HeapWord*)curObj), "Containment"); 1.280 - // the last promoted object may fail the mark() != NULL test of is_oop(). 1.281 - guarantee(curObj->next() == NULL || oop(curObj)->is_oop(), "must be an oop"); 1.282 - if (curObj->hasDisplacedMark()) { 1.283 - numObjsWithDisplacedHdrs++; 1.284 - } 1.285 - } 1.286 - // Count the number of displaced headers 1.287 - size_t numDisplacedHdrs = 0; 1.288 - for (SpoolBlock* curSpool = _spoolHead; 1.289 - curSpool != _spoolTail && curSpool != NULL; 1.290 - curSpool = curSpool->nextSpoolBlock) { 1.291 - // the first entry is just a self-pointer; indices 1 through 1.292 - // bufferSize - 1 are occupied (thus, bufferSize - 1 slots). 1.293 - guarantee((void*)curSpool->displacedHdr == (void*)&curSpool->displacedHdr, 1.294 - "first entry of displacedHdr should be self-referential"); 1.295 - numDisplacedHdrs += curSpool->bufferSize - 1; 1.296 - } 1.297 - guarantee((_spoolHead == _spoolTail) == (numDisplacedHdrs == 0), 1.298 - "internal consistency"); 1.299 - guarantee(_spoolTail != NULL || _nextIndex == 1, 1.300 - "Inconsistency between _spoolTail and _nextIndex"); 1.301 - // We overcounted (_firstIndex-1) worth of slots in block 1.302 - // _spoolHead and we undercounted (_nextIndex-1) worth of 1.303 - // slots in block _spoolTail. We make an appropriate 1.304 - // adjustment by subtracting the first and adding the 1.305 - // second: - (_firstIndex - 1) + (_nextIndex - 1) 1.306 - numDisplacedHdrs += (_nextIndex - _firstIndex); 1.307 - guarantee(numDisplacedHdrs == numObjsWithDisplacedHdrs, "Displaced hdr count"); 1.308 -} 1.309 - 1.310 -void PromotionInfo::print_on(outputStream* st) const { 1.311 - SpoolBlock* curSpool = NULL; 1.312 - size_t i = 0; 1.313 - st->print_cr("start & end indices: [" SIZE_FORMAT ", " SIZE_FORMAT ")", 1.314 - _firstIndex, _nextIndex); 1.315 - for (curSpool = _spoolHead; curSpool != _spoolTail && curSpool != NULL; 1.316 - curSpool = curSpool->nextSpoolBlock) { 1.317 - curSpool->print_on(st); 1.318 - st->print_cr(" active "); 1.319 - i++; 1.320 - } 1.321 - for (curSpool = _spoolTail; curSpool != NULL; 1.322 - curSpool = curSpool->nextSpoolBlock) { 1.323 - curSpool->print_on(st); 1.324 - st->print_cr(" inactive "); 1.325 - i++; 1.326 - } 1.327 - for (curSpool = _spareSpool; curSpool != NULL; 1.328 - curSpool = curSpool->nextSpoolBlock) { 1.329 - curSpool->print_on(st); 1.330 - st->print_cr(" free "); 1.331 - i++; 1.332 - } 1.333 - st->print_cr(SIZE_FORMAT " header spooling blocks", i); 1.334 -} 1.335 - 1.336 -void SpoolBlock::print_on(outputStream* st) const { 1.337 - st->print("[" PTR_FORMAT "," PTR_FORMAT "), " SIZE_FORMAT " HeapWords -> " PTR_FORMAT, 1.338 - this, (HeapWord*)displacedHdr + bufferSize, 1.339 - bufferSize, nextSpoolBlock); 1.340 -} 1.341 - 1.342 /////////////////////////////////////////////////////////////////////////// 1.343 // CFLS_LAB 1.344 ///////////////////////////////////////////////////////////////////////////