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

changeset 435
a61af66fc99e
child 548
ba764ed4b6f2
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.hpp	Sat Dec 01 00:00:00 2007 +0000
     1.3 @@ -0,0 +1,241 @@
     1.4 +/*
     1.5 + * Copyright 2001-2006 Sun Microsystems, Inc.  All Rights Reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
    1.24 + * have any questions.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +// Forward decl.
    1.29 +
    1.30 +class PLABStats;
    1.31 +
    1.32 +// A per-thread allocation buffer used during GC.
    1.33 +class ParGCAllocBuffer: public CHeapObj {
    1.34 +protected:
    1.35 +  char head[32];
    1.36 +  size_t _word_sz;          // in HeapWord units
    1.37 +  HeapWord* _bottom;
    1.38 +  HeapWord* _top;
    1.39 +  HeapWord* _end;       // last allocatable address + 1
    1.40 +  HeapWord* _hard_end;  // _end + AlignmentReserve
    1.41 +  bool      _retained;  // whether we hold a _retained_filler
    1.42 +  MemRegion _retained_filler;
    1.43 +  // In support of ergonomic sizing of PLAB's
    1.44 +  size_t    _allocated;     // in HeapWord units
    1.45 +  size_t    _wasted;        // in HeapWord units
    1.46 +  char tail[32];
    1.47 +  static const size_t FillerHeaderSize;
    1.48 +  static const size_t AlignmentReserve;
    1.49 +
    1.50 +public:
    1.51 +  // Initializes the buffer to be empty, but with the given "word_sz".
    1.52 +  // Must get initialized with "set_buf" for an allocation to succeed.
    1.53 +  ParGCAllocBuffer(size_t word_sz);
    1.54 +
    1.55 +  static const size_t min_size() {
    1.56 +    return ThreadLocalAllocBuffer::min_size();
    1.57 +  }
    1.58 +
    1.59 +  static const size_t max_size() {
    1.60 +    return ThreadLocalAllocBuffer::max_size();
    1.61 +  }
    1.62 +
    1.63 +  // If an allocation of the given "word_sz" can be satisfied within the
    1.64 +  // buffer, do the allocation, returning a pointer to the start of the
    1.65 +  // allocated block.  If the allocation request cannot be satisfied,
    1.66 +  // return NULL.
    1.67 +  HeapWord* allocate(size_t word_sz) {
    1.68 +    HeapWord* res = _top;
    1.69 +    HeapWord* new_top = _top + word_sz;
    1.70 +    if (new_top <= _end) {
    1.71 +      _top = new_top;
    1.72 +      return res;
    1.73 +    } else {
    1.74 +      return NULL;
    1.75 +    }
    1.76 +  }
    1.77 +
    1.78 +  // Undo the last allocation in the buffer, which is required to be of the
    1.79 +  // "obj" of the given "word_sz".
    1.80 +  void undo_allocation(HeapWord* obj, size_t word_sz) {
    1.81 +    assert(_top - word_sz >= _bottom
    1.82 +           && _top - word_sz == obj,
    1.83 +           "Bad undo_allocation");
    1.84 +    _top = _top - word_sz;
    1.85 +  }
    1.86 +
    1.87 +  // The total (word) size of the buffer, including both allocated and
    1.88 +  // unallocted space.
    1.89 +  size_t word_sz() { return _word_sz; }
    1.90 +
    1.91 +  // Should only be done if we are about to reset with a new buffer of the
    1.92 +  // given size.
    1.93 +  void set_word_size(size_t new_word_sz) {
    1.94 +    assert(new_word_sz > AlignmentReserve, "Too small");
    1.95 +    _word_sz = new_word_sz;
    1.96 +  }
    1.97 +
    1.98 +  // The number of words of unallocated space remaining in the buffer.
    1.99 +  size_t words_remaining() {
   1.100 +    assert(_end >= _top, "Negative buffer");
   1.101 +    return pointer_delta(_end, _top, HeapWordSize);
   1.102 +  }
   1.103 +
   1.104 +  bool contains(void* addr) {
   1.105 +    return (void*)_bottom <= addr && addr < (void*)_hard_end;
   1.106 +  }
   1.107 +
   1.108 +  // Sets the space of the buffer to be [buf, space+word_sz()).
   1.109 +  void set_buf(HeapWord* buf) {
   1.110 +    _bottom   = buf;
   1.111 +    _top      = _bottom;
   1.112 +    _hard_end = _bottom + word_sz();
   1.113 +    _end      = _hard_end - AlignmentReserve;
   1.114 +    assert(_end >= _top, "Negative buffer");
   1.115 +    // In support of ergonomic sizing
   1.116 +    _allocated += word_sz();
   1.117 +  }
   1.118 +
   1.119 +  // Flush the stats supporting ergonomic sizing of PLAB's
   1.120 +  void flush_stats(PLABStats* stats);
   1.121 +  void flush_stats_and_retire(PLABStats* stats, bool retain) {
   1.122 +    // We flush the stats first in order to get a reading of
   1.123 +    // unused space in the last buffer.
   1.124 +    if (ResizePLAB) {
   1.125 +      flush_stats(stats);
   1.126 +    }
   1.127 +    // Retire the last allocation buffer.
   1.128 +    retire(true, retain);
   1.129 +  }
   1.130 +
   1.131 +  // Force future allocations to fail and queries for contains()
   1.132 +  // to return false
   1.133 +  void invalidate() {
   1.134 +    assert(!_retained, "Shouldn't retain an invalidated buffer.");
   1.135 +    _end    = _hard_end;
   1.136 +    _wasted += pointer_delta(_end, _top);  // unused  space
   1.137 +    _top    = _end;      // force future allocations to fail
   1.138 +    _bottom = _end;      // force future contains() queries to return false
   1.139 +  }
   1.140 +
   1.141 +  // Fills in the unallocated portion of the buffer with a garbage object.
   1.142 +  // If "end_of_gc" is TRUE, is after the last use in the GC.  IF "retain"
   1.143 +  // is true, attempt to re-use the unused portion in the next GC.
   1.144 +  void retire(bool end_of_gc, bool retain);
   1.145 +
   1.146 +  void print() PRODUCT_RETURN;
   1.147 +};
   1.148 +
   1.149 +// PLAB stats book-keeping
   1.150 +class PLABStats VALUE_OBJ_CLASS_SPEC {
   1.151 +  size_t _allocated;      // total allocated
   1.152 +  size_t _wasted;         // of which wasted (internal fragmentation)
   1.153 +  size_t _unused;         // Unused in last buffer
   1.154 +  size_t _used;           // derived = allocated - wasted - unused
   1.155 +  size_t _desired_plab_sz;// output of filter (below), suitably trimmed and quantized
   1.156 +  AdaptiveWeightedAverage
   1.157 +         _filter;         // integrator with decay
   1.158 +
   1.159 + public:
   1.160 +  PLABStats(size_t desired_plab_sz_, unsigned wt) :
   1.161 +    _allocated(0),
   1.162 +    _wasted(0),
   1.163 +    _unused(0),
   1.164 +    _used(0),
   1.165 +    _desired_plab_sz(desired_plab_sz_),
   1.166 +    _filter(wt)
   1.167 +  {
   1.168 +    size_t min_sz = min_size();
   1.169 +    size_t max_sz = max_size();
   1.170 +    size_t aligned_min_sz = align_object_size(min_sz);
   1.171 +    size_t aligned_max_sz = align_object_size(max_sz);
   1.172 +    assert(min_sz <= aligned_min_sz && max_sz >= aligned_max_sz &&
   1.173 +           min_sz <= max_sz,
   1.174 +           "PLAB clipping computation in adjust_desired_plab_sz()"
   1.175 +           " may be incorrect");
   1.176 +  }
   1.177 +
   1.178 +  static const size_t min_size() {
   1.179 +    return ParGCAllocBuffer::min_size();
   1.180 +  }
   1.181 +
   1.182 +  static const size_t max_size() {
   1.183 +    return ParGCAllocBuffer::max_size();
   1.184 +  }
   1.185 +
   1.186 +  size_t desired_plab_sz() {
   1.187 +    return _desired_plab_sz;
   1.188 +  }
   1.189 +
   1.190 +  void adjust_desired_plab_sz(); // filter computation, latches output to
   1.191 +                                 // _desired_plab_sz, clears sensor accumulators
   1.192 +
   1.193 +  void add_allocated(size_t v) {
   1.194 +    Atomic::add_ptr(v, &_allocated);
   1.195 +  }
   1.196 +
   1.197 +  void add_unused(size_t v) {
   1.198 +    Atomic::add_ptr(v, &_unused);
   1.199 +  }
   1.200 +
   1.201 +  void add_wasted(size_t v) {
   1.202 +    Atomic::add_ptr(v, &_wasted);
   1.203 +  }
   1.204 +};
   1.205 +
   1.206 +class ParGCAllocBufferWithBOT: public ParGCAllocBuffer {
   1.207 +  BlockOffsetArrayContigSpace _bt;
   1.208 +  BlockOffsetSharedArray*     _bsa;
   1.209 +  HeapWord*                   _true_end;  // end of the whole ParGCAllocBuffer
   1.210 +
   1.211 +  static const size_t ChunkSizeInWords;
   1.212 +  static const size_t ChunkSizeInBytes;
   1.213 +  HeapWord* allocate_slow(size_t word_sz);
   1.214 +
   1.215 +  void fill_region_with_block(MemRegion mr, bool contig);
   1.216 +
   1.217 +public:
   1.218 +  ParGCAllocBufferWithBOT(size_t word_sz, BlockOffsetSharedArray* bsa);
   1.219 +
   1.220 +  HeapWord* allocate(size_t word_sz) {
   1.221 +    HeapWord* res = ParGCAllocBuffer::allocate(word_sz);
   1.222 +    if (res != NULL) {
   1.223 +      _bt.alloc_block(res, word_sz);
   1.224 +    } else {
   1.225 +      res = allocate_slow(word_sz);
   1.226 +    }
   1.227 +    return res;
   1.228 +  }
   1.229 +
   1.230 +  void undo_allocation(HeapWord* obj, size_t word_sz);
   1.231 +
   1.232 +  void set_buf(HeapWord* buf_start) {
   1.233 +    ParGCAllocBuffer::set_buf(buf_start);
   1.234 +    _true_end = _hard_end;
   1.235 +    _bt.set_region(MemRegion(buf_start, word_sz()));
   1.236 +    _bt.initialize_threshold();
   1.237 +  }
   1.238 +
   1.239 +  void retire(bool end_of_gc, bool retain);
   1.240 +
   1.241 +  MemRegion range() {
   1.242 +    return MemRegion(_top, _true_end);
   1.243 +  }
   1.244 +};

mercurial