1.1 --- a/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp Mon Nov 15 16:25:14 2010 -0800 1.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp Tue Nov 16 14:07:33 2010 -0800 1.3 @@ -31,17 +31,12 @@ 1.4 } 1.5 1.6 template <class T> 1.7 -inline void G1RemSet::write_ref_nv(HeapRegion* from, T* p) { 1.8 - par_write_ref_nv(from, p, 0); 1.9 -} 1.10 - 1.11 -inline bool G1RemSet::self_forwarded(oop obj) { 1.12 - bool result = (obj->is_forwarded() && (obj->forwardee()== obj)); 1.13 - return result; 1.14 +inline void G1RemSet::write_ref(HeapRegion* from, T* p) { 1.15 + par_write_ref(from, p, 0); 1.16 } 1.17 1.18 template <class T> 1.19 -inline void G1RemSet::par_write_ref_nv(HeapRegion* from, T* p, int tid) { 1.20 +inline void G1RemSet::par_write_ref(HeapRegion* from, T* p, int tid) { 1.21 oop obj = oopDesc::load_decode_heap_oop(p); 1.22 #ifdef ASSERT 1.23 // can't do because of races 1.24 @@ -62,34 +57,15 @@ 1.25 assert(from == NULL || from->is_in_reserved(p), "p is not in from"); 1.26 1.27 HeapRegion* to = _g1->heap_region_containing(obj); 1.28 - // The test below could be optimized by applying a bit op to to and from. 1.29 - if (to != NULL && from != NULL && from != to) { 1.30 - // The _traversal_in_progress flag is true during the collection pause, 1.31 - // false during the evacuation failure handling. This should avoid a 1.32 - // potential loop if we were to add the card containing 'p' to the DCQS 1.33 - // that's used to regenerate the remembered sets for the collection set, 1.34 - // in the event of an evacuation failure, here. The UpdateRSImmediate 1.35 - // closure will eventally call this routine. 1.36 - if (_traversal_in_progress && 1.37 - to->in_collection_set() && !self_forwarded(obj)) { 1.38 - 1.39 - assert(_cset_rs_update_cl[tid] != NULL, "should have been set already"); 1.40 - _cset_rs_update_cl[tid]->do_oop(p); 1.41 - 1.42 - // Deferred updates to the CSet are either discarded (in the normal case), 1.43 - // or processed (if an evacuation failure occurs) at the end 1.44 - // of the collection. 1.45 - // See G1RemSet::cleanup_after_oops_into_collection_set_do(). 1.46 - } else { 1.47 + if (to != NULL && from != to) { 1.48 #if G1_REM_SET_LOGGING 1.49 - gclog_or_tty->print_cr("Adding " PTR_FORMAT " (" PTR_FORMAT ") to RS" 1.50 - " for region [" PTR_FORMAT ", " PTR_FORMAT ")", 1.51 - p, obj, 1.52 - to->bottom(), to->end()); 1.53 + gclog_or_tty->print_cr("Adding " PTR_FORMAT " (" PTR_FORMAT ") to RS" 1.54 + " for region [" PTR_FORMAT ", " PTR_FORMAT ")", 1.55 + p, obj, 1.56 + to->bottom(), to->end()); 1.57 #endif 1.58 - assert(to->rem_set() != NULL, "Need per-region 'into' remsets."); 1.59 - to->rem_set()->add_reference(p, tid); 1.60 - } 1.61 + assert(to->rem_set() != NULL, "Need per-region 'into' remsets."); 1.62 + to->rem_set()->add_reference(p, tid); 1.63 } 1.64 } 1.65 1.66 @@ -108,3 +84,64 @@ 1.67 } 1.68 } 1.69 1.70 +template <class T> 1.71 +inline void UpdateRSOrPushRefOopClosure::do_oop_work(T* p) { 1.72 + oop obj = oopDesc::load_decode_heap_oop(p); 1.73 +#ifdef ASSERT 1.74 + // can't do because of races 1.75 + // assert(obj == NULL || obj->is_oop(), "expected an oop"); 1.76 + 1.77 + // Do the safe subset of is_oop 1.78 + if (obj != NULL) { 1.79 +#ifdef CHECK_UNHANDLED_OOPS 1.80 + oopDesc* o = obj.obj(); 1.81 +#else 1.82 + oopDesc* o = obj; 1.83 +#endif // CHECK_UNHANDLED_OOPS 1.84 + assert((intptr_t)o % MinObjAlignmentInBytes == 0, "not oop aligned"); 1.85 + assert(Universe::heap()->is_in_reserved(obj), "must be in heap"); 1.86 + } 1.87 +#endif // ASSERT 1.88 + 1.89 + assert(_from != NULL, "from region must be non-NULL"); 1.90 + 1.91 + HeapRegion* to = _g1->heap_region_containing(obj); 1.92 + if (to != NULL && _from != to) { 1.93 + // The _record_refs_into_cset flag is true during the RSet 1.94 + // updating part of an evacuation pause. It is false at all 1.95 + // other times: 1.96 + // * rebuilding the rembered sets after a full GC 1.97 + // * during concurrent refinement. 1.98 + // * updating the remembered sets of regions in the collection 1.99 + // set in the event of an evacuation failure (when deferred 1.100 + // updates are enabled). 1.101 + 1.102 + if (_record_refs_into_cset && to->in_collection_set()) { 1.103 + // We are recording references that point into the collection 1.104 + // set and this particular reference does exactly that... 1.105 + // If the referenced object has already been forwarded 1.106 + // to itself, we are handling an evacuation failure and 1.107 + // we have already visited/tried to copy this object 1.108 + // there is no need to retry. 1.109 + if (!self_forwarded(obj)) { 1.110 + assert(_push_ref_cl != NULL, "should not be null"); 1.111 + // Push the reference in the refs queue of the G1ParScanThreadState 1.112 + // instance for this worker thread. 1.113 + _push_ref_cl->do_oop(p); 1.114 + } 1.115 + 1.116 + // Deferred updates to the CSet are either discarded (in the normal case), 1.117 + // or processed (if an evacuation failure occurs) at the end 1.118 + // of the collection. 1.119 + // See G1RemSet::cleanup_after_oops_into_collection_set_do(). 1.120 + } else { 1.121 + // We either don't care about pushing references that point into the 1.122 + // collection set (i.e. we're not during an evacuation pause) _or_ 1.123 + // the reference doesn't point into the collection set. Either way 1.124 + // we add the reference directly to the RSet of the region containing 1.125 + // the referenced object. 1.126 + _g1_rem_set->par_write_ref(_from, p, _worker_i); 1.127 + } 1.128 + } 1.129 +} 1.130 +