jdk

Форк
0
/
test_virtualMemoryTracker.cpp 
565 строк · 16.1 Кб
1
/*
2
 * Copyright (c) 2018, 2024, 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
// Tests here test the VM-global NMT facility.
25
//  The tests must *not* modify global state! E.g. switch NMT on or off. Instead, they
26
//  should work passively with whatever setting the gtestlauncher had been started with
27
//  - if NMT is enabled, test NMT, otherwise do whatever minimal tests make sense if NMT
28
//  is off.
29
//
30
// The gtestLauncher then are called with various levels of -XX:NativeMemoryTracking during
31
//  jtreg-controlled gtests (see test/hotspot/jtreg/gtest/NMTGtests.java)
32

33
#include "precompiled.hpp"
34

35
#include "memory/virtualspace.hpp"
36
#include "nmt/memTracker.hpp"
37
#include "nmt/virtualMemoryTracker.hpp"
38
#include "utilities/globalDefinitions.hpp"
39
#include "utilities/macros.hpp"
40
#include "unittest.hpp"
41

42
#include <stdio.h>
43

44
// #define LOG(...) printf(__VA_ARGS__); printf("\n"); fflush(stdout);
45
#define LOG(...)
46

47
namespace {
48
  struct R {
49
    address _addr;
50
    size_t  _size;
51
  };
52
}
53

54
#define check(rmr, regions) check_inner((rmr), (regions), ARRAY_SIZE(regions), __FILE__, __LINE__)
55

56
#define check_empty(rmr)                              \
57
  do {                                                \
58
    check_inner((rmr), nullptr, 0, __FILE__, __LINE__);  \
59
  } while (false)
60

61
static void diagnostic_print(ReservedMemoryRegion* rmr) {
62
  CommittedRegionIterator iter = rmr->iterate_committed_regions();
63
  LOG("In reserved region " PTR_FORMAT ", size " SIZE_FORMAT_HEX ":", p2i(rmr->base()), rmr->size());
64
  for (const CommittedMemoryRegion* region = iter.next(); region != nullptr; region = iter.next()) {
65
    LOG("   committed region: " PTR_FORMAT ", size " SIZE_FORMAT_HEX, p2i(region->base()), region->size());
66
  }
67
}
68

69
static void check_inner(ReservedMemoryRegion* rmr, R* regions, size_t regions_size, const char* file, int line) {
70
  CommittedRegionIterator iter = rmr->iterate_committed_regions();
71
  size_t i = 0;
72
  size_t size = 0;
73

74
  // Helpful log
75
  diagnostic_print(rmr);
76

77
#define WHERE " from " << file << ":" << line
78

79
  for (const CommittedMemoryRegion* region = iter.next(); region != nullptr; region = iter.next()) {
80
    EXPECT_LT(i, regions_size) << WHERE;
81
    EXPECT_EQ(region->base(), regions[i]._addr) << WHERE;
82
    EXPECT_EQ(region->size(), regions[i]._size) << WHERE;
83
    size += region->size();
84
    i++;
85
  }
86

87
  EXPECT_EQ(i, regions_size) << WHERE;
88
  EXPECT_EQ(size, rmr->committed_size()) << WHERE;
89
}
90

91
class VirtualMemoryTrackerTest {
92
public:
93
  static void test_add_committed_region_adjacent() {
94

95
    size_t size  = 0x01000000;
96
    ReservedSpace rs(size);
97
    address addr = (address)rs.base();
98

99
    address frame1 = (address)0x1234;
100
    address frame2 = (address)0x1235;
101

102
    NativeCallStack stack(&frame1, 1);
103
    NativeCallStack stack2(&frame2, 1);
104

105
    // Fetch the added RMR for the space
106
    ReservedMemoryRegion* rmr = VirtualMemoryTracker::_reserved_regions->find(ReservedMemoryRegion(addr, size));
107

108
    ASSERT_EQ(rmr->size(), size);
109
    ASSERT_EQ(rmr->base(), addr);
110

111
    // Commit Size Granularity
112
    const size_t cs = 0x1000;
113

114
    // Commit adjacent regions with same stack
115

116
    { // Commit one region
117
      rmr->add_committed_region(addr + cs, cs, stack);
118
      R r[] = { {addr + cs, cs} };
119
      check(rmr, r);
120
    }
121

122
    { // Commit adjacent - lower address
123
      rmr->add_committed_region(addr, cs, stack);
124
      R r[] = { {addr, 2 * cs} };
125
      check(rmr, r);
126
    }
127

128
    { // Commit adjacent - higher address
129
      rmr->add_committed_region(addr + 2 * cs, cs, stack);
130
      R r[] = { {addr, 3 * cs} };
131
      check(rmr, r);
132
    }
133

134
    // Cleanup
135
    rmr->remove_uncommitted_region(addr, 3 * cs);
136
    ASSERT_EQ(rmr->committed_size(), 0u);
137

138

139
    // Commit adjacent regions with different stacks
140

141
    { // Commit one region
142
      rmr->add_committed_region(addr + cs, cs, stack);
143
      R r[] = { {addr + cs, cs} };
144
      check(rmr, r);
145
    }
146

147
    { // Commit adjacent - lower address
148
      rmr->add_committed_region(addr, cs, stack2);
149
      R r[] = { {addr,      cs},
150
                {addr + cs, cs} };
151
      check(rmr, r);
152
    }
153

154
    { // Commit adjacent - higher address
155
      rmr->add_committed_region(addr + 2 * cs, cs, stack2);
156
      R r[] = { {addr,          cs},
157
                {addr +     cs, cs},
158
                {addr + 2 * cs, cs} };
159
      check(rmr, r);
160
    }
161

162
    // Cleanup
163
    rmr->remove_uncommitted_region(addr, 3 * cs);
164
    ASSERT_EQ(rmr->committed_size(), 0u);
165
  }
166

167
  static void test_add_committed_region_adjacent_overlapping() {
168

169
    size_t size  = 0x01000000;
170
    ReservedSpace rs(size);
171
    address addr = (address)rs.base();
172

173
    address frame1 = (address)0x1234;
174
    address frame2 = (address)0x1235;
175

176
    NativeCallStack stack(&frame1, 1);
177
    NativeCallStack stack2(&frame2, 1);
178

179
    // Add the reserved memory
180
    VirtualMemoryTracker::add_reserved_region(addr, size, stack, mtTest);
181

182
    // Fetch the added RMR for the space
183
    ReservedMemoryRegion* rmr = VirtualMemoryTracker::_reserved_regions->find(ReservedMemoryRegion(addr, size));
184

185
    ASSERT_EQ(rmr->size(), size);
186
    ASSERT_EQ(rmr->base(), addr);
187

188
    // Commit Size Granularity
189
    const size_t cs = 0x1000;
190

191
    // Commit adjacent and overlapping regions with same stack
192

193
    { // Commit two non-adjacent regions
194
      rmr->add_committed_region(addr, 2 * cs, stack);
195
      rmr->add_committed_region(addr + 3 * cs, 2 * cs, stack);
196
      R r[] = { {addr,          2 * cs},
197
                {addr + 3 * cs, 2 * cs} };
198
      check(rmr, r);
199
    }
200

201
    { // Commit adjacent and overlapping
202
      rmr->add_committed_region(addr + 2 * cs, 2 * cs, stack);
203
      R r[] = { {addr, 5 * cs} };
204
      check(rmr, r);
205
    }
206

207
    // revert to two non-adjacent regions
208
    rmr->remove_uncommitted_region(addr + 2 * cs, cs);
209
    ASSERT_EQ(rmr->committed_size(), 4 * cs);
210

211
    { // Commit overlapping and adjacent
212
      rmr->add_committed_region(addr + cs, 2 * cs, stack);
213
      R r[] = { {addr, 5 * cs} };
214
      check(rmr, r);
215
    }
216

217
    // Cleanup
218
    rmr->remove_uncommitted_region(addr, 5 * cs);
219
    ASSERT_EQ(rmr->committed_size(), 0u);
220

221

222
    // Commit adjacent and overlapping regions with different stacks
223

224
    { // Commit two non-adjacent regions
225
      rmr->add_committed_region(addr, 2 * cs, stack);
226
      rmr->add_committed_region(addr + 3 * cs, 2 * cs, stack);
227
      R r[] = { {addr,          2 * cs},
228
                {addr + 3 * cs, 2 * cs} };
229
      check(rmr, r);
230
    }
231

232
    { // Commit adjacent and overlapping
233
      rmr->add_committed_region(addr + 2 * cs, 2 * cs, stack2);
234
      R r[] = { {addr,          2 * cs},
235
                {addr + 2 * cs, 2 * cs},
236
                {addr + 4 * cs,     cs} };
237
      check(rmr, r);
238
    }
239

240
    // revert to two non-adjacent regions
241
    rmr->add_committed_region(addr, 5 * cs, stack);
242
    rmr->remove_uncommitted_region(addr + 2 * cs, cs);
243
    ASSERT_EQ(rmr->committed_size(), 4 * cs);
244

245
    { // Commit overlapping and adjacent
246
      rmr->add_committed_region(addr + cs, 2 * cs, stack2);
247
      R r[] = { {addr,              cs},
248
                {addr +     cs, 2 * cs},
249
                {addr + 3 * cs, 2 * cs} };
250
      check(rmr, r);
251
    }
252
  }
253

254
  static void test_add_committed_region_overlapping() {
255

256
    size_t size  = 0x01000000;
257
    ReservedSpace rs(size);
258
    address addr = (address)rs.base();
259

260
    address frame1 = (address)0x1234;
261
    address frame2 = (address)0x1235;
262

263
    NativeCallStack stack(&frame1, 1);
264
    NativeCallStack stack2(&frame2, 1);
265

266
    // Fetch the added RMR for the space
267
    ReservedMemoryRegion* rmr = VirtualMemoryTracker::_reserved_regions->find(ReservedMemoryRegion(addr, size));
268

269
    ASSERT_EQ(rmr->size(), size);
270
    ASSERT_EQ(rmr->base(), addr);
271

272
    // Commit Size Granularity
273
    const size_t cs = 0x1000;
274

275
    // With same stack
276

277
    { // Commit one region
278
      rmr->add_committed_region(addr, cs, stack);
279
      R r[] = { {addr, cs} };
280
      check(rmr, r);
281
    }
282

283
    { // Commit the same region
284
      rmr->add_committed_region(addr, cs, stack);
285
      R r[] = { {addr, cs} };
286
      check(rmr, r);
287
    }
288

289
    { // Commit a succeeding region
290
      rmr->add_committed_region(addr + cs, cs, stack);
291
      R r[] = { {addr, 2 * cs} };
292
      check(rmr, r);
293
    }
294

295
    { // Commit  over two regions
296
      rmr->add_committed_region(addr, 2 * cs, stack);
297
      R r[] = { {addr, 2 * cs} };
298
      check(rmr, r);
299
    }
300

301
    {// Commit first part of a region
302
      rmr->add_committed_region(addr, cs, stack);
303
      R r[] = { {addr, 2 * cs} };
304
      check(rmr, r);
305
    }
306

307
    { // Commit second part of a region
308
      rmr->add_committed_region(addr + cs, cs, stack);
309
      R r[] = { {addr, 2 * cs} };
310
      check(rmr, r);
311
    }
312

313
    { // Commit a third part
314
      rmr->add_committed_region(addr + 2 * cs, cs, stack);
315
      R r[] = { {addr, 3 * cs} };
316
      check(rmr, r);
317
    }
318

319
    { // Commit in the middle of a region
320
      rmr->add_committed_region(addr + 1 * cs, cs, stack);
321
      R r[] = { {addr, 3 * cs} };
322
      check(rmr, r);
323
    }
324

325
    // Cleanup
326
    rmr->remove_uncommitted_region(addr, 3 * cs);
327
    ASSERT_EQ(rmr->committed_size(), 0u);
328

329
    // With preceding region
330

331
    rmr->add_committed_region(addr,              cs, stack);
332
    rmr->add_committed_region(addr + 2 * cs, 3 * cs, stack);
333

334
    rmr->add_committed_region(addr + 2 * cs,     cs, stack);
335
    {
336
      R r[] = { {addr,              cs},
337
                {addr + 2 * cs, 3 * cs} };
338
      check(rmr, r);
339
    }
340

341
    rmr->add_committed_region(addr + 3 * cs,     cs, stack);
342
    {
343
      R r[] = { {addr,              cs},
344
                {addr + 2 * cs, 3 * cs} };
345
      check(rmr, r);
346
    }
347

348
    rmr->add_committed_region(addr + 4 * cs,     cs, stack);
349
    {
350
      R r[] = { {addr,              cs},
351
                {addr + 2 * cs, 3 * cs} };
352
      check(rmr, r);
353
    }
354

355
    // Cleanup
356
    rmr->remove_uncommitted_region(addr, 5 * cs);
357
    ASSERT_EQ(rmr->committed_size(), 0u);
358

359
    // With different stacks
360

361
    { // Commit one region
362
      rmr->add_committed_region(addr, cs, stack);
363
      R r[] = { {addr, cs} };
364
      check(rmr, r);
365
    }
366

367
    { // Commit the same region
368
      rmr->add_committed_region(addr, cs, stack2);
369
      R r[] = { {addr, cs} };
370
      check(rmr, r);
371
    }
372

373
    { // Commit a succeeding region
374
      rmr->add_committed_region(addr + cs, cs, stack);
375
      R r[] = { {addr,      cs},
376
                {addr + cs, cs} };
377
      check(rmr, r);
378
    }
379

380
    { // Commit  over two regions
381
      rmr->add_committed_region(addr, 2 * cs, stack);
382
      R r[] = { {addr, 2 * cs} };
383
      check(rmr, r);
384
    }
385

386
    {// Commit first part of a region
387
      rmr->add_committed_region(addr, cs, stack2);
388
      R r[] = { {addr,      cs},
389
                {addr + cs, cs} };
390
      check(rmr, r);
391
    }
392

393
    { // Commit second part of a region
394
      rmr->add_committed_region(addr + cs, cs, stack2);
395
      R r[] = { {addr, 2 * cs} };
396
      check(rmr, r);
397
    }
398

399
    { // Commit a third part
400
      rmr->add_committed_region(addr + 2 * cs, cs, stack2);
401
      R r[] = { {addr, 3 * cs} };
402
      check(rmr, r);
403
    }
404

405
    { // Commit in the middle of a region
406
      rmr->add_committed_region(addr + 1 * cs, cs, stack);
407
      R r[] = { {addr,          cs},
408
                {addr +     cs, cs},
409
                {addr + 2 * cs, cs} };
410
      check(rmr, r);
411
    }
412
  }
413

414
  static void test_add_committed_region() {
415
    test_add_committed_region_adjacent();
416
    test_add_committed_region_adjacent_overlapping();
417
    test_add_committed_region_overlapping();
418
  }
419

420
  template <size_t S>
421
  static void fix(R r[S]) {
422

423
  }
424

425
  static void test_remove_uncommitted_region() {
426

427
    size_t size  = 0x01000000;
428
    ReservedSpace rs(size);
429
    address addr = (address)rs.base();
430

431
    address frame1 = (address)0x1234;
432
    address frame2 = (address)0x1235;
433

434
    NativeCallStack stack(&frame1, 1);
435
    NativeCallStack stack2(&frame2, 1);
436

437
    // Fetch the added RMR for the space
438
    ReservedMemoryRegion* rmr = VirtualMemoryTracker::_reserved_regions->find(ReservedMemoryRegion(addr, size));
439

440
    ASSERT_EQ(rmr->size(), size);
441
    ASSERT_EQ(rmr->base(), addr);
442

443
    // Commit Size Granularity
444
    const size_t cs = 0x1000;
445

446
    { // Commit regions
447
      rmr->add_committed_region(addr, 3 * cs, stack);
448
      R r[] = { {addr, 3 * cs} };
449
      check(rmr, r);
450

451
      // Remove only existing
452
      rmr->remove_uncommitted_region(addr, 3 * cs);
453
      check_empty(rmr);
454
    }
455

456
    {
457
      rmr->add_committed_region(addr + 0 * cs, cs, stack);
458
      rmr->add_committed_region(addr + 2 * cs, cs, stack);
459
      rmr->add_committed_region(addr + 4 * cs, cs, stack);
460

461
      { // Remove first
462
        rmr->remove_uncommitted_region(addr, cs);
463
        R r[] = { {addr + 2 * cs, cs},
464
                  {addr + 4 * cs, cs} };
465
        check(rmr, r);
466
      }
467

468
      // add back
469
      rmr->add_committed_region(addr,          cs, stack);
470

471
      { // Remove middle
472
        rmr->remove_uncommitted_region(addr + 2 * cs, cs);
473
        R r[] = { {addr + 0 * cs, cs},
474
                  {addr + 4 * cs, cs} };
475
        check(rmr, r);
476
      }
477

478
      // add back
479
      rmr->add_committed_region(addr + 2 * cs, cs, stack);
480

481
      { // Remove end
482
        rmr->remove_uncommitted_region(addr + 4 * cs, cs);
483
        R r[] = { {addr + 0 * cs, cs},
484
                  {addr + 2 * cs, cs} };
485
        check(rmr, r);
486
      }
487

488
      rmr->remove_uncommitted_region(addr, 5 * cs);
489
      check_empty(rmr);
490
    }
491

492
    { // Remove larger region
493
      rmr->add_committed_region(addr + 1 * cs, cs, stack);
494
      rmr->remove_uncommitted_region(addr, 3 * cs);
495
      check_empty(rmr);
496
    }
497

498
    { // Remove smaller region - in the middle
499
      rmr->add_committed_region(addr, 3 * cs, stack);
500
      rmr->remove_uncommitted_region(addr + 1 * cs, cs);
501
      R r[] = { { addr + 0 * cs, cs},
502
                { addr + 2 * cs, cs} };
503
      check(rmr, r);
504

505
      rmr->remove_uncommitted_region(addr, 3 * cs);
506
      check_empty(rmr);
507
    }
508

509
    { // Remove smaller region - at the beginning
510
      rmr->add_committed_region(addr, 3 * cs, stack);
511
      rmr->remove_uncommitted_region(addr + 0 * cs, cs);
512
      R r[] = { { addr + 1 * cs, 2 * cs} };
513
      check(rmr, r);
514

515
      rmr->remove_uncommitted_region(addr, 3 * cs);
516
      check_empty(rmr);
517
    }
518

519
    { // Remove smaller region - at the end
520
      rmr->add_committed_region(addr, 3 * cs, stack);
521
      rmr->remove_uncommitted_region(addr + 2 * cs, cs);
522
      R r[] = { { addr, 2 * cs} };
523
      check(rmr, r);
524

525
      rmr->remove_uncommitted_region(addr, 3 * cs);
526
      check_empty(rmr);
527
    }
528

529
    { // Remove smaller, overlapping region - at the beginning
530
      rmr->add_committed_region(addr + 1 * cs, 4 * cs, stack);
531
      rmr->remove_uncommitted_region(addr, 2 * cs);
532
      R r[] = { { addr + 2 * cs, 3 * cs} };
533
      check(rmr, r);
534

535
      rmr->remove_uncommitted_region(addr + 1 * cs, 4 * cs);
536
      check_empty(rmr);
537
    }
538

539
    { // Remove smaller, overlapping region - at the end
540
      rmr->add_committed_region(addr, 3 * cs, stack);
541
      rmr->remove_uncommitted_region(addr + 2 * cs, 2 * cs);
542
      R r[] = { { addr, 2 * cs} };
543
      check(rmr, r);
544

545
      rmr->remove_uncommitted_region(addr, 3 * cs);
546
      check_empty(rmr);
547
    }
548
  }
549
};
550

551
TEST_VM(NMT_VirtualMemoryTracker, add_committed_region) {
552
  if (MemTracker::tracking_level() >= NMT_detail) {
553
    VirtualMemoryTrackerTest::test_add_committed_region();
554
  } else {
555
    tty->print_cr("skipped.");
556
  }
557
}
558

559
TEST_VM(NMT_VirtualMemoryTracker, remove_uncommitted_region) {
560
  if (MemTracker::tracking_level() >= NMT_detail) {
561
    VirtualMemoryTrackerTest::test_remove_uncommitted_region();
562
  } else {
563
    tty->print_cr("skipped.");
564
  }
565
}
566

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.