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 };