Mercurial > hg > graal-compiler
annotate src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.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) 2003, 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:
579
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
579
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:
579
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "gc_implementation/parallelScavenge/psVirtualspace.hpp" | |
27 #include "runtime/os.hpp" | |
28 #include "runtime/virtualspace.hpp" | |
29 #ifdef TARGET_OS_FAMILY_linux | |
30 # include "os_linux.inline.hpp" | |
31 #endif | |
32 #ifdef TARGET_OS_FAMILY_solaris | |
33 # include "os_solaris.inline.hpp" | |
34 #endif | |
35 #ifdef TARGET_OS_FAMILY_windows | |
36 # include "os_windows.inline.hpp" | |
37 #endif | |
0 | 38 |
39 // PSVirtualSpace | |
40 | |
41 PSVirtualSpace::PSVirtualSpace(ReservedSpace rs, size_t alignment) : | |
42 _alignment(alignment) | |
43 { | |
44 set_reserved(rs); | |
45 set_committed(reserved_low_addr(), reserved_low_addr()); | |
46 DEBUG_ONLY(verify()); | |
47 } | |
48 | |
49 PSVirtualSpace::PSVirtualSpace(ReservedSpace rs) : | |
50 _alignment(os::vm_page_size()) | |
51 { | |
52 set_reserved(rs); | |
53 set_committed(reserved_low_addr(), reserved_low_addr()); | |
54 DEBUG_ONLY(verify()); | |
55 } | |
56 | |
57 // Deprecated. | |
58 PSVirtualSpace::PSVirtualSpace(): _alignment(os::vm_page_size()) { | |
59 } | |
60 | |
61 // Deprecated. | |
62 bool PSVirtualSpace::initialize(ReservedSpace rs, | |
63 size_t commit_size) { | |
64 set_reserved(rs); | |
65 set_committed(reserved_low_addr(), reserved_low_addr()); | |
66 | |
67 // Commit to initial size. | |
68 assert(commit_size <= rs.size(), "commit_size too big"); | |
69 bool result = commit_size > 0 ? expand_by(commit_size) : true; | |
70 DEBUG_ONLY(verify()); | |
71 return result; | |
72 } | |
73 | |
74 PSVirtualSpace::~PSVirtualSpace() { | |
75 release(); | |
76 } | |
77 | |
78 bool PSVirtualSpace::contains(void* p) const { | |
79 char* const cp = (char*)p; | |
80 return cp >= committed_low_addr() && cp < committed_high_addr(); | |
81 } | |
82 | |
83 void PSVirtualSpace::release() { | |
84 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); | |
237
1fdb98a17101
6716785: implicit null checks not triggering with CompressedOops
coleenp
parents:
0
diff
changeset
|
85 // This may not release memory it didn't reserve. |
1fdb98a17101
6716785: implicit null checks not triggering with CompressedOops
coleenp
parents:
0
diff
changeset
|
86 // Use rs.release() to release the underlying memory instead. |
0 | 87 _reserved_low_addr = _reserved_high_addr = NULL; |
88 _committed_low_addr = _committed_high_addr = NULL; | |
89 _special = false; | |
90 } | |
91 | |
535
4e400c36026f
6783381: NUMA allocator: don't pretouch eden space with UseNUMA
iveresov
parents:
337
diff
changeset
|
92 bool PSVirtualSpace::expand_by(size_t bytes) { |
0 | 93 assert(is_aligned(bytes), "arg not aligned"); |
94 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); | |
95 | |
96 if (uncommitted_size() < bytes) { | |
97 return false; | |
98 } | |
99 | |
100 char* const base_addr = committed_high_addr(); | |
101 bool result = special() || os::commit_memory(base_addr, bytes, alignment()); | |
102 if (result) { | |
103 _committed_high_addr += bytes; | |
104 } | |
105 | |
106 return result; | |
107 } | |
108 | |
109 bool PSVirtualSpace::shrink_by(size_t bytes) { | |
110 assert(is_aligned(bytes), "arg not aligned"); | |
111 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); | |
112 | |
113 if (committed_size() < bytes) { | |
114 return false; | |
115 } | |
116 | |
117 char* const base_addr = committed_high_addr() - bytes; | |
118 bool result = special() || os::uncommit_memory(base_addr, bytes); | |
119 if (result) { | |
120 _committed_high_addr -= bytes; | |
121 } | |
122 | |
123 return result; | |
124 } | |
125 | |
126 size_t | |
127 PSVirtualSpace::expand_into(PSVirtualSpace* other_space, size_t bytes) { | |
128 assert(is_aligned(bytes), "arg not aligned"); | |
129 assert(grows_up(), "this space must grow up"); | |
130 assert(other_space->grows_down(), "other space must grow down"); | |
131 assert(reserved_high_addr() == other_space->reserved_low_addr(), | |
132 "spaces not contiguous"); | |
133 assert(special() == other_space->special(), "one space is special, the other is not"); | |
134 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); | |
135 DEBUG_ONLY(PSVirtualSpaceVerifier other_verifier(other_space)); | |
136 | |
137 size_t bytes_needed = bytes; | |
138 | |
139 // First use the uncommitted region in this space. | |
140 size_t tmp_bytes = MIN2(uncommitted_size(), bytes_needed); | |
141 if (tmp_bytes > 0) { | |
142 if (expand_by(tmp_bytes)) { | |
143 bytes_needed -= tmp_bytes; | |
144 } else { | |
145 return 0; | |
146 } | |
147 } | |
148 | |
149 // Next take from the uncommitted region in the other space, and commit it. | |
150 tmp_bytes = MIN2(other_space->uncommitted_size(), bytes_needed); | |
151 if (tmp_bytes > 0) { | |
152 char* const commit_base = committed_high_addr(); | |
153 if (other_space->special() || | |
154 os::commit_memory(commit_base, tmp_bytes, alignment())) { | |
155 // Reduce the reserved region in the other space. | |
156 other_space->set_reserved(other_space->reserved_low_addr() + tmp_bytes, | |
157 other_space->reserved_high_addr(), | |
158 other_space->special()); | |
159 | |
160 // Grow both reserved and committed in this space. | |
161 _reserved_high_addr += tmp_bytes; | |
162 _committed_high_addr += tmp_bytes; | |
163 bytes_needed -= tmp_bytes; | |
164 } else { | |
165 return bytes - bytes_needed; | |
166 } | |
167 } | |
168 | |
169 // Finally take from the already committed region in the other space. | |
170 tmp_bytes = bytes_needed; | |
171 if (tmp_bytes > 0) { | |
172 // Reduce both committed and reserved in the other space. | |
173 other_space->set_committed(other_space->committed_low_addr() + tmp_bytes, | |
174 other_space->committed_high_addr()); | |
175 other_space->set_reserved(other_space->reserved_low_addr() + tmp_bytes, | |
176 other_space->reserved_high_addr(), | |
177 other_space->special()); | |
178 | |
179 // Grow both reserved and committed in this space. | |
180 _reserved_high_addr += tmp_bytes; | |
181 _committed_high_addr += tmp_bytes; | |
182 } | |
183 | |
184 return bytes; | |
185 } | |
186 | |
187 #ifndef PRODUCT | |
188 bool PSVirtualSpace::is_aligned(size_t value, size_t align) { | |
189 const size_t tmp_value = value + align - 1; | |
190 const size_t mask = ~(align - 1); | |
191 return (tmp_value & mask) == value; | |
192 } | |
193 | |
194 bool PSVirtualSpace::is_aligned(size_t value) const { | |
195 return is_aligned(value, alignment()); | |
196 } | |
197 | |
198 bool PSVirtualSpace::is_aligned(char* value) const { | |
199 return is_aligned((size_t)value); | |
200 } | |
201 | |
202 void PSVirtualSpace::verify() const { | |
203 assert(is_aligned(alignment(), os::vm_page_size()), "bad alignment"); | |
204 assert(is_aligned(reserved_low_addr()), "bad reserved_low_addr"); | |
205 assert(is_aligned(reserved_high_addr()), "bad reserved_high_addr"); | |
206 assert(is_aligned(committed_low_addr()), "bad committed_low_addr"); | |
207 assert(is_aligned(committed_high_addr()), "bad committed_high_addr"); | |
208 | |
209 // Reserved region must be non-empty or both addrs must be 0. | |
210 assert(reserved_low_addr() < reserved_high_addr() || | |
211 reserved_low_addr() == NULL && reserved_high_addr() == NULL, | |
212 "bad reserved addrs"); | |
213 assert(committed_low_addr() <= committed_high_addr(), "bad committed addrs"); | |
214 | |
215 if (grows_up()) { | |
216 assert(reserved_low_addr() == committed_low_addr(), "bad low addrs"); | |
217 assert(reserved_high_addr() >= committed_high_addr(), "bad high addrs"); | |
218 } else { | |
219 assert(reserved_high_addr() == committed_high_addr(), "bad high addrs"); | |
220 assert(reserved_low_addr() <= committed_low_addr(), "bad low addrs"); | |
221 } | |
222 } | |
223 | |
224 void PSVirtualSpace::print() const { | |
225 gclog_or_tty->print_cr("virtual space [" PTR_FORMAT "]: alignment=" | |
226 SIZE_FORMAT "K grows %s%s", | |
227 this, alignment() / K, grows_up() ? "up" : "down", | |
228 special() ? " (pinned in memory)" : ""); | |
229 gclog_or_tty->print_cr(" reserved=" SIZE_FORMAT "K" | |
230 " [" PTR_FORMAT "," PTR_FORMAT "]" | |
231 " committed=" SIZE_FORMAT "K" | |
232 " [" PTR_FORMAT "," PTR_FORMAT "]", | |
233 reserved_size() / K, | |
234 reserved_low_addr(), reserved_high_addr(), | |
235 committed_size() / K, | |
236 committed_low_addr(), committed_high_addr()); | |
237 } | |
238 #endif // #ifndef PRODUCT | |
239 | |
240 void PSVirtualSpace::print_space_boundaries_on(outputStream* st) const { | |
241 st->print_cr(" [" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT ")", | |
242 low_boundary(), high(), high_boundary()); | |
243 } | |
244 | |
245 PSVirtualSpaceHighToLow::PSVirtualSpaceHighToLow(ReservedSpace rs, | |
246 size_t alignment) : | |
247 PSVirtualSpace(alignment) | |
248 { | |
249 set_reserved(rs); | |
250 set_committed(reserved_high_addr(), reserved_high_addr()); | |
251 DEBUG_ONLY(verify()); | |
252 } | |
253 | |
254 PSVirtualSpaceHighToLow::PSVirtualSpaceHighToLow(ReservedSpace rs) { | |
255 set_reserved(rs); | |
256 set_committed(reserved_high_addr(), reserved_high_addr()); | |
257 DEBUG_ONLY(verify()); | |
258 } | |
259 | |
535
4e400c36026f
6783381: NUMA allocator: don't pretouch eden space with UseNUMA
iveresov
parents:
337
diff
changeset
|
260 bool PSVirtualSpaceHighToLow::expand_by(size_t bytes) { |
0 | 261 assert(is_aligned(bytes), "arg not aligned"); |
262 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); | |
263 | |
264 if (uncommitted_size() < bytes) { | |
265 return false; | |
266 } | |
267 | |
268 char* const base_addr = committed_low_addr() - bytes; | |
269 bool result = special() || os::commit_memory(base_addr, bytes, alignment()); | |
270 if (result) { | |
271 _committed_low_addr -= bytes; | |
272 } | |
273 | |
274 return result; | |
275 } | |
276 | |
277 bool PSVirtualSpaceHighToLow::shrink_by(size_t bytes) { | |
278 assert(is_aligned(bytes), "arg not aligned"); | |
279 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); | |
280 | |
281 if (committed_size() < bytes) { | |
282 return false; | |
283 } | |
284 | |
285 char* const base_addr = committed_low_addr(); | |
286 bool result = special() || os::uncommit_memory(base_addr, bytes); | |
287 if (result) { | |
288 _committed_low_addr += bytes; | |
289 } | |
290 | |
291 return result; | |
292 } | |
293 | |
294 size_t PSVirtualSpaceHighToLow::expand_into(PSVirtualSpace* other_space, | |
295 size_t bytes) { | |
296 assert(is_aligned(bytes), "arg not aligned"); | |
297 assert(grows_down(), "this space must grow down"); | |
298 assert(other_space->grows_up(), "other space must grow up"); | |
299 assert(reserved_low_addr() == other_space->reserved_high_addr(), | |
300 "spaces not contiguous"); | |
301 assert(special() == other_space->special(), "one space is special in memory, the other is not"); | |
302 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); | |
303 DEBUG_ONLY(PSVirtualSpaceVerifier other_verifier(other_space)); | |
304 | |
305 size_t bytes_needed = bytes; | |
306 | |
307 // First use the uncommitted region in this space. | |
308 size_t tmp_bytes = MIN2(uncommitted_size(), bytes_needed); | |
309 if (tmp_bytes > 0) { | |
310 if (expand_by(tmp_bytes)) { | |
311 bytes_needed -= tmp_bytes; | |
312 } else { | |
313 return 0; | |
314 } | |
315 } | |
316 | |
317 // Next take from the uncommitted region in the other space, and commit it. | |
318 tmp_bytes = MIN2(other_space->uncommitted_size(), bytes_needed); | |
319 if (tmp_bytes > 0) { | |
320 char* const commit_base = committed_low_addr() - tmp_bytes; | |
321 if (other_space->special() || | |
322 os::commit_memory(commit_base, tmp_bytes, alignment())) { | |
323 // Reduce the reserved region in the other space. | |
324 other_space->set_reserved(other_space->reserved_low_addr(), | |
325 other_space->reserved_high_addr() - tmp_bytes, | |
326 other_space->special()); | |
327 | |
328 // Grow both reserved and committed in this space. | |
329 _reserved_low_addr -= tmp_bytes; | |
330 _committed_low_addr -= tmp_bytes; | |
331 bytes_needed -= tmp_bytes; | |
332 } else { | |
333 return bytes - bytes_needed; | |
334 } | |
335 } | |
336 | |
337 // Finally take from the already committed region in the other space. | |
338 tmp_bytes = bytes_needed; | |
339 if (tmp_bytes > 0) { | |
340 // Reduce both committed and reserved in the other space. | |
341 other_space->set_committed(other_space->committed_low_addr(), | |
342 other_space->committed_high_addr() - tmp_bytes); | |
343 other_space->set_reserved(other_space->reserved_low_addr(), | |
344 other_space->reserved_high_addr() - tmp_bytes, | |
345 other_space->special()); | |
346 | |
347 // Grow both reserved and committed in this space. | |
348 _reserved_low_addr -= tmp_bytes; | |
349 _committed_low_addr -= tmp_bytes; | |
350 } | |
351 | |
352 return bytes; | |
353 } | |
354 | |
355 void | |
356 PSVirtualSpaceHighToLow::print_space_boundaries_on(outputStream* st) const { | |
357 st->print_cr(" (" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT "]", | |
358 high_boundary(), low(), low_boundary()); | |
359 } |