Tue, 07 Oct 2008 11:01:35 -0700
Merge
1 /*
2 * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
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 */
25 #include "incls/_precompiled.incl"
26 #include "incls/_psVirtualspace.cpp.incl"
28 // PSVirtualSpace
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 }
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 }
46 // Deprecated.
47 PSVirtualSpace::PSVirtualSpace(): _alignment(os::vm_page_size()) {
48 }
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());
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 }
63 PSVirtualSpace::~PSVirtualSpace() {
64 release();
65 }
67 bool PSVirtualSpace::contains(void* p) const {
68 char* const cp = (char*)p;
69 return cp >= committed_low_addr() && cp < committed_high_addr();
70 }
72 void PSVirtualSpace::release() {
73 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
74 // This may not release memory it didn't reserve.
75 // Use rs.release() to release the underlying memory instead.
76 _reserved_low_addr = _reserved_high_addr = NULL;
77 _committed_low_addr = _committed_high_addr = NULL;
78 _special = false;
79 }
81 bool PSVirtualSpace::expand_by(size_t bytes, bool pre_touch) {
82 assert(is_aligned(bytes), "arg not aligned");
83 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
85 if (uncommitted_size() < bytes) {
86 return false;
87 }
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 }
95 if (pre_touch || AlwaysPreTouch) {
96 for (char* curr = base_addr;
97 curr < _committed_high_addr;
98 curr += os::vm_page_size()) {
99 char tmp = *curr;
100 *curr = 0;
101 }
102 }
104 return result;
105 }
107 bool PSVirtualSpace::shrink_by(size_t bytes) {
108 assert(is_aligned(bytes), "arg not aligned");
109 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
111 if (committed_size() < bytes) {
112 return false;
113 }
115 char* const base_addr = committed_high_addr() - bytes;
116 bool result = special() || os::uncommit_memory(base_addr, bytes);
117 if (result) {
118 _committed_high_addr -= bytes;
119 }
121 return result;
122 }
124 size_t
125 PSVirtualSpace::expand_into(PSVirtualSpace* other_space, size_t bytes) {
126 assert(is_aligned(bytes), "arg not aligned");
127 assert(grows_up(), "this space must grow up");
128 assert(other_space->grows_down(), "other space must grow down");
129 assert(reserved_high_addr() == other_space->reserved_low_addr(),
130 "spaces not contiguous");
131 assert(special() == other_space->special(), "one space is special, the other is not");
132 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
133 DEBUG_ONLY(PSVirtualSpaceVerifier other_verifier(other_space));
135 size_t bytes_needed = bytes;
137 // First use the uncommitted region in this space.
138 size_t tmp_bytes = MIN2(uncommitted_size(), bytes_needed);
139 if (tmp_bytes > 0) {
140 if (expand_by(tmp_bytes)) {
141 bytes_needed -= tmp_bytes;
142 } else {
143 return 0;
144 }
145 }
147 // Next take from the uncommitted region in the other space, and commit it.
148 tmp_bytes = MIN2(other_space->uncommitted_size(), bytes_needed);
149 if (tmp_bytes > 0) {
150 char* const commit_base = committed_high_addr();
151 if (other_space->special() ||
152 os::commit_memory(commit_base, tmp_bytes, alignment())) {
153 // Reduce the reserved region in the other space.
154 other_space->set_reserved(other_space->reserved_low_addr() + tmp_bytes,
155 other_space->reserved_high_addr(),
156 other_space->special());
158 // Grow both reserved and committed in this space.
159 _reserved_high_addr += tmp_bytes;
160 _committed_high_addr += tmp_bytes;
161 bytes_needed -= tmp_bytes;
162 } else {
163 return bytes - bytes_needed;
164 }
165 }
167 // Finally take from the already committed region in the other space.
168 tmp_bytes = bytes_needed;
169 if (tmp_bytes > 0) {
170 // Reduce both committed and reserved in the other space.
171 other_space->set_committed(other_space->committed_low_addr() + tmp_bytes,
172 other_space->committed_high_addr());
173 other_space->set_reserved(other_space->reserved_low_addr() + tmp_bytes,
174 other_space->reserved_high_addr(),
175 other_space->special());
177 // Grow both reserved and committed in this space.
178 _reserved_high_addr += tmp_bytes;
179 _committed_high_addr += tmp_bytes;
180 }
182 return bytes;
183 }
185 #ifndef PRODUCT
186 bool PSVirtualSpace::is_aligned(size_t value, size_t align) {
187 const size_t tmp_value = value + align - 1;
188 const size_t mask = ~(align - 1);
189 return (tmp_value & mask) == value;
190 }
192 bool PSVirtualSpace::is_aligned(size_t value) const {
193 return is_aligned(value, alignment());
194 }
196 bool PSVirtualSpace::is_aligned(char* value) const {
197 return is_aligned((size_t)value);
198 }
200 void PSVirtualSpace::verify() const {
201 assert(is_aligned(alignment(), os::vm_page_size()), "bad alignment");
202 assert(is_aligned(reserved_low_addr()), "bad reserved_low_addr");
203 assert(is_aligned(reserved_high_addr()), "bad reserved_high_addr");
204 assert(is_aligned(committed_low_addr()), "bad committed_low_addr");
205 assert(is_aligned(committed_high_addr()), "bad committed_high_addr");
207 // Reserved region must be non-empty or both addrs must be 0.
208 assert(reserved_low_addr() < reserved_high_addr() ||
209 reserved_low_addr() == NULL && reserved_high_addr() == NULL,
210 "bad reserved addrs");
211 assert(committed_low_addr() <= committed_high_addr(), "bad committed addrs");
213 if (grows_up()) {
214 assert(reserved_low_addr() == committed_low_addr(), "bad low addrs");
215 assert(reserved_high_addr() >= committed_high_addr(), "bad high addrs");
216 } else {
217 assert(reserved_high_addr() == committed_high_addr(), "bad high addrs");
218 assert(reserved_low_addr() <= committed_low_addr(), "bad low addrs");
219 }
220 }
222 void PSVirtualSpace::print() const {
223 gclog_or_tty->print_cr("virtual space [" PTR_FORMAT "]: alignment="
224 SIZE_FORMAT "K grows %s%s",
225 this, alignment() / K, grows_up() ? "up" : "down",
226 special() ? " (pinned in memory)" : "");
227 gclog_or_tty->print_cr(" reserved=" SIZE_FORMAT "K"
228 " [" PTR_FORMAT "," PTR_FORMAT "]"
229 " committed=" SIZE_FORMAT "K"
230 " [" PTR_FORMAT "," PTR_FORMAT "]",
231 reserved_size() / K,
232 reserved_low_addr(), reserved_high_addr(),
233 committed_size() / K,
234 committed_low_addr(), committed_high_addr());
235 }
236 #endif // #ifndef PRODUCT
238 void PSVirtualSpace::print_space_boundaries_on(outputStream* st) const {
239 st->print_cr(" [" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT ")",
240 low_boundary(), high(), high_boundary());
241 }
243 PSVirtualSpaceHighToLow::PSVirtualSpaceHighToLow(ReservedSpace rs,
244 size_t alignment) :
245 PSVirtualSpace(alignment)
246 {
247 set_reserved(rs);
248 set_committed(reserved_high_addr(), reserved_high_addr());
249 DEBUG_ONLY(verify());
250 }
252 PSVirtualSpaceHighToLow::PSVirtualSpaceHighToLow(ReservedSpace rs) {
253 set_reserved(rs);
254 set_committed(reserved_high_addr(), reserved_high_addr());
255 DEBUG_ONLY(verify());
256 }
258 bool PSVirtualSpaceHighToLow::expand_by(size_t bytes, bool pre_touch) {
259 assert(is_aligned(bytes), "arg not aligned");
260 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
262 if (uncommitted_size() < bytes) {
263 return false;
264 }
266 char* const base_addr = committed_low_addr() - bytes;
267 bool result = special() || os::commit_memory(base_addr, bytes, alignment());
268 if (result) {
269 _committed_low_addr -= bytes;
270 }
272 if (pre_touch || AlwaysPreTouch) {
273 for (char* curr = base_addr;
274 curr < _committed_high_addr;
275 curr += os::vm_page_size()) {
276 char tmp = *curr;
277 *curr = 0;
278 }
279 }
281 return result;
282 }
284 bool PSVirtualSpaceHighToLow::shrink_by(size_t bytes) {
285 assert(is_aligned(bytes), "arg not aligned");
286 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
288 if (committed_size() < bytes) {
289 return false;
290 }
292 char* const base_addr = committed_low_addr();
293 bool result = special() || os::uncommit_memory(base_addr, bytes);
294 if (result) {
295 _committed_low_addr += bytes;
296 }
298 return result;
299 }
301 size_t PSVirtualSpaceHighToLow::expand_into(PSVirtualSpace* other_space,
302 size_t bytes) {
303 assert(is_aligned(bytes), "arg not aligned");
304 assert(grows_down(), "this space must grow down");
305 assert(other_space->grows_up(), "other space must grow up");
306 assert(reserved_low_addr() == other_space->reserved_high_addr(),
307 "spaces not contiguous");
308 assert(special() == other_space->special(), "one space is special in memory, the other is not");
309 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
310 DEBUG_ONLY(PSVirtualSpaceVerifier other_verifier(other_space));
312 size_t bytes_needed = bytes;
314 // First use the uncommitted region in this space.
315 size_t tmp_bytes = MIN2(uncommitted_size(), bytes_needed);
316 if (tmp_bytes > 0) {
317 if (expand_by(tmp_bytes)) {
318 bytes_needed -= tmp_bytes;
319 } else {
320 return 0;
321 }
322 }
324 // Next take from the uncommitted region in the other space, and commit it.
325 tmp_bytes = MIN2(other_space->uncommitted_size(), bytes_needed);
326 if (tmp_bytes > 0) {
327 char* const commit_base = committed_low_addr() - tmp_bytes;
328 if (other_space->special() ||
329 os::commit_memory(commit_base, tmp_bytes, alignment())) {
330 // Reduce the reserved region in the other space.
331 other_space->set_reserved(other_space->reserved_low_addr(),
332 other_space->reserved_high_addr() - tmp_bytes,
333 other_space->special());
335 // Grow both reserved and committed in this space.
336 _reserved_low_addr -= tmp_bytes;
337 _committed_low_addr -= tmp_bytes;
338 bytes_needed -= tmp_bytes;
339 } else {
340 return bytes - bytes_needed;
341 }
342 }
344 // Finally take from the already committed region in the other space.
345 tmp_bytes = bytes_needed;
346 if (tmp_bytes > 0) {
347 // Reduce both committed and reserved in the other space.
348 other_space->set_committed(other_space->committed_low_addr(),
349 other_space->committed_high_addr() - tmp_bytes);
350 other_space->set_reserved(other_space->reserved_low_addr(),
351 other_space->reserved_high_addr() - tmp_bytes,
352 other_space->special());
354 // Grow both reserved and committed in this space.
355 _reserved_low_addr -= tmp_bytes;
356 _committed_low_addr -= tmp_bytes;
357 }
359 return bytes;
360 }
362 void
363 PSVirtualSpaceHighToLow::print_space_boundaries_on(outputStream* st) const {
364 st->print_cr(" (" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT "]",
365 high_boundary(), low(), low_boundary());
366 }