1 /*
   2  * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2018, 2020 SAP SE. All rights reserved.
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * This code is free software; you can redistribute it and/or modify it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  *
  24  */
  25 
  26 #ifndef SHARE_MEMORY_METASPACE_VIRTUALSPACELIST_HPP
  27 #define SHARE_MEMORY_METASPACE_VIRTUALSPACELIST_HPP
  28 
  29 #include "memory/allocation.hpp"
  30 #include "memory/metaspace/counter.hpp"
  31 #include "memory/metaspace/commitLimiter.hpp"
  32 #include "memory/metaspace/virtualSpaceNode.hpp"
  33 #include "memory/virtualspace.hpp"
  34 #include "utilities/globalDefinitions.hpp"
  35 
  36 class outputStream;
  37 
  38 namespace metaspace {
  39 
  40 class Metachunk;
  41 class FreeChunkListVector;
  42 
  43 
  44 // VirtualSpaceList manages a single (if its non-expandable) or
  45 //  a series of (if its expandable) virtual memory regions used
  46 //  for metaspace.
  47 //
  48 // Internally it holds a list of nodes (VirtualSpaceNode) each
  49 //  managing a single contiguous memory region. The first node of
  50 //  this list is the current node and used for allocation of new
  51 //  root chunks.
  52 //
  53 // Beyond access to those nodes and the ability to grow new nodes
  54 //  (if expandable) it allows for purging: purging this list means
  55 //  removing and unmapping all memory regions which are unused.
  56 
  57 class VirtualSpaceList : public CHeapObj<mtClass> {
  58 
  59   // Name
  60   const char* const _name;
  61 
  62   // Head of the list.
  63   VirtualSpaceNode* _first_node;
  64 
  65   // Number of nodes (kept for statistics only).
  66   IntCounter _nodes_counter;
  67 
  68   // Whether this list can expand by allocating new nodes.
  69   const bool _can_expand;
  70 
  71   // Whether this list can be purged.
  72   const bool _can_purge;
  73 
  74   // Used to check limits before committing memory.
  75   CommitLimiter* const _commit_limiter;
  76 
  77   // Statistics
  78 
  79   // Holds sum of reserved space, in words, over all list nodes.
  80   SizeCounter _reserved_words_counter;
  81 
  82   // Holds sum of committed space, in words, over all list nodes.
  83   SizeCounter _committed_words_counter;
  84 
  85   // Create a new node and append it to the list. After
  86   // this function, _current_node shall point to a new empty node.
  87   // List must be expandable for this to work.
  88   void create_new_node();
  89 
  90 public:
  91 
  92   // Create a new, empty, expandable list.
  93   VirtualSpaceList(const char* name, CommitLimiter* commit_limiter);
  94 
  95   // Create a new list. The list will contain one node only, which uses the given ReservedSpace.
  96   // It will be not expandable beyond that first node.
  97   VirtualSpaceList(const char* name, ReservedSpace rs, CommitLimiter* commit_limiter);
  98 
  99   virtual ~VirtualSpaceList();
 100 
 101   // Allocate a root chunk from this list.
 102   // Note: this just returns a chunk whose memory is reserved; no memory is committed yet.
 103   // Hence, before using this chunk, it must be committed.
 104   // May return NULL if vslist would need to be expanded to hold the new root node but
 105   // the list cannot be expanded (in practice this means we reached CompressedClassSpaceSize).
 106   Metachunk* allocate_root_chunk();
 107 
 108   // Attempts to purge nodes. This will remove and delete nodes which only contain free chunks.
 109   // The free chunks are removed from the freelists before the nodes are deleted.
 110   // Return number of purged nodes.
 111   int purge(FreeChunkListVector* freelists);
 112 
 113   //// Statistics ////
 114 
 115   // Return sum of reserved words in all nodes.
 116   size_t reserved_words() const     { return _reserved_words_counter.get(); }
 117 
 118   // Return sum of committed words in all nodes.
 119   size_t committed_words() const    { return _committed_words_counter.get(); }
 120 
 121   // Return number of nodes in this list.
 122   int num_nodes() const             { return _nodes_counter.get(); }
 123 
 124   //// Debug stuff ////
 125   DEBUG_ONLY(void verify(bool slow) const;)
 126   DEBUG_ONLY(void verify_locked(bool slow) const;)
 127 
 128   // Print all nodes in this space list.
 129   void print_on(outputStream* st) const;
 130 
 131   // Returns true if this pointer is contained in one of our nodes.
 132   bool contains(const MetaWord* p) const;
 133 
 134   // Returns true if the list is not expandable and no more root chunks
 135   // can be allocated.
 136   bool is_full() const;
 137 
 138   // Convenience methods to return the global class-space vslist
 139   //  and non-class vslist, respectively.
 140   static VirtualSpaceList* vslist_class();
 141   static VirtualSpaceList* vslist_nonclass();
 142 
 143   // These exist purely to print limits of the compressed class space;
 144   // if we ever change the ccs to not use a degenerated-list-of-one-node this
 145   // will go away.
 146   MetaWord* base_of_first_node() const { return _first_node != NULL ? _first_node->base() : NULL; }
 147   size_t word_size_of_first_node() const { return _first_node != NULL ? _first_node->word_size() : 0; }
 148 
 149 };
 150 
 151 } // namespace metaspace
 152 
 153 #endif // SHARE_MEMORY_METASPACE_VIRTUALSPACELIST_HPP
 154