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

Tue, 08 Aug 2017 15:57:29 +0800

author
aoqi
date
Tue, 08 Aug 2017 15:57:29 +0800
changeset 6876
710a3c8b516e
parent 6376
cfd4aac53239
parent 0
f90c822e73f8
child 7535
7ae4e26cb1e0
permissions
-rw-r--r--

merge

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

mercurial