1 /* 2 * Copyright (c) 2001, 2009, 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 // Forward decl. 26 27 class PLABStats; 28 29 // A per-thread allocation buffer used during GC. 30 class ParGCAllocBuffer: public CHeapObj { 31 protected: 32 char head[32]; 33 size_t _word_sz; // in HeapWord units 34 HeapWord* _bottom; 35 HeapWord* _top; 36 HeapWord* _end; // last allocatable address + 1 37 HeapWord* _hard_end; // _end + AlignmentReserve 38 bool _retained; // whether we hold a _retained_filler 39 MemRegion _retained_filler; 40 // In support of ergonomic sizing of PLAB's 41 size_t _allocated; // in HeapWord units 42 size_t _wasted; // in HeapWord units 43 char tail[32]; 44 static size_t FillerHeaderSize; 45 static size_t AlignmentReserve; 46 47 public: 48 // Initializes the buffer to be empty, but with the given "word_sz". 49 // Must get initialized with "set_buf" for an allocation to succeed. 50 ParGCAllocBuffer(size_t word_sz); 51 52 static const size_t min_size() { 53 return ThreadLocalAllocBuffer::min_size(); 54 } 55 56 static const size_t max_size() { 57 return ThreadLocalAllocBuffer::max_size(); 58 } 59 60 // If an allocation of the given "word_sz" can be satisfied within the 61 // buffer, do the allocation, returning a pointer to the start of the 62 // allocated block. If the allocation request cannot be satisfied, 63 // return NULL. 64 HeapWord* allocate(size_t word_sz) { 65 HeapWord* res = _top; 66 if (pointer_delta(_end, _top) >= word_sz) { 67 _top = _top + word_sz; 68 return res; 69 } else { 70 return NULL; 71 } 72 } 73 74 // Undo the last allocation in the buffer, which is required to be of the 75 // "obj" of the given "word_sz". 76 void undo_allocation(HeapWord* obj, size_t word_sz) { 77 assert(pointer_delta(_top, _bottom) >= word_sz, "Bad undo"); 78 assert(pointer_delta(_top, obj) == word_sz, "Bad undo"); 79 _top = obj; 80 } 81 82 // The total (word) size of the buffer, including both allocated and 83 // unallocted space. 84 size_t word_sz() { return _word_sz; } 85 86 // Should only be done if we are about to reset with a new buffer of the 87 // given size. 88 void set_word_size(size_t new_word_sz) { 89 assert(new_word_sz > AlignmentReserve, "Too small"); 90 _word_sz = new_word_sz; 91 } 92 93 // The number of words of unallocated space remaining in the buffer. 94 size_t words_remaining() { 95 assert(_end >= _top, "Negative buffer"); 96 return pointer_delta(_end, _top, HeapWordSize); 97 } 98 99 bool contains(void* addr) { 100 return (void*)_bottom <= addr && addr < (void*)_hard_end; 101 } 102 103 // Sets the space of the buffer to be [buf, space+word_sz()). 104 void set_buf(HeapWord* buf) { 105 _bottom = buf; 106 _top = _bottom; 107 _hard_end = _bottom + word_sz(); 108 _end = _hard_end - AlignmentReserve; 109 assert(_end >= _top, "Negative buffer"); 110 // In support of ergonomic sizing 111 _allocated += word_sz(); 112 } 113 114 // Flush the stats supporting ergonomic sizing of PLAB's 115 void flush_stats(PLABStats* stats); 116 void flush_stats_and_retire(PLABStats* stats, bool retain) { 117 // We flush the stats first in order to get a reading of 118 // unused space in the last buffer. 119 if (ResizePLAB) { 120 flush_stats(stats); 121 } 122 // Retire the last allocation buffer. 123 retire(true, retain); 124 } 125 126 // Force future allocations to fail and queries for contains() 127 // to return false 128 void invalidate() { 129 assert(!_retained, "Shouldn't retain an invalidated buffer."); 130 _end = _hard_end; 131 _wasted += pointer_delta(_end, _top); // unused space 132 _top = _end; // force future allocations to fail 133 _bottom = _end; // force future contains() queries to return false 134 } 135 136 // Fills in the unallocated portion of the buffer with a garbage object. 137 // If "end_of_gc" is TRUE, is after the last use in the GC. IF "retain" 138 // is true, attempt to re-use the unused portion in the next GC. 139 void retire(bool end_of_gc, bool retain); 140 141 void print() PRODUCT_RETURN; 142 }; 143 144 // PLAB stats book-keeping 145 class PLABStats VALUE_OBJ_CLASS_SPEC { 146 size_t _allocated; // total allocated 147 size_t _wasted; // of which wasted (internal fragmentation) 148 size_t _unused; // Unused in last buffer 149 size_t _used; // derived = allocated - wasted - unused 150 size_t _desired_plab_sz;// output of filter (below), suitably trimmed and quantized 151 AdaptiveWeightedAverage 152 _filter; // integrator with decay 153 154 public: 155 PLABStats(size_t desired_plab_sz_, unsigned wt) : 156 _allocated(0), 157 _wasted(0), 158 _unused(0), 159 _used(0), 160 _desired_plab_sz(desired_plab_sz_), 161 _filter(wt) 162 { 163 size_t min_sz = min_size(); 164 size_t max_sz = max_size(); 165 size_t aligned_min_sz = align_object_size(min_sz); 166 size_t aligned_max_sz = align_object_size(max_sz); 167 assert(min_sz <= aligned_min_sz && max_sz >= aligned_max_sz && 168 min_sz <= max_sz, 169 "PLAB clipping computation in adjust_desired_plab_sz()" 170 " may be incorrect"); 171 } 172 173 static const size_t min_size() { 174 return ParGCAllocBuffer::min_size(); 175 } 176 177 static const size_t max_size() { 178 return ParGCAllocBuffer::max_size(); 179 } 180 181 size_t desired_plab_sz() { 182 return _desired_plab_sz; 183 } 184 185 void adjust_desired_plab_sz(); // filter computation, latches output to 186 // _desired_plab_sz, clears sensor accumulators 187 188 void add_allocated(size_t v) { 189 Atomic::add_ptr(v, &_allocated); 190 } 191 192 void add_unused(size_t v) { 193 Atomic::add_ptr(v, &_unused); 194 } 195 196 void add_wasted(size_t v) { 197 Atomic::add_ptr(v, &_wasted); 198 } 199 }; 200 201 class ParGCAllocBufferWithBOT: public ParGCAllocBuffer { 202 BlockOffsetArrayContigSpace _bt; 203 BlockOffsetSharedArray* _bsa; 204 HeapWord* _true_end; // end of the whole ParGCAllocBuffer 205 206 static const size_t ChunkSizeInWords; 207 static const size_t ChunkSizeInBytes; 208 HeapWord* allocate_slow(size_t word_sz); 209 210 void fill_region_with_block(MemRegion mr, bool contig); 211 212 public: 213 ParGCAllocBufferWithBOT(size_t word_sz, BlockOffsetSharedArray* bsa); 214 215 HeapWord* allocate(size_t word_sz) { 216 HeapWord* res = ParGCAllocBuffer::allocate(word_sz); 217 if (res != NULL) { 218 _bt.alloc_block(res, word_sz); 219 } else { 220 res = allocate_slow(word_sz); 221 } 222 return res; 223 } 224 225 void undo_allocation(HeapWord* obj, size_t word_sz); 226 227 void set_buf(HeapWord* buf_start) { 228 ParGCAllocBuffer::set_buf(buf_start); 229 _true_end = _hard_end; 230 _bt.set_region(MemRegion(buf_start, word_sz())); 231 _bt.initialize_threshold(); 232 } 233 234 void retire(bool end_of_gc, bool retain); 235 236 MemRegion range() { 237 return MemRegion(_top, _true_end); 238 } 239 };