1.1 --- a/src/share/vm/memory/referenceProcessor.cpp Wed Nov 19 14:20:51 2008 -0800 1.2 +++ b/src/share/vm/memory/referenceProcessor.cpp Thu Nov 20 12:27:41 2008 -0800 1.3 @@ -47,7 +47,9 @@ 1.4 } 1.5 bool empty() const { return head() == ReferenceProcessor::sentinel_ref(); } 1.6 size_t length() { return _len; } 1.7 - void set_length(size_t len) { _len = len; } 1.8 + void set_length(size_t len) { _len = len; } 1.9 + void inc_length(size_t inc) { _len += inc; assert(_len > 0, "Error"); } 1.10 + void dec_length(size_t dec) { _len -= dec; } 1.11 private: 1.12 // Set value depending on UseCompressedOops. This could be a template class 1.13 // but then we have to fix all the instantiations and declarations that use this class. 1.14 @@ -436,13 +438,13 @@ 1.15 // The "allow_null_referent" argument tells us to allow for the possibility 1.16 // of a NULL referent in the discovered Reference object. This typically 1.17 // happens in the case of concurrent collectors that may have done the 1.18 - // discovery concurrently or interleaved with mutator execution. 1.19 + // discovery concurrently, or interleaved, with mutator execution. 1.20 inline void load_ptrs(DEBUG_ONLY(bool allow_null_referent)); 1.21 1.22 // Move to the next discovered reference. 1.23 inline void next(); 1.24 1.25 - // Remove the current reference from the list and move to the next. 1.26 + // Remove the current reference from the list 1.27 inline void remove(); 1.28 1.29 // Make the Reference object active again. 1.30 @@ -476,7 +478,6 @@ 1.31 inline size_t removed() const { return _removed; } 1.32 ) 1.33 1.34 -private: 1.35 inline void move_to_next(); 1.36 1.37 private: 1.38 @@ -553,7 +554,7 @@ 1.39 oopDesc::store_heap_oop((oop*)_prev_next, _next); 1.40 } 1.41 NOT_PRODUCT(_removed++); 1.42 - move_to_next(); 1.43 + _refs_list.dec_length(1); 1.44 } 1.45 1.46 inline void DiscoveredListIterator::move_to_next() { 1.47 @@ -591,12 +592,13 @@ 1.48 gclog_or_tty->print_cr("Dropping reference (" INTPTR_FORMAT ": %s" ") by policy", 1.49 iter.obj(), iter.obj()->blueprint()->internal_name()); 1.50 } 1.51 + // Remove Reference object from list 1.52 + iter.remove(); 1.53 // Make the Reference object active again 1.54 iter.make_active(); 1.55 // keep the referent around 1.56 iter.make_referent_alive(); 1.57 - // Remove Reference object from list 1.58 - iter.remove(); 1.59 + iter.move_to_next(); 1.60 } else { 1.61 iter.next(); 1.62 } 1.63 @@ -629,12 +631,13 @@ 1.64 iter.obj(), iter.obj()->blueprint()->internal_name()); 1.65 } 1.66 // The referent is reachable after all. 1.67 + // Remove Reference object from list. 1.68 + iter.remove(); 1.69 // Update the referent pointer as necessary: Note that this 1.70 // should not entail any recursive marking because the 1.71 // referent must already have been traversed. 1.72 iter.make_referent_alive(); 1.73 - // Remove Reference object from list 1.74 - iter.remove(); 1.75 + iter.move_to_next(); 1.76 } else { 1.77 iter.next(); 1.78 } 1.79 @@ -670,6 +673,7 @@ 1.80 } else { 1.81 keep_alive->do_oop((oop*)next_addr); 1.82 } 1.83 + iter.move_to_next(); 1.84 } else { 1.85 iter.next(); 1.86 } 1.87 @@ -832,9 +836,9 @@ 1.88 } 1.89 java_lang_ref_Reference::set_discovered(move_tail, ref_lists[to_idx].head()); 1.90 ref_lists[to_idx].set_head(move_head); 1.91 - ref_lists[to_idx].set_length(ref_lists[to_idx].length() + refs_to_move); 1.92 + ref_lists[to_idx].inc_length(refs_to_move); 1.93 ref_lists[from_idx].set_head(new_head); 1.94 - ref_lists[from_idx].set_length(ref_lists[from_idx].length() - refs_to_move); 1.95 + ref_lists[from_idx].dec_length(refs_to_move); 1.96 } else { 1.97 ++to_idx; 1.98 } 1.99 @@ -923,7 +927,6 @@ 1.100 void ReferenceProcessor::clean_up_discovered_reflist(DiscoveredList& refs_list) { 1.101 assert(!discovery_is_atomic(), "Else why call this method?"); 1.102 DiscoveredListIterator iter(refs_list, NULL, NULL); 1.103 - size_t length = refs_list.length(); 1.104 while (iter.has_next()) { 1.105 iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */)); 1.106 oop next = java_lang_ref_Reference::next(iter.obj()); 1.107 @@ -941,12 +944,11 @@ 1.108 ) 1.109 // Remove Reference object from list 1.110 iter.remove(); 1.111 - --length; 1.112 + iter.move_to_next(); 1.113 } else { 1.114 iter.next(); 1.115 } 1.116 } 1.117 - refs_list.set_length(length); 1.118 NOT_PRODUCT( 1.119 if (PrintGCDetails && TraceReferenceGC) { 1.120 gclog_or_tty->print( 1.121 @@ -1024,7 +1026,7 @@ 1.122 // We have separate lists for enqueueing so no synchronization 1.123 // is necessary. 1.124 refs_list.set_head(obj); 1.125 - refs_list.set_length(refs_list.length() + 1); 1.126 + refs_list.inc_length(1); 1.127 if (_discovered_list_needs_barrier) { 1.128 _bs->write_ref_field((void*)discovered_addr, current_head); guarantee(false, "Needs to be fixed: YSR"); 1.129 } 1.130 @@ -1168,7 +1170,7 @@ 1.131 _bs->write_ref_field((oop*)discovered_addr, current_head); 1.132 } 1.133 list->set_head(obj); 1.134 - list->set_length(list->length() + 1); 1.135 + list->inc_length(1); 1.136 } 1.137 1.138 // In the MT discovery case, it is currently possible to see 1.139 @@ -1209,45 +1211,48 @@ 1.140 TraceTime tt("Preclean SoftReferences", PrintGCDetails && PrintReferenceGC, 1.141 false, gclog_or_tty); 1.142 for (int i = 0; i < _num_q; i++) { 1.143 + if (yield->should_return()) { 1.144 + return; 1.145 + } 1.146 preclean_discovered_reflist(_discoveredSoftRefs[i], is_alive, 1.147 keep_alive, complete_gc, yield); 1.148 } 1.149 } 1.150 - if (yield->should_return()) { 1.151 - return; 1.152 - } 1.153 1.154 // Weak references 1.155 { 1.156 TraceTime tt("Preclean WeakReferences", PrintGCDetails && PrintReferenceGC, 1.157 false, gclog_or_tty); 1.158 for (int i = 0; i < _num_q; i++) { 1.159 + if (yield->should_return()) { 1.160 + return; 1.161 + } 1.162 preclean_discovered_reflist(_discoveredWeakRefs[i], is_alive, 1.163 keep_alive, complete_gc, yield); 1.164 } 1.165 } 1.166 - if (yield->should_return()) { 1.167 - return; 1.168 - } 1.169 1.170 // Final references 1.171 { 1.172 TraceTime tt("Preclean FinalReferences", PrintGCDetails && PrintReferenceGC, 1.173 false, gclog_or_tty); 1.174 for (int i = 0; i < _num_q; i++) { 1.175 + if (yield->should_return()) { 1.176 + return; 1.177 + } 1.178 preclean_discovered_reflist(_discoveredFinalRefs[i], is_alive, 1.179 keep_alive, complete_gc, yield); 1.180 } 1.181 } 1.182 - if (yield->should_return()) { 1.183 - return; 1.184 - } 1.185 1.186 // Phantom references 1.187 { 1.188 TraceTime tt("Preclean PhantomReferences", PrintGCDetails && PrintReferenceGC, 1.189 false, gclog_or_tty); 1.190 for (int i = 0; i < _num_q; i++) { 1.191 + if (yield->should_return()) { 1.192 + return; 1.193 + } 1.194 preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive, 1.195 keep_alive, complete_gc, yield); 1.196 } 1.197 @@ -1256,9 +1261,12 @@ 1.198 1.199 // Walk the given discovered ref list, and remove all reference objects 1.200 // whose referents are still alive, whose referents are NULL or which 1.201 -// are not active (have a non-NULL next field). NOTE: For this to work 1.202 -// correctly, refs discovery can not be happening concurrently with this 1.203 -// step. 1.204 +// are not active (have a non-NULL next field). NOTE: When we are 1.205 +// thus precleaning the ref lists (which happens single-threaded today), 1.206 +// we do not disable refs discovery to honour the correct semantics of 1.207 +// java.lang.Reference. As a result, we need to be careful below 1.208 +// that ref removal steps interleave safely with ref discovery steps 1.209 +// (in this thread). 1.210 void 1.211 ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list, 1.212 BoolObjectClosure* is_alive, 1.213 @@ -1266,7 +1274,6 @@ 1.214 VoidClosure* complete_gc, 1.215 YieldClosure* yield) { 1.216 DiscoveredListIterator iter(refs_list, keep_alive, is_alive); 1.217 - size_t length = refs_list.length(); 1.218 while (iter.has_next()) { 1.219 iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */)); 1.220 oop obj = iter.obj(); 1.221 @@ -1281,7 +1288,6 @@ 1.222 } 1.223 // Remove Reference object from list 1.224 iter.remove(); 1.225 - --length; 1.226 // Keep alive its cohort. 1.227 iter.make_referent_alive(); 1.228 if (UseCompressedOops) { 1.229 @@ -1291,12 +1297,11 @@ 1.230 oop* next_addr = (oop*)java_lang_ref_Reference::next_addr(obj); 1.231 keep_alive->do_oop(next_addr); 1.232 } 1.233 + iter.move_to_next(); 1.234 } else { 1.235 iter.next(); 1.236 } 1.237 } 1.238 - refs_list.set_length(length); 1.239 - 1.240 // Close the reachable set 1.241 complete_gc->do_void(); 1.242