1 /* 2 * Copyright (c) 2018, 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 #include "precompiled.hpp" 25 26 // Included early because the NMT flags don't include it. 27 #include "utilities/macros.hpp" 28 29 #if INCLUDE_NMT 30 31 #include "services/memTracker.hpp" 32 #include "services/virtualMemoryTracker.hpp" 33 #include "utilities/globalDefinitions.hpp" 34 #include "unittest.hpp" 35 36 namespace { 37 struct R { 38 address _addr; 39 size_t _size; 40 }; 41 } 42 43 #define check(rmr, regions) check_inner((rmr), (regions), ARRAY_SIZE(regions), __FILE__, __LINE__) 44 45 #define check_empty(rmr) \ 46 do { \ 47 check_inner((rmr), NULL, 0, __FILE__, __LINE__); \ 48 } while (false) 49 50 static void check_inner(ReservedMemoryRegion* rmr, R* regions, size_t regions_size, const char* file, int line) { 51 CommittedRegionIterator iter = rmr->iterate_committed_regions(); 52 size_t i = 0; 53 size_t size = 0; 54 55 #define WHERE " from " << file << ":" << line 56 57 for (const CommittedMemoryRegion* region = iter.next(); region != NULL; region = iter.next()) { 58 EXPECT_LT(i, regions_size) << WHERE; 59 EXPECT_EQ(region->base(), regions[i]._addr) << WHERE; 60 EXPECT_EQ(region->size(), regions[i]._size) << WHERE; 61 size += region->size(); 62 i++; 63 } 64 65 EXPECT_EQ(i, regions_size) << WHERE; 66 EXPECT_EQ(size, rmr->committed_size()) << WHERE; 67 } 68 69 class VirtualMemoryTrackerTest { 70 public: 71 static void test_add_committed_region_adjacent() { 72 VirtualMemoryTracker::initialize(NMT_detail); 73 VirtualMemoryTracker::late_initialize(NMT_detail); 74 75 address addr = (address)0x10000000; 76 size_t size = 0x01000000; 77 78 address frame1 = (address)0x1234; 79 address frame2 = (address)0x1235; 80 81 NativeCallStack stack(&frame1, 1); 82 NativeCallStack stack2(&frame2, 1); 83 84 // Add the reserved memory 85 VirtualMemoryTracker::add_reserved_region(addr, size, stack, mtTest); 86 87 // Fetch the added RMR added above 88 ReservedMemoryRegion* rmr = VirtualMemoryTracker::_reserved_regions->find(ReservedMemoryRegion(addr, size)); 89 90 ASSERT_EQ(rmr->size(), size); 91 ASSERT_EQ(rmr->base(), addr); 92 93 // Commit Size Granularity 94 const size_t cs = 0x1000; 95 96 // Commit adjacent regions with same stack 97 98 { // Commit one region 99 rmr->add_committed_region(addr + cs, cs, stack); 100 R r[] = { {addr + cs, cs} }; 101 check(rmr, r); 102 } 103 104 { // Commit adjacent - lower address 105 rmr->add_committed_region(addr, cs, stack); 106 R r[] = { {addr, 2 * cs} }; 107 check(rmr, r); 108 } 109 110 { // Commit adjacent - higher address 111 rmr->add_committed_region(addr + 2 * cs, cs, stack); 112 R r[] = { {addr, 3 * cs} }; 113 check(rmr, r); 114 } 115 116 // Cleanup 117 rmr->remove_uncommitted_region(addr, 3 * cs); 118 ASSERT_EQ(rmr->committed_size(), 0u); 119 120 121 // Commit adjacent regions with different stacks 122 123 { // Commit one region 124 rmr->add_committed_region(addr + cs, cs, stack); 125 R r[] = { {addr + cs, cs} }; 126 check(rmr, r); 127 } 128 129 { // Commit adjacent - lower address 130 rmr->add_committed_region(addr, cs, stack2); 131 R r[] = { {addr, cs}, 132 {addr + cs, cs} }; 133 check(rmr, r); 134 } 135 136 { // Commit adjacent - higher address 137 rmr->add_committed_region(addr + 2 * cs, cs, stack2); 138 R r[] = { {addr, cs}, 139 {addr + cs, cs}, 140 {addr + 2 * cs, cs} }; 141 check(rmr, r); 142 } 143 144 // Cleanup 145 rmr->remove_uncommitted_region(addr, 3 * cs); 146 ASSERT_EQ(rmr->committed_size(), 0u); 147 } 148 149 static void test_add_committed_region_adjacent_overlapping() { 150 VirtualMemoryTracker::initialize(NMT_detail); 151 VirtualMemoryTracker::late_initialize(NMT_detail); 152 153 address addr = (address)0x10000000; 154 size_t size = 0x01000000; 155 156 address frame1 = (address)0x1234; 157 address frame2 = (address)0x1235; 158 159 NativeCallStack stack(&frame1, 1); 160 NativeCallStack stack2(&frame2, 1); 161 162 // Add the reserved memory 163 VirtualMemoryTracker::add_reserved_region(addr, size, stack, mtTest); 164 165 // Fetch the added RMR added above 166 ReservedMemoryRegion* rmr = VirtualMemoryTracker::_reserved_regions->find(ReservedMemoryRegion(addr, size)); 167 168 ASSERT_EQ(rmr->size(), size); 169 ASSERT_EQ(rmr->base(), addr); 170 171 // Commit Size Granularity 172 const size_t cs = 0x1000; 173 174 // Commit adjacent and overlapping regions with same stack 175 176 { // Commit two non-adjacent regions 177 rmr->add_committed_region(addr, 2 * cs, stack); 178 rmr->add_committed_region(addr + 3 * cs, 2 * cs, stack); 179 R r[] = { {addr, 2 * cs}, 180 {addr + 3 * cs, 2 * cs} }; 181 check(rmr, r); 182 } 183 184 { // Commit adjacent and overlapping 185 rmr->add_committed_region(addr + 2 * cs, 2 * cs, stack); 186 R r[] = { {addr, 5 * cs} }; 187 check(rmr, r); 188 } 189 190 // revert to two non-adjacent regions 191 rmr->remove_uncommitted_region(addr + 2 * cs, cs); 192 ASSERT_EQ(rmr->committed_size(), 4 * cs); 193 194 { // Commit overlapping and adjacent 195 rmr->add_committed_region(addr + cs, 2 * cs, stack); 196 R r[] = { {addr, 5 * cs} }; 197 check(rmr, r); 198 } 199 200 // Cleanup 201 rmr->remove_uncommitted_region(addr, 5 * cs); 202 ASSERT_EQ(rmr->committed_size(), 0u); 203 204 205 // Commit adjacent and overlapping regions with different stacks 206 207 { // Commit two non-adjacent regions 208 rmr->add_committed_region(addr, 2 * cs, stack); 209 rmr->add_committed_region(addr + 3 * cs, 2 * cs, stack); 210 R r[] = { {addr, 2 * cs}, 211 {addr + 3 * cs, 2 * cs} }; 212 check(rmr, r); 213 } 214 215 { // Commit adjacent and overlapping 216 rmr->add_committed_region(addr + 2 * cs, 2 * cs, stack2); 217 R r[] = { {addr, 2 * cs}, 218 {addr + 2 * cs, 2 * cs}, 219 {addr + 4 * cs, cs} }; 220 check(rmr, r); 221 } 222 223 // revert to two non-adjacent regions 224 rmr->add_committed_region(addr, 5 * cs, stack); 225 rmr->remove_uncommitted_region(addr + 2 * cs, cs); 226 ASSERT_EQ(rmr->committed_size(), 4 * cs); 227 228 { // Commit overlapping and adjacent 229 rmr->add_committed_region(addr + cs, 2 * cs, stack2); 230 R r[] = { {addr, cs}, 231 {addr + cs, 2 * cs}, 232 {addr + 3 * cs, 2 * cs} }; 233 check(rmr, r); 234 } 235 } 236 237 static void test_add_committed_region_overlapping() { 238 VirtualMemoryTracker::initialize(NMT_detail); 239 VirtualMemoryTracker::late_initialize(NMT_detail); 240 241 address addr = (address)0x10000000; 242 size_t size = 0x01000000; 243 244 address frame1 = (address)0x1234; 245 address frame2 = (address)0x1235; 246 247 NativeCallStack stack(&frame1, 1); 248 NativeCallStack stack2(&frame2, 1); 249 250 // Add the reserved memory 251 VirtualMemoryTracker::add_reserved_region(addr, size, stack, mtTest); 252 253 // Fetch the added RMR added above 254 ReservedMemoryRegion* rmr = VirtualMemoryTracker::_reserved_regions->find(ReservedMemoryRegion(addr, size)); 255 256 ASSERT_EQ(rmr->size(), size); 257 ASSERT_EQ(rmr->base(), addr); 258 259 // Commit Size Granularity 260 const size_t cs = 0x1000; 261 262 // With same stack 263 264 { // Commit one region 265 rmr->add_committed_region(addr, cs, stack); 266 R r[] = { {addr, cs} }; 267 check(rmr, r); 268 } 269 270 { // Commit the same region 271 rmr->add_committed_region(addr, cs, stack); 272 R r[] = { {addr, cs} }; 273 check(rmr, r); 274 } 275 276 { // Commit a succeeding region 277 rmr->add_committed_region(addr + cs, cs, stack); 278 R r[] = { {addr, 2 * cs} }; 279 check(rmr, r); 280 } 281 282 { // Commit over two regions 283 rmr->add_committed_region(addr, 2 * cs, stack); 284 R r[] = { {addr, 2 * cs} }; 285 check(rmr, r); 286 } 287 288 {// Commit first part of a region 289 rmr->add_committed_region(addr, cs, stack); 290 R r[] = { {addr, 2 * cs} }; 291 check(rmr, r); 292 } 293 294 { // Commit second part of a region 295 rmr->add_committed_region(addr + cs, cs, stack); 296 R r[] = { {addr, 2 * cs} }; 297 check(rmr, r); 298 } 299 300 { // Commit a third part 301 rmr->add_committed_region(addr + 2 * cs, cs, stack); 302 R r[] = { {addr, 3 * cs} }; 303 check(rmr, r); 304 } 305 306 { // Commit in the middle of a region 307 rmr->add_committed_region(addr + 1 * cs, cs, stack); 308 R r[] = { {addr, 3 * cs} }; 309 check(rmr, r); 310 } 311 312 // Cleanup 313 rmr->remove_uncommitted_region(addr, 3 * cs); 314 ASSERT_EQ(rmr->committed_size(), 0u); 315 316 // With preceding region 317 318 rmr->add_committed_region(addr, cs, stack); 319 rmr->add_committed_region(addr + 2 * cs, 3 * cs, stack); 320 321 rmr->add_committed_region(addr + 2 * cs, cs, stack); 322 { 323 R r[] = { {addr, cs}, 324 {addr + 2 * cs, 3 * cs} }; 325 check(rmr, r); 326 } 327 328 rmr->add_committed_region(addr + 3 * cs, cs, stack); 329 { 330 R r[] = { {addr, cs}, 331 {addr + 2 * cs, 3 * cs} }; 332 check(rmr, r); 333 } 334 335 rmr->add_committed_region(addr + 4 * cs, cs, stack); 336 { 337 R r[] = { {addr, cs}, 338 {addr + 2 * cs, 3 * cs} }; 339 check(rmr, r); 340 } 341 342 // Cleanup 343 rmr->remove_uncommitted_region(addr, 5 * cs); 344 ASSERT_EQ(rmr->committed_size(), 0u); 345 346 // With different stacks 347 348 { // Commit one region 349 rmr->add_committed_region(addr, cs, stack); 350 R r[] = { {addr, cs} }; 351 check(rmr, r); 352 } 353 354 { // Commit the same region 355 rmr->add_committed_region(addr, cs, stack2); 356 R r[] = { {addr, cs} }; 357 check(rmr, r); 358 } 359 360 { // Commit a succeeding region 361 rmr->add_committed_region(addr + cs, cs, stack); 362 R r[] = { {addr, cs}, 363 {addr + cs, cs} }; 364 check(rmr, r); 365 } 366 367 { // Commit over two regions 368 rmr->add_committed_region(addr, 2 * cs, stack); 369 R r[] = { {addr, 2 * cs} }; 370 check(rmr, r); 371 } 372 373 {// Commit first part of a region 374 rmr->add_committed_region(addr, cs, stack2); 375 R r[] = { {addr, cs}, 376 {addr + cs, cs} }; 377 check(rmr, r); 378 } 379 380 { // Commit second part of a region 381 rmr->add_committed_region(addr + cs, cs, stack2); 382 R r[] = { {addr, 2 * cs} }; 383 check(rmr, r); 384 } 385 386 { // Commit a third part 387 rmr->add_committed_region(addr + 2 * cs, cs, stack2); 388 R r[] = { {addr, 3 * cs} }; 389 check(rmr, r); 390 } 391 392 { // Commit in the middle of a region 393 rmr->add_committed_region(addr + 1 * cs, cs, stack); 394 R r[] = { {addr, cs}, 395 {addr + cs, cs}, 396 {addr + 2 * cs, cs} }; 397 check(rmr, r); 398 } 399 } 400 401 static void test_add_committed_region() { 402 test_add_committed_region_adjacent(); 403 test_add_committed_region_adjacent_overlapping(); 404 test_add_committed_region_overlapping(); 405 } 406 407 template <size_t S> 408 static void fix(R r[S]) { 409 410 } 411 412 static void test_remove_uncommitted_region() { 413 VirtualMemoryTracker::initialize(NMT_detail); 414 VirtualMemoryTracker::late_initialize(NMT_detail); 415 416 address addr = (address)0x10000000; 417 size_t size = 0x01000000; 418 419 address frame1 = (address)0x1234; 420 address frame2 = (address)0x1235; 421 422 NativeCallStack stack(&frame1, 1); 423 NativeCallStack stack2(&frame2, 1); 424 425 // Add the reserved memory 426 VirtualMemoryTracker::add_reserved_region(addr, size, stack, mtTest); 427 428 // Fetch the added RMR added above 429 ReservedMemoryRegion* rmr = VirtualMemoryTracker::_reserved_regions->find(ReservedMemoryRegion(addr, size)); 430 431 ASSERT_EQ(rmr->size(), size); 432 ASSERT_EQ(rmr->base(), addr); 433 434 // Commit Size Granularity 435 const size_t cs = 0x1000; 436 437 { // Commit regions 438 rmr->add_committed_region(addr, 3 * cs, stack); 439 R r[] = { {addr, 3 * cs} }; 440 check(rmr, r); 441 442 // Remove only existing 443 rmr->remove_uncommitted_region(addr, 3 * cs); 444 check_empty(rmr); 445 } 446 447 { 448 rmr->add_committed_region(addr + 0 * cs, cs, stack); 449 rmr->add_committed_region(addr + 2 * cs, cs, stack); 450 rmr->add_committed_region(addr + 4 * cs, cs, stack); 451 452 { // Remove first 453 rmr->remove_uncommitted_region(addr, cs); 454 R r[] = { {addr + 2 * cs, cs}, 455 {addr + 4 * cs, cs} }; 456 check(rmr, r); 457 } 458 459 // add back 460 rmr->add_committed_region(addr, cs, stack); 461 462 { // Remove middle 463 rmr->remove_uncommitted_region(addr + 2 * cs, cs); 464 R r[] = { {addr + 0 * cs, cs}, 465 {addr + 4 * cs, cs} }; 466 check(rmr, r); 467 } 468 469 // add back 470 rmr->add_committed_region(addr + 2 * cs, cs, stack); 471 472 { // Remove end 473 rmr->remove_uncommitted_region(addr + 4 * cs, cs); 474 R r[] = { {addr + 0 * cs, cs}, 475 {addr + 2 * cs, cs} }; 476 check(rmr, r); 477 } 478 479 rmr->remove_uncommitted_region(addr, 5 * cs); 480 check_empty(rmr); 481 } 482 483 { // Remove larger region 484 rmr->add_committed_region(addr + 1 * cs, cs, stack); 485 rmr->remove_uncommitted_region(addr, 3 * cs); 486 check_empty(rmr); 487 } 488 489 { // Remove smaller region - in the middle 490 rmr->add_committed_region(addr, 3 * cs, stack); 491 rmr->remove_uncommitted_region(addr + 1 * cs, cs); 492 R r[] = { { addr + 0 * cs, cs}, 493 { addr + 2 * cs, cs} }; 494 check(rmr, r); 495 496 rmr->remove_uncommitted_region(addr, 3 * cs); 497 check_empty(rmr); 498 } 499 500 { // Remove smaller region - at the beginning 501 rmr->add_committed_region(addr, 3 * cs, stack); 502 rmr->remove_uncommitted_region(addr + 0 * cs, cs); 503 R r[] = { { addr + 1 * cs, 2 * cs} }; 504 check(rmr, r); 505 506 rmr->remove_uncommitted_region(addr, 3 * cs); 507 check_empty(rmr); 508 } 509 510 { // Remove smaller region - at the end 511 rmr->add_committed_region(addr, 3 * cs, stack); 512 rmr->remove_uncommitted_region(addr + 2 * cs, cs); 513 R r[] = { { addr, 2 * cs} }; 514 check(rmr, r); 515 516 rmr->remove_uncommitted_region(addr, 3 * cs); 517 check_empty(rmr); 518 } 519 520 { // Remove smaller, overlapping region - at the beginning 521 rmr->add_committed_region(addr + 1 * cs, 4 * cs, stack); 522 rmr->remove_uncommitted_region(addr, 2 * cs); 523 R r[] = { { addr + 2 * cs, 3 * cs} }; 524 check(rmr, r); 525 526 rmr->remove_uncommitted_region(addr + 1 * cs, 4 * cs); 527 check_empty(rmr); 528 } 529 530 { // Remove smaller, overlapping region - at the end 531 rmr->add_committed_region(addr, 3 * cs, stack); 532 rmr->remove_uncommitted_region(addr + 2 * cs, 2 * cs); 533 R r[] = { { addr, 2 * cs} }; 534 check(rmr, r); 535 536 rmr->remove_uncommitted_region(addr, 3 * cs); 537 check_empty(rmr); 538 } 539 } 540 }; 541 542 TEST_VM(VirtualMemoryTracker, add_committed_region) { 543 VirtualMemoryTrackerTest::test_add_committed_region(); 544 } 545 546 TEST_VM(VirtualMemoryTracker, remove_uncommitted_region) { 547 VirtualMemoryTrackerTest::test_remove_uncommitted_region(); 548 } 549 550 #endif // INCLUDE_NMT