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