Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/memory/metaspace/binList.hpp
40957 views
1
/*
2
* Copyright (c) 2020, 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_BINLIST_HPP
27
#define SHARE_MEMORY_METASPACE_BINLIST_HPP
28
29
#include "memory/metaspace/counters.hpp"
30
#include "memory/metaspace/metaspaceCommon.hpp"
31
#include "utilities/align.hpp"
32
#include "utilities/debug.hpp"
33
#include "utilities/globalDefinitions.hpp"
34
35
namespace metaspace {
36
37
// BinList is a data structure to manage small to very small memory blocks
38
// (only a few words). It is used to manage deallocated blocks - see
39
// class FreeBlocks.
40
41
// Memory blocks are kept in linked lists. Each list
42
// contains blocks of only one size. There is a list for blocks of two words,
43
// for blocks of three words, etc. The list heads are kept in a vector,
44
// ordered by block size.
45
//
46
47
// wordsize
48
//
49
// +---+ +---+ +---+ +---+
50
// 1 | |-->| |-->| |-...->| |
51
// +---+ +---+ +---+ +---+
52
//
53
// +----+ +----+ +----+ +----+
54
// 2 | |-->| |-->| |-...->| |
55
// +----+ +----+ +----+ +----+
56
//
57
// +-----+ +-----+ +-----+ +-----+
58
// 3 | |-->| |-->| |-...->| |
59
// +-----+ +-----+ +-----+ +-----+
60
// .
61
// .
62
// .
63
//
64
// +----------+ +----------+ +----------+ +----------+
65
// n | |-->| |-->| |-...->| |
66
// +----------+ +----------+ +----------+ +----------+
67
68
// Insertion is of course fast, O(1).
69
//
70
// On retrieval, we attempt to find the closest fit to a given size, walking the
71
// list head vector (a bitmask is used to speed that part up).
72
//
73
// This structure is a bit expensive in memory costs (we pay one pointer per managed
74
// block size) so we only use it for a small number of sizes.
75
76
template <size_t smallest_word_size, int num_lists>
77
class BinListImpl {
78
79
struct Block {
80
Block* const _next;
81
const size_t _word_size;
82
Block(Block* next, size_t word_size) :
83
_next(next),
84
_word_size(word_size)
85
{}
86
};
87
88
#define BLOCK_FORMAT "Block @" PTR_FORMAT ": size: " SIZE_FORMAT ", next: " PTR_FORMAT
89
#define BLOCK_FORMAT_ARGS(b) p2i(b), (b)->_word_size, p2i((b)->_next)
90
91
// Smallest block size must be large enough to hold a Block structure.
92
STATIC_ASSERT(smallest_word_size * sizeof(MetaWord) >= sizeof(Block));
93
STATIC_ASSERT(num_lists > 0);
94
95
public:
96
97
// Minimal word size a block must have to be manageable by this structure.
98
const static size_t MinWordSize = smallest_word_size;
99
100
// Maximal (incl) word size a block can have to be manageable by this structure.
101
const static size_t MaxWordSize = MinWordSize + num_lists - 1;
102
103
private:
104
105
Block* _blocks[num_lists];
106
107
MemRangeCounter _counter;
108
109
static int index_for_word_size(size_t word_size) {
110
int index = (int)(word_size - MinWordSize);
111
assert(index >= 0 && index < num_lists, "Invalid index %d", index);
112
return index;
113
}
114
115
static size_t word_size_for_index(int index) {
116
assert(index >= 0 && index < num_lists, "Invalid index %d", index);
117
return MinWordSize + index;
118
}
119
120
// Search the range [index, _num_lists) for the smallest non-empty list. Returns -1 on fail.
121
int index_for_next_non_empty_list(int index) {
122
assert(index >= 0 && index < num_lists, "Invalid index %d", index);
123
int i2 = index;
124
while (i2 < num_lists && _blocks[i2] == NULL) {
125
i2 ++;
126
}
127
return i2 == num_lists ? -1 : i2;
128
}
129
130
public:
131
132
BinListImpl() {
133
for (int i = 0; i < num_lists; i++) {
134
_blocks[i] = NULL;
135
}
136
}
137
138
void add_block(MetaWord* p, size_t word_size) {
139
assert(word_size >= MinWordSize &&
140
word_size <= MaxWordSize, "bad block size");
141
const int index = index_for_word_size(word_size);
142
Block* old_head = _blocks[index];
143
Block* new_head = new(p)Block(old_head, word_size);
144
_blocks[index] = new_head;
145
_counter.add(word_size);
146
}
147
148
// Given a word_size, searches and returns a block of at least that size.
149
// Block may be larger. Real block size is returned in *p_real_word_size.
150
MetaWord* remove_block(size_t word_size, size_t* p_real_word_size) {
151
assert(word_size >= MinWordSize &&
152
word_size <= MaxWordSize, "bad block size " SIZE_FORMAT ".", word_size);
153
int index = index_for_word_size(word_size);
154
index = index_for_next_non_empty_list(index);
155
if (index != -1) {
156
Block* b = _blocks[index];
157
const size_t real_word_size = word_size_for_index(index);
158
assert(b != NULL, "Sanity");
159
assert(b->_word_size >= word_size &&
160
b->_word_size == real_word_size,
161
"bad block size in list[%d] (" BLOCK_FORMAT ")", index, BLOCK_FORMAT_ARGS(b));
162
_blocks[index] = b->_next;
163
_counter.sub(real_word_size);
164
*p_real_word_size = real_word_size;
165
return (MetaWord*)b;
166
} else {
167
*p_real_word_size = 0;
168
return NULL;
169
}
170
}
171
172
// Returns number of blocks in this structure
173
unsigned count() const { return _counter.count(); }
174
175
// Returns total size, in words, of all elements.
176
size_t total_size() const { return _counter.total_size(); }
177
178
bool is_empty() const { return count() == 0; }
179
180
#ifdef ASSERT
181
void verify() const {
182
MemRangeCounter local_counter;
183
for (int i = 0; i < num_lists; i++) {
184
const size_t s = MinWordSize + i;
185
int pos = 0;
186
for (Block* b = _blocks[i]; b != NULL; b = b->_next, pos++) {
187
assert(b->_word_size == s,
188
"bad block size in list[%d] at pos %d (" BLOCK_FORMAT ")",
189
i, pos, BLOCK_FORMAT_ARGS(b));
190
local_counter.add(s);
191
}
192
}
193
local_counter.check(_counter);
194
}
195
#endif // ASSERT
196
197
};
198
199
typedef BinListImpl<2, 32> BinList32;
200
201
} // namespace metaspace
202
203
#endif // SHARE_MEMORY_METASPACE_BINLIST_HPP
204
205