1.1 --- a/src/share/vm/memory/referenceProcessor.hpp Thu Sep 22 07:18:51 2011 -0400 1.2 +++ b/src/share/vm/memory/referenceProcessor.hpp Thu Sep 22 10:57:37 2011 -0700 1.3 @@ -48,18 +48,175 @@ 1.4 // forward references 1.5 class ReferencePolicy; 1.6 class AbstractRefProcTaskExecutor; 1.7 -class DiscoveredList; 1.8 + 1.9 +// List of discovered references. 1.10 +class DiscoveredList { 1.11 +public: 1.12 + DiscoveredList() : _len(0), _compressed_head(0), _oop_head(NULL) { } 1.13 + oop head() const { 1.14 + return UseCompressedOops ? oopDesc::decode_heap_oop(_compressed_head) : 1.15 + _oop_head; 1.16 + } 1.17 + HeapWord* adr_head() { 1.18 + return UseCompressedOops ? (HeapWord*)&_compressed_head : 1.19 + (HeapWord*)&_oop_head; 1.20 + } 1.21 + void set_head(oop o) { 1.22 + if (UseCompressedOops) { 1.23 + // Must compress the head ptr. 1.24 + _compressed_head = oopDesc::encode_heap_oop(o); 1.25 + } else { 1.26 + _oop_head = o; 1.27 + } 1.28 + } 1.29 + bool is_empty() const { return head() == NULL; } 1.30 + size_t length() { return _len; } 1.31 + void set_length(size_t len) { _len = len; } 1.32 + void inc_length(size_t inc) { _len += inc; assert(_len > 0, "Error"); } 1.33 + void dec_length(size_t dec) { _len -= dec; } 1.34 +private: 1.35 + // Set value depending on UseCompressedOops. This could be a template class 1.36 + // but then we have to fix all the instantiations and declarations that use this class. 1.37 + oop _oop_head; 1.38 + narrowOop _compressed_head; 1.39 + size_t _len; 1.40 +}; 1.41 + 1.42 +// Iterator for the list of discovered references. 1.43 +class DiscoveredListIterator { 1.44 +private: 1.45 + DiscoveredList& _refs_list; 1.46 + HeapWord* _prev_next; 1.47 + oop _prev; 1.48 + oop _ref; 1.49 + HeapWord* _discovered_addr; 1.50 + oop _next; 1.51 + HeapWord* _referent_addr; 1.52 + oop _referent; 1.53 + OopClosure* _keep_alive; 1.54 + BoolObjectClosure* _is_alive; 1.55 + 1.56 + DEBUG_ONLY( 1.57 + oop _first_seen; // cyclic linked list check 1.58 + ) 1.59 + 1.60 + NOT_PRODUCT( 1.61 + size_t _processed; 1.62 + size_t _removed; 1.63 + ) 1.64 + 1.65 +public: 1.66 + inline DiscoveredListIterator(DiscoveredList& refs_list, 1.67 + OopClosure* keep_alive, 1.68 + BoolObjectClosure* is_alive): 1.69 + _refs_list(refs_list), 1.70 + _prev_next(refs_list.adr_head()), 1.71 + _prev(NULL), 1.72 + _ref(refs_list.head()), 1.73 +#ifdef ASSERT 1.74 + _first_seen(refs_list.head()), 1.75 +#endif 1.76 +#ifndef PRODUCT 1.77 + _processed(0), 1.78 + _removed(0), 1.79 +#endif 1.80 + _next(NULL), 1.81 + _keep_alive(keep_alive), 1.82 + _is_alive(is_alive) 1.83 +{ } 1.84 + 1.85 + // End Of List. 1.86 + inline bool has_next() const { return _ref != NULL; } 1.87 + 1.88 + // Get oop to the Reference object. 1.89 + inline oop obj() const { return _ref; } 1.90 + 1.91 + // Get oop to the referent object. 1.92 + inline oop referent() const { return _referent; } 1.93 + 1.94 + // Returns true if referent is alive. 1.95 + inline bool is_referent_alive() const { 1.96 + return _is_alive->do_object_b(_referent); 1.97 + } 1.98 + 1.99 + // Loads data for the current reference. 1.100 + // The "allow_null_referent" argument tells us to allow for the possibility 1.101 + // of a NULL referent in the discovered Reference object. This typically 1.102 + // happens in the case of concurrent collectors that may have done the 1.103 + // discovery concurrently, or interleaved, with mutator execution. 1.104 + void load_ptrs(DEBUG_ONLY(bool allow_null_referent)); 1.105 + 1.106 + // Move to the next discovered reference. 1.107 + inline void next() { 1.108 + _prev_next = _discovered_addr; 1.109 + _prev = _ref; 1.110 + move_to_next(); 1.111 + } 1.112 + 1.113 + // Remove the current reference from the list 1.114 + void remove(); 1.115 + 1.116 + // Make the Reference object active again. 1.117 + void make_active(); 1.118 + 1.119 + // Make the referent alive. 1.120 + inline void make_referent_alive() { 1.121 + if (UseCompressedOops) { 1.122 + _keep_alive->do_oop((narrowOop*)_referent_addr); 1.123 + } else { 1.124 + _keep_alive->do_oop((oop*)_referent_addr); 1.125 + } 1.126 + } 1.127 + 1.128 + // Update the discovered field. 1.129 + inline void update_discovered() { 1.130 + // First _prev_next ref actually points into DiscoveredList (gross). 1.131 + if (UseCompressedOops) { 1.132 + if (!oopDesc::is_null(*(narrowOop*)_prev_next)) { 1.133 + _keep_alive->do_oop((narrowOop*)_prev_next); 1.134 + } 1.135 + } else { 1.136 + if (!oopDesc::is_null(*(oop*)_prev_next)) { 1.137 + _keep_alive->do_oop((oop*)_prev_next); 1.138 + } 1.139 + } 1.140 + } 1.141 + 1.142 + // NULL out referent pointer. 1.143 + void clear_referent(); 1.144 + 1.145 + // Statistics 1.146 + NOT_PRODUCT( 1.147 + inline size_t processed() const { return _processed; } 1.148 + inline size_t removed() const { return _removed; } 1.149 + ) 1.150 + 1.151 + inline void move_to_next() { 1.152 + if (_ref == _next) { 1.153 + // End of the list. 1.154 + _ref = NULL; 1.155 + } else { 1.156 + _ref = _next; 1.157 + } 1.158 + assert(_ref != _first_seen, "cyclic ref_list found"); 1.159 + NOT_PRODUCT(_processed++); 1.160 + } 1.161 + 1.162 +}; 1.163 1.164 class ReferenceProcessor : public CHeapObj { 1.165 protected: 1.166 // Compatibility with pre-4965777 JDK's 1.167 static bool _pending_list_uses_discovered_field; 1.168 - MemRegion _span; // (right-open) interval of heap 1.169 - // subject to wkref discovery 1.170 - bool _discovering_refs; // true when discovery enabled 1.171 - bool _discovery_is_atomic; // if discovery is atomic wrt 1.172 - // other collectors in configuration 1.173 - bool _discovery_is_mt; // true if reference discovery is MT. 1.174 + 1.175 + MemRegion _span; // (right-open) interval of heap 1.176 + // subject to wkref discovery 1.177 + 1.178 + bool _discovering_refs; // true when discovery enabled 1.179 + bool _discovery_is_atomic; // if discovery is atomic wrt 1.180 + // other collectors in configuration 1.181 + bool _discovery_is_mt; // true if reference discovery is MT. 1.182 + 1.183 // If true, setting "next" field of a discovered refs list requires 1.184 // write barrier(s). (Must be true if used in a collector in which 1.185 // elements of a discovered list may be moved during discovery: for 1.186 @@ -67,18 +224,19 @@ 1.187 // long-term concurrent marking phase that does weak reference 1.188 // discovery.) 1.189 bool _discovered_list_needs_barrier; 1.190 - BarrierSet* _bs; // Cached copy of BarrierSet. 1.191 - bool _enqueuing_is_done; // true if all weak references enqueued 1.192 - bool _processing_is_mt; // true during phases when 1.193 - // reference processing is MT. 1.194 - int _next_id; // round-robin mod _num_q counter in 1.195 - // support of work distribution 1.196 1.197 - // For collectors that do not keep GC marking information 1.198 + BarrierSet* _bs; // Cached copy of BarrierSet. 1.199 + bool _enqueuing_is_done; // true if all weak references enqueued 1.200 + bool _processing_is_mt; // true during phases when 1.201 + // reference processing is MT. 1.202 + int _next_id; // round-robin mod _num_q counter in 1.203 + // support of work distribution 1.204 + 1.205 + // For collectors that do not keep GC liveness information 1.206 // in the object header, this field holds a closure that 1.207 // helps the reference processor determine the reachability 1.208 - // of an oop (the field is currently initialized to NULL for 1.209 - // all collectors but the CMS collector). 1.210 + // of an oop. It is currently initialized to NULL for all 1.211 + // collectors except for CMS and G1. 1.212 BoolObjectClosure* _is_alive_non_header; 1.213 1.214 // Soft ref clearing policies 1.215 @@ -102,10 +260,13 @@ 1.216 DiscoveredList* _discoveredPhantomRefs; 1.217 1.218 public: 1.219 - int num_q() { return _num_q; } 1.220 - int max_num_q() { return _max_num_q; } 1.221 - void set_active_mt_degree(int v) { _num_q = v; } 1.222 - DiscoveredList* discovered_soft_refs() { return _discoveredSoftRefs; } 1.223 + static int number_of_subclasses_of_ref() { return (REF_PHANTOM - REF_OTHER); } 1.224 + 1.225 + int num_q() { return _num_q; } 1.226 + int max_num_q() { return _max_num_q; } 1.227 + void set_active_mt_degree(int v) { _num_q = v; } 1.228 + DiscoveredList* discovered_soft_refs() { return _discoveredSoftRefs; } 1.229 + 1.230 ReferencePolicy* setup_policy(bool always_clear) { 1.231 _current_soft_ref_policy = always_clear ? 1.232 _always_clear_soft_ref_policy : _default_soft_ref_policy; 1.233 @@ -205,6 +366,11 @@ 1.234 void enqueue_discovered_reflists(HeapWord* pending_list_addr, AbstractRefProcTaskExecutor* task_executor); 1.235 1.236 protected: 1.237 + // Set the 'discovered' field of the given reference to 1.238 + // the given value - emitting barriers depending upon 1.239 + // the value of _discovered_list_needs_barrier. 1.240 + void set_discovered(oop ref, oop value); 1.241 + 1.242 // "Preclean" the given discovered reference list 1.243 // by removing references with strongly reachable referents. 1.244 // Currently used in support of CMS only. 1.245 @@ -290,7 +456,19 @@ 1.246 void set_span(MemRegion span) { _span = span; } 1.247 1.248 // start and stop weak ref discovery 1.249 - void enable_discovery() { _discovering_refs = true; } 1.250 + void enable_discovery(bool verify_disabled, bool check_no_refs) { 1.251 +#ifdef ASSERT 1.252 + // Verify that we're not currently discovering refs 1.253 + assert(!verify_disabled || !_discovering_refs, "nested call?"); 1.254 + 1.255 + if (check_no_refs) { 1.256 + // Verify that the discovered lists are empty 1.257 + verify_no_references_recorded(); 1.258 + } 1.259 +#endif // ASSERT 1.260 + _discovering_refs = true; 1.261 + } 1.262 + 1.263 void disable_discovery() { _discovering_refs = false; } 1.264 bool discovery_enabled() { return _discovering_refs; } 1.265 1.266 @@ -365,7 +543,7 @@ 1.267 1.268 ~NoRefDiscovery() { 1.269 if (_was_discovering_refs) { 1.270 - _rp->enable_discovery(); 1.271 + _rp->enable_discovery(true /*verify_disabled*/, false /*check_no_refs*/); 1.272 } 1.273 } 1.274 };