1 /*
  2  * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
  3  * Copyright (c) 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_METASPACEARENA_HPP
 27 #define SHARE_MEMORY_METASPACE_METASPACEARENA_HPP
 28 
 29 #include "memory/allocation.hpp"
 30 #include "memory/metaspace.hpp"
 31 #include "memory/metaspace/counters.hpp"
 32 #include "memory/metaspace/metablock.hpp"
 33 #include "memory/metaspace/metachunkList.hpp"
 34 
 35 class outputStream;
 36 class Mutex;
 37 
 38 namespace metaspace {
 39 
 40 class ArenaGrowthPolicy;
 41 struct ArenaStats;
 42 class MetaspaceContext;
 43 class ChunkManager;
 44 class FreeBlocks;
 45 class Metachunk;
 46 
 47 
 48 // The MetaspaceArena is a growable metaspace memory pool belonging to a CLD;
 49 //  internally it consists of a list of metaspace chunks, of which the head chunk
 50 //  is the current chunk from which we allocate via pointer bump.
 51 //
 52 //  +---------------+
 53 //  |     Arena     |
 54 //  +---------------+
 55 //            |
 56 //            | _chunks                                               commit top
 57 //            |                                                       v
 58 //        +----------+      +----------+      +----------+      +----------+
 59 //        | retired  | ---> | retired  | ---> | retired  | ---> | current  |
 60 //        | chunk    |      | chunk    |      | chunk    |      | chunk    |
 61 //        +----------+      +----------+      +----------+      +----------+
 62 //                                                                  ^
 63 //                                                                  used top
 64 //
 65 //        +------------+
 66 //        | FreeBlocks | --> O -> O -> O -> O
 67 //        +------------+
 68 //
 69 //
 70 
 71 // When the current chunk is used up, MetaspaceArena requests a new chunk from
 72 //  the associated ChunkManager.
 73 //
 74 // MetaspaceArena also keeps a FreeBlocks structure to manage memory blocks which
 75 //  had been deallocated prematurely.
 76 //
 77 
 78 class MetaspaceArena : public CHeapObj<mtClass> {
 79   friend class MetaspaceArenaTestFriend;
 80 
 81   // Please note that access to a metaspace arena may be shared
 82   // between threads and needs to be synchronized in CLMS.
 83 
 84   const size_t _allocation_alignment_words;
 85 
 86   // Reference to the chunk manager to allocate chunks from.
 87   ChunkManager* const _chunk_manager;
 88 
 89   // Reference to the growth policy to use.
 90   const ArenaGrowthPolicy* const _growth_policy;
 91 
 92   // List of chunks. Head of the list is the current chunk.
 93   MetachunkList _chunks;
 94 
 95   // Structure to take care of leftover/deallocated space in used chunks.
 96   // Owned by the Arena. Gets allocated on demand only.
 97   FreeBlocks* _fbl;
 98 
 99   Metachunk* current_chunk()              { return _chunks.first(); }
100   const Metachunk* current_chunk() const  { return _chunks.first(); }
101 
102   // Reference to an outside counter to keep track of used space.
103   SizeAtomicCounter* const _total_used_words_counter;
104 
105   // A name for purely debugging/logging purposes.
106   const char* const _name;
107 
108 #ifdef ASSERT
109   // Allocation guards: When active, arena allocations are interleaved with
110   //  fence allocations. An overwritten fence indicates a buffer overrun in either
111   //  the preceding or the following user block. All fences are linked together;
112   //  validating the fences just means walking that linked list.
113   // Note that for the Arena, fence blocks are just another form of user blocks.
114   class Fence {
115     static const uintx EyeCatcher =
116       NOT_LP64(0x77698465) LP64_ONLY(0x7769846577698465ULL); // "META" resp "METAMETA"
117     // Two eyecatchers to easily spot a corrupted _next pointer
118     const uintx _eye1;
119     const Fence* const _next;
120     NOT_LP64(uintx _dummy;)
121     const uintx _eye2;
122   public:
123     Fence(const Fence* next) : _eye1(EyeCatcher), _next(next), _eye2(EyeCatcher) {}
124     const Fence* next() const { return _next; }
125     void verify() const;
126   };
127   const Fence* _first_fence;
128 #endif // ASSERT
129 
130   ChunkManager* chunk_manager() const           { return _chunk_manager; }
131 
132   // free block list
133   FreeBlocks* fbl() const                       { return _fbl; }
134   void add_allocation_to_fbl(MetaBlock bl);
135 
136   // Given a chunk, return the committed remainder of this chunk.
137   MetaBlock salvage_chunk(Metachunk* c);
138 
139   // Allocate a new chunk from the underlying chunk manager able to hold at least
140   // requested word size.
141   Metachunk* allocate_new_chunk(size_t requested_word_size);
142 
143   // Returns the level of the next chunk to be added, acc to growth policy.
144   chunklevel_t next_chunk_level() const;
145 
146   // Attempt to enlarge the current chunk to make it large enough to hold at least
147   //  requested_word_size additional words.
148   //
149   // On success, true is returned, false otherwise.
150   bool attempt_enlarge_current_chunk(size_t requested_word_size);
151 
152   // Allocate from the arena proper, once dictionary allocations and fencing are sorted out.
153   MetaBlock allocate_inner(size_t word_size, MetaBlock& wastage);
154 
155 public:
156 
157   MetaspaceArena(MetaspaceContext* context,
158                  const ArenaGrowthPolicy* growth_policy,
159                  size_t allocation_alignment_words,
160                  const char* name);
161 
162   ~MetaspaceArena();
163 
164   size_t allocation_alignment_words() const { return _allocation_alignment_words; }
165   size_t allocation_alignment_bytes() const { return allocation_alignment_words() * BytesPerWord; }
166 
167   // Allocate memory from Metaspace.
168   // On success, returns non-empty block of the specified word size, and
169   // possibly a wastage block that is the result of alignment operations.
170   // On failure, returns an empty block. Failure may happen if we hit a
171   // commit limit.
172   MetaBlock allocate(size_t word_size, MetaBlock& wastage);
173 
174   // Prematurely returns a metaspace allocation to the _block_freelists because it is not
175   // needed anymore.
176   void deallocate(MetaBlock bl);
177 
178   // Update statistics. This walks all in-use chunks.
179   void add_to_statistics(ArenaStats* out) const;
180 
181   // Convenience method to get the most important usage statistics.
182   // For deeper analysis use add_to_statistics().
183   void usage_numbers(size_t* p_used_words, size_t* p_committed_words, size_t* p_capacity_words) const;
184 
185   DEBUG_ONLY(void verify() const;)
186   DEBUG_ONLY(void verify_allocation_guards() const;)
187 
188   void print_on(outputStream* st) const;
189 
190   // Returns true if the given block is contained in this arena
191   DEBUG_ONLY(bool contains(MetaBlock bl) const;)
192 };
193 
194 } // namespace metaspace
195 
196 #endif // SHARE_MEMORY_METASPACE_METASPACEARENA_HPP
197