src/share/vm/memory/binaryTreeDictionary.hpp

Fri, 20 Sep 2013 10:53:28 +0200

author
stefank
date
Fri, 20 Sep 2013 10:53:28 +0200
changeset 5769
2c022e432e10
parent 4488
3c327c2b6782
child 6198
55fb97c4c58d
permissions
-rw-r--r--

8024974: Incorrect use of GC_locker::is_active()
Summary: SymbolTable and StringTable can make calls to GC_locker::is_active() outside a safepoint. This isn't safe because the GC_locker active state (lock count) is only updated at a safepoint and only remains valid as long as _needs_gc is true. However, outside a safepoint_needs_gc can change to false at any time, which makes it impossible to do a correct call to is_active() in that context. In this case these calls can just be removed since the input argument to basic_add() should never be on the heap and so there's no need to check the GC_locker state. This change also adjusts the assert() in is_active() to makes sure all calls to this function are always done under a safepoint.
Reviewed-by: brutisso, dcubed
Contributed-by: per.liden@oracle.com

     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_t, template <class> class FreeList_t> class TreeChunk;
    41 template <class Chunk_t, template <class> class FreeList_t> class BinaryTreeDictionary;
    42 template <class Chunk_t, template <class> class FreeList_t> class AscendTreeCensusClosure;
    43 template <class Chunk_t, template <class> class FreeList_t> class DescendTreeCensusClosure;
    44 template <class Chunk_t, template <class> class FreeList_t> class DescendTreeSearchClosure;
    46 class FreeChunk;
    47 template <class> class AdaptiveFreeList;
    48 typedef BinaryTreeDictionary<FreeChunk, AdaptiveFreeList> AFLBinaryTreeDictionary;
    50 template <class Chunk_t, template <class> class FreeList_t>
    51 class TreeList : public FreeList_t<Chunk_t> {
    52   friend class TreeChunk<Chunk_t, FreeList_t>;
    53   friend class BinaryTreeDictionary<Chunk_t, FreeList_t>;
    54   friend class AscendTreeCensusClosure<Chunk_t, FreeList_t>;
    55   friend class DescendTreeCensusClosure<Chunk_t, FreeList_t>;
    56   friend class DescendTreeSearchClosure<Chunk_t, FreeList_t>;
    58   TreeList<Chunk_t, FreeList_t>* _parent;
    59   TreeList<Chunk_t, FreeList_t>* _left;
    60   TreeList<Chunk_t, FreeList_t>* _right;
    62  protected:
    64   TreeList<Chunk_t, FreeList_t>* parent() const { return _parent; }
    65   TreeList<Chunk_t, FreeList_t>* left()   const { return _left;   }
    66   TreeList<Chunk_t, FreeList_t>* right()  const { return _right;  }
    68   // Wrapper on call to base class, to get the template to compile.
    69   Chunk_t* head() const { return FreeList_t<Chunk_t>::head(); }
    70   Chunk_t* tail() const { return FreeList_t<Chunk_t>::tail(); }
    71   void set_head(Chunk_t* head) { FreeList_t<Chunk_t>::set_head(head); }
    72   void set_tail(Chunk_t* tail) { FreeList_t<Chunk_t>::set_tail(tail); }
    74   size_t size() const { return FreeList_t<Chunk_t>::size(); }
    76   // Accessors for links in tree.
    78   void set_left(TreeList<Chunk_t, FreeList_t>* tl) {
    79     _left   = tl;
    80     if (tl != NULL)
    81       tl->set_parent(this);
    82   }
    83   void set_right(TreeList<Chunk_t, FreeList_t>* tl) {
    84     _right  = tl;
    85     if (tl != NULL)
    86       tl->set_parent(this);
    87   }
    88   void set_parent(TreeList<Chunk_t, FreeList_t>* tl)  { _parent = tl;   }
    90   void clear_left()               { _left = NULL;   }
    91   void clear_right()              { _right = NULL;  }
    92   void clear_parent()             { _parent = NULL; }
    93   void initialize()               { clear_left(); clear_right(), clear_parent(); FreeList_t<Chunk_t>::initialize(); }
    95   // For constructing a TreeList from a Tree chunk or
    96   // address and size.
    97   TreeList();
    98   static TreeList<Chunk_t, FreeList_t>*
    99           as_TreeList(TreeChunk<Chunk_t, FreeList_t>* tc);
   100   static TreeList<Chunk_t, FreeList_t>* as_TreeList(HeapWord* addr, size_t size);
   102   // Returns the head of the free list as a pointer to a TreeChunk.
   103   TreeChunk<Chunk_t, FreeList_t>* head_as_TreeChunk();
   105   // Returns the first available chunk in the free list as a pointer
   106   // to a TreeChunk.
   107   TreeChunk<Chunk_t, FreeList_t>* first_available();
   109   // Returns the block with the largest heap address amongst
   110   // those in the list for this size; potentially slow and expensive,
   111   // use with caution!
   112   TreeChunk<Chunk_t, FreeList_t>* largest_address();
   114   TreeList<Chunk_t, FreeList_t>* get_better_list(
   115     BinaryTreeDictionary<Chunk_t, FreeList_t>* dictionary);
   117   // remove_chunk_replace_if_needed() removes the given "tc" from the TreeList.
   118   // If "tc" is the first chunk in the list, it is also the
   119   // TreeList that is the node in the tree.  remove_chunk_replace_if_needed()
   120   // returns the possibly replaced TreeList* for the node in
   121   // the tree.  It also updates the parent of the original
   122   // node to point to the new node.
   123   TreeList<Chunk_t, FreeList_t>* remove_chunk_replace_if_needed(TreeChunk<Chunk_t, FreeList_t>* tc);
   124   // See FreeList.
   125   void return_chunk_at_head(TreeChunk<Chunk_t, FreeList_t>* tc);
   126   void return_chunk_at_tail(TreeChunk<Chunk_t, FreeList_t>* tc);
   127 };
   129 // A TreeChunk is a subclass of a Chunk that additionally
   130 // maintains a pointer to the free list on which it is currently
   131 // linked.
   132 // A TreeChunk is also used as a node in the binary tree.  This
   133 // allows the binary tree to be maintained without any additional
   134 // storage (the free chunks are used).  In a binary tree the first
   135 // chunk in the free list is also the tree node.  Note that the
   136 // TreeChunk has an embedded TreeList for this purpose.  Because
   137 // the first chunk in the list is distinguished in this fashion
   138 // (also is the node in the tree), it is the last chunk to be found
   139 // on the free list for a node in the tree and is only removed if
   140 // it is the last chunk on the free list.
   142 template <class Chunk_t, template <class> class FreeList_t>
   143 class TreeChunk : public Chunk_t {
   144   friend class TreeList<Chunk_t, FreeList_t>;
   145   TreeList<Chunk_t, FreeList_t>* _list;
   146   TreeList<Chunk_t, FreeList_t> _embedded_list;  // if non-null, this chunk is on _list
   148   static size_t _min_tree_chunk_size;
   150  protected:
   151   TreeList<Chunk_t, FreeList_t>* embedded_list() const { return (TreeList<Chunk_t, FreeList_t>*) &_embedded_list; }
   152   void set_embedded_list(TreeList<Chunk_t, FreeList_t>* v) { _embedded_list = *v; }
   153  public:
   154   TreeList<Chunk_t, FreeList_t>* list() { return _list; }
   155   void set_list(TreeList<Chunk_t, FreeList_t>* v) { _list = v; }
   156   static TreeChunk<Chunk_t, FreeList_t>* as_TreeChunk(Chunk_t* fc);
   157   // Initialize fields in a TreeChunk that should be
   158   // initialized when the TreeChunk is being added to
   159   // a free list in the tree.
   160   void initialize() { embedded_list()->initialize(); }
   162   Chunk_t* next() const { return Chunk_t::next(); }
   163   Chunk_t* prev() const { return Chunk_t::prev(); }
   164   size_t size() const volatile { return Chunk_t::size(); }
   166   static size_t min_size() {
   167     return _min_tree_chunk_size;
   168   }
   170   // debugging
   171   void verify_tree_chunk_list() const;
   172   void assert_is_mangled() const;
   173 };
   176 template <class Chunk_t, template <class> class FreeList_t>
   177 class BinaryTreeDictionary: public FreeBlockDictionary<Chunk_t> {
   178   friend class VMStructs;
   179   size_t     _total_size;
   180   size_t     _total_free_blocks;
   181   TreeList<Chunk_t, FreeList_t>* _root;
   183   // private accessors
   184   void set_total_size(size_t v) { _total_size = v; }
   185   virtual void inc_total_size(size_t v);
   186   virtual void dec_total_size(size_t v);
   187   void set_total_free_blocks(size_t v) { _total_free_blocks = v; }
   188   TreeList<Chunk_t, FreeList_t>* root() const { return _root; }
   189   void set_root(TreeList<Chunk_t, FreeList_t>* v) { _root = v; }
   191   // This field is added and can be set to point to the
   192   // the Mutex used to synchronize access to the
   193   // dictionary so that assertion checking can be done.
   194   // For example it is set to point to _parDictionaryAllocLock.
   195   NOT_PRODUCT(Mutex* _lock;)
   197   // Remove a chunk of size "size" or larger from the tree and
   198   // return it.  If the chunk
   199   // is the last chunk of that size, remove the node for that size
   200   // from the tree.
   201   TreeChunk<Chunk_t, FreeList_t>* get_chunk_from_tree(size_t size, enum FreeBlockDictionary<Chunk_t>::Dither dither);
   202   // Remove this chunk from the tree.  If the removal results
   203   // in an empty list in the tree, remove the empty list.
   204   TreeChunk<Chunk_t, FreeList_t>* remove_chunk_from_tree(TreeChunk<Chunk_t, FreeList_t>* tc);
   205   // Remove the node in the trees starting at tl that has the
   206   // minimum value and return it.  Repair the tree as needed.
   207   TreeList<Chunk_t, FreeList_t>* remove_tree_minimum(TreeList<Chunk_t, FreeList_t>* tl);
   208   // Add this free chunk to the tree.
   209   void       insert_chunk_in_tree(Chunk_t* freeChunk);
   210  public:
   212   // Return a list of the specified size or NULL from the tree.
   213   // The list is not removed from the tree.
   214   TreeList<Chunk_t, FreeList_t>* find_list (size_t size) const;
   216   void       verify_tree() const;
   217   // verify that the given chunk is in the tree.
   218   bool       verify_chunk_in_free_list(Chunk_t* tc) const;
   219  private:
   220   void          verify_tree_helper(TreeList<Chunk_t, FreeList_t>* tl) const;
   221   static size_t verify_prev_free_ptrs(TreeList<Chunk_t, FreeList_t>* tl);
   223   // Returns the total number of chunks in the list.
   224   size_t     total_list_length(TreeList<Chunk_t, FreeList_t>* tl) const;
   225   // Returns the total number of words in the chunks in the tree
   226   // starting at "tl".
   227   size_t     total_size_in_tree(TreeList<Chunk_t, FreeList_t>* tl) const;
   228   // Returns the sum of the square of the size of each block
   229   // in the tree starting at "tl".
   230   double     sum_of_squared_block_sizes(TreeList<Chunk_t, FreeList_t>* const tl) const;
   231   // Returns the total number of free blocks in the tree starting
   232   // at "tl".
   233   size_t     total_free_blocks_in_tree(TreeList<Chunk_t, FreeList_t>* tl) const;
   234   size_t     num_free_blocks()  const;
   235   size_t     tree_height() const;
   236   size_t     tree_height_helper(TreeList<Chunk_t, FreeList_t>* tl) const;
   237   size_t     total_nodes_in_tree(TreeList<Chunk_t, FreeList_t>* tl) const;
   238   size_t     total_nodes_helper(TreeList<Chunk_t, FreeList_t>* tl) const;
   240  public:
   241   // Constructor
   242   BinaryTreeDictionary() :
   243     _total_size(0), _total_free_blocks(0), _root(0) {}
   245   BinaryTreeDictionary(MemRegion mr);
   247   // Public accessors
   248   size_t total_size() const { return _total_size; }
   249   size_t total_free_blocks() const { return _total_free_blocks; }
   251   // Reset the dictionary to the initial conditions with
   252   // a single free chunk.
   253   void       reset(MemRegion mr);
   254   void       reset(HeapWord* addr, size_t size);
   255   // Reset the dictionary to be empty.
   256   void       reset();
   258   // Return a chunk of size "size" or greater from
   259   // the tree.
   260   Chunk_t* get_chunk(size_t size, enum FreeBlockDictionary<Chunk_t>::Dither dither) {
   261     FreeBlockDictionary<Chunk_t>::verify_par_locked();
   262     Chunk_t* res = get_chunk_from_tree(size, dither);
   263     assert(res == NULL || res->is_free(),
   264            "Should be returning a free chunk");
   265     assert(dither != FreeBlockDictionary<Chunk_t>::exactly ||
   266            res == NULL || res->size() == size, "Not correct size");
   267     return res;
   268   }
   270   void return_chunk(Chunk_t* chunk) {
   271     FreeBlockDictionary<Chunk_t>::verify_par_locked();
   272     insert_chunk_in_tree(chunk);
   273   }
   275   void remove_chunk(Chunk_t* chunk) {
   276     FreeBlockDictionary<Chunk_t>::verify_par_locked();
   277     remove_chunk_from_tree((TreeChunk<Chunk_t, FreeList_t>*)chunk);
   278     assert(chunk->is_free(), "Should still be a free chunk");
   279   }
   281   size_t     max_chunk_size() const;
   282   size_t     total_chunk_size(debug_only(const Mutex* lock)) const {
   283     debug_only(
   284       if (lock != NULL && lock->owned_by_self()) {
   285         assert(total_size_in_tree(root()) == total_size(),
   286                "_total_size inconsistency");
   287       }
   288     )
   289     return total_size();
   290   }
   292   size_t     min_size() const {
   293     return TreeChunk<Chunk_t, FreeList_t>::min_size();
   294   }
   296   double     sum_of_squared_block_sizes() const {
   297     return sum_of_squared_block_sizes(root());
   298   }
   300   Chunk_t* find_chunk_ends_at(HeapWord* target) const;
   302   // Find the list with size "size" in the binary tree and update
   303   // the statistics in the list according to "split" (chunk was
   304   // split or coalesce) and "birth" (chunk was added or removed).
   305   void       dict_census_update(size_t size, bool split, bool birth);
   306   // Return true if the dictionary is overpopulated (more chunks of
   307   // this size than desired) for size "size".
   308   bool       coal_dict_over_populated(size_t size);
   309   // Methods called at the beginning of a sweep to prepare the
   310   // statistics for the sweep.
   311   void       begin_sweep_dict_census(double coalSurplusPercent,
   312                                   float inter_sweep_current,
   313                                   float inter_sweep_estimate,
   314                                   float intra_sweep_estimate);
   315   // Methods called after the end of a sweep to modify the
   316   // statistics for the sweep.
   317   void       end_sweep_dict_census(double splitSurplusPercent);
   318   // Return the largest free chunk in the tree.
   319   Chunk_t* find_largest_dict() const;
   320   // Accessors for statistics
   321   void       set_tree_surplus(double splitSurplusPercent);
   322   void       set_tree_hints(void);
   323   // Reset statistics for all the lists in the tree.
   324   void       clear_tree_census(void);
   325   // Print the statistcis for all the lists in the tree.  Also may
   326   // print out summaries.
   327   void       print_dict_census(void) const;
   328   void       print_free_lists(outputStream* st) const;
   330   // For debugging.  Returns the sum of the _returned_bytes for
   331   // all lists in the tree.
   332   size_t     sum_dict_returned_bytes()     PRODUCT_RETURN0;
   333   // Sets the _returned_bytes for all the lists in the tree to zero.
   334   void       initialize_dict_returned_bytes()      PRODUCT_RETURN;
   335   // For debugging.  Return the total number of chunks in the dictionary.
   336   size_t     total_count()       PRODUCT_RETURN0;
   338   void       report_statistics() const;
   340   void       verify() const;
   341 };
   343 #endif // SHARE_VM_MEMORY_BINARYTREEDICTIONARY_HPP

mercurial