src/share/vm/memory/binaryTreeDictionary.hpp

Wed, 25 Apr 2012 09:55:55 -0700

author
jmasa
date
Wed, 25 Apr 2012 09:55:55 -0700
changeset 3732
f69a5d43dc19
parent 3730
9f059abe8cf2
child 3822
a297b0e14605
permissions
-rw-r--r--

7164144: Fix variable naming style in freeBlockDictionary.* and binaryTreeDictionary*
Summary: Fix naming style to be consistent with the predominant hotspot style.
Reviewed-by: ysr, brutisso

     1 /*
     2  * Copyright (c) 2001, 2012, 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  */
    25 #ifndef SHARE_VM_MEMORY_BINARYTREEDICTIONARY_HPP
    26 #define SHARE_VM_MEMORY_BINARYTREEDICTIONARY_HPP
    28 #include "memory/freeBlockDictionary.hpp"
    29 #include "memory/freeList.hpp"
    31 /*
    32  * A binary tree based search structure for free blocks.
    33  * This is currently used in the Concurrent Mark&Sweep implementation, but
    34  * will be used for free block management for metadata.
    35  */
    37 // A TreeList is a FreeList which can be used to maintain a
    38 // binary tree of free lists.
    40 template <class Chunk> class TreeChunk;
    41 template <class Chunk> class BinaryTreeDictionary;
    42 template <class Chunk> class AscendTreeCensusClosure;
    43 template <class Chunk> class DescendTreeCensusClosure;
    44 template <class Chunk> class DescendTreeSearchClosure;
    46 template <class Chunk>
    47 class TreeList: public FreeList<Chunk> {
    48   friend class TreeChunk<Chunk>;
    49   friend class BinaryTreeDictionary<Chunk>;
    50   friend class AscendTreeCensusClosure<Chunk>;
    51   friend class DescendTreeCensusClosure<Chunk>;
    52   friend class DescendTreeSearchClosure<Chunk>;
    54   TreeList<Chunk>* _parent;
    55   TreeList<Chunk>* _left;
    56   TreeList<Chunk>* _right;
    58  protected:
    59   TreeList<Chunk>* parent() const { return _parent; }
    60   TreeList<Chunk>* left()   const { return _left;   }
    61   TreeList<Chunk>* right()  const { return _right;  }
    63   // Wrapper on call to base class, to get the template to compile.
    64   Chunk* head() const { return FreeList<Chunk>::head(); }
    65   Chunk* tail() const { return FreeList<Chunk>::tail(); }
    66   void set_head(Chunk* head) { FreeList<Chunk>::set_head(head); }
    67   void set_tail(Chunk* tail) { FreeList<Chunk>::set_tail(tail); }
    69   size_t size() const { return FreeList<Chunk>::size(); }
    71   // Accessors for links in tree.
    73   void set_left(TreeList<Chunk>* tl) {
    74     _left   = tl;
    75     if (tl != NULL)
    76       tl->set_parent(this);
    77   }
    78   void set_right(TreeList<Chunk>* tl) {
    79     _right  = tl;
    80     if (tl != NULL)
    81       tl->set_parent(this);
    82   }
    83   void set_parent(TreeList<Chunk>* tl)  { _parent = tl;   }
    85   void clearLeft()               { _left = NULL;   }
    86   void clear_right()              { _right = NULL;  }
    87   void clear_parent()             { _parent = NULL; }
    88   void initialize()              { clearLeft(); clear_right(), clear_parent(); }
    90   // For constructing a TreeList from a Tree chunk or
    91   // address and size.
    92   static TreeList<Chunk>* as_TreeList(TreeChunk<Chunk>* tc);
    93   static TreeList<Chunk>* as_TreeList(HeapWord* addr, size_t size);
    95   // Returns the head of the free list as a pointer to a TreeChunk.
    96   TreeChunk<Chunk>* head_as_TreeChunk();
    98   // Returns the first available chunk in the free list as a pointer
    99   // to a TreeChunk.
   100   TreeChunk<Chunk>* first_available();
   102   // Returns the block with the largest heap address amongst
   103   // those in the list for this size; potentially slow and expensive,
   104   // use with caution!
   105   TreeChunk<Chunk>* largest_address();
   107   // remove_chunk_replace_if_needed() removes the given "tc" from the TreeList.
   108   // If "tc" is the first chunk in the list, it is also the
   109   // TreeList that is the node in the tree.  remove_chunk_replace_if_needed()
   110   // returns the possibly replaced TreeList* for the node in
   111   // the tree.  It also updates the parent of the original
   112   // node to point to the new node.
   113   TreeList<Chunk>* remove_chunk_replace_if_needed(TreeChunk<Chunk>* tc);
   114   // See FreeList.
   115   void return_chunk_at_head(TreeChunk<Chunk>* tc);
   116   void return_chunk_at_tail(TreeChunk<Chunk>* tc);
   117 };
   119 // A TreeChunk is a subclass of a Chunk that additionally
   120 // maintains a pointer to the free list on which it is currently
   121 // linked.
   122 // A TreeChunk is also used as a node in the binary tree.  This
   123 // allows the binary tree to be maintained without any additional
   124 // storage (the free chunks are used).  In a binary tree the first
   125 // chunk in the free list is also the tree node.  Note that the
   126 // TreeChunk has an embedded TreeList for this purpose.  Because
   127 // the first chunk in the list is distinguished in this fashion
   128 // (also is the node in the tree), it is the last chunk to be found
   129 // on the free list for a node in the tree and is only removed if
   130 // it is the last chunk on the free list.
   132 template <class Chunk>
   133 class TreeChunk : public Chunk {
   134   friend class TreeList<Chunk>;
   135   TreeList<Chunk>* _list;
   136   TreeList<Chunk> _embedded_list;  // if non-null, this chunk is on _list
   137  protected:
   138   TreeList<Chunk>* embedded_list() const { return (TreeList<Chunk>*) &_embedded_list; }
   139   void set_embedded_list(TreeList<Chunk>* v) { _embedded_list = *v; }
   140  public:
   141   TreeList<Chunk>* list() { return _list; }
   142   void set_list(TreeList<Chunk>* v) { _list = v; }
   143   static TreeChunk<Chunk>* as_TreeChunk(Chunk* fc);
   144   // Initialize fields in a TreeChunk that should be
   145   // initialized when the TreeChunk is being added to
   146   // a free list in the tree.
   147   void initialize() { embedded_list()->initialize(); }
   149   Chunk* next() const { return Chunk::next(); }
   150   Chunk* prev() const { return Chunk::prev(); }
   151   size_t size() const volatile { return Chunk::size(); }
   153   // debugging
   154   void verify_tree_chunk_list() const;
   155 };
   158 template <class Chunk>
   159 class BinaryTreeDictionary: public FreeBlockDictionary<Chunk> {
   160   friend class VMStructs;
   161   bool       _splay;
   162   size_t     _total_size;
   163   size_t     _total_free_blocks;
   164   TreeList<Chunk>* _root;
   165   bool       _adaptive_freelists;
   167   // private accessors
   168   bool splay() const { return _splay; }
   169   void set_splay(bool v) { _splay = v; }
   170   void set_total_size(size_t v) { _total_size = v; }
   171   virtual void inc_total_size(size_t v);
   172   virtual void dec_total_size(size_t v);
   173   size_t total_free_blocks() const { return _total_free_blocks; }
   174   void set_total_free_blocks(size_t v) { _total_free_blocks = v; }
   175   TreeList<Chunk>* root() const { return _root; }
   176   void set_root(TreeList<Chunk>* v) { _root = v; }
   177   bool adaptive_freelists() { return _adaptive_freelists; }
   179   // This field is added and can be set to point to the
   180   // the Mutex used to synchronize access to the
   181   // dictionary so that assertion checking can be done.
   182   // For example it is set to point to _parDictionaryAllocLock.
   183   NOT_PRODUCT(Mutex* _lock;)
   185   // Remove a chunk of size "size" or larger from the tree and
   186   // return it.  If the chunk
   187   // is the last chunk of that size, remove the node for that size
   188   // from the tree.
   189   TreeChunk<Chunk>* get_chunk_from_tree(size_t size, enum FreeBlockDictionary<Chunk>::Dither dither, bool splay);
   190   // Return a list of the specified size or NULL from the tree.
   191   // The list is not removed from the tree.
   192   TreeList<Chunk>* find_list (size_t size) const;
   193   // Remove this chunk from the tree.  If the removal results
   194   // in an empty list in the tree, remove the empty list.
   195   TreeChunk<Chunk>* remove_chunk_from_tree(TreeChunk<Chunk>* tc);
   196   // Remove the node in the trees starting at tl that has the
   197   // minimum value and return it.  Repair the tree as needed.
   198   TreeList<Chunk>* remove_tree_minimum(TreeList<Chunk>* tl);
   199   void       semi_splay_step(TreeList<Chunk>* tl);
   200   // Add this free chunk to the tree.
   201   void       insert_chunk_in_tree(Chunk* freeChunk);
   202  public:
   204   static const size_t min_tree_chunk_size  = sizeof(TreeChunk<Chunk>)/HeapWordSize;
   206   void       verify_tree() const;
   207   // verify that the given chunk is in the tree.
   208   bool       verify_chunk_in_free_list(Chunk* tc) const;
   209  private:
   210   void          verify_tree_helper(TreeList<Chunk>* tl) const;
   211   static size_t verify_prev_free_ptrs(TreeList<Chunk>* tl);
   213   // Returns the total number of chunks in the list.
   214   size_t     total_list_length(TreeList<Chunk>* tl) const;
   215   // Returns the total number of words in the chunks in the tree
   216   // starting at "tl".
   217   size_t     total_size_in_tree(TreeList<Chunk>* tl) const;
   218   // Returns the sum of the square of the size of each block
   219   // in the tree starting at "tl".
   220   double     sum_of_squared_block_sizes(TreeList<Chunk>* const tl) const;
   221   // Returns the total number of free blocks in the tree starting
   222   // at "tl".
   223   size_t     total_free_blocks_in_tree(TreeList<Chunk>* tl) const;
   224   size_t     num_free_blocks() const;
   225   size_t     treeHeight() const;
   226   size_t     tree_height_helper(TreeList<Chunk>* tl) const;
   227   size_t     total_nodes_in_tree(TreeList<Chunk>* tl) const;
   228   size_t     total_nodes_helper(TreeList<Chunk>* tl) const;
   230  public:
   231   // Constructor
   232   BinaryTreeDictionary(bool adaptive_freelists, bool splay = false);
   233   BinaryTreeDictionary(MemRegion mr, bool adaptive_freelists, bool splay = false);
   235   // Public accessors
   236   size_t total_size() const { return _total_size; }
   238   // Reset the dictionary to the initial conditions with
   239   // a single free chunk.
   240   void       reset(MemRegion mr);
   241   void       reset(HeapWord* addr, size_t size);
   242   // Reset the dictionary to be empty.
   243   void       reset();
   245   // Return a chunk of size "size" or greater from
   246   // the tree.
   247   // want a better dynamic splay strategy for the future.
   248   Chunk* get_chunk(size_t size, enum FreeBlockDictionary<Chunk>::Dither dither) {
   249     FreeBlockDictionary<Chunk>::verify_par_locked();
   250     Chunk* res = get_chunk_from_tree(size, dither, splay());
   251     assert(res == NULL || res->is_free(),
   252            "Should be returning a free chunk");
   253     return res;
   254   }
   256   void return_chunk(Chunk* chunk) {
   257     FreeBlockDictionary<Chunk>::verify_par_locked();
   258     insert_chunk_in_tree(chunk);
   259   }
   261   void remove_chunk(Chunk* chunk) {
   262     FreeBlockDictionary<Chunk>::verify_par_locked();
   263     remove_chunk_from_tree((TreeChunk<Chunk>*)chunk);
   264     assert(chunk->is_free(), "Should still be a free chunk");
   265   }
   267   size_t     max_chunk_size() const;
   268   size_t     total_chunk_size(debug_only(const Mutex* lock)) const {
   269     debug_only(
   270       if (lock != NULL && lock->owned_by_self()) {
   271         assert(total_size_in_tree(root()) == total_size(),
   272                "_total_size inconsistency");
   273       }
   274     )
   275     return total_size();
   276   }
   278   size_t     min_size() const {
   279     return min_tree_chunk_size;
   280   }
   282   double     sum_of_squared_block_sizes() const {
   283     return sum_of_squared_block_sizes(root());
   284   }
   286   Chunk* find_chunk_ends_at(HeapWord* target) const;
   288   // Find the list with size "size" in the binary tree and update
   289   // the statistics in the list according to "split" (chunk was
   290   // split or coalesce) and "birth" (chunk was added or removed).
   291   void       dict_census_udpate(size_t size, bool split, bool birth);
   292   // Return true if the dictionary is overpopulated (more chunks of
   293   // this size than desired) for size "size".
   294   bool       coal_dict_over_populated(size_t size);
   295   // Methods called at the beginning of a sweep to prepare the
   296   // statistics for the sweep.
   297   void       begin_sweep_dict_census(double coalSurplusPercent,
   298                                   float inter_sweep_current,
   299                                   float inter_sweep_estimate,
   300                                   float intra_sweep_estimate);
   301   // Methods called after the end of a sweep to modify the
   302   // statistics for the sweep.
   303   void       end_sweep_dict_census(double splitSurplusPercent);
   304   // Return the largest free chunk in the tree.
   305   Chunk* find_largest_dict() const;
   306   // Accessors for statistics
   307   void       set_tree_surplus(double splitSurplusPercent);
   308   void       set_tree_hints(void);
   309   // Reset statistics for all the lists in the tree.
   310   void       clear_tree_census(void);
   311   // Print the statistcis for all the lists in the tree.  Also may
   312   // print out summaries.
   313   void       print_dict_census(void) const;
   314   void       print_free_lists(outputStream* st) const;
   316   // For debugging.  Returns the sum of the _returned_bytes for
   317   // all lists in the tree.
   318   size_t     sum_dict_returned_bytes()     PRODUCT_RETURN0;
   319   // Sets the _returned_bytes for all the lists in the tree to zero.
   320   void       initialize_dict_returned_bytes()      PRODUCT_RETURN;
   321   // For debugging.  Return the total number of chunks in the dictionary.
   322   size_t     total_count()       PRODUCT_RETURN0;
   324   void       report_statistics() const;
   326   void       verify() const;
   327 };
   329 #endif // SHARE_VM_MEMORY_BINARYTREEDICTIONARY_HPP

mercurial