1 /*
2 * Copyright (c) 2012, 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 #ifndef SHARE_MEMORY_METASPACE_METACHUNK_HPP
25 #define SHARE_MEMORY_METASPACE_METACHUNK_HPP
26
27 #include "memory/metaspace/metabase.hpp"
28 #include "memory/metaspace/metaspaceCommon.hpp"
29 #include "utilities/debug.hpp"
30 #include "utilities/globalDefinitions.hpp"
31
32 class MetachunkTest;
33
34 namespace metaspace {
35
36 class VirtualSpaceNode;
37
38 // Metachunk - Quantum of allocation from a Virtualspace
39 // Metachunks are reused (when freed are put on a global freelist) and
40 // have no permanent association to a SpaceManager.
41
42 // +--------------+ <- end --+ --+
43 // | | | |
44 // | | | free |
45 // | | | |
46 // | | | | size | capacity
47 // | | | |
48 // | | <- top -- + |
49 // | | | |
50 // | | | used |
51 // | | | |
52 // | | | |
53 // +--------------+ <- bottom --+ --+
54
55 enum ChunkOrigin {
56 // Chunk normally born (via take_from_committed)
57 origin_normal = 1,
58 // Chunk was born as padding chunk
59 origin_pad = 2,
60 // Chunk was born as leftover chunk in VirtualSpaceNode::retire
61 origin_leftover = 3,
62 // Chunk was born as result of a merge of smaller chunks
63 origin_merge = 4,
64 // Chunk was born as result of a split of a larger chunk
65 origin_split = 5,
66
67 origin_minimum = origin_normal,
68 origin_maximum = origin_split,
69 origins_count = origin_maximum + 1
70 };
71
72 inline bool is_valid_chunkorigin(ChunkOrigin origin) {
73 return origin == origin_normal ||
74 origin == origin_pad ||
75 origin == origin_leftover ||
76 origin == origin_merge ||
77 origin == origin_split;
78 }
79
80 class Metachunk : public Metabase<Metachunk> {
81
82 friend class ::MetachunkTest;
83
84 // The VirtualSpaceNode containing this chunk.
85 VirtualSpaceNode* const _container;
86
87 // Current allocation top.
88 MetaWord* _top;
89
90 // A 32bit sentinel for debugging purposes.
91 enum { CHUNK_SENTINEL = 0x4d4554EF, // "MET"
92 CHUNK_SENTINEL_INVALID = 0xFEEEEEEF
93 };
94
95 uint32_t _sentinel;
96
97 const ChunkIndex _chunk_type;
98 const bool _is_class;
99 // Whether the chunk is free (in freelist) or in use by some class loader.
100 bool _is_tagged_free;
101
102 ChunkOrigin _origin;
103 int _use_count;
104
105 MetaWord* initial_top() const { return (MetaWord*)this + overhead(); }
106 MetaWord* top() const { return _top; }
107
108 public:
109 // Metachunks are allocated out of a MetadataVirtualSpace and
110 // and use some of its space to describe itself (plus alignment
111 // considerations). Metadata is allocated in the rest of the chunk.
112 // This size is the overhead of maintaining the Metachunk within
113 // the space.
114
115 // Alignment of each allocation in the chunks.
116 static size_t object_alignment();
117
118 // Size of the Metachunk header, in words, including alignment.
119 static size_t overhead();
120
121 Metachunk(ChunkIndex chunktype, bool is_class, size_t word_size, VirtualSpaceNode* container);
122
123 MetaWord* allocate(size_t word_size);
124
125 VirtualSpaceNode* container() const { return _container; }
126
127 MetaWord* bottom() const { return (MetaWord*) this; }
128
129 // Reset top to bottom so chunk can be reused.
130 void reset_empty() { _top = initial_top(); clear_next(); clear_prev(); }
131 bool is_empty() { return _top == initial_top(); }
132
133 // used (has been allocated)
134 // free (available for future allocations)
135 size_t word_size() const { return size(); }
136 size_t used_word_size() const;
137 size_t free_word_size() const;
138
139 bool is_tagged_free() { return _is_tagged_free; }
140 void set_is_tagged_free(bool v) { _is_tagged_free = v; }
141
142 bool contains(const void* ptr) { return bottom() <= ptr && ptr < _top; }
143
144 void print_on(outputStream* st) const;
145
146 bool is_valid_sentinel() const { return _sentinel == CHUNK_SENTINEL; }
147 void remove_sentinel() { _sentinel = CHUNK_SENTINEL_INVALID; }
148
149 int get_use_count() const { return _use_count; }
150 void inc_use_count() { _use_count ++; }
151
152 ChunkOrigin get_origin() const { return _origin; }
153 void set_origin(ChunkOrigin orig) { _origin = orig; }
154
155 ChunkIndex get_chunk_type() const { return _chunk_type; }
156 bool is_class() const { return _is_class; }
157
158 DEBUG_ONLY(void mangle(juint word_value);)
159 DEBUG_ONLY(void verify() const;)
160
161 };
162
163
164 // Helper function that does a bunch of checks for a chunk.
165 DEBUG_ONLY(void do_verify_chunk(Metachunk* chunk);)
166
167 // Given a Metachunk, update its in-use information (both in the
168 // chunk and the occupancy map).
169 void do_update_in_use_info_for_chunk(Metachunk* chunk, bool inuse);
170
171 } // namespace metaspace
172
173 #endif // SHARE_MEMORY_METASPACE_METACHUNK_HPP
|
1 /*
2 * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2017, 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_METACHUNK_HPP
27 #define SHARE_MEMORY_METASPACE_METACHUNK_HPP
28
29
30 #include "memory/metaspace/counter.hpp"
31 #include "memory/metaspace/chunkLevel.hpp"
32 #include "utilities/debug.hpp"
33 #include "utilities/globalDefinitions.hpp"
34
35
36 class outputStream;
37
38 namespace metaspace {
39
40 class VirtualSpaceNode;
41
42 // A Metachunk is a contiguous metaspace memory region. It is part of
43 // a MetaspaceArena, which keeps a list of MetaChunk and allocates via
44 // pointer bump from the top element in the list.
45 //
46 // The Metachunk object itself (the "chunk header") is separated from
47 // the memory region (the chunk payload) it describes. It also can have
48 // no payload (a "dead" chunk). In itself it lives in C-heap, managed
49 // as part of a pool of Metachunk headers (ChunkHeaderPool).
50 //
51 // -- Metachunk state --
52 //
53 // A Metachunk is "in-use" if it is part of a MetaspaceArena. That means
54 // its memory is used - or will be used shortly - to hold VM metadata
55 // on behalf of a class loader.
56 //
57 // A Metachunk is "free" if its payload is currently unused. In that
58 // case it is managed by a chunk freelist (the ChunkManager).
59 //
60 // A Metachunk is "dead" if it does not have a corresponding payload.
61 // In that case it lives as part of a freelist-of-dead-chunk-headers
62 // in the ChunkHeaderPool.
63 //
64 // -- Level --
65 //
66 // Metachunks are managed as part of a buddy style allocation scheme.
67 // Sized always in steps of power-of-2, ranging from the smallest chunk size
68 // (1Kb) to the largest (4Mb) (see chunklevel.hpp).
69 // Its size is encoded as level, with level 0 being the largest chunk
70 // size ("root chunk").
71 //
72 // -- Payload commit state --
73 //
74 // A Metachunk payload may be committed, partly committed or completely
75 // uncommitted. Technically, a payload may be committed "checkered" -
76 // i.e. committed and uncommitted parts may interleave - but the
77 // important part is how much contiguous space is committed starting
78 // at the base of the payload (since that's where we allocate).
79 //
80 // The Metachunk keeps track of how much space is committed starting
81 // at the base of the payload - which is a performace optimization -
82 // while underlying layers (VirtualSpaceNode->commitmask) keep track
83 // of the "real" commit state, aka which granules are committed,
84 // independent on what chunks reside above those granules.
85
86
87 // +--------------+ <- end -----------+ ----------+
88 // | | | |
89 // | | | |
90 // | | | |
91 // | | | |
92 // | | | |
93 // | ----------- | <- committed_top -- + |
94 // | | | |
95 // | | | "free" |
96 // | | | | size
97 // | | "free_below_ | |
98 // | | committed" | |
99 // | | | |
100 // | | | |
101 // | ----------- | <- top --------- + -------- |
102 // | | | |
103 // | | "used" | |
104 // | | | |
105 // +--------------+ <- start ----------+ ----------+
106
107 // Note: this is a chunk **descriptor**. The real Payload area lives in metaspace,
108 // this class lives somewhere else.
109 class Metachunk {
110
111 // start of chunk memory; NULL if dead.
112 MetaWord* _base;
113
114 // Used words.
115 size_t _used_words;
116
117 // Size of the region, starting from base, which is guaranteed to be committed. In words.
118 // The actual size of committed regions may actually be larger.
119 //
120 // (This is a performance optimization. The underlying VirtualSpaceNode knows
121 // which granules are committed; but we want to avoid having to ask.)
122 size_t _committed_words;
123
124 chunklevel_t _level; // aka size.
125
126 // state_free: free, owned by a ChunkManager
127 // state_in_use: in-use, owned by a MetaspaceArena
128 // dead: just a hollow chunk header without associated memory, owned
129 // by chunk header pool.
130 enum state_t {
131 state_free = 0,
132 state_in_use = 1,
133 state_dead = 2
134 };
135 state_t _state;
136
137 // We need unfortunately a back link to the virtual space node
138 // for splitting and merging nodes.
139 VirtualSpaceNode* _vsnode;
140
141
142 // A chunk header is kept in a list:
143 // 1 in the list of used chunks inside a MetaspaceArena, if it is in use
144 // 2 in the list of free chunks inside a ChunkManager, if it is free
145 // 3 in the freelist of unused headers inside the ChunkHeaderPool,
146 // if it is unused (e.g. result of chunk merging) and has no associated
147 // memory area.
148 Metachunk* _prev;
149 Metachunk* _next;
150
151 // Furthermore, we keep, per chunk, information about the neighboring chunks.
152 // This is needed to split and merge chunks.
153 //
154 // Note: These members can be modified concurrently while a chunk is alive and in use.
155 // This can happen if a neighboring chunk is added or removed.
156 // This means only read or modify these members under expand lock protection.
157 Metachunk* _prev_in_vs;
158 Metachunk* _next_in_vs;
159
160 // Commit uncommitted section of the chunk.
161 // Fails if we hit a commit limit.
162 bool commit_up_to(size_t new_committed_words);
163
164 DEBUG_ONLY(static void assert_have_expand_lock();)
165
166 public:
167
168 Metachunk()
169 : _base(NULL),
170 _used_words(0),
171 _committed_words(0),
172 _level(chunklevel::ROOT_CHUNK_LEVEL),
173 _state(state_free),
174 _vsnode(NULL),
175 _prev(NULL), _next(NULL),
176 _prev_in_vs(NULL), _next_in_vs(NULL)
177 {}
178
179 void clear() {
180 _base = NULL;
181 _used_words = 0;
182 _committed_words = 0;
183 _level = chunklevel::ROOT_CHUNK_LEVEL;
184 _state = state_free;
185 _vsnode = NULL;
186 _prev = NULL;
187 _next = NULL;
188 _prev_in_vs = NULL;
189 _next_in_vs = NULL;
190 }
191
192
193 size_t word_size() const { return chunklevel::word_size_for_level(_level); }
194
195 MetaWord* base() const { return _base; }
196 MetaWord* top() const { return base() + _used_words; }
197 MetaWord* committed_top() const { return base() + _committed_words; }
198 MetaWord* end() const { return base() + word_size(); }
199
200 // Chunk list wiring
201 void set_prev(Metachunk* c) { _prev = c; }
202 Metachunk* prev() const { return _prev; }
203 void set_next(Metachunk* c) { _next = c; }
204 Metachunk* next() const { return _next; }
205
206 DEBUG_ONLY(bool in_list() const { return _prev != NULL || _next != NULL; })
207
208 // Physical neighbors wiring
209 void set_prev_in_vs(Metachunk* c) { DEBUG_ONLY(assert_have_expand_lock()); _prev_in_vs = c; }
210 Metachunk* prev_in_vs() const { DEBUG_ONLY(assert_have_expand_lock()); return _prev_in_vs; }
211 void set_next_in_vs(Metachunk* c) { DEBUG_ONLY(assert_have_expand_lock()); _next_in_vs = c; }
212 Metachunk* next_in_vs() const { DEBUG_ONLY(assert_have_expand_lock()); return _next_in_vs; }
213
214 bool is_free() const { return _state == state_free; }
215 bool is_in_use() const { return _state == state_in_use; }
216 bool is_dead() const { return _state == state_dead; }
217 void set_free() { _state = state_free; }
218 void set_in_use() { _state = state_in_use; }
219 void set_dead() { _state = state_dead; }
220
221 // Return a single char presentation of the state ('f', 'u', 'd')
222 char get_state_char() const;
223
224 void inc_level() { _level ++; DEBUG_ONLY(chunklevel::is_valid_level(_level);) }
225 void dec_level() { _level --; DEBUG_ONLY(chunklevel::is_valid_level(_level);) }
226 chunklevel_t level() const { return _level; }
227
228 // Convenience functions for extreme levels.
229 bool is_root_chunk() const { return chunklevel::ROOT_CHUNK_LEVEL == _level; }
230 bool is_leaf_chunk() const { return chunklevel::HIGHEST_CHUNK_LEVEL == _level; }
231
232 VirtualSpaceNode* vsnode() const { return _vsnode; }
233
234 size_t used_words() const { return _used_words; }
235 size_t free_words() const { return word_size() - used_words(); }
236 size_t free_below_committed_words() const { return committed_words() - used_words(); }
237 void reset_used_words() { _used_words = 0; }
238
239 size_t committed_words() const { return _committed_words; }
240 void set_committed_words(size_t v);
241 bool is_fully_committed() const { return committed_words() == word_size(); }
242 bool is_fully_uncommitted() const { return committed_words() == 0; }
243
244 // Ensure that chunk is committed up to at least new_committed_words words.
245 // Fails if we hit a commit limit.
246 bool ensure_committed(size_t new_committed_words);
247 bool ensure_committed_locked(size_t new_committed_words);
248
249 bool ensure_fully_committed() { return ensure_committed(word_size()); }
250 bool ensure_fully_committed_locked() { return ensure_committed_locked(word_size()); }
251
252 // Ensure that the chunk is committed far enough to serve an additional allocation of word_size.
253 bool ensure_committed_additional(size_t additional_word_size) {
254 return ensure_committed(used_words() + additional_word_size);
255 }
256
257 // Uncommit chunk area. The area must be a common multiple of the
258 // commit granule size (in other words, we cannot uncommit chunks smaller than
259 // a commit granule size).
260 void uncommit();
261 void uncommit_locked();
262
263 // Allocation from a chunk
264
265 // Allocate word_size words from this chunk (word_size must be aligned to
266 // allocation_alignment_words).
267 //
268 // Caller must make sure the chunk is both large enough and committed far enough
269 // to hold the allocation. Will always work.
270 //
271 MetaWord* allocate(size_t request_word_size);
272
273 // Initialize structure for reuse.
274 void initialize(VirtualSpaceNode* node, MetaWord* base, chunklevel_t lvl) {
275 _vsnode = node; _base = base; _level = lvl;
276 _used_words = _committed_words = 0; _state = state_free;
277 _next = _prev = _next_in_vs = _prev_in_vs = NULL;
278 }
279
280 // Returns true if this chunk is the leader in its buddy pair, false if not.
281 // Do not call for root chunks.
282 bool is_leader() const {
283 assert(!is_root_chunk(), "Root chunks have no buddy."); // Bit harsh?
284 return is_aligned(base(), chunklevel::word_size_for_level(level() - 1) * BytesPerWord);
285 }
286
287 //// Debug stuff ////
288 #ifdef ASSERT
289 void verify(bool slow) const;
290 // Verifies linking with neighbors in virtual space. Needs expand lock protection.
291 void verify_neighborhood() const;
292 void zap_header(uint8_t c = 0x17);
293 void fill_with_pattern(MetaWord pattern, size_t word_size);
294 void check_pattern(MetaWord pattern, size_t word_size);
295
296 // Returns true if given pointer points into the payload area of this chunk.
297 bool is_valid_pointer(const MetaWord* p) const {
298 return base() <= p && p < top();
299 }
300
301 // Returns true if given pointer points into the commmitted payload area of this chunk.
302 bool is_valid_committed_pointer(const MetaWord* p) const {
303 return base() <= p && p < committed_top();
304 }
305
306 #endif // ASSERT
307
308 void print_on(outputStream* st) const;
309
310 };
311
312 // Little print helpers: since we often print out chunks, here some convenience macros
313 #define METACHUNK_FORMAT "@" PTR_FORMAT ", %c, base " PTR_FORMAT ", level " CHKLVL_FORMAT
314 #define METACHUNK_FORMAT_ARGS(chunk) p2i(chunk), chunk->get_state_char(), p2i(chunk->base()), chunk->level()
315
316 #define METACHUNK_FULL_FORMAT "@" PTR_FORMAT ", %c, base " PTR_FORMAT ", level " CHKLVL_FORMAT " (" SIZE_FORMAT "), used: " SIZE_FORMAT ", committed: " SIZE_FORMAT ", committed-free: " SIZE_FORMAT
317 #define METACHUNK_FULL_FORMAT_ARGS(chunk) p2i(chunk), chunk->get_state_char(), p2i(chunk->base()), chunk->level(), chunk->word_size(), chunk->used_words(), chunk->committed_words(), chunk->free_below_committed_words()
318
319 } // namespace metaspace
320
321 #endif // SHARE_MEMORY_METASPACE_METACHUNK_HPP
|