# HG changeset patch # User johnc # Date 1293135597 28800 # Node ID 9deafc053a1a61a45b9dad936b2d48bc99cd9f31 # Parent 4c7605ccbb8b119fad935e01ef267ad47c7bca53# Parent 1d92613a1e8a1dd7f08f2487771394cc7c108eec Merge diff -r 4c7605ccbb8b -r 9deafc053a1a hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Wed Dec 22 19:20:47 2010 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu Dec 23 12:19:57 2010 -0800 @@ -1825,23 +1825,11 @@ } } - -class G1CMIsAliveClosure: public BoolObjectClosure { - G1CollectedHeap* _g1; - public: - G1CMIsAliveClosure(G1CollectedHeap* g1) : - _g1(g1) - {} - - void do_object(oop obj) { - assert(false, "not to be invoked"); - } - bool do_object_b(oop obj) { - HeapWord* addr = (HeapWord*)obj; - return addr != NULL && - (!_g1->is_in_g1_reserved(addr) || !_g1->is_obj_ill(obj)); - } -}; +bool G1CMIsAliveClosure::do_object_b(oop obj) { + HeapWord* addr = (HeapWord*)obj; + return addr != NULL && + (!_g1->is_in_g1_reserved(addr) || !_g1->is_obj_ill(obj)); +} class G1CMKeepAliveClosure: public OopClosure { G1CollectedHeap* _g1; @@ -1896,16 +1884,15 @@ rp->setup_policy(clear_all_soft_refs); assert(_markStack.isEmpty(), "mark stack should be empty"); - G1CMIsAliveClosure g1IsAliveClosure (g1h); - G1CMKeepAliveClosure g1KeepAliveClosure(g1h, this, nextMarkBitMap()); + G1CMIsAliveClosure g1_is_alive(g1h); + G1CMKeepAliveClosure g1_keep_alive(g1h, this, nextMarkBitMap()); G1CMDrainMarkingStackClosure - g1DrainMarkingStackClosure(nextMarkBitMap(), &_markStack, - &g1KeepAliveClosure); + g1_drain_mark_stack(nextMarkBitMap(), &_markStack, &g1_keep_alive); // XXXYYY Also: copy the parallel ref processing code from CMS. - rp->process_discovered_references(&g1IsAliveClosure, - &g1KeepAliveClosure, - &g1DrainMarkingStackClosure, + rp->process_discovered_references(&g1_is_alive, + &g1_keep_alive, + &g1_drain_mark_stack, NULL); assert(_markStack.overflow() || _markStack.isEmpty(), "mark stack should be empty (unless it overflowed)"); @@ -1918,8 +1905,8 @@ assert(!rp->discovery_enabled(), "should have been disabled"); // Now clean up stale oops in SymbolTable and StringTable - SymbolTable::unlink(&g1IsAliveClosure); - StringTable::unlink(&g1IsAliveClosure); + SymbolTable::unlink(&g1_is_alive); + StringTable::unlink(&g1_is_alive); } void ConcurrentMark::swapMarkBitMaps() { diff -r 4c7605ccbb8b -r 9deafc053a1a hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Wed Dec 22 19:20:47 2010 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Thu Dec 23 12:19:57 2010 -0800 @@ -33,6 +33,25 @@ typedef GenericTaskQueue CMTaskQueue; typedef GenericTaskQueueSet CMTaskQueueSet; +// Closure used by CM during concurrent reference discovery +// and reference processing (during remarking) to determine +// if a particular object is alive. It is primarily used +// to determine if referents of discovered reference objects +// are alive. An instance is also embedded into the +// reference processor as the _is_alive_non_header field +class G1CMIsAliveClosure: public BoolObjectClosure { + G1CollectedHeap* _g1; + public: + G1CMIsAliveClosure(G1CollectedHeap* g1) : + _g1(g1) + {} + + void do_object(oop obj) { + ShouldNotCallThis(); + } + bool do_object_b(oop obj); +}; + // A generic CM bit map. This is essentially a wrapper around the BitMap // class, with one bit per (1<<_shifter) HeapWords. diff -r 4c7605ccbb8b -r 9deafc053a1a hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Dec 22 19:20:47 2010 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Dec 23 12:19:57 2010 -0800 @@ -1192,6 +1192,7 @@ return false; } + DTraceGCProbeMarker gc_probe_marker(true /* full */); ResourceMark rm; if (PrintHeapAtGC) { @@ -1768,6 +1769,7 @@ _g1_policy(policy_), _dirty_card_queue_set(false), _into_cset_dirty_card_queue_set(false), + _is_alive_closure(this), _ref_processor(NULL), _process_strong_tasks(new SubTasksDone(G1H_PS_NumElements)), _bot_shared(NULL), @@ -2061,7 +2063,8 @@ mr, // span false, // Reference discovery is not atomic true, // mt_discovery - NULL, // is alive closure: need to fill this in for efficiency + &_is_alive_closure, // is alive closure + // for efficiency ParallelGCThreads, ParallelRefProcEnabled, true); // Setting next fields of discovered @@ -3211,13 +3214,14 @@ return false; } + DTraceGCProbeMarker gc_probe_marker(false /* full */); + ResourceMark rm; + if (PrintHeapAtGC) { Universe::print_heap_before_gc(); } { - ResourceMark rm; - // This call will decide whether this pause is an initial-mark // pause. If it is, during_initial_mark_pause() will return true // for the duration of this pause. @@ -3956,8 +3960,6 @@ // Now restore saved marks, if any. if (_objs_with_preserved_marks != NULL) { assert(_preserved_marks_of_objs != NULL, "Both or none."); - assert(_objs_with_preserved_marks->length() == - _preserved_marks_of_objs->length(), "Both or none."); guarantee(_objs_with_preserved_marks->length() == _preserved_marks_of_objs->length(), "Both or none."); for (int i = 0; i < _objs_with_preserved_marks->length(); i++) { @@ -4052,7 +4054,10 @@ } void G1CollectedHeap::preserve_mark_if_necessary(oop obj, markOop m) { - if (m != markOopDesc::prototype()) { + assert(evacuation_failed(), "Oversaving!"); + // We want to call the "for_promotion_failure" version only in the + // case of a promotion failure. + if (m->must_be_preserved_for_promotion_failure(obj)) { if (_objs_with_preserved_marks == NULL) { assert(_preserved_marks_of_objs == NULL, "Both or none."); _objs_with_preserved_marks = diff -r 4c7605ccbb8b -r 9deafc053a1a hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Dec 22 19:20:47 2010 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Dec 23 12:19:57 2010 -0800 @@ -849,6 +849,12 @@ void print_gc_alloc_regions(); #endif // !PRODUCT + // Instance of the concurrent mark is_alive closure for embedding + // into the reference processor as the is_alive_non_header. This + // prevents unnecessary additions to the discovered lists during + // concurrent discovery. + G1CMIsAliveClosure _is_alive_closure; + // ("Weak") Reference processing support ReferenceProcessor* _ref_processor; @@ -893,7 +899,7 @@ // specified by the policy object. jint initialize(); - void ref_processing_init(); + virtual void ref_processing_init(); void set_par_threads(int t) { SharedHeap::set_par_threads(t); diff -r 4c7605ccbb8b -r 9deafc053a1a hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp --- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Wed Dec 22 19:20:47 2010 -0800 +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Thu Dec 23 12:19:57 2010 -0800 @@ -1058,10 +1058,11 @@ #endif void ParNewGeneration::preserve_mark_if_necessary(oop obj, markOop m) { - if ((m != markOopDesc::prototype()) && - (!UseBiasedLocking || (m != markOopDesc::biased_locking_prototype()))) { + if (m->must_be_preserved_for_promotion_failure(obj)) { + // We should really have separate per-worker stacks, rather + // than use locking of a common pair of stacks. MutexLocker ml(ParGCRareEvent_lock); - DefNewGeneration::preserve_mark_if_necessary(obj, m); + preserve_mark(obj, m); } } diff -r 4c7605ccbb8b -r 9deafc053a1a hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Wed Dec 22 19:20:47 2010 -0800 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Thu Dec 23 12:19:57 2010 -0800 @@ -694,6 +694,8 @@ void PSScavenge::oop_promotion_failed(oop obj, markOop obj_mark) { _promotion_failed = true; if (obj_mark->must_be_preserved_for_promotion_failure(obj)) { + // Should use per-worker private stakcs hetre rather than + // locking a common pair of stacks. ThreadCritical tc; _preserved_oop_stack.push(obj); _preserved_mark_stack.push(obj_mark); diff -r 4c7605ccbb8b -r 9deafc053a1a hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp --- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp Wed Dec 22 19:20:47 2010 -0800 +++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp Thu Dec 23 12:19:57 2010 -0800 @@ -209,4 +209,15 @@ HeapWord* result() const { return _res; } }; +class DTraceGCProbeMarker : public StackObj { +public: + DTraceGCProbeMarker(bool full) { + VM_GC_Operation::notify_gc_begin(full); + } + + ~DTraceGCProbeMarker() { + VM_GC_Operation::notify_gc_end(); + } +}; + #endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_VMGCOPERATIONS_HPP diff -r 4c7605ccbb8b -r 9deafc053a1a hotspot/src/share/vm/memory/defNewGeneration.cpp --- a/hotspot/src/share/vm/memory/defNewGeneration.cpp Wed Dec 22 19:20:47 2010 -0800 +++ b/hotspot/src/share/vm/memory/defNewGeneration.cpp Thu Dec 23 12:19:57 2010 -0800 @@ -684,23 +684,28 @@ _preserved_marks_of_objs.clear(true); } +void DefNewGeneration::preserve_mark(oop obj, markOop m) { + assert(promotion_failed() && m->must_be_preserved_for_promotion_failure(obj), + "Oversaving!"); + _objs_with_preserved_marks.push(obj); + _preserved_marks_of_objs.push(m); +} + void DefNewGeneration::preserve_mark_if_necessary(oop obj, markOop m) { if (m->must_be_preserved_for_promotion_failure(obj)) { - _objs_with_preserved_marks.push(obj); - _preserved_marks_of_objs.push(m); + preserve_mark(obj, m); } } void DefNewGeneration::handle_promotion_failure(oop old) { - preserve_mark_if_necessary(old, old->mark()); - if (!_promotion_failed && PrintPromotionFailure) { + if (PrintPromotionFailure && !_promotion_failed) { gclog_or_tty->print(" (promotion failure size = " SIZE_FORMAT ") ", old->size()); } - + _promotion_failed = true; + preserve_mark_if_necessary(old, old->mark()); // forward to self old->forward_to(old); - _promotion_failed = true; _promo_failure_scan_stack.push(old); diff -r 4c7605ccbb8b -r 9deafc053a1a hotspot/src/share/vm/memory/defNewGeneration.hpp --- a/hotspot/src/share/vm/memory/defNewGeneration.hpp Wed Dec 22 19:20:47 2010 -0800 +++ b/hotspot/src/share/vm/memory/defNewGeneration.hpp Thu Dec 23 12:19:57 2010 -0800 @@ -85,6 +85,7 @@ // Preserve the mark of "obj", if necessary, in preparation for its mark // word being overwritten with a self-forwarding-pointer. void preserve_mark_if_necessary(oop obj, markOop m); + void preserve_mark(oop obj, markOop m); // work routine used by the above // Together, these keep pairs. // They should always contain the same number of elements. diff -r 4c7605ccbb8b -r 9deafc053a1a hotspot/src/share/vm/oops/markOop.inline.hpp --- a/hotspot/src/share/vm/oops/markOop.inline.hpp Wed Dec 22 19:20:47 2010 -0800 +++ b/hotspot/src/share/vm/oops/markOop.inline.hpp Thu Dec 23 12:19:57 2010 -0800 @@ -30,7 +30,7 @@ #include "oops/markOop.hpp" #include "runtime/globals.hpp" -// Should this header be preserved during GC? +// Should this header be preserved during GC (when biased locking is enabled)? inline bool markOopDesc::must_be_preserved_with_bias(oop obj_containing_mark) const { assert(UseBiasedLocking, "unexpected"); if (has_bias_pattern()) { @@ -47,14 +47,15 @@ return (!is_unlocked() || !has_no_hash()); } +// Should this header be preserved during GC? inline bool markOopDesc::must_be_preserved(oop obj_containing_mark) const { if (!UseBiasedLocking) return (!is_unlocked() || !has_no_hash()); return must_be_preserved_with_bias(obj_containing_mark); } -// Should this header (including its age bits) be preserved in the -// case of a promotion failure during scavenge? +// Should this header be preserved in the case of a promotion failure +// during scavenge (when biased locking is enabled)? inline bool markOopDesc::must_be_preserved_with_bias_for_promotion_failure(oop obj_containing_mark) const { assert(UseBiasedLocking, "unexpected"); // We don't explicitly save off the mark words of biased and @@ -70,18 +71,20 @@ prototype_for_object(obj_containing_mark)->has_bias_pattern()) { return true; } - return (this != prototype()); + return (!is_unlocked() || !has_no_hash()); } +// Should this header be preserved in the case of a promotion failure +// during scavenge? inline bool markOopDesc::must_be_preserved_for_promotion_failure(oop obj_containing_mark) const { if (!UseBiasedLocking) - return (this != prototype()); + return (!is_unlocked() || !has_no_hash()); return must_be_preserved_with_bias_for_promotion_failure(obj_containing_mark); } -// Should this header (including its age bits) be preserved in the -// case of a scavenge in which CMS is the old generation? +// Same as must_be_preserved_with_bias_for_promotion_failure() except that +// it takes a klassOop argument, instead of the object of which this is the mark word. inline bool markOopDesc::must_be_preserved_with_bias_for_cms_scavenge(klassOop klass_of_obj_containing_mark) const { assert(UseBiasedLocking, "unexpected"); // CMS scavenges preserve mark words in similar fashion to promotion failures; see above @@ -89,11 +92,14 @@ klass_of_obj_containing_mark->klass_part()->prototype_header()->has_bias_pattern()) { return true; } - return (this != prototype()); + return (!is_unlocked() || !has_no_hash()); } + +// Same as must_be_preserved_for_promotion_failure() except that +// it takes a klassOop argument, instead of the object of which this is the mark word. inline bool markOopDesc::must_be_preserved_for_cms_scavenge(klassOop klass_of_obj_containing_mark) const { if (!UseBiasedLocking) - return (this != prototype()); + return (!is_unlocked() || !has_no_hash()); return must_be_preserved_with_bias_for_cms_scavenge(klass_of_obj_containing_mark); }