Mercurial > hg > truffle
annotate src/share/vm/memory/referenceProcessor.cpp @ 453:c96030fff130
6684579: SoftReference processing can be made more efficient
Summary: For current soft-ref clearing policies, we can decide at marking time if a soft-reference will definitely not be cleared, postponing the decision of whether it will definitely be cleared to the final reference processing phase. This can be especially beneficial in the case of concurrent collectors where the marking is usually concurrent but reference processing is usually not.
Reviewed-by: jmasa
author | ysr |
---|---|
date | Thu, 20 Nov 2008 16:56:09 -0800 |
parents | 00b023ae2d78 |
children | 27a80744a83b |
rev | line source |
---|---|
0 | 1 /* |
196 | 2 * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 # include "incls/_precompiled.incl" | |
26 # include "incls/_referenceProcessor.cpp.incl" | |
27 | |
453
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
28 ReferencePolicy* ReferenceProcessor::_always_clear_soft_ref_policy = NULL; |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
29 ReferencePolicy* ReferenceProcessor::_default_soft_ref_policy = NULL; |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
30 oop ReferenceProcessor::_sentinelRef = NULL; |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
31 const int subclasses_of_ref = REF_PHANTOM - REF_OTHER; |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
32 |
0 | 33 // List of discovered references. |
34 class DiscoveredList { | |
35 public: | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
36 DiscoveredList() : _len(0), _compressed_head(0), _oop_head(NULL) { } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
37 oop head() const { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
38 return UseCompressedOops ? oopDesc::decode_heap_oop_not_null(_compressed_head) : |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
39 _oop_head; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
40 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
41 HeapWord* adr_head() { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
42 return UseCompressedOops ? (HeapWord*)&_compressed_head : |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
43 (HeapWord*)&_oop_head; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
44 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
45 void set_head(oop o) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
46 if (UseCompressedOops) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
47 // Must compress the head ptr. |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
48 _compressed_head = oopDesc::encode_heap_oop_not_null(o); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
49 } else { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
50 _oop_head = o; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
51 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
52 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
53 bool empty() const { return head() == ReferenceProcessor::sentinel_ref(); } |
0 | 54 size_t length() { return _len; } |
452
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
55 void set_length(size_t len) { _len = len; } |
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
56 void inc_length(size_t inc) { _len += inc; assert(_len > 0, "Error"); } |
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
57 void dec_length(size_t dec) { _len -= dec; } |
0 | 58 private: |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
59 // Set value depending on UseCompressedOops. This could be a template class |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
60 // but then we have to fix all the instantiations and declarations that use this class. |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
61 oop _oop_head; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
62 narrowOop _compressed_head; |
0 | 63 size_t _len; |
64 }; | |
65 | |
66 void referenceProcessor_init() { | |
67 ReferenceProcessor::init_statics(); | |
68 } | |
69 | |
70 void ReferenceProcessor::init_statics() { | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
71 assert(_sentinelRef == NULL, "should be initialized precisely once"); |
0 | 72 EXCEPTION_MARK; |
73 _sentinelRef = instanceKlass::cast( | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
74 SystemDictionary::reference_klass())-> |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
75 allocate_permanent_instance(THREAD); |
0 | 76 |
77 // Initialize the master soft ref clock. | |
78 java_lang_ref_SoftReference::set_clock(os::javaTimeMillis()); | |
79 | |
80 if (HAS_PENDING_EXCEPTION) { | |
81 Handle ex(THREAD, PENDING_EXCEPTION); | |
82 vm_exit_during_initialization(ex); | |
83 } | |
84 assert(_sentinelRef != NULL && _sentinelRef->is_oop(), | |
85 "Just constructed it!"); | |
453
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
86 _always_clear_soft_ref_policy = new AlwaysClearPolicy(); |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
87 _default_soft_ref_policy = new COMPILER2_PRESENT(LRUMaxHeapPolicy()) |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
88 NOT_COMPILER2(LRUCurrentHeapPolicy()); |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
89 if (_always_clear_soft_ref_policy == NULL || _default_soft_ref_policy == NULL) { |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
90 vm_exit_during_initialization("Could not allocate reference policy object"); |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
91 } |
0 | 92 guarantee(RefDiscoveryPolicy == ReferenceBasedDiscovery || |
93 RefDiscoveryPolicy == ReferentBasedDiscovery, | |
94 "Unrecongnized RefDiscoveryPolicy"); | |
95 } | |
96 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
97 ReferenceProcessor* |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
98 ReferenceProcessor::create_ref_processor(MemRegion span, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
99 bool atomic_discovery, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
100 bool mt_discovery, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
101 BoolObjectClosure* is_alive_non_header, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
102 int parallel_gc_threads, |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
103 bool mt_processing, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
104 bool dl_needs_barrier) { |
0 | 105 int mt_degree = 1; |
106 if (parallel_gc_threads > 1) { | |
107 mt_degree = parallel_gc_threads; | |
108 } | |
109 ReferenceProcessor* rp = | |
110 new ReferenceProcessor(span, atomic_discovery, | |
111 mt_discovery, mt_degree, | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
112 mt_processing && (parallel_gc_threads > 0), |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
113 dl_needs_barrier); |
0 | 114 if (rp == NULL) { |
115 vm_exit_during_initialization("Could not allocate ReferenceProcessor object"); | |
116 } | |
117 rp->set_is_alive_non_header(is_alive_non_header); | |
453
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
118 rp->snap_policy(false /* default soft ref policy */); |
0 | 119 return rp; |
120 } | |
121 | |
122 ReferenceProcessor::ReferenceProcessor(MemRegion span, | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
123 bool atomic_discovery, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
124 bool mt_discovery, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
125 int mt_degree, |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
126 bool mt_processing, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
127 bool discovered_list_needs_barrier) : |
0 | 128 _discovering_refs(false), |
129 _enqueuing_is_done(false), | |
130 _is_alive_non_header(NULL), | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
131 _discovered_list_needs_barrier(discovered_list_needs_barrier), |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
132 _bs(NULL), |
0 | 133 _processing_is_mt(mt_processing), |
134 _next_id(0) | |
135 { | |
136 _span = span; | |
137 _discovery_is_atomic = atomic_discovery; | |
138 _discovery_is_mt = mt_discovery; | |
139 _num_q = mt_degree; | |
140 _discoveredSoftRefs = NEW_C_HEAP_ARRAY(DiscoveredList, _num_q * subclasses_of_ref); | |
141 if (_discoveredSoftRefs == NULL) { | |
142 vm_exit_during_initialization("Could not allocated RefProc Array"); | |
143 } | |
144 _discoveredWeakRefs = &_discoveredSoftRefs[_num_q]; | |
145 _discoveredFinalRefs = &_discoveredWeakRefs[_num_q]; | |
146 _discoveredPhantomRefs = &_discoveredFinalRefs[_num_q]; | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
147 assert(sentinel_ref() != NULL, "_sentinelRef is NULL"); |
0 | 148 // Initialized all entries to _sentinelRef |
149 for (int i = 0; i < _num_q * subclasses_of_ref; i++) { | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
150 _discoveredSoftRefs[i].set_head(sentinel_ref()); |
0 | 151 _discoveredSoftRefs[i].set_length(0); |
152 } | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
153 // If we do barreirs, cache a copy of the barrier set. |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
154 if (discovered_list_needs_barrier) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
155 _bs = Universe::heap()->barrier_set(); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
156 } |
0 | 157 } |
158 | |
159 #ifndef PRODUCT | |
160 void ReferenceProcessor::verify_no_references_recorded() { | |
161 guarantee(!_discovering_refs, "Discovering refs?"); | |
162 for (int i = 0; i < _num_q * subclasses_of_ref; i++) { | |
163 guarantee(_discoveredSoftRefs[i].empty(), | |
164 "Found non-empty discovered list"); | |
165 } | |
166 } | |
167 #endif | |
168 | |
169 void ReferenceProcessor::weak_oops_do(OopClosure* f) { | |
170 for (int i = 0; i < _num_q * subclasses_of_ref; i++) { | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
171 if (UseCompressedOops) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
172 f->do_oop((narrowOop*)_discoveredSoftRefs[i].adr_head()); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
173 } else { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
174 f->do_oop((oop*)_discoveredSoftRefs[i].adr_head()); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
175 } |
0 | 176 } |
177 } | |
178 | |
179 void ReferenceProcessor::oops_do(OopClosure* f) { | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
180 f->do_oop(adr_sentinel_ref()); |
0 | 181 } |
182 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
183 void ReferenceProcessor::update_soft_ref_master_clock() { |
0 | 184 // Update (advance) the soft ref master clock field. This must be done |
185 // after processing the soft ref list. | |
186 jlong now = os::javaTimeMillis(); | |
187 jlong clock = java_lang_ref_SoftReference::clock(); | |
188 NOT_PRODUCT( | |
189 if (now < clock) { | |
190 warning("time warp: %d to %d", clock, now); | |
191 } | |
192 ) | |
193 // In product mode, protect ourselves from system time being adjusted | |
194 // externally and going backward; see note in the implementation of | |
195 // GenCollectedHeap::time_since_last_gc() for the right way to fix | |
196 // this uniformly throughout the VM; see bug-id 4741166. XXX | |
197 if (now > clock) { | |
198 java_lang_ref_SoftReference::set_clock(now); | |
199 } | |
200 // Else leave clock stalled at its old value until time progresses | |
201 // past clock value. | |
202 } | |
203 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
204 void ReferenceProcessor::process_discovered_references( |
0 | 205 BoolObjectClosure* is_alive, |
206 OopClosure* keep_alive, | |
207 VoidClosure* complete_gc, | |
208 AbstractRefProcTaskExecutor* task_executor) { | |
209 NOT_PRODUCT(verify_ok_to_handle_reflists()); | |
210 | |
211 assert(!enqueuing_is_done(), "If here enqueuing should not be complete"); | |
212 // Stop treating discovered references specially. | |
213 disable_discovery(); | |
214 | |
215 bool trace_time = PrintGCDetails && PrintReferenceGC; | |
216 // Soft references | |
217 { | |
218 TraceTime tt("SoftReference", trace_time, false, gclog_or_tty); | |
453
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
219 process_discovered_reflist(_discoveredSoftRefs, _current_soft_ref_policy, true, |
0 | 220 is_alive, keep_alive, complete_gc, task_executor); |
221 } | |
222 | |
223 update_soft_ref_master_clock(); | |
224 | |
225 // Weak references | |
226 { | |
227 TraceTime tt("WeakReference", trace_time, false, gclog_or_tty); | |
228 process_discovered_reflist(_discoveredWeakRefs, NULL, true, | |
229 is_alive, keep_alive, complete_gc, task_executor); | |
230 } | |
231 | |
232 // Final references | |
233 { | |
234 TraceTime tt("FinalReference", trace_time, false, gclog_or_tty); | |
235 process_discovered_reflist(_discoveredFinalRefs, NULL, false, | |
236 is_alive, keep_alive, complete_gc, task_executor); | |
237 } | |
238 | |
239 // Phantom references | |
240 { | |
241 TraceTime tt("PhantomReference", trace_time, false, gclog_or_tty); | |
242 process_discovered_reflist(_discoveredPhantomRefs, NULL, false, | |
243 is_alive, keep_alive, complete_gc, task_executor); | |
244 } | |
245 | |
246 // Weak global JNI references. It would make more sense (semantically) to | |
247 // traverse these simultaneously with the regular weak references above, but | |
248 // that is not how the JDK1.2 specification is. See #4126360. Native code can | |
249 // thus use JNI weak references to circumvent the phantom references and | |
250 // resurrect a "post-mortem" object. | |
251 { | |
252 TraceTime tt("JNI Weak Reference", trace_time, false, gclog_or_tty); | |
253 if (task_executor != NULL) { | |
254 task_executor->set_single_threaded_mode(); | |
255 } | |
256 process_phaseJNI(is_alive, keep_alive, complete_gc); | |
257 } | |
258 } | |
259 | |
260 #ifndef PRODUCT | |
261 // Calculate the number of jni handles. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
262 uint ReferenceProcessor::count_jni_refs() { |
0 | 263 class AlwaysAliveClosure: public BoolObjectClosure { |
264 public: | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
265 virtual bool do_object_b(oop obj) { return true; } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
266 virtual void do_object(oop obj) { assert(false, "Don't call"); } |
0 | 267 }; |
268 | |
269 class CountHandleClosure: public OopClosure { | |
270 private: | |
271 int _count; | |
272 public: | |
273 CountHandleClosure(): _count(0) {} | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
274 void do_oop(oop* unused) { _count++; } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
275 void do_oop(narrowOop* unused) { ShouldNotReachHere(); } |
0 | 276 int count() { return _count; } |
277 }; | |
278 CountHandleClosure global_handle_count; | |
279 AlwaysAliveClosure always_alive; | |
280 JNIHandles::weak_oops_do(&always_alive, &global_handle_count); | |
281 return global_handle_count.count(); | |
282 } | |
283 #endif | |
284 | |
285 void ReferenceProcessor::process_phaseJNI(BoolObjectClosure* is_alive, | |
286 OopClosure* keep_alive, | |
287 VoidClosure* complete_gc) { | |
288 #ifndef PRODUCT | |
289 if (PrintGCDetails && PrintReferenceGC) { | |
290 unsigned int count = count_jni_refs(); | |
291 gclog_or_tty->print(", %u refs", count); | |
292 } | |
293 #endif | |
294 JNIHandles::weak_oops_do(is_alive, keep_alive); | |
295 // Finally remember to keep sentinel around | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
296 keep_alive->do_oop(adr_sentinel_ref()); |
0 | 297 complete_gc->do_void(); |
298 } | |
299 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
300 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
301 template <class T> |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
302 static bool enqueue_discovered_ref_helper(ReferenceProcessor* ref, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
303 AbstractRefProcTaskExecutor* task_executor) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
304 |
0 | 305 // Remember old value of pending references list |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
306 T* pending_list_addr = (T*)java_lang_ref_Reference::pending_list_addr(); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
307 T old_pending_list_value = *pending_list_addr; |
0 | 308 |
309 // Enqueue references that are not made active again, and | |
310 // clear the decks for the next collection (cycle). | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
311 ref->enqueue_discovered_reflists((HeapWord*)pending_list_addr, task_executor); |
0 | 312 // Do the oop-check on pending_list_addr missed in |
313 // enqueue_discovered_reflist. We should probably | |
314 // do a raw oop_check so that future such idempotent | |
315 // oop_stores relying on the oop-check side-effect | |
316 // may be elided automatically and safely without | |
317 // affecting correctness. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
318 oop_store(pending_list_addr, oopDesc::load_decode_heap_oop(pending_list_addr)); |
0 | 319 |
320 // Stop treating discovered references specially. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
321 ref->disable_discovery(); |
0 | 322 |
323 // Return true if new pending references were added | |
324 return old_pending_list_value != *pending_list_addr; | |
325 } | |
326 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
327 bool ReferenceProcessor::enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
328 NOT_PRODUCT(verify_ok_to_handle_reflists()); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
329 if (UseCompressedOops) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
330 return enqueue_discovered_ref_helper<narrowOop>(this, task_executor); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
331 } else { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
332 return enqueue_discovered_ref_helper<oop>(this, task_executor); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
333 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
334 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
335 |
0 | 336 void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list, |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
337 HeapWord* pending_list_addr) { |
0 | 338 // Given a list of refs linked through the "discovered" field |
339 // (java.lang.ref.Reference.discovered) chain them through the | |
340 // "next" field (java.lang.ref.Reference.next) and prepend | |
341 // to the pending list. | |
342 if (TraceReferenceGC && PrintGCDetails) { | |
343 gclog_or_tty->print_cr("ReferenceProcessor::enqueue_discovered_reflist list " | |
344 INTPTR_FORMAT, (address)refs_list.head()); | |
345 } | |
346 oop obj = refs_list.head(); | |
347 // Walk down the list, copying the discovered field into | |
348 // the next field and clearing it (except for the last | |
349 // non-sentinel object which is treated specially to avoid | |
350 // confusion with an active reference). | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
351 while (obj != sentinel_ref()) { |
0 | 352 assert(obj->is_instanceRef(), "should be reference object"); |
353 oop next = java_lang_ref_Reference::discovered(obj); | |
354 if (TraceReferenceGC && PrintGCDetails) { | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
355 gclog_or_tty->print_cr(" obj " INTPTR_FORMAT "/next " INTPTR_FORMAT, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
356 obj, next); |
0 | 357 } |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
358 assert(java_lang_ref_Reference::next(obj) == NULL, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
359 "The reference should not be enqueued"); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
360 if (next == sentinel_ref()) { // obj is last |
0 | 361 // Swap refs_list into pendling_list_addr and |
362 // set obj's next to what we read from pending_list_addr. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
363 oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr); |
0 | 364 // Need oop_check on pending_list_addr above; |
365 // see special oop-check code at the end of | |
366 // enqueue_discovered_reflists() further below. | |
367 if (old == NULL) { | |
368 // obj should be made to point to itself, since | |
369 // pending list was empty. | |
370 java_lang_ref_Reference::set_next(obj, obj); | |
371 } else { | |
372 java_lang_ref_Reference::set_next(obj, old); | |
373 } | |
374 } else { | |
375 java_lang_ref_Reference::set_next(obj, next); | |
376 } | |
377 java_lang_ref_Reference::set_discovered(obj, (oop) NULL); | |
378 obj = next; | |
379 } | |
380 } | |
381 | |
382 // Parallel enqueue task | |
383 class RefProcEnqueueTask: public AbstractRefProcTaskExecutor::EnqueueTask { | |
384 public: | |
385 RefProcEnqueueTask(ReferenceProcessor& ref_processor, | |
386 DiscoveredList discovered_refs[], | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
387 HeapWord* pending_list_addr, |
0 | 388 oop sentinel_ref, |
389 int n_queues) | |
390 : EnqueueTask(ref_processor, discovered_refs, | |
391 pending_list_addr, sentinel_ref, n_queues) | |
392 { } | |
393 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
394 virtual void work(unsigned int work_id) { |
0 | 395 assert(work_id < (unsigned int)_ref_processor.num_q(), "Index out-of-bounds"); |
396 // Simplest first cut: static partitioning. | |
397 int index = work_id; | |
398 for (int j = 0; j < subclasses_of_ref; j++, index += _n_queues) { | |
399 _ref_processor.enqueue_discovered_reflist( | |
400 _refs_lists[index], _pending_list_addr); | |
401 _refs_lists[index].set_head(_sentinel_ref); | |
402 _refs_lists[index].set_length(0); | |
403 } | |
404 } | |
405 }; | |
406 | |
407 // Enqueue references that are not made active again | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
408 void ReferenceProcessor::enqueue_discovered_reflists(HeapWord* pending_list_addr, |
0 | 409 AbstractRefProcTaskExecutor* task_executor) { |
410 if (_processing_is_mt && task_executor != NULL) { | |
411 // Parallel code | |
412 RefProcEnqueueTask tsk(*this, _discoveredSoftRefs, | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
413 pending_list_addr, sentinel_ref(), _num_q); |
0 | 414 task_executor->execute(tsk); |
415 } else { | |
416 // Serial code: call the parent class's implementation | |
417 for (int i = 0; i < _num_q * subclasses_of_ref; i++) { | |
418 enqueue_discovered_reflist(_discoveredSoftRefs[i], pending_list_addr); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
419 _discoveredSoftRefs[i].set_head(sentinel_ref()); |
0 | 420 _discoveredSoftRefs[i].set_length(0); |
421 } | |
422 } | |
423 } | |
424 | |
425 // Iterator for the list of discovered references. | |
426 class DiscoveredListIterator { | |
427 public: | |
428 inline DiscoveredListIterator(DiscoveredList& refs_list, | |
429 OopClosure* keep_alive, | |
430 BoolObjectClosure* is_alive); | |
431 | |
432 // End Of List. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
433 inline bool has_next() const { return _next != ReferenceProcessor::sentinel_ref(); } |
0 | 434 |
435 // Get oop to the Reference object. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
436 inline oop obj() const { return _ref; } |
0 | 437 |
438 // Get oop to the referent object. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
439 inline oop referent() const { return _referent; } |
0 | 440 |
441 // Returns true if referent is alive. | |
442 inline bool is_referent_alive() const; | |
443 | |
444 // Loads data for the current reference. | |
445 // The "allow_null_referent" argument tells us to allow for the possibility | |
446 // of a NULL referent in the discovered Reference object. This typically | |
447 // happens in the case of concurrent collectors that may have done the | |
452
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
448 // discovery concurrently, or interleaved, with mutator execution. |
0 | 449 inline void load_ptrs(DEBUG_ONLY(bool allow_null_referent)); |
450 | |
451 // Move to the next discovered reference. | |
452 inline void next(); | |
453 | |
452
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
454 // Remove the current reference from the list |
0 | 455 inline void remove(); |
456 | |
457 // Make the Reference object active again. | |
458 inline void make_active() { java_lang_ref_Reference::set_next(_ref, NULL); } | |
459 | |
460 // Make the referent alive. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
461 inline void make_referent_alive() { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
462 if (UseCompressedOops) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
463 _keep_alive->do_oop((narrowOop*)_referent_addr); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
464 } else { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
465 _keep_alive->do_oop((oop*)_referent_addr); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
466 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
467 } |
0 | 468 |
469 // Update the discovered field. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
470 inline void update_discovered() { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
471 // First _prev_next ref actually points into DiscoveredList (gross). |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
472 if (UseCompressedOops) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
473 _keep_alive->do_oop((narrowOop*)_prev_next); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
474 } else { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
475 _keep_alive->do_oop((oop*)_prev_next); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
476 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
477 } |
0 | 478 |
479 // NULL out referent pointer. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
480 inline void clear_referent() { oop_store_raw(_referent_addr, NULL); } |
0 | 481 |
482 // Statistics | |
483 NOT_PRODUCT( | |
484 inline size_t processed() const { return _processed; } | |
485 inline size_t removed() const { return _removed; } | |
486 ) | |
487 | |
488 inline void move_to_next(); | |
489 | |
490 private: | |
491 DiscoveredList& _refs_list; | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
492 HeapWord* _prev_next; |
0 | 493 oop _ref; |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
494 HeapWord* _discovered_addr; |
0 | 495 oop _next; |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
496 HeapWord* _referent_addr; |
0 | 497 oop _referent; |
498 OopClosure* _keep_alive; | |
499 BoolObjectClosure* _is_alive; | |
500 DEBUG_ONLY( | |
501 oop _first_seen; // cyclic linked list check | |
502 ) | |
503 NOT_PRODUCT( | |
504 size_t _processed; | |
505 size_t _removed; | |
506 ) | |
507 }; | |
508 | |
509 inline DiscoveredListIterator::DiscoveredListIterator(DiscoveredList& refs_list, | |
510 OopClosure* keep_alive, | |
511 BoolObjectClosure* is_alive) | |
512 : _refs_list(refs_list), | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
513 _prev_next(refs_list.adr_head()), |
0 | 514 _ref(refs_list.head()), |
515 #ifdef ASSERT | |
516 _first_seen(refs_list.head()), | |
517 #endif | |
518 #ifndef PRODUCT | |
519 _processed(0), | |
520 _removed(0), | |
521 #endif | |
522 _next(refs_list.head()), | |
523 _keep_alive(keep_alive), | |
524 _is_alive(is_alive) | |
525 { } | |
526 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
527 inline bool DiscoveredListIterator::is_referent_alive() const { |
0 | 528 return _is_alive->do_object_b(_referent); |
529 } | |
530 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
531 inline void DiscoveredListIterator::load_ptrs(DEBUG_ONLY(bool allow_null_referent)) { |
0 | 532 _discovered_addr = java_lang_ref_Reference::discovered_addr(_ref); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
533 oop discovered = java_lang_ref_Reference::discovered(_ref); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
534 assert(_discovered_addr && discovered->is_oop_or_null(), |
0 | 535 "discovered field is bad"); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
536 _next = discovered; |
0 | 537 _referent_addr = java_lang_ref_Reference::referent_addr(_ref); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
538 _referent = java_lang_ref_Reference::referent(_ref); |
0 | 539 assert(Universe::heap()->is_in_reserved_or_null(_referent), |
540 "Wrong oop found in java.lang.Reference object"); | |
541 assert(allow_null_referent ? | |
542 _referent->is_oop_or_null() | |
543 : _referent->is_oop(), | |
544 "bad referent"); | |
545 } | |
546 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
547 inline void DiscoveredListIterator::next() { |
0 | 548 _prev_next = _discovered_addr; |
549 move_to_next(); | |
550 } | |
551 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
552 inline void DiscoveredListIterator::remove() { |
0 | 553 assert(_ref->is_oop(), "Dropping a bad reference"); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
554 oop_store_raw(_discovered_addr, NULL); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
555 // First _prev_next ref actually points into DiscoveredList (gross). |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
556 if (UseCompressedOops) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
557 // Remove Reference object from list. |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
558 oopDesc::encode_store_heap_oop_not_null((narrowOop*)_prev_next, _next); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
559 } else { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
560 // Remove Reference object from list. |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
561 oopDesc::store_heap_oop((oop*)_prev_next, _next); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
562 } |
0 | 563 NOT_PRODUCT(_removed++); |
452
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
564 _refs_list.dec_length(1); |
0 | 565 } |
566 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
567 inline void DiscoveredListIterator::move_to_next() { |
0 | 568 _ref = _next; |
569 assert(_ref != _first_seen, "cyclic ref_list found"); | |
570 NOT_PRODUCT(_processed++); | |
571 } | |
572 | |
573 // NOTE: process_phase*() are largely similar, and at a high level | |
574 // merely iterate over the extant list applying a predicate to | |
575 // each of its elements and possibly removing that element from the | |
576 // list and applying some further closures to that element. | |
577 // We should consider the possibility of replacing these | |
578 // process_phase*() methods by abstracting them into | |
579 // a single general iterator invocation that receives appropriate | |
580 // closures that accomplish this work. | |
581 | |
582 // (SoftReferences only) Traverse the list and remove any SoftReferences whose | |
583 // referents are not alive, but that should be kept alive for policy reasons. | |
584 // Keep alive the transitive closure of all such referents. | |
585 void | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
586 ReferenceProcessor::process_phase1(DiscoveredList& refs_list, |
0 | 587 ReferencePolicy* policy, |
588 BoolObjectClosure* is_alive, | |
589 OopClosure* keep_alive, | |
590 VoidClosure* complete_gc) { | |
591 assert(policy != NULL, "Must have a non-NULL policy"); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
592 DiscoveredListIterator iter(refs_list, keep_alive, is_alive); |
0 | 593 // Decide which softly reachable refs should be kept alive. |
594 while (iter.has_next()) { | |
595 iter.load_ptrs(DEBUG_ONLY(!discovery_is_atomic() /* allow_null_referent */)); | |
596 bool referent_is_dead = (iter.referent() != NULL) && !iter.is_referent_alive(); | |
597 if (referent_is_dead && !policy->should_clear_reference(iter.obj())) { | |
598 if (TraceReferenceGC) { | |
599 gclog_or_tty->print_cr("Dropping reference (" INTPTR_FORMAT ": %s" ") by policy", | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
600 iter.obj(), iter.obj()->blueprint()->internal_name()); |
0 | 601 } |
452
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
602 // Remove Reference object from list |
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
603 iter.remove(); |
0 | 604 // Make the Reference object active again |
605 iter.make_active(); | |
606 // keep the referent around | |
607 iter.make_referent_alive(); | |
452
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
608 iter.move_to_next(); |
0 | 609 } else { |
610 iter.next(); | |
611 } | |
612 } | |
613 // Close the reachable set | |
614 complete_gc->do_void(); | |
615 NOT_PRODUCT( | |
616 if (PrintGCDetails && TraceReferenceGC) { | |
617 gclog_or_tty->print(" Dropped %d dead Refs out of %d " | |
618 "discovered Refs by policy ", iter.removed(), iter.processed()); | |
619 } | |
620 ) | |
621 } | |
622 | |
623 // Traverse the list and remove any Refs that are not active, or | |
624 // whose referents are either alive or NULL. | |
625 void | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
626 ReferenceProcessor::pp2_work(DiscoveredList& refs_list, |
0 | 627 BoolObjectClosure* is_alive, |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
628 OopClosure* keep_alive) { |
0 | 629 assert(discovery_is_atomic(), "Error"); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
630 DiscoveredListIterator iter(refs_list, keep_alive, is_alive); |
0 | 631 while (iter.has_next()) { |
632 iter.load_ptrs(DEBUG_ONLY(false /* allow_null_referent */)); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
633 DEBUG_ONLY(oop next = java_lang_ref_Reference::next(iter.obj());) |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
634 assert(next == NULL, "Should not discover inactive Reference"); |
0 | 635 if (iter.is_referent_alive()) { |
636 if (TraceReferenceGC) { | |
637 gclog_or_tty->print_cr("Dropping strongly reachable reference (" INTPTR_FORMAT ": %s)", | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
638 iter.obj(), iter.obj()->blueprint()->internal_name()); |
0 | 639 } |
640 // The referent is reachable after all. | |
452
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
641 // Remove Reference object from list. |
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
642 iter.remove(); |
0 | 643 // Update the referent pointer as necessary: Note that this |
644 // should not entail any recursive marking because the | |
645 // referent must already have been traversed. | |
646 iter.make_referent_alive(); | |
452
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
647 iter.move_to_next(); |
0 | 648 } else { |
649 iter.next(); | |
650 } | |
651 } | |
652 NOT_PRODUCT( | |
653 if (PrintGCDetails && TraceReferenceGC) { | |
654 gclog_or_tty->print(" Dropped %d active Refs out of %d " | |
655 "Refs in discovered list ", iter.removed(), iter.processed()); | |
656 } | |
657 ) | |
658 } | |
659 | |
660 void | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
661 ReferenceProcessor::pp2_work_concurrent_discovery(DiscoveredList& refs_list, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
662 BoolObjectClosure* is_alive, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
663 OopClosure* keep_alive, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
664 VoidClosure* complete_gc) { |
0 | 665 assert(!discovery_is_atomic(), "Error"); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
666 DiscoveredListIterator iter(refs_list, keep_alive, is_alive); |
0 | 667 while (iter.has_next()) { |
668 iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */)); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
669 HeapWord* next_addr = java_lang_ref_Reference::next_addr(iter.obj()); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
670 oop next = java_lang_ref_Reference::next(iter.obj()); |
0 | 671 if ((iter.referent() == NULL || iter.is_referent_alive() || |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
672 next != NULL)) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
673 assert(next->is_oop_or_null(), "bad next field"); |
0 | 674 // Remove Reference object from list |
675 iter.remove(); | |
676 // Trace the cohorts | |
677 iter.make_referent_alive(); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
678 if (UseCompressedOops) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
679 keep_alive->do_oop((narrowOop*)next_addr); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
680 } else { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
681 keep_alive->do_oop((oop*)next_addr); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
682 } |
452
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
683 iter.move_to_next(); |
0 | 684 } else { |
685 iter.next(); | |
686 } | |
687 } | |
688 // Now close the newly reachable set | |
689 complete_gc->do_void(); | |
690 NOT_PRODUCT( | |
691 if (PrintGCDetails && TraceReferenceGC) { | |
692 gclog_or_tty->print(" Dropped %d active Refs out of %d " | |
693 "Refs in discovered list ", iter.removed(), iter.processed()); | |
694 } | |
695 ) | |
696 } | |
697 | |
698 // Traverse the list and process the referents, by either | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
699 // clearing them or keeping them (and their reachable |
0 | 700 // closure) alive. |
701 void | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
702 ReferenceProcessor::process_phase3(DiscoveredList& refs_list, |
0 | 703 bool clear_referent, |
704 BoolObjectClosure* is_alive, | |
705 OopClosure* keep_alive, | |
706 VoidClosure* complete_gc) { | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
707 DiscoveredListIterator iter(refs_list, keep_alive, is_alive); |
0 | 708 while (iter.has_next()) { |
709 iter.update_discovered(); | |
710 iter.load_ptrs(DEBUG_ONLY(false /* allow_null_referent */)); | |
711 if (clear_referent) { | |
712 // NULL out referent pointer | |
713 iter.clear_referent(); | |
714 } else { | |
715 // keep the referent around | |
716 iter.make_referent_alive(); | |
717 } | |
718 if (TraceReferenceGC) { | |
719 gclog_or_tty->print_cr("Adding %sreference (" INTPTR_FORMAT ": %s) as pending", | |
720 clear_referent ? "cleared " : "", | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
721 iter.obj(), iter.obj()->blueprint()->internal_name()); |
0 | 722 } |
723 assert(iter.obj()->is_oop(UseConcMarkSweepGC), "Adding a bad reference"); | |
724 // If discovery is concurrent, we may have objects with null referents, | |
725 // being those that were concurrently cleared after they were discovered | |
726 // (and not subsequently precleaned). | |
727 assert( (discovery_is_atomic() && iter.referent()->is_oop()) | |
728 || (!discovery_is_atomic() && iter.referent()->is_oop_or_null(UseConcMarkSweepGC)), | |
729 "Adding a bad referent"); | |
730 iter.next(); | |
731 } | |
732 // Remember to keep sentinel pointer around | |
733 iter.update_discovered(); | |
734 // Close the reachable set | |
735 complete_gc->do_void(); | |
736 } | |
737 | |
738 void | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
739 ReferenceProcessor::abandon_partial_discovered_list(DiscoveredList& refs_list) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
740 oop obj = refs_list.head(); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
741 while (obj != sentinel_ref()) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
742 oop discovered = java_lang_ref_Reference::discovered(obj); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
743 java_lang_ref_Reference::set_discovered_raw(obj, NULL); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
744 obj = discovered; |
0 | 745 } |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
746 refs_list.set_head(sentinel_ref()); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
747 refs_list.set_length(0); |
0 | 748 } |
749 | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
750 void ReferenceProcessor::abandon_partial_discovery() { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
751 // loop over the lists |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
752 for (int i = 0; i < _num_q * subclasses_of_ref; i++) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
753 if (TraceReferenceGC && PrintGCDetails && ((i % _num_q) == 0)) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
754 gclog_or_tty->print_cr( |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
755 "\nAbandoning %s discovered list", |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
756 list_name(i)); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
757 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
758 abandon_partial_discovered_list(_discoveredSoftRefs[i]); |
0 | 759 } |
760 } | |
761 | |
762 class RefProcPhase1Task: public AbstractRefProcTaskExecutor::ProcessTask { | |
763 public: | |
764 RefProcPhase1Task(ReferenceProcessor& ref_processor, | |
765 DiscoveredList refs_lists[], | |
766 ReferencePolicy* policy, | |
767 bool marks_oops_alive) | |
768 : ProcessTask(ref_processor, refs_lists, marks_oops_alive), | |
769 _policy(policy) | |
770 { } | |
771 virtual void work(unsigned int i, BoolObjectClosure& is_alive, | |
772 OopClosure& keep_alive, | |
773 VoidClosure& complete_gc) | |
774 { | |
775 _ref_processor.process_phase1(_refs_lists[i], _policy, | |
776 &is_alive, &keep_alive, &complete_gc); | |
777 } | |
778 private: | |
779 ReferencePolicy* _policy; | |
780 }; | |
781 | |
782 class RefProcPhase2Task: public AbstractRefProcTaskExecutor::ProcessTask { | |
783 public: | |
784 RefProcPhase2Task(ReferenceProcessor& ref_processor, | |
785 DiscoveredList refs_lists[], | |
786 bool marks_oops_alive) | |
787 : ProcessTask(ref_processor, refs_lists, marks_oops_alive) | |
788 { } | |
789 virtual void work(unsigned int i, BoolObjectClosure& is_alive, | |
790 OopClosure& keep_alive, | |
791 VoidClosure& complete_gc) | |
792 { | |
793 _ref_processor.process_phase2(_refs_lists[i], | |
794 &is_alive, &keep_alive, &complete_gc); | |
795 } | |
796 }; | |
797 | |
798 class RefProcPhase3Task: public AbstractRefProcTaskExecutor::ProcessTask { | |
799 public: | |
800 RefProcPhase3Task(ReferenceProcessor& ref_processor, | |
801 DiscoveredList refs_lists[], | |
802 bool clear_referent, | |
803 bool marks_oops_alive) | |
804 : ProcessTask(ref_processor, refs_lists, marks_oops_alive), | |
805 _clear_referent(clear_referent) | |
806 { } | |
807 virtual void work(unsigned int i, BoolObjectClosure& is_alive, | |
808 OopClosure& keep_alive, | |
809 VoidClosure& complete_gc) | |
810 { | |
811 _ref_processor.process_phase3(_refs_lists[i], _clear_referent, | |
812 &is_alive, &keep_alive, &complete_gc); | |
813 } | |
814 private: | |
815 bool _clear_referent; | |
816 }; | |
817 | |
818 // Balances reference queues. | |
819 void ReferenceProcessor::balance_queues(DiscoveredList ref_lists[]) | |
820 { | |
821 // calculate total length | |
822 size_t total_refs = 0; | |
823 for (int i = 0; i < _num_q; ++i) { | |
824 total_refs += ref_lists[i].length(); | |
825 } | |
826 size_t avg_refs = total_refs / _num_q + 1; | |
827 int to_idx = 0; | |
828 for (int from_idx = 0; from_idx < _num_q; from_idx++) { | |
829 while (ref_lists[from_idx].length() > avg_refs) { | |
830 assert(to_idx < _num_q, "Sanity Check!"); | |
831 if (ref_lists[to_idx].length() < avg_refs) { | |
832 // move superfluous refs | |
833 size_t refs_to_move = | |
834 MIN2(ref_lists[from_idx].length() - avg_refs, | |
835 avg_refs - ref_lists[to_idx].length()); | |
836 oop move_head = ref_lists[from_idx].head(); | |
837 oop move_tail = move_head; | |
838 oop new_head = move_head; | |
839 // find an element to split the list on | |
840 for (size_t j = 0; j < refs_to_move; ++j) { | |
841 move_tail = new_head; | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
842 new_head = java_lang_ref_Reference::discovered(new_head); |
0 | 843 } |
844 java_lang_ref_Reference::set_discovered(move_tail, ref_lists[to_idx].head()); | |
845 ref_lists[to_idx].set_head(move_head); | |
452
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
846 ref_lists[to_idx].inc_length(refs_to_move); |
0 | 847 ref_lists[from_idx].set_head(new_head); |
452
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
848 ref_lists[from_idx].dec_length(refs_to_move); |
0 | 849 } else { |
850 ++to_idx; | |
851 } | |
852 } | |
853 } | |
854 } | |
855 | |
856 void | |
857 ReferenceProcessor::process_discovered_reflist( | |
858 DiscoveredList refs_lists[], | |
859 ReferencePolicy* policy, | |
860 bool clear_referent, | |
861 BoolObjectClosure* is_alive, | |
862 OopClosure* keep_alive, | |
863 VoidClosure* complete_gc, | |
864 AbstractRefProcTaskExecutor* task_executor) | |
865 { | |
866 bool mt = task_executor != NULL && _processing_is_mt; | |
867 if (mt && ParallelRefProcBalancingEnabled) { | |
868 balance_queues(refs_lists); | |
869 } | |
870 if (PrintReferenceGC && PrintGCDetails) { | |
871 size_t total = 0; | |
872 for (int i = 0; i < _num_q; ++i) { | |
873 total += refs_lists[i].length(); | |
874 } | |
875 gclog_or_tty->print(", %u refs", total); | |
876 } | |
877 | |
878 // Phase 1 (soft refs only): | |
879 // . Traverse the list and remove any SoftReferences whose | |
880 // referents are not alive, but that should be kept alive for | |
881 // policy reasons. Keep alive the transitive closure of all | |
882 // such referents. | |
883 if (policy != NULL) { | |
884 if (mt) { | |
885 RefProcPhase1Task phase1(*this, refs_lists, policy, true /*marks_oops_alive*/); | |
886 task_executor->execute(phase1); | |
887 } else { | |
888 for (int i = 0; i < _num_q; i++) { | |
889 process_phase1(refs_lists[i], policy, | |
890 is_alive, keep_alive, complete_gc); | |
891 } | |
892 } | |
893 } else { // policy == NULL | |
894 assert(refs_lists != _discoveredSoftRefs, | |
895 "Policy must be specified for soft references."); | |
896 } | |
897 | |
898 // Phase 2: | |
899 // . Traverse the list and remove any refs whose referents are alive. | |
900 if (mt) { | |
901 RefProcPhase2Task phase2(*this, refs_lists, !discovery_is_atomic() /*marks_oops_alive*/); | |
902 task_executor->execute(phase2); | |
903 } else { | |
904 for (int i = 0; i < _num_q; i++) { | |
905 process_phase2(refs_lists[i], is_alive, keep_alive, complete_gc); | |
906 } | |
907 } | |
908 | |
909 // Phase 3: | |
910 // . Traverse the list and process referents as appropriate. | |
911 if (mt) { | |
912 RefProcPhase3Task phase3(*this, refs_lists, clear_referent, true /*marks_oops_alive*/); | |
913 task_executor->execute(phase3); | |
914 } else { | |
915 for (int i = 0; i < _num_q; i++) { | |
916 process_phase3(refs_lists[i], clear_referent, | |
917 is_alive, keep_alive, complete_gc); | |
918 } | |
919 } | |
920 } | |
921 | |
922 void ReferenceProcessor::clean_up_discovered_references() { | |
923 // loop over the lists | |
924 for (int i = 0; i < _num_q * subclasses_of_ref; i++) { | |
925 if (TraceReferenceGC && PrintGCDetails && ((i % _num_q) == 0)) { | |
926 gclog_or_tty->print_cr( | |
927 "\nScrubbing %s discovered list of Null referents", | |
928 list_name(i)); | |
929 } | |
930 clean_up_discovered_reflist(_discoveredSoftRefs[i]); | |
931 } | |
932 } | |
933 | |
934 void ReferenceProcessor::clean_up_discovered_reflist(DiscoveredList& refs_list) { | |
935 assert(!discovery_is_atomic(), "Else why call this method?"); | |
936 DiscoveredListIterator iter(refs_list, NULL, NULL); | |
937 while (iter.has_next()) { | |
938 iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */)); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
939 oop next = java_lang_ref_Reference::next(iter.obj()); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
940 assert(next->is_oop_or_null(), "bad next field"); |
0 | 941 // If referent has been cleared or Reference is not active, |
942 // drop it. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
943 if (iter.referent() == NULL || next != NULL) { |
0 | 944 debug_only( |
945 if (PrintGCDetails && TraceReferenceGC) { | |
946 gclog_or_tty->print_cr("clean_up_discovered_list: Dropping Reference: " | |
947 INTPTR_FORMAT " with next field: " INTPTR_FORMAT | |
948 " and referent: " INTPTR_FORMAT, | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
949 iter.obj(), next, iter.referent()); |
0 | 950 } |
951 ) | |
952 // Remove Reference object from list | |
953 iter.remove(); | |
452
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
954 iter.move_to_next(); |
0 | 955 } else { |
956 iter.next(); | |
957 } | |
958 } | |
959 NOT_PRODUCT( | |
960 if (PrintGCDetails && TraceReferenceGC) { | |
961 gclog_or_tty->print( | |
962 " Removed %d Refs with NULL referents out of %d discovered Refs", | |
963 iter.removed(), iter.processed()); | |
964 } | |
965 ) | |
966 } | |
967 | |
968 inline DiscoveredList* ReferenceProcessor::get_discovered_list(ReferenceType rt) { | |
969 int id = 0; | |
970 // Determine the queue index to use for this object. | |
971 if (_discovery_is_mt) { | |
972 // During a multi-threaded discovery phase, | |
973 // each thread saves to its "own" list. | |
974 Thread* thr = Thread::current(); | |
975 assert(thr->is_GC_task_thread(), | |
976 "Dubious cast from Thread* to WorkerThread*?"); | |
977 id = ((WorkerThread*)thr)->id(); | |
978 } else { | |
979 // single-threaded discovery, we save in round-robin | |
980 // fashion to each of the lists. | |
981 if (_processing_is_mt) { | |
982 id = next_id(); | |
983 } | |
984 } | |
985 assert(0 <= id && id < _num_q, "Id is out-of-bounds (call Freud?)"); | |
986 | |
987 // Get the discovered queue to which we will add | |
988 DiscoveredList* list = NULL; | |
989 switch (rt) { | |
990 case REF_OTHER: | |
991 // Unknown reference type, no special treatment | |
992 break; | |
993 case REF_SOFT: | |
994 list = &_discoveredSoftRefs[id]; | |
995 break; | |
996 case REF_WEAK: | |
997 list = &_discoveredWeakRefs[id]; | |
998 break; | |
999 case REF_FINAL: | |
1000 list = &_discoveredFinalRefs[id]; | |
1001 break; | |
1002 case REF_PHANTOM: | |
1003 list = &_discoveredPhantomRefs[id]; | |
1004 break; | |
1005 case REF_NONE: | |
1006 // we should not reach here if we are an instanceRefKlass | |
1007 default: | |
1008 ShouldNotReachHere(); | |
1009 } | |
1010 return list; | |
1011 } | |
1012 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1013 inline void |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1014 ReferenceProcessor::add_to_discovered_list_mt(DiscoveredList& refs_list, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1015 oop obj, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1016 HeapWord* discovered_addr) { |
0 | 1017 assert(_discovery_is_mt, "!_discovery_is_mt should have been handled by caller"); |
1018 // First we must make sure this object is only enqueued once. CAS in a non null | |
1019 // discovered_addr. | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1020 oop current_head = refs_list.head(); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1021 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1022 // Note: In the case of G1, this pre-barrier is strictly |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1023 // not necessary because the only case we are interested in |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1024 // here is when *discovered_addr is NULL, so this will expand to |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1025 // nothing. As a result, I am just manually eliding this out for G1. |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1026 if (_discovered_list_needs_barrier && !UseG1GC) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1027 _bs->write_ref_field_pre((void*)discovered_addr, current_head); guarantee(false, "Needs to be fixed: YSR"); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1028 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1029 oop retest = oopDesc::atomic_compare_exchange_oop(current_head, discovered_addr, |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1030 NULL); |
0 | 1031 if (retest == NULL) { |
1032 // This thread just won the right to enqueue the object. | |
1033 // We have separate lists for enqueueing so no synchronization | |
1034 // is necessary. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1035 refs_list.set_head(obj); |
452
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
1036 refs_list.inc_length(1); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1037 if (_discovered_list_needs_barrier) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1038 _bs->write_ref_field((void*)discovered_addr, current_head); guarantee(false, "Needs to be fixed: YSR"); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1039 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1040 |
0 | 1041 } else { |
1042 // If retest was non NULL, another thread beat us to it: | |
1043 // The reference has already been discovered... | |
1044 if (TraceReferenceGC) { | |
1045 gclog_or_tty->print_cr("Already enqueued reference (" INTPTR_FORMAT ": %s)", | |
1046 obj, obj->blueprint()->internal_name()); | |
1047 } | |
1048 } | |
1049 } | |
1050 | |
1051 // We mention two of several possible choices here: | |
1052 // #0: if the reference object is not in the "originating generation" | |
1053 // (or part of the heap being collected, indicated by our "span" | |
1054 // we don't treat it specially (i.e. we scan it as we would | |
1055 // a normal oop, treating its references as strong references). | |
1056 // This means that references can't be enqueued unless their | |
1057 // referent is also in the same span. This is the simplest, | |
1058 // most "local" and most conservative approach, albeit one | |
1059 // that may cause weak references to be enqueued least promptly. | |
1060 // We call this choice the "ReferenceBasedDiscovery" policy. | |
1061 // #1: the reference object may be in any generation (span), but if | |
1062 // the referent is in the generation (span) being currently collected | |
1063 // then we can discover the reference object, provided | |
1064 // the object has not already been discovered by | |
1065 // a different concurrently running collector (as may be the | |
1066 // case, for instance, if the reference object is in CMS and | |
1067 // the referent in DefNewGeneration), and provided the processing | |
1068 // of this reference object by the current collector will | |
1069 // appear atomic to every other collector in the system. | |
1070 // (Thus, for instance, a concurrent collector may not | |
1071 // discover references in other generations even if the | |
1072 // referent is in its own generation). This policy may, | |
1073 // in certain cases, enqueue references somewhat sooner than | |
1074 // might Policy #0 above, but at marginally increased cost | |
1075 // and complexity in processing these references. | |
1076 // We call this choice the "RefeferentBasedDiscovery" policy. | |
1077 bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) { | |
1078 // We enqueue references only if we are discovering refs | |
1079 // (rather than processing discovered refs). | |
1080 if (!_discovering_refs || !RegisterReferences) { | |
1081 return false; | |
1082 } | |
1083 // We only enqueue active references. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1084 oop next = java_lang_ref_Reference::next(obj); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1085 if (next != NULL) { |
0 | 1086 return false; |
1087 } | |
1088 | |
1089 HeapWord* obj_addr = (HeapWord*)obj; | |
1090 if (RefDiscoveryPolicy == ReferenceBasedDiscovery && | |
1091 !_span.contains(obj_addr)) { | |
1092 // Reference is not in the originating generation; | |
1093 // don't treat it specially (i.e. we want to scan it as a normal | |
1094 // object with strong references). | |
1095 return false; | |
1096 } | |
1097 | |
1098 // We only enqueue references whose referents are not (yet) strongly | |
1099 // reachable. | |
1100 if (is_alive_non_header() != NULL) { | |
1101 oop referent = java_lang_ref_Reference::referent(obj); | |
453
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
1102 // In the case of non-concurrent discovery, the last |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
1103 // disjunct below should hold. It may not hold in the |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
1104 // case of concurrent discovery because mutators may |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
1105 // concurrently clear() a Reference. |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
1106 assert(UseConcMarkSweepGC || UseG1GC || referent != NULL, |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
1107 "Refs with null referents already filtered"); |
0 | 1108 if (is_alive_non_header()->do_object_b(referent)) { |
1109 return false; // referent is reachable | |
1110 } | |
1111 } | |
453
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
1112 if (rt == REF_SOFT) { |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
1113 // For soft refs we can decide now if these are not |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
1114 // current candidates for clearing, in which case we |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
1115 // can mark through them now, rather than delaying that |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
1116 // to the reference-processing phase. Since all current |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
1117 // time-stamp policies advance the soft-ref clock only |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
1118 // at a major collection cycle, this is always currently |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
1119 // accurate. |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
1120 if (!_current_soft_ref_policy->should_clear_reference(obj)) { |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
1121 return false; |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
1122 } |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
452
diff
changeset
|
1123 } |
0 | 1124 |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1125 HeapWord* const discovered_addr = java_lang_ref_Reference::discovered_addr(obj); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1126 const oop discovered = java_lang_ref_Reference::discovered(obj); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1127 assert(discovered->is_oop_or_null(), "bad discovered field"); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1128 if (discovered != NULL) { |
0 | 1129 // The reference has already been discovered... |
1130 if (TraceReferenceGC) { | |
1131 gclog_or_tty->print_cr("Already enqueued reference (" INTPTR_FORMAT ": %s)", | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1132 obj, obj->blueprint()->internal_name()); |
0 | 1133 } |
1134 if (RefDiscoveryPolicy == ReferentBasedDiscovery) { | |
1135 // assumes that an object is not processed twice; | |
1136 // if it's been already discovered it must be on another | |
1137 // generation's discovered list; so we won't discover it. | |
1138 return false; | |
1139 } else { | |
1140 assert(RefDiscoveryPolicy == ReferenceBasedDiscovery, | |
1141 "Unrecognized policy"); | |
1142 // Check assumption that an object is not potentially | |
1143 // discovered twice except by concurrent collectors that potentially | |
1144 // trace the same Reference object twice. | |
1145 assert(UseConcMarkSweepGC, | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1146 "Only possible with an incremental-update concurrent collector"); |
0 | 1147 return true; |
1148 } | |
1149 } | |
1150 | |
1151 if (RefDiscoveryPolicy == ReferentBasedDiscovery) { | |
1152 oop referent = java_lang_ref_Reference::referent(obj); | |
1153 assert(referent->is_oop(), "bad referent"); | |
1154 // enqueue if and only if either: | |
1155 // reference is in our span or | |
1156 // we are an atomic collector and referent is in our span | |
1157 if (_span.contains(obj_addr) || | |
1158 (discovery_is_atomic() && _span.contains(referent))) { | |
1159 // should_enqueue = true; | |
1160 } else { | |
1161 return false; | |
1162 } | |
1163 } else { | |
1164 assert(RefDiscoveryPolicy == ReferenceBasedDiscovery && | |
1165 _span.contains(obj_addr), "code inconsistency"); | |
1166 } | |
1167 | |
1168 // Get the right type of discovered queue head. | |
1169 DiscoveredList* list = get_discovered_list(rt); | |
1170 if (list == NULL) { | |
1171 return false; // nothing special needs to be done | |
1172 } | |
1173 | |
1174 if (_discovery_is_mt) { | |
1175 add_to_discovered_list_mt(*list, obj, discovered_addr); | |
1176 } else { | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1177 // If "_discovered_list_needs_barrier", we do write barriers when |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1178 // updating the discovered reference list. Otherwise, we do a raw store |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1179 // here: the field will be visited later when processing the discovered |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1180 // references. |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1181 oop current_head = list->head(); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1182 // As in the case further above, since we are over-writing a NULL |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1183 // pre-value, we can safely elide the pre-barrier here for the case of G1. |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1184 assert(discovered == NULL, "control point invariant"); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1185 if (_discovered_list_needs_barrier && !UseG1GC) { // safe to elide for G1 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1186 _bs->write_ref_field_pre((oop*)discovered_addr, current_head); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1187 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1188 oop_store_raw(discovered_addr, current_head); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1189 if (_discovered_list_needs_barrier) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1190 _bs->write_ref_field((oop*)discovered_addr, current_head); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1191 } |
0 | 1192 list->set_head(obj); |
452
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
1193 list->inc_length(1); |
0 | 1194 } |
1195 | |
1196 // In the MT discovery case, it is currently possible to see | |
1197 // the following message multiple times if several threads | |
1198 // discover a reference about the same time. Only one will | |
1199 // however have actually added it to the disocvered queue. | |
1200 // One could let add_to_discovered_list_mt() return an | |
1201 // indication for success in queueing (by 1 thread) or | |
1202 // failure (by all other threads), but I decided the extra | |
1203 // code was not worth the effort for something that is | |
1204 // only used for debugging support. | |
1205 if (TraceReferenceGC) { | |
1206 oop referent = java_lang_ref_Reference::referent(obj); | |
1207 if (PrintGCDetails) { | |
1208 gclog_or_tty->print_cr("Enqueued reference (" INTPTR_FORMAT ": %s)", | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1209 obj, obj->blueprint()->internal_name()); |
0 | 1210 } |
1211 assert(referent->is_oop(), "Enqueued a bad referent"); | |
1212 } | |
1213 assert(obj->is_oop(), "Enqueued a bad reference"); | |
1214 return true; | |
1215 } | |
1216 | |
1217 // Preclean the discovered references by removing those | |
1218 // whose referents are alive, and by marking from those that | |
1219 // are not active. These lists can be handled here | |
1220 // in any order and, indeed, concurrently. | |
1221 void ReferenceProcessor::preclean_discovered_references( | |
1222 BoolObjectClosure* is_alive, | |
1223 OopClosure* keep_alive, | |
1224 VoidClosure* complete_gc, | |
1225 YieldClosure* yield) { | |
1226 | |
1227 NOT_PRODUCT(verify_ok_to_handle_reflists()); | |
1228 | |
1229 // Soft references | |
1230 { | |
1231 TraceTime tt("Preclean SoftReferences", PrintGCDetails && PrintReferenceGC, | |
1232 false, gclog_or_tty); | |
1233 for (int i = 0; i < _num_q; i++) { | |
452
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
1234 if (yield->should_return()) { |
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
1235 return; |
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
1236 } |
0 | 1237 preclean_discovered_reflist(_discoveredSoftRefs[i], is_alive, |
1238 keep_alive, complete_gc, yield); | |
1239 } | |
1240 } | |
1241 | |
1242 // Weak references | |
1243 { | |
1244 TraceTime tt("Preclean WeakReferences", PrintGCDetails && PrintReferenceGC, | |
1245 false, gclog_or_tty); | |
1246 for (int i = 0; i < _num_q; i++) { | |
452
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
1247 if (yield->should_return()) { |
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
1248 return; |
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
1249 } |
0 | 1250 preclean_discovered_reflist(_discoveredWeakRefs[i], is_alive, |
1251 keep_alive, complete_gc, yield); | |
1252 } | |
1253 } | |
1254 | |
1255 // Final references | |
1256 { | |
1257 TraceTime tt("Preclean FinalReferences", PrintGCDetails && PrintReferenceGC, | |
1258 false, gclog_or_tty); | |
1259 for (int i = 0; i < _num_q; i++) { | |
452
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
1260 if (yield->should_return()) { |
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
1261 return; |
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
1262 } |
0 | 1263 preclean_discovered_reflist(_discoveredFinalRefs[i], is_alive, |
1264 keep_alive, complete_gc, yield); | |
1265 } | |
1266 } | |
1267 | |
1268 // Phantom references | |
1269 { | |
1270 TraceTime tt("Preclean PhantomReferences", PrintGCDetails && PrintReferenceGC, | |
1271 false, gclog_or_tty); | |
1272 for (int i = 0; i < _num_q; i++) { | |
452
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
1273 if (yield->should_return()) { |
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
1274 return; |
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
1275 } |
0 | 1276 preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive, |
1277 keep_alive, complete_gc, yield); | |
1278 } | |
1279 } | |
1280 } | |
1281 | |
1282 // Walk the given discovered ref list, and remove all reference objects | |
1283 // whose referents are still alive, whose referents are NULL or which | |
452
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
1284 // are not active (have a non-NULL next field). NOTE: When we are |
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
1285 // thus precleaning the ref lists (which happens single-threaded today), |
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
1286 // we do not disable refs discovery to honour the correct semantics of |
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
1287 // java.lang.Reference. As a result, we need to be careful below |
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
1288 // that ref removal steps interleave safely with ref discovery steps |
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
1289 // (in this thread). |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1290 void |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1291 ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1292 BoolObjectClosure* is_alive, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1293 OopClosure* keep_alive, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1294 VoidClosure* complete_gc, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1295 YieldClosure* yield) { |
0 | 1296 DiscoveredListIterator iter(refs_list, keep_alive, is_alive); |
1297 while (iter.has_next()) { | |
1298 iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */)); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1299 oop obj = iter.obj(); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1300 oop next = java_lang_ref_Reference::next(obj); |
0 | 1301 if (iter.referent() == NULL || iter.is_referent_alive() || |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1302 next != NULL) { |
0 | 1303 // The referent has been cleared, or is alive, or the Reference is not |
1304 // active; we need to trace and mark its cohort. | |
1305 if (TraceReferenceGC) { | |
1306 gclog_or_tty->print_cr("Precleaning Reference (" INTPTR_FORMAT ": %s)", | |
1307 iter.obj(), iter.obj()->blueprint()->internal_name()); | |
1308 } | |
1309 // Remove Reference object from list | |
1310 iter.remove(); | |
1311 // Keep alive its cohort. | |
1312 iter.make_referent_alive(); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1313 if (UseCompressedOops) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1314 narrowOop* next_addr = (narrowOop*)java_lang_ref_Reference::next_addr(obj); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1315 keep_alive->do_oop(next_addr); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1316 } else { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1317 oop* next_addr = (oop*)java_lang_ref_Reference::next_addr(obj); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1318 keep_alive->do_oop(next_addr); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1319 } |
452
00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
ysr
parents:
356
diff
changeset
|
1320 iter.move_to_next(); |
0 | 1321 } else { |
1322 iter.next(); | |
1323 } | |
1324 } | |
1325 // Close the reachable set | |
1326 complete_gc->do_void(); | |
1327 | |
1328 NOT_PRODUCT( | |
1329 if (PrintGCDetails && PrintReferenceGC) { | |
1330 gclog_or_tty->print(" Dropped %d Refs out of %d " | |
1331 "Refs in discovered list ", iter.removed(), iter.processed()); | |
1332 } | |
1333 ) | |
1334 } | |
1335 | |
1336 const char* ReferenceProcessor::list_name(int i) { | |
1337 assert(i >= 0 && i <= _num_q * subclasses_of_ref, "Out of bounds index"); | |
1338 int j = i / _num_q; | |
1339 switch (j) { | |
1340 case 0: return "SoftRef"; | |
1341 case 1: return "WeakRef"; | |
1342 case 2: return "FinalRef"; | |
1343 case 3: return "PhantomRef"; | |
1344 } | |
1345 ShouldNotReachHere(); | |
1346 return NULL; | |
1347 } | |
1348 | |
1349 #ifndef PRODUCT | |
1350 void ReferenceProcessor::verify_ok_to_handle_reflists() { | |
1351 // empty for now | |
1352 } | |
1353 #endif | |
1354 | |
1355 void ReferenceProcessor::verify() { | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1356 guarantee(sentinel_ref() != NULL && sentinel_ref()->is_oop(), "Lost _sentinelRef"); |
0 | 1357 } |
1358 | |
1359 #ifndef PRODUCT | |
1360 void ReferenceProcessor::clear_discovered_references() { | |
1361 guarantee(!_discovering_refs, "Discovering refs?"); | |
1362 for (int i = 0; i < _num_q * subclasses_of_ref; i++) { | |
1363 oop obj = _discoveredSoftRefs[i].head(); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1364 while (obj != sentinel_ref()) { |
0 | 1365 oop next = java_lang_ref_Reference::discovered(obj); |
1366 java_lang_ref_Reference::set_discovered(obj, (oop) NULL); | |
1367 obj = next; | |
1368 } | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
5
diff
changeset
|
1369 _discoveredSoftRefs[i].set_head(sentinel_ref()); |
0 | 1370 _discoveredSoftRefs[i].set_length(0); |
1371 } | |
1372 } | |
1373 #endif // PRODUCT |