src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.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 4037
da91efe96a93
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/adjoiningGenerations.hpp"
stefank@2314 27 #include "gc_implementation/parallelScavenge/adjoiningVirtualSpaces.hpp"
stefank@2314 28 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
stefank@2314 29 #include "gc_implementation/parallelScavenge/psPermGen.hpp"
duke@435 30
duke@435 31 // If boundary moving is being used, create the young gen and old
duke@435 32 // gen with ASPSYoungGen and ASPSOldGen, respectively. Revert to
duke@435 33 // the old behavior otherwise (with PSYoungGen and PSOldGen).
duke@435 34
duke@435 35 AdjoiningGenerations::AdjoiningGenerations(ReservedSpace old_young_rs,
duke@435 36 size_t init_low_byte_size,
duke@435 37 size_t min_low_byte_size,
duke@435 38 size_t max_low_byte_size,
duke@435 39 size_t init_high_byte_size,
duke@435 40 size_t min_high_byte_size,
duke@435 41 size_t max_high_byte_size,
duke@435 42 size_t alignment) :
duke@435 43 _virtual_spaces(old_young_rs, min_low_byte_size,
duke@435 44 min_high_byte_size, alignment) {
duke@435 45 assert(min_low_byte_size <= init_low_byte_size &&
duke@435 46 init_low_byte_size <= max_low_byte_size, "Parameter check");
duke@435 47 assert(min_high_byte_size <= init_high_byte_size &&
duke@435 48 init_high_byte_size <= max_high_byte_size, "Parameter check");
duke@435 49 // Create the generations differently based on the option to
duke@435 50 // move the boundary.
duke@435 51 if (UseAdaptiveGCBoundary) {
duke@435 52 // Initialize the adjoining virtual spaces. Then pass the
duke@435 53 // a virtual to each generation for initialization of the
duke@435 54 // generation.
duke@435 55
duke@435 56 // Does the actual creation of the virtual spaces
duke@435 57 _virtual_spaces.initialize(max_low_byte_size,
duke@435 58 init_low_byte_size,
duke@435 59 init_high_byte_size);
duke@435 60
duke@435 61 // Place the young gen at the high end. Passes in the virtual space.
duke@435 62 _young_gen = new ASPSYoungGen(_virtual_spaces.high(),
duke@435 63 _virtual_spaces.high()->committed_size(),
duke@435 64 min_high_byte_size,
duke@435 65 _virtual_spaces.high_byte_size_limit());
duke@435 66
duke@435 67 // Place the old gen at the low end. Passes in the virtual space.
duke@435 68 _old_gen = new ASPSOldGen(_virtual_spaces.low(),
duke@435 69 _virtual_spaces.low()->committed_size(),
duke@435 70 min_low_byte_size,
duke@435 71 _virtual_spaces.low_byte_size_limit(),
duke@435 72 "old", 1);
duke@435 73
duke@435 74 young_gen()->initialize_work();
duke@435 75 assert(young_gen()->reserved().byte_size() <= young_gen()->gen_size_limit(),
duke@435 76 "Consistency check");
duke@435 77 assert(old_young_rs.size() >= young_gen()->gen_size_limit(),
duke@435 78 "Consistency check");
duke@435 79
duke@435 80 old_gen()->initialize_work("old", 1);
duke@435 81 assert(old_gen()->reserved().byte_size() <= old_gen()->gen_size_limit(),
duke@435 82 "Consistency check");
duke@435 83 assert(old_young_rs.size() >= old_gen()->gen_size_limit(),
duke@435 84 "Consistency check");
duke@435 85 } else {
duke@435 86
duke@435 87 // Layout the reserved space for the generations.
duke@435 88 ReservedSpace old_rs =
duke@435 89 virtual_spaces()->reserved_space().first_part(max_low_byte_size);
duke@435 90 ReservedSpace heap_rs =
duke@435 91 virtual_spaces()->reserved_space().last_part(max_low_byte_size);
duke@435 92 ReservedSpace young_rs = heap_rs.first_part(max_high_byte_size);
duke@435 93 assert(young_rs.size() == heap_rs.size(), "Didn't reserve all of the heap");
duke@435 94
duke@435 95 // Create the generations. Virtual spaces are not passed in.
duke@435 96 _young_gen = new PSYoungGen(init_high_byte_size,
duke@435 97 min_high_byte_size,
duke@435 98 max_high_byte_size);
duke@435 99 _old_gen = new PSOldGen(init_low_byte_size,
duke@435 100 min_low_byte_size,
duke@435 101 max_low_byte_size,
duke@435 102 "old", 1);
duke@435 103
duke@435 104 // The virtual spaces are created by the initialization of the gens.
duke@435 105 _young_gen->initialize(young_rs, alignment);
duke@435 106 assert(young_gen()->gen_size_limit() == young_rs.size(),
duke@435 107 "Consistency check");
duke@435 108 _old_gen->initialize(old_rs, alignment, "old", 1);
duke@435 109 assert(old_gen()->gen_size_limit() == old_rs.size(), "Consistency check");
duke@435 110 }
duke@435 111 }
duke@435 112
duke@435 113 size_t AdjoiningGenerations::reserved_byte_size() {
duke@435 114 return virtual_spaces()->reserved_space().size();
duke@435 115 }
duke@435 116
duke@435 117
duke@435 118 // Make checks on the current sizes of the generations and
duke@435 119 // the contraints on the sizes of the generations. Push
duke@435 120 // up the boundary within the contraints. A partial
duke@435 121 // push can occur.
duke@435 122 void AdjoiningGenerations::request_old_gen_expansion(size_t expand_in_bytes) {
duke@435 123 assert(UseAdaptiveSizePolicy && UseAdaptiveGCBoundary, "runtime check");
duke@435 124
duke@435 125 assert_lock_strong(ExpandHeap_lock);
duke@435 126 assert_locked_or_safepoint(Heap_lock);
duke@435 127
duke@435 128 // These sizes limit the amount the boundaries can move. Effectively,
duke@435 129 // the generation says how much it is willing to yield to the other
duke@435 130 // generation.
duke@435 131 const size_t young_gen_available = young_gen()->available_for_contraction();
duke@435 132 const size_t old_gen_available = old_gen()->available_for_expansion();
duke@435 133 const size_t alignment = virtual_spaces()->alignment();
duke@435 134 size_t change_in_bytes = MIN3(young_gen_available,
duke@435 135 old_gen_available,
duke@435 136 align_size_up_(expand_in_bytes, alignment));
duke@435 137
duke@435 138 if (change_in_bytes == 0) {
duke@435 139 return;
duke@435 140 }
duke@435 141
duke@435 142 if (TraceAdaptiveGCBoundary) {
duke@435 143 gclog_or_tty->print_cr("Before expansion of old gen with boundary move");
duke@435 144 gclog_or_tty->print_cr(" Requested change: 0x%x Attempted change: 0x%x",
duke@435 145 expand_in_bytes, change_in_bytes);
duke@435 146 if (!PrintHeapAtGC) {
duke@435 147 Universe::print_on(gclog_or_tty);
duke@435 148 }
duke@435 149 gclog_or_tty->print_cr(" PSOldGen max size: " SIZE_FORMAT "K",
duke@435 150 old_gen()->max_gen_size()/K);
duke@435 151 }
duke@435 152
duke@435 153 // Move the boundary between the generations up (smaller young gen).
duke@435 154 if (virtual_spaces()->adjust_boundary_up(change_in_bytes)) {
duke@435 155 young_gen()->reset_after_change();
duke@435 156 old_gen()->reset_after_change();
duke@435 157 }
duke@435 158
duke@435 159 // The total reserved for the generations should match the sum
duke@435 160 // of the two even if the boundary is moving.
duke@435 161 assert(reserved_byte_size() ==
duke@435 162 old_gen()->max_gen_size() + young_gen()->max_size(),
duke@435 163 "Space is missing");
duke@435 164 young_gen()->space_invariants();
duke@435 165 old_gen()->space_invariants();
duke@435 166
duke@435 167 if (TraceAdaptiveGCBoundary) {
duke@435 168 gclog_or_tty->print_cr("After expansion of old gen with boundary move");
duke@435 169 if (!PrintHeapAtGC) {
duke@435 170 Universe::print_on(gclog_or_tty);
duke@435 171 }
duke@435 172 gclog_or_tty->print_cr(" PSOldGen max size: " SIZE_FORMAT "K",
duke@435 173 old_gen()->max_gen_size()/K);
duke@435 174 }
duke@435 175 }
duke@435 176
duke@435 177 // See comments on request_old_gen_expansion()
duke@435 178 bool AdjoiningGenerations::request_young_gen_expansion(size_t expand_in_bytes) {
duke@435 179 assert(UseAdaptiveSizePolicy && UseAdaptiveGCBoundary, "runtime check");
duke@435 180
duke@435 181 // If eden is not empty, the boundary can be moved but no advantage
duke@435 182 // can be made of the move since eden cannot be moved.
duke@435 183 if (!young_gen()->eden_space()->is_empty()) {
duke@435 184 return false;
duke@435 185 }
duke@435 186
duke@435 187
duke@435 188 bool result = false;
duke@435 189 const size_t young_gen_available = young_gen()->available_for_expansion();
duke@435 190 const size_t old_gen_available = old_gen()->available_for_contraction();
duke@435 191 const size_t alignment = virtual_spaces()->alignment();
duke@435 192 size_t change_in_bytes = MIN3(young_gen_available,
duke@435 193 old_gen_available,
duke@435 194 align_size_up_(expand_in_bytes, alignment));
duke@435 195
duke@435 196 if (change_in_bytes == 0) {
duke@435 197 return false;
duke@435 198 }
duke@435 199
duke@435 200 if (TraceAdaptiveGCBoundary) {
duke@435 201 gclog_or_tty->print_cr("Before expansion of young gen with boundary move");
duke@435 202 gclog_or_tty->print_cr(" Requested change: 0x%x Attempted change: 0x%x",
duke@435 203 expand_in_bytes, change_in_bytes);
duke@435 204 if (!PrintHeapAtGC) {
duke@435 205 Universe::print_on(gclog_or_tty);
duke@435 206 }
duke@435 207 gclog_or_tty->print_cr(" PSYoungGen max size: " SIZE_FORMAT "K",
duke@435 208 young_gen()->max_size()/K);
duke@435 209 }
duke@435 210
duke@435 211 // Move the boundary between the generations down (smaller old gen).
duke@435 212 MutexLocker x(ExpandHeap_lock);
duke@435 213 if (virtual_spaces()->adjust_boundary_down(change_in_bytes)) {
duke@435 214 young_gen()->reset_after_change();
duke@435 215 old_gen()->reset_after_change();
duke@435 216 result = true;
duke@435 217 }
duke@435 218
duke@435 219 // The total reserved for the generations should match the sum
duke@435 220 // of the two even if the boundary is moving.
duke@435 221 assert(reserved_byte_size() ==
duke@435 222 old_gen()->max_gen_size() + young_gen()->max_size(),
duke@435 223 "Space is missing");
duke@435 224 young_gen()->space_invariants();
duke@435 225 old_gen()->space_invariants();
duke@435 226
duke@435 227 if (TraceAdaptiveGCBoundary) {
duke@435 228 gclog_or_tty->print_cr("After expansion of young gen with boundary move");
duke@435 229 if (!PrintHeapAtGC) {
duke@435 230 Universe::print_on(gclog_or_tty);
duke@435 231 }
duke@435 232 gclog_or_tty->print_cr(" PSYoungGen max size: " SIZE_FORMAT "K",
duke@435 233 young_gen()->max_size()/K);
duke@435 234 }
duke@435 235
duke@435 236 return result;
duke@435 237 }
duke@435 238
duke@435 239 // Additional space is needed in the old generation. Try to move the boundary
duke@435 240 // up to meet the need. Moves boundary up only
duke@435 241 void AdjoiningGenerations::adjust_boundary_for_old_gen_needs(
duke@435 242 size_t desired_free_space) {
duke@435 243 assert(UseAdaptiveSizePolicy && UseAdaptiveGCBoundary, "runtime check");
duke@435 244
duke@435 245 // Stress testing.
duke@435 246 if (PSAdaptiveSizePolicyResizeVirtualSpaceAlot == 1) {
duke@435 247 MutexLocker x(ExpandHeap_lock);
duke@435 248 request_old_gen_expansion(virtual_spaces()->alignment() * 3 / 2);
duke@435 249 }
duke@435 250
duke@435 251 // Expand only if the entire generation is already committed.
duke@435 252 if (old_gen()->virtual_space()->uncommitted_size() == 0) {
duke@435 253 if (old_gen()->free_in_bytes() < desired_free_space) {
duke@435 254 MutexLocker x(ExpandHeap_lock);
duke@435 255 request_old_gen_expansion(desired_free_space);
duke@435 256 }
duke@435 257 }
duke@435 258 }
duke@435 259
duke@435 260 // See comment on adjust_boundary_for_old_gen_needss().
duke@435 261 // Adjust boundary down only.
duke@435 262 void AdjoiningGenerations::adjust_boundary_for_young_gen_needs(size_t eden_size,
duke@435 263 size_t survivor_size) {
duke@435 264
duke@435 265 assert(UseAdaptiveSizePolicy && UseAdaptiveGCBoundary, "runtime check");
duke@435 266
duke@435 267 // Stress testing.
duke@435 268 if (PSAdaptiveSizePolicyResizeVirtualSpaceAlot == 0) {
duke@435 269 request_young_gen_expansion(virtual_spaces()->alignment() * 3 / 2);
duke@435 270 eden_size = young_gen()->eden_space()->capacity_in_bytes();
duke@435 271 }
duke@435 272
duke@435 273 // Expand only if the entire generation is already committed.
duke@435 274 if (young_gen()->virtual_space()->uncommitted_size() == 0) {
duke@435 275 size_t desired_size = eden_size + 2 * survivor_size;
duke@435 276 const size_t committed = young_gen()->virtual_space()->committed_size();
duke@435 277 if (desired_size > committed) {
duke@435 278 request_young_gen_expansion(desired_size - committed);
duke@435 279 }
duke@435 280 }
duke@435 281 }

mercurial