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