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