Mercurial > hg > graal-compiler
annotate src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp @ 1091:6aa7255741f3
6906727: UseCompressedOops: some card-marking fixes related to object arrays
Summary: Introduced a new write_ref_array(HeapWords* start, size_t count) method that does the requisite MemRegion range calculation so (some of the) clients of the erstwhile write_ref_array(MemRegion mr) do not need to worry. This removed all external uses of array_size(), which was also simplified and made private. Asserts were added to catch other possible issues. Further, less essential, fixes stemming from this investigation are deferred to CR 6904516 (to follow shortly in hs17).
Reviewed-by: kvn, coleenp, jmasa
author | ysr |
---|---|
date | Thu, 03 Dec 2009 15:01:57 -0800 |
parents | 0fbdb4381b99 |
children | c18cbe5936b8 |
rev | line source |
---|---|
0 | 1 /* |
579 | 2 * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 #include "incls/_precompiled.incl" | |
26 #include "incls/_psVirtualspace.cpp.incl" | |
27 | |
28 // PSVirtualSpace | |
29 | |
30 PSVirtualSpace::PSVirtualSpace(ReservedSpace rs, size_t alignment) : | |
31 _alignment(alignment) | |
32 { | |
33 set_reserved(rs); | |
34 set_committed(reserved_low_addr(), reserved_low_addr()); | |
35 DEBUG_ONLY(verify()); | |
36 } | |
37 | |
38 PSVirtualSpace::PSVirtualSpace(ReservedSpace rs) : | |
39 _alignment(os::vm_page_size()) | |
40 { | |
41 set_reserved(rs); | |
42 set_committed(reserved_low_addr(), reserved_low_addr()); | |
43 DEBUG_ONLY(verify()); | |
44 } | |
45 | |
46 // Deprecated. | |
47 PSVirtualSpace::PSVirtualSpace(): _alignment(os::vm_page_size()) { | |
48 } | |
49 | |
50 // Deprecated. | |
51 bool PSVirtualSpace::initialize(ReservedSpace rs, | |
52 size_t commit_size) { | |
53 set_reserved(rs); | |
54 set_committed(reserved_low_addr(), reserved_low_addr()); | |
55 | |
56 // Commit to initial size. | |
57 assert(commit_size <= rs.size(), "commit_size too big"); | |
58 bool result = commit_size > 0 ? expand_by(commit_size) : true; | |
59 DEBUG_ONLY(verify()); | |
60 return result; | |
61 } | |
62 | |
63 PSVirtualSpace::~PSVirtualSpace() { | |
64 release(); | |
65 } | |
66 | |
67 bool PSVirtualSpace::contains(void* p) const { | |
68 char* const cp = (char*)p; | |
69 return cp >= committed_low_addr() && cp < committed_high_addr(); | |
70 } | |
71 | |
72 void PSVirtualSpace::release() { | |
73 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); | |
237
1fdb98a17101
6716785: implicit null checks not triggering with CompressedOops
coleenp
parents:
0
diff
changeset
|
74 // This may not release memory it didn't reserve. |
1fdb98a17101
6716785: implicit null checks not triggering with CompressedOops
coleenp
parents:
0
diff
changeset
|
75 // Use rs.release() to release the underlying memory instead. |
0 | 76 _reserved_low_addr = _reserved_high_addr = NULL; |
77 _committed_low_addr = _committed_high_addr = NULL; | |
78 _special = false; | |
79 } | |
80 | |
535
4e400c36026f
6783381: NUMA allocator: don't pretouch eden space with UseNUMA
iveresov
parents:
337
diff
changeset
|
81 bool PSVirtualSpace::expand_by(size_t bytes) { |
0 | 82 assert(is_aligned(bytes), "arg not aligned"); |
83 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); | |
84 | |
85 if (uncommitted_size() < bytes) { | |
86 return false; | |
87 } | |
88 | |
89 char* const base_addr = committed_high_addr(); | |
90 bool result = special() || os::commit_memory(base_addr, bytes, alignment()); | |
91 if (result) { | |
92 _committed_high_addr += bytes; | |
93 } | |
94 | |
95 return result; | |
96 } | |
97 | |
98 bool PSVirtualSpace::shrink_by(size_t bytes) { | |
99 assert(is_aligned(bytes), "arg not aligned"); | |
100 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); | |
101 | |
102 if (committed_size() < bytes) { | |
103 return false; | |
104 } | |
105 | |
106 char* const base_addr = committed_high_addr() - bytes; | |
107 bool result = special() || os::uncommit_memory(base_addr, bytes); | |
108 if (result) { | |
109 _committed_high_addr -= bytes; | |
110 } | |
111 | |
112 return result; | |
113 } | |
114 | |
115 size_t | |
116 PSVirtualSpace::expand_into(PSVirtualSpace* other_space, size_t bytes) { | |
117 assert(is_aligned(bytes), "arg not aligned"); | |
118 assert(grows_up(), "this space must grow up"); | |
119 assert(other_space->grows_down(), "other space must grow down"); | |
120 assert(reserved_high_addr() == other_space->reserved_low_addr(), | |
121 "spaces not contiguous"); | |
122 assert(special() == other_space->special(), "one space is special, the other is not"); | |
123 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); | |
124 DEBUG_ONLY(PSVirtualSpaceVerifier other_verifier(other_space)); | |
125 | |
126 size_t bytes_needed = bytes; | |
127 | |
128 // First use the uncommitted region in this space. | |
129 size_t tmp_bytes = MIN2(uncommitted_size(), bytes_needed); | |
130 if (tmp_bytes > 0) { | |
131 if (expand_by(tmp_bytes)) { | |
132 bytes_needed -= tmp_bytes; | |
133 } else { | |
134 return 0; | |
135 } | |
136 } | |
137 | |
138 // Next take from the uncommitted region in the other space, and commit it. | |
139 tmp_bytes = MIN2(other_space->uncommitted_size(), bytes_needed); | |
140 if (tmp_bytes > 0) { | |
141 char* const commit_base = committed_high_addr(); | |
142 if (other_space->special() || | |
143 os::commit_memory(commit_base, tmp_bytes, alignment())) { | |
144 // Reduce the reserved region in the other space. | |
145 other_space->set_reserved(other_space->reserved_low_addr() + tmp_bytes, | |
146 other_space->reserved_high_addr(), | |
147 other_space->special()); | |
148 | |
149 // Grow both reserved and committed in this space. | |
150 _reserved_high_addr += tmp_bytes; | |
151 _committed_high_addr += tmp_bytes; | |
152 bytes_needed -= tmp_bytes; | |
153 } else { | |
154 return bytes - bytes_needed; | |
155 } | |
156 } | |
157 | |
158 // Finally take from the already committed region in the other space. | |
159 tmp_bytes = bytes_needed; | |
160 if (tmp_bytes > 0) { | |
161 // Reduce both committed and reserved in the other space. | |
162 other_space->set_committed(other_space->committed_low_addr() + tmp_bytes, | |
163 other_space->committed_high_addr()); | |
164 other_space->set_reserved(other_space->reserved_low_addr() + tmp_bytes, | |
165 other_space->reserved_high_addr(), | |
166 other_space->special()); | |
167 | |
168 // Grow both reserved and committed in this space. | |
169 _reserved_high_addr += tmp_bytes; | |
170 _committed_high_addr += tmp_bytes; | |
171 } | |
172 | |
173 return bytes; | |
174 } | |
175 | |
176 #ifndef PRODUCT | |
177 bool PSVirtualSpace::is_aligned(size_t value, size_t align) { | |
178 const size_t tmp_value = value + align - 1; | |
179 const size_t mask = ~(align - 1); | |
180 return (tmp_value & mask) == value; | |
181 } | |
182 | |
183 bool PSVirtualSpace::is_aligned(size_t value) const { | |
184 return is_aligned(value, alignment()); | |
185 } | |
186 | |
187 bool PSVirtualSpace::is_aligned(char* value) const { | |
188 return is_aligned((size_t)value); | |
189 } | |
190 | |
191 void PSVirtualSpace::verify() const { | |
192 assert(is_aligned(alignment(), os::vm_page_size()), "bad alignment"); | |
193 assert(is_aligned(reserved_low_addr()), "bad reserved_low_addr"); | |
194 assert(is_aligned(reserved_high_addr()), "bad reserved_high_addr"); | |
195 assert(is_aligned(committed_low_addr()), "bad committed_low_addr"); | |
196 assert(is_aligned(committed_high_addr()), "bad committed_high_addr"); | |
197 | |
198 // Reserved region must be non-empty or both addrs must be 0. | |
199 assert(reserved_low_addr() < reserved_high_addr() || | |
200 reserved_low_addr() == NULL && reserved_high_addr() == NULL, | |
201 "bad reserved addrs"); | |
202 assert(committed_low_addr() <= committed_high_addr(), "bad committed addrs"); | |
203 | |
204 if (grows_up()) { | |
205 assert(reserved_low_addr() == committed_low_addr(), "bad low addrs"); | |
206 assert(reserved_high_addr() >= committed_high_addr(), "bad high addrs"); | |
207 } else { | |
208 assert(reserved_high_addr() == committed_high_addr(), "bad high addrs"); | |
209 assert(reserved_low_addr() <= committed_low_addr(), "bad low addrs"); | |
210 } | |
211 } | |
212 | |
213 void PSVirtualSpace::print() const { | |
214 gclog_or_tty->print_cr("virtual space [" PTR_FORMAT "]: alignment=" | |
215 SIZE_FORMAT "K grows %s%s", | |
216 this, alignment() / K, grows_up() ? "up" : "down", | |
217 special() ? " (pinned in memory)" : ""); | |
218 gclog_or_tty->print_cr(" reserved=" SIZE_FORMAT "K" | |
219 " [" PTR_FORMAT "," PTR_FORMAT "]" | |
220 " committed=" SIZE_FORMAT "K" | |
221 " [" PTR_FORMAT "," PTR_FORMAT "]", | |
222 reserved_size() / K, | |
223 reserved_low_addr(), reserved_high_addr(), | |
224 committed_size() / K, | |
225 committed_low_addr(), committed_high_addr()); | |
226 } | |
227 #endif // #ifndef PRODUCT | |
228 | |
229 void PSVirtualSpace::print_space_boundaries_on(outputStream* st) const { | |
230 st->print_cr(" [" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT ")", | |
231 low_boundary(), high(), high_boundary()); | |
232 } | |
233 | |
234 PSVirtualSpaceHighToLow::PSVirtualSpaceHighToLow(ReservedSpace rs, | |
235 size_t alignment) : | |
236 PSVirtualSpace(alignment) | |
237 { | |
238 set_reserved(rs); | |
239 set_committed(reserved_high_addr(), reserved_high_addr()); | |
240 DEBUG_ONLY(verify()); | |
241 } | |
242 | |
243 PSVirtualSpaceHighToLow::PSVirtualSpaceHighToLow(ReservedSpace rs) { | |
244 set_reserved(rs); | |
245 set_committed(reserved_high_addr(), reserved_high_addr()); | |
246 DEBUG_ONLY(verify()); | |
247 } | |
248 | |
535
4e400c36026f
6783381: NUMA allocator: don't pretouch eden space with UseNUMA
iveresov
parents:
337
diff
changeset
|
249 bool PSVirtualSpaceHighToLow::expand_by(size_t bytes) { |
0 | 250 assert(is_aligned(bytes), "arg not aligned"); |
251 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); | |
252 | |
253 if (uncommitted_size() < bytes) { | |
254 return false; | |
255 } | |
256 | |
257 char* const base_addr = committed_low_addr() - bytes; | |
258 bool result = special() || os::commit_memory(base_addr, bytes, alignment()); | |
259 if (result) { | |
260 _committed_low_addr -= bytes; | |
261 } | |
262 | |
263 return result; | |
264 } | |
265 | |
266 bool PSVirtualSpaceHighToLow::shrink_by(size_t bytes) { | |
267 assert(is_aligned(bytes), "arg not aligned"); | |
268 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); | |
269 | |
270 if (committed_size() < bytes) { | |
271 return false; | |
272 } | |
273 | |
274 char* const base_addr = committed_low_addr(); | |
275 bool result = special() || os::uncommit_memory(base_addr, bytes); | |
276 if (result) { | |
277 _committed_low_addr += bytes; | |
278 } | |
279 | |
280 return result; | |
281 } | |
282 | |
283 size_t PSVirtualSpaceHighToLow::expand_into(PSVirtualSpace* other_space, | |
284 size_t bytes) { | |
285 assert(is_aligned(bytes), "arg not aligned"); | |
286 assert(grows_down(), "this space must grow down"); | |
287 assert(other_space->grows_up(), "other space must grow up"); | |
288 assert(reserved_low_addr() == other_space->reserved_high_addr(), | |
289 "spaces not contiguous"); | |
290 assert(special() == other_space->special(), "one space is special in memory, the other is not"); | |
291 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); | |
292 DEBUG_ONLY(PSVirtualSpaceVerifier other_verifier(other_space)); | |
293 | |
294 size_t bytes_needed = bytes; | |
295 | |
296 // First use the uncommitted region in this space. | |
297 size_t tmp_bytes = MIN2(uncommitted_size(), bytes_needed); | |
298 if (tmp_bytes > 0) { | |
299 if (expand_by(tmp_bytes)) { | |
300 bytes_needed -= tmp_bytes; | |
301 } else { | |
302 return 0; | |
303 } | |
304 } | |
305 | |
306 // Next take from the uncommitted region in the other space, and commit it. | |
307 tmp_bytes = MIN2(other_space->uncommitted_size(), bytes_needed); | |
308 if (tmp_bytes > 0) { | |
309 char* const commit_base = committed_low_addr() - tmp_bytes; | |
310 if (other_space->special() || | |
311 os::commit_memory(commit_base, tmp_bytes, alignment())) { | |
312 // Reduce the reserved region in the other space. | |
313 other_space->set_reserved(other_space->reserved_low_addr(), | |
314 other_space->reserved_high_addr() - tmp_bytes, | |
315 other_space->special()); | |
316 | |
317 // Grow both reserved and committed in this space. | |
318 _reserved_low_addr -= tmp_bytes; | |
319 _committed_low_addr -= tmp_bytes; | |
320 bytes_needed -= tmp_bytes; | |
321 } else { | |
322 return bytes - bytes_needed; | |
323 } | |
324 } | |
325 | |
326 // Finally take from the already committed region in the other space. | |
327 tmp_bytes = bytes_needed; | |
328 if (tmp_bytes > 0) { | |
329 // Reduce both committed and reserved in the other space. | |
330 other_space->set_committed(other_space->committed_low_addr(), | |
331 other_space->committed_high_addr() - tmp_bytes); | |
332 other_space->set_reserved(other_space->reserved_low_addr(), | |
333 other_space->reserved_high_addr() - tmp_bytes, | |
334 other_space->special()); | |
335 | |
336 // Grow both reserved and committed in this space. | |
337 _reserved_low_addr -= tmp_bytes; | |
338 _committed_low_addr -= tmp_bytes; | |
339 } | |
340 | |
341 return bytes; | |
342 } | |
343 | |
344 void | |
345 PSVirtualSpaceHighToLow::print_space_boundaries_on(outputStream* st) const { | |
346 st->print_cr(" (" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT "]", | |
347 high_boundary(), low(), low_boundary()); | |
348 } |