src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Cdiff src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp

src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp

Print this page
rev 5732 : [mq]: comments2

*** 115,128 **** // // Unfortunately, i couldn't come up with a good abstraction to factor and // hide the naked CGC_lock manipulation in the baton-passing code // further below. That's something we should try to do. Also, the proof // of correctness of this 2-level locking scheme is far from obvious, ! // and potentially quite slippery. We have an uneasy supsicion, for instance, // that there may be a theoretical possibility of delay/starvation in the // low-level lock/wait/notify scheme used for the baton-passing because of ! // potential intereference with the priority scheme embodied in the // CMS-token-passing protocol. See related comments at a CGC_lock->wait() // invocation further below and marked with "XXX 20011219YSR". // Indeed, as we note elsewhere, this may become yet more slippery // in the presence of multiple CMS and/or multiple VM threads. XXX --- 115,128 ---- // // Unfortunately, i couldn't come up with a good abstraction to factor and // hide the naked CGC_lock manipulation in the baton-passing code // further below. That's something we should try to do. Also, the proof // of correctness of this 2-level locking scheme is far from obvious, ! // and potentially quite slippery. We have an uneasy suspicion, for instance, // that there may be a theoretical possibility of delay/starvation in the // low-level lock/wait/notify scheme used for the baton-passing because of ! // potential interference with the priority scheme embodied in the // CMS-token-passing protocol. See related comments at a CGC_lock->wait() // invocation further below and marked with "XXX 20011219YSR". // Indeed, as we note elsewhere, this may become yet more slippery // in the presence of multiple CMS and/or multiple VM threads. XXX
*** 257,267 **** // generation may be larger than that in, say, a contiguous young // generation. // Ideally, in the calculation below, we'd compute the dilatation // factor as: MinChunkSize/(promoting_gen's min object size) // Since we do not have such a general query interface for the ! // promoting generation, we'll instead just use the mimimum // object size (which today is a header's worth of space); // note that all arithmetic is in units of HeapWords. assert(MinChunkSize >= CollectedHeap::min_fill_size(), "just checking"); assert(_dilatation_factor >= 1.0, "from previous assert"); } --- 257,267 ---- // generation may be larger than that in, say, a contiguous young // generation. // Ideally, in the calculation below, we'd compute the dilatation // factor as: MinChunkSize/(promoting_gen's min object size) // Since we do not have such a general query interface for the ! // promoting generation, we'll instead just use the minimum // object size (which today is a header's worth of space); // note that all arithmetic is in units of HeapWords. assert(MinChunkSize >= CollectedHeap::min_fill_size(), "just checking"); assert(_dilatation_factor >= 1.0, "from previous assert"); }
*** 272,282 **** // via CMSInitiatingOccupancyFraction (argument "io" below), it // is calculated by: // // Let "f" be MinHeapFreeRatio in // ! // _intiating_occupancy = 100-f + // f * (CMSTriggerRatio/100) // where CMSTriggerRatio is the argument "tr" below. // // That is, if we assume the heap is at its desired maximum occupancy at the // end of a collection, we let CMSTriggerRatio of the (purported) free --- 272,282 ---- // via CMSInitiatingOccupancyFraction (argument "io" below), it // is calculated by: // // Let "f" be MinHeapFreeRatio in // ! // _initiating_occupancy = 100-f + // f * (CMSTriggerRatio/100) // where CMSTriggerRatio is the argument "tr" below. // // That is, if we assume the heap is at its desired maximum occupancy at the // end of a collection, we let CMSTriggerRatio of the (purported) free
*** 2669,2679 **** // prologue delegate to the collector, which delegates back // some "local" work to a worker method in the individual generations // that it's responsible for collecting, while itself doing any // work common to all generations it's responsible for. A similar // comment applies to the gc_epilogue()'s. ! // The role of the varaible _between_prologue_and_epilogue is to // enforce the invocation protocol. void CMSCollector::gc_prologue(bool full) { // Call gc_prologue_work() for the CMSGen // we are responsible for. --- 2669,2679 ---- // prologue delegate to the collector, which delegates back // some "local" work to a worker method in the individual generations // that it's responsible for collecting, while itself doing any // work common to all generations it's responsible for. A similar // comment applies to the gc_epilogue()'s. ! // The role of the variable _between_prologue_and_epilogue is to // enforce the invocation protocol. void CMSCollector::gc_prologue(bool full) { // Call gc_prologue_work() for the CMSGen // we are responsible for.
*** 2876,2889 **** #endif // Check reachability of the given heap address in CMS generation, // treating all other generations as roots. bool CMSCollector::is_cms_reachable(HeapWord* addr) { ! // We could "guarantee" below, rather than assert, but i'll // leave these as "asserts" so that an adventurous debugger // could try this in the product build provided some subset of ! // the conditions were met, provided they were intersted in the // results and knew that the computation below wouldn't interfere // with other concurrent computations mutating the structures // being read or written. assert(SafepointSynchronize::is_at_safepoint(), "Else mutations in object graph will make answer suspect"); --- 2876,2889 ---- #endif // Check reachability of the given heap address in CMS generation, // treating all other generations as roots. bool CMSCollector::is_cms_reachable(HeapWord* addr) { ! // We could "guarantee" below, rather than assert, but I'll // leave these as "asserts" so that an adventurous debugger // could try this in the product build provided some subset of ! // the conditions were met, provided they were interested in the // results and knew that the computation below wouldn't interfere // with other concurrent computations mutating the structures // being read or written. assert(SafepointSynchronize::is_at_safepoint(), "Else mutations in object graph will make answer suspect");
*** 2980,2990 **** // Turn off refs discovery -- so we will be tracing through refs. // This is as intended, because by this time // GC must already have cleared any refs that need to be cleared, // and traced those that need to be marked; moreover, ! // the marking done here is not going to intefere in any // way with the marking information used by GC. NoRefDiscovery no_discovery(ref_processor()); COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;) --- 2980,2990 ---- // Turn off refs discovery -- so we will be tracing through refs. // This is as intended, because by this time // GC must already have cleared any refs that need to be cleared, // and traced those that need to be marked; moreover, ! // the marking done here is not going to interfere in any // way with the marking information used by GC. NoRefDiscovery no_discovery(ref_processor()); COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;)
*** 2998,3008 **** // Update the saved marks which may affect the root scans. gch->save_marks(); if (CMSRemarkVerifyVariant == 1) { // In this first variant of verification, we complete ! // all marking, then check if the new marks-verctor is // a subset of the CMS marks-vector. verify_after_remark_work_1(); } else if (CMSRemarkVerifyVariant == 2) { // In this second variant of verification, we flag an error // (i.e. an object reachable in the new marks-vector not reachable --- 2998,3008 ---- // Update the saved marks which may affect the root scans. gch->save_marks(); if (CMSRemarkVerifyVariant == 1) { // In this first variant of verification, we complete ! // all marking, then check if the new marks-vector is // a subset of the CMS marks-vector. verify_after_remark_work_1(); } else if (CMSRemarkVerifyVariant == 2) { // In this second variant of verification, we flag an error // (i.e. an object reachable in the new marks-vector not reachable
*** 3399,3409 **** // Otherwise, we try expansion. expand(word_sz*HeapWordSize, MinHeapDeltaBytes, CMSExpansionCause::_allocate_par_lab); // Now go around the loop and try alloc again; // A competing par_promote might beat us to the expansion space, ! // so we may go around the loop again if promotion fails agaion. if (GCExpandToAllocateDelayMillis > 0) { os::sleep(Thread::current(), GCExpandToAllocateDelayMillis, false); } } } --- 3399,3409 ---- // Otherwise, we try expansion. expand(word_sz*HeapWordSize, MinHeapDeltaBytes, CMSExpansionCause::_allocate_par_lab); // Now go around the loop and try alloc again; // A competing par_promote might beat us to the expansion space, ! // so we may go around the loop again if promotion fails again. if (GCExpandToAllocateDelayMillis > 0) { os::sleep(Thread::current(), GCExpandToAllocateDelayMillis, false); } } }
*** 4371,4381 **** // We really need to reconsider the synchronization between the GC // thread and the yield-requesting threads in the future and we // should really use wait/notify, which is the recommended // way of doing this type of interaction. Additionally, we should // consolidate the eight methods that do the yield operation and they ! // are almost identical into one for better maintenability and // readability. See 6445193. // // Tony 2006.06.29 for (unsigned i = 0; i < CMSCoordinatorYieldSleepCount && ConcurrentMarkSweepThread::should_yield() && --- 4371,4381 ---- // We really need to reconsider the synchronization between the GC // thread and the yield-requesting threads in the future and we // should really use wait/notify, which is the recommended // way of doing this type of interaction. Additionally, we should // consolidate the eight methods that do the yield operation and they ! // are almost identical into one for better maintainability and // readability. See 6445193. // // Tony 2006.06.29 for (unsigned i = 0; i < CMSCoordinatorYieldSleepCount && ConcurrentMarkSweepThread::should_yield() &&
*** 4539,4549 **** assert(_collectorState == AbortablePreclean, "Inconsistent control state"); // If Eden's current occupancy is below this threshold, // immediately schedule the remark; else preclean // past the next scavenge in an effort to ! // schedule the pause as described avove. By choosing // CMSScheduleRemarkEdenSizeThreshold >= max eden size // we will never do an actual abortable preclean cycle. if (get_eden_used() > CMSScheduleRemarkEdenSizeThreshold) { TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); CMSPhaseAccounting pa(this, "abortable-preclean", !PrintGCDetails); --- 4539,4549 ---- assert(_collectorState == AbortablePreclean, "Inconsistent control state"); // If Eden's current occupancy is below this threshold, // immediately schedule the remark; else preclean // past the next scavenge in an effort to ! // schedule the pause as described above. By choosing // CMSScheduleRemarkEdenSizeThreshold >= max eden size // we will never do an actual abortable preclean cycle. if (get_eden_used() > CMSScheduleRemarkEdenSizeThreshold) { TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); CMSPhaseAccounting pa(this, "abortable-preclean", !PrintGCDetails);
*** 5535,5546 **** OopTaskQueue* work_q = work_queue(i); ModUnionClosure modUnionClosure(&(_collector->_modUnionTable)); // CAUTION! CAUTION! CAUTION! CAUTION! CAUTION! CAUTION! CAUTION! // CAUTION: This closure has state that persists across calls to // the work method dirty_range_iterate_clear() in that it has ! // imbedded in it a (subtype of) UpwardsObjectClosure. The ! // use of that state in the imbedded UpwardsObjectClosure instance // assumes that the cards are always iterated (even if in parallel // by several threads) in monotonically increasing order per each // thread. This is true of the implementation below which picks // card ranges (chunks) in monotonically increasing order globally // and, a-fortiori, in monotonically increasing order per thread --- 5535,5546 ---- OopTaskQueue* work_q = work_queue(i); ModUnionClosure modUnionClosure(&(_collector->_modUnionTable)); // CAUTION! CAUTION! CAUTION! CAUTION! CAUTION! CAUTION! CAUTION! // CAUTION: This closure has state that persists across calls to // the work method dirty_range_iterate_clear() in that it has ! // embedded in it a (subtype of) UpwardsObjectClosure. The ! // use of that state in the embedded UpwardsObjectClosure instance // assumes that the cards are always iterated (even if in parallel // by several threads) in monotonically increasing order per each // thread. This is true of the implementation below which picks // card ranges (chunks) in monotonically increasing order globally // and, a-fortiori, in monotonically increasing order per thread
*** 5551,5561 **** // revisited and modified appropriately. See also related // bug 4756801 work on which should examine this code to make // sure that the changes there do not run counter to the // assumptions made here and necessary for correctness and // efficiency. Note also that this code might yield inefficient ! // behaviour in the case of very large objects that span one or // more work chunks. Such objects would potentially be scanned // several times redundantly. Work on 4756801 should try and // address that performance anomaly if at all possible. XXX MemRegion full_span = _collector->_span; CMSBitMap* bm = &(_collector->_markBitMap); // shared --- 5551,5561 ---- // revisited and modified appropriately. See also related // bug 4756801 work on which should examine this code to make // sure that the changes there do not run counter to the // assumptions made here and necessary for correctness and // efficiency. Note also that this code might yield inefficient ! // behavior in the case of very large objects that span one or // more work chunks. Such objects would potentially be scanned // several times redundantly. Work on 4756801 should try and // address that performance anomaly if at all possible. XXX MemRegion full_span = _collector->_span; CMSBitMap* bm = &(_collector->_markBitMap); // shared
*** 5577,5587 **** assert((size_t)round_to((intptr_t)chunk_size, alignment) == chunk_size, "Check alignment"); while (!pst->is_task_claimed(/* reference */ nth_task)) { // Having claimed the nth_task, compute corresponding mem-region, ! // which is a-fortiori aligned correctly (i.e. at a MUT bopundary). // The alignment restriction ensures that we do not need any // synchronization with other gang-workers while setting or // clearing bits in thus chunk of the MUT. MemRegion this_span = MemRegion(start_addr + nth_task*chunk_size, start_addr + (nth_task+1)*chunk_size); --- 5577,5587 ---- assert((size_t)round_to((intptr_t)chunk_size, alignment) == chunk_size, "Check alignment"); while (!pst->is_task_claimed(/* reference */ nth_task)) { // Having claimed the nth_task, compute corresponding mem-region, ! // which is a-fortiori aligned correctly (i.e. at a MUT boundary). // The alignment restriction ensures that we do not need any // synchronization with other gang-workers while setting or // clearing bits in thus chunk of the MUT. MemRegion this_span = MemRegion(start_addr + nth_task*chunk_size, start_addr + (nth_task+1)*chunk_size);
*** 6369,6379 **** _intra_sweep_estimate.sample(_intra_sweep_timer.seconds()); _inter_sweep_timer.reset(); _inter_sweep_timer.start(); ! // We need to use a monotonically non-deccreasing time in ms // or we will see time-warp warnings and os::javaTimeMillis() // does not guarantee monotonicity. jlong now = os::javaTimeNanos() / NANOSECS_PER_MILLISEC; update_time_of_last_gc(now); --- 6369,6379 ---- _intra_sweep_estimate.sample(_intra_sweep_timer.seconds()); _inter_sweep_timer.reset(); _inter_sweep_timer.start(); ! // We need to use a monotonically non-decreasing time in ms // or we will see time-warp warnings and os::javaTimeMillis() // does not guarantee monotonicity. jlong now = os::javaTimeNanos() / NANOSECS_PER_MILLISEC; update_time_of_last_gc(now);
*** 6730,6740 **** (_bmWordSize >> (_shifter + LogBitsPerByte)) + 1)); if (!brs.is_reserved()) { warning("CMS bit map allocation failure"); return false; } ! // For now we'll just commit all of the bit map up fromt. // Later on we'll try to be more parsimonious with swap. if (!_virtual_space.initialize(brs, brs.size())) { warning("CMS bit map backing store failure"); return false; } --- 6730,6740 ---- (_bmWordSize >> (_shifter + LogBitsPerByte)) + 1)); if (!brs.is_reserved()) { warning("CMS bit map allocation failure"); return false; } ! // For now we'll just commit all of the bit map up front. // Later on we'll try to be more parsimonious with swap. if (!_virtual_space.initialize(brs, brs.size())) { warning("CMS bit map backing store failure"); return false; }
*** 6837,6848 **** return true; } // XXX FIX ME !!! In the MT case we come in here holding a // leaf lock. For printing we need to take a further lock ! // which has lower rank. We need to recallibrate the two ! // lock-ranks involved in order to be able to rpint the // messages below. (Or defer the printing to the caller. // For now we take the expedient path of just disabling the // messages for the problematic case.) void CMSMarkStack::expand() { assert(_capacity <= MarkStackSizeMax, "stack bigger than permitted"); --- 6837,6848 ---- return true; } // XXX FIX ME !!! In the MT case we come in here holding a // leaf lock. For printing we need to take a further lock ! // which has lower rank. We need to recalibrate the two ! // lock-ranks involved in order to be able to print the // messages below. (Or defer the printing to the caller. // For now we take the expedient path of just disabling the // messages for the problematic case.) void CMSMarkStack::expand() { assert(_capacity <= MarkStackSizeMax, "stack bigger than permitted");
*** 7178,7196 **** assert(_bitMap->isMarked(addr+size-1), "inconsistent Printezis mark"); } #endif // ASSERT } else { ! // an unitialized object assert(_bitMap->isMarked(addr+1), "missing Printezis mark?"); HeapWord* nextOneAddr = _bitMap->getNextMarkedWordAddress(addr + 2); size = pointer_delta(nextOneAddr + 1, addr); assert(size == CompactibleFreeListSpace::adjustObjectSize(size), "alignment problem"); // Note that pre-cleaning needn't redirty the card. OopDesc::set_klass() // will dirty the card when the klass pointer is installed in the ! // object (signalling the completion of initialization). } } else { // Either a not yet marked object or an uninitialized object if (p->klass_or_null() == NULL) { // An uninitialized object, skip to the next card, since --- 7178,7196 ---- assert(_bitMap->isMarked(addr+size-1), "inconsistent Printezis mark"); } #endif // ASSERT } else { ! // An uninitialized object. assert(_bitMap->isMarked(addr+1), "missing Printezis mark?"); HeapWord* nextOneAddr = _bitMap->getNextMarkedWordAddress(addr + 2); size = pointer_delta(nextOneAddr + 1, addr); assert(size == CompactibleFreeListSpace::adjustObjectSize(size), "alignment problem"); // Note that pre-cleaning needn't redirty the card. OopDesc::set_klass() // will dirty the card when the klass pointer is installed in the ! // object (signaling the completion of initialization). } } else { // Either a not yet marked object or an uninitialized object if (p->klass_or_null() == NULL) { // An uninitialized object, skip to the next card, since
*** 7997,8007 **** // in the mod union table, thus ensuring that the object remains // in the grey set and continue. In the case of object arrays // we need to dirty all of the cards that the object spans, // since the rescan of object arrays will be limited to the // dirty cards. ! // Note that no one can be intefering with us in this action // of dirtying the mod union table, so no locking or atomics // are required. if (obj->is_objArray()) { size_t sz = obj->size(); HeapWord* end_card_addr = (HeapWord*)round_to( --- 7997,8007 ---- // in the mod union table, thus ensuring that the object remains // in the grey set and continue. In the case of object arrays // we need to dirty all of the cards that the object spans, // since the rescan of object arrays will be limited to the // dirty cards. ! // Note that no one can be interfering with us in this action // of dirtying the mod union table, so no locking or atomics // are required. if (obj->is_objArray()) { size_t sz = obj->size(); HeapWord* end_card_addr = (HeapWord*)round_to(
*** 9023,9033 **** #ifndef PRODUCT // Debugging support for CMSStackOverflowALot // It's OK to call this multi-threaded; the worst thing // that can happen is that we'll get a bunch of closely ! // spaced simulated oveflows, but that's OK, in fact // probably good as it would exercise the overflow code // under contention. bool CMSCollector::simulate_overflow() { if (_overflow_counter-- <= 0) { // just being defensive _overflow_counter = CMSMarkStackOverflowInterval; --- 9023,9033 ---- #ifndef PRODUCT // Debugging support for CMSStackOverflowALot // It's OK to call this multi-threaded; the worst thing // that can happen is that we'll get a bunch of closely ! // spaced simulated overflows, but that's OK, in fact // probably good as it would exercise the overflow code // under contention. bool CMSCollector::simulate_overflow() { if (_overflow_counter-- <= 0) { // just being defensive _overflow_counter = CMSMarkStackOverflowInterval;
*** 9143,9153 **** // above, if it is still the same value. if (_overflow_list == BUSY) { (void) Atomic::cmpxchg_ptr(NULL, &_overflow_list, BUSY); } } else { ! // Chop off the suffix and rerturn it to the global list. assert(cur->mark() != BUSY, "Error"); oop suffix_head = cur->mark(); // suffix will be put back on global list cur->set_mark(NULL); // break off suffix // It's possible that the list is still in the empty(busy) state // we left it in a short while ago; in that case we may be --- 9143,9153 ---- // above, if it is still the same value. if (_overflow_list == BUSY) { (void) Atomic::cmpxchg_ptr(NULL, &_overflow_list, BUSY); } } else { ! // Chop off the suffix and return it to the global list. assert(cur->mark() != BUSY, "Error"); oop suffix_head = cur->mark(); // suffix will be put back on global list cur->set_mark(NULL); // break off suffix // It's possible that the list is still in the empty(busy) state // we left it in a short while ago; in that case we may be
src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File