src/share/vm/gc_implementation/concurrentMarkSweep/freeList.hpp

Thu, 20 Nov 2008 16:56:09 -0800

author
ysr
date
Thu, 20 Nov 2008 16:56:09 -0800
changeset 888
c96030fff130
parent 631
d1605aabd0a1
child 1580
e018e6884bd8
permissions
-rw-r--r--

6684579: SoftReference processing can be made more efficient
Summary: For current soft-ref clearing policies, we can decide at marking time if a soft-reference will definitely not be cleared, postponing the decision of whether it will definitely be cleared to the final reference processing phase. This can be especially beneficial in the case of concurrent collectors where the marking is usually concurrent but reference processing is usually not.
Reviewed-by: jmasa

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

mercurial