Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/gtest/metaspace/test_commitmask.cpp
41145 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
#include "precompiled.hpp"
27
#include "memory/metaspace/commitMask.hpp"
28
#include "memory/metaspace/metaspaceSettings.hpp"
29
#include "metaspaceGtestCommon.hpp"
30
#include "metaspaceGtestRangeHelpers.hpp"
31
#include "runtime/os.hpp"
32
#include "utilities/align.hpp"
33
#include "utilities/debug.hpp"
34
35
using metaspace::CommitMask;
36
using metaspace::Settings;
37
38
static int get_random(int limit) { return os::random() % limit; }
39
40
class CommitMaskTest {
41
const MetaWord* const _base;
42
const size_t _word_size;
43
44
CommitMask _mask;
45
46
void verify_mask() {
47
// Note: we omit the touch test since we operate on fictional
48
// memory
49
DEBUG_ONLY(_mask.verify();)
50
}
51
52
// Return a random sub range within [_base.._base + word_size),
53
// aligned to granule size
54
const MetaWord* calc_random_subrange(size_t* p_word_size) {
55
size_t l1 = get_random((int)_word_size);
56
size_t l2 = get_random((int)_word_size);
57
if (l1 > l2) {
58
size_t l = l1;
59
l1 = l2;
60
l2 = l;
61
}
62
l1 = align_down(l1, Settings::commit_granule_words());
63
l2 = align_up(l2, Settings::commit_granule_words());
64
65
const MetaWord* p = _base + l1;
66
const size_t len = l2 - l1;
67
68
assert(p >= _base && p + len <= _base + _word_size,
69
"Sanity");
70
*p_word_size = len;
71
72
return p;
73
}
74
75
void test1() {
76
77
LOG("test1");
78
79
// Commit everything
80
size_t prior_committed = _mask.mark_range_as_committed(_base, _word_size);
81
verify_mask();
82
ASSERT_LE(prior_committed, _word_size); // We do not really know
83
84
// Commit everything again, should be a noop
85
prior_committed = _mask.mark_range_as_committed(_base, _word_size);
86
verify_mask();
87
ASSERT_EQ(prior_committed, _word_size);
88
89
ASSERT_EQ(_mask.get_committed_size(),
90
_word_size);
91
ASSERT_EQ(_mask.get_committed_size_in_range(_base, _word_size),
92
_word_size);
93
94
for (const MetaWord* p = _base; p < _base + _word_size; p++) {
95
ASSERT_TRUE(_mask.is_committed_address(p));
96
}
97
98
// Now make an uncommitted hole
99
size_t sr_word_size;
100
const MetaWord* sr_base = calc_random_subrange(&sr_word_size);
101
LOG("subrange " PTR_FORMAT "-" PTR_FORMAT ".",
102
p2i(sr_base), p2i(sr_base + sr_word_size));
103
104
size_t prior_uncommitted =
105
_mask.mark_range_as_uncommitted(sr_base, sr_word_size);
106
verify_mask();
107
ASSERT_EQ(prior_uncommitted, (size_t)0);
108
109
// Again, for fun, should be a noop now.
110
prior_uncommitted = _mask.mark_range_as_uncommitted(sr_base, sr_word_size);
111
verify_mask();
112
ASSERT_EQ(prior_uncommitted, sr_word_size);
113
114
ASSERT_EQ(_mask.get_committed_size_in_range(sr_base, sr_word_size),
115
(size_t)0);
116
ASSERT_EQ(_mask.get_committed_size(),
117
_word_size - sr_word_size);
118
ASSERT_EQ(_mask.get_committed_size_in_range(_base, _word_size),
119
_word_size - sr_word_size);
120
for (const MetaWord* p = _base; p < _base + _word_size; p++) {
121
if (p >= sr_base && p < sr_base + sr_word_size) {
122
ASSERT_FALSE(_mask.is_committed_address(p));
123
} else {
124
ASSERT_TRUE(_mask.is_committed_address(p));
125
}
126
}
127
128
// Recommit whole range
129
prior_committed = _mask.mark_range_as_committed(_base, _word_size);
130
verify_mask();
131
ASSERT_EQ(prior_committed, _word_size - sr_word_size);
132
133
ASSERT_EQ(_mask.get_committed_size_in_range(sr_base, sr_word_size),
134
sr_word_size);
135
ASSERT_EQ(_mask.get_committed_size(),
136
_word_size);
137
ASSERT_EQ(_mask.get_committed_size_in_range(_base, _word_size),
138
_word_size);
139
for (const MetaWord* p = _base; p < _base + _word_size; p++) {
140
ASSERT_TRUE(_mask.is_committed_address(p));
141
}
142
143
}
144
145
void test2() {
146
147
LOG("test2");
148
149
// Uncommit everything
150
size_t prior_uncommitted = _mask.mark_range_as_uncommitted(_base, _word_size);
151
verify_mask();
152
ASSERT_LE(prior_uncommitted, _word_size);
153
154
// Uncommit everything again, should be a noop
155
prior_uncommitted = _mask.mark_range_as_uncommitted(_base, _word_size);
156
verify_mask();
157
ASSERT_EQ(prior_uncommitted, _word_size);
158
159
ASSERT_EQ(_mask.get_committed_size(),
160
(size_t)0);
161
ASSERT_EQ(_mask.get_committed_size_in_range(_base, _word_size),
162
(size_t)0);
163
164
// Now make an committed region
165
size_t sr_word_size;
166
const MetaWord* sr_base = calc_random_subrange(&sr_word_size);
167
LOG("subrange " PTR_FORMAT "-" PTR_FORMAT ".",
168
p2i(sr_base), p2i(sr_base + sr_word_size));
169
170
ASSERT_EQ(_mask.get_committed_size_in_range(sr_base, sr_word_size),
171
(size_t)0);
172
for (const MetaWord* p = _base; p < _base + _word_size; p++) {
173
ASSERT_FALSE(_mask.is_committed_address(p));
174
}
175
176
size_t prior_committed = _mask.mark_range_as_committed(sr_base, sr_word_size);
177
verify_mask();
178
ASSERT_EQ(prior_committed, (size_t)0);
179
180
// Again, for fun, should be a noop now.
181
prior_committed = _mask.mark_range_as_committed(sr_base, sr_word_size);
182
verify_mask();
183
ASSERT_EQ(prior_committed, sr_word_size);
184
185
ASSERT_EQ(_mask.get_committed_size_in_range(sr_base, sr_word_size),
186
sr_word_size);
187
ASSERT_EQ(_mask.get_committed_size(),
188
sr_word_size);
189
ASSERT_EQ(_mask.get_committed_size_in_range(_base, _word_size),
190
sr_word_size);
191
for (const MetaWord* p = _base; p < _base + _word_size; p++) {
192
if (p >= sr_base && p < sr_base + sr_word_size) {
193
ASSERT_TRUE(_mask.is_committed_address(p));
194
} else {
195
ASSERT_FALSE(_mask.is_committed_address(p));
196
}
197
}
198
199
// Re-uncommit whole range
200
prior_uncommitted = _mask.mark_range_as_uncommitted(_base, _word_size);
201
verify_mask();
202
ASSERT_EQ(prior_uncommitted, _word_size - sr_word_size);
203
204
EXPECT_EQ(_mask.get_committed_size_in_range(sr_base, sr_word_size),
205
(size_t)0);
206
EXPECT_EQ(_mask.get_committed_size(),
207
(size_t)0);
208
EXPECT_EQ(_mask.get_committed_size_in_range(_base, _word_size),
209
(size_t)0);
210
for (const MetaWord* p = _base; p < _base + _word_size; p++) {
211
ASSERT_FALSE(_mask.is_committed_address(p));
212
}
213
214
}
215
216
void test3() {
217
218
// arbitrary ranges are set and cleared and compared with the test map
219
TestMap map(_word_size);
220
221
_mask.clear_large();
222
223
for (int run = 0; run < 100; run++) {
224
225
// A random range
226
SizeRange r = SizeRange(_word_size).random_aligned_subrange(Settings::commit_granule_words());
227
228
if (os::random() % 100 < 50) {
229
_mask.mark_range_as_committed(_base + r.lowest(), r.size());
230
map.set_range(r.lowest(), r.end());
231
} else {
232
_mask.mark_range_as_uncommitted(_base + r.lowest(), r.size());
233
map.clear_range(r.lowest(), r.end());
234
}
235
236
ASSERT_EQ(_mask.get_committed_size(), (size_t)map.get_num_set());
237
238
ASSERT_EQ(_mask.get_committed_size_in_range(_base + r.lowest(), r.size()),
239
(size_t)map.get_num_set(r.lowest(), r.end()));
240
241
}
242
243
}
244
245
public:
246
247
CommitMaskTest(const MetaWord* base, size_t size) :
248
_base(base),
249
_word_size(size),
250
_mask(base, size)
251
{}
252
253
void test() {
254
LOG("mask range: " PTR_FORMAT "-" PTR_FORMAT
255
" (" SIZE_FORMAT " words).",
256
p2i(_base), p2i(_base + _word_size), _word_size);
257
for (int i = 0; i < 5; i++) {
258
test1(); test2(); test3();
259
}
260
}
261
262
};
263
264
TEST_VM(metaspace, commit_mask_basics) {
265
266
const MetaWord* const base = (const MetaWord*) 0x100000;
267
268
CommitMask mask1(base, Settings::commit_granule_words());
269
ASSERT_EQ(mask1.size(), (BitMap::idx_t)1);
270
271
CommitMask mask2(base, Settings::commit_granule_words() * 4);
272
ASSERT_EQ(mask2.size(), (BitMap::idx_t)4);
273
274
CommitMask mask3(base, Settings::commit_granule_words() * 43);
275
ASSERT_EQ(mask3.size(), (BitMap::idx_t)43);
276
277
mask3.mark_range_as_committed(base, Settings::commit_granule_words());
278
mask3.mark_range_as_committed(base + (Settings::commit_granule_words() * 42), Settings::commit_granule_words());
279
280
ASSERT_EQ(mask3.at(0), 1);
281
for (int i = 1; i < 42; i++) {
282
ASSERT_EQ(mask3.at(i), 0);
283
}
284
ASSERT_EQ(mask3.at(42), 1);
285
286
}
287
288
TEST_VM(metaspace, commit_mask_small) {
289
290
const MetaWord* const base = (const MetaWord*) 0x100000;
291
292
CommitMaskTest test(base, Settings::commit_granule_words());
293
test.test();
294
295
}
296
297
TEST_VM(metaspace, commit_mask_range) {
298
299
const MetaWord* const base = (const MetaWord*) 0x100000;
300
const size_t len = Settings::commit_granule_words() * 4;
301
const MetaWord* const end = base + len;
302
CommitMask mask(base, len);
303
304
LOG("total range: " PTR_FORMAT "-" PTR_FORMAT "\n", p2i(base), p2i(end));
305
306
size_t l = mask.mark_range_as_committed(base, len);
307
ASSERT_LE(l, len);
308
309
for (const MetaWord* p = base; p <= end - Settings::commit_granule_words();
310
p += Settings::commit_granule_words()) {
311
for (const MetaWord* p2 = p + Settings::commit_granule_words();
312
p2 <= end; p2 += Settings::commit_granule_words()) {
313
LOG(PTR_FORMAT "-" PTR_FORMAT "\n", p2i(p), p2i(p2));
314
EXPECT_EQ(mask.get_committed_size_in_range(p, p2 - p),
315
(size_t)(p2 - p));
316
}
317
}
318
319
l = mask.mark_range_as_uncommitted(base, len);
320
ASSERT_EQ(l, (size_t)0);
321
322
for (const MetaWord* p = base; p <= end - Settings::commit_granule_words();
323
p += Settings::commit_granule_words()) {
324
for (const MetaWord* p2 = p + Settings::commit_granule_words();
325
p2 <= end; p2 += Settings::commit_granule_words()) {
326
LOG(PTR_FORMAT "-" PTR_FORMAT "\n", p2i(p), p2i(p2));
327
EXPECT_EQ(mask.get_committed_size_in_range(p, p2 - p),
328
(size_t)(0));
329
}
330
}
331
332
}
333
334
TEST_VM(metaspace, commit_mask_random) {
335
336
for (int i = 0; i < 5; i++) {
337
338
// make up a range out of thin air
339
const MetaWord* const base =
340
align_down( (const MetaWord*) ((uintptr_t) os::random() * os::random()),
341
Settings::commit_granule_bytes());
342
const size_t len = align_up( 1 + (os::random() % M),
343
Settings::commit_granule_words());
344
345
CommitMaskTest test(base, len);
346
test.test();
347
348
}
349
350
}
351
352