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