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

Sat, 01 Dec 2007 00:00:00 +0000

author
duke
date
Sat, 01 Dec 2007 00:00:00 +0000
changeset 435
a61af66fc99e
child 622
790e66e5fbac
permissions
-rw-r--r--

Initial load

     1 /*
     2  * Copyright 2001-2005 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 //
    26 // Free block maintenance for Concurrent Mark Sweep Generation
    27 //
    28 // The main data structure for free blocks are
    29 // . an indexed array of small free blocks, and
    30 // . a dictionary of large free blocks
    31 //
    33 // No virtuals in FreeChunk (don't want any vtables).
    35 // A FreeChunk is merely a chunk that can be in a doubly linked list
    36 // and has a size field. NOTE: FreeChunks are distinguished from allocated
    37 // objects in two ways (by the sweeper). The second word (prev) has the
    38 // LSB set to indicate a free chunk; allocated objects' klass() pointers
    39 // don't have their LSB set. The corresponding bit in the CMSBitMap is
    40 // set when the chunk is allocated. There are also blocks that "look free"
    41 // but are not part of the free list and should not be coalesced into larger
    42 // free blocks. These free blocks have their two LSB's set.
    44 class FreeChunk VALUE_OBJ_CLASS_SPEC {
    45   friend class VMStructs;
    46   FreeChunk* _next;
    47   FreeChunk* _prev;
    48   size_t     _size;
    50  public:
    51   NOT_PRODUCT(static const size_t header_size();)
    52   // Returns "true" if the "wrd", which is required to be the second word
    53   // of a block, indicates that the block represents a free chunk.
    54   static bool secondWordIndicatesFreeChunk(intptr_t wrd) {
    55     return (wrd & 0x1) == 0x1;
    56   }
    57   bool isFree()       const {
    58     return secondWordIndicatesFreeChunk((intptr_t)_prev);
    59   }
    60   bool cantCoalesce() const { return (((intptr_t)_prev) & 0x3) == 0x3; }
    61   FreeChunk* next()   const { return _next; }
    62   FreeChunk* prev()   const { return (FreeChunk*)(((intptr_t)_prev) & ~(0x3)); }
    63   debug_only(void* prev_addr() const { return (void*)&_prev; })
    65   void linkAfter(FreeChunk* ptr) {
    66     linkNext(ptr);
    67     if (ptr != NULL) ptr->linkPrev(this);
    68   }
    69   void linkAfterNonNull(FreeChunk* ptr) {
    70     assert(ptr != NULL, "precondition violation");
    71     linkNext(ptr);
    72     ptr->linkPrev(this);
    73   }
    74   void linkNext(FreeChunk* ptr) { _next = ptr; }
    75   void linkPrev(FreeChunk* ptr) { _prev = (FreeChunk*)((intptr_t)ptr | 0x1); }
    76   void clearPrev()              { _prev = NULL; }
    77   void clearNext()              { _next = NULL; }
    78   void dontCoalesce()      {
    79     // the block should be free
    80     assert(isFree(), "Should look like a free block");
    81     _prev = (FreeChunk*)(((intptr_t)_prev) | 0x2);
    82   }
    83   void markFree()    { _prev = (FreeChunk*)((intptr_t)_prev | 0x1);    }
    84   void markNotFree() { _prev = NULL; }
    86   size_t size()           const { return _size; }
    87   void setSize(size_t size)     { _size = size; }
    89   // For volatile reads:
    90   size_t* size_addr()           { return &_size; }
    92   // Return the address past the end of this chunk
    93   HeapWord* end() const { return ((HeapWord*) this) + _size; }
    95   // debugging
    96   void verify()             const PRODUCT_RETURN;
    97   void verifyList()         const PRODUCT_RETURN;
    98   void mangleAllocated(size_t size) PRODUCT_RETURN;
    99   void mangleFreed(size_t size)     PRODUCT_RETURN;
   100 };
   102 // Alignment helpers etc.
   103 #define numQuanta(x,y) ((x+y-1)/y)
   104 enum AlignmentConstants {
   105   MinChunkSize = numQuanta(sizeof(FreeChunk), MinObjAlignmentInBytes) * MinObjAlignment
   106 };
   108 // A FreeBlockDictionary is an abstract superclass that will allow
   109 // a number of alternative implementations in the future.
   110 class FreeBlockDictionary: public CHeapObj {
   111  public:
   112   enum Dither {
   113     atLeast,
   114     exactly,
   115     roughly
   116   };
   117   enum DictionaryChoice {
   118     dictionaryBinaryTree = 0,
   119     dictionarySplayTree  = 1,
   120     dictionarySkipList   = 2
   121   };
   123  private:
   124   NOT_PRODUCT(Mutex* _lock;)
   126  public:
   127   virtual void       removeChunk(FreeChunk* fc) = 0;
   128   virtual FreeChunk* getChunk(size_t size, Dither dither = atLeast) = 0;
   129   virtual void       returnChunk(FreeChunk* chunk) = 0;
   130   virtual size_t     totalChunkSize(debug_only(const Mutex* lock)) const = 0;
   131   virtual size_t     maxChunkSize()   const = 0;
   132   virtual size_t     minSize()        const = 0;
   133   // Reset the dictionary to the initial conditions for a single
   134   // block.
   135   virtual void       reset(HeapWord* addr, size_t size) = 0;
   136   virtual void       reset() = 0;
   138   virtual void       dictCensusUpdate(size_t size, bool split, bool birth) = 0;
   139   virtual bool       coalDictOverPopulated(size_t size) = 0;
   140   virtual void       beginSweepDictCensus(double coalSurplusPercent,
   141                        float sweep_current, float sweep_ewstimate) = 0;
   142   virtual void       endSweepDictCensus(double splitSurplusPercent) = 0;
   143   virtual FreeChunk* findLargestDict() const = 0;
   144   // verify that the given chunk is in the dictionary.
   145   virtual bool verifyChunkInFreeLists(FreeChunk* tc) const = 0;
   147   // Sigma_{all_free_blocks} (block_size^2)
   148   virtual double sum_of_squared_block_sizes() const = 0;
   150   virtual FreeChunk* find_chunk_ends_at(HeapWord* target) const = 0;
   151   virtual void inc_totalSize(size_t v) = 0;
   152   virtual void dec_totalSize(size_t v) = 0;
   154   NOT_PRODUCT (
   155     virtual size_t   sumDictReturnedBytes() = 0;
   156     virtual void     initializeDictReturnedBytes() = 0;
   157     virtual size_t   totalCount() = 0;
   158   )
   160   virtual void       reportStatistics() const {
   161     gclog_or_tty->print("No statistics available");
   162   }
   164   virtual void       printDictCensus() const = 0;
   166   virtual void       verify()         const = 0;
   168   Mutex* par_lock()                const PRODUCT_RETURN0;
   169   void   set_par_lock(Mutex* lock)       PRODUCT_RETURN;
   170   void   verify_par_locked()       const PRODUCT_RETURN;
   171 };

mercurial