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