1 /* 2 * Copyright (c) 2003, 2009, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * 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)); 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 } 80 81 bool PSVirtualSpace::expand_by(size_t bytes) { 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 249 bool PSVirtualSpaceHighToLow::expand_by(size_t bytes) { 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 }