1 #ifdef USE_PRAGMA_IDENT_HDR 2 #pragma ident "@(#)parGCAllocBuffer.hpp 1.30 07/05/29 09:44:13 JVM" 3 #endif 4 /* 5 * Copyright 2001-2006 Sun Microsystems, Inc. All Rights Reserved. 6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7 * 8 * This code is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License version 2 only, as 10 * published by the Free Software Foundation. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 23 * CA 95054 USA or visit www.sun.com if you need additional information or 24 * have any questions. 25 * 26 */ 27 28 // Forward decl. 29 30 class PLABStats; 31 32 // A per-thread allocation buffer used during GC. 33 class ParGCAllocBuffer: public CHeapObj { 34 protected: 35 char head[32]; 36 size_t _word_sz; // in HeapWord units 37 HeapWord* _bottom; 38 HeapWord* _top; 39 HeapWord* _end; // last allocatable address + 1 40 HeapWord* _hard_end; // _end + AlignmentReserve 41 bool _retained; // whether we hold a _retained_filler 42 MemRegion _retained_filler; 43 // In support of ergonomic sizing of PLAB's 44 size_t _allocated; // in HeapWord units 45 size_t _wasted; // in HeapWord units 46 char tail[32]; 47 static const size_t FillerHeaderSize; 48 static const size_t AlignmentReserve; 49 50 public: 51 // Initializes the buffer to be empty, but with the given "word_sz". 52 // Must get initialized with "set_buf" for an allocation to succeed. 53 ParGCAllocBuffer(size_t word_sz); 54 55 static const size_t min_size() { 56 return ThreadLocalAllocBuffer::min_size(); 57 } 58 59 static const size_t max_size() { 60 return ThreadLocalAllocBuffer::max_size(); 61 } 62 63 // If an allocation of the given "word_sz" can be satisfied within the 64 // buffer, do the allocation, returning a pointer to the start of the 65 // allocated block. If the allocation request cannot be satisfied, 66 // return NULL. 67 HeapWord* allocate(size_t word_sz) { 68 HeapWord* res = _top; 69 HeapWord* new_top = _top + word_sz; 70 if (new_top <= _end) { 71 _top = new_top; 72 return res; 73 } else { 74 return NULL; 75 } 76 } 77 78 // Undo the last allocation in the buffer, which is required to be of the 79 // "obj" of the given "word_sz". 80 void undo_allocation(HeapWord* obj, size_t word_sz) { 81 assert(_top - word_sz >= _bottom 82 && _top - word_sz == obj, 83 "Bad undo_allocation"); 84 _top = _top - word_sz; 85 } 86 87 // The total (word) size of the buffer, including both allocated and 88 // unallocted space. 89 size_t word_sz() { return _word_sz; } 90 91 // Should only be done if we are about to reset with a new buffer of the 92 // given size. 93 void set_word_size(size_t new_word_sz) { 94 assert(new_word_sz > AlignmentReserve, "Too small"); 95 _word_sz = new_word_sz; 96 } 97 98 // The number of words of unallocated space remaining in the buffer. 99 size_t words_remaining() { 100 assert(_end >= _top, "Negative buffer"); 101 return pointer_delta(_end, _top, HeapWordSize); 102 } 103 104 bool contains(void* addr) { 105 return (void*)_bottom <= addr && addr < (void*)_hard_end; 106 } 107 108 // Sets the space of the buffer to be [buf, space+word_sz()). 109 void set_buf(HeapWord* buf) { 110 _bottom = buf; 111 _top = _bottom; 112 _hard_end = _bottom + word_sz(); 113 _end = _hard_end - AlignmentReserve; 114 assert(_end >= _top, "Negative buffer"); 115 // In support of ergonomic sizing 116 _allocated += word_sz(); 117 } 118 119 // Flush the stats supporting ergonomic sizing of PLAB's 120 void flush_stats(PLABStats* stats); 121 void flush_stats_and_retire(PLABStats* stats, bool retain) { 122 // We flush the stats first in order to get a reading of 123 // unused space in the last buffer. 124 if (ResizePLAB) { 125 flush_stats(stats); 126 } 127 // Retire the last allocation buffer. 128 retire(true, retain); 129 } 130 131 // Force future allocations to fail and queries for contains() 132 // to return false 133 void invalidate() { 134 assert(!_retained, "Shouldn't retain an invalidated buffer."); 135 _end = _hard_end; 136 _wasted += pointer_delta(_end, _top); // unused space 137 _top = _end; // force future allocations to fail 138 _bottom = _end; // force future contains() queries to return false 139 } 140 141 // Fills in the unallocated portion of the buffer with a garbage object. 142 // If "end_of_gc" is TRUE, is after the last use in the GC. IF "retain" 143 // is true, attempt to re-use the unused portion in the next GC. 144 void retire(bool end_of_gc, bool retain); 145 146 void print() PRODUCT_RETURN; 147 }; 148 149 // PLAB stats book-keeping 150 class PLABStats VALUE_OBJ_CLASS_SPEC { 151 size_t _allocated; // total allocated 152 size_t _wasted; // of which wasted (internal fragmentation) 153 size_t _unused; // Unused in last buffer 154 size_t _used; // derived = allocated - wasted - unused 155 size_t _desired_plab_sz;// output of filter (below), suitably trimmed and quantized 156 AdaptiveWeightedAverage 157 _filter; // integrator with decay 158 159 public: 160 PLABStats(size_t desired_plab_sz_, unsigned wt) : 161 _allocated(0), 162 _wasted(0), 163 _unused(0), 164 _used(0), 165 _desired_plab_sz(desired_plab_sz_), 166 _filter(wt) 167 { 168 size_t min_sz = min_size(); 169 size_t max_sz = max_size(); 170 size_t aligned_min_sz = align_object_size(min_sz); 171 size_t aligned_max_sz = align_object_size(max_sz); 172 assert(min_sz <= aligned_min_sz && max_sz >= aligned_max_sz && 173 min_sz <= max_sz, 174 "PLAB clipping computation in adjust_desired_plab_sz()" 175 " may be incorrect"); 176 } 177 178 static const size_t min_size() { 179 return ParGCAllocBuffer::min_size(); 180 } 181 182 static const size_t max_size() { 183 return ParGCAllocBuffer::max_size(); 184 } 185 186 size_t desired_plab_sz() { 187 return _desired_plab_sz; 188 } 189 190 void adjust_desired_plab_sz(); // filter computation, latches output to 191 // _desired_plab_sz, clears sensor accumulators 192 193 void add_allocated(size_t v) { 194 Atomic::add_ptr(v, &_allocated); 195 } 196 197 void add_unused(size_t v) { 198 Atomic::add_ptr(v, &_unused); 199 } 200 201 void add_wasted(size_t v) { 202 Atomic::add_ptr(v, &_wasted); 203 } 204 }; 205 206 class ParGCAllocBufferWithBOT: public ParGCAllocBuffer { 207 BlockOffsetArrayContigSpace _bt; 208 BlockOffsetSharedArray* _bsa; 209 HeapWord* _true_end; // end of the whole ParGCAllocBuffer 210 211 static const size_t ChunkSizeInWords; 212 static const size_t ChunkSizeInBytes; 213 HeapWord* allocate_slow(size_t word_sz); 214 215 void fill_region_with_block(MemRegion mr, bool contig); 216 217 public: 218 ParGCAllocBufferWithBOT(size_t word_sz, BlockOffsetSharedArray* bsa); 219 220 HeapWord* allocate(size_t word_sz) { 221 HeapWord* res = ParGCAllocBuffer::allocate(word_sz); 222 if (res != NULL) { 223 _bt.alloc_block(res, word_sz); 224 } else { 225 res = allocate_slow(word_sz); 226 } 227 return res; 228 } 229 230 void undo_allocation(HeapWord* obj, size_t word_sz); 231 232 void set_buf(HeapWord* buf_start) { 233 ParGCAllocBuffer::set_buf(buf_start); 234 _true_end = _hard_end; 235 _bt.set_region(MemRegion(buf_start, word_sz())); 236 _bt.initialize_threshold(); 237 } 238 239 void retire(bool end_of_gc, bool retain); 240 241 MemRegion range() { 242 return MemRegion(_top, _true_end); 243 } 244 };