src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp

Mon, 03 Jun 2013 14:37:13 -0700

author
tamao
date
Mon, 03 Jun 2013 14:37:13 -0700
changeset 5206
87c64c0438fb
parent 4130
2e6857353b2c
child 6198
55fb97c4c58d
permissions
-rw-r--r--

6976350: G1: deal with fragmentation while copying objects during GC
Summary: Create G1ParGCAllocBufferContainer to contain two buffers instead of previously using one buffer, in order to hold the first priority buffer longer. Thus, when some large objects hits the value of free space left in the first priority buffer it has an alternative to fit in the second priority buffer while the first priority buffer is given more chances to try allocating smaller objects. Overall, it will improve heap space efficiency.
Reviewed-by: johnc, jmasa, brutisso
Contributed-by: tamao <tao.mao@oracle.com>

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

mercurial