1 /*
   2  * Copyright (c) 2018, 2019, 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  */
  24 
  25 #ifndef SHARE_MEMORY_METASPACE_CHUNKMANAGER_HPP
  26 #define SHARE_MEMORY_METASPACE_CHUNKMANAGER_HPP
  27 
  28 #include "memory/allocation.hpp"
  29 #include "memory/metaspace/chunkLevel.hpp"
  30 #include "memory/metaspace/counter.hpp"
  31 #include "memory/metaspace/metachunk.hpp"
  32 
  33 namespace metaspace {
  34 
  35 class VirtualSpaceList;
  36 class ChunkManagerStatistics;
  37 
  38 // class ChunkManager
  39 //
  40 // The ChunkManager has a central role. Callers request chunks from it.
  41 // It keeps the freelists for chunks. If the freelist is exhausted it
  42 // allocates new chunks from a connected VirtualSpaceList.
  43 //
  44 class ChunkManager : public CHeapObj<mtInternal> {
  45 
  46   // A chunk manager is connected to a virtual space list which is used
  47   // to allocate new root chunks when no free chunks are found.
  48   VirtualSpaceList* const _vslist;
  49 
  50   // Name
  51   const char* const _name;
  52 
  53   // Freelist
  54   MetachunkList _chunks [chklvl::NUM_CHUNK_LEVELS];
  55 
  56   // Total size, in words, of all chunks.
  57   SizeCounter _total_word_size;
  58 
  59   // Total size, in words, of the committed parts of all chunks.
  60   SizeCounter _committed_word_size;
  61 
  62   // Returns true if this manager contains the given chunk. Slow (walks free list) and
  63   // only needed for verifications.
  64   DEBUG_ONLY(bool contains_chunk(Metachunk* metachunk) const;)
  65 
  66   // Given a chunk we are about to handout to the caller, make sure it is committed
  67   // according to constants::committed_words_on_fresh_chunks.
  68   // May fail if we hit the commit limit.
  69   static bool commit_chunk_before_handout(Metachunk* c);
  70 
  71   // Return a single chunk to the freelist and adjust accounting. No merge is attempted.
  72   void return_chunk_simple(Metachunk* c);
  73 
  74   // Take a single chunk from the given freelist and adjust counters. Returns NULL
  75   // if there is no fitting chunk for this level.
  76   Metachunk* remove_first_chunk_at_level(chklvl_t l);
  77 
  78 
  79   // Given a chunk which must be outside of a freelist and must be free, split it to
  80   // meet a target level and return it. Splinters are added to the freelist.
  81   Metachunk* split_chunk_and_add_splinters(Metachunk* c, chklvl_t target_level);
  82 
  83 public:
  84 
  85   // Creates a chunk manager with a given name (which is for debug purposes only)
  86   // and an associated space list which will be used to request new chunks from
  87   // (see get_chunk())
  88   ChunkManager(const char* name, VirtualSpaceList* space_list);
  89 
  90   // Get a chunk and be smart about it.
  91   // - 1) Attempt to find a free chunk of exactly the pref_level level
  92   // - 2) Failing that, attempt to find a chunk smaller or equal the minimal level.
  93   // - 3) Failing that, attempt to find a free chunk of larger size and split it.
  94   // - 4) Failing that, attempt to allocate a new chunk from the connected virtual space.
  95   // - Failing that, give up and return NULL.
  96   // Note: this is not guaranteed to return a *committed* chunk. The chunk manager will
  97   //   attempt to commit the returned chunk according to constants::committed_words_on_fresh_chunks;
  98   //   but this may fail if we hit a commit limit. In that case, a partly uncommitted chunk
  99   //   will be returned, and the commit is attempted again when we allocate from the chunk's
 100   //   uncommitted area. See also Metachunk::allocate.
 101   Metachunk* get_chunk(chklvl_t min_level, chklvl_t pref_level);
 102 
 103   // Return a single chunk to the ChunkManager and adjust accounting. May merge chunk
 104   //  with neighbors.
 105   // Happens after a Classloader was unloaded and releases its metaspace chunks.
 106   // !! Note: this may invalidate the chunk. Do not access the chunk after
 107   //    this function returns !!
 108   void return_chunk(Metachunk* c);
 109 
 110   // Uncommit payload area of free chunks. Will be called during Metaspace GC.
 111   void uncommit_free_chunks();
 112 
 113   // Run verifications. slow=true: verify chunk-internal integrity too.
 114   DEBUG_ONLY(void verify(bool slow) const;)
 115   DEBUG_ONLY(void verify_locked(bool slow) const;)
 116 
 117   // Returns the name of this chunk manager.
 118   const char* name() const                  { return _name; }
 119 
 120   // Returns number of words in all free chunks.
 121   size_t total_word_size() const            { return _total_word_size.get(); }
 122 
 123   // Update statistics.
 124   void add_to_statistics(ChunkManagerStatistics* out) const;
 125 
 126 private:
 127 
 128   static ChunkManager* _chunkmanager_class;
 129   static ChunkManager* _chunkmanager_nonclass;
 130 
 131 public:
 132 
 133   static ChunkManager* chunkmanager_class() { return _chunkmanager_class; }
 134   static ChunkManager* chunkmanager_nonclass() { return _chunkmanager_nonclass; }
 135 
 136   static void set_chunkmanager_class(ChunkManager* cm);
 137   static void set_chunkmanager_nonclass(ChunkManager* cm);
 138 
 139 };
 140 
 141 } // namespace metaspace
 142 
 143 #endif // SHARE_MEMORY_METASPACE_CHUNKMANAGER_HPP