Mercurial > hg > graal-compiler
annotate src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp @ 2149:7e37af9d69ef
7011379: G1: overly long concurrent marking cycles
Summary: This changeset introduces filtering of SATB buffers at the point when they are about to be enqueued. If this filtering clears enough entries on each buffer, the buffer can then be re-used and not enqueued. This cuts down the number of SATB buffers that need to be processed by the concurrent marking threads.
Reviewed-by: johnc, ysr
author | tonyp |
---|---|
date | Wed, 19 Jan 2011 09:35:17 -0500 |
parents | f95d63e2154a |
children | f08d439fab8c |
rev | line source |
---|---|
0 | 1 /* |
1972 | 2 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
237
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
237
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:
237
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "gc_implementation/parallelScavenge/parMarkBitMap.hpp" | |
27 #include "gc_implementation/parallelScavenge/parMarkBitMap.inline.hpp" | |
28 #include "gc_implementation/parallelScavenge/psParallelCompact.hpp" | |
29 #include "oops/oop.inline.hpp" | |
30 #include "runtime/os.hpp" | |
31 #include "utilities/bitMap.inline.hpp" | |
32 #ifdef TARGET_OS_FAMILY_linux | |
33 # include "os_linux.inline.hpp" | |
34 #endif | |
35 #ifdef TARGET_OS_FAMILY_solaris | |
36 # include "os_solaris.inline.hpp" | |
37 #endif | |
38 #ifdef TARGET_OS_FAMILY_windows | |
39 # include "os_windows.inline.hpp" | |
40 #endif | |
0 | 41 |
42 bool | |
43 ParMarkBitMap::initialize(MemRegion covered_region) | |
44 { | |
45 const idx_t bits = bits_required(covered_region); | |
46 // The bits will be divided evenly between two bitmaps; each of them should be | |
47 // an integral number of words. | |
48 assert(bits % (BitsPerWord * 2) == 0, "region size unaligned"); | |
49 | |
50 const size_t words = bits / BitsPerWord; | |
51 const size_t raw_bytes = words * sizeof(idx_t); | |
52 const size_t page_sz = os::page_size_for_region(raw_bytes, raw_bytes, 10); | |
53 const size_t granularity = os::vm_allocation_granularity(); | |
54 const size_t bytes = align_size_up(raw_bytes, MAX2(page_sz, granularity)); | |
55 | |
56 const size_t rs_align = page_sz == (size_t) os::vm_page_size() ? 0 : | |
57 MAX2(page_sz, granularity); | |
79
82db0859acbe
6642862: Code cache allocation fails with large pages after 6588638
jcoomes
parents:
0
diff
changeset
|
58 ReservedSpace rs(bytes, rs_align, rs_align > 0); |
0 | 59 os::trace_page_sizes("par bitmap", raw_bytes, raw_bytes, page_sz, |
60 rs.base(), rs.size()); | |
61 _virtual_space = new PSVirtualSpace(rs, page_sz); | |
62 if (_virtual_space != NULL && _virtual_space->expand_by(bytes)) { | |
63 _region_start = covered_region.start(); | |
64 _region_size = covered_region.word_size(); | |
65 idx_t* map = (idx_t*)_virtual_space->reserved_low_addr(); | |
66 _beg_bits.set_map(map); | |
67 _beg_bits.set_size(bits / 2); | |
68 _end_bits.set_map(map + words / 2); | |
69 _end_bits.set_size(bits / 2); | |
70 return true; | |
71 } | |
72 | |
73 _region_start = 0; | |
74 _region_size = 0; | |
75 if (_virtual_space != NULL) { | |
76 delete _virtual_space; | |
77 _virtual_space = NULL; | |
237
1fdb98a17101
6716785: implicit null checks not triggering with CompressedOops
coleenp
parents:
196
diff
changeset
|
78 // Release memory reserved in the space. |
1fdb98a17101
6716785: implicit null checks not triggering with CompressedOops
coleenp
parents:
196
diff
changeset
|
79 rs.release(); |
0 | 80 } |
81 return false; | |
82 } | |
83 | |
84 #ifdef ASSERT | |
85 extern size_t mark_bitmap_count; | |
86 extern size_t mark_bitmap_size; | |
87 #endif // #ifdef ASSERT | |
88 | |
89 bool | |
90 ParMarkBitMap::mark_obj(HeapWord* addr, size_t size) | |
91 { | |
92 const idx_t beg_bit = addr_to_bit(addr); | |
93 if (_beg_bits.par_set_bit(beg_bit)) { | |
94 const idx_t end_bit = addr_to_bit(addr + size - 1); | |
95 bool end_bit_ok = _end_bits.par_set_bit(end_bit); | |
96 assert(end_bit_ok, "concurrency problem"); | |
97 DEBUG_ONLY(Atomic::inc_ptr(&mark_bitmap_count)); | |
98 DEBUG_ONLY(Atomic::add_ptr(size, &mark_bitmap_size)); | |
99 return true; | |
100 } | |
101 return false; | |
102 } | |
103 | |
104 size_t | |
105 ParMarkBitMap::live_words_in_range(HeapWord* beg_addr, HeapWord* end_addr) const | |
106 { | |
107 assert(beg_addr <= end_addr, "bad range"); | |
108 | |
109 idx_t live_bits = 0; | |
110 | |
111 // The bitmap routines require the right boundary to be word-aligned. | |
112 const idx_t end_bit = addr_to_bit(end_addr); | |
113 const idx_t range_end = BitMap::word_align_up(end_bit); | |
114 | |
115 idx_t beg_bit = find_obj_beg(addr_to_bit(beg_addr), range_end); | |
116 while (beg_bit < end_bit) { | |
117 idx_t tmp_end = find_obj_end(beg_bit, range_end); | |
118 if (tmp_end < end_bit) { | |
119 live_bits += tmp_end - beg_bit + 1; | |
120 beg_bit = find_obj_beg(tmp_end + 1, range_end); | |
121 } else { | |
122 live_bits += end_bit - beg_bit; // No + 1 here; end_bit is not counted. | |
123 return bits_to_words(live_bits); | |
124 } | |
125 } | |
126 return bits_to_words(live_bits); | |
127 } | |
128 | |
129 size_t ParMarkBitMap::live_words_in_range(HeapWord* beg_addr, oop end_obj) const | |
130 { | |
131 assert(beg_addr <= (HeapWord*)end_obj, "bad range"); | |
132 assert(is_marked(end_obj), "end_obj must be live"); | |
133 | |
134 idx_t live_bits = 0; | |
135 | |
136 // The bitmap routines require the right boundary to be word-aligned. | |
137 const idx_t end_bit = addr_to_bit((HeapWord*)end_obj); | |
138 const idx_t range_end = BitMap::word_align_up(end_bit); | |
139 | |
140 idx_t beg_bit = find_obj_beg(addr_to_bit(beg_addr), range_end); | |
141 while (beg_bit < end_bit) { | |
142 idx_t tmp_end = find_obj_end(beg_bit, range_end); | |
143 assert(tmp_end < end_bit, "missing end bit"); | |
144 live_bits += tmp_end - beg_bit + 1; | |
145 beg_bit = find_obj_beg(tmp_end + 1, range_end); | |
146 } | |
147 return bits_to_words(live_bits); | |
148 } | |
149 | |
150 ParMarkBitMap::IterationStatus | |
151 ParMarkBitMap::iterate(ParMarkBitMapClosure* live_closure, | |
152 idx_t range_beg, idx_t range_end) const | |
153 { | |
154 DEBUG_ONLY(verify_bit(range_beg);) | |
155 DEBUG_ONLY(verify_bit(range_end);) | |
156 assert(range_beg <= range_end, "live range invalid"); | |
157 | |
158 // The bitmap routines require the right boundary to be word-aligned. | |
159 const idx_t search_end = BitMap::word_align_up(range_end); | |
160 | |
161 idx_t cur_beg = find_obj_beg(range_beg, search_end); | |
162 while (cur_beg < range_end) { | |
163 const idx_t cur_end = find_obj_end(cur_beg, search_end); | |
164 if (cur_end >= range_end) { | |
165 // The obj ends outside the range. | |
166 live_closure->set_source(bit_to_addr(cur_beg)); | |
167 return incomplete; | |
168 } | |
169 | |
170 const size_t size = obj_size(cur_beg, cur_end); | |
171 IterationStatus status = live_closure->do_addr(bit_to_addr(cur_beg), size); | |
172 if (status != incomplete) { | |
173 assert(status == would_overflow || status == full, "sanity"); | |
174 return status; | |
175 } | |
176 | |
177 // Successfully processed the object; look for the next object. | |
178 cur_beg = find_obj_beg(cur_end + 1, search_end); | |
179 } | |
180 | |
181 live_closure->set_source(bit_to_addr(range_end)); | |
182 return complete; | |
183 } | |
184 | |
185 ParMarkBitMap::IterationStatus | |
186 ParMarkBitMap::iterate(ParMarkBitMapClosure* live_closure, | |
187 ParMarkBitMapClosure* dead_closure, | |
188 idx_t range_beg, idx_t range_end, | |
189 idx_t dead_range_end) const | |
190 { | |
191 DEBUG_ONLY(verify_bit(range_beg);) | |
192 DEBUG_ONLY(verify_bit(range_end);) | |
193 DEBUG_ONLY(verify_bit(dead_range_end);) | |
194 assert(range_beg <= range_end, "live range invalid"); | |
195 assert(range_end <= dead_range_end, "dead range invalid"); | |
196 | |
197 // The bitmap routines require the right boundary to be word-aligned. | |
198 const idx_t live_search_end = BitMap::word_align_up(range_end); | |
199 const idx_t dead_search_end = BitMap::word_align_up(dead_range_end); | |
200 | |
201 idx_t cur_beg = range_beg; | |
202 if (range_beg < range_end && is_unmarked(range_beg)) { | |
203 // The range starts with dead space. Look for the next object, then fill. | |
204 cur_beg = find_obj_beg(range_beg + 1, dead_search_end); | |
205 const idx_t dead_space_end = MIN2(cur_beg - 1, dead_range_end - 1); | |
206 const size_t size = obj_size(range_beg, dead_space_end); | |
207 dead_closure->do_addr(bit_to_addr(range_beg), size); | |
208 } | |
209 | |
210 while (cur_beg < range_end) { | |
211 const idx_t cur_end = find_obj_end(cur_beg, live_search_end); | |
212 if (cur_end >= range_end) { | |
213 // The obj ends outside the range. | |
214 live_closure->set_source(bit_to_addr(cur_beg)); | |
215 return incomplete; | |
216 } | |
217 | |
218 const size_t size = obj_size(cur_beg, cur_end); | |
219 IterationStatus status = live_closure->do_addr(bit_to_addr(cur_beg), size); | |
220 if (status != incomplete) { | |
221 assert(status == would_overflow || status == full, "sanity"); | |
222 return status; | |
223 } | |
224 | |
225 // Look for the start of the next object. | |
226 const idx_t dead_space_beg = cur_end + 1; | |
227 cur_beg = find_obj_beg(dead_space_beg, dead_search_end); | |
228 if (cur_beg > dead_space_beg) { | |
229 // Found dead space; compute the size and invoke the dead closure. | |
230 const idx_t dead_space_end = MIN2(cur_beg - 1, dead_range_end - 1); | |
231 const size_t size = obj_size(dead_space_beg, dead_space_end); | |
232 dead_closure->do_addr(bit_to_addr(dead_space_beg), size); | |
233 } | |
234 } | |
235 | |
236 live_closure->set_source(bit_to_addr(range_end)); | |
237 return complete; | |
238 } | |
239 | |
240 #ifndef PRODUCT | |
241 void ParMarkBitMap::reset_counters() | |
242 { | |
243 _cas_tries = _cas_retries = _cas_by_another = 0; | |
244 } | |
245 #endif // #ifndef PRODUCT | |
246 | |
247 #ifdef ASSERT | |
248 void ParMarkBitMap::verify_clear() const | |
249 { | |
250 const idx_t* const beg = (const idx_t*)_virtual_space->committed_low_addr(); | |
251 const idx_t* const end = (const idx_t*)_virtual_space->committed_high_addr(); | |
252 for (const idx_t* p = beg; p < end; ++p) { | |
253 assert(*p == 0, "bitmap not clear"); | |
254 } | |
255 } | |
256 #endif // #ifdef ASSERT |