src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp

Thu, 22 Sep 2011 10:57:37 -0700

author
johnc
date
Thu, 22 Sep 2011 10:57:37 -0700
changeset 3175
4dfb2df418f2
parent 2314
f95d63e2154a
child 3156
f08d439fab8c
permissions
-rw-r--r--

6484982: G1: process references during evacuation pauses
Summary: G1 now uses two reference processors - one is used by concurrent marking and the other is used by STW GCs (both full and incremental evacuation pauses). In an evacuation pause, the reference processor is embedded into the closures used to scan objects. Doing so causes causes reference objects to be 'discovered' by the reference processor. At the end of the evacuation pause, these discovered reference objects are processed - preserving (and copying) referent objects (and their reachable graphs) as appropriate.
Reviewed-by: ysr, jwilhelm, brutisso, stefank, tonyp

duke@435 1 /*
stefank@2314 2 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
stefank@2314 25 #include "precompiled.hpp"
stefank@2314 26 #include "gc_implementation/parallelScavenge/psVirtualspace.hpp"
stefank@2314 27 #include "runtime/os.hpp"
stefank@2314 28 #include "runtime/virtualspace.hpp"
stefank@2314 29 #ifdef TARGET_OS_FAMILY_linux
stefank@2314 30 # include "os_linux.inline.hpp"
stefank@2314 31 #endif
stefank@2314 32 #ifdef TARGET_OS_FAMILY_solaris
stefank@2314 33 # include "os_solaris.inline.hpp"
stefank@2314 34 #endif
stefank@2314 35 #ifdef TARGET_OS_FAMILY_windows
stefank@2314 36 # include "os_windows.inline.hpp"
stefank@2314 37 #endif
duke@435 38
duke@435 39 // PSVirtualSpace
duke@435 40
duke@435 41 PSVirtualSpace::PSVirtualSpace(ReservedSpace rs, size_t alignment) :
duke@435 42 _alignment(alignment)
duke@435 43 {
duke@435 44 set_reserved(rs);
duke@435 45 set_committed(reserved_low_addr(), reserved_low_addr());
duke@435 46 DEBUG_ONLY(verify());
duke@435 47 }
duke@435 48
duke@435 49 PSVirtualSpace::PSVirtualSpace(ReservedSpace rs) :
duke@435 50 _alignment(os::vm_page_size())
duke@435 51 {
duke@435 52 set_reserved(rs);
duke@435 53 set_committed(reserved_low_addr(), reserved_low_addr());
duke@435 54 DEBUG_ONLY(verify());
duke@435 55 }
duke@435 56
duke@435 57 // Deprecated.
duke@435 58 PSVirtualSpace::PSVirtualSpace(): _alignment(os::vm_page_size()) {
duke@435 59 }
duke@435 60
duke@435 61 // Deprecated.
duke@435 62 bool PSVirtualSpace::initialize(ReservedSpace rs,
duke@435 63 size_t commit_size) {
duke@435 64 set_reserved(rs);
duke@435 65 set_committed(reserved_low_addr(), reserved_low_addr());
duke@435 66
duke@435 67 // Commit to initial size.
duke@435 68 assert(commit_size <= rs.size(), "commit_size too big");
duke@435 69 bool result = commit_size > 0 ? expand_by(commit_size) : true;
duke@435 70 DEBUG_ONLY(verify());
duke@435 71 return result;
duke@435 72 }
duke@435 73
duke@435 74 PSVirtualSpace::~PSVirtualSpace() {
duke@435 75 release();
duke@435 76 }
duke@435 77
duke@435 78 bool PSVirtualSpace::contains(void* p) const {
duke@435 79 char* const cp = (char*)p;
duke@435 80 return cp >= committed_low_addr() && cp < committed_high_addr();
duke@435 81 }
duke@435 82
duke@435 83 void PSVirtualSpace::release() {
duke@435 84 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
coleenp@672 85 // This may not release memory it didn't reserve.
coleenp@672 86 // Use rs.release() to release the underlying memory instead.
duke@435 87 _reserved_low_addr = _reserved_high_addr = NULL;
duke@435 88 _committed_low_addr = _committed_high_addr = NULL;
duke@435 89 _special = false;
duke@435 90 }
duke@435 91
iveresov@970 92 bool PSVirtualSpace::expand_by(size_t bytes) {
duke@435 93 assert(is_aligned(bytes), "arg not aligned");
duke@435 94 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
duke@435 95
duke@435 96 if (uncommitted_size() < bytes) {
duke@435 97 return false;
duke@435 98 }
duke@435 99
duke@435 100 char* const base_addr = committed_high_addr();
duke@435 101 bool result = special() || os::commit_memory(base_addr, bytes, alignment());
duke@435 102 if (result) {
duke@435 103 _committed_high_addr += bytes;
duke@435 104 }
duke@435 105
duke@435 106 return result;
duke@435 107 }
duke@435 108
duke@435 109 bool PSVirtualSpace::shrink_by(size_t bytes) {
duke@435 110 assert(is_aligned(bytes), "arg not aligned");
duke@435 111 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
duke@435 112
duke@435 113 if (committed_size() < bytes) {
duke@435 114 return false;
duke@435 115 }
duke@435 116
duke@435 117 char* const base_addr = committed_high_addr() - bytes;
duke@435 118 bool result = special() || os::uncommit_memory(base_addr, bytes);
duke@435 119 if (result) {
duke@435 120 _committed_high_addr -= bytes;
duke@435 121 }
duke@435 122
duke@435 123 return result;
duke@435 124 }
duke@435 125
duke@435 126 size_t
duke@435 127 PSVirtualSpace::expand_into(PSVirtualSpace* other_space, size_t bytes) {
duke@435 128 assert(is_aligned(bytes), "arg not aligned");
duke@435 129 assert(grows_up(), "this space must grow up");
duke@435 130 assert(other_space->grows_down(), "other space must grow down");
duke@435 131 assert(reserved_high_addr() == other_space->reserved_low_addr(),
duke@435 132 "spaces not contiguous");
duke@435 133 assert(special() == other_space->special(), "one space is special, the other is not");
duke@435 134 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
duke@435 135 DEBUG_ONLY(PSVirtualSpaceVerifier other_verifier(other_space));
duke@435 136
duke@435 137 size_t bytes_needed = bytes;
duke@435 138
duke@435 139 // First use the uncommitted region in this space.
duke@435 140 size_t tmp_bytes = MIN2(uncommitted_size(), bytes_needed);
duke@435 141 if (tmp_bytes > 0) {
duke@435 142 if (expand_by(tmp_bytes)) {
duke@435 143 bytes_needed -= tmp_bytes;
duke@435 144 } else {
duke@435 145 return 0;
duke@435 146 }
duke@435 147 }
duke@435 148
duke@435 149 // Next take from the uncommitted region in the other space, and commit it.
duke@435 150 tmp_bytes = MIN2(other_space->uncommitted_size(), bytes_needed);
duke@435 151 if (tmp_bytes > 0) {
duke@435 152 char* const commit_base = committed_high_addr();
duke@435 153 if (other_space->special() ||
duke@435 154 os::commit_memory(commit_base, tmp_bytes, alignment())) {
duke@435 155 // Reduce the reserved region in the other space.
duke@435 156 other_space->set_reserved(other_space->reserved_low_addr() + tmp_bytes,
duke@435 157 other_space->reserved_high_addr(),
duke@435 158 other_space->special());
duke@435 159
duke@435 160 // Grow both reserved and committed in this space.
duke@435 161 _reserved_high_addr += tmp_bytes;
duke@435 162 _committed_high_addr += tmp_bytes;
duke@435 163 bytes_needed -= tmp_bytes;
duke@435 164 } else {
duke@435 165 return bytes - bytes_needed;
duke@435 166 }
duke@435 167 }
duke@435 168
duke@435 169 // Finally take from the already committed region in the other space.
duke@435 170 tmp_bytes = bytes_needed;
duke@435 171 if (tmp_bytes > 0) {
duke@435 172 // Reduce both committed and reserved in the other space.
duke@435 173 other_space->set_committed(other_space->committed_low_addr() + tmp_bytes,
duke@435 174 other_space->committed_high_addr());
duke@435 175 other_space->set_reserved(other_space->reserved_low_addr() + tmp_bytes,
duke@435 176 other_space->reserved_high_addr(),
duke@435 177 other_space->special());
duke@435 178
duke@435 179 // Grow both reserved and committed in this space.
duke@435 180 _reserved_high_addr += tmp_bytes;
duke@435 181 _committed_high_addr += tmp_bytes;
duke@435 182 }
duke@435 183
duke@435 184 return bytes;
duke@435 185 }
duke@435 186
duke@435 187 #ifndef PRODUCT
duke@435 188 bool PSVirtualSpace::is_aligned(size_t value, size_t align) {
duke@435 189 const size_t tmp_value = value + align - 1;
duke@435 190 const size_t mask = ~(align - 1);
duke@435 191 return (tmp_value & mask) == value;
duke@435 192 }
duke@435 193
duke@435 194 bool PSVirtualSpace::is_aligned(size_t value) const {
duke@435 195 return is_aligned(value, alignment());
duke@435 196 }
duke@435 197
duke@435 198 bool PSVirtualSpace::is_aligned(char* value) const {
duke@435 199 return is_aligned((size_t)value);
duke@435 200 }
duke@435 201
duke@435 202 void PSVirtualSpace::verify() const {
duke@435 203 assert(is_aligned(alignment(), os::vm_page_size()), "bad alignment");
duke@435 204 assert(is_aligned(reserved_low_addr()), "bad reserved_low_addr");
duke@435 205 assert(is_aligned(reserved_high_addr()), "bad reserved_high_addr");
duke@435 206 assert(is_aligned(committed_low_addr()), "bad committed_low_addr");
duke@435 207 assert(is_aligned(committed_high_addr()), "bad committed_high_addr");
duke@435 208
duke@435 209 // Reserved region must be non-empty or both addrs must be 0.
duke@435 210 assert(reserved_low_addr() < reserved_high_addr() ||
duke@435 211 reserved_low_addr() == NULL && reserved_high_addr() == NULL,
duke@435 212 "bad reserved addrs");
duke@435 213 assert(committed_low_addr() <= committed_high_addr(), "bad committed addrs");
duke@435 214
duke@435 215 if (grows_up()) {
duke@435 216 assert(reserved_low_addr() == committed_low_addr(), "bad low addrs");
duke@435 217 assert(reserved_high_addr() >= committed_high_addr(), "bad high addrs");
duke@435 218 } else {
duke@435 219 assert(reserved_high_addr() == committed_high_addr(), "bad high addrs");
duke@435 220 assert(reserved_low_addr() <= committed_low_addr(), "bad low addrs");
duke@435 221 }
duke@435 222 }
duke@435 223
duke@435 224 void PSVirtualSpace::print() const {
duke@435 225 gclog_or_tty->print_cr("virtual space [" PTR_FORMAT "]: alignment="
duke@435 226 SIZE_FORMAT "K grows %s%s",
duke@435 227 this, alignment() / K, grows_up() ? "up" : "down",
duke@435 228 special() ? " (pinned in memory)" : "");
duke@435 229 gclog_or_tty->print_cr(" reserved=" SIZE_FORMAT "K"
duke@435 230 " [" PTR_FORMAT "," PTR_FORMAT "]"
duke@435 231 " committed=" SIZE_FORMAT "K"
duke@435 232 " [" PTR_FORMAT "," PTR_FORMAT "]",
duke@435 233 reserved_size() / K,
duke@435 234 reserved_low_addr(), reserved_high_addr(),
duke@435 235 committed_size() / K,
duke@435 236 committed_low_addr(), committed_high_addr());
duke@435 237 }
duke@435 238 #endif // #ifndef PRODUCT
duke@435 239
duke@435 240 void PSVirtualSpace::print_space_boundaries_on(outputStream* st) const {
duke@435 241 st->print_cr(" [" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT ")",
duke@435 242 low_boundary(), high(), high_boundary());
duke@435 243 }
duke@435 244
duke@435 245 PSVirtualSpaceHighToLow::PSVirtualSpaceHighToLow(ReservedSpace rs,
duke@435 246 size_t alignment) :
duke@435 247 PSVirtualSpace(alignment)
duke@435 248 {
duke@435 249 set_reserved(rs);
duke@435 250 set_committed(reserved_high_addr(), reserved_high_addr());
duke@435 251 DEBUG_ONLY(verify());
duke@435 252 }
duke@435 253
duke@435 254 PSVirtualSpaceHighToLow::PSVirtualSpaceHighToLow(ReservedSpace rs) {
duke@435 255 set_reserved(rs);
duke@435 256 set_committed(reserved_high_addr(), reserved_high_addr());
duke@435 257 DEBUG_ONLY(verify());
duke@435 258 }
duke@435 259
iveresov@970 260 bool PSVirtualSpaceHighToLow::expand_by(size_t bytes) {
duke@435 261 assert(is_aligned(bytes), "arg not aligned");
duke@435 262 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
duke@435 263
duke@435 264 if (uncommitted_size() < bytes) {
duke@435 265 return false;
duke@435 266 }
duke@435 267
duke@435 268 char* const base_addr = committed_low_addr() - bytes;
duke@435 269 bool result = special() || os::commit_memory(base_addr, bytes, alignment());
duke@435 270 if (result) {
duke@435 271 _committed_low_addr -= bytes;
duke@435 272 }
duke@435 273
duke@435 274 return result;
duke@435 275 }
duke@435 276
duke@435 277 bool PSVirtualSpaceHighToLow::shrink_by(size_t bytes) {
duke@435 278 assert(is_aligned(bytes), "arg not aligned");
duke@435 279 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
duke@435 280
duke@435 281 if (committed_size() < bytes) {
duke@435 282 return false;
duke@435 283 }
duke@435 284
duke@435 285 char* const base_addr = committed_low_addr();
duke@435 286 bool result = special() || os::uncommit_memory(base_addr, bytes);
duke@435 287 if (result) {
duke@435 288 _committed_low_addr += bytes;
duke@435 289 }
duke@435 290
duke@435 291 return result;
duke@435 292 }
duke@435 293
duke@435 294 size_t PSVirtualSpaceHighToLow::expand_into(PSVirtualSpace* other_space,
duke@435 295 size_t bytes) {
duke@435 296 assert(is_aligned(bytes), "arg not aligned");
duke@435 297 assert(grows_down(), "this space must grow down");
duke@435 298 assert(other_space->grows_up(), "other space must grow up");
duke@435 299 assert(reserved_low_addr() == other_space->reserved_high_addr(),
duke@435 300 "spaces not contiguous");
duke@435 301 assert(special() == other_space->special(), "one space is special in memory, the other is not");
duke@435 302 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
duke@435 303 DEBUG_ONLY(PSVirtualSpaceVerifier other_verifier(other_space));
duke@435 304
duke@435 305 size_t bytes_needed = bytes;
duke@435 306
duke@435 307 // First use the uncommitted region in this space.
duke@435 308 size_t tmp_bytes = MIN2(uncommitted_size(), bytes_needed);
duke@435 309 if (tmp_bytes > 0) {
duke@435 310 if (expand_by(tmp_bytes)) {
duke@435 311 bytes_needed -= tmp_bytes;
duke@435 312 } else {
duke@435 313 return 0;
duke@435 314 }
duke@435 315 }
duke@435 316
duke@435 317 // Next take from the uncommitted region in the other space, and commit it.
duke@435 318 tmp_bytes = MIN2(other_space->uncommitted_size(), bytes_needed);
duke@435 319 if (tmp_bytes > 0) {
duke@435 320 char* const commit_base = committed_low_addr() - tmp_bytes;
duke@435 321 if (other_space->special() ||
duke@435 322 os::commit_memory(commit_base, tmp_bytes, alignment())) {
duke@435 323 // Reduce the reserved region in the other space.
duke@435 324 other_space->set_reserved(other_space->reserved_low_addr(),
duke@435 325 other_space->reserved_high_addr() - tmp_bytes,
duke@435 326 other_space->special());
duke@435 327
duke@435 328 // Grow both reserved and committed in this space.
duke@435 329 _reserved_low_addr -= tmp_bytes;
duke@435 330 _committed_low_addr -= tmp_bytes;
duke@435 331 bytes_needed -= tmp_bytes;
duke@435 332 } else {
duke@435 333 return bytes - bytes_needed;
duke@435 334 }
duke@435 335 }
duke@435 336
duke@435 337 // Finally take from the already committed region in the other space.
duke@435 338 tmp_bytes = bytes_needed;
duke@435 339 if (tmp_bytes > 0) {
duke@435 340 // Reduce both committed and reserved in the other space.
duke@435 341 other_space->set_committed(other_space->committed_low_addr(),
duke@435 342 other_space->committed_high_addr() - tmp_bytes);
duke@435 343 other_space->set_reserved(other_space->reserved_low_addr(),
duke@435 344 other_space->reserved_high_addr() - tmp_bytes,
duke@435 345 other_space->special());
duke@435 346
duke@435 347 // Grow both reserved and committed in this space.
duke@435 348 _reserved_low_addr -= tmp_bytes;
duke@435 349 _committed_low_addr -= tmp_bytes;
duke@435 350 }
duke@435 351
duke@435 352 return bytes;
duke@435 353 }
duke@435 354
duke@435 355 void
duke@435 356 PSVirtualSpaceHighToLow::print_space_boundaries_on(outputStream* st) const {
duke@435 357 st->print_cr(" (" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT "]",
duke@435 358 high_boundary(), low(), low_boundary());
duke@435 359 }

mercurial