1 /* 2 * Copyright (c) 2001, 2015, 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/shared/collectorCounters.hpp" 27 #include "memory/allocation.inline.hpp" 28 #include "memory/blockOffsetTable.inline.hpp" 29 #include "memory/generation.inline.hpp" 30 #include "memory/generationSpec.hpp" 31 #include "memory/space.hpp" 32 #include "memory/tenuredGeneration.hpp" 33 #include "oops/oop.inline.hpp" 34 #include "runtime/java.hpp" 35 #include "utilities/macros.hpp" 36 37 #if INCLUDE_ALL_GCS 38 #include "gc_implementation/shared/parGCAllocBuffer.hpp" 39 #endif 40 41 TenuredGeneration::TenuredGeneration(ReservedSpace rs, 42 size_t initial_byte_size, int level, 43 GenRemSet* remset) : 44 OneContigSpaceCardGeneration(rs, initial_byte_size, 45 level, remset, NULL) 46 { 47 HeapWord* bottom = (HeapWord*) _virtual_space.low(); 48 HeapWord* end = (HeapWord*) _virtual_space.high(); 49 _the_space = new TenuredSpace(_bts, MemRegion(bottom, end)); 50 _the_space->reset_saved_mark(); 51 _shrink_factor = 0; 52 _capacity_at_prologue = 0; 53 54 _gc_stats = new GCStats(); 55 56 // initialize performance counters 57 58 const char* gen_name = "old"; 59 60 // Generation Counters -- generation 1, 1 subspace 61 _gen_counters = new GenerationCounters(gen_name, 1, 1, &_virtual_space); 62 63 _gc_counters = new CollectorCounters("MSC", 1); 64 65 _space_counters = new CSpaceCounters(gen_name, 0, 66 _virtual_space.reserved_size(), 67 _the_space, _gen_counters); 68 #if INCLUDE_ALL_GCS 69 if (UseParNewGC) { 70 typedef ParGCAllocBufferWithBOT* ParGCAllocBufferWithBOTPtr; 71 _alloc_buffers = NEW_C_HEAP_ARRAY(ParGCAllocBufferWithBOTPtr, 72 ParallelGCThreads, mtGC); 73 if (_alloc_buffers == NULL) 74 vm_exit_during_initialization("Could not allocate alloc_buffers"); 75 for (uint i = 0; i < ParallelGCThreads; i++) { 76 _alloc_buffers[i] = 77 new ParGCAllocBufferWithBOT(OldPLABSize, _bts); 78 if (_alloc_buffers[i] == NULL) 79 vm_exit_during_initialization("Could not allocate alloc_buffers"); 80 } 81 } else { 82 _alloc_buffers = NULL; 83 } 84 #endif // INCLUDE_ALL_GCS 85 } 86 87 88 const char* TenuredGeneration::name() const { 89 return "tenured generation"; 90 } 91 92 void TenuredGeneration::gc_prologue(bool full) { 93 _capacity_at_prologue = capacity(); 94 _used_at_prologue = used(); 95 if (VerifyBeforeGC) { 96 verify_alloc_buffers_clean(); 97 } 98 } 99 100 void TenuredGeneration::gc_epilogue(bool full) { 101 if (VerifyAfterGC) { 102 verify_alloc_buffers_clean(); 103 } 104 OneContigSpaceCardGeneration::gc_epilogue(full); 105 } 106 107 108 bool TenuredGeneration::should_collect(bool full, 109 size_t size, 110 bool is_tlab) { 111 // This should be one big conditional or (||), but I want to be able to tell 112 // why it returns what it returns (without re-evaluating the conditionals 113 // in case they aren't idempotent), so I'm doing it this way. 114 // DeMorgan says it's okay. 115 bool result = false; 116 if (!result && full) { 117 result = true; 118 if (PrintGC && Verbose) { 119 gclog_or_tty->print_cr("TenuredGeneration::should_collect: because" 120 " full"); 121 } 122 } 123 if (!result && should_allocate(size, is_tlab)) { 124 result = true; 125 if (PrintGC && Verbose) { 126 gclog_or_tty->print_cr("TenuredGeneration::should_collect: because" 127 " should_allocate(" SIZE_FORMAT ")", 128 size); 129 } 130 } 131 // If we don't have very much free space. 132 // XXX: 10000 should be a percentage of the capacity!!! 133 if (!result && free() < 10000) { 134 result = true; 135 if (PrintGC && Verbose) { 136 gclog_or_tty->print_cr("TenuredGeneration::should_collect: because" 137 " free(): " SIZE_FORMAT, 138 free()); 139 } 140 } 141 // If we had to expand to accomodate promotions from younger generations 142 if (!result && _capacity_at_prologue < capacity()) { 143 result = true; 144 if (PrintGC && Verbose) { 145 gclog_or_tty->print_cr("TenuredGeneration::should_collect: because" 146 "_capacity_at_prologue: " SIZE_FORMAT " < capacity(): " SIZE_FORMAT, 147 _capacity_at_prologue, capacity()); 148 } 149 } 150 return result; 151 } 152 153 void TenuredGeneration::collect(bool full, 154 bool clear_all_soft_refs, 155 size_t size, 156 bool is_tlab) { 157 retire_alloc_buffers_before_full_gc(); 158 OneContigSpaceCardGeneration::collect(full, clear_all_soft_refs, 159 size, is_tlab); 160 } 161 162 void TenuredGeneration::compute_new_size() { 163 assert_locked_or_safepoint(Heap_lock); 164 165 // Compute some numbers about the state of the heap. 166 const size_t used_after_gc = used(); 167 const size_t capacity_after_gc = capacity(); 168 169 CardGeneration::compute_new_size(); 170 171 assert(used() == used_after_gc && used_after_gc <= capacity(), 172 err_msg("used: " SIZE_FORMAT " used_after_gc: " SIZE_FORMAT 173 " capacity: " SIZE_FORMAT, used(), used_after_gc, capacity())); 174 } 175 void TenuredGeneration::update_gc_stats(int current_level, 176 bool full) { 177 // If the next lower level(s) has been collected, gather any statistics 178 // that are of interest at this point. 179 if (!full && (current_level + 1) == level()) { 180 // Calculate size of data promoted from the younger generations 181 // before doing the collection. 182 size_t used_before_gc = used(); 183 184 // If the younger gen collections were skipped, then the 185 // number of promoted bytes will be 0 and adding it to the 186 // average will incorrectly lessen the average. It is, however, 187 // also possible that no promotion was needed. 188 if (used_before_gc >= _used_at_prologue) { 189 size_t promoted_in_bytes = used_before_gc - _used_at_prologue; 190 gc_stats()->avg_promoted()->sample(promoted_in_bytes); 191 } 192 } 193 } 194 195 void TenuredGeneration::update_counters() { 196 if (UsePerfData) { 197 _space_counters->update_all(); 198 _gen_counters->update_all(); 199 } 200 } 201 202 203 #if INCLUDE_ALL_GCS 204 oop TenuredGeneration::par_promote(int thread_num, 205 oop old, markOop m, size_t word_sz) { 206 207 ParGCAllocBufferWithBOT* buf = _alloc_buffers[thread_num]; 208 HeapWord* obj_ptr = buf->allocate(word_sz); 209 bool is_lab = true; 210 if (obj_ptr == NULL) { 211 #ifndef PRODUCT 212 if (Universe::heap()->promotion_should_fail()) { 213 return NULL; 214 } 215 #endif // #ifndef PRODUCT 216 217 // Slow path: 218 if (word_sz * 100 < ParallelGCBufferWastePct * buf->word_sz()) { 219 // Is small enough; abandon this buffer and start a new one. 220 size_t buf_size = buf->word_sz(); 221 HeapWord* buf_space = 222 TenuredGeneration::par_allocate(buf_size, false); 223 if (buf_space == NULL) { 224 buf_space = expand_and_allocate(buf_size, false, true /* parallel*/); 225 } 226 if (buf_space != NULL) { 227 buf->retire(false, false); 228 buf->set_buf(buf_space); 229 obj_ptr = buf->allocate(word_sz); 230 assert(obj_ptr != NULL, "Buffer was definitely big enough..."); 231 } 232 }; 233 // Otherwise, buffer allocation failed; try allocating object 234 // individually. 235 if (obj_ptr == NULL) { 236 obj_ptr = TenuredGeneration::par_allocate(word_sz, false); 237 if (obj_ptr == NULL) { 238 obj_ptr = expand_and_allocate(word_sz, false, true /* parallel */); 239 } 240 } 241 if (obj_ptr == NULL) return NULL; 242 } 243 assert(obj_ptr != NULL, "program logic"); 244 Copy::aligned_disjoint_words((HeapWord*)old, obj_ptr, word_sz); 245 oop obj = oop(obj_ptr); 246 // Restore the mark word copied above. 247 obj->set_mark(m); 248 return obj; 249 } 250 251 void TenuredGeneration::par_promote_alloc_undo(int thread_num, 252 HeapWord* obj, 253 size_t word_sz) { 254 ParGCAllocBufferWithBOT* buf = _alloc_buffers[thread_num]; 255 if (buf->contains(obj)) { 256 guarantee(buf->contains(obj + word_sz - 1), 257 "should contain whole object"); 258 buf->undo_allocation(obj, word_sz); 259 } else { 260 CollectedHeap::fill_with_object(obj, word_sz); 261 } 262 } 263 264 void TenuredGeneration::par_promote_alloc_done(int thread_num) { 265 ParGCAllocBufferWithBOT* buf = _alloc_buffers[thread_num]; 266 buf->retire(true, ParallelGCRetainPLAB); 267 } 268 269 void TenuredGeneration::retire_alloc_buffers_before_full_gc() { 270 if (UseParNewGC) { 271 for (uint i = 0; i < ParallelGCThreads; i++) { 272 _alloc_buffers[i]->retire(true /*end_of_gc*/, false /*retain*/); 273 } 274 } 275 } 276 277 // Verify that any retained parallel allocation buffers do not 278 // intersect with dirty cards. 279 void TenuredGeneration::verify_alloc_buffers_clean() { 280 if (UseParNewGC) { 281 for (uint i = 0; i < ParallelGCThreads; i++) { 282 _rs->verify_aligned_region_empty(_alloc_buffers[i]->range()); 283 } 284 } 285 } 286 287 #else // INCLUDE_ALL_GCS 288 void TenuredGeneration::retire_alloc_buffers_before_full_gc() {} 289 void TenuredGeneration::verify_alloc_buffers_clean() {} 290 #endif // INCLUDE_ALL_GCS 291 292 bool TenuredGeneration::promotion_attempt_is_safe(size_t max_promotion_in_bytes) const { 293 size_t available = max_contiguous_available(); 294 size_t av_promo = (size_t)gc_stats()->avg_promoted()->padded_average(); 295 bool res = (available >= av_promo) || (available >= max_promotion_in_bytes); 296 if (PrintGC && Verbose) { 297 gclog_or_tty->print_cr( 298 "Tenured: promo attempt is%s safe: available("SIZE_FORMAT") %s av_promo("SIZE_FORMAT")," 299 "max_promo("SIZE_FORMAT")", 300 res? "":" not", available, res? ">=":"<", 301 av_promo, max_promotion_in_bytes); 302 } 303 return res; 304 }