Mercurial > hg > graal-jvmci-8
annotate src/share/vm/gc_implementation/g1/concurrentMark.cpp @ 3285:49a67202bc67
7011855: G1: non-product flag to artificially grow the heap
Summary: It introduces non-product cmd line parameter G1DummyRegionsPerGC which indicates how many "dummy" regions to allocate at the end of each GC. This allows the G1 heap to grow artificially and makes concurrent marking cycles more frequent irrespective of what the application that is running is doing. The dummy regions will be found totally empty during cleanup so this parameter can also be used to stress the concurrent cleanup operation.
Reviewed-by: brutisso, johnc
author | tonyp |
---|---|
date | Tue, 19 Apr 2011 15:46:59 -0400 |
parents | 8f1042ff784d |
children | cd8e33b2a8ad |
rev | line source |
---|---|
342 | 1 /* |
2149 | 2 * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. |
342 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1547
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1547
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1547
diff
changeset
|
21 * questions. |
342 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "classfile/symbolTable.hpp" | |
27 #include "gc_implementation/g1/concurrentMark.hpp" | |
28 #include "gc_implementation/g1/concurrentMarkThread.inline.hpp" | |
29 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" | |
30 #include "gc_implementation/g1/g1CollectorPolicy.hpp" | |
31 #include "gc_implementation/g1/g1RemSet.hpp" | |
32 #include "gc_implementation/g1/heapRegionRemSet.hpp" | |
33 #include "gc_implementation/g1/heapRegionSeq.inline.hpp" | |
2125
7246a374a9f2
6458402: 3 jvmti tests fail with CMS and +ExplicitGCInvokesConcurrent
kamg
parents:
2037
diff
changeset
|
34 #include "gc_implementation/shared/vmGCOperations.hpp" |
1972 | 35 #include "memory/genOopClosures.inline.hpp" |
36 #include "memory/referencePolicy.hpp" | |
37 #include "memory/resourceArea.hpp" | |
38 #include "oops/oop.inline.hpp" | |
39 #include "runtime/handles.inline.hpp" | |
40 #include "runtime/java.hpp" | |
342 | 41 |
42 // | |
43 // CMS Bit Map Wrapper | |
44 | |
45 CMBitMapRO::CMBitMapRO(ReservedSpace rs, int shifter): | |
46 _bm((uintptr_t*)NULL,0), | |
47 _shifter(shifter) { | |
48 _bmStartWord = (HeapWord*)(rs.base()); | |
49 _bmWordSize = rs.size()/HeapWordSize; // rs.size() is in bytes | |
50 ReservedSpace brs(ReservedSpace::allocation_align_size_up( | |
51 (_bmWordSize >> (_shifter + LogBitsPerByte)) + 1)); | |
52 | |
53 guarantee(brs.is_reserved(), "couldn't allocate CMS bit map"); | |
54 // For now we'll just commit all of the bit map up fromt. | |
55 // Later on we'll try to be more parsimonious with swap. | |
56 guarantee(_virtual_space.initialize(brs, brs.size()), | |
57 "couldn't reseve backing store for CMS bit map"); | |
58 assert(_virtual_space.committed_size() == brs.size(), | |
59 "didn't reserve backing store for all of CMS bit map?"); | |
60 _bm.set_map((uintptr_t*)_virtual_space.low()); | |
61 assert(_virtual_space.committed_size() << (_shifter + LogBitsPerByte) >= | |
62 _bmWordSize, "inconsistency in bit map sizing"); | |
63 _bm.set_size(_bmWordSize >> _shifter); | |
64 } | |
65 | |
66 HeapWord* CMBitMapRO::getNextMarkedWordAddress(HeapWord* addr, | |
67 HeapWord* limit) const { | |
68 // First we must round addr *up* to a possible object boundary. | |
69 addr = (HeapWord*)align_size_up((intptr_t)addr, | |
70 HeapWordSize << _shifter); | |
71 size_t addrOffset = heapWordToOffset(addr); | |
72 if (limit == NULL) limit = _bmStartWord + _bmWordSize; | |
73 size_t limitOffset = heapWordToOffset(limit); | |
74 size_t nextOffset = _bm.get_next_one_offset(addrOffset, limitOffset); | |
75 HeapWord* nextAddr = offsetToHeapWord(nextOffset); | |
76 assert(nextAddr >= addr, "get_next_one postcondition"); | |
77 assert(nextAddr == limit || isMarked(nextAddr), | |
78 "get_next_one postcondition"); | |
79 return nextAddr; | |
80 } | |
81 | |
82 HeapWord* CMBitMapRO::getNextUnmarkedWordAddress(HeapWord* addr, | |
83 HeapWord* limit) const { | |
84 size_t addrOffset = heapWordToOffset(addr); | |
85 if (limit == NULL) limit = _bmStartWord + _bmWordSize; | |
86 size_t limitOffset = heapWordToOffset(limit); | |
87 size_t nextOffset = _bm.get_next_zero_offset(addrOffset, limitOffset); | |
88 HeapWord* nextAddr = offsetToHeapWord(nextOffset); | |
89 assert(nextAddr >= addr, "get_next_one postcondition"); | |
90 assert(nextAddr == limit || !isMarked(nextAddr), | |
91 "get_next_one postcondition"); | |
92 return nextAddr; | |
93 } | |
94 | |
95 int CMBitMapRO::heapWordDiffToOffsetDiff(size_t diff) const { | |
96 assert((diff & ((1 << _shifter) - 1)) == 0, "argument check"); | |
97 return (int) (diff >> _shifter); | |
98 } | |
99 | |
100 bool CMBitMapRO::iterate(BitMapClosure* cl, MemRegion mr) { | |
101 HeapWord* left = MAX2(_bmStartWord, mr.start()); | |
102 HeapWord* right = MIN2(_bmStartWord + _bmWordSize, mr.end()); | |
103 if (right > left) { | |
104 // Right-open interval [leftOffset, rightOffset). | |
105 return _bm.iterate(cl, heapWordToOffset(left), heapWordToOffset(right)); | |
106 } else { | |
107 return true; | |
108 } | |
109 } | |
110 | |
111 void CMBitMapRO::mostly_disjoint_range_union(BitMap* from_bitmap, | |
112 size_t from_start_index, | |
113 HeapWord* to_start_word, | |
114 size_t word_num) { | |
115 _bm.mostly_disjoint_range_union(from_bitmap, | |
116 from_start_index, | |
117 heapWordToOffset(to_start_word), | |
118 word_num); | |
119 } | |
120 | |
121 #ifndef PRODUCT | |
122 bool CMBitMapRO::covers(ReservedSpace rs) const { | |
123 // assert(_bm.map() == _virtual_space.low(), "map inconsistency"); | |
645
c3a720eefe82
6816308: Changes to allow builds with latest Windows SDK 6.1 on 64bit Windows 2003
kvn
parents:
619
diff
changeset
|
124 assert(((size_t)_bm.size() * (size_t)(1 << _shifter)) == _bmWordSize, |
342 | 125 "size inconsistency"); |
126 return _bmStartWord == (HeapWord*)(rs.base()) && | |
127 _bmWordSize == rs.size()>>LogHeapWordSize; | |
128 } | |
129 #endif | |
130 | |
131 void CMBitMap::clearAll() { | |
132 _bm.clear(); | |
133 return; | |
134 } | |
135 | |
136 void CMBitMap::markRange(MemRegion mr) { | |
137 mr.intersection(MemRegion(_bmStartWord, _bmWordSize)); | |
138 assert(!mr.is_empty(), "unexpected empty region"); | |
139 assert((offsetToHeapWord(heapWordToOffset(mr.end())) == | |
140 ((HeapWord *) mr.end())), | |
141 "markRange memory region end is not card aligned"); | |
142 // convert address range into offset range | |
143 _bm.at_put_range(heapWordToOffset(mr.start()), | |
144 heapWordToOffset(mr.end()), true); | |
145 } | |
146 | |
147 void CMBitMap::clearRange(MemRegion mr) { | |
148 mr.intersection(MemRegion(_bmStartWord, _bmWordSize)); | |
149 assert(!mr.is_empty(), "unexpected empty region"); | |
150 // convert address range into offset range | |
151 _bm.at_put_range(heapWordToOffset(mr.start()), | |
152 heapWordToOffset(mr.end()), false); | |
153 } | |
154 | |
155 MemRegion CMBitMap::getAndClearMarkedRegion(HeapWord* addr, | |
156 HeapWord* end_addr) { | |
157 HeapWord* start = getNextMarkedWordAddress(addr); | |
158 start = MIN2(start, end_addr); | |
159 HeapWord* end = getNextUnmarkedWordAddress(start); | |
160 end = MIN2(end, end_addr); | |
161 assert(start <= end, "Consistency check"); | |
162 MemRegion mr(start, end); | |
163 if (!mr.is_empty()) { | |
164 clearRange(mr); | |
165 } | |
166 return mr; | |
167 } | |
168 | |
169 CMMarkStack::CMMarkStack(ConcurrentMark* cm) : | |
170 _base(NULL), _cm(cm) | |
171 #ifdef ASSERT | |
172 , _drain_in_progress(false) | |
173 , _drain_in_progress_yields(false) | |
174 #endif | |
175 {} | |
176 | |
177 void CMMarkStack::allocate(size_t size) { | |
178 _base = NEW_C_HEAP_ARRAY(oop, size); | |
179 if (_base == NULL) | |
180 vm_exit_during_initialization("Failed to allocate " | |
181 "CM region mark stack"); | |
182 _index = 0; | |
183 // QQQQ cast ... | |
184 _capacity = (jint) size; | |
185 _oops_do_bound = -1; | |
186 NOT_PRODUCT(_max_depth = 0); | |
187 } | |
188 | |
189 CMMarkStack::~CMMarkStack() { | |
190 if (_base != NULL) FREE_C_HEAP_ARRAY(oop, _base); | |
191 } | |
192 | |
193 void CMMarkStack::par_push(oop ptr) { | |
194 while (true) { | |
195 if (isFull()) { | |
196 _overflow = true; | |
197 return; | |
198 } | |
199 // Otherwise... | |
200 jint index = _index; | |
201 jint next_index = index+1; | |
202 jint res = Atomic::cmpxchg(next_index, &_index, index); | |
203 if (res == index) { | |
204 _base[index] = ptr; | |
205 // Note that we don't maintain this atomically. We could, but it | |
206 // doesn't seem necessary. | |
207 NOT_PRODUCT(_max_depth = MAX2(_max_depth, next_index)); | |
208 return; | |
209 } | |
210 // Otherwise, we need to try again. | |
211 } | |
212 } | |
213 | |
214 void CMMarkStack::par_adjoin_arr(oop* ptr_arr, int n) { | |
215 while (true) { | |
216 if (isFull()) { | |
217 _overflow = true; | |
218 return; | |
219 } | |
220 // Otherwise... | |
221 jint index = _index; | |
222 jint next_index = index + n; | |
223 if (next_index > _capacity) { | |
224 _overflow = true; | |
225 return; | |
226 } | |
227 jint res = Atomic::cmpxchg(next_index, &_index, index); | |
228 if (res == index) { | |
229 for (int i = 0; i < n; i++) { | |
230 int ind = index + i; | |
231 assert(ind < _capacity, "By overflow test above."); | |
232 _base[ind] = ptr_arr[i]; | |
233 } | |
234 NOT_PRODUCT(_max_depth = MAX2(_max_depth, next_index)); | |
235 return; | |
236 } | |
237 // Otherwise, we need to try again. | |
238 } | |
239 } | |
240 | |
241 | |
242 void CMMarkStack::par_push_arr(oop* ptr_arr, int n) { | |
243 MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag); | |
244 jint start = _index; | |
245 jint next_index = start + n; | |
246 if (next_index > _capacity) { | |
247 _overflow = true; | |
248 return; | |
249 } | |
250 // Otherwise. | |
251 _index = next_index; | |
252 for (int i = 0; i < n; i++) { | |
253 int ind = start + i; | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
254 assert(ind < _capacity, "By overflow test above."); |
342 | 255 _base[ind] = ptr_arr[i]; |
256 } | |
257 } | |
258 | |
259 | |
260 bool CMMarkStack::par_pop_arr(oop* ptr_arr, int max, int* n) { | |
261 MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag); | |
262 jint index = _index; | |
263 if (index == 0) { | |
264 *n = 0; | |
265 return false; | |
266 } else { | |
267 int k = MIN2(max, index); | |
268 jint new_ind = index - k; | |
269 for (int j = 0; j < k; j++) { | |
270 ptr_arr[j] = _base[new_ind + j]; | |
271 } | |
272 _index = new_ind; | |
273 *n = k; | |
274 return true; | |
275 } | |
276 } | |
277 | |
278 | |
279 CMRegionStack::CMRegionStack() : _base(NULL) {} | |
280 | |
281 void CMRegionStack::allocate(size_t size) { | |
282 _base = NEW_C_HEAP_ARRAY(MemRegion, size); | |
283 if (_base == NULL) | |
284 vm_exit_during_initialization("Failed to allocate " | |
285 "CM region mark stack"); | |
286 _index = 0; | |
287 // QQQQ cast ... | |
288 _capacity = (jint) size; | |
289 } | |
290 | |
291 CMRegionStack::~CMRegionStack() { | |
292 if (_base != NULL) FREE_C_HEAP_ARRAY(oop, _base); | |
293 } | |
294 | |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
295 void CMRegionStack::push_lock_free(MemRegion mr) { |
342 | 296 assert(mr.word_size() > 0, "Precondition"); |
297 while (true) { | |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
298 jint index = _index; |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
299 |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
300 if (index >= _capacity) { |
342 | 301 _overflow = true; |
302 return; | |
303 } | |
304 // Otherwise... | |
305 jint next_index = index+1; | |
306 jint res = Atomic::cmpxchg(next_index, &_index, index); | |
307 if (res == index) { | |
308 _base[index] = mr; | |
309 return; | |
310 } | |
311 // Otherwise, we need to try again. | |
312 } | |
313 } | |
314 | |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
315 // Lock-free pop of the region stack. Called during the concurrent |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
316 // marking / remark phases. Should only be called in tandem with |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
317 // other lock-free pops. |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
318 MemRegion CMRegionStack::pop_lock_free() { |
342 | 319 while (true) { |
320 jint index = _index; | |
321 | |
322 if (index == 0) { | |
323 return MemRegion(); | |
324 } | |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
325 // Otherwise... |
342 | 326 jint next_index = index-1; |
327 jint res = Atomic::cmpxchg(next_index, &_index, index); | |
328 if (res == index) { | |
329 MemRegion mr = _base[next_index]; | |
330 if (mr.start() != NULL) { | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
331 assert(mr.end() != NULL, "invariant"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
332 assert(mr.word_size() > 0, "invariant"); |
342 | 333 return mr; |
334 } else { | |
335 // that entry was invalidated... let's skip it | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
336 assert(mr.end() == NULL, "invariant"); |
342 | 337 } |
338 } | |
339 // Otherwise, we need to try again. | |
340 } | |
341 } | |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
342 |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
343 #if 0 |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
344 // The routines that manipulate the region stack with a lock are |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
345 // not currently used. They should be retained, however, as a |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
346 // diagnostic aid. |
1358
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
347 |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
348 void CMRegionStack::push_with_lock(MemRegion mr) { |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
349 assert(mr.word_size() > 0, "Precondition"); |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
350 MutexLockerEx x(CMRegionStack_lock, Mutex::_no_safepoint_check_flag); |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
351 |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
352 if (isFull()) { |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
353 _overflow = true; |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
354 return; |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
355 } |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
356 |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
357 _base[_index] = mr; |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
358 _index += 1; |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
359 } |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
360 |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
361 MemRegion CMRegionStack::pop_with_lock() { |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
362 MutexLockerEx x(CMRegionStack_lock, Mutex::_no_safepoint_check_flag); |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
363 |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
364 while (true) { |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
365 if (_index == 0) { |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
366 return MemRegion(); |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
367 } |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
368 _index -= 1; |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
369 |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
370 MemRegion mr = _base[_index]; |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
371 if (mr.start() != NULL) { |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
372 assert(mr.end() != NULL, "invariant"); |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
373 assert(mr.word_size() > 0, "invariant"); |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
374 return mr; |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
375 } else { |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
376 // that entry was invalidated... let's skip it |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
377 assert(mr.end() == NULL, "invariant"); |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
378 } |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
379 } |
72f725c5a7be
6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()
tonyp
parents:
1317
diff
changeset
|
380 } |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
381 #endif |
342 | 382 |
383 bool CMRegionStack::invalidate_entries_into_cset() { | |
384 bool result = false; | |
385 G1CollectedHeap* g1h = G1CollectedHeap::heap(); | |
386 for (int i = 0; i < _oops_do_bound; ++i) { | |
387 MemRegion mr = _base[i]; | |
388 if (mr.start() != NULL) { | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
389 assert(mr.end() != NULL, "invariant"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
390 assert(mr.word_size() > 0, "invariant"); |
342 | 391 HeapRegion* hr = g1h->heap_region_containing(mr.start()); |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
392 assert(hr != NULL, "invariant"); |
342 | 393 if (hr->in_collection_set()) { |
394 // The region points into the collection set | |
395 _base[i] = MemRegion(); | |
396 result = true; | |
397 } | |
398 } else { | |
399 // that entry was invalidated... let's skip it | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
400 assert(mr.end() == NULL, "invariant"); |
342 | 401 } |
402 } | |
403 return result; | |
404 } | |
405 | |
406 template<class OopClosureClass> | |
407 bool CMMarkStack::drain(OopClosureClass* cl, CMBitMap* bm, bool yield_after) { | |
408 assert(!_drain_in_progress || !_drain_in_progress_yields || yield_after | |
409 || SafepointSynchronize::is_at_safepoint(), | |
410 "Drain recursion must be yield-safe."); | |
411 bool res = true; | |
412 debug_only(_drain_in_progress = true); | |
413 debug_only(_drain_in_progress_yields = yield_after); | |
414 while (!isEmpty()) { | |
415 oop newOop = pop(); | |
416 assert(G1CollectedHeap::heap()->is_in_reserved(newOop), "Bad pop"); | |
417 assert(newOop->is_oop(), "Expected an oop"); | |
418 assert(bm == NULL || bm->isMarked((HeapWord*)newOop), | |
419 "only grey objects on this stack"); | |
420 // iterate over the oops in this oop, marking and pushing | |
421 // the ones in CMS generation. | |
422 newOop->oop_iterate(cl); | |
423 if (yield_after && _cm->do_yield_check()) { | |
424 res = false; break; | |
425 } | |
426 } | |
427 debug_only(_drain_in_progress = false); | |
428 return res; | |
429 } | |
430 | |
431 void CMMarkStack::oops_do(OopClosure* f) { | |
432 if (_index == 0) return; | |
433 assert(_oops_do_bound != -1 && _oops_do_bound <= _index, | |
434 "Bound must be set."); | |
435 for (int i = 0; i < _oops_do_bound; i++) { | |
436 f->do_oop(&_base[i]); | |
437 } | |
438 _oops_do_bound = -1; | |
439 } | |
440 | |
441 bool ConcurrentMark::not_yet_marked(oop obj) const { | |
442 return (_g1h->is_obj_ill(obj) | |
443 || (_g1h->is_in_permanent(obj) | |
444 && !nextMarkBitMap()->isMarked((HeapWord*)obj))); | |
445 } | |
446 | |
447 #ifdef _MSC_VER // the use of 'this' below gets a warning, make it go away | |
448 #pragma warning( disable:4355 ) // 'this' : used in base member initializer list | |
449 #endif // _MSC_VER | |
450 | |
451 ConcurrentMark::ConcurrentMark(ReservedSpace rs, | |
452 int max_regions) : | |
453 _markBitMap1(rs, MinObjAlignment - 1), | |
454 _markBitMap2(rs, MinObjAlignment - 1), | |
455 | |
456 _parallel_marking_threads(0), | |
457 _sleep_factor(0.0), | |
458 _marking_task_overhead(1.0), | |
459 _cleanup_sleep_factor(0.0), | |
460 _cleanup_task_overhead(1.0), | |
2152 | 461 _cleanup_list("Cleanup List"), |
342 | 462 _region_bm(max_regions, false /* in_resource_area*/), |
463 _card_bm((rs.size() + CardTableModRefBS::card_size - 1) >> | |
464 CardTableModRefBS::card_shift, | |
465 false /* in_resource_area*/), | |
466 _prevMarkBitMap(&_markBitMap1), | |
467 _nextMarkBitMap(&_markBitMap2), | |
468 _at_least_one_mark_complete(false), | |
469 | |
470 _markStack(this), | |
471 _regionStack(), | |
472 // _finger set in set_non_marking_state | |
473 | |
474 _max_task_num(MAX2(ParallelGCThreads, (size_t)1)), | |
475 // _active_tasks set in set_non_marking_state | |
476 // _tasks set inside the constructor | |
477 _task_queues(new CMTaskQueueSet((int) _max_task_num)), | |
478 _terminator(ParallelTaskTerminator((int) _max_task_num, _task_queues)), | |
479 | |
480 _has_overflown(false), | |
481 _concurrent(false), | |
619
7ea5ca260b28
6814467: G1: small fixes related to concurrent marking verboseness
tonyp
parents:
470
diff
changeset
|
482 _has_aborted(false), |
7ea5ca260b28
6814467: G1: small fixes related to concurrent marking verboseness
tonyp
parents:
470
diff
changeset
|
483 _restart_for_overflow(false), |
7ea5ca260b28
6814467: G1: small fixes related to concurrent marking verboseness
tonyp
parents:
470
diff
changeset
|
484 _concurrent_marking_in_progress(false), |
7ea5ca260b28
6814467: G1: small fixes related to concurrent marking verboseness
tonyp
parents:
470
diff
changeset
|
485 _should_gray_objects(false), |
342 | 486 |
487 // _verbose_level set below | |
488 | |
489 _init_times(), | |
490 _remark_times(), _remark_mark_times(), _remark_weak_ref_times(), | |
491 _cleanup_times(), | |
492 _total_counting_time(0.0), | |
493 _total_rs_scrub_time(0.0), | |
494 | |
936 | 495 _parallel_workers(NULL) |
342 | 496 { |
497 CMVerboseLevel verbose_level = | |
498 (CMVerboseLevel) G1MarkingVerboseLevel; | |
499 if (verbose_level < no_verbose) | |
500 verbose_level = no_verbose; | |
501 if (verbose_level > high_verbose) | |
502 verbose_level = high_verbose; | |
503 _verbose_level = verbose_level; | |
504 | |
505 if (verbose_low()) | |
506 gclog_or_tty->print_cr("[global] init, heap start = "PTR_FORMAT", " | |
507 "heap end = "PTR_FORMAT, _heap_start, _heap_end); | |
508 | |
1284 | 509 _markStack.allocate(MarkStackSize); |
751 | 510 _regionStack.allocate(G1MarkRegionStackSize); |
342 | 511 |
512 // Create & start a ConcurrentMark thread. | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
513 _cmThread = new ConcurrentMarkThread(this); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
514 assert(cmThread() != NULL, "CM Thread should have been created"); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
515 assert(cmThread()->cm() != NULL, "CM Thread should refer to this cm"); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
516 |
342 | 517 _g1h = G1CollectedHeap::heap(); |
518 assert(CGC_lock != NULL, "Where's the CGC_lock?"); | |
519 assert(_markBitMap1.covers(rs), "_markBitMap1 inconsistency"); | |
520 assert(_markBitMap2.covers(rs), "_markBitMap2 inconsistency"); | |
521 | |
522 SATBMarkQueueSet& satb_qs = JavaThread::satb_mark_queue_set(); | |
1282 | 523 satb_qs.set_buffer_size(G1SATBBufferSize); |
342 | 524 |
525 _tasks = NEW_C_HEAP_ARRAY(CMTask*, _max_task_num); | |
526 _accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_task_num); | |
527 | |
528 // so that the assertion in MarkingTaskQueue::task_queue doesn't fail | |
529 _active_tasks = _max_task_num; | |
530 for (int i = 0; i < (int) _max_task_num; ++i) { | |
531 CMTaskQueue* task_queue = new CMTaskQueue(); | |
532 task_queue->initialize(); | |
533 _task_queues->register_queue(i, task_queue); | |
534 | |
535 _tasks[i] = new CMTask(i, this, task_queue, _task_queues); | |
536 _accum_task_vtime[i] = 0.0; | |
537 } | |
538 | |
1284 | 539 if (ConcGCThreads > ParallelGCThreads) { |
540 vm_exit_during_initialization("Can't have more ConcGCThreads " | |
342 | 541 "than ParallelGCThreads."); |
542 } | |
543 if (ParallelGCThreads == 0) { | |
544 // if we are not running with any parallel GC threads we will not | |
545 // spawn any marking threads either | |
546 _parallel_marking_threads = 0; | |
547 _sleep_factor = 0.0; | |
548 _marking_task_overhead = 1.0; | |
549 } else { | |
1284 | 550 if (ConcGCThreads > 0) { |
551 // notice that ConcGCThreads overwrites G1MarkingOverheadPercent | |
342 | 552 // if both are set |
553 | |
1284 | 554 _parallel_marking_threads = ConcGCThreads; |
342 | 555 _sleep_factor = 0.0; |
556 _marking_task_overhead = 1.0; | |
751 | 557 } else if (G1MarkingOverheadPercent > 0) { |
342 | 558 // we will calculate the number of parallel marking threads |
559 // based on a target overhead with respect to the soft real-time | |
560 // goal | |
561 | |
751 | 562 double marking_overhead = (double) G1MarkingOverheadPercent / 100.0; |
342 | 563 double overall_cm_overhead = |
751 | 564 (double) MaxGCPauseMillis * marking_overhead / |
565 (double) GCPauseIntervalMillis; | |
342 | 566 double cpu_ratio = 1.0 / (double) os::processor_count(); |
567 double marking_thread_num = ceil(overall_cm_overhead / cpu_ratio); | |
568 double marking_task_overhead = | |
569 overall_cm_overhead / marking_thread_num * | |
570 (double) os::processor_count(); | |
571 double sleep_factor = | |
572 (1.0 - marking_task_overhead) / marking_task_overhead; | |
573 | |
574 _parallel_marking_threads = (size_t) marking_thread_num; | |
575 _sleep_factor = sleep_factor; | |
576 _marking_task_overhead = marking_task_overhead; | |
577 } else { | |
578 _parallel_marking_threads = MAX2((ParallelGCThreads + 2) / 4, (size_t)1); | |
579 _sleep_factor = 0.0; | |
580 _marking_task_overhead = 1.0; | |
581 } | |
582 | |
583 if (parallel_marking_threads() > 1) | |
584 _cleanup_task_overhead = 1.0; | |
585 else | |
586 _cleanup_task_overhead = marking_task_overhead(); | |
587 _cleanup_sleep_factor = | |
588 (1.0 - cleanup_task_overhead()) / cleanup_task_overhead(); | |
589 | |
590 #if 0 | |
591 gclog_or_tty->print_cr("Marking Threads %d", parallel_marking_threads()); | |
592 gclog_or_tty->print_cr("CM Marking Task Overhead %1.4lf", marking_task_overhead()); | |
593 gclog_or_tty->print_cr("CM Sleep Factor %1.4lf", sleep_factor()); | |
594 gclog_or_tty->print_cr("CL Marking Task Overhead %1.4lf", cleanup_task_overhead()); | |
595 gclog_or_tty->print_cr("CL Sleep Factor %1.4lf", cleanup_sleep_factor()); | |
596 #endif | |
597 | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
598 guarantee(parallel_marking_threads() > 0, "peace of mind"); |
1833
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1719
diff
changeset
|
599 _parallel_workers = new FlexibleWorkGang("G1 Parallel Marking Threads", |
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1719
diff
changeset
|
600 (int) _parallel_marking_threads, false, true); |
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1719
diff
changeset
|
601 if (_parallel_workers == NULL) { |
342 | 602 vm_exit_during_initialization("Failed necessary allocation."); |
1833
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1719
diff
changeset
|
603 } else { |
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1719
diff
changeset
|
604 _parallel_workers->initialize_workers(); |
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1719
diff
changeset
|
605 } |
342 | 606 } |
607 | |
608 // so that the call below can read a sensible value | |
609 _heap_start = (HeapWord*) rs.base(); | |
610 set_non_marking_state(); | |
611 } | |
612 | |
613 void ConcurrentMark::update_g1_committed(bool force) { | |
614 // If concurrent marking is not in progress, then we do not need to | |
615 // update _heap_end. This has a subtle and important | |
616 // side-effect. Imagine that two evacuation pauses happen between | |
617 // marking completion and remark. The first one can grow the | |
618 // heap (hence now the finger is below the heap end). Then, the | |
619 // second one could unnecessarily push regions on the region | |
620 // stack. This causes the invariant that the region stack is empty | |
621 // at the beginning of remark to be false. By ensuring that we do | |
622 // not observe heap expansions after marking is complete, then we do | |
623 // not have this problem. | |
624 if (!concurrent_marking_in_progress() && !force) | |
625 return; | |
626 | |
627 MemRegion committed = _g1h->g1_committed(); | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
628 assert(committed.start() == _heap_start, "start shouldn't change"); |
342 | 629 HeapWord* new_end = committed.end(); |
630 if (new_end > _heap_end) { | |
631 // The heap has been expanded. | |
632 | |
633 _heap_end = new_end; | |
634 } | |
635 // Notice that the heap can also shrink. However, this only happens | |
636 // during a Full GC (at least currently) and the entire marking | |
637 // phase will bail out and the task will not be restarted. So, let's | |
638 // do nothing. | |
639 } | |
640 | |
641 void ConcurrentMark::reset() { | |
642 // Starting values for these two. This should be called in a STW | |
643 // phase. CM will be notified of any future g1_committed expansions | |
644 // will be at the end of evacuation pauses, when tasks are | |
645 // inactive. | |
646 MemRegion committed = _g1h->g1_committed(); | |
647 _heap_start = committed.start(); | |
648 _heap_end = committed.end(); | |
649 | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
650 // Separated the asserts so that we know which one fires. |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
651 assert(_heap_start != NULL, "heap bounds should look ok"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
652 assert(_heap_end != NULL, "heap bounds should look ok"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
653 assert(_heap_start < _heap_end, "heap bounds should look ok"); |
342 | 654 |
655 // reset all the marking data structures and any necessary flags | |
656 clear_marking_state(); | |
657 | |
658 if (verbose_low()) | |
659 gclog_or_tty->print_cr("[global] resetting"); | |
660 | |
661 // We do reset all of them, since different phases will use | |
662 // different number of active threads. So, it's easiest to have all | |
663 // of them ready. | |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
664 for (int i = 0; i < (int) _max_task_num; ++i) { |
342 | 665 _tasks[i]->reset(_nextMarkBitMap); |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
666 } |
342 | 667 |
668 // we need this to make sure that the flag is on during the evac | |
669 // pause with initial mark piggy-backed | |
670 set_concurrent_marking_in_progress(); | |
671 } | |
672 | |
673 void ConcurrentMark::set_phase(size_t active_tasks, bool concurrent) { | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
674 assert(active_tasks <= _max_task_num, "we should not have more"); |
342 | 675 |
676 _active_tasks = active_tasks; | |
677 // Need to update the three data structures below according to the | |
678 // number of active threads for this phase. | |
679 _terminator = ParallelTaskTerminator((int) active_tasks, _task_queues); | |
680 _first_overflow_barrier_sync.set_n_workers((int) active_tasks); | |
681 _second_overflow_barrier_sync.set_n_workers((int) active_tasks); | |
682 | |
683 _concurrent = concurrent; | |
684 // We propagate this to all tasks, not just the active ones. | |
685 for (int i = 0; i < (int) _max_task_num; ++i) | |
686 _tasks[i]->set_concurrent(concurrent); | |
687 | |
688 if (concurrent) { | |
689 set_concurrent_marking_in_progress(); | |
690 } else { | |
691 // We currently assume that the concurrent flag has been set to | |
692 // false before we start remark. At this point we should also be | |
693 // in a STW phase. | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
694 assert(!concurrent_marking_in_progress(), "invariant"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
695 assert(_finger == _heap_end, "only way to get here"); |
342 | 696 update_g1_committed(true); |
697 } | |
698 } | |
699 | |
700 void ConcurrentMark::set_non_marking_state() { | |
701 // We set the global marking state to some default values when we're | |
702 // not doing marking. | |
703 clear_marking_state(); | |
704 _active_tasks = 0; | |
705 clear_concurrent_marking_in_progress(); | |
706 } | |
707 | |
708 ConcurrentMark::~ConcurrentMark() { | |
709 for (int i = 0; i < (int) _max_task_num; ++i) { | |
710 delete _task_queues->queue(i); | |
711 delete _tasks[i]; | |
712 } | |
713 delete _task_queues; | |
714 FREE_C_HEAP_ARRAY(CMTask*, _max_task_num); | |
715 } | |
716 | |
717 // This closure is used to mark refs into the g1 generation | |
718 // from external roots in the CMS bit map. | |
719 // Called at the first checkpoint. | |
720 // | |
721 | |
722 void ConcurrentMark::clearNextBitmap() { | |
1359
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
723 G1CollectedHeap* g1h = G1CollectedHeap::heap(); |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
724 G1CollectorPolicy* g1p = g1h->g1_policy(); |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
725 |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
726 // Make sure that the concurrent mark thread looks to still be in |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
727 // the current cycle. |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
728 guarantee(cmThread()->during_cycle(), "invariant"); |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
729 |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
730 // We are finishing up the current cycle by clearing the next |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
731 // marking bitmap and getting it ready for the next cycle. During |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
732 // this time no other cycle can start. So, let's make sure that this |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
733 // is the case. |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
734 guarantee(!g1h->mark_in_progress(), "invariant"); |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
735 |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
736 // clear the mark bitmap (no grey objects to start with). |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
737 // We need to do this in chunks and offer to yield in between |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
738 // each chunk. |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
739 HeapWord* start = _nextMarkBitMap->startWord(); |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
740 HeapWord* end = _nextMarkBitMap->endWord(); |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
741 HeapWord* cur = start; |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
742 size_t chunkSize = M; |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
743 while (cur < end) { |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
744 HeapWord* next = cur + chunkSize; |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
745 if (next > end) |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
746 next = end; |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
747 MemRegion mr(cur,next); |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
748 _nextMarkBitMap->clearRange(mr); |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
749 cur = next; |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
750 do_yield_check(); |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
751 |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
752 // Repeat the asserts from above. We'll do them as asserts here to |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
753 // minimize their overhead on the product. However, we'll have |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
754 // them as guarantees at the beginning / end of the bitmap |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
755 // clearing to get some checking in the product. |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
756 assert(cmThread()->during_cycle(), "invariant"); |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
757 assert(!g1h->mark_in_progress(), "invariant"); |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
758 } |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
759 |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
760 // Repeat the asserts from above. |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
761 guarantee(cmThread()->during_cycle(), "invariant"); |
23b1b27ac76c
6909756: G1: guarantee(G1CollectedHeap::heap()->mark_in_progress(),"Precondition.")
tonyp
parents:
1358
diff
changeset
|
762 guarantee(!g1h->mark_in_progress(), "invariant"); |
342 | 763 } |
764 | |
765 class NoteStartOfMarkHRClosure: public HeapRegionClosure { | |
766 public: | |
767 bool doHeapRegion(HeapRegion* r) { | |
768 if (!r->continuesHumongous()) { | |
769 r->note_start_of_marking(true); | |
770 } | |
771 return false; | |
772 } | |
773 }; | |
774 | |
775 void ConcurrentMark::checkpointRootsInitialPre() { | |
776 G1CollectedHeap* g1h = G1CollectedHeap::heap(); | |
777 G1CollectorPolicy* g1p = g1h->g1_policy(); | |
778 | |
779 _has_aborted = false; | |
780 | |
1547
fb1a39993f69
6951319: enable solaris builds using Sun Studio 12 update 1
jcoomes
parents:
1388
diff
changeset
|
781 #ifndef PRODUCT |
1044 | 782 if (G1PrintReachableAtInitialMark) { |
1388 | 783 print_reachable("at-cycle-start", |
784 true /* use_prev_marking */, true /* all */); | |
1044 | 785 } |
1547
fb1a39993f69
6951319: enable solaris builds using Sun Studio 12 update 1
jcoomes
parents:
1388
diff
changeset
|
786 #endif |
342 | 787 |
788 // Initialise marking structures. This has to be done in a STW phase. | |
789 reset(); | |
790 } | |
791 | |
792 class CMMarkRootsClosure: public OopsInGenClosure { | |
793 private: | |
794 ConcurrentMark* _cm; | |
795 G1CollectedHeap* _g1h; | |
796 bool _do_barrier; | |
797 | |
798 public: | |
799 CMMarkRootsClosure(ConcurrentMark* cm, | |
800 G1CollectedHeap* g1h, | |
801 bool do_barrier) : _cm(cm), _g1h(g1h), | |
802 _do_barrier(do_barrier) { } | |
803 | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
804 virtual void do_oop(narrowOop* p) { do_oop_work(p); } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
805 virtual void do_oop( oop* p) { do_oop_work(p); } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
806 |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
807 template <class T> void do_oop_work(T* p) { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
808 T heap_oop = oopDesc::load_heap_oop(p); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
809 if (!oopDesc::is_null(heap_oop)) { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
810 oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
811 assert(obj->is_oop() || obj->mark() == NULL, |
342 | 812 "expected an oop, possibly with mark word displaced"); |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
813 HeapWord* addr = (HeapWord*)obj; |
342 | 814 if (_g1h->is_in_g1_reserved(addr)) { |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
815 _cm->grayRoot(obj); |
342 | 816 } |
817 } | |
818 if (_do_barrier) { | |
819 assert(!_g1h->is_in_g1_reserved(p), | |
820 "Should be called on external roots"); | |
821 do_barrier(p); | |
822 } | |
823 } | |
824 }; | |
825 | |
826 void ConcurrentMark::checkpointRootsInitialPost() { | |
827 G1CollectedHeap* g1h = G1CollectedHeap::heap(); | |
828 | |
829 // For each region note start of marking. | |
830 NoteStartOfMarkHRClosure startcl; | |
831 g1h->heap_region_iterate(&startcl); | |
832 | |
833 // Start weak-reference discovery. | |
834 ReferenceProcessor* rp = g1h->ref_processor(); | |
835 rp->verify_no_references_recorded(); | |
836 rp->enable_discovery(); // enable ("weak") refs discovery | |
457
27a80744a83b
6778647: snap(), snap_policy() should be renamed setup(), setup_policy()
ysr
parents:
453
diff
changeset
|
837 rp->setup_policy(false); // snapshot the soft ref policy to be used in this cycle |
342 | 838 |
839 SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); | |
1317
d4197f8d516a
6935821: G1: threads created during marking do not active their SATB queues
tonyp
parents:
1314
diff
changeset
|
840 // This is the start of the marking cycle, we're expected all |
d4197f8d516a
6935821: G1: threads created during marking do not active their SATB queues
tonyp
parents:
1314
diff
changeset
|
841 // threads to have SATB queues with active set to false. |
d4197f8d516a
6935821: G1: threads created during marking do not active their SATB queues
tonyp
parents:
1314
diff
changeset
|
842 satb_mq_set.set_active_all_threads(true, /* new active value */ |
d4197f8d516a
6935821: G1: threads created during marking do not active their SATB queues
tonyp
parents:
1314
diff
changeset
|
843 false /* expected_active */); |
342 | 844 |
845 // update_g1_committed() will be called at the end of an evac pause | |
846 // when marking is on. So, it's also called at the end of the | |
847 // initial-mark pause to update the heap end, if the heap expands | |
848 // during it. No need to call it here. | |
849 } | |
850 | |
851 // Checkpoint the roots into this generation from outside | |
852 // this generation. [Note this initial checkpoint need only | |
853 // be approximate -- we'll do a catch up phase subsequently.] | |
854 void ConcurrentMark::checkpointRootsInitial() { | |
855 assert(SafepointSynchronize::is_at_safepoint(), "world should be stopped"); | |
856 G1CollectedHeap* g1h = G1CollectedHeap::heap(); | |
857 | |
858 double start = os::elapsedTime(); | |
859 | |
860 G1CollectorPolicy* g1p = G1CollectedHeap::heap()->g1_policy(); | |
861 g1p->record_concurrent_mark_init_start(); | |
862 checkpointRootsInitialPre(); | |
863 | |
864 // YSR: when concurrent precleaning is in place, we'll | |
865 // need to clear the cached card table here | |
866 | |
867 ResourceMark rm; | |
868 HandleMark hm; | |
869 | |
870 g1h->ensure_parsability(false); | |
871 g1h->perm_gen()->save_marks(); | |
872 | |
873 CMMarkRootsClosure notOlder(this, g1h, false); | |
874 CMMarkRootsClosure older(this, g1h, true); | |
875 | |
876 g1h->set_marking_started(); | |
877 g1h->rem_set()->prepare_for_younger_refs_iterate(false); | |
878 | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
912
diff
changeset
|
879 g1h->process_strong_roots(true, // activate StrongRootsScope |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
912
diff
changeset
|
880 false, // fake perm gen collection |
342 | 881 SharedHeap::SO_AllClasses, |
882 ¬Older, // Regular roots | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
912
diff
changeset
|
883 NULL, // do not visit active blobs |
342 | 884 &older // Perm Gen Roots |
885 ); | |
886 checkpointRootsInitialPost(); | |
887 | |
888 // Statistics. | |
889 double end = os::elapsedTime(); | |
890 _init_times.add((end - start) * 1000.0); | |
891 | |
892 g1p->record_concurrent_mark_init_end(); | |
893 } | |
894 | |
895 /* | |
896 Notice that in the next two methods, we actually leave the STS | |
897 during the barrier sync and join it immediately afterwards. If we | |
898 do not do this, this then the following deadlock can occur: one | |
899 thread could be in the barrier sync code, waiting for the other | |
900 thread to also sync up, whereas another one could be trying to | |
901 yield, while also waiting for the other threads to sync up too. | |
902 | |
903 Because the thread that does the sync barrier has left the STS, it | |
904 is possible to be suspended for a Full GC or an evacuation pause | |
905 could occur. This is actually safe, since the entering the sync | |
906 barrier is one of the last things do_marking_step() does, and it | |
907 doesn't manipulate any data structures afterwards. | |
908 */ | |
909 | |
910 void ConcurrentMark::enter_first_sync_barrier(int task_num) { | |
911 if (verbose_low()) | |
912 gclog_or_tty->print_cr("[%d] entering first barrier", task_num); | |
913 | |
914 ConcurrentGCThread::stsLeave(); | |
915 _first_overflow_barrier_sync.enter(); | |
916 ConcurrentGCThread::stsJoin(); | |
917 // at this point everyone should have synced up and not be doing any | |
918 // more work | |
919 | |
920 if (verbose_low()) | |
921 gclog_or_tty->print_cr("[%d] leaving first barrier", task_num); | |
922 | |
923 // let task 0 do this | |
924 if (task_num == 0) { | |
925 // task 0 is responsible for clearing the global data structures | |
926 clear_marking_state(); | |
927 | |
928 if (PrintGC) { | |
929 gclog_or_tty->date_stamp(PrintGCDateStamps); | |
930 gclog_or_tty->stamp(PrintGCTimeStamps); | |
931 gclog_or_tty->print_cr("[GC concurrent-mark-reset-for-overflow]"); | |
932 } | |
933 } | |
934 | |
935 // after this, each task should reset its own data structures then | |
936 // then go into the second barrier | |
937 } | |
938 | |
939 void ConcurrentMark::enter_second_sync_barrier(int task_num) { | |
940 if (verbose_low()) | |
941 gclog_or_tty->print_cr("[%d] entering second barrier", task_num); | |
942 | |
943 ConcurrentGCThread::stsLeave(); | |
944 _second_overflow_barrier_sync.enter(); | |
945 ConcurrentGCThread::stsJoin(); | |
946 // at this point everything should be re-initialised and ready to go | |
947 | |
948 if (verbose_low()) | |
949 gclog_or_tty->print_cr("[%d] leaving second barrier", task_num); | |
950 } | |
951 | |
952 void ConcurrentMark::grayRoot(oop p) { | |
953 HeapWord* addr = (HeapWord*) p; | |
954 // We can't really check against _heap_start and _heap_end, since it | |
955 // is possible during an evacuation pause with piggy-backed | |
956 // initial-mark that the committed space is expanded during the | |
957 // pause without CM observing this change. So the assertions below | |
958 // is a bit conservative; but better than nothing. | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
959 assert(_g1h->g1_committed().contains(addr), |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
960 "address should be within the heap bounds"); |
342 | 961 |
962 if (!_nextMarkBitMap->isMarked(addr)) | |
963 _nextMarkBitMap->parMark(addr); | |
964 } | |
965 | |
966 void ConcurrentMark::grayRegionIfNecessary(MemRegion mr) { | |
967 // The objects on the region have already been marked "in bulk" by | |
968 // the caller. We only need to decide whether to push the region on | |
969 // the region stack or not. | |
970 | |
971 if (!concurrent_marking_in_progress() || !_should_gray_objects) | |
972 // We're done with marking and waiting for remark. We do not need to | |
973 // push anything else on the region stack. | |
974 return; | |
975 | |
976 HeapWord* finger = _finger; | |
977 | |
978 if (verbose_low()) | |
979 gclog_or_tty->print_cr("[global] attempting to push " | |
980 "region ["PTR_FORMAT", "PTR_FORMAT"), finger is at " | |
981 PTR_FORMAT, mr.start(), mr.end(), finger); | |
982 | |
983 if (mr.start() < finger) { | |
984 // The finger is always heap region aligned and it is not possible | |
985 // for mr to span heap regions. | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
986 assert(mr.end() <= finger, "invariant"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
987 |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
988 // Separated the asserts so that we know which one fires. |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
989 assert(mr.start() <= mr.end(), |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
990 "region boundaries should fall within the committed space"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
991 assert(_heap_start <= mr.start(), |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
992 "region boundaries should fall within the committed space"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
993 assert(mr.end() <= _heap_end, |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
994 "region boundaries should fall within the committed space"); |
342 | 995 if (verbose_low()) |
996 gclog_or_tty->print_cr("[global] region ["PTR_FORMAT", "PTR_FORMAT") " | |
997 "below the finger, pushing it", | |
998 mr.start(), mr.end()); | |
999 | |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
1000 if (!region_stack_push_lock_free(mr)) { |
342 | 1001 if (verbose_low()) |
1002 gclog_or_tty->print_cr("[global] region stack has overflown."); | |
1003 } | |
1004 } | |
1005 } | |
1006 | |
1007 void ConcurrentMark::markAndGrayObjectIfNecessary(oop p) { | |
1008 // The object is not marked by the caller. We need to at least mark | |
1009 // it and maybe push in on the stack. | |
1010 | |
1011 HeapWord* addr = (HeapWord*)p; | |
1012 if (!_nextMarkBitMap->isMarked(addr)) { | |
1013 // We definitely need to mark it, irrespective whether we bail out | |
1014 // because we're done with marking. | |
1015 if (_nextMarkBitMap->parMark(addr)) { | |
1016 if (!concurrent_marking_in_progress() || !_should_gray_objects) | |
1017 // If we're done with concurrent marking and we're waiting for | |
1018 // remark, then we're not pushing anything on the stack. | |
1019 return; | |
1020 | |
1021 // No OrderAccess:store_load() is needed. It is implicit in the | |
1022 // CAS done in parMark(addr) above | |
1023 HeapWord* finger = _finger; | |
1024 | |
1025 if (addr < finger) { | |
1026 if (!mark_stack_push(oop(addr))) { | |
1027 if (verbose_low()) | |
1028 gclog_or_tty->print_cr("[global] global stack overflow " | |
1029 "during parMark"); | |
1030 } | |
1031 } | |
1032 } | |
1033 } | |
1034 } | |
1035 | |
1036 class CMConcurrentMarkingTask: public AbstractGangTask { | |
1037 private: | |
1038 ConcurrentMark* _cm; | |
1039 ConcurrentMarkThread* _cmt; | |
1040 | |
1041 public: | |
1042 void work(int worker_i) { | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
1043 assert(Thread::current()->is_ConcurrentGC_thread(), |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
1044 "this should only be done by a conc GC thread"); |
1974
fd1d227ef1b9
6983204: G1: Nightly test nsk/regression/b4958615 failing with +ExplicitGCInvokesConcurrent
johnc
parents:
1972
diff
changeset
|
1045 ResourceMark rm; |
342 | 1046 |
1047 double start_vtime = os::elapsedVTime(); | |
1048 | |
1049 ConcurrentGCThread::stsJoin(); | |
1050 | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
1051 assert((size_t) worker_i < _cm->active_tasks(), "invariant"); |
342 | 1052 CMTask* the_task = _cm->task(worker_i); |
1053 the_task->record_start_time(); | |
1054 if (!_cm->has_aborted()) { | |
1055 do { | |
1056 double start_vtime_sec = os::elapsedVTime(); | |
1057 double start_time_sec = os::elapsedTime(); | |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1058 double mark_step_duration_ms = G1ConcMarkStepDurationMillis; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1059 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1060 the_task->do_marking_step(mark_step_duration_ms, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1061 true /* do_stealing */, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1062 true /* do_termination */); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1063 |
342 | 1064 double end_time_sec = os::elapsedTime(); |
1065 double end_vtime_sec = os::elapsedVTime(); | |
1066 double elapsed_vtime_sec = end_vtime_sec - start_vtime_sec; | |
1067 double elapsed_time_sec = end_time_sec - start_time_sec; | |
1068 _cm->clear_has_overflown(); | |
1069 | |
1070 bool ret = _cm->do_yield_check(worker_i); | |
1071 | |
1072 jlong sleep_time_ms; | |
1073 if (!_cm->has_aborted() && the_task->has_aborted()) { | |
1074 sleep_time_ms = | |
1075 (jlong) (elapsed_vtime_sec * _cm->sleep_factor() * 1000.0); | |
1076 ConcurrentGCThread::stsLeave(); | |
1077 os::sleep(Thread::current(), sleep_time_ms, false); | |
1078 ConcurrentGCThread::stsJoin(); | |
1079 } | |
1080 double end_time2_sec = os::elapsedTime(); | |
1081 double elapsed_time2_sec = end_time2_sec - start_time_sec; | |
1082 | |
1083 #if 0 | |
1084 gclog_or_tty->print_cr("CM: elapsed %1.4lf ms, sleep %1.4lf ms, " | |
1085 "overhead %1.4lf", | |
1086 elapsed_vtime_sec * 1000.0, (double) sleep_time_ms, | |
1087 the_task->conc_overhead(os::elapsedTime()) * 8.0); | |
1088 gclog_or_tty->print_cr("elapsed time %1.4lf ms, time 2: %1.4lf ms", | |
1089 elapsed_time_sec * 1000.0, elapsed_time2_sec * 1000.0); | |
1090 #endif | |
1091 } while (!_cm->has_aborted() && the_task->has_aborted()); | |
1092 } | |
1093 the_task->record_end_time(); | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
1094 guarantee(!the_task->has_aborted() || _cm->has_aborted(), "invariant"); |
342 | 1095 |
1096 ConcurrentGCThread::stsLeave(); | |
1097 | |
1098 double end_vtime = os::elapsedVTime(); | |
1099 _cm->update_accum_task_vtime(worker_i, end_vtime - start_vtime); | |
1100 } | |
1101 | |
1102 CMConcurrentMarkingTask(ConcurrentMark* cm, | |
1103 ConcurrentMarkThread* cmt) : | |
1104 AbstractGangTask("Concurrent Mark"), _cm(cm), _cmt(cmt) { } | |
1105 | |
1106 ~CMConcurrentMarkingTask() { } | |
1107 }; | |
1108 | |
1109 void ConcurrentMark::markFromRoots() { | |
1110 // we might be tempted to assert that: | |
1111 // assert(asynch == !SafepointSynchronize::is_at_safepoint(), | |
1112 // "inconsistent argument?"); | |
1113 // However that wouldn't be right, because it's possible that | |
1114 // a safepoint is indeed in progress as a younger generation | |
1115 // stop-the-world GC happens even as we mark in this generation. | |
1116 | |
1117 _restart_for_overflow = false; | |
1118 | |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1119 size_t active_workers = MAX2((size_t) 1, parallel_marking_threads()); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1120 set_phase(active_workers, true /* concurrent */); |
342 | 1121 |
1122 CMConcurrentMarkingTask markingTask(this, cmThread()); | |
1123 if (parallel_marking_threads() > 0) | |
1124 _parallel_workers->run_task(&markingTask); | |
1125 else | |
1126 markingTask.work(0); | |
1127 print_stats(); | |
1128 } | |
1129 | |
1130 void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { | |
1131 // world is stopped at this checkpoint | |
1132 assert(SafepointSynchronize::is_at_safepoint(), | |
1133 "world should be stopped"); | |
1134 G1CollectedHeap* g1h = G1CollectedHeap::heap(); | |
1135 | |
1136 // If a full collection has happened, we shouldn't do this. | |
1137 if (has_aborted()) { | |
1138 g1h->set_marking_complete(); // So bitmap clearing isn't confused | |
1139 return; | |
1140 } | |
1141 | |
2125
7246a374a9f2
6458402: 3 jvmti tests fail with CMS and +ExplicitGCInvokesConcurrent
kamg
parents:
2037
diff
changeset
|
1142 SvcGCMarker sgcm(SvcGCMarker::OTHER); |
7246a374a9f2
6458402: 3 jvmti tests fail with CMS and +ExplicitGCInvokesConcurrent
kamg
parents:
2037
diff
changeset
|
1143 |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1144 if (VerifyDuringGC) { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1145 HandleMark hm; // handle scope |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1146 gclog_or_tty->print(" VerifyDuringGC:(before)"); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1147 Universe::heap()->prepare_for_verify(); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1148 Universe::verify(true, false, true); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1149 } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1150 |
342 | 1151 G1CollectorPolicy* g1p = g1h->g1_policy(); |
1152 g1p->record_concurrent_mark_remark_start(); | |
1153 | |
1154 double start = os::elapsedTime(); | |
1155 | |
1156 checkpointRootsFinalWork(); | |
1157 | |
1158 double mark_work_end = os::elapsedTime(); | |
1159 | |
1160 weakRefsWork(clear_all_soft_refs); | |
1161 | |
1162 if (has_overflown()) { | |
1163 // Oops. We overflowed. Restart concurrent marking. | |
1164 _restart_for_overflow = true; | |
1165 // Clear the flag. We do not need it any more. | |
1166 clear_has_overflown(); | |
1167 if (G1TraceMarkStackOverflow) | |
1168 gclog_or_tty->print_cr("\nRemark led to restart for overflow."); | |
1169 } else { | |
2149 | 1170 SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); |
342 | 1171 // We're done with marking. |
1317
d4197f8d516a
6935821: G1: threads created during marking do not active their SATB queues
tonyp
parents:
1314
diff
changeset
|
1172 // This is the end of the marking cycle, we're expected all |
d4197f8d516a
6935821: G1: threads created during marking do not active their SATB queues
tonyp
parents:
1314
diff
changeset
|
1173 // threads to have SATB queues with active set to true. |
2149 | 1174 satb_mq_set.set_active_all_threads(false, /* new active value */ |
1175 true /* expected_active */); | |
811 | 1176 |
1177 if (VerifyDuringGC) { | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1178 HandleMark hm; // handle scope |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1179 gclog_or_tty->print(" VerifyDuringGC:(after)"); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1180 Universe::heap()->prepare_for_verify(); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1181 Universe::heap()->verify(/* allow_dirty */ true, |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1182 /* silent */ false, |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1183 /* use_prev_marking */ false); |
811 | 1184 } |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1185 assert(!restart_for_overflow(), "sanity"); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1186 } |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1187 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1188 // Reset the marking state if marking completed |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1189 if (!restart_for_overflow()) { |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1190 set_non_marking_state(); |
342 | 1191 } |
1192 | |
1193 #if VERIFY_OBJS_PROCESSED | |
1194 _scan_obj_cl.objs_processed = 0; | |
1195 ThreadLocalObjQueue::objs_enqueued = 0; | |
1196 #endif | |
1197 | |
1198 // Statistics | |
1199 double now = os::elapsedTime(); | |
1200 _remark_mark_times.add((mark_work_end - start) * 1000.0); | |
1201 _remark_weak_ref_times.add((now - mark_work_end) * 1000.0); | |
1202 _remark_times.add((now - start) * 1000.0); | |
1203 | |
1204 g1p->record_concurrent_mark_remark_end(); | |
1205 } | |
1206 | |
1207 #define CARD_BM_TEST_MODE 0 | |
1208 | |
1209 class CalcLiveObjectsClosure: public HeapRegionClosure { | |
1210 | |
1211 CMBitMapRO* _bm; | |
1212 ConcurrentMark* _cm; | |
1213 bool _changed; | |
1214 bool _yield; | |
1215 size_t _words_done; | |
1216 size_t _tot_live; | |
1217 size_t _tot_used; | |
1218 size_t _regions_done; | |
1219 double _start_vtime_sec; | |
1220 | |
1221 BitMap* _region_bm; | |
1222 BitMap* _card_bm; | |
1223 intptr_t _bottom_card_num; | |
1224 bool _final; | |
1225 | |
1226 void mark_card_num_range(intptr_t start_card_num, intptr_t last_card_num) { | |
1227 for (intptr_t i = start_card_num; i <= last_card_num; i++) { | |
1228 #if CARD_BM_TEST_MODE | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
1229 guarantee(_card_bm->at(i - _bottom_card_num), "Should already be set."); |
342 | 1230 #else |
1231 _card_bm->par_at_put(i - _bottom_card_num, 1); | |
1232 #endif | |
1233 } | |
1234 } | |
1235 | |
1236 public: | |
1237 CalcLiveObjectsClosure(bool final, | |
1238 CMBitMapRO *bm, ConcurrentMark *cm, | |
936 | 1239 BitMap* region_bm, BitMap* card_bm) : |
342 | 1240 _bm(bm), _cm(cm), _changed(false), _yield(true), |
1241 _words_done(0), _tot_live(0), _tot_used(0), | |
936 | 1242 _region_bm(region_bm), _card_bm(card_bm),_final(final), |
342 | 1243 _regions_done(0), _start_vtime_sec(0.0) |
1244 { | |
1245 _bottom_card_num = | |
1246 intptr_t(uintptr_t(G1CollectedHeap::heap()->reserved_region().start()) >> | |
1247 CardTableModRefBS::card_shift); | |
1248 } | |
1249 | |
829 | 1250 // It takes a region that's not empty (i.e., it has at least one |
1251 // live object in it and sets its corresponding bit on the region | |
1252 // bitmap to 1. If the region is "starts humongous" it will also set | |
1253 // to 1 the bits on the region bitmap that correspond to its | |
1254 // associated "continues humongous" regions. | |
1255 void set_bit_for_region(HeapRegion* hr) { | |
1256 assert(!hr->continuesHumongous(), "should have filtered those out"); | |
1257 | |
1258 size_t index = hr->hrs_index(); | |
1259 if (!hr->startsHumongous()) { | |
1260 // Normal (non-humongous) case: just set the bit. | |
1261 _region_bm->par_at_put((BitMap::idx_t) index, true); | |
1262 } else { | |
1263 // Starts humongous case: calculate how many regions are part of | |
1264 // this humongous region and then set the bit range. It might | |
1265 // have been a bit more efficient to look at the object that | |
1266 // spans these humongous regions to calculate their number from | |
1267 // the object's size. However, it's a good idea to calculate | |
1268 // this based on the metadata itself, and not the region | |
1269 // contents, so that this code is not aware of what goes into | |
1270 // the humongous regions (in case this changes in the future). | |
1271 G1CollectedHeap* g1h = G1CollectedHeap::heap(); | |
1272 size_t end_index = index + 1; | |
831 | 1273 while (end_index < g1h->n_regions()) { |
1274 HeapRegion* chr = g1h->region_at(end_index); | |
829 | 1275 if (!chr->continuesHumongous()) { |
1276 break; | |
1277 } | |
1278 end_index += 1; | |
1279 } | |
1280 _region_bm->par_at_put_range((BitMap::idx_t) index, | |
1281 (BitMap::idx_t) end_index, true); | |
1282 } | |
1283 } | |
1284 | |
342 | 1285 bool doHeapRegion(HeapRegion* hr) { |
1286 if (!_final && _regions_done == 0) | |
1287 _start_vtime_sec = os::elapsedVTime(); | |
1288 | |
639 | 1289 if (hr->continuesHumongous()) { |
829 | 1290 // We will ignore these here and process them when their |
1291 // associated "starts humongous" region is processed (see | |
1292 // set_bit_for_heap_region()). Note that we cannot rely on their | |
1293 // associated "starts humongous" region to have their bit set to | |
1294 // 1 since, due to the region chunking in the parallel region | |
1295 // iteration, a "continues humongous" region might be visited | |
1296 // before its associated "starts humongous". | |
639 | 1297 return false; |
1298 } | |
342 | 1299 |
1300 HeapWord* nextTop = hr->next_top_at_mark_start(); | |
1301 HeapWord* start = hr->top_at_conc_mark_count(); | |
1302 assert(hr->bottom() <= start && start <= hr->end() && | |
1303 hr->bottom() <= nextTop && nextTop <= hr->end() && | |
1304 start <= nextTop, | |
1305 "Preconditions."); | |
1306 // Otherwise, record the number of word's we'll examine. | |
1307 size_t words_done = (nextTop - start); | |
1308 // Find the first marked object at or after "start". | |
1309 start = _bm->getNextMarkedWordAddress(start, nextTop); | |
1310 size_t marked_bytes = 0; | |
1311 | |
1312 // Below, the term "card num" means the result of shifting an address | |
1313 // by the card shift -- address 0 corresponds to card number 0. One | |
1314 // must subtract the card num of the bottom of the heap to obtain a | |
1315 // card table index. | |
1316 // The first card num of the sequence of live cards currently being | |
1317 // constructed. -1 ==> no sequence. | |
1318 intptr_t start_card_num = -1; | |
1319 // The last card num of the sequence of live cards currently being | |
1320 // constructed. -1 ==> no sequence. | |
1321 intptr_t last_card_num = -1; | |
1322 | |
1323 while (start < nextTop) { | |
1324 if (_yield && _cm->do_yield_check()) { | |
1325 // We yielded. It might be for a full collection, in which case | |
1326 // all bets are off; terminate the traversal. | |
1327 if (_cm->has_aborted()) { | |
1328 _changed = false; | |
1329 return true; | |
1330 } else { | |
1331 // Otherwise, it might be a collection pause, and the region | |
1332 // we're looking at might be in the collection set. We'll | |
1333 // abandon this region. | |
1334 return false; | |
1335 } | |
1336 } | |
1337 oop obj = oop(start); | |
1338 int obj_sz = obj->size(); | |
1339 // The card num of the start of the current object. | |
1340 intptr_t obj_card_num = | |
1341 intptr_t(uintptr_t(start) >> CardTableModRefBS::card_shift); | |
1342 | |
1343 HeapWord* obj_last = start + obj_sz - 1; | |
1344 intptr_t obj_last_card_num = | |
1345 intptr_t(uintptr_t(obj_last) >> CardTableModRefBS::card_shift); | |
1346 | |
1347 if (obj_card_num != last_card_num) { | |
1348 if (start_card_num == -1) { | |
1349 assert(last_card_num == -1, "Both or neither."); | |
1350 start_card_num = obj_card_num; | |
1351 } else { | |
1352 assert(last_card_num != -1, "Both or neither."); | |
1353 assert(obj_card_num >= last_card_num, "Inv"); | |
1354 if ((obj_card_num - last_card_num) > 1) { | |
1355 // Mark the last run, and start a new one. | |
1356 mark_card_num_range(start_card_num, last_card_num); | |
1357 start_card_num = obj_card_num; | |
1358 } | |
1359 } | |
1360 #if CARD_BM_TEST_MODE | |
1361 /* | |
1362 gclog_or_tty->print_cr("Setting bits from %d/%d.", | |
1363 obj_card_num - _bottom_card_num, | |
1364 obj_last_card_num - _bottom_card_num); | |
1365 */ | |
1366 for (intptr_t j = obj_card_num; j <= obj_last_card_num; j++) { | |
1367 _card_bm->par_at_put(j - _bottom_card_num, 1); | |
1368 } | |
1369 #endif | |
1370 } | |
1371 // In any case, we set the last card num. | |
1372 last_card_num = obj_last_card_num; | |
1373 | |
1030
dfdaf65c3423
6858886: G1: guarantee(_next_marked_bytes <= used(),"invariant") at heapRegion.hpp:359
apetrusenko
parents:
1023
diff
changeset
|
1374 marked_bytes += (size_t)obj_sz * HeapWordSize; |
342 | 1375 // Find the next marked object after this one. |
1376 start = _bm->getNextMarkedWordAddress(start + 1, nextTop); | |
1377 _changed = true; | |
1378 } | |
1379 // Handle the last range, if any. | |
1380 if (start_card_num != -1) | |
1381 mark_card_num_range(start_card_num, last_card_num); | |
1382 if (_final) { | |
1383 // Mark the allocated-since-marking portion... | |
1384 HeapWord* tp = hr->top(); | |
1385 if (nextTop < tp) { | |
1386 start_card_num = | |
1387 intptr_t(uintptr_t(nextTop) >> CardTableModRefBS::card_shift); | |
1388 last_card_num = | |
1389 intptr_t(uintptr_t(tp) >> CardTableModRefBS::card_shift); | |
1390 mark_card_num_range(start_card_num, last_card_num); | |
1391 // This definitely means the region has live objects. | |
829 | 1392 set_bit_for_region(hr); |
342 | 1393 } |
1394 } | |
1395 | |
1396 hr->add_to_marked_bytes(marked_bytes); | |
1397 // Update the live region bitmap. | |
1398 if (marked_bytes > 0) { | |
829 | 1399 set_bit_for_region(hr); |
342 | 1400 } |
1401 hr->set_top_at_conc_mark_count(nextTop); | |
1402 _tot_live += hr->next_live_bytes(); | |
1403 _tot_used += hr->used(); | |
1404 _words_done = words_done; | |
1405 | |
1406 if (!_final) { | |
1407 ++_regions_done; | |
1408 if (_regions_done % 10 == 0) { | |
1409 double end_vtime_sec = os::elapsedVTime(); | |
1410 double elapsed_vtime_sec = end_vtime_sec - _start_vtime_sec; | |
1411 if (elapsed_vtime_sec > (10.0 / 1000.0)) { | |
1412 jlong sleep_time_ms = | |
1413 (jlong) (elapsed_vtime_sec * _cm->cleanup_sleep_factor() * 1000.0); | |
1414 os::sleep(Thread::current(), sleep_time_ms, false); | |
1415 _start_vtime_sec = end_vtime_sec; | |
1416 } | |
1417 } | |
1418 } | |
1419 | |
1420 return false; | |
1421 } | |
1422 | |
1423 bool changed() { return _changed; } | |
1424 void reset() { _changed = false; _words_done = 0; } | |
1425 void no_yield() { _yield = false; } | |
1426 size_t words_done() { return _words_done; } | |
1427 size_t tot_live() { return _tot_live; } | |
1428 size_t tot_used() { return _tot_used; } | |
1429 }; | |
1430 | |
1431 | |
1432 void ConcurrentMark::calcDesiredRegions() { | |
1433 _region_bm.clear(); | |
1434 _card_bm.clear(); | |
1435 CalcLiveObjectsClosure calccl(false /*final*/, | |
1436 nextMarkBitMap(), this, | |
936 | 1437 &_region_bm, &_card_bm); |
342 | 1438 G1CollectedHeap *g1h = G1CollectedHeap::heap(); |
1439 g1h->heap_region_iterate(&calccl); | |
1440 | |
1441 do { | |
1442 calccl.reset(); | |
1443 g1h->heap_region_iterate(&calccl); | |
1444 } while (calccl.changed()); | |
1445 } | |
1446 | |
1447 class G1ParFinalCountTask: public AbstractGangTask { | |
1448 protected: | |
1449 G1CollectedHeap* _g1h; | |
1450 CMBitMap* _bm; | |
1451 size_t _n_workers; | |
1452 size_t *_live_bytes; | |
1453 size_t *_used_bytes; | |
1454 BitMap* _region_bm; | |
1455 BitMap* _card_bm; | |
1456 public: | |
1457 G1ParFinalCountTask(G1CollectedHeap* g1h, CMBitMap* bm, | |
1458 BitMap* region_bm, BitMap* card_bm) : | |
1459 AbstractGangTask("G1 final counting"), _g1h(g1h), | |
1460 _bm(bm), _region_bm(region_bm), _card_bm(card_bm) | |
1461 { | |
1462 if (ParallelGCThreads > 0) | |
1463 _n_workers = _g1h->workers()->total_workers(); | |
1464 else | |
1465 _n_workers = 1; | |
1466 _live_bytes = NEW_C_HEAP_ARRAY(size_t, _n_workers); | |
1467 _used_bytes = NEW_C_HEAP_ARRAY(size_t, _n_workers); | |
1468 } | |
1469 | |
1470 ~G1ParFinalCountTask() { | |
1471 FREE_C_HEAP_ARRAY(size_t, _live_bytes); | |
1472 FREE_C_HEAP_ARRAY(size_t, _used_bytes); | |
1473 } | |
1474 | |
1475 void work(int i) { | |
1476 CalcLiveObjectsClosure calccl(true /*final*/, | |
1477 _bm, _g1h->concurrent_mark(), | |
936 | 1478 _region_bm, _card_bm); |
342 | 1479 calccl.no_yield(); |
1833
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1719
diff
changeset
|
1480 if (G1CollectedHeap::use_parallel_gc_threads()) { |
355 | 1481 _g1h->heap_region_par_iterate_chunked(&calccl, i, |
1482 HeapRegion::FinalCountClaimValue); | |
342 | 1483 } else { |
1484 _g1h->heap_region_iterate(&calccl); | |
1485 } | |
1486 assert(calccl.complete(), "Shouldn't have yielded!"); | |
1487 | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
1488 assert((size_t) i < _n_workers, "invariant"); |
342 | 1489 _live_bytes[i] = calccl.tot_live(); |
1490 _used_bytes[i] = calccl.tot_used(); | |
1491 } | |
1492 size_t live_bytes() { | |
1493 size_t live_bytes = 0; | |
1494 for (size_t i = 0; i < _n_workers; ++i) | |
1495 live_bytes += _live_bytes[i]; | |
1496 return live_bytes; | |
1497 } | |
1498 size_t used_bytes() { | |
1499 size_t used_bytes = 0; | |
1500 for (size_t i = 0; i < _n_workers; ++i) | |
1501 used_bytes += _used_bytes[i]; | |
1502 return used_bytes; | |
1503 } | |
1504 }; | |
1505 | |
1506 class G1ParNoteEndTask; | |
1507 | |
1508 class G1NoteEndOfConcMarkClosure : public HeapRegionClosure { | |
1509 G1CollectedHeap* _g1; | |
1510 int _worker_num; | |
1511 size_t _max_live_bytes; | |
1512 size_t _regions_claimed; | |
1513 size_t _freed_bytes; | |
2173 | 1514 FreeRegionList* _local_cleanup_list; |
1515 HumongousRegionSet* _humongous_proxy_set; | |
1516 HRRSCleanupTask* _hrrs_cleanup_task; | |
342 | 1517 double _claimed_region_time; |
1518 double _max_region_time; | |
1519 | |
1520 public: | |
1521 G1NoteEndOfConcMarkClosure(G1CollectedHeap* g1, | |
2173 | 1522 int worker_num, |
1523 FreeRegionList* local_cleanup_list, | |
1524 HumongousRegionSet* humongous_proxy_set, | |
1525 HRRSCleanupTask* hrrs_cleanup_task); | |
342 | 1526 size_t freed_bytes() { return _freed_bytes; } |
1527 | |
1528 bool doHeapRegion(HeapRegion *r); | |
1529 | |
1530 size_t max_live_bytes() { return _max_live_bytes; } | |
1531 size_t regions_claimed() { return _regions_claimed; } | |
1532 double claimed_region_time_sec() { return _claimed_region_time; } | |
1533 double max_region_time_sec() { return _max_region_time; } | |
1534 }; | |
1535 | |
1536 class G1ParNoteEndTask: public AbstractGangTask { | |
1537 friend class G1NoteEndOfConcMarkClosure; | |
2152 | 1538 |
342 | 1539 protected: |
1540 G1CollectedHeap* _g1h; | |
1541 size_t _max_live_bytes; | |
1542 size_t _freed_bytes; | |
2152 | 1543 FreeRegionList* _cleanup_list; |
1544 | |
342 | 1545 public: |
1546 G1ParNoteEndTask(G1CollectedHeap* g1h, | |
2152 | 1547 FreeRegionList* cleanup_list) : |
342 | 1548 AbstractGangTask("G1 note end"), _g1h(g1h), |
2152 | 1549 _max_live_bytes(0), _freed_bytes(0), _cleanup_list(cleanup_list) { } |
342 | 1550 |
1551 void work(int i) { | |
1552 double start = os::elapsedTime(); | |
2173 | 1553 FreeRegionList local_cleanup_list("Local Cleanup List"); |
1554 HumongousRegionSet humongous_proxy_set("Local Cleanup Humongous Proxy Set"); | |
1555 HRRSCleanupTask hrrs_cleanup_task; | |
1556 G1NoteEndOfConcMarkClosure g1_note_end(_g1h, i, &local_cleanup_list, | |
1557 &humongous_proxy_set, | |
1558 &hrrs_cleanup_task); | |
1833
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1719
diff
changeset
|
1559 if (G1CollectedHeap::use_parallel_gc_threads()) { |
355 | 1560 _g1h->heap_region_par_iterate_chunked(&g1_note_end, i, |
1561 HeapRegion::NoteEndClaimValue); | |
342 | 1562 } else { |
1563 _g1h->heap_region_iterate(&g1_note_end); | |
1564 } | |
1565 assert(g1_note_end.complete(), "Shouldn't have yielded!"); | |
1566 | |
2152 | 1567 // Now update the lists |
1568 _g1h->update_sets_after_freeing_regions(g1_note_end.freed_bytes(), | |
1569 NULL /* free_list */, | |
2173 | 1570 &humongous_proxy_set, |
2152 | 1571 true /* par */); |
342 | 1572 { |
1573 MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag); | |
1574 _max_live_bytes += g1_note_end.max_live_bytes(); | |
1575 _freed_bytes += g1_note_end.freed_bytes(); | |
2152 | 1576 |
2173 | 1577 _cleanup_list->add_as_tail(&local_cleanup_list); |
1578 assert(local_cleanup_list.is_empty(), "post-condition"); | |
1579 | |
1580 HeapRegionRemSet::finish_cleanup_task(&hrrs_cleanup_task); | |
342 | 1581 } |
1582 double end = os::elapsedTime(); | |
1583 if (G1PrintParCleanupStats) { | |
1584 gclog_or_tty->print(" Worker thread %d [%8.3f..%8.3f = %8.3f ms] " | |
1585 "claimed %d regions (tot = %8.3f ms, max = %8.3f ms).\n", | |
1586 i, start, end, (end-start)*1000.0, | |
1587 g1_note_end.regions_claimed(), | |
1588 g1_note_end.claimed_region_time_sec()*1000.0, | |
1589 g1_note_end.max_region_time_sec()*1000.0); | |
1590 } | |
1591 } | |
1592 size_t max_live_bytes() { return _max_live_bytes; } | |
1593 size_t freed_bytes() { return _freed_bytes; } | |
1594 }; | |
1595 | |
1596 class G1ParScrubRemSetTask: public AbstractGangTask { | |
1597 protected: | |
1598 G1RemSet* _g1rs; | |
1599 BitMap* _region_bm; | |
1600 BitMap* _card_bm; | |
1601 public: | |
1602 G1ParScrubRemSetTask(G1CollectedHeap* g1h, | |
1603 BitMap* region_bm, BitMap* card_bm) : | |
1604 AbstractGangTask("G1 ScrubRS"), _g1rs(g1h->g1_rem_set()), | |
1605 _region_bm(region_bm), _card_bm(card_bm) | |
1606 {} | |
1607 | |
1608 void work(int i) { | |
1833
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1719
diff
changeset
|
1609 if (G1CollectedHeap::use_parallel_gc_threads()) { |
355 | 1610 _g1rs->scrub_par(_region_bm, _card_bm, i, |
1611 HeapRegion::ScrubRemSetClaimValue); | |
342 | 1612 } else { |
1613 _g1rs->scrub(_region_bm, _card_bm); | |
1614 } | |
1615 } | |
1616 | |
1617 }; | |
1618 | |
1619 G1NoteEndOfConcMarkClosure:: | |
1620 G1NoteEndOfConcMarkClosure(G1CollectedHeap* g1, | |
2173 | 1621 int worker_num, |
1622 FreeRegionList* local_cleanup_list, | |
1623 HumongousRegionSet* humongous_proxy_set, | |
1624 HRRSCleanupTask* hrrs_cleanup_task) | |
342 | 1625 : _g1(g1), _worker_num(worker_num), |
1626 _max_live_bytes(0), _regions_claimed(0), | |
2152 | 1627 _freed_bytes(0), |
342 | 1628 _claimed_region_time(0.0), _max_region_time(0.0), |
2173 | 1629 _local_cleanup_list(local_cleanup_list), |
1630 _humongous_proxy_set(humongous_proxy_set), | |
1631 _hrrs_cleanup_task(hrrs_cleanup_task) { } | |
2152 | 1632 |
1633 bool G1NoteEndOfConcMarkClosure::doHeapRegion(HeapRegion *hr) { | |
342 | 1634 // We use a claim value of zero here because all regions |
1635 // were claimed with value 1 in the FinalCount task. | |
2152 | 1636 hr->reset_gc_time_stamp(); |
1637 if (!hr->continuesHumongous()) { | |
342 | 1638 double start = os::elapsedTime(); |
1639 _regions_claimed++; | |
2152 | 1640 hr->note_end_of_marking(); |
1641 _max_live_bytes += hr->max_live_bytes(); | |
2173 | 1642 _g1->free_region_if_empty(hr, |
1643 &_freed_bytes, | |
1644 _local_cleanup_list, | |
1645 _humongous_proxy_set, | |
1646 _hrrs_cleanup_task, | |
1647 true /* par */); | |
342 | 1648 double region_time = (os::elapsedTime() - start); |
1649 _claimed_region_time += region_time; | |
1650 if (region_time > _max_region_time) _max_region_time = region_time; | |
1651 } | |
1652 return false; | |
1653 } | |
1654 | |
1655 void ConcurrentMark::cleanup() { | |
1656 // world is stopped at this checkpoint | |
1657 assert(SafepointSynchronize::is_at_safepoint(), | |
1658 "world should be stopped"); | |
1659 G1CollectedHeap* g1h = G1CollectedHeap::heap(); | |
1660 | |
1661 // If a full collection has happened, we shouldn't do this. | |
1662 if (has_aborted()) { | |
1663 g1h->set_marking_complete(); // So bitmap clearing isn't confused | |
1664 return; | |
1665 } | |
1666 | |
2152 | 1667 g1h->verify_region_sets_optional(); |
1668 | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1669 if (VerifyDuringGC) { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1670 HandleMark hm; // handle scope |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1671 gclog_or_tty->print(" VerifyDuringGC:(before)"); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1672 Universe::heap()->prepare_for_verify(); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1673 Universe::verify(/* allow dirty */ true, |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1674 /* silent */ false, |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1675 /* prev marking */ true); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1676 } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1677 |
342 | 1678 G1CollectorPolicy* g1p = G1CollectedHeap::heap()->g1_policy(); |
1679 g1p->record_concurrent_mark_cleanup_start(); | |
1680 | |
1681 double start = os::elapsedTime(); | |
1682 | |
2173 | 1683 HeapRegionRemSet::reset_for_cleanup_tasks(); |
1684 | |
342 | 1685 // Do counting once more with the world stopped for good measure. |
1686 G1ParFinalCountTask g1_par_count_task(g1h, nextMarkBitMap(), | |
1687 &_region_bm, &_card_bm); | |
1833
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1719
diff
changeset
|
1688 if (G1CollectedHeap::use_parallel_gc_threads()) { |
355 | 1689 assert(g1h->check_heap_region_claim_values( |
1690 HeapRegion::InitialClaimValue), | |
1691 "sanity check"); | |
1692 | |
342 | 1693 int n_workers = g1h->workers()->total_workers(); |
1694 g1h->set_par_threads(n_workers); | |
1695 g1h->workers()->run_task(&g1_par_count_task); | |
1696 g1h->set_par_threads(0); | |
355 | 1697 |
1698 assert(g1h->check_heap_region_claim_values( | |
1699 HeapRegion::FinalCountClaimValue), | |
1700 "sanity check"); | |
342 | 1701 } else { |
1702 g1_par_count_task.work(0); | |
1703 } | |
1704 | |
1705 size_t known_garbage_bytes = | |
1706 g1_par_count_task.used_bytes() - g1_par_count_task.live_bytes(); | |
1707 #if 0 | |
1708 gclog_or_tty->print_cr("used %1.2lf, live %1.2lf, garbage %1.2lf", | |
1709 (double) g1_par_count_task.used_bytes() / (double) (1024 * 1024), | |
1710 (double) g1_par_count_task.live_bytes() / (double) (1024 * 1024), | |
1711 (double) known_garbage_bytes / (double) (1024 * 1024)); | |
1712 #endif // 0 | |
1713 g1p->set_known_garbage_bytes(known_garbage_bytes); | |
1714 | |
1715 size_t start_used_bytes = g1h->used(); | |
1716 _at_least_one_mark_complete = true; | |
1717 g1h->set_marking_complete(); | |
1718 | |
1719 double count_end = os::elapsedTime(); | |
1720 double this_final_counting_time = (count_end - start); | |
1721 if (G1PrintParCleanupStats) { | |
1722 gclog_or_tty->print_cr("Cleanup:"); | |
1723 gclog_or_tty->print_cr(" Finalize counting: %8.3f ms", | |
1724 this_final_counting_time*1000.0); | |
1725 } | |
1726 _total_counting_time += this_final_counting_time; | |
1727 | |
2435
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
1728 if (G1PrintRegionLivenessInfo) { |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
1729 G1PrintRegionLivenessInfoClosure cl(gclog_or_tty, "Post-Marking"); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
1730 _g1h->heap_region_iterate(&cl); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
1731 } |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
1732 |
342 | 1733 // Install newly created mark bitMap as "prev". |
1734 swapMarkBitMaps(); | |
1735 | |
1736 g1h->reset_gc_time_stamp(); | |
1737 | |
1738 // Note end of marking in all heap regions. | |
1739 double note_end_start = os::elapsedTime(); | |
2152 | 1740 G1ParNoteEndTask g1_par_note_end_task(g1h, &_cleanup_list); |
1833
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1719
diff
changeset
|
1741 if (G1CollectedHeap::use_parallel_gc_threads()) { |
342 | 1742 int n_workers = g1h->workers()->total_workers(); |
1743 g1h->set_par_threads(n_workers); | |
1744 g1h->workers()->run_task(&g1_par_note_end_task); | |
1745 g1h->set_par_threads(0); | |
355 | 1746 |
1747 assert(g1h->check_heap_region_claim_values(HeapRegion::NoteEndClaimValue), | |
1748 "sanity check"); | |
342 | 1749 } else { |
1750 g1_par_note_end_task.work(0); | |
1751 } | |
2152 | 1752 |
1753 if (!cleanup_list_is_empty()) { | |
1754 // The cleanup list is not empty, so we'll have to process it | |
1755 // concurrently. Notify anyone else that might be wanting free | |
1756 // regions that there will be more free regions coming soon. | |
1757 g1h->set_free_regions_coming(); | |
1758 } | |
342 | 1759 double note_end_end = os::elapsedTime(); |
1760 if (G1PrintParCleanupStats) { | |
1761 gclog_or_tty->print_cr(" note end of marking: %8.3f ms.", | |
1762 (note_end_end - note_end_start)*1000.0); | |
1763 } | |
1764 | |
355 | 1765 |
342 | 1766 // call below, since it affects the metric by which we sort the heap |
1767 // regions. | |
1768 if (G1ScrubRemSets) { | |
1769 double rs_scrub_start = os::elapsedTime(); | |
1770 G1ParScrubRemSetTask g1_par_scrub_rs_task(g1h, &_region_bm, &_card_bm); | |
1833
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1719
diff
changeset
|
1771 if (G1CollectedHeap::use_parallel_gc_threads()) { |
342 | 1772 int n_workers = g1h->workers()->total_workers(); |
1773 g1h->set_par_threads(n_workers); | |
1774 g1h->workers()->run_task(&g1_par_scrub_rs_task); | |
1775 g1h->set_par_threads(0); | |
355 | 1776 |
1777 assert(g1h->check_heap_region_claim_values( | |
1778 HeapRegion::ScrubRemSetClaimValue), | |
1779 "sanity check"); | |
342 | 1780 } else { |
1781 g1_par_scrub_rs_task.work(0); | |
1782 } | |
1783 | |
1784 double rs_scrub_end = os::elapsedTime(); | |
1785 double this_rs_scrub_time = (rs_scrub_end - rs_scrub_start); | |
1786 _total_rs_scrub_time += this_rs_scrub_time; | |
1787 } | |
1788 | |
1789 // this will also free any regions totally full of garbage objects, | |
1790 // and sort the regions. | |
1791 g1h->g1_policy()->record_concurrent_mark_cleanup_end( | |
1792 g1_par_note_end_task.freed_bytes(), | |
1793 g1_par_note_end_task.max_live_bytes()); | |
1794 | |
1795 // Statistics. | |
1796 double end = os::elapsedTime(); | |
1797 _cleanup_times.add((end - start) * 1000.0); | |
1798 | |
1799 // G1CollectedHeap::heap()->print(); | |
1800 // gclog_or_tty->print_cr("HEAP GC TIME STAMP : %d", | |
1801 // G1CollectedHeap::heap()->get_gc_time_stamp()); | |
1802 | |
1803 if (PrintGC || PrintGCDetails) { | |
1804 g1h->print_size_transition(gclog_or_tty, | |
1805 start_used_bytes, | |
1806 g1h->used(), | |
1807 g1h->capacity()); | |
1808 } | |
1809 | |
1810 size_t cleaned_up_bytes = start_used_bytes - g1h->used(); | |
1811 g1p->decrease_known_garbage_bytes(cleaned_up_bytes); | |
1812 | |
1813 // We need to make this be a "collection" so any collection pause that | |
1814 // races with it goes around and waits for completeCleanup to finish. | |
1815 g1h->increment_total_collections(); | |
1816 | |
751 | 1817 if (VerifyDuringGC) { |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1818 HandleMark hm; // handle scope |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1819 gclog_or_tty->print(" VerifyDuringGC:(after)"); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1820 Universe::heap()->prepare_for_verify(); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1821 Universe::verify(/* allow dirty */ true, |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1822 /* silent */ false, |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1823 /* prev marking */ true); |
342 | 1824 } |
2152 | 1825 |
1826 g1h->verify_region_sets_optional(); | |
342 | 1827 } |
1828 | |
1829 void ConcurrentMark::completeCleanup() { | |
1830 if (has_aborted()) return; | |
1831 | |
2152 | 1832 G1CollectedHeap* g1h = G1CollectedHeap::heap(); |
1833 | |
1834 _cleanup_list.verify_optional(); | |
2361 | 1835 FreeRegionList tmp_free_list("Tmp Free List"); |
2152 | 1836 |
1837 if (G1ConcRegionFreeingVerbose) { | |
1838 gclog_or_tty->print_cr("G1ConcRegionFreeing [complete cleanup] : " | |
1839 "cleanup list has "SIZE_FORMAT" entries", | |
1840 _cleanup_list.length()); | |
1841 } | |
1842 | |
1843 // Noone else should be accessing the _cleanup_list at this point, | |
1844 // so it's not necessary to take any locks | |
1845 while (!_cleanup_list.is_empty()) { | |
1846 HeapRegion* hr = _cleanup_list.remove_head(); | |
1847 assert(hr != NULL, "the list was not empty"); | |
1848 hr->rem_set()->clear(); | |
2361 | 1849 tmp_free_list.add_as_tail(hr); |
2152 | 1850 |
1851 // Instead of adding one region at a time to the secondary_free_list, | |
1852 // we accumulate them in the local list and move them a few at a | |
1853 // time. This also cuts down on the number of notify_all() calls | |
1854 // we do during this process. We'll also append the local list when | |
1855 // _cleanup_list is empty (which means we just removed the last | |
1856 // region from the _cleanup_list). | |
2361 | 1857 if ((tmp_free_list.length() % G1SecondaryFreeListAppendLength == 0) || |
2152 | 1858 _cleanup_list.is_empty()) { |
1859 if (G1ConcRegionFreeingVerbose) { | |
1860 gclog_or_tty->print_cr("G1ConcRegionFreeing [complete cleanup] : " | |
1861 "appending "SIZE_FORMAT" entries to the " | |
1862 "secondary_free_list, clean list still has " | |
1863 SIZE_FORMAT" entries", | |
2361 | 1864 tmp_free_list.length(), |
2152 | 1865 _cleanup_list.length()); |
342 | 1866 } |
2152 | 1867 |
1868 { | |
1869 MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag); | |
2361 | 1870 g1h->secondary_free_list_add_as_tail(&tmp_free_list); |
2152 | 1871 SecondaryFreeList_lock->notify_all(); |
1872 } | |
1873 | |
1874 if (G1StressConcRegionFreeing) { | |
1875 for (uintx i = 0; i < G1StressConcRegionFreeingDelayMillis; ++i) { | |
1876 os::sleep(Thread::current(), (jlong) 1, false); | |
1877 } | |
1878 } | |
342 | 1879 } |
1880 } | |
2361 | 1881 assert(tmp_free_list.is_empty(), "post-condition"); |
342 | 1882 } |
1883 | |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1884 // Support closures for reference procssing in G1 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1885 |
2037
b03260081e9b
7006113: G1: Initialize ReferenceProcessor::_is_alive_non_header field
johnc
parents:
1974
diff
changeset
|
1886 bool G1CMIsAliveClosure::do_object_b(oop obj) { |
b03260081e9b
7006113: G1: Initialize ReferenceProcessor::_is_alive_non_header field
johnc
parents:
1974
diff
changeset
|
1887 HeapWord* addr = (HeapWord*)obj; |
b03260081e9b
7006113: G1: Initialize ReferenceProcessor::_is_alive_non_header field
johnc
parents:
1974
diff
changeset
|
1888 return addr != NULL && |
b03260081e9b
7006113: G1: Initialize ReferenceProcessor::_is_alive_non_header field
johnc
parents:
1974
diff
changeset
|
1889 (!_g1->is_in_g1_reserved(addr) || !_g1->is_obj_ill(obj)); |
b03260081e9b
7006113: G1: Initialize ReferenceProcessor::_is_alive_non_header field
johnc
parents:
1974
diff
changeset
|
1890 } |
342 | 1891 |
1892 class G1CMKeepAliveClosure: public OopClosure { | |
1893 G1CollectedHeap* _g1; | |
1894 ConcurrentMark* _cm; | |
1895 CMBitMap* _bitMap; | |
1896 public: | |
1897 G1CMKeepAliveClosure(G1CollectedHeap* g1, ConcurrentMark* cm, | |
1898 CMBitMap* bitMap) : | |
1899 _g1(g1), _cm(cm), | |
1900 _bitMap(bitMap) {} | |
1901 | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1902 virtual void do_oop(narrowOop* p) { do_oop_work(p); } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1903 virtual void do_oop( oop* p) { do_oop_work(p); } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1904 |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
1905 template <class T> void do_oop_work(T* p) { |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1906 oop obj = oopDesc::load_decode_heap_oop(p); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1907 HeapWord* addr = (HeapWord*)obj; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1908 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1909 if (_cm->verbose_high()) |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1910 gclog_or_tty->print_cr("\t[0] we're looking at location " |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1911 "*"PTR_FORMAT" = "PTR_FORMAT, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1912 p, (void*) obj); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1913 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1914 if (_g1->is_in_g1_reserved(addr) && _g1->is_obj_ill(obj)) { |
342 | 1915 _bitMap->mark(addr); |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1916 _cm->mark_stack_push(obj); |
342 | 1917 } |
1918 } | |
1919 }; | |
1920 | |
1921 class G1CMDrainMarkingStackClosure: public VoidClosure { | |
1922 CMMarkStack* _markStack; | |
1923 CMBitMap* _bitMap; | |
1924 G1CMKeepAliveClosure* _oopClosure; | |
1925 public: | |
1926 G1CMDrainMarkingStackClosure(CMBitMap* bitMap, CMMarkStack* markStack, | |
1927 G1CMKeepAliveClosure* oopClosure) : | |
1928 _bitMap(bitMap), | |
1929 _markStack(markStack), | |
1930 _oopClosure(oopClosure) | |
1931 {} | |
1932 | |
1933 void do_void() { | |
1934 _markStack->drain((OopClosure*)_oopClosure, _bitMap, false); | |
1935 } | |
1936 }; | |
1937 | |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1938 // 'Keep Alive' closure used by parallel reference processing. |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1939 // An instance of this closure is used in the parallel reference processing |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1940 // code rather than an instance of G1CMKeepAliveClosure. We could have used |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1941 // the G1CMKeepAliveClosure as it is MT-safe. Also reference objects are |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1942 // placed on to discovered ref lists once so we can mark and push with no |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1943 // need to check whether the object has already been marked. Using the |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1944 // G1CMKeepAliveClosure would mean, however, having all the worker threads |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1945 // operating on the global mark stack. This means that an individual |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1946 // worker would be doing lock-free pushes while it processes its own |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1947 // discovered ref list followed by drain call. If the discovered ref lists |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1948 // are unbalanced then this could cause interference with the other |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1949 // workers. Using a CMTask (and its embedded local data structures) |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1950 // avoids that potential interference. |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1951 class G1CMParKeepAliveAndDrainClosure: public OopClosure { |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1952 ConcurrentMark* _cm; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1953 CMTask* _task; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1954 CMBitMap* _bitMap; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1955 int _ref_counter_limit; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1956 int _ref_counter; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1957 public: |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1958 G1CMParKeepAliveAndDrainClosure(ConcurrentMark* cm, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1959 CMTask* task, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1960 CMBitMap* bitMap) : |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1961 _cm(cm), _task(task), _bitMap(bitMap), |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1962 _ref_counter_limit(G1RefProcDrainInterval) |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1963 { |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1964 assert(_ref_counter_limit > 0, "sanity"); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1965 _ref_counter = _ref_counter_limit; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1966 } |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1967 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1968 virtual void do_oop(narrowOop* p) { do_oop_work(p); } |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1969 virtual void do_oop( oop* p) { do_oop_work(p); } |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1970 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1971 template <class T> void do_oop_work(T* p) { |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1972 if (!_cm->has_overflown()) { |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1973 oop obj = oopDesc::load_decode_heap_oop(p); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1974 if (_cm->verbose_high()) |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1975 gclog_or_tty->print_cr("\t[%d] we're looking at location " |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1976 "*"PTR_FORMAT" = "PTR_FORMAT, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1977 _task->task_id(), p, (void*) obj); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1978 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1979 _task->deal_with_reference(obj); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1980 _ref_counter--; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1981 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1982 if (_ref_counter == 0) { |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1983 // We have dealt with _ref_counter_limit references, pushing them and objects |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1984 // reachable from them on to the local stack (and possibly the global stack). |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1985 // Call do_marking_step() to process these entries. We call the routine in a |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1986 // loop, which we'll exit if there's nothing more to do (i.e. we're done |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1987 // with the entries that we've pushed as a result of the deal_with_reference |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1988 // calls above) or we overflow. |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1989 // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() flag |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1990 // while there may still be some work to do. (See the comment at the |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1991 // beginning of CMTask::do_marking_step() for those conditions - one of which |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1992 // is reaching the specified time target.) It is only when |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1993 // CMTask::do_marking_step() returns without setting the has_aborted() flag |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1994 // that the marking has completed. |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1995 do { |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1996 double mark_step_duration_ms = G1ConcMarkStepDurationMillis; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1997 _task->do_marking_step(mark_step_duration_ms, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1998 false /* do_stealing */, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
1999 false /* do_termination */); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2000 } while (_task->has_aborted() && !_cm->has_overflown()); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2001 _ref_counter = _ref_counter_limit; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2002 } |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2003 } else { |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2004 if (_cm->verbose_high()) |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2005 gclog_or_tty->print_cr("\t[%d] CM Overflow", _task->task_id()); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2006 } |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2007 } |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2008 }; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2009 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2010 class G1CMParDrainMarkingStackClosure: public VoidClosure { |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2011 ConcurrentMark* _cm; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2012 CMTask* _task; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2013 public: |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2014 G1CMParDrainMarkingStackClosure(ConcurrentMark* cm, CMTask* task) : |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2015 _cm(cm), _task(task) |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2016 {} |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2017 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2018 void do_void() { |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2019 do { |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2020 if (_cm->verbose_high()) |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2021 gclog_or_tty->print_cr("\t[%d] Drain: Calling do marking_step", _task->task_id()); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2022 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2023 // We call CMTask::do_marking_step() to completely drain the local and |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2024 // global marking stacks. The routine is called in a loop, which we'll |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2025 // exit if there's nothing more to do (i.e. we'completely drained the |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2026 // entries that were pushed as a result of applying the |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2027 // G1CMParKeepAliveAndDrainClosure to the entries on the discovered ref |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2028 // lists above) or we overflow the global marking stack. |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2029 // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() flag |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2030 // while there may still be some work to do. (See the comment at the |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2031 // beginning of CMTask::do_marking_step() for those conditions - one of which |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2032 // is reaching the specified time target.) It is only when |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2033 // CMTask::do_marking_step() returns without setting the has_aborted() flag |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2034 // that the marking has completed. |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2035 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2036 _task->do_marking_step(1000000000.0 /* something very large */, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2037 true /* do_stealing */, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2038 true /* do_termination */); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2039 } while (_task->has_aborted() && !_cm->has_overflown()); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2040 } |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2041 }; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2042 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2043 // Implementation of AbstractRefProcTaskExecutor for G1 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2044 class G1RefProcTaskExecutor: public AbstractRefProcTaskExecutor { |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2045 private: |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2046 G1CollectedHeap* _g1h; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2047 ConcurrentMark* _cm; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2048 CMBitMap* _bitmap; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2049 WorkGang* _workers; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2050 int _active_workers; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2051 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2052 public: |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2053 G1RefProcTaskExecutor(G1CollectedHeap* g1h, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2054 ConcurrentMark* cm, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2055 CMBitMap* bitmap, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2056 WorkGang* workers, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2057 int n_workers) : |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2058 _g1h(g1h), _cm(cm), _bitmap(bitmap), |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2059 _workers(workers), _active_workers(n_workers) |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2060 { } |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2061 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2062 // Executes the given task using concurrent marking worker threads. |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2063 virtual void execute(ProcessTask& task); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2064 virtual void execute(EnqueueTask& task); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2065 }; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2066 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2067 class G1RefProcTaskProxy: public AbstractGangTask { |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2068 typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2069 ProcessTask& _proc_task; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2070 G1CollectedHeap* _g1h; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2071 ConcurrentMark* _cm; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2072 CMBitMap* _bitmap; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2073 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2074 public: |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2075 G1RefProcTaskProxy(ProcessTask& proc_task, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2076 G1CollectedHeap* g1h, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2077 ConcurrentMark* cm, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2078 CMBitMap* bitmap) : |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2079 AbstractGangTask("Process reference objects in parallel"), |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2080 _proc_task(proc_task), _g1h(g1h), _cm(cm), _bitmap(bitmap) |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2081 {} |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2082 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2083 virtual void work(int i) { |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2084 CMTask* marking_task = _cm->task(i); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2085 G1CMIsAliveClosure g1_is_alive(_g1h); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2086 G1CMParKeepAliveAndDrainClosure g1_par_keep_alive(_cm, marking_task, _bitmap); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2087 G1CMParDrainMarkingStackClosure g1_par_drain(_cm, marking_task); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2088 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2089 _proc_task.work(i, g1_is_alive, g1_par_keep_alive, g1_par_drain); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2090 } |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2091 }; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2092 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2093 void G1RefProcTaskExecutor::execute(ProcessTask& proc_task) { |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2094 assert(_workers != NULL, "Need parallel worker threads."); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2095 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2096 G1RefProcTaskProxy proc_task_proxy(proc_task, _g1h, _cm, _bitmap); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2097 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2098 // We need to reset the phase for each task execution so that |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2099 // the termination protocol of CMTask::do_marking_step works. |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2100 _cm->set_phase(_active_workers, false /* concurrent */); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2101 _g1h->set_par_threads(_active_workers); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2102 _workers->run_task(&proc_task_proxy); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2103 _g1h->set_par_threads(0); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2104 } |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2105 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2106 class G1RefEnqueueTaskProxy: public AbstractGangTask { |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2107 typedef AbstractRefProcTaskExecutor::EnqueueTask EnqueueTask; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2108 EnqueueTask& _enq_task; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2109 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2110 public: |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2111 G1RefEnqueueTaskProxy(EnqueueTask& enq_task) : |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2112 AbstractGangTask("Enqueue reference objects in parallel"), |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2113 _enq_task(enq_task) |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2114 { } |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2115 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2116 virtual void work(int i) { |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2117 _enq_task.work(i); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2118 } |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2119 }; |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2120 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2121 void G1RefProcTaskExecutor::execute(EnqueueTask& enq_task) { |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2122 assert(_workers != NULL, "Need parallel worker threads."); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2123 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2124 G1RefEnqueueTaskProxy enq_task_proxy(enq_task); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2125 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2126 _g1h->set_par_threads(_active_workers); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2127 _workers->run_task(&enq_task_proxy); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2128 _g1h->set_par_threads(0); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2129 } |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2130 |
342 | 2131 void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) { |
2132 ResourceMark rm; | |
2133 HandleMark hm; | |
453
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
355
diff
changeset
|
2134 G1CollectedHeap* g1h = G1CollectedHeap::heap(); |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
355
diff
changeset
|
2135 ReferenceProcessor* rp = g1h->ref_processor(); |
342 | 2136 |
1974
fd1d227ef1b9
6983204: G1: Nightly test nsk/regression/b4958615 failing with +ExplicitGCInvokesConcurrent
johnc
parents:
1972
diff
changeset
|
2137 // See the comment in G1CollectedHeap::ref_processing_init() |
fd1d227ef1b9
6983204: G1: Nightly test nsk/regression/b4958615 failing with +ExplicitGCInvokesConcurrent
johnc
parents:
1972
diff
changeset
|
2138 // about how reference processing currently works in G1. |
fd1d227ef1b9
6983204: G1: Nightly test nsk/regression/b4958615 failing with +ExplicitGCInvokesConcurrent
johnc
parents:
1972
diff
changeset
|
2139 |
342 | 2140 // Process weak references. |
457
27a80744a83b
6778647: snap(), snap_policy() should be renamed setup(), setup_policy()
ysr
parents:
453
diff
changeset
|
2141 rp->setup_policy(clear_all_soft_refs); |
342 | 2142 assert(_markStack.isEmpty(), "mark stack should be empty"); |
2143 | |
2037
b03260081e9b
7006113: G1: Initialize ReferenceProcessor::_is_alive_non_header field
johnc
parents:
1974
diff
changeset
|
2144 G1CMIsAliveClosure g1_is_alive(g1h); |
b03260081e9b
7006113: G1: Initialize ReferenceProcessor::_is_alive_non_header field
johnc
parents:
1974
diff
changeset
|
2145 G1CMKeepAliveClosure g1_keep_alive(g1h, this, nextMarkBitMap()); |
342 | 2146 G1CMDrainMarkingStackClosure |
2037
b03260081e9b
7006113: G1: Initialize ReferenceProcessor::_is_alive_non_header field
johnc
parents:
1974
diff
changeset
|
2147 g1_drain_mark_stack(nextMarkBitMap(), &_markStack, &g1_keep_alive); |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2148 // We use the work gang from the G1CollectedHeap and we utilize all |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2149 // the worker threads. |
2369
92da084fefc9
6668573: CMS: reference processing crash if ParallelCMSThreads > ParallelGCThreads
ysr
parents:
2361
diff
changeset
|
2150 int active_workers = g1h->workers() ? g1h->workers()->total_workers() : 1; |
92da084fefc9
6668573: CMS: reference processing crash if ParallelCMSThreads > ParallelGCThreads
ysr
parents:
2361
diff
changeset
|
2151 active_workers = MAX2(MIN2(active_workers, (int)_max_task_num), 1); |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2152 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2153 G1RefProcTaskExecutor par_task_executor(g1h, this, nextMarkBitMap(), |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2154 g1h->workers(), active_workers); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2155 |
2369
92da084fefc9
6668573: CMS: reference processing crash if ParallelCMSThreads > ParallelGCThreads
ysr
parents:
2361
diff
changeset
|
2156 |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2157 if (rp->processing_is_mt()) { |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2158 // Set the degree of MT here. If the discovery is done MT, there |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2159 // may have been a different number of threads doing the discovery |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2160 // and a different number of discovered lists may have Ref objects. |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2161 // That is OK as long as the Reference lists are balanced (see |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2162 // balance_all_queues() and balance_queues()). |
2369
92da084fefc9
6668573: CMS: reference processing crash if ParallelCMSThreads > ParallelGCThreads
ysr
parents:
2361
diff
changeset
|
2163 rp->set_active_mt_degree(active_workers); |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2164 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2165 rp->process_discovered_references(&g1_is_alive, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2166 &g1_keep_alive, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2167 &g1_drain_mark_stack, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2168 &par_task_executor); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2169 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2170 // The work routines of the parallel keep_alive and drain_marking_stack |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2171 // will set the has_overflown flag if we overflow the global marking |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2172 // stack. |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2173 } else { |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2174 rp->process_discovered_references(&g1_is_alive, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2175 &g1_keep_alive, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2176 &g1_drain_mark_stack, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2177 NULL); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2178 |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2179 } |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2180 |
342 | 2181 assert(_markStack.overflow() || _markStack.isEmpty(), |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2182 "mark stack should be empty (unless it overflowed)"); |
342 | 2183 if (_markStack.overflow()) { |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2184 // Should have been done already when we tried to push an |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2185 // entry on to the global mark stack. But let's do it again. |
342 | 2186 set_has_overflown(); |
2187 } | |
2188 | |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2189 if (rp->processing_is_mt()) { |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2190 assert(rp->num_q() == active_workers, "why not"); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2191 rp->enqueue_discovered_references(&par_task_executor); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2192 } else { |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2193 rp->enqueue_discovered_references(); |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2194 } |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2195 |
342 | 2196 rp->verify_no_references_recorded(); |
2197 assert(!rp->discovery_enabled(), "should have been disabled"); | |
2198 | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2175
diff
changeset
|
2199 // Now clean up stale oops in StringTable |
2037
b03260081e9b
7006113: G1: Initialize ReferenceProcessor::_is_alive_non_header field
johnc
parents:
1974
diff
changeset
|
2200 StringTable::unlink(&g1_is_alive); |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2175
diff
changeset
|
2201 // Clean up unreferenced symbols in symbol table. |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2175
diff
changeset
|
2202 SymbolTable::unlink(); |
342 | 2203 } |
2204 | |
2205 void ConcurrentMark::swapMarkBitMaps() { | |
2206 CMBitMapRO* temp = _prevMarkBitMap; | |
2207 _prevMarkBitMap = (CMBitMapRO*)_nextMarkBitMap; | |
2208 _nextMarkBitMap = (CMBitMap*) temp; | |
2209 } | |
2210 | |
2211 class CMRemarkTask: public AbstractGangTask { | |
2212 private: | |
2213 ConcurrentMark *_cm; | |
2214 | |
2215 public: | |
2216 void work(int worker_i) { | |
2217 // Since all available tasks are actually started, we should | |
2218 // only proceed if we're supposed to be actived. | |
2219 if ((size_t)worker_i < _cm->active_tasks()) { | |
2220 CMTask* task = _cm->task(worker_i); | |
2221 task->record_start_time(); | |
2222 do { | |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2223 task->do_marking_step(1000000000.0 /* something very large */, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2224 true /* do_stealing */, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2225 true /* do_termination */); |
342 | 2226 } while (task->has_aborted() && !_cm->has_overflown()); |
2227 // If we overflow, then we do not want to restart. We instead | |
2228 // want to abort remark and do concurrent marking again. | |
2229 task->record_end_time(); | |
2230 } | |
2231 } | |
2232 | |
2233 CMRemarkTask(ConcurrentMark* cm) : | |
2234 AbstractGangTask("Par Remark"), _cm(cm) { } | |
2235 }; | |
2236 | |
2237 void ConcurrentMark::checkpointRootsFinalWork() { | |
2238 ResourceMark rm; | |
2239 HandleMark hm; | |
2240 G1CollectedHeap* g1h = G1CollectedHeap::heap(); | |
2241 | |
2242 g1h->ensure_parsability(false); | |
2243 | |
1833
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1719
diff
changeset
|
2244 if (G1CollectedHeap::use_parallel_gc_threads()) { |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
912
diff
changeset
|
2245 G1CollectedHeap::StrongRootsScope srs(g1h); |
342 | 2246 // this is remark, so we'll use up all available threads |
2247 int active_workers = ParallelGCThreads; | |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2248 set_phase(active_workers, false /* concurrent */); |
342 | 2249 |
2250 CMRemarkTask remarkTask(this); | |
2251 // We will start all available threads, even if we decide that the | |
2252 // active_workers will be fewer. The extra ones will just bail out | |
2253 // immediately. | |
2254 int n_workers = g1h->workers()->total_workers(); | |
2255 g1h->set_par_threads(n_workers); | |
2256 g1h->workers()->run_task(&remarkTask); | |
2257 g1h->set_par_threads(0); | |
2258 } else { | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
912
diff
changeset
|
2259 G1CollectedHeap::StrongRootsScope srs(g1h); |
342 | 2260 // this is remark, so we'll use up all available threads |
2261 int active_workers = 1; | |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
2262 set_phase(active_workers, false /* concurrent */); |
342 | 2263 |
2264 CMRemarkTask remarkTask(this); | |
2265 // We will start all available threads, even if we decide that the | |
2266 // active_workers will be fewer. The extra ones will just bail out | |
2267 // immediately. | |
2268 remarkTask.work(0); | |
2269 } | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
2270 SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
2271 guarantee(satb_mq_set.completed_buffers_num() == 0, "invariant"); |
342 | 2272 |
2273 print_stats(); | |
2274 | |
2275 #if VERIFY_OBJS_PROCESSED | |
2276 if (_scan_obj_cl.objs_processed != ThreadLocalObjQueue::objs_enqueued) { | |
2277 gclog_or_tty->print_cr("Processed = %d, enqueued = %d.", | |
2278 _scan_obj_cl.objs_processed, | |
2279 ThreadLocalObjQueue::objs_enqueued); | |
2280 guarantee(_scan_obj_cl.objs_processed == | |
2281 ThreadLocalObjQueue::objs_enqueued, | |
2282 "Different number of objs processed and enqueued."); | |
2283 } | |
2284 #endif | |
2285 } | |
2286 | |
1044 | 2287 #ifndef PRODUCT |
2288 | |
1388 | 2289 class PrintReachableOopClosure: public OopClosure { |
342 | 2290 private: |
2291 G1CollectedHeap* _g1h; | |
2292 CMBitMapRO* _bitmap; | |
2293 outputStream* _out; | |
1044 | 2294 bool _use_prev_marking; |
1388 | 2295 bool _all; |
342 | 2296 |
2297 public: | |
1388 | 2298 PrintReachableOopClosure(CMBitMapRO* bitmap, |
2299 outputStream* out, | |
2300 bool use_prev_marking, | |
2301 bool all) : | |
1044 | 2302 _g1h(G1CollectedHeap::heap()), |
1388 | 2303 _bitmap(bitmap), _out(out), _use_prev_marking(use_prev_marking), _all(all) { } |
342 | 2304 |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
2305 void do_oop(narrowOop* p) { do_oop_work(p); } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
2306 void do_oop( oop* p) { do_oop_work(p); } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
2307 |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
2308 template <class T> void do_oop_work(T* p) { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
2309 oop obj = oopDesc::load_decode_heap_oop(p); |
342 | 2310 const char* str = NULL; |
2311 const char* str2 = ""; | |
2312 | |
1388 | 2313 if (obj == NULL) { |
2314 str = ""; | |
2315 } else if (!_g1h->is_in_g1_reserved(obj)) { | |
2316 str = " O"; | |
2317 } else { | |
342 | 2318 HeapRegion* hr = _g1h->heap_region_containing(obj); |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
2319 guarantee(hr != NULL, "invariant"); |
1044 | 2320 bool over_tams = false; |
2321 if (_use_prev_marking) { | |
2322 over_tams = hr->obj_allocated_since_prev_marking(obj); | |
2323 } else { | |
2324 over_tams = hr->obj_allocated_since_next_marking(obj); | |
2325 } | |
1388 | 2326 bool marked = _bitmap->isMarked((HeapWord*) obj); |
1044 | 2327 |
2328 if (over_tams) { | |
1388 | 2329 str = " >"; |
2330 if (marked) { | |
342 | 2331 str2 = " AND MARKED"; |
1044 | 2332 } |
1388 | 2333 } else if (marked) { |
2334 str = " M"; | |
1044 | 2335 } else { |
1388 | 2336 str = " NOT"; |
1044 | 2337 } |
342 | 2338 } |
2339 | |
1388 | 2340 _out->print_cr(" "PTR_FORMAT": "PTR_FORMAT"%s%s", |
342 | 2341 p, (void*) obj, str, str2); |
2342 } | |
2343 }; | |
2344 | |
1388 | 2345 class PrintReachableObjectClosure : public ObjectClosure { |
342 | 2346 private: |
1044 | 2347 CMBitMapRO* _bitmap; |
342 | 2348 outputStream* _out; |
1044 | 2349 bool _use_prev_marking; |
1388 | 2350 bool _all; |
2351 HeapRegion* _hr; | |
342 | 2352 |
2353 public: | |
1388 | 2354 PrintReachableObjectClosure(CMBitMapRO* bitmap, |
2355 outputStream* out, | |
2356 bool use_prev_marking, | |
2357 bool all, | |
2358 HeapRegion* hr) : | |
2359 _bitmap(bitmap), _out(out), | |
2360 _use_prev_marking(use_prev_marking), _all(all), _hr(hr) { } | |
2361 | |
2362 void do_object(oop o) { | |
2363 bool over_tams; | |
2364 if (_use_prev_marking) { | |
2365 over_tams = _hr->obj_allocated_since_prev_marking(o); | |
2366 } else { | |
2367 over_tams = _hr->obj_allocated_since_next_marking(o); | |
2368 } | |
2369 bool marked = _bitmap->isMarked((HeapWord*) o); | |
2370 bool print_it = _all || over_tams || marked; | |
2371 | |
2372 if (print_it) { | |
2373 _out->print_cr(" "PTR_FORMAT"%s", | |
2374 o, (over_tams) ? " >" : (marked) ? " M" : ""); | |
2375 PrintReachableOopClosure oopCl(_bitmap, _out, _use_prev_marking, _all); | |
2376 o->oop_iterate(&oopCl); | |
2377 } | |
342 | 2378 } |
2379 }; | |
2380 | |
1388 | 2381 class PrintReachableRegionClosure : public HeapRegionClosure { |
342 | 2382 private: |
1044 | 2383 CMBitMapRO* _bitmap; |
342 | 2384 outputStream* _out; |
1044 | 2385 bool _use_prev_marking; |
1388 | 2386 bool _all; |
342 | 2387 |
2388 public: | |
2389 bool doHeapRegion(HeapRegion* hr) { | |
2390 HeapWord* b = hr->bottom(); | |
2391 HeapWord* e = hr->end(); | |
2392 HeapWord* t = hr->top(); | |
1044 | 2393 HeapWord* p = NULL; |
2394 if (_use_prev_marking) { | |
2395 p = hr->prev_top_at_mark_start(); | |
2396 } else { | |
2397 p = hr->next_top_at_mark_start(); | |
2398 } | |
342 | 2399 _out->print_cr("** ["PTR_FORMAT", "PTR_FORMAT"] top: "PTR_FORMAT" " |
1044 | 2400 "TAMS: "PTR_FORMAT, b, e, t, p); |
1388 | 2401 _out->cr(); |
2402 | |
2403 HeapWord* from = b; | |
2404 HeapWord* to = t; | |
2405 | |
2406 if (to > from) { | |
2407 _out->print_cr("Objects in ["PTR_FORMAT", "PTR_FORMAT"]", from, to); | |
2408 _out->cr(); | |
2409 PrintReachableObjectClosure ocl(_bitmap, _out, | |
2410 _use_prev_marking, _all, hr); | |
2411 hr->object_iterate_mem_careful(MemRegion(from, to), &ocl); | |
2412 _out->cr(); | |
2413 } | |
342 | 2414 |
2415 return false; | |
2416 } | |
2417 | |
1388 | 2418 PrintReachableRegionClosure(CMBitMapRO* bitmap, |
2419 outputStream* out, | |
2420 bool use_prev_marking, | |
2421 bool all) : | |
2422 _bitmap(bitmap), _out(out), _use_prev_marking(use_prev_marking), _all(all) { } | |
342 | 2423 }; |
2424 | |
1388 | 2425 void ConcurrentMark::print_reachable(const char* str, |
2426 bool use_prev_marking, | |
2427 bool all) { | |
2428 gclog_or_tty->cr(); | |
2429 gclog_or_tty->print_cr("== Doing heap dump... "); | |
1044 | 2430 |
2431 if (G1PrintReachableBaseFile == NULL) { | |
2432 gclog_or_tty->print_cr(" #### error: no base file defined"); | |
2433 return; | |
2434 } | |
2435 | |
2436 if (strlen(G1PrintReachableBaseFile) + 1 + strlen(str) > | |
2437 (JVM_MAXPATHLEN - 1)) { | |
2438 gclog_or_tty->print_cr(" #### error: file name too long"); | |
2439 return; | |
2440 } | |
2441 | |
2442 char file_name[JVM_MAXPATHLEN]; | |
2443 sprintf(file_name, "%s.%s", G1PrintReachableBaseFile, str); | |
2444 gclog_or_tty->print_cr(" dumping to file %s", file_name); | |
2445 | |
2446 fileStream fout(file_name); | |
2447 if (!fout.is_open()) { | |
2448 gclog_or_tty->print_cr(" #### error: could not open file"); | |
2449 return; | |
2450 } | |
2451 | |
2452 outputStream* out = &fout; | |
2453 | |
2454 CMBitMapRO* bitmap = NULL; | |
2455 if (use_prev_marking) { | |
2456 bitmap = _prevMarkBitMap; | |
2457 } else { | |
2458 bitmap = _nextMarkBitMap; | |
2459 } | |
2460 | |
2461 out->print_cr("-- USING %s", (use_prev_marking) ? "PTAMS" : "NTAMS"); | |
2462 out->cr(); | |
2463 | |
1388 | 2464 out->print_cr("--- ITERATING OVER REGIONS"); |
1044 | 2465 out->cr(); |
1388 | 2466 PrintReachableRegionClosure rcl(bitmap, out, use_prev_marking, all); |
2467 _g1h->heap_region_iterate(&rcl); | |
1044 | 2468 out->cr(); |
2469 | |
2470 gclog_or_tty->print_cr(" done"); | |
1388 | 2471 gclog_or_tty->flush(); |
342 | 2472 } |
2473 | |
1044 | 2474 #endif // PRODUCT |
2475 | |
342 | 2476 // This note is for drainAllSATBBuffers and the code in between. |
2477 // In the future we could reuse a task to do this work during an | |
2478 // evacuation pause (since now tasks are not active and can be claimed | |
2479 // during an evacuation pause). This was a late change to the code and | |
2480 // is currently not being taken advantage of. | |
2481 | |
2482 class CMGlobalObjectClosure : public ObjectClosure { | |
2483 private: | |
2484 ConcurrentMark* _cm; | |
2485 | |
2486 public: | |
2487 void do_object(oop obj) { | |
2488 _cm->deal_with_reference(obj); | |
2489 } | |
2490 | |
2491 CMGlobalObjectClosure(ConcurrentMark* cm) : _cm(cm) { } | |
2492 }; | |
2493 | |
2494 void ConcurrentMark::deal_with_reference(oop obj) { | |
2495 if (verbose_high()) | |
2496 gclog_or_tty->print_cr("[global] we're dealing with reference "PTR_FORMAT, | |
2497 (void*) obj); | |
2498 | |
2499 | |
2500 HeapWord* objAddr = (HeapWord*) obj; | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
2501 assert(obj->is_oop_or_null(true /* ignore mark word */), "Error"); |
342 | 2502 if (_g1h->is_in_g1_reserved(objAddr)) { |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
2503 assert(obj != NULL, "is_in_g1_reserved should ensure this"); |
342 | 2504 HeapRegion* hr = _g1h->heap_region_containing(obj); |
2505 if (_g1h->is_obj_ill(obj, hr)) { | |
2506 if (verbose_high()) | |
2507 gclog_or_tty->print_cr("[global] "PTR_FORMAT" is not considered " | |
2508 "marked", (void*) obj); | |
2509 | |
2510 // we need to mark it first | |
2511 if (_nextMarkBitMap->parMark(objAddr)) { | |
2512 // No OrderAccess:store_load() is needed. It is implicit in the | |
2513 // CAS done in parMark(objAddr) above | |
2514 HeapWord* finger = _finger; | |
2515 if (objAddr < finger) { | |
2516 if (verbose_high()) | |
2517 gclog_or_tty->print_cr("[global] below the global finger " | |
2518 "("PTR_FORMAT"), pushing it", finger); | |
2519 if (!mark_stack_push(obj)) { | |
2520 if (verbose_low()) | |
2521 gclog_or_tty->print_cr("[global] global stack overflow during " | |
2522 "deal_with_reference"); | |
2523 } | |
2524 } | |
2525 } | |
2526 } | |
2527 } | |
2528 } | |
2529 | |
2530 void ConcurrentMark::drainAllSATBBuffers() { | |
2531 CMGlobalObjectClosure oc(this); | |
2532 SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); | |
2533 satb_mq_set.set_closure(&oc); | |
2534 | |
2535 while (satb_mq_set.apply_closure_to_completed_buffer()) { | |
2536 if (verbose_medium()) | |
2537 gclog_or_tty->print_cr("[global] processed an SATB buffer"); | |
2538 } | |
2539 | |
2540 // no need to check whether we should do this, as this is only | |
2541 // called during an evacuation pause | |
2542 satb_mq_set.iterate_closure_all_threads(); | |
2543 | |
2544 satb_mq_set.set_closure(NULL); | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
2545 assert(satb_mq_set.completed_buffers_num() == 0, "invariant"); |
342 | 2546 } |
2547 | |
2548 void ConcurrentMark::markPrev(oop p) { | |
2549 // Note we are overriding the read-only view of the prev map here, via | |
2550 // the cast. | |
2551 ((CMBitMap*)_prevMarkBitMap)->mark((HeapWord*)p); | |
2552 } | |
2553 | |
2554 void ConcurrentMark::clear(oop p) { | |
2555 assert(p != NULL && p->is_oop(), "expected an oop"); | |
2556 HeapWord* addr = (HeapWord*)p; | |
2557 assert(addr >= _nextMarkBitMap->startWord() || | |
2558 addr < _nextMarkBitMap->endWord(), "in a region"); | |
2559 | |
2560 _nextMarkBitMap->clear(addr); | |
2561 } | |
2562 | |
2563 void ConcurrentMark::clearRangeBothMaps(MemRegion mr) { | |
2564 // Note we are overriding the read-only view of the prev map here, via | |
2565 // the cast. | |
2566 ((CMBitMap*)_prevMarkBitMap)->clearRange(mr); | |
2567 _nextMarkBitMap->clearRange(mr); | |
2568 } | |
2569 | |
2570 HeapRegion* | |
2571 ConcurrentMark::claim_region(int task_num) { | |
2572 // "checkpoint" the finger | |
2573 HeapWord* finger = _finger; | |
2574 | |
2575 // _heap_end will not change underneath our feet; it only changes at | |
2576 // yield points. | |
2577 while (finger < _heap_end) { | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
2578 assert(_g1h->is_in_g1_reserved(finger), "invariant"); |
342 | 2579 |
2580 // is the gap between reading the finger and doing the CAS too long? | |
2581 | |
2582 HeapRegion* curr_region = _g1h->heap_region_containing(finger); | |
2583 HeapWord* bottom = curr_region->bottom(); | |
2584 HeapWord* end = curr_region->end(); | |
2585 HeapWord* limit = curr_region->next_top_at_mark_start(); | |
2586 | |
2587 if (verbose_low()) | |
2588 gclog_or_tty->print_cr("[%d] curr_region = "PTR_FORMAT" " | |
2589 "["PTR_FORMAT", "PTR_FORMAT"), " | |
2590 "limit = "PTR_FORMAT, | |
2591 task_num, curr_region, bottom, end, limit); | |
2592 | |
2593 HeapWord* res = | |
2594 (HeapWord*) Atomic::cmpxchg_ptr(end, &_finger, finger); | |
2595 if (res == finger) { | |
2596 // we succeeded | |
2597 | |
2598 // notice that _finger == end cannot be guaranteed here since, | |
2599 // someone else might have moved the finger even further | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
2600 assert(_finger >= end, "the finger should have moved forward"); |
342 | 2601 |
2602 if (verbose_low()) | |
2603 gclog_or_tty->print_cr("[%d] we were successful with region = " | |
2604 PTR_FORMAT, task_num, curr_region); | |
2605 | |
2606 if (limit > bottom) { | |
2607 if (verbose_low()) | |
2608 gclog_or_tty->print_cr("[%d] region "PTR_FORMAT" is not empty, " | |
2609 "returning it ", task_num, curr_region); | |
2610 return curr_region; | |
2611 } else { | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
2612 assert(limit == bottom, |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
2613 "the region limit should be at bottom"); |
342 | 2614 if (verbose_low()) |
2615 gclog_or_tty->print_cr("[%d] region "PTR_FORMAT" is empty, " | |
2616 "returning NULL", task_num, curr_region); | |
2617 // we return NULL and the caller should try calling | |
2618 // claim_region() again. | |
2619 return NULL; | |
2620 } | |
2621 } else { | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
2622 assert(_finger > finger, "the finger should have moved forward"); |
342 | 2623 if (verbose_low()) |
2624 gclog_or_tty->print_cr("[%d] somebody else moved the finger, " | |
2625 "global finger = "PTR_FORMAT", " | |
2626 "our finger = "PTR_FORMAT, | |
2627 task_num, _finger, finger); | |
2628 | |
2629 // read it again | |
2630 finger = _finger; | |
2631 } | |
2632 } | |
2633 | |
2634 return NULL; | |
2635 } | |
2636 | |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2637 bool ConcurrentMark::invalidate_aborted_regions_in_cset() { |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2638 bool result = false; |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2639 for (int i = 0; i < (int)_max_task_num; ++i) { |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2640 CMTask* the_task = _tasks[i]; |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2641 MemRegion mr = the_task->aborted_region(); |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2642 if (mr.start() != NULL) { |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2643 assert(mr.end() != NULL, "invariant"); |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2644 assert(mr.word_size() > 0, "invariant"); |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2645 HeapRegion* hr = _g1h->heap_region_containing(mr.start()); |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2646 assert(hr != NULL, "invariant"); |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2647 if (hr->in_collection_set()) { |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2648 // The region points into the collection set |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2649 the_task->set_aborted_region(MemRegion()); |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2650 result = true; |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2651 } |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2652 } |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2653 } |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2654 return result; |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2655 } |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2656 |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2657 bool ConcurrentMark::has_aborted_regions() { |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2658 for (int i = 0; i < (int)_max_task_num; ++i) { |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2659 CMTask* the_task = _tasks[i]; |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2660 MemRegion mr = the_task->aborted_region(); |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2661 if (mr.start() != NULL) { |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2662 assert(mr.end() != NULL, "invariant"); |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2663 assert(mr.word_size() > 0, "invariant"); |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2664 return true; |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2665 } |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2666 } |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2667 return false; |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2668 } |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2669 |
342 | 2670 void ConcurrentMark::oops_do(OopClosure* cl) { |
2671 if (_markStack.size() > 0 && verbose_low()) | |
2672 gclog_or_tty->print_cr("[global] scanning the global marking stack, " | |
2673 "size = %d", _markStack.size()); | |
2674 // we first iterate over the contents of the mark stack... | |
2675 _markStack.oops_do(cl); | |
2676 | |
2677 for (int i = 0; i < (int)_max_task_num; ++i) { | |
2678 OopTaskQueue* queue = _task_queues->queue((int)i); | |
2679 | |
2680 if (queue->size() > 0 && verbose_low()) | |
2681 gclog_or_tty->print_cr("[global] scanning task queue of task %d, " | |
2682 "size = %d", i, queue->size()); | |
2683 | |
2684 // ...then over the contents of the all the task queues. | |
2685 queue->oops_do(cl); | |
2686 } | |
2687 | |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2688 // Invalidate any entries, that are in the region stack, that |
342 | 2689 // point into the collection set |
2690 if (_regionStack.invalidate_entries_into_cset()) { | |
2691 // otherwise, any gray objects copied during the evacuation pause | |
2692 // might not be visited. | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
2693 assert(_should_gray_objects, "invariant"); |
342 | 2694 } |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2695 |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2696 // Invalidate any aborted regions, recorded in the individual CM |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2697 // tasks, that point into the collection set. |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2698 if (invalidate_aborted_regions_in_cset()) { |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2699 // otherwise, any gray objects copied during the evacuation pause |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2700 // might not be visited. |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2701 assert(_should_gray_objects, "invariant"); |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2702 } |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2703 |
342 | 2704 } |
2705 | |
2706 void ConcurrentMark::clear_marking_state() { | |
2707 _markStack.setEmpty(); | |
2708 _markStack.clear_overflow(); | |
2709 _regionStack.setEmpty(); | |
2710 _regionStack.clear_overflow(); | |
2711 clear_has_overflown(); | |
2712 _finger = _heap_start; | |
2713 | |
2714 for (int i = 0; i < (int)_max_task_num; ++i) { | |
2715 OopTaskQueue* queue = _task_queues->queue(i); | |
2716 queue->set_empty(); | |
1885
a5c514e74487
6988458: G1: assert(mr.end() <= _cm->finger()) failed: otherwise the region shouldn't be on the stack
johnc
parents:
1835
diff
changeset
|
2717 // Clear any partial regions from the CMTasks |
a5c514e74487
6988458: G1: assert(mr.end() <= _cm->finger()) failed: otherwise the region shouldn't be on the stack
johnc
parents:
1835
diff
changeset
|
2718 _tasks[i]->clear_aborted_region(); |
342 | 2719 } |
2720 } | |
2721 | |
2722 void ConcurrentMark::print_stats() { | |
2723 if (verbose_stats()) { | |
2724 gclog_or_tty->print_cr("---------------------------------------------------------------------"); | |
2725 for (size_t i = 0; i < _active_tasks; ++i) { | |
2726 _tasks[i]->print_stats(); | |
2727 gclog_or_tty->print_cr("---------------------------------------------------------------------"); | |
2728 } | |
2729 } | |
2730 } | |
2731 | |
2732 class CSMarkOopClosure: public OopClosure { | |
2733 friend class CSMarkBitMapClosure; | |
2734 | |
2735 G1CollectedHeap* _g1h; | |
2736 CMBitMap* _bm; | |
2737 ConcurrentMark* _cm; | |
2738 oop* _ms; | |
2739 jint* _array_ind_stack; | |
2740 int _ms_size; | |
2741 int _ms_ind; | |
2742 int _array_increment; | |
2743 | |
2744 bool push(oop obj, int arr_ind = 0) { | |
2745 if (_ms_ind == _ms_size) { | |
2746 gclog_or_tty->print_cr("Mark stack is full."); | |
2747 return false; | |
2748 } | |
2749 _ms[_ms_ind] = obj; | |
2750 if (obj->is_objArray()) _array_ind_stack[_ms_ind] = arr_ind; | |
2751 _ms_ind++; | |
2752 return true; | |
2753 } | |
2754 | |
2755 oop pop() { | |
2756 if (_ms_ind == 0) return NULL; | |
2757 else { | |
2758 _ms_ind--; | |
2759 return _ms[_ms_ind]; | |
2760 } | |
2761 } | |
2762 | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
2763 template <class T> bool drain() { |
342 | 2764 while (_ms_ind > 0) { |
2765 oop obj = pop(); | |
2766 assert(obj != NULL, "Since index was non-zero."); | |
2767 if (obj->is_objArray()) { | |
2768 jint arr_ind = _array_ind_stack[_ms_ind]; | |
2769 objArrayOop aobj = objArrayOop(obj); | |
2770 jint len = aobj->length(); | |
2771 jint next_arr_ind = arr_ind + _array_increment; | |
2772 if (next_arr_ind < len) { | |
2773 push(obj, next_arr_ind); | |
2774 } | |
2775 // Now process this portion of this one. | |
2776 int lim = MIN2(next_arr_ind, len); | |
2777 for (int j = arr_ind; j < lim; j++) { | |
912
308762b2bf14
6872000: G1: compilation fails on linux/older gcc
apetrusenko
parents:
866
diff
changeset
|
2778 do_oop(aobj->objArrayOopDesc::obj_at_addr<T>(j)); |
342 | 2779 } |
2780 | |
2781 } else { | |
2782 obj->oop_iterate(this); | |
2783 } | |
2784 if (abort()) return false; | |
2785 } | |
2786 return true; | |
2787 } | |
2788 | |
2789 public: | |
2790 CSMarkOopClosure(ConcurrentMark* cm, int ms_size) : | |
2791 _g1h(G1CollectedHeap::heap()), | |
2792 _cm(cm), | |
2793 _bm(cm->nextMarkBitMap()), | |
2794 _ms_size(ms_size), _ms_ind(0), | |
2795 _ms(NEW_C_HEAP_ARRAY(oop, ms_size)), | |
2796 _array_ind_stack(NEW_C_HEAP_ARRAY(jint, ms_size)), | |
2797 _array_increment(MAX2(ms_size/8, 16)) | |
2798 {} | |
2799 | |
2800 ~CSMarkOopClosure() { | |
2801 FREE_C_HEAP_ARRAY(oop, _ms); | |
2802 FREE_C_HEAP_ARRAY(jint, _array_ind_stack); | |
2803 } | |
2804 | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
2805 virtual void do_oop(narrowOop* p) { do_oop_work(p); } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
2806 virtual void do_oop( oop* p) { do_oop_work(p); } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
2807 |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
2808 template <class T> void do_oop_work(T* p) { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
2809 T heap_oop = oopDesc::load_heap_oop(p); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
2810 if (oopDesc::is_null(heap_oop)) return; |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
2811 oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); |
342 | 2812 if (obj->is_forwarded()) { |
2813 // If the object has already been forwarded, we have to make sure | |
2814 // that it's marked. So follow the forwarding pointer. Note that | |
2815 // this does the right thing for self-forwarding pointers in the | |
2816 // evacuation failure case. | |
2817 obj = obj->forwardee(); | |
2818 } | |
2819 HeapRegion* hr = _g1h->heap_region_containing(obj); | |
2820 if (hr != NULL) { | |
2821 if (hr->in_collection_set()) { | |
2822 if (_g1h->is_obj_ill(obj)) { | |
2823 _bm->mark((HeapWord*)obj); | |
2824 if (!push(obj)) { | |
2825 gclog_or_tty->print_cr("Setting abort in CSMarkOopClosure because push failed."); | |
2826 set_abort(); | |
2827 } | |
2828 } | |
2829 } else { | |
2830 // Outside the collection set; we need to gray it | |
2831 _cm->deal_with_reference(obj); | |
2832 } | |
2833 } | |
2834 } | |
2835 }; | |
2836 | |
2837 class CSMarkBitMapClosure: public BitMapClosure { | |
2838 G1CollectedHeap* _g1h; | |
2839 CMBitMap* _bitMap; | |
2840 ConcurrentMark* _cm; | |
2841 CSMarkOopClosure _oop_cl; | |
2842 public: | |
2843 CSMarkBitMapClosure(ConcurrentMark* cm, int ms_size) : | |
2844 _g1h(G1CollectedHeap::heap()), | |
2845 _bitMap(cm->nextMarkBitMap()), | |
2846 _oop_cl(cm, ms_size) | |
2847 {} | |
2848 | |
2849 ~CSMarkBitMapClosure() {} | |
2850 | |
2851 bool do_bit(size_t offset) { | |
2852 // convert offset into a HeapWord* | |
2853 HeapWord* addr = _bitMap->offsetToHeapWord(offset); | |
2854 assert(_bitMap->endWord() && addr < _bitMap->endWord(), | |
2855 "address out of range"); | |
2856 assert(_bitMap->isMarked(addr), "tautology"); | |
2857 oop obj = oop(addr); | |
2858 if (!obj->is_forwarded()) { | |
2859 if (!_oop_cl.push(obj)) return false; | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
2860 if (UseCompressedOops) { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
2861 if (!_oop_cl.drain<narrowOop>()) return false; |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
2862 } else { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
2863 if (!_oop_cl.drain<oop>()) return false; |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
2864 } |
342 | 2865 } |
2866 // Otherwise... | |
2867 return true; | |
2868 } | |
2869 }; | |
2870 | |
2871 | |
2872 class CompleteMarkingInCSHRClosure: public HeapRegionClosure { | |
2873 CMBitMap* _bm; | |
2874 CSMarkBitMapClosure _bit_cl; | |
2875 enum SomePrivateConstants { | |
2876 MSSize = 1000 | |
2877 }; | |
2878 bool _completed; | |
2879 public: | |
2880 CompleteMarkingInCSHRClosure(ConcurrentMark* cm) : | |
2881 _bm(cm->nextMarkBitMap()), | |
2882 _bit_cl(cm, MSSize), | |
2883 _completed(true) | |
2884 {} | |
2885 | |
2886 ~CompleteMarkingInCSHRClosure() {} | |
2887 | |
2888 bool doHeapRegion(HeapRegion* r) { | |
2889 if (!r->evacuation_failed()) { | |
2890 MemRegion mr = MemRegion(r->bottom(), r->next_top_at_mark_start()); | |
2891 if (!mr.is_empty()) { | |
2892 if (!_bm->iterate(&_bit_cl, mr)) { | |
2893 _completed = false; | |
2894 return true; | |
2895 } | |
2896 } | |
2897 } | |
2898 return false; | |
2899 } | |
2900 | |
2901 bool completed() { return _completed; } | |
2902 }; | |
2903 | |
2904 class ClearMarksInHRClosure: public HeapRegionClosure { | |
2905 CMBitMap* _bm; | |
2906 public: | |
2907 ClearMarksInHRClosure(CMBitMap* bm): _bm(bm) { } | |
2908 | |
2909 bool doHeapRegion(HeapRegion* r) { | |
2910 if (!r->used_region().is_empty() && !r->evacuation_failed()) { | |
2911 MemRegion usedMR = r->used_region(); | |
2912 _bm->clearRange(r->used_region()); | |
2913 } | |
2914 return false; | |
2915 } | |
2916 }; | |
2917 | |
2918 void ConcurrentMark::complete_marking_in_collection_set() { | |
2919 G1CollectedHeap* g1h = G1CollectedHeap::heap(); | |
2920 | |
2921 if (!g1h->mark_in_progress()) { | |
2922 g1h->g1_policy()->record_mark_closure_time(0.0); | |
2923 return; | |
2924 } | |
2925 | |
2926 int i = 1; | |
2927 double start = os::elapsedTime(); | |
2928 while (true) { | |
2929 i++; | |
2930 CompleteMarkingInCSHRClosure cmplt(this); | |
2931 g1h->collection_set_iterate(&cmplt); | |
2932 if (cmplt.completed()) break; | |
2933 } | |
2934 double end_time = os::elapsedTime(); | |
2935 double elapsed_time_ms = (end_time - start) * 1000.0; | |
2936 g1h->g1_policy()->record_mark_closure_time(elapsed_time_ms); | |
2937 | |
2938 ClearMarksInHRClosure clr(nextMarkBitMap()); | |
2939 g1h->collection_set_iterate(&clr); | |
2940 } | |
2941 | |
2942 // The next two methods deal with the following optimisation. Some | |
2943 // objects are gray by being marked and located above the finger. If | |
2944 // they are copied, during an evacuation pause, below the finger then | |
2945 // the need to be pushed on the stack. The observation is that, if | |
2946 // there are no regions in the collection set located above the | |
2947 // finger, then the above cannot happen, hence we do not need to | |
2948 // explicitly gray any objects when copying them to below the | |
2949 // finger. The global stack will be scanned to ensure that, if it | |
2950 // points to objects being copied, it will update their | |
2951 // location. There is a tricky situation with the gray objects in | |
2952 // region stack that are being coped, however. See the comment in | |
2953 // newCSet(). | |
2954 | |
2955 void ConcurrentMark::newCSet() { | |
2956 if (!concurrent_marking_in_progress()) | |
2957 // nothing to do if marking is not in progress | |
2958 return; | |
2959 | |
2960 // find what the lowest finger is among the global and local fingers | |
2961 _min_finger = _finger; | |
2962 for (int i = 0; i < (int)_max_task_num; ++i) { | |
2963 CMTask* task = _tasks[i]; | |
2964 HeapWord* task_finger = task->finger(); | |
2965 if (task_finger != NULL && task_finger < _min_finger) | |
2966 _min_finger = task_finger; | |
2967 } | |
2968 | |
2969 _should_gray_objects = false; | |
2970 | |
2971 // This fixes a very subtle and fustrating bug. It might be the case | |
2972 // that, during en evacuation pause, heap regions that contain | |
2973 // objects that are gray (by being in regions contained in the | |
2974 // region stack) are included in the collection set. Since such gray | |
2975 // objects will be moved, and because it's not easy to redirect | |
2976 // region stack entries to point to a new location (because objects | |
2977 // in one region might be scattered to multiple regions after they | |
2978 // are copied), one option is to ensure that all marked objects | |
2979 // copied during a pause are pushed on the stack. Notice, however, | |
2980 // that this problem can only happen when the region stack is not | |
2981 // empty during an evacuation pause. So, we make the fix a bit less | |
2982 // conservative and ensure that regions are pushed on the stack, | |
2983 // irrespective whether all collection set regions are below the | |
2984 // finger, if the region stack is not empty. This is expected to be | |
2985 // a rare case, so I don't think it's necessary to be smarted about it. | |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
2986 if (!region_stack_empty() || has_aborted_regions()) |
342 | 2987 _should_gray_objects = true; |
2988 } | |
2989 | |
2990 void ConcurrentMark::registerCSetRegion(HeapRegion* hr) { | |
2991 if (!concurrent_marking_in_progress()) | |
2992 return; | |
2993 | |
2994 HeapWord* region_end = hr->end(); | |
2995 if (region_end > _min_finger) | |
2996 _should_gray_objects = true; | |
2997 } | |
2998 | |
2999 // abandon current marking iteration due to a Full GC | |
3000 void ConcurrentMark::abort() { | |
3001 // Clear all marks to force marking thread to do nothing | |
3002 _nextMarkBitMap->clearAll(); | |
3003 // Empty mark stack | |
3004 clear_marking_state(); | |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3005 for (int i = 0; i < (int)_max_task_num; ++i) { |
342 | 3006 _tasks[i]->clear_region_fields(); |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3007 } |
342 | 3008 _has_aborted = true; |
3009 | |
3010 SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); | |
3011 satb_mq_set.abandon_partial_marking(); | |
1317
d4197f8d516a
6935821: G1: threads created during marking do not active their SATB queues
tonyp
parents:
1314
diff
changeset
|
3012 // This can be called either during or outside marking, we'll read |
d4197f8d516a
6935821: G1: threads created during marking do not active their SATB queues
tonyp
parents:
1314
diff
changeset
|
3013 // the expected_active value from the SATB queue set. |
d4197f8d516a
6935821: G1: threads created during marking do not active their SATB queues
tonyp
parents:
1314
diff
changeset
|
3014 satb_mq_set.set_active_all_threads( |
d4197f8d516a
6935821: G1: threads created during marking do not active their SATB queues
tonyp
parents:
1314
diff
changeset
|
3015 false, /* new active value */ |
d4197f8d516a
6935821: G1: threads created during marking do not active their SATB queues
tonyp
parents:
1314
diff
changeset
|
3016 satb_mq_set.is_active() /* expected_active */); |
342 | 3017 } |
3018 | |
3019 static void print_ms_time_info(const char* prefix, const char* name, | |
3020 NumberSeq& ns) { | |
3021 gclog_or_tty->print_cr("%s%5d %12s: total time = %8.2f s (avg = %8.2f ms).", | |
3022 prefix, ns.num(), name, ns.sum()/1000.0, ns.avg()); | |
3023 if (ns.num() > 0) { | |
3024 gclog_or_tty->print_cr("%s [std. dev = %8.2f ms, max = %8.2f ms]", | |
3025 prefix, ns.sd(), ns.maximum()); | |
3026 } | |
3027 } | |
3028 | |
3029 void ConcurrentMark::print_summary_info() { | |
3030 gclog_or_tty->print_cr(" Concurrent marking:"); | |
3031 print_ms_time_info(" ", "init marks", _init_times); | |
3032 print_ms_time_info(" ", "remarks", _remark_times); | |
3033 { | |
3034 print_ms_time_info(" ", "final marks", _remark_mark_times); | |
3035 print_ms_time_info(" ", "weak refs", _remark_weak_ref_times); | |
3036 | |
3037 } | |
3038 print_ms_time_info(" ", "cleanups", _cleanup_times); | |
3039 gclog_or_tty->print_cr(" Final counting total time = %8.2f s (avg = %8.2f ms).", | |
3040 _total_counting_time, | |
3041 (_cleanup_times.num() > 0 ? _total_counting_time * 1000.0 / | |
3042 (double)_cleanup_times.num() | |
3043 : 0.0)); | |
3044 if (G1ScrubRemSets) { | |
3045 gclog_or_tty->print_cr(" RS scrub total time = %8.2f s (avg = %8.2f ms).", | |
3046 _total_rs_scrub_time, | |
3047 (_cleanup_times.num() > 0 ? _total_rs_scrub_time * 1000.0 / | |
3048 (double)_cleanup_times.num() | |
3049 : 0.0)); | |
3050 } | |
3051 gclog_or_tty->print_cr(" Total stop_world time = %8.2f s.", | |
3052 (_init_times.sum() + _remark_times.sum() + | |
3053 _cleanup_times.sum())/1000.0); | |
3054 gclog_or_tty->print_cr(" Total concurrent time = %8.2f s " | |
3055 "(%8.2f s marking, %8.2f s counting).", | |
3056 cmThread()->vtime_accum(), | |
3057 cmThread()->vtime_mark_accum(), | |
3058 cmThread()->vtime_count_accum()); | |
3059 } | |
3060 | |
1019 | 3061 void ConcurrentMark::print_worker_threads_on(outputStream* st) const { |
3062 _parallel_workers->print_worker_threads_on(st); | |
3063 } | |
3064 | |
342 | 3065 // Closures |
3066 // XXX: there seems to be a lot of code duplication here; | |
3067 // should refactor and consolidate the shared code. | |
3068 | |
3069 // This closure is used to mark refs into the CMS generation in | |
3070 // the CMS bit map. Called at the first checkpoint. | |
3071 | |
3072 // We take a break if someone is trying to stop the world. | |
3073 bool ConcurrentMark::do_yield_check(int worker_i) { | |
3074 if (should_yield()) { | |
3075 if (worker_i == 0) | |
3076 _g1h->g1_policy()->record_concurrent_pause(); | |
3077 cmThread()->yield(); | |
3078 if (worker_i == 0) | |
3079 _g1h->g1_policy()->record_concurrent_pause_end(); | |
3080 return true; | |
3081 } else { | |
3082 return false; | |
3083 } | |
3084 } | |
3085 | |
3086 bool ConcurrentMark::should_yield() { | |
3087 return cmThread()->should_yield(); | |
3088 } | |
3089 | |
3090 bool ConcurrentMark::containing_card_is_marked(void* p) { | |
3091 size_t offset = pointer_delta(p, _g1h->reserved_region().start(), 1); | |
3092 return _card_bm.at(offset >> CardTableModRefBS::card_shift); | |
3093 } | |
3094 | |
3095 bool ConcurrentMark::containing_cards_are_marked(void* start, | |
3096 void* last) { | |
3097 return | |
3098 containing_card_is_marked(start) && | |
3099 containing_card_is_marked(last); | |
3100 } | |
3101 | |
3102 #ifndef PRODUCT | |
3103 // for debugging purposes | |
3104 void ConcurrentMark::print_finger() { | |
3105 gclog_or_tty->print_cr("heap ["PTR_FORMAT", "PTR_FORMAT"), global finger = "PTR_FORMAT, | |
3106 _heap_start, _heap_end, _finger); | |
3107 for (int i = 0; i < (int) _max_task_num; ++i) { | |
3108 gclog_or_tty->print(" %d: "PTR_FORMAT, i, _tasks[i]->finger()); | |
3109 } | |
3110 gclog_or_tty->print_cr(""); | |
3111 } | |
3112 #endif | |
3113 | |
3114 // Closure for iteration over bitmaps | |
3115 class CMBitMapClosure : public BitMapClosure { | |
3116 private: | |
3117 // the bitmap that is being iterated over | |
3118 CMBitMap* _nextMarkBitMap; | |
3119 ConcurrentMark* _cm; | |
3120 CMTask* _task; | |
3121 // true if we're scanning a heap region claimed by the task (so that | |
3122 // we move the finger along), false if we're not, i.e. currently when | |
3123 // scanning a heap region popped from the region stack (so that we | |
3124 // do not move the task finger along; it'd be a mistake if we did so). | |
3125 bool _scanning_heap_region; | |
3126 | |
3127 public: | |
3128 CMBitMapClosure(CMTask *task, | |
3129 ConcurrentMark* cm, | |
3130 CMBitMap* nextMarkBitMap) | |
3131 : _task(task), _cm(cm), _nextMarkBitMap(nextMarkBitMap) { } | |
3132 | |
3133 void set_scanning_heap_region(bool scanning_heap_region) { | |
3134 _scanning_heap_region = scanning_heap_region; | |
3135 } | |
3136 | |
3137 bool do_bit(size_t offset) { | |
3138 HeapWord* addr = _nextMarkBitMap->offsetToHeapWord(offset); | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3139 assert(_nextMarkBitMap->isMarked(addr), "invariant"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3140 assert( addr < _cm->finger(), "invariant"); |
342 | 3141 |
3142 if (_scanning_heap_region) { | |
3143 statsOnly( _task->increase_objs_found_on_bitmap() ); | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3144 assert(addr >= _task->finger(), "invariant"); |
342 | 3145 // We move that task's local finger along. |
3146 _task->move_finger_to(addr); | |
3147 } else { | |
3148 // We move the task's region finger along. | |
3149 _task->move_region_finger_to(addr); | |
3150 } | |
3151 | |
3152 _task->scan_object(oop(addr)); | |
3153 // we only partially drain the local queue and global stack | |
3154 _task->drain_local_queue(true); | |
3155 _task->drain_global_stack(true); | |
3156 | |
3157 // if the has_aborted flag has been raised, we need to bail out of | |
3158 // the iteration | |
3159 return !_task->has_aborted(); | |
3160 } | |
3161 }; | |
3162 | |
3163 // Closure for iterating over objects, currently only used for | |
3164 // processing SATB buffers. | |
3165 class CMObjectClosure : public ObjectClosure { | |
3166 private: | |
3167 CMTask* _task; | |
3168 | |
3169 public: | |
3170 void do_object(oop obj) { | |
3171 _task->deal_with_reference(obj); | |
3172 } | |
3173 | |
3174 CMObjectClosure(CMTask* task) : _task(task) { } | |
3175 }; | |
3176 | |
3177 // Closure for iterating over object fields | |
3178 class CMOopClosure : public OopClosure { | |
3179 private: | |
3180 G1CollectedHeap* _g1h; | |
3181 ConcurrentMark* _cm; | |
3182 CMTask* _task; | |
3183 | |
3184 public: | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
3185 virtual void do_oop(narrowOop* p) { do_oop_work(p); } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
3186 virtual void do_oop( oop* p) { do_oop_work(p); } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
3187 |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
3188 template <class T> void do_oop_work(T* p) { |
2152 | 3189 assert( _g1h->is_in_g1_reserved((HeapWord*) p), "invariant"); |
2361 | 3190 assert(!_g1h->is_on_master_free_list( |
2152 | 3191 _g1h->heap_region_containing((HeapWord*) p)), "invariant"); |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
3192 |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
3193 oop obj = oopDesc::load_decode_heap_oop(p); |
342 | 3194 if (_cm->verbose_high()) |
3195 gclog_or_tty->print_cr("[%d] we're looking at location " | |
3196 "*"PTR_FORMAT" = "PTR_FORMAT, | |
3197 _task->task_id(), p, (void*) obj); | |
3198 _task->deal_with_reference(obj); | |
3199 } | |
3200 | |
3201 CMOopClosure(G1CollectedHeap* g1h, | |
3202 ConcurrentMark* cm, | |
3203 CMTask* task) | |
1974
fd1d227ef1b9
6983204: G1: Nightly test nsk/regression/b4958615 failing with +ExplicitGCInvokesConcurrent
johnc
parents:
1972
diff
changeset
|
3204 : _g1h(g1h), _cm(cm), _task(task) |
fd1d227ef1b9
6983204: G1: Nightly test nsk/regression/b4958615 failing with +ExplicitGCInvokesConcurrent
johnc
parents:
1972
diff
changeset
|
3205 { |
2436 | 3206 assert(_ref_processor == NULL, "should be initialized to NULL"); |
3207 | |
3208 if (G1UseConcMarkReferenceProcessing) { | |
3209 _ref_processor = g1h->ref_processor(); | |
3210 assert(_ref_processor != NULL, "should not be NULL"); | |
3211 } | |
1974
fd1d227ef1b9
6983204: G1: Nightly test nsk/regression/b4958615 failing with +ExplicitGCInvokesConcurrent
johnc
parents:
1972
diff
changeset
|
3212 } |
342 | 3213 }; |
3214 | |
3215 void CMTask::setup_for_region(HeapRegion* hr) { | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3216 // Separated the asserts so that we know which one fires. |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3217 assert(hr != NULL, |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3218 "claim_region() should have filtered out continues humongous regions"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3219 assert(!hr->continuesHumongous(), |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3220 "claim_region() should have filtered out continues humongous regions"); |
342 | 3221 |
3222 if (_cm->verbose_low()) | |
3223 gclog_or_tty->print_cr("[%d] setting up for region "PTR_FORMAT, | |
3224 _task_id, hr); | |
3225 | |
3226 _curr_region = hr; | |
3227 _finger = hr->bottom(); | |
3228 update_region_limit(); | |
3229 } | |
3230 | |
3231 void CMTask::update_region_limit() { | |
3232 HeapRegion* hr = _curr_region; | |
3233 HeapWord* bottom = hr->bottom(); | |
3234 HeapWord* limit = hr->next_top_at_mark_start(); | |
3235 | |
3236 if (limit == bottom) { | |
3237 if (_cm->verbose_low()) | |
3238 gclog_or_tty->print_cr("[%d] found an empty region " | |
3239 "["PTR_FORMAT", "PTR_FORMAT")", | |
3240 _task_id, bottom, limit); | |
3241 // The region was collected underneath our feet. | |
3242 // We set the finger to bottom to ensure that the bitmap | |
3243 // iteration that will follow this will not do anything. | |
3244 // (this is not a condition that holds when we set the region up, | |
3245 // as the region is not supposed to be empty in the first place) | |
3246 _finger = bottom; | |
3247 } else if (limit >= _region_limit) { | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3248 assert(limit >= _finger, "peace of mind"); |
342 | 3249 } else { |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3250 assert(limit < _region_limit, "only way to get here"); |
342 | 3251 // This can happen under some pretty unusual circumstances. An |
3252 // evacuation pause empties the region underneath our feet (NTAMS | |
3253 // at bottom). We then do some allocation in the region (NTAMS | |
3254 // stays at bottom), followed by the region being used as a GC | |
3255 // alloc region (NTAMS will move to top() and the objects | |
3256 // originally below it will be grayed). All objects now marked in | |
3257 // the region are explicitly grayed, if below the global finger, | |
3258 // and we do not need in fact to scan anything else. So, we simply | |
3259 // set _finger to be limit to ensure that the bitmap iteration | |
3260 // doesn't do anything. | |
3261 _finger = limit; | |
3262 } | |
3263 | |
3264 _region_limit = limit; | |
3265 } | |
3266 | |
3267 void CMTask::giveup_current_region() { | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3268 assert(_curr_region != NULL, "invariant"); |
342 | 3269 if (_cm->verbose_low()) |
3270 gclog_or_tty->print_cr("[%d] giving up region "PTR_FORMAT, | |
3271 _task_id, _curr_region); | |
3272 clear_region_fields(); | |
3273 } | |
3274 | |
3275 void CMTask::clear_region_fields() { | |
3276 // Values for these three fields that indicate that we're not | |
3277 // holding on to a region. | |
3278 _curr_region = NULL; | |
3279 _finger = NULL; | |
3280 _region_limit = NULL; | |
3281 | |
3282 _region_finger = NULL; | |
3283 } | |
3284 | |
3285 void CMTask::reset(CMBitMap* nextMarkBitMap) { | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3286 guarantee(nextMarkBitMap != NULL, "invariant"); |
342 | 3287 |
3288 if (_cm->verbose_low()) | |
3289 gclog_or_tty->print_cr("[%d] resetting", _task_id); | |
3290 | |
3291 _nextMarkBitMap = nextMarkBitMap; | |
3292 clear_region_fields(); | |
1885
a5c514e74487
6988458: G1: assert(mr.end() <= _cm->finger()) failed: otherwise the region shouldn't be on the stack
johnc
parents:
1835
diff
changeset
|
3293 assert(_aborted_region.is_empty(), "should have been cleared"); |
342 | 3294 |
3295 _calls = 0; | |
3296 _elapsed_time_ms = 0.0; | |
3297 _termination_time_ms = 0.0; | |
3298 _termination_start_time_ms = 0.0; | |
3299 | |
3300 #if _MARKING_STATS_ | |
3301 _local_pushes = 0; | |
3302 _local_pops = 0; | |
3303 _local_max_size = 0; | |
3304 _objs_scanned = 0; | |
3305 _global_pushes = 0; | |
3306 _global_pops = 0; | |
3307 _global_max_size = 0; | |
3308 _global_transfers_to = 0; | |
3309 _global_transfers_from = 0; | |
3310 _region_stack_pops = 0; | |
3311 _regions_claimed = 0; | |
3312 _objs_found_on_bitmap = 0; | |
3313 _satb_buffers_processed = 0; | |
3314 _steal_attempts = 0; | |
3315 _steals = 0; | |
3316 _aborted = 0; | |
3317 _aborted_overflow = 0; | |
3318 _aborted_cm_aborted = 0; | |
3319 _aborted_yield = 0; | |
3320 _aborted_timed_out = 0; | |
3321 _aborted_satb = 0; | |
3322 _aborted_termination = 0; | |
3323 #endif // _MARKING_STATS_ | |
3324 } | |
3325 | |
3326 bool CMTask::should_exit_termination() { | |
3327 regular_clock_call(); | |
3328 // This is called when we are in the termination protocol. We should | |
3329 // quit if, for some reason, this task wants to abort or the global | |
3330 // stack is not empty (this means that we can get work from it). | |
3331 return !_cm->mark_stack_empty() || has_aborted(); | |
3332 } | |
3333 | |
3334 // This determines whether the method below will check both the local | |
3335 // and global fingers when determining whether to push on the stack a | |
3336 // gray object (value 1) or whether it will only check the global one | |
3337 // (value 0). The tradeoffs are that the former will be a bit more | |
3338 // accurate and possibly push less on the stack, but it might also be | |
3339 // a little bit slower. | |
3340 | |
3341 #define _CHECK_BOTH_FINGERS_ 1 | |
3342 | |
3343 void CMTask::deal_with_reference(oop obj) { | |
3344 if (_cm->verbose_high()) | |
3345 gclog_or_tty->print_cr("[%d] we're dealing with reference = "PTR_FORMAT, | |
3346 _task_id, (void*) obj); | |
3347 | |
3348 ++_refs_reached; | |
3349 | |
3350 HeapWord* objAddr = (HeapWord*) obj; | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
831
diff
changeset
|
3351 assert(obj->is_oop_or_null(true /* ignore mark word */), "Error"); |
342 | 3352 if (_g1h->is_in_g1_reserved(objAddr)) { |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3353 assert(obj != NULL, "is_in_g1_reserved should ensure this"); |
342 | 3354 HeapRegion* hr = _g1h->heap_region_containing(obj); |
3355 if (_g1h->is_obj_ill(obj, hr)) { | |
3356 if (_cm->verbose_high()) | |
3357 gclog_or_tty->print_cr("[%d] "PTR_FORMAT" is not considered marked", | |
3358 _task_id, (void*) obj); | |
3359 | |
3360 // we need to mark it first | |
3361 if (_nextMarkBitMap->parMark(objAddr)) { | |
3362 // No OrderAccess:store_load() is needed. It is implicit in the | |
3363 // CAS done in parMark(objAddr) above | |
3364 HeapWord* global_finger = _cm->finger(); | |
3365 | |
3366 #if _CHECK_BOTH_FINGERS_ | |
3367 // we will check both the local and global fingers | |
3368 | |
3369 if (_finger != NULL && objAddr < _finger) { | |
3370 if (_cm->verbose_high()) | |
3371 gclog_or_tty->print_cr("[%d] below the local finger ("PTR_FORMAT"), " | |
3372 "pushing it", _task_id, _finger); | |
3373 push(obj); | |
3374 } else if (_curr_region != NULL && objAddr < _region_limit) { | |
3375 // do nothing | |
3376 } else if (objAddr < global_finger) { | |
3377 // Notice that the global finger might be moving forward | |
3378 // concurrently. This is not a problem. In the worst case, we | |
3379 // mark the object while it is above the global finger and, by | |
3380 // the time we read the global finger, it has moved forward | |
3381 // passed this object. In this case, the object will probably | |
3382 // be visited when a task is scanning the region and will also | |
3383 // be pushed on the stack. So, some duplicate work, but no | |
3384 // correctness problems. | |
3385 | |
3386 if (_cm->verbose_high()) | |
3387 gclog_or_tty->print_cr("[%d] below the global finger " | |
3388 "("PTR_FORMAT"), pushing it", | |
3389 _task_id, global_finger); | |
3390 push(obj); | |
3391 } else { | |
3392 // do nothing | |
3393 } | |
3394 #else // _CHECK_BOTH_FINGERS_ | |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
3395 // we will only check the global finger |
342 | 3396 |
3397 if (objAddr < global_finger) { | |
3398 // see long comment above | |
3399 | |
3400 if (_cm->verbose_high()) | |
3401 gclog_or_tty->print_cr("[%d] below the global finger " | |
3402 "("PTR_FORMAT"), pushing it", | |
3403 _task_id, global_finger); | |
3404 push(obj); | |
3405 } | |
3406 #endif // _CHECK_BOTH_FINGERS_ | |
3407 } | |
3408 } | |
3409 } | |
3410 } | |
3411 | |
3412 void CMTask::push(oop obj) { | |
3413 HeapWord* objAddr = (HeapWord*) obj; | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3414 assert(_g1h->is_in_g1_reserved(objAddr), "invariant"); |
2361 | 3415 assert(!_g1h->is_on_master_free_list( |
2152 | 3416 _g1h->heap_region_containing((HeapWord*) objAddr)), "invariant"); |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3417 assert(!_g1h->is_obj_ill(obj), "invariant"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3418 assert(_nextMarkBitMap->isMarked(objAddr), "invariant"); |
342 | 3419 |
3420 if (_cm->verbose_high()) | |
3421 gclog_or_tty->print_cr("[%d] pushing "PTR_FORMAT, _task_id, (void*) obj); | |
3422 | |
3423 if (!_task_queue->push(obj)) { | |
3424 // The local task queue looks full. We need to push some entries | |
3425 // to the global stack. | |
3426 | |
3427 if (_cm->verbose_medium()) | |
3428 gclog_or_tty->print_cr("[%d] task queue overflow, " | |
3429 "moving entries to the global stack", | |
3430 _task_id); | |
3431 move_entries_to_global_stack(); | |
3432 | |
3433 // this should succeed since, even if we overflow the global | |
3434 // stack, we should have definitely removed some entries from the | |
3435 // local queue. So, there must be space on it. | |
3436 bool success = _task_queue->push(obj); | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3437 assert(success, "invariant"); |
342 | 3438 } |
3439 | |
3440 statsOnly( int tmp_size = _task_queue->size(); | |
3441 if (tmp_size > _local_max_size) | |
3442 _local_max_size = tmp_size; | |
3443 ++_local_pushes ); | |
3444 } | |
3445 | |
3446 void CMTask::reached_limit() { | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3447 assert(_words_scanned >= _words_scanned_limit || |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3448 _refs_reached >= _refs_reached_limit , |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3449 "shouldn't have been called otherwise"); |
342 | 3450 regular_clock_call(); |
3451 } | |
3452 | |
3453 void CMTask::regular_clock_call() { | |
3454 if (has_aborted()) | |
3455 return; | |
3456 | |
3457 // First, we need to recalculate the words scanned and refs reached | |
3458 // limits for the next clock call. | |
3459 recalculate_limits(); | |
3460 | |
3461 // During the regular clock call we do the following | |
3462 | |
3463 // (1) If an overflow has been flagged, then we abort. | |
3464 if (_cm->has_overflown()) { | |
3465 set_has_aborted(); | |
3466 return; | |
3467 } | |
3468 | |
3469 // If we are not concurrent (i.e. we're doing remark) we don't need | |
3470 // to check anything else. The other steps are only needed during | |
3471 // the concurrent marking phase. | |
3472 if (!concurrent()) | |
3473 return; | |
3474 | |
3475 // (2) If marking has been aborted for Full GC, then we also abort. | |
3476 if (_cm->has_aborted()) { | |
3477 set_has_aborted(); | |
3478 statsOnly( ++_aborted_cm_aborted ); | |
3479 return; | |
3480 } | |
3481 | |
3482 double curr_time_ms = os::elapsedVTime() * 1000.0; | |
3483 | |
3484 // (3) If marking stats are enabled, then we update the step history. | |
3485 #if _MARKING_STATS_ | |
3486 if (_words_scanned >= _words_scanned_limit) | |
3487 ++_clock_due_to_scanning; | |
3488 if (_refs_reached >= _refs_reached_limit) | |
3489 ++_clock_due_to_marking; | |
3490 | |
3491 double last_interval_ms = curr_time_ms - _interval_start_time_ms; | |
3492 _interval_start_time_ms = curr_time_ms; | |
3493 _all_clock_intervals_ms.add(last_interval_ms); | |
3494 | |
3495 if (_cm->verbose_medium()) { | |
3496 gclog_or_tty->print_cr("[%d] regular clock, interval = %1.2lfms, " | |
3497 "scanned = %d%s, refs reached = %d%s", | |
3498 _task_id, last_interval_ms, | |
3499 _words_scanned, | |
3500 (_words_scanned >= _words_scanned_limit) ? " (*)" : "", | |
3501 _refs_reached, | |
3502 (_refs_reached >= _refs_reached_limit) ? " (*)" : ""); | |
3503 } | |
3504 #endif // _MARKING_STATS_ | |
3505 | |
3506 // (4) We check whether we should yield. If we have to, then we abort. | |
3507 if (_cm->should_yield()) { | |
3508 // We should yield. To do this we abort the task. The caller is | |
3509 // responsible for yielding. | |
3510 set_has_aborted(); | |
3511 statsOnly( ++_aborted_yield ); | |
3512 return; | |
3513 } | |
3514 | |
3515 // (5) We check whether we've reached our time quota. If we have, | |
3516 // then we abort. | |
3517 double elapsed_time_ms = curr_time_ms - _start_time_ms; | |
3518 if (elapsed_time_ms > _time_target_ms) { | |
3519 set_has_aborted(); | |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
3520 _has_timed_out = true; |
342 | 3521 statsOnly( ++_aborted_timed_out ); |
3522 return; | |
3523 } | |
3524 | |
3525 // (6) Finally, we check whether there are enough completed STAB | |
3526 // buffers available for processing. If there are, we abort. | |
3527 SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); | |
3528 if (!_draining_satb_buffers && satb_mq_set.process_completed_buffers()) { | |
3529 if (_cm->verbose_low()) | |
3530 gclog_or_tty->print_cr("[%d] aborting to deal with pending SATB buffers", | |
3531 _task_id); | |
3532 // we do need to process SATB buffers, we'll abort and restart | |
3533 // the marking task to do so | |
3534 set_has_aborted(); | |
3535 statsOnly( ++_aborted_satb ); | |
3536 return; | |
3537 } | |
3538 } | |
3539 | |
3540 void CMTask::recalculate_limits() { | |
3541 _real_words_scanned_limit = _words_scanned + words_scanned_period; | |
3542 _words_scanned_limit = _real_words_scanned_limit; | |
3543 | |
3544 _real_refs_reached_limit = _refs_reached + refs_reached_period; | |
3545 _refs_reached_limit = _real_refs_reached_limit; | |
3546 } | |
3547 | |
3548 void CMTask::decrease_limits() { | |
3549 // This is called when we believe that we're going to do an infrequent | |
3550 // operation which will increase the per byte scanned cost (i.e. move | |
3551 // entries to/from the global stack). It basically tries to decrease the | |
3552 // scanning limit so that the clock is called earlier. | |
3553 | |
3554 if (_cm->verbose_medium()) | |
3555 gclog_or_tty->print_cr("[%d] decreasing limits", _task_id); | |
3556 | |
3557 _words_scanned_limit = _real_words_scanned_limit - | |
3558 3 * words_scanned_period / 4; | |
3559 _refs_reached_limit = _real_refs_reached_limit - | |
3560 3 * refs_reached_period / 4; | |
3561 } | |
3562 | |
3563 void CMTask::move_entries_to_global_stack() { | |
3564 // local array where we'll store the entries that will be popped | |
3565 // from the local queue | |
3566 oop buffer[global_stack_transfer_size]; | |
3567 | |
3568 int n = 0; | |
3569 oop obj; | |
3570 while (n < global_stack_transfer_size && _task_queue->pop_local(obj)) { | |
3571 buffer[n] = obj; | |
3572 ++n; | |
3573 } | |
3574 | |
3575 if (n > 0) { | |
3576 // we popped at least one entry from the local queue | |
3577 | |
3578 statsOnly( ++_global_transfers_to; _local_pops += n ); | |
3579 | |
3580 if (!_cm->mark_stack_push(buffer, n)) { | |
3581 if (_cm->verbose_low()) | |
3582 gclog_or_tty->print_cr("[%d] aborting due to global stack overflow", _task_id); | |
3583 set_has_aborted(); | |
3584 } else { | |
3585 // the transfer was successful | |
3586 | |
3587 if (_cm->verbose_medium()) | |
3588 gclog_or_tty->print_cr("[%d] pushed %d entries to the global stack", | |
3589 _task_id, n); | |
3590 statsOnly( int tmp_size = _cm->mark_stack_size(); | |
3591 if (tmp_size > _global_max_size) | |
3592 _global_max_size = tmp_size; | |
3593 _global_pushes += n ); | |
3594 } | |
3595 } | |
3596 | |
3597 // this operation was quite expensive, so decrease the limits | |
3598 decrease_limits(); | |
3599 } | |
3600 | |
3601 void CMTask::get_entries_from_global_stack() { | |
3602 // local array where we'll store the entries that will be popped | |
3603 // from the global stack. | |
3604 oop buffer[global_stack_transfer_size]; | |
3605 int n; | |
3606 _cm->mark_stack_pop(buffer, global_stack_transfer_size, &n); | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3607 assert(n <= global_stack_transfer_size, |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3608 "we should not pop more than the given limit"); |
342 | 3609 if (n > 0) { |
3610 // yes, we did actually pop at least one entry | |
3611 | |
3612 statsOnly( ++_global_transfers_from; _global_pops += n ); | |
3613 if (_cm->verbose_medium()) | |
3614 gclog_or_tty->print_cr("[%d] popped %d entries from the global stack", | |
3615 _task_id, n); | |
3616 for (int i = 0; i < n; ++i) { | |
3617 bool success = _task_queue->push(buffer[i]); | |
3618 // We only call this when the local queue is empty or under a | |
3619 // given target limit. So, we do not expect this push to fail. | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3620 assert(success, "invariant"); |
342 | 3621 } |
3622 | |
3623 statsOnly( int tmp_size = _task_queue->size(); | |
3624 if (tmp_size > _local_max_size) | |
3625 _local_max_size = tmp_size; | |
3626 _local_pushes += n ); | |
3627 } | |
3628 | |
3629 // this operation was quite expensive, so decrease the limits | |
3630 decrease_limits(); | |
3631 } | |
3632 | |
3633 void CMTask::drain_local_queue(bool partially) { | |
3634 if (has_aborted()) | |
3635 return; | |
3636 | |
3637 // Decide what the target size is, depending whether we're going to | |
3638 // drain it partially (so that other tasks can steal if they run out | |
3639 // of things to do) or totally (at the very end). | |
3640 size_t target_size; | |
3641 if (partially) | |
3642 target_size = MIN2((size_t)_task_queue->max_elems()/3, GCDrainStackTargetSize); | |
3643 else | |
3644 target_size = 0; | |
3645 | |
3646 if (_task_queue->size() > target_size) { | |
3647 if (_cm->verbose_high()) | |
3648 gclog_or_tty->print_cr("[%d] draining local queue, target size = %d", | |
3649 _task_id, target_size); | |
3650 | |
3651 oop obj; | |
3652 bool ret = _task_queue->pop_local(obj); | |
3653 while (ret) { | |
3654 statsOnly( ++_local_pops ); | |
3655 | |
3656 if (_cm->verbose_high()) | |
3657 gclog_or_tty->print_cr("[%d] popped "PTR_FORMAT, _task_id, | |
3658 (void*) obj); | |
3659 | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3660 assert(_g1h->is_in_g1_reserved((HeapWord*) obj), "invariant" ); |
2361 | 3661 assert(!_g1h->is_on_master_free_list( |
2152 | 3662 _g1h->heap_region_containing((HeapWord*) obj)), "invariant"); |
342 | 3663 |
3664 scan_object(obj); | |
3665 | |
3666 if (_task_queue->size() <= target_size || has_aborted()) | |
3667 ret = false; | |
3668 else | |
3669 ret = _task_queue->pop_local(obj); | |
3670 } | |
3671 | |
3672 if (_cm->verbose_high()) | |
3673 gclog_or_tty->print_cr("[%d] drained local queue, size = %d", | |
3674 _task_id, _task_queue->size()); | |
3675 } | |
3676 } | |
3677 | |
3678 void CMTask::drain_global_stack(bool partially) { | |
3679 if (has_aborted()) | |
3680 return; | |
3681 | |
3682 // We have a policy to drain the local queue before we attempt to | |
3683 // drain the global stack. | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3684 assert(partially || _task_queue->size() == 0, "invariant"); |
342 | 3685 |
3686 // Decide what the target size is, depending whether we're going to | |
3687 // drain it partially (so that other tasks can steal if they run out | |
3688 // of things to do) or totally (at the very end). Notice that, | |
3689 // because we move entries from the global stack in chunks or | |
3690 // because another task might be doing the same, we might in fact | |
3691 // drop below the target. But, this is not a problem. | |
3692 size_t target_size; | |
3693 if (partially) | |
3694 target_size = _cm->partial_mark_stack_size_target(); | |
3695 else | |
3696 target_size = 0; | |
3697 | |
3698 if (_cm->mark_stack_size() > target_size) { | |
3699 if (_cm->verbose_low()) | |
3700 gclog_or_tty->print_cr("[%d] draining global_stack, target size %d", | |
3701 _task_id, target_size); | |
3702 | |
3703 while (!has_aborted() && _cm->mark_stack_size() > target_size) { | |
3704 get_entries_from_global_stack(); | |
3705 drain_local_queue(partially); | |
3706 } | |
3707 | |
3708 if (_cm->verbose_low()) | |
3709 gclog_or_tty->print_cr("[%d] drained global stack, size = %d", | |
3710 _task_id, _cm->mark_stack_size()); | |
3711 } | |
3712 } | |
3713 | |
3714 // SATB Queue has several assumptions on whether to call the par or | |
3715 // non-par versions of the methods. this is why some of the code is | |
3716 // replicated. We should really get rid of the single-threaded version | |
3717 // of the code to simplify things. | |
3718 void CMTask::drain_satb_buffers() { | |
3719 if (has_aborted()) | |
3720 return; | |
3721 | |
3722 // We set this so that the regular clock knows that we're in the | |
3723 // middle of draining buffers and doesn't set the abort flag when it | |
3724 // notices that SATB buffers are available for draining. It'd be | |
3725 // very counter productive if it did that. :-) | |
3726 _draining_satb_buffers = true; | |
3727 | |
3728 CMObjectClosure oc(this); | |
3729 SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); | |
1833
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1719
diff
changeset
|
3730 if (G1CollectedHeap::use_parallel_gc_threads()) |
342 | 3731 satb_mq_set.set_par_closure(_task_id, &oc); |
3732 else | |
3733 satb_mq_set.set_closure(&oc); | |
3734 | |
3735 // This keeps claiming and applying the closure to completed buffers | |
3736 // until we run out of buffers or we need to abort. | |
1833
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1719
diff
changeset
|
3737 if (G1CollectedHeap::use_parallel_gc_threads()) { |
342 | 3738 while (!has_aborted() && |
3739 satb_mq_set.par_apply_closure_to_completed_buffer(_task_id)) { | |
3740 if (_cm->verbose_medium()) | |
3741 gclog_or_tty->print_cr("[%d] processed an SATB buffer", _task_id); | |
3742 statsOnly( ++_satb_buffers_processed ); | |
3743 regular_clock_call(); | |
3744 } | |
3745 } else { | |
3746 while (!has_aborted() && | |
3747 satb_mq_set.apply_closure_to_completed_buffer()) { | |
3748 if (_cm->verbose_medium()) | |
3749 gclog_or_tty->print_cr("[%d] processed an SATB buffer", _task_id); | |
3750 statsOnly( ++_satb_buffers_processed ); | |
3751 regular_clock_call(); | |
3752 } | |
3753 } | |
3754 | |
3755 if (!concurrent() && !has_aborted()) { | |
3756 // We should only do this during remark. | |
1833
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1719
diff
changeset
|
3757 if (G1CollectedHeap::use_parallel_gc_threads()) |
342 | 3758 satb_mq_set.par_iterate_closure_all_threads(_task_id); |
3759 else | |
3760 satb_mq_set.iterate_closure_all_threads(); | |
3761 } | |
3762 | |
3763 _draining_satb_buffers = false; | |
3764 | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3765 assert(has_aborted() || |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3766 concurrent() || |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3767 satb_mq_set.completed_buffers_num() == 0, "invariant"); |
342 | 3768 |
1833
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1719
diff
changeset
|
3769 if (G1CollectedHeap::use_parallel_gc_threads()) |
342 | 3770 satb_mq_set.set_par_closure(_task_id, NULL); |
3771 else | |
3772 satb_mq_set.set_closure(NULL); | |
3773 | |
3774 // again, this was a potentially expensive operation, decrease the | |
3775 // limits to get the regular clock call early | |
3776 decrease_limits(); | |
3777 } | |
3778 | |
3779 void CMTask::drain_region_stack(BitMapClosure* bc) { | |
3780 if (has_aborted()) | |
3781 return; | |
3782 | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3783 assert(_region_finger == NULL, |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3784 "it should be NULL when we're not scanning a region"); |
342 | 3785 |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3786 if (!_cm->region_stack_empty() || !_aborted_region.is_empty()) { |
342 | 3787 if (_cm->verbose_low()) |
3788 gclog_or_tty->print_cr("[%d] draining region stack, size = %d", | |
3789 _task_id, _cm->region_stack_size()); | |
3790 | |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3791 MemRegion mr; |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3792 |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3793 if (!_aborted_region.is_empty()) { |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3794 mr = _aborted_region; |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3795 _aborted_region = MemRegion(); |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3796 |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3797 if (_cm->verbose_low()) |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3798 gclog_or_tty->print_cr("[%d] scanning aborted region [ " PTR_FORMAT ", " PTR_FORMAT " )", |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3799 _task_id, mr.start(), mr.end()); |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3800 } else { |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3801 mr = _cm->region_stack_pop_lock_free(); |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3802 // it returns MemRegion() if the pop fails |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3803 statsOnly(if (mr.start() != NULL) ++_region_stack_pops ); |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3804 } |
342 | 3805 |
3806 while (mr.start() != NULL) { | |
3807 if (_cm->verbose_medium()) | |
3808 gclog_or_tty->print_cr("[%d] we are scanning region " | |
3809 "["PTR_FORMAT", "PTR_FORMAT")", | |
3810 _task_id, mr.start(), mr.end()); | |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3811 |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3812 assert(mr.end() <= _cm->finger(), |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3813 "otherwise the region shouldn't be on the stack"); |
342 | 3814 assert(!mr.is_empty(), "Only non-empty regions live on the region stack"); |
3815 if (_nextMarkBitMap->iterate(bc, mr)) { | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3816 assert(!has_aborted(), |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3817 "cannot abort the task without aborting the bitmap iteration"); |
342 | 3818 |
3819 // We finished iterating over the region without aborting. | |
3820 regular_clock_call(); | |
3821 if (has_aborted()) | |
3822 mr = MemRegion(); | |
3823 else { | |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3824 mr = _cm->region_stack_pop_lock_free(); |
342 | 3825 // it returns MemRegion() if the pop fails |
3826 statsOnly(if (mr.start() != NULL) ++_region_stack_pops ); | |
3827 } | |
3828 } else { | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3829 assert(has_aborted(), "currently the only way to do so"); |
342 | 3830 |
3831 // The only way to abort the bitmap iteration is to return | |
3832 // false from the do_bit() method. However, inside the | |
3833 // do_bit() method we move the _region_finger to point to the | |
3834 // object currently being looked at. So, if we bail out, we | |
3835 // have definitely set _region_finger to something non-null. | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
3836 assert(_region_finger != NULL, "invariant"); |
342 | 3837 |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3838 // Make sure that any previously aborted region has been |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3839 // cleared. |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3840 assert(_aborted_region.is_empty(), "aborted region not cleared"); |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3841 |
342 | 3842 // The iteration was actually aborted. So now _region_finger |
3843 // points to the address of the object we last scanned. If we | |
3844 // leave it there, when we restart this task, we will rescan | |
3845 // the object. It is easy to avoid this. We move the finger by | |
3846 // enough to point to the next possible object header (the | |
3847 // bitmap knows by how much we need to move it as it knows its | |
3848 // granularity). | |
3849 MemRegion newRegion = | |
3850 MemRegion(_nextMarkBitMap->nextWord(_region_finger), mr.end()); | |
3851 | |
3852 if (!newRegion.is_empty()) { | |
3853 if (_cm->verbose_low()) { | |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3854 gclog_or_tty->print_cr("[%d] recording unscanned region" |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3855 "[" PTR_FORMAT "," PTR_FORMAT ") in CMTask", |
342 | 3856 _task_id, |
3857 newRegion.start(), newRegion.end()); | |
3858 } | |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3859 // Now record the part of the region we didn't scan to |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3860 // make sure this task scans it later. |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
3861 _aborted_region = newRegion; |
342 | 3862 } |
3863 // break from while | |
3864 mr = MemRegion(); | |
3865 } | |
3866 _region_finger = NULL; | |
3867 } | |
3868 | |
3869 if (_cm->verbose_low()) | |
3870 gclog_or_tty->print_cr("[%d] drained region stack, size = %d", | |
3871 _task_id, _cm->region_stack_size()); | |
3872 } | |
3873 } | |
3874 | |
3875 void CMTask::print_stats() { | |
3876 gclog_or_tty->print_cr("Marking Stats, task = %d, calls = %d", | |
3877 _task_id, _calls); | |
3878 gclog_or_tty->print_cr(" Elapsed time = %1.2lfms, Termination time = %1.2lfms", | |
3879 _elapsed_time_ms, _termination_time_ms); | |
3880 gclog_or_tty->print_cr(" Step Times (cum): num = %d, avg = %1.2lfms, sd = %1.2lfms", | |
3881 _step_times_ms.num(), _step_times_ms.avg(), | |
3882 _step_times_ms.sd()); | |
3883 gclog_or_tty->print_cr(" max = %1.2lfms, total = %1.2lfms", | |
3884 _step_times_ms.maximum(), _step_times_ms.sum()); | |
3885 | |
3886 #if _MARKING_STATS_ | |
3887 gclog_or_tty->print_cr(" Clock Intervals (cum): num = %d, avg = %1.2lfms, sd = %1.2lfms", | |
3888 _all_clock_intervals_ms.num(), _all_clock_intervals_ms.avg(), | |
3889 _all_clock_intervals_ms.sd()); | |
3890 gclog_or_tty->print_cr(" max = %1.2lfms, total = %1.2lfms", | |
3891 _all_clock_intervals_ms.maximum(), | |
3892 _all_clock_intervals_ms.sum()); | |
3893 gclog_or_tty->print_cr(" Clock Causes (cum): scanning = %d, marking = %d", | |
3894 _clock_due_to_scanning, _clock_due_to_marking); | |
3895 gclog_or_tty->print_cr(" Objects: scanned = %d, found on the bitmap = %d", | |
3896 _objs_scanned, _objs_found_on_bitmap); | |
3897 gclog_or_tty->print_cr(" Local Queue: pushes = %d, pops = %d, max size = %d", | |
3898 _local_pushes, _local_pops, _local_max_size); | |
3899 gclog_or_tty->print_cr(" Global Stack: pushes = %d, pops = %d, max size = %d", | |
3900 _global_pushes, _global_pops, _global_max_size); | |
3901 gclog_or_tty->print_cr(" transfers to = %d, transfers from = %d", | |
3902 _global_transfers_to,_global_transfers_from); | |
3903 gclog_or_tty->print_cr(" Regions: claimed = %d, Region Stack: pops = %d", | |
3904 _regions_claimed, _region_stack_pops); | |
3905 gclog_or_tty->print_cr(" SATB buffers: processed = %d", _satb_buffers_processed); | |
3906 gclog_or_tty->print_cr(" Steals: attempts = %d, successes = %d", | |
3907 _steal_attempts, _steals); | |
3908 gclog_or_tty->print_cr(" Aborted: %d, due to", _aborted); | |
3909 gclog_or_tty->print_cr(" overflow: %d, global abort: %d, yield: %d", | |
3910 _aborted_overflow, _aborted_cm_aborted, _aborted_yield); | |
3911 gclog_or_tty->print_cr(" time out: %d, SATB: %d, termination: %d", | |
3912 _aborted_timed_out, _aborted_satb, _aborted_termination); | |
3913 #endif // _MARKING_STATS_ | |
3914 } | |
3915 | |
3916 /***************************************************************************** | |
3917 | |
3918 The do_marking_step(time_target_ms) method is the building block | |
3919 of the parallel marking framework. It can be called in parallel | |
3920 with other invocations of do_marking_step() on different tasks | |
3921 (but only one per task, obviously) and concurrently with the | |
3922 mutator threads, or during remark, hence it eliminates the need | |
3923 for two versions of the code. When called during remark, it will | |
3924 pick up from where the task left off during the concurrent marking | |
3925 phase. Interestingly, tasks are also claimable during evacuation | |
3926 pauses too, since do_marking_step() ensures that it aborts before | |
3927 it needs to yield. | |
3928 | |
3929 The data structures that is uses to do marking work are the | |
3930 following: | |
3931 | |
3932 (1) Marking Bitmap. If there are gray objects that appear only | |
3933 on the bitmap (this happens either when dealing with an overflow | |
3934 or when the initial marking phase has simply marked the roots | |
3935 and didn't push them on the stack), then tasks claim heap | |
3936 regions whose bitmap they then scan to find gray objects. A | |
3937 global finger indicates where the end of the last claimed region | |
3938 is. A local finger indicates how far into the region a task has | |
3939 scanned. The two fingers are used to determine how to gray an | |
3940 object (i.e. whether simply marking it is OK, as it will be | |
3941 visited by a task in the future, or whether it needs to be also | |
3942 pushed on a stack). | |
3943 | |
3944 (2) Local Queue. The local queue of the task which is accessed | |
3945 reasonably efficiently by the task. Other tasks can steal from | |
3946 it when they run out of work. Throughout the marking phase, a | |
3947 task attempts to keep its local queue short but not totally | |
3948 empty, so that entries are available for stealing by other | |
3949 tasks. Only when there is no more work, a task will totally | |
3950 drain its local queue. | |
3951 | |
3952 (3) Global Mark Stack. This handles local queue overflow. During | |
3953 marking only sets of entries are moved between it and the local | |
3954 queues, as access to it requires a mutex and more fine-grain | |
3955 interaction with it which might cause contention. If it | |
3956 overflows, then the marking phase should restart and iterate | |
3957 over the bitmap to identify gray objects. Throughout the marking | |
3958 phase, tasks attempt to keep the global mark stack at a small | |
3959 length but not totally empty, so that entries are available for | |
3960 popping by other tasks. Only when there is no more work, tasks | |
3961 will totally drain the global mark stack. | |
3962 | |
3963 (4) Global Region Stack. Entries on it correspond to areas of | |
3964 the bitmap that need to be scanned since they contain gray | |
3965 objects. Pushes on the region stack only happen during | |
3966 evacuation pauses and typically correspond to areas covered by | |
3967 GC LABS. If it overflows, then the marking phase should restart | |
3968 and iterate over the bitmap to identify gray objects. Tasks will | |
3969 try to totally drain the region stack as soon as possible. | |
3970 | |
3971 (5) SATB Buffer Queue. This is where completed SATB buffers are | |
3972 made available. Buffers are regularly removed from this queue | |
3973 and scanned for roots, so that the queue doesn't get too | |
3974 long. During remark, all completed buffers are processed, as | |
3975 well as the filled in parts of any uncompleted buffers. | |
3976 | |
3977 The do_marking_step() method tries to abort when the time target | |
3978 has been reached. There are a few other cases when the | |
3979 do_marking_step() method also aborts: | |
3980 | |
3981 (1) When the marking phase has been aborted (after a Full GC). | |
3982 | |
3983 (2) When a global overflow (either on the global stack or the | |
3984 region stack) has been triggered. Before the task aborts, it | |
3985 will actually sync up with the other tasks to ensure that all | |
3986 the marking data structures (local queues, stacks, fingers etc.) | |
3987 are re-initialised so that when do_marking_step() completes, | |
3988 the marking phase can immediately restart. | |
3989 | |
3990 (3) When enough completed SATB buffers are available. The | |
3991 do_marking_step() method only tries to drain SATB buffers right | |
3992 at the beginning. So, if enough buffers are available, the | |
3993 marking step aborts and the SATB buffers are processed at | |
3994 the beginning of the next invocation. | |
3995 | |
3996 (4) To yield. when we have to yield then we abort and yield | |
3997 right at the end of do_marking_step(). This saves us from a lot | |
3998 of hassle as, by yielding we might allow a Full GC. If this | |
3999 happens then objects will be compacted underneath our feet, the | |
4000 heap might shrink, etc. We save checking for this by just | |
4001 aborting and doing the yield right at the end. | |
4002 | |
4003 From the above it follows that the do_marking_step() method should | |
4004 be called in a loop (or, otherwise, regularly) until it completes. | |
4005 | |
4006 If a marking step completes without its has_aborted() flag being | |
4007 true, it means it has completed the current marking phase (and | |
4008 also all other marking tasks have done so and have all synced up). | |
4009 | |
4010 A method called regular_clock_call() is invoked "regularly" (in | |
4011 sub ms intervals) throughout marking. It is this clock method that | |
4012 checks all the abort conditions which were mentioned above and | |
4013 decides when the task should abort. A work-based scheme is used to | |
4014 trigger this clock method: when the number of object words the | |
4015 marking phase has scanned or the number of references the marking | |
4016 phase has visited reach a given limit. Additional invocations to | |
4017 the method clock have been planted in a few other strategic places | |
4018 too. The initial reason for the clock method was to avoid calling | |
4019 vtime too regularly, as it is quite expensive. So, once it was in | |
4020 place, it was natural to piggy-back all the other conditions on it | |
4021 too and not constantly check them throughout the code. | |
4022 | |
4023 *****************************************************************************/ | |
4024 | |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
4025 void CMTask::do_marking_step(double time_target_ms, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
4026 bool do_stealing, |
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
4027 bool do_termination) { |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4028 assert(time_target_ms >= 1.0, "minimum granularity is 1ms"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4029 assert(concurrent() == _cm->concurrent(), "they should be the same"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4030 |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4031 assert(concurrent() || _cm->region_stack_empty(), |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4032 "the region stack should have been cleared before remark"); |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
4033 assert(concurrent() || !_cm->has_aborted_regions(), |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
4034 "aborted regions should have been cleared before remark"); |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4035 assert(_region_finger == NULL, |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4036 "this should be non-null only when a region is being scanned"); |
342 | 4037 |
4038 G1CollectorPolicy* g1_policy = _g1h->g1_policy(); | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4039 assert(_task_queues != NULL, "invariant"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4040 assert(_task_queue != NULL, "invariant"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4041 assert(_task_queues->queue(_task_id) == _task_queue, "invariant"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4042 |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4043 assert(!_claimed, |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4044 "only one thread should claim this task at any one time"); |
342 | 4045 |
4046 // OK, this doesn't safeguard again all possible scenarios, as it is | |
4047 // possible for two threads to set the _claimed flag at the same | |
4048 // time. But it is only for debugging purposes anyway and it will | |
4049 // catch most problems. | |
4050 _claimed = true; | |
4051 | |
4052 _start_time_ms = os::elapsedVTime() * 1000.0; | |
4053 statsOnly( _interval_start_time_ms = _start_time_ms ); | |
4054 | |
4055 double diff_prediction_ms = | |
4056 g1_policy->get_new_prediction(&_marking_step_diffs_ms); | |
4057 _time_target_ms = time_target_ms - diff_prediction_ms; | |
4058 | |
4059 // set up the variables that are used in the work-based scheme to | |
4060 // call the regular clock method | |
4061 _words_scanned = 0; | |
4062 _refs_reached = 0; | |
4063 recalculate_limits(); | |
4064 | |
4065 // clear all flags | |
4066 clear_has_aborted(); | |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
4067 _has_timed_out = false; |
342 | 4068 _draining_satb_buffers = false; |
4069 | |
4070 ++_calls; | |
4071 | |
4072 if (_cm->verbose_low()) | |
4073 gclog_or_tty->print_cr("[%d] >>>>>>>>>> START, call = %d, " | |
4074 "target = %1.2lfms >>>>>>>>>>", | |
4075 _task_id, _calls, _time_target_ms); | |
4076 | |
4077 // Set up the bitmap and oop closures. Anything that uses them is | |
4078 // eventually called from this method, so it is OK to allocate these | |
4079 // statically. | |
4080 CMBitMapClosure bitmap_closure(this, _cm, _nextMarkBitMap); | |
4081 CMOopClosure oop_closure(_g1h, _cm, this); | |
4082 set_oop_closure(&oop_closure); | |
4083 | |
4084 if (_cm->has_overflown()) { | |
4085 // This can happen if the region stack or the mark stack overflows | |
4086 // during a GC pause and this task, after a yield point, | |
4087 // restarts. We have to abort as we need to get into the overflow | |
4088 // protocol which happens right at the end of this task. | |
4089 set_has_aborted(); | |
4090 } | |
4091 | |
4092 // First drain any available SATB buffers. After this, we will not | |
4093 // look at SATB buffers before the next invocation of this method. | |
4094 // If enough completed SATB buffers are queued up, the regular clock | |
4095 // will abort this task so that it restarts. | |
4096 drain_satb_buffers(); | |
4097 // ...then partially drain the local queue and the global stack | |
4098 drain_local_queue(true); | |
4099 drain_global_stack(true); | |
4100 | |
4101 // Then totally drain the region stack. We will not look at | |
4102 // it again before the next invocation of this method. Entries on | |
4103 // the region stack are only added during evacuation pauses, for | |
4104 // which we have to yield. When we do, we abort the task anyway so | |
4105 // it will look at the region stack again when it restarts. | |
4106 bitmap_closure.set_scanning_heap_region(false); | |
4107 drain_region_stack(&bitmap_closure); | |
4108 // ...then partially drain the local queue and the global stack | |
4109 drain_local_queue(true); | |
4110 drain_global_stack(true); | |
4111 | |
4112 do { | |
4113 if (!has_aborted() && _curr_region != NULL) { | |
4114 // This means that we're already holding on to a region. | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4115 assert(_finger != NULL, "if region is not NULL, then the finger " |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4116 "should not be NULL either"); |
342 | 4117 |
4118 // We might have restarted this task after an evacuation pause | |
4119 // which might have evacuated the region we're holding on to | |
4120 // underneath our feet. Let's read its limit again to make sure | |
4121 // that we do not iterate over a region of the heap that | |
4122 // contains garbage (update_region_limit() will also move | |
4123 // _finger to the start of the region if it is found empty). | |
4124 update_region_limit(); | |
4125 // We will start from _finger not from the start of the region, | |
4126 // as we might be restarting this task after aborting half-way | |
4127 // through scanning this region. In this case, _finger points to | |
4128 // the address where we last found a marked object. If this is a | |
4129 // fresh region, _finger points to start(). | |
4130 MemRegion mr = MemRegion(_finger, _region_limit); | |
4131 | |
4132 if (_cm->verbose_low()) | |
4133 gclog_or_tty->print_cr("[%d] we're scanning part " | |
4134 "["PTR_FORMAT", "PTR_FORMAT") " | |
4135 "of region "PTR_FORMAT, | |
4136 _task_id, _finger, _region_limit, _curr_region); | |
4137 | |
4138 // Let's iterate over the bitmap of the part of the | |
4139 // region that is left. | |
4140 bitmap_closure.set_scanning_heap_region(true); | |
4141 if (mr.is_empty() || | |
4142 _nextMarkBitMap->iterate(&bitmap_closure, mr)) { | |
4143 // We successfully completed iterating over the region. Now, | |
4144 // let's give up the region. | |
4145 giveup_current_region(); | |
4146 regular_clock_call(); | |
4147 } else { | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4148 assert(has_aborted(), "currently the only way to do so"); |
342 | 4149 // The only way to abort the bitmap iteration is to return |
4150 // false from the do_bit() method. However, inside the | |
4151 // do_bit() method we move the _finger to point to the | |
4152 // object currently being looked at. So, if we bail out, we | |
4153 // have definitely set _finger to something non-null. | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4154 assert(_finger != NULL, "invariant"); |
342 | 4155 |
4156 // Region iteration was actually aborted. So now _finger | |
4157 // points to the address of the object we last scanned. If we | |
4158 // leave it there, when we restart this task, we will rescan | |
4159 // the object. It is easy to avoid this. We move the finger by | |
4160 // enough to point to the next possible object header (the | |
4161 // bitmap knows by how much we need to move it as it knows its | |
4162 // granularity). | |
1314
3f0549ed0c98
6921710: G1: assert(new_finger >= _finger && new_finger < _region_limit,"invariant")
apetrusenko
parents:
1284
diff
changeset
|
4163 assert(_finger < _region_limit, "invariant"); |
3f0549ed0c98
6921710: G1: assert(new_finger >= _finger && new_finger < _region_limit,"invariant")
apetrusenko
parents:
1284
diff
changeset
|
4164 HeapWord* new_finger = _nextMarkBitMap->nextWord(_finger); |
3f0549ed0c98
6921710: G1: assert(new_finger >= _finger && new_finger < _region_limit,"invariant")
apetrusenko
parents:
1284
diff
changeset
|
4165 // Check if bitmap iteration was aborted while scanning the last object |
3f0549ed0c98
6921710: G1: assert(new_finger >= _finger && new_finger < _region_limit,"invariant")
apetrusenko
parents:
1284
diff
changeset
|
4166 if (new_finger >= _region_limit) { |
3f0549ed0c98
6921710: G1: assert(new_finger >= _finger && new_finger < _region_limit,"invariant")
apetrusenko
parents:
1284
diff
changeset
|
4167 giveup_current_region(); |
3f0549ed0c98
6921710: G1: assert(new_finger >= _finger && new_finger < _region_limit,"invariant")
apetrusenko
parents:
1284
diff
changeset
|
4168 } else { |
3f0549ed0c98
6921710: G1: assert(new_finger >= _finger && new_finger < _region_limit,"invariant")
apetrusenko
parents:
1284
diff
changeset
|
4169 move_finger_to(new_finger); |
3f0549ed0c98
6921710: G1: assert(new_finger >= _finger && new_finger < _region_limit,"invariant")
apetrusenko
parents:
1284
diff
changeset
|
4170 } |
342 | 4171 } |
4172 } | |
4173 // At this point we have either completed iterating over the | |
4174 // region we were holding on to, or we have aborted. | |
4175 | |
4176 // We then partially drain the local queue and the global stack. | |
4177 // (Do we really need this?) | |
4178 drain_local_queue(true); | |
4179 drain_global_stack(true); | |
4180 | |
4181 // Read the note on the claim_region() method on why it might | |
4182 // return NULL with potentially more regions available for | |
4183 // claiming and why we have to check out_of_regions() to determine | |
4184 // whether we're done or not. | |
4185 while (!has_aborted() && _curr_region == NULL && !_cm->out_of_regions()) { | |
4186 // We are going to try to claim a new region. We should have | |
4187 // given up on the previous one. | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4188 // Separated the asserts so that we know which one fires. |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4189 assert(_curr_region == NULL, "invariant"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4190 assert(_finger == NULL, "invariant"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4191 assert(_region_limit == NULL, "invariant"); |
342 | 4192 if (_cm->verbose_low()) |
4193 gclog_or_tty->print_cr("[%d] trying to claim a new region", _task_id); | |
4194 HeapRegion* claimed_region = _cm->claim_region(_task_id); | |
4195 if (claimed_region != NULL) { | |
4196 // Yes, we managed to claim one | |
4197 statsOnly( ++_regions_claimed ); | |
4198 | |
4199 if (_cm->verbose_low()) | |
4200 gclog_or_tty->print_cr("[%d] we successfully claimed " | |
4201 "region "PTR_FORMAT, | |
4202 _task_id, claimed_region); | |
4203 | |
4204 setup_for_region(claimed_region); | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4205 assert(_curr_region == claimed_region, "invariant"); |
342 | 4206 } |
4207 // It is important to call the regular clock here. It might take | |
4208 // a while to claim a region if, for example, we hit a large | |
4209 // block of empty regions. So we need to call the regular clock | |
4210 // method once round the loop to make sure it's called | |
4211 // frequently enough. | |
4212 regular_clock_call(); | |
4213 } | |
4214 | |
4215 if (!has_aborted() && _curr_region == NULL) { | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4216 assert(_cm->out_of_regions(), |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4217 "at this point we should be out of regions"); |
342 | 4218 } |
4219 } while ( _curr_region != NULL && !has_aborted()); | |
4220 | |
4221 if (!has_aborted()) { | |
4222 // We cannot check whether the global stack is empty, since other | |
343
afc1ce1efe66
6710665: G1: guarantee(_cm->out_of_regions() && _cm->region_stack_empty() && _task_queue->size() == 0, ...)
iveresov
parents:
342
diff
changeset
|
4223 // tasks might be pushing objects to it concurrently. We also cannot |
afc1ce1efe66
6710665: G1: guarantee(_cm->out_of_regions() && _cm->region_stack_empty() && _task_queue->size() == 0, ...)
iveresov
parents:
342
diff
changeset
|
4224 // check if the region stack is empty because if a thread is aborting |
afc1ce1efe66
6710665: G1: guarantee(_cm->out_of_regions() && _cm->region_stack_empty() && _task_queue->size() == 0, ...)
iveresov
parents:
342
diff
changeset
|
4225 // it can push a partially done region back. |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4226 assert(_cm->out_of_regions(), |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4227 "at this point we should be out of regions"); |
342 | 4228 |
4229 if (_cm->verbose_low()) | |
4230 gclog_or_tty->print_cr("[%d] all regions claimed", _task_id); | |
4231 | |
4232 // Try to reduce the number of available SATB buffers so that | |
4233 // remark has less work to do. | |
4234 drain_satb_buffers(); | |
4235 } | |
4236 | |
4237 // Since we've done everything else, we can now totally drain the | |
4238 // local queue and global stack. | |
4239 drain_local_queue(false); | |
4240 drain_global_stack(false); | |
4241 | |
4242 // Attempt at work stealing from other task's queues. | |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
4243 if (do_stealing && !has_aborted()) { |
342 | 4244 // We have not aborted. This means that we have finished all that |
4245 // we could. Let's try to do some stealing... | |
4246 | |
4247 // We cannot check whether the global stack is empty, since other | |
343
afc1ce1efe66
6710665: G1: guarantee(_cm->out_of_regions() && _cm->region_stack_empty() && _task_queue->size() == 0, ...)
iveresov
parents:
342
diff
changeset
|
4248 // tasks might be pushing objects to it concurrently. We also cannot |
afc1ce1efe66
6710665: G1: guarantee(_cm->out_of_regions() && _cm->region_stack_empty() && _task_queue->size() == 0, ...)
iveresov
parents:
342
diff
changeset
|
4249 // check if the region stack is empty because if a thread is aborting |
afc1ce1efe66
6710665: G1: guarantee(_cm->out_of_regions() && _cm->region_stack_empty() && _task_queue->size() == 0, ...)
iveresov
parents:
342
diff
changeset
|
4250 // it can push a partially done region back. |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4251 assert(_cm->out_of_regions() && _task_queue->size() == 0, |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4252 "only way to reach here"); |
342 | 4253 |
4254 if (_cm->verbose_low()) | |
4255 gclog_or_tty->print_cr("[%d] starting to steal", _task_id); | |
4256 | |
4257 while (!has_aborted()) { | |
4258 oop obj; | |
4259 statsOnly( ++_steal_attempts ); | |
4260 | |
4261 if (_cm->try_stealing(_task_id, &_hash_seed, obj)) { | |
4262 if (_cm->verbose_medium()) | |
4263 gclog_or_tty->print_cr("[%d] stolen "PTR_FORMAT" successfully", | |
4264 _task_id, (void*) obj); | |
4265 | |
4266 statsOnly( ++_steals ); | |
4267 | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4268 assert(_nextMarkBitMap->isMarked((HeapWord*) obj), |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4269 "any stolen object should be marked"); |
342 | 4270 scan_object(obj); |
4271 | |
4272 // And since we're towards the end, let's totally drain the | |
4273 // local queue and global stack. | |
4274 drain_local_queue(false); | |
4275 drain_global_stack(false); | |
4276 } else { | |
4277 break; | |
4278 } | |
4279 } | |
4280 } | |
4281 | |
4282 // We still haven't aborted. Now, let's try to get into the | |
4283 // termination protocol. | |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
4284 if (do_termination && !has_aborted()) { |
342 | 4285 // We cannot check whether the global stack is empty, since other |
343
afc1ce1efe66
6710665: G1: guarantee(_cm->out_of_regions() && _cm->region_stack_empty() && _task_queue->size() == 0, ...)
iveresov
parents:
342
diff
changeset
|
4286 // tasks might be concurrently pushing objects on it. We also cannot |
afc1ce1efe66
6710665: G1: guarantee(_cm->out_of_regions() && _cm->region_stack_empty() && _task_queue->size() == 0, ...)
iveresov
parents:
342
diff
changeset
|
4287 // check if the region stack is empty because if a thread is aborting |
afc1ce1efe66
6710665: G1: guarantee(_cm->out_of_regions() && _cm->region_stack_empty() && _task_queue->size() == 0, ...)
iveresov
parents:
342
diff
changeset
|
4288 // it can push a partially done region back. |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4289 // Separated the asserts so that we know which one fires. |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4290 assert(_cm->out_of_regions(), "only way to reach here"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4291 assert(_task_queue->size() == 0, "only way to reach here"); |
342 | 4292 |
4293 if (_cm->verbose_low()) | |
4294 gclog_or_tty->print_cr("[%d] starting termination protocol", _task_id); | |
4295 | |
4296 _termination_start_time_ms = os::elapsedVTime() * 1000.0; | |
4297 // The CMTask class also extends the TerminatorTerminator class, | |
4298 // hence its should_exit_termination() method will also decide | |
4299 // whether to exit the termination protocol or not. | |
4300 bool finished = _cm->terminator()->offer_termination(this); | |
4301 double termination_end_time_ms = os::elapsedVTime() * 1000.0; | |
4302 _termination_time_ms += | |
4303 termination_end_time_ms - _termination_start_time_ms; | |
4304 | |
4305 if (finished) { | |
4306 // We're all done. | |
4307 | |
4308 if (_task_id == 0) { | |
4309 // let's allow task 0 to do this | |
4310 if (concurrent()) { | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4311 assert(_cm->concurrent_marking_in_progress(), "invariant"); |
342 | 4312 // we need to set this to false before the next |
4313 // safepoint. This way we ensure that the marking phase | |
4314 // doesn't observe any more heap expansions. | |
4315 _cm->clear_concurrent_marking_in_progress(); | |
4316 } | |
4317 } | |
4318 | |
4319 // We can now guarantee that the global stack is empty, since | |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4320 // all other tasks have finished. We separated the guarantees so |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4321 // that, if a condition is false, we can immediately find out |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4322 // which one. |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4323 guarantee(_cm->out_of_regions(), "only way to reach here"); |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
4324 guarantee(_aborted_region.is_empty(), "only way to reach here"); |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4325 guarantee(_cm->region_stack_empty(), "only way to reach here"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4326 guarantee(_cm->mark_stack_empty(), "only way to reach here"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4327 guarantee(_task_queue->size() == 0, "only way to reach here"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4328 guarantee(!_cm->has_overflown(), "only way to reach here"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4329 guarantee(!_cm->mark_stack_overflow(), "only way to reach here"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4330 guarantee(!_cm->region_stack_overflow(), "only way to reach here"); |
342 | 4331 |
4332 if (_cm->verbose_low()) | |
4333 gclog_or_tty->print_cr("[%d] all tasks terminated", _task_id); | |
4334 } else { | |
4335 // Apparently there's more work to do. Let's abort this task. It | |
4336 // will restart it and we can hopefully find more things to do. | |
4337 | |
4338 if (_cm->verbose_low()) | |
4339 gclog_or_tty->print_cr("[%d] apparently there is more work to do", _task_id); | |
4340 | |
4341 set_has_aborted(); | |
4342 statsOnly( ++_aborted_termination ); | |
4343 } | |
4344 } | |
4345 | |
4346 // Mainly for debugging purposes to make sure that a pointer to the | |
4347 // closure which was statically allocated in this frame doesn't | |
4348 // escape it by accident. | |
4349 set_oop_closure(NULL); | |
4350 double end_time_ms = os::elapsedVTime() * 1000.0; | |
4351 double elapsed_time_ms = end_time_ms - _start_time_ms; | |
4352 // Update the step history. | |
4353 _step_times_ms.add(elapsed_time_ms); | |
4354 | |
4355 if (has_aborted()) { | |
4356 // The task was aborted for some reason. | |
4357 | |
4358 statsOnly( ++_aborted ); | |
4359 | |
2174
234761c55641
6608385: G1: need to support parallel reference processing
johnc
parents:
2152
diff
changeset
|
4360 if (_has_timed_out) { |
342 | 4361 double diff_ms = elapsed_time_ms - _time_target_ms; |
4362 // Keep statistics of how well we did with respect to hitting | |
4363 // our target only if we actually timed out (if we aborted for | |
4364 // other reasons, then the results might get skewed). | |
4365 _marking_step_diffs_ms.add(diff_ms); | |
4366 } | |
4367 | |
4368 if (_cm->has_overflown()) { | |
4369 // This is the interesting one. We aborted because a global | |
4370 // overflow was raised. This means we have to restart the | |
4371 // marking phase and start iterating over regions. However, in | |
4372 // order to do this we have to make sure that all tasks stop | |
4373 // what they are doing and re-initialise in a safe manner. We | |
4374 // will achieve this with the use of two barrier sync points. | |
4375 | |
4376 if (_cm->verbose_low()) | |
4377 gclog_or_tty->print_cr("[%d] detected overflow", _task_id); | |
4378 | |
4379 _cm->enter_first_sync_barrier(_task_id); | |
4380 // When we exit this sync barrier we know that all tasks have | |
4381 // stopped doing marking work. So, it's now safe to | |
4382 // re-initialise our data structures. At the end of this method, | |
4383 // task 0 will clear the global data structures. | |
4384 | |
4385 statsOnly( ++_aborted_overflow ); | |
4386 | |
4387 // We clear the local state of this task... | |
4388 clear_region_fields(); | |
4389 | |
4390 // ...and enter the second barrier. | |
4391 _cm->enter_second_sync_barrier(_task_id); | |
4392 // At this point everything has bee re-initialised and we're | |
4393 // ready to restart. | |
4394 } | |
4395 | |
4396 if (_cm->verbose_low()) { | |
4397 gclog_or_tty->print_cr("[%d] <<<<<<<<<< ABORTING, target = %1.2lfms, " | |
4398 "elapsed = %1.2lfms <<<<<<<<<<", | |
4399 _task_id, _time_target_ms, elapsed_time_ms); | |
4400 if (_cm->has_aborted()) | |
4401 gclog_or_tty->print_cr("[%d] ========== MARKING ABORTED ==========", | |
4402 _task_id); | |
4403 } | |
4404 } else { | |
4405 if (_cm->verbose_low()) | |
4406 gclog_or_tty->print_cr("[%d] <<<<<<<<<< FINISHED, target = %1.2lfms, " | |
4407 "elapsed = %1.2lfms <<<<<<<<<<", | |
4408 _task_id, _time_target_ms, elapsed_time_ms); | |
4409 } | |
4410 | |
4411 _claimed = false; | |
4412 } | |
4413 | |
4414 CMTask::CMTask(int task_id, | |
4415 ConcurrentMark* cm, | |
4416 CMTaskQueue* task_queue, | |
4417 CMTaskQueueSet* task_queues) | |
4418 : _g1h(G1CollectedHeap::heap()), | |
4419 _task_id(task_id), _cm(cm), | |
4420 _claimed(false), | |
4421 _nextMarkBitMap(NULL), _hash_seed(17), | |
4422 _task_queue(task_queue), | |
4423 _task_queues(task_queues), | |
1835
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
4424 _oop_closure(NULL), |
4805b9f4779e
6941395: G1: Use only lock-free versions of region stack push() and pop()
johnc
parents:
1833
diff
changeset
|
4425 _aborted_region(MemRegion()) { |
1023
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4426 guarantee(task_queue != NULL, "invariant"); |
11d4857fe5e1
6888619: G1: too many guarantees in concurrent marking
tonyp
parents:
1022
diff
changeset
|
4427 guarantee(task_queues != NULL, "invariant"); |
342 | 4428 |
4429 statsOnly( _clock_due_to_scanning = 0; | |
4430 _clock_due_to_marking = 0 ); | |
4431 | |
4432 _marking_step_diffs_ms.add(0.5); | |
4433 } | |
2435
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4434 |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4435 // These are formatting macros that are used below to ensure |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4436 // consistent formatting. The *_H_* versions are used to format the |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4437 // header for a particular value and they should be kept consistent |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4438 // with the corresponding macro. Also note that most of the macros add |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4439 // the necessary white space (as a prefix) which makes them a bit |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4440 // easier to compose. |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4441 |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4442 // All the output lines are prefixed with this string to be able to |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4443 // identify them easily in a large log file. |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4444 #define G1PPRL_LINE_PREFIX "###" |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4445 |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4446 #define G1PPRL_ADDR_BASE_FORMAT " "PTR_FORMAT"-"PTR_FORMAT |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4447 #ifdef _LP64 |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4448 #define G1PPRL_ADDR_BASE_H_FORMAT " %37s" |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4449 #else // _LP64 |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4450 #define G1PPRL_ADDR_BASE_H_FORMAT " %21s" |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4451 #endif // _LP64 |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4452 |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4453 // For per-region info |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4454 #define G1PPRL_TYPE_FORMAT " %-4s" |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4455 #define G1PPRL_TYPE_H_FORMAT " %4s" |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4456 #define G1PPRL_BYTE_FORMAT " "SIZE_FORMAT_W(9) |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4457 #define G1PPRL_BYTE_H_FORMAT " %9s" |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4458 #define G1PPRL_DOUBLE_FORMAT " %14.1f" |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4459 #define G1PPRL_DOUBLE_H_FORMAT " %14s" |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4460 |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4461 // For summary info |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4462 #define G1PPRL_SUM_ADDR_FORMAT(tag) " "tag":"G1PPRL_ADDR_BASE_FORMAT |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4463 #define G1PPRL_SUM_BYTE_FORMAT(tag) " "tag": "SIZE_FORMAT |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4464 #define G1PPRL_SUM_MB_FORMAT(tag) " "tag": %1.2f MB" |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4465 #define G1PPRL_SUM_MB_PERC_FORMAT(tag) G1PPRL_SUM_MB_FORMAT(tag)" / %1.2f %%" |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4466 |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4467 G1PrintRegionLivenessInfoClosure:: |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4468 G1PrintRegionLivenessInfoClosure(outputStream* out, const char* phase_name) |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4469 : _out(out), |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4470 _total_used_bytes(0), _total_capacity_bytes(0), |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4471 _total_prev_live_bytes(0), _total_next_live_bytes(0), |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4472 _hum_used_bytes(0), _hum_capacity_bytes(0), |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4473 _hum_prev_live_bytes(0), _hum_next_live_bytes(0) { |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4474 G1CollectedHeap* g1h = G1CollectedHeap::heap(); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4475 MemRegion g1_committed = g1h->g1_committed(); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4476 MemRegion g1_reserved = g1h->g1_reserved(); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4477 double now = os::elapsedTime(); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4478 |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4479 // Print the header of the output. |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4480 _out->cr(); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4481 _out->print_cr(G1PPRL_LINE_PREFIX" PHASE %s @ %1.3f", phase_name, now); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4482 _out->print_cr(G1PPRL_LINE_PREFIX" HEAP" |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4483 G1PPRL_SUM_ADDR_FORMAT("committed") |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4484 G1PPRL_SUM_ADDR_FORMAT("reserved") |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4485 G1PPRL_SUM_BYTE_FORMAT("region-size"), |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4486 g1_committed.start(), g1_committed.end(), |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4487 g1_reserved.start(), g1_reserved.end(), |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4488 HeapRegion::GrainBytes); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4489 _out->print_cr(G1PPRL_LINE_PREFIX); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4490 _out->print_cr(G1PPRL_LINE_PREFIX |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4491 G1PPRL_TYPE_H_FORMAT |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4492 G1PPRL_ADDR_BASE_H_FORMAT |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4493 G1PPRL_BYTE_H_FORMAT |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4494 G1PPRL_BYTE_H_FORMAT |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4495 G1PPRL_BYTE_H_FORMAT |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4496 G1PPRL_DOUBLE_H_FORMAT, |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4497 "type", "address-range", |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4498 "used", "prev-live", "next-live", "gc-eff"); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4499 } |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4500 |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4501 // It takes as a parameter a reference to one of the _hum_* fields, it |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4502 // deduces the corresponding value for a region in a humongous region |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4503 // series (either the region size, or what's left if the _hum_* field |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4504 // is < the region size), and updates the _hum_* field accordingly. |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4505 size_t G1PrintRegionLivenessInfoClosure::get_hum_bytes(size_t* hum_bytes) { |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4506 size_t bytes = 0; |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4507 // The > 0 check is to deal with the prev and next live bytes which |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4508 // could be 0. |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4509 if (*hum_bytes > 0) { |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4510 bytes = MIN2((size_t) HeapRegion::GrainBytes, *hum_bytes); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4511 *hum_bytes -= bytes; |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4512 } |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4513 return bytes; |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4514 } |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4515 |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4516 // It deduces the values for a region in a humongous region series |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4517 // from the _hum_* fields and updates those accordingly. It assumes |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4518 // that that _hum_* fields have already been set up from the "starts |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4519 // humongous" region and we visit the regions in address order. |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4520 void G1PrintRegionLivenessInfoClosure::get_hum_bytes(size_t* used_bytes, |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4521 size_t* capacity_bytes, |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4522 size_t* prev_live_bytes, |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4523 size_t* next_live_bytes) { |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4524 assert(_hum_used_bytes > 0 && _hum_capacity_bytes > 0, "pre-condition"); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4525 *used_bytes = get_hum_bytes(&_hum_used_bytes); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4526 *capacity_bytes = get_hum_bytes(&_hum_capacity_bytes); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4527 *prev_live_bytes = get_hum_bytes(&_hum_prev_live_bytes); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4528 *next_live_bytes = get_hum_bytes(&_hum_next_live_bytes); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4529 } |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4530 |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4531 bool G1PrintRegionLivenessInfoClosure::doHeapRegion(HeapRegion* r) { |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4532 const char* type = ""; |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4533 HeapWord* bottom = r->bottom(); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4534 HeapWord* end = r->end(); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4535 size_t capacity_bytes = r->capacity(); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4536 size_t used_bytes = r->used(); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4537 size_t prev_live_bytes = r->live_bytes(); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4538 size_t next_live_bytes = r->next_live_bytes(); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4539 double gc_eff = r->gc_efficiency(); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4540 if (r->used() == 0) { |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4541 type = "FREE"; |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4542 } else if (r->is_survivor()) { |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4543 type = "SURV"; |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4544 } else if (r->is_young()) { |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4545 type = "EDEN"; |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4546 } else if (r->startsHumongous()) { |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4547 type = "HUMS"; |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4548 |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4549 assert(_hum_used_bytes == 0 && _hum_capacity_bytes == 0 && |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4550 _hum_prev_live_bytes == 0 && _hum_next_live_bytes == 0, |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4551 "they should have been zeroed after the last time we used them"); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4552 // Set up the _hum_* fields. |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4553 _hum_capacity_bytes = capacity_bytes; |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4554 _hum_used_bytes = used_bytes; |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4555 _hum_prev_live_bytes = prev_live_bytes; |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4556 _hum_next_live_bytes = next_live_bytes; |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4557 get_hum_bytes(&used_bytes, &capacity_bytes, |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4558 &prev_live_bytes, &next_live_bytes); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4559 end = bottom + HeapRegion::GrainWords; |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4560 } else if (r->continuesHumongous()) { |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4561 type = "HUMC"; |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4562 get_hum_bytes(&used_bytes, &capacity_bytes, |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4563 &prev_live_bytes, &next_live_bytes); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4564 assert(end == bottom + HeapRegion::GrainWords, "invariant"); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4565 } else { |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4566 type = "OLD"; |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4567 } |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4568 |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4569 _total_used_bytes += used_bytes; |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4570 _total_capacity_bytes += capacity_bytes; |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4571 _total_prev_live_bytes += prev_live_bytes; |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4572 _total_next_live_bytes += next_live_bytes; |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4573 |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4574 // Print a line for this particular region. |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4575 _out->print_cr(G1PPRL_LINE_PREFIX |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4576 G1PPRL_TYPE_FORMAT |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4577 G1PPRL_ADDR_BASE_FORMAT |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4578 G1PPRL_BYTE_FORMAT |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4579 G1PPRL_BYTE_FORMAT |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4580 G1PPRL_BYTE_FORMAT |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4581 G1PPRL_DOUBLE_FORMAT, |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4582 type, bottom, end, |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4583 used_bytes, prev_live_bytes, next_live_bytes, gc_eff); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4584 |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4585 return false; |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4586 } |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4587 |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4588 G1PrintRegionLivenessInfoClosure::~G1PrintRegionLivenessInfoClosure() { |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4589 // Print the footer of the output. |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4590 _out->print_cr(G1PPRL_LINE_PREFIX); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4591 _out->print_cr(G1PPRL_LINE_PREFIX |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4592 " SUMMARY" |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4593 G1PPRL_SUM_MB_FORMAT("capacity") |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4594 G1PPRL_SUM_MB_PERC_FORMAT("used") |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4595 G1PPRL_SUM_MB_PERC_FORMAT("prev-live") |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4596 G1PPRL_SUM_MB_PERC_FORMAT("next-live"), |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4597 bytes_to_mb(_total_capacity_bytes), |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4598 bytes_to_mb(_total_used_bytes), |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4599 perc(_total_used_bytes, _total_capacity_bytes), |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4600 bytes_to_mb(_total_prev_live_bytes), |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4601 perc(_total_prev_live_bytes, _total_capacity_bytes), |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4602 bytes_to_mb(_total_next_live_bytes), |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4603 perc(_total_next_live_bytes, _total_capacity_bytes)); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4604 _out->cr(); |
371bbc844bf1
7027766: G1: introduce flag to dump the liveness information per region at the end of marking
tonyp
parents:
2369
diff
changeset
|
4605 } |