1 /*
   2  * Copyright 2001-2006 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  20  * CA 95054 USA or visit www.sun.com if you need additional information or
  21  * have any questions.
  22  *
  23  */
  24 
  25 class CompactibleFreeListSpace;
  26 
  27 // A class for maintaining a free list of FreeChunk's.  The FreeList
  28 // maintains a the structure of the list (head, tail, etc.) plus
  29 // statistics for allocations from the list.  The links between items
  30 // are not part of FreeList.  The statistics are
  31 // used to make decisions about coalescing FreeChunk's when they
  32 // are swept during collection.
  33 //
  34 // See the corresponding .cpp file for a description of the specifics
  35 // for that implementation.
  36 
  37 class Mutex;
  38 
  39 class FreeList VALUE_OBJ_CLASS_SPEC {
  40   friend class CompactibleFreeListSpace;
  41   friend class printTreeCensusClosure;
  42   FreeChunk*    _head;          // List of free chunks
  43   FreeChunk*    _tail;          // Tail of list of free chunks
  44   size_t        _size;          // Size in Heap words of each chunks
  45   ssize_t       _count;         // Number of entries in list
  46   size_t        _hint;          // next larger size list with a positive surplus
  47 
  48   AllocationStats _allocation_stats;            // statistics for smart allocation
  49 
  50 #ifdef ASSERT
  51   Mutex*        _protecting_lock;
  52 #endif
  53 
  54   // Asserts false if the protecting lock (if any) is not held.
  55   void assert_proper_lock_protection_work() const PRODUCT_RETURN;
  56   void assert_proper_lock_protection() const {
  57 #ifdef ASSERT
  58     if (_protecting_lock != NULL)
  59       assert_proper_lock_protection_work();
  60 #endif
  61   }
  62 
  63   // Initialize the allocation statistics.
  64  protected:
  65   void init_statistics();
  66   void set_count(ssize_t v) { _count = v;}
  67   void increment_count()    { _count++; }
  68   void decrement_count() {
  69     _count--;
  70     assert(_count >= 0, "Count should not be negative");
  71   }
  72 
  73  public:
  74   // Constructor
  75   // Construct a list without any entries.
  76   FreeList();
  77   // Construct a list with "fc" as the first (and lone) entry in the list.
  78   FreeList(FreeChunk* fc);
  79   // Construct a list which will have a FreeChunk at address "addr" and
  80   // of size "size" as the first (and lone) entry in the list.
  81   FreeList(HeapWord* addr, size_t size);
  82 
  83   // Reset the head, tail, hint, and count of a free list.
  84   void reset(size_t hint);
  85 
  86   // Declare the current free list to be protected by the given lock.
  87 #ifdef ASSERT
  88   void set_protecting_lock(Mutex* protecting_lock) {
  89     _protecting_lock = protecting_lock;
  90   }
  91 #endif
  92 
  93   // Accessors.
  94   FreeChunk* head() const {
  95     assert_proper_lock_protection();
  96     return _head;
  97   }
  98   void set_head(FreeChunk* v) {
  99     assert_proper_lock_protection();
 100     _head = v;
 101     assert(!_head || _head->size() == _size, "bad chunk size");
 102   }
 103   // Set the head of the list and set the prev field of non-null
 104   // values to NULL.
 105   void link_head(FreeChunk* v) {
 106     assert_proper_lock_protection();
 107     set_head(v);
 108     // If this method is not used (just set the head instead),
 109     // this check can be avoided.
 110     if (v != NULL) {
 111       v->linkPrev(NULL);
 112     }
 113   }
 114 
 115   FreeChunk* tail() const {
 116     assert_proper_lock_protection();
 117     return _tail;
 118   }
 119   void set_tail(FreeChunk* v) {
 120     assert_proper_lock_protection();
 121     _tail = v;
 122     assert(!_tail || _tail->size() == _size, "bad chunk size");
 123   }
 124   // Set the tail of the list and set the next field of non-null
 125   // values to NULL.
 126   void link_tail(FreeChunk* v) {
 127     assert_proper_lock_protection();
 128     set_tail(v);
 129     if (v != NULL) {
 130       v->clearNext();
 131     }
 132   }
 133 
 134   // No locking checks in read-accessors: lock-free reads (only) are benign.
 135   // Readers are expected to have the lock if they are doing work that
 136   // requires atomicity guarantees in sections of code.
 137   size_t size() const {
 138     return _size;
 139   }
 140   void set_size(size_t v) {
 141     assert_proper_lock_protection();
 142     _size = v;
 143   }
 144   ssize_t count() const {
 145     return _count;
 146   }
 147   size_t hint() const {
 148     return _hint;
 149   }
 150   void set_hint(size_t v) {
 151     assert_proper_lock_protection();
 152     assert(v == 0 || _size < v, "Bad hint"); _hint = v;
 153   }
 154 
 155   // Accessors for statistics
 156   AllocationStats* allocation_stats() {
 157     assert_proper_lock_protection();
 158     return &_allocation_stats;
 159   }
 160 
 161   ssize_t desired() const {
 162     return _allocation_stats.desired();
 163   }
 164   void set_desired(ssize_t v) {
 165     assert_proper_lock_protection();
 166     _allocation_stats.set_desired(v);
 167   }
 168   void compute_desired(float inter_sweep_current,
 169                        float inter_sweep_estimate) {
 170     assert_proper_lock_protection();
 171     _allocation_stats.compute_desired(_count,
 172                                       inter_sweep_current,
 173                                       inter_sweep_estimate);
 174   }
 175   ssize_t coalDesired() const {
 176     return _allocation_stats.coalDesired();
 177   }
 178   void set_coalDesired(ssize_t v) {
 179     assert_proper_lock_protection();
 180     _allocation_stats.set_coalDesired(v);
 181   }
 182 
 183   ssize_t surplus() const {
 184     return _allocation_stats.surplus();
 185   }
 186   void set_surplus(ssize_t v) {
 187     assert_proper_lock_protection();
 188     _allocation_stats.set_surplus(v);
 189   }
 190   void increment_surplus() {
 191     assert_proper_lock_protection();
 192     _allocation_stats.increment_surplus();
 193   }
 194   void decrement_surplus() {
 195     assert_proper_lock_protection();
 196     _allocation_stats.decrement_surplus();
 197   }
 198 
 199   ssize_t bfrSurp() const {
 200     return _allocation_stats.bfrSurp();
 201   }
 202   void set_bfrSurp(ssize_t v) {
 203     assert_proper_lock_protection();
 204     _allocation_stats.set_bfrSurp(v);
 205   }
 206   ssize_t prevSweep() const {
 207     return _allocation_stats.prevSweep();
 208   }
 209   void set_prevSweep(ssize_t v) {
 210     assert_proper_lock_protection();
 211     _allocation_stats.set_prevSweep(v);
 212   }
 213   ssize_t beforeSweep() const {
 214     return _allocation_stats.beforeSweep();
 215   }
 216   void set_beforeSweep(ssize_t v) {
 217     assert_proper_lock_protection();
 218     _allocation_stats.set_beforeSweep(v);
 219   }
 220 
 221   ssize_t coalBirths() const {
 222     return _allocation_stats.coalBirths();
 223   }
 224   void set_coalBirths(ssize_t v) {
 225     assert_proper_lock_protection();
 226     _allocation_stats.set_coalBirths(v);
 227   }
 228   void increment_coalBirths() {
 229     assert_proper_lock_protection();
 230     _allocation_stats.increment_coalBirths();
 231   }
 232 
 233   ssize_t coalDeaths() const {
 234     return _allocation_stats.coalDeaths();
 235   }
 236   void set_coalDeaths(ssize_t v) {
 237     assert_proper_lock_protection();
 238     _allocation_stats.set_coalDeaths(v);
 239   }
 240   void increment_coalDeaths() {
 241     assert_proper_lock_protection();
 242     _allocation_stats.increment_coalDeaths();
 243   }
 244 
 245   ssize_t splitBirths() const {
 246     return _allocation_stats.splitBirths();
 247   }
 248   void set_splitBirths(ssize_t v) {
 249     assert_proper_lock_protection();
 250     _allocation_stats.set_splitBirths(v);
 251   }
 252   void increment_splitBirths() {
 253     assert_proper_lock_protection();
 254     _allocation_stats.increment_splitBirths();
 255   }
 256 
 257   ssize_t splitDeaths() const {
 258     return _allocation_stats.splitDeaths();
 259   }
 260   void set_splitDeaths(ssize_t v) {
 261     assert_proper_lock_protection();
 262     _allocation_stats.set_splitDeaths(v);
 263   }
 264   void increment_splitDeaths() {
 265     assert_proper_lock_protection();
 266     _allocation_stats.increment_splitDeaths();
 267   }
 268 
 269   NOT_PRODUCT(
 270     // For debugging.  The "_returnedBytes" in all the lists are summed
 271     // and compared with the total number of bytes swept during a
 272     // collection.
 273     size_t returnedBytes() const { return _allocation_stats.returnedBytes(); }
 274     void set_returnedBytes(size_t v) { _allocation_stats.set_returnedBytes(v); }
 275     void increment_returnedBytes_by(size_t v) {
 276       _allocation_stats.set_returnedBytes(_allocation_stats.returnedBytes() + v);
 277     }
 278   )
 279 
 280   // Unlink head of list and return it.  Returns NULL if
 281   // the list is empty.
 282   FreeChunk* getChunkAtHead();
 283 
 284   // Remove the first "n" or "count", whichever is smaller, chunks from the
 285   // list, setting "fl", which is required to be empty, to point to them.
 286   void getFirstNChunksFromList(size_t n, FreeList* fl);
 287 
 288   // Unlink this chunk from it's free list
 289   void removeChunk(FreeChunk* fc);
 290 
 291   // Add this chunk to this free list.
 292   void returnChunkAtHead(FreeChunk* fc);
 293   void returnChunkAtTail(FreeChunk* fc);
 294 
 295   // Similar to returnChunk* but also records some diagnostic
 296   // information.
 297   void returnChunkAtHead(FreeChunk* fc, bool record_return);
 298   void returnChunkAtTail(FreeChunk* fc, bool record_return);
 299 
 300   // Prepend "fl" (whose size is required to be the same as that of "this")
 301   // to the front of "this" list.
 302   void prepend(FreeList* fl);
 303 
 304   // Verify that the chunk is in the list.
 305   // found.  Return NULL if "fc" is not found.
 306   bool verifyChunkInFreeLists(FreeChunk* fc) const;
 307 
 308   // Printing support
 309   static void print_labels_on(outputStream* st, const char* c);
 310   void print_on(outputStream* st, const char* c = NULL) const;
 311 };