Mercurial > hg > truffle
comparison src/share/vm/runtime/os.cpp @ 20360:833b0f92429a
8046598: Scalable Native memory tracking development
Summary: Enhance scalability of native memory tracking
Reviewed-by: coleenp, ctornqvi, gtriantafill
author | zgu |
---|---|
date | Wed, 27 Aug 2014 08:19:12 -0400 |
parents | fa62fb12cdca |
children | ed3d653e4012 |
comparison
equal
deleted
inserted
replaced
20359:4d3a43351904 | 20360:833b0f92429a |
---|---|
47 #include "runtime/mutexLocker.hpp" | 47 #include "runtime/mutexLocker.hpp" |
48 #include "runtime/os.hpp" | 48 #include "runtime/os.hpp" |
49 #include "runtime/stubRoutines.hpp" | 49 #include "runtime/stubRoutines.hpp" |
50 #include "runtime/thread.inline.hpp" | 50 #include "runtime/thread.inline.hpp" |
51 #include "services/attachListener.hpp" | 51 #include "services/attachListener.hpp" |
52 #include "services/nmtCommon.hpp" | |
52 #include "services/memTracker.hpp" | 53 #include "services/memTracker.hpp" |
53 #include "services/threadService.hpp" | 54 #include "services/threadService.hpp" |
54 #include "utilities/defaultStream.hpp" | 55 #include "utilities/defaultStream.hpp" |
55 #include "utilities/events.hpp" | 56 #include "utilities/events.hpp" |
56 #ifdef TARGET_OS_FAMILY_linux | 57 #ifdef TARGET_OS_FAMILY_linux |
559 (volatile jint *) &cur_malloc_words); | 560 (volatile jint *) &cur_malloc_words); |
560 } | 561 } |
561 return ptr; | 562 return ptr; |
562 } | 563 } |
563 | 564 |
564 void* os::malloc(size_t size, MEMFLAGS memflags, address caller) { | 565 void* os::malloc(size_t size, MEMFLAGS flags) { |
566 return os::malloc(size, flags, CALLER_PC); | |
567 } | |
568 | |
569 void* os::malloc(size_t size, MEMFLAGS memflags, const NativeCallStack& stack) { | |
565 NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1)); | 570 NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1)); |
566 NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size)); | 571 NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size)); |
567 | 572 |
568 #ifdef ASSERT | 573 #ifdef ASSERT |
569 // checking for the WatcherThread and crash_protection first | 574 // checking for the WatcherThread and crash_protection first |
585 // return a valid pointer if size is zero | 590 // return a valid pointer if size is zero |
586 // if NULL is returned the calling functions assume out of memory. | 591 // if NULL is returned the calling functions assume out of memory. |
587 size = 1; | 592 size = 1; |
588 } | 593 } |
589 | 594 |
595 // NMT support | |
596 NMT_TrackingLevel level = MemTracker::tracking_level(); | |
597 size_t nmt_header_size = MemTracker::malloc_header_size(level); | |
598 | |
590 #ifndef ASSERT | 599 #ifndef ASSERT |
591 const size_t alloc_size = size; | 600 const size_t alloc_size = size + nmt_header_size; |
592 #else | 601 #else |
593 const size_t alloc_size = GuardedMemory::get_total_size(size); | 602 const size_t alloc_size = GuardedMemory::get_total_size(size + nmt_header_size); |
594 if (size > alloc_size) { // Check for rollover. | 603 if (size + nmt_header_size > alloc_size) { // Check for rollover. |
595 return NULL; | 604 return NULL; |
596 } | 605 } |
597 #endif | 606 #endif |
598 | 607 |
599 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); | 608 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); |
608 #ifdef ASSERT | 617 #ifdef ASSERT |
609 if (ptr == NULL) { | 618 if (ptr == NULL) { |
610 return NULL; | 619 return NULL; |
611 } | 620 } |
612 // Wrap memory with guard | 621 // Wrap memory with guard |
613 GuardedMemory guarded(ptr, size); | 622 GuardedMemory guarded(ptr, size + nmt_header_size); |
614 ptr = guarded.get_user_ptr(); | 623 ptr = guarded.get_user_ptr(); |
615 #endif | 624 #endif |
616 if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) { | 625 if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) { |
617 tty->print_cr("os::malloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr); | 626 tty->print_cr("os::malloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr); |
618 breakpoint(); | 627 breakpoint(); |
621 if (PrintMalloc && tty != NULL) { | 630 if (PrintMalloc && tty != NULL) { |
622 tty->print_cr("os::malloc " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr); | 631 tty->print_cr("os::malloc " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr); |
623 } | 632 } |
624 | 633 |
625 // we do not track guard memory | 634 // we do not track guard memory |
626 MemTracker::record_malloc((address)ptr, size, memflags, caller == 0 ? CALLER_PC : caller); | 635 return MemTracker::record_malloc((address)ptr, size, memflags, stack, level); |
627 | 636 } |
628 return ptr; | 637 |
629 } | 638 void* os::realloc(void *memblock, size_t size, MEMFLAGS flags) { |
630 | 639 return os::realloc(memblock, size, flags, CALLER_PC); |
631 | 640 } |
632 void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, address caller) { | 641 |
642 void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCallStack& stack) { | |
633 #ifndef ASSERT | 643 #ifndef ASSERT |
634 NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1)); | 644 NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1)); |
635 NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size)); | 645 NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size)); |
636 MemTracker::Tracker tkr = MemTracker::get_realloc_tracker(); | 646 // NMT support |
637 void* ptr = ::realloc(memblock, size); | 647 void* membase = MemTracker::record_free(memblock); |
638 if (ptr != NULL) { | 648 NMT_TrackingLevel level = MemTracker::tracking_level(); |
639 tkr.record((address)memblock, (address)ptr, size, memflags, | 649 size_t nmt_header_size = MemTracker::malloc_header_size(level); |
640 caller == 0 ? CALLER_PC : caller); | 650 void* ptr = ::realloc(membase, size + nmt_header_size); |
641 } else { | 651 return MemTracker::record_malloc(ptr, size, memflags, stack, level); |
642 tkr.discard(); | |
643 } | |
644 return ptr; | |
645 #else | 652 #else |
646 if (memblock == NULL) { | 653 if (memblock == NULL) { |
647 return os::malloc(size, memflags, (caller == 0 ? CALLER_PC : caller)); | 654 return os::malloc(size, memflags, stack); |
648 } | 655 } |
649 if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { | 656 if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { |
650 tty->print_cr("os::realloc caught " PTR_FORMAT, memblock); | 657 tty->print_cr("os::realloc caught " PTR_FORMAT, memblock); |
651 breakpoint(); | 658 breakpoint(); |
652 } | 659 } |
653 verify_memory(memblock); | 660 // NMT support |
661 void* membase = MemTracker::malloc_base(memblock); | |
662 verify_memory(membase); | |
654 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); | 663 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); |
655 if (size == 0) { | 664 if (size == 0) { |
656 return NULL; | 665 return NULL; |
657 } | 666 } |
658 // always move the block | 667 // always move the block |
659 void* ptr = os::malloc(size, memflags, caller == 0 ? CALLER_PC : caller); | 668 void* ptr = os::malloc(size, memflags, stack); |
660 if (PrintMalloc) { | 669 if (PrintMalloc) { |
661 tty->print_cr("os::remalloc " SIZE_FORMAT " bytes, " PTR_FORMAT " --> " PTR_FORMAT, size, memblock, ptr); | 670 tty->print_cr("os::remalloc " SIZE_FORMAT " bytes, " PTR_FORMAT " --> " PTR_FORMAT, size, memblock, ptr); |
662 } | 671 } |
663 // Copy to new memory if malloc didn't fail | 672 // Copy to new memory if malloc didn't fail |
664 if ( ptr != NULL ) { | 673 if ( ptr != NULL ) { |
665 GuardedMemory guarded(memblock); | 674 GuardedMemory guarded(MemTracker::malloc_base(memblock)); |
666 memcpy(ptr, memblock, MIN2(size, guarded.get_user_size())); | 675 // Guard's user data contains NMT header |
667 if (paranoid) verify_memory(ptr); | 676 size_t memblock_size = guarded.get_user_size() - MemTracker::malloc_header_size(memblock); |
677 memcpy(ptr, memblock, MIN2(size, memblock_size)); | |
678 if (paranoid) verify_memory(MemTracker::malloc_base(ptr)); | |
668 if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) { | 679 if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) { |
669 tty->print_cr("os::realloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr); | 680 tty->print_cr("os::realloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr); |
670 breakpoint(); | 681 breakpoint(); |
671 } | 682 } |
672 os::free(memblock); | 683 os::free(memblock); |
675 #endif | 686 #endif |
676 } | 687 } |
677 | 688 |
678 | 689 |
679 void os::free(void *memblock, MEMFLAGS memflags) { | 690 void os::free(void *memblock, MEMFLAGS memflags) { |
680 address trackp = (address) memblock; | |
681 NOT_PRODUCT(inc_stat_counter(&num_frees, 1)); | 691 NOT_PRODUCT(inc_stat_counter(&num_frees, 1)); |
682 #ifdef ASSERT | 692 #ifdef ASSERT |
683 if (memblock == NULL) return; | 693 if (memblock == NULL) return; |
684 if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { | 694 if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { |
685 if (tty != NULL) tty->print_cr("os::free caught " PTR_FORMAT, memblock); | 695 if (tty != NULL) tty->print_cr("os::free caught " PTR_FORMAT, memblock); |
686 breakpoint(); | 696 breakpoint(); |
687 } | 697 } |
688 verify_memory(memblock); | 698 void* membase = MemTracker::record_free(memblock); |
699 verify_memory(membase); | |
689 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); | 700 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); |
690 | 701 |
691 GuardedMemory guarded(memblock); | 702 GuardedMemory guarded(membase); |
692 size_t size = guarded.get_user_size(); | 703 size_t size = guarded.get_user_size(); |
693 inc_stat_counter(&free_bytes, size); | 704 inc_stat_counter(&free_bytes, size); |
694 memblock = guarded.release_for_freeing(); | 705 membase = guarded.release_for_freeing(); |
695 if (PrintMalloc && tty != NULL) { | 706 if (PrintMalloc && tty != NULL) { |
696 fprintf(stderr, "os::free " SIZE_FORMAT " bytes --> " PTR_FORMAT "\n", size, (uintptr_t)memblock); | 707 fprintf(stderr, "os::free " SIZE_FORMAT " bytes --> " PTR_FORMAT "\n", size, (uintptr_t)membase); |
697 } | 708 } |
698 #endif | 709 ::free(membase); |
699 MemTracker::record_free(trackp, memflags); | 710 #else |
700 | 711 void* membase = MemTracker::record_free(memblock); |
701 ::free(memblock); | 712 ::free(membase); |
713 #endif | |
702 } | 714 } |
703 | 715 |
704 void os::init_random(long initval) { | 716 void os::init_random(long initval) { |
705 _rand_seed = initval; | 717 _rand_seed = initval; |
706 } | 718 } |
1410 } | 1422 } |
1411 | 1423 |
1412 char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint) { | 1424 char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint) { |
1413 char* result = pd_reserve_memory(bytes, addr, alignment_hint); | 1425 char* result = pd_reserve_memory(bytes, addr, alignment_hint); |
1414 if (result != NULL) { | 1426 if (result != NULL) { |
1415 MemTracker::record_virtual_memory_reserve((address)result, bytes, mtNone, CALLER_PC); | 1427 MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC); |
1416 } | 1428 } |
1417 | 1429 |
1418 return result; | 1430 return result; |
1419 } | 1431 } |
1420 | 1432 |
1421 char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint, | 1433 char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint, |
1422 MEMFLAGS flags) { | 1434 MEMFLAGS flags) { |
1423 char* result = pd_reserve_memory(bytes, addr, alignment_hint); | 1435 char* result = pd_reserve_memory(bytes, addr, alignment_hint); |
1424 if (result != NULL) { | 1436 if (result != NULL) { |
1425 MemTracker::record_virtual_memory_reserve((address)result, bytes, mtNone, CALLER_PC); | 1437 MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC); |
1426 MemTracker::record_virtual_memory_type((address)result, flags); | 1438 MemTracker::record_virtual_memory_type((address)result, flags); |
1427 } | 1439 } |
1428 | 1440 |
1429 return result; | 1441 return result; |
1430 } | 1442 } |
1431 | 1443 |
1432 char* os::attempt_reserve_memory_at(size_t bytes, char* addr) { | 1444 char* os::attempt_reserve_memory_at(size_t bytes, char* addr) { |
1433 char* result = pd_attempt_reserve_memory_at(bytes, addr); | 1445 char* result = pd_attempt_reserve_memory_at(bytes, addr); |
1434 if (result != NULL) { | 1446 if (result != NULL) { |
1435 MemTracker::record_virtual_memory_reserve((address)result, bytes, mtNone, CALLER_PC); | 1447 MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC); |
1436 } | 1448 } |
1437 return result; | 1449 return result; |
1438 } | 1450 } |
1439 | 1451 |
1440 void os::split_reserved_memory(char *base, size_t size, | 1452 void os::split_reserved_memory(char *base, size_t size, |
1470 os::pd_commit_memory_or_exit(addr, size, alignment_hint, executable, mesg); | 1482 os::pd_commit_memory_or_exit(addr, size, alignment_hint, executable, mesg); |
1471 MemTracker::record_virtual_memory_commit((address)addr, size, CALLER_PC); | 1483 MemTracker::record_virtual_memory_commit((address)addr, size, CALLER_PC); |
1472 } | 1484 } |
1473 | 1485 |
1474 bool os::uncommit_memory(char* addr, size_t bytes) { | 1486 bool os::uncommit_memory(char* addr, size_t bytes) { |
1475 MemTracker::Tracker tkr = MemTracker::get_virtual_memory_uncommit_tracker(); | 1487 bool res; |
1476 bool res = pd_uncommit_memory(addr, bytes); | 1488 if (MemTracker::tracking_level() > NMT_minimal) { |
1477 if (res) { | 1489 Tracker tkr = MemTracker::get_virtual_memory_uncommit_tracker(); |
1478 tkr.record((address)addr, bytes); | 1490 res = pd_uncommit_memory(addr, bytes); |
1491 if (res) { | |
1492 tkr.record((address)addr, bytes); | |
1493 } | |
1479 } else { | 1494 } else { |
1480 tkr.discard(); | 1495 res = pd_uncommit_memory(addr, bytes); |
1481 } | 1496 } |
1482 return res; | 1497 return res; |
1483 } | 1498 } |
1484 | 1499 |
1485 bool os::release_memory(char* addr, size_t bytes) { | 1500 bool os::release_memory(char* addr, size_t bytes) { |
1486 MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker(); | 1501 bool res; |
1487 bool res = pd_release_memory(addr, bytes); | 1502 if (MemTracker::tracking_level() > NMT_minimal) { |
1488 if (res) { | 1503 Tracker tkr = MemTracker::get_virtual_memory_release_tracker(); |
1489 tkr.record((address)addr, bytes); | 1504 res = pd_release_memory(addr, bytes); |
1505 if (res) { | |
1506 tkr.record((address)addr, bytes); | |
1507 } | |
1490 } else { | 1508 } else { |
1491 tkr.discard(); | 1509 res = pd_release_memory(addr, bytes); |
1492 } | 1510 } |
1493 return res; | 1511 return res; |
1494 } | 1512 } |
1495 | 1513 |
1496 | 1514 |
1497 char* os::map_memory(int fd, const char* file_name, size_t file_offset, | 1515 char* os::map_memory(int fd, const char* file_name, size_t file_offset, |
1498 char *addr, size_t bytes, bool read_only, | 1516 char *addr, size_t bytes, bool read_only, |
1499 bool allow_exec) { | 1517 bool allow_exec) { |
1500 char* result = pd_map_memory(fd, file_name, file_offset, addr, bytes, read_only, allow_exec); | 1518 char* result = pd_map_memory(fd, file_name, file_offset, addr, bytes, read_only, allow_exec); |
1501 if (result != NULL) { | 1519 if (result != NULL) { |
1502 MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, mtNone, CALLER_PC); | 1520 MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, CALLER_PC); |
1503 } | 1521 } |
1504 return result; | 1522 return result; |
1505 } | 1523 } |
1506 | 1524 |
1507 char* os::remap_memory(int fd, const char* file_name, size_t file_offset, | 1525 char* os::remap_memory(int fd, const char* file_name, size_t file_offset, |
1510 return pd_remap_memory(fd, file_name, file_offset, addr, bytes, | 1528 return pd_remap_memory(fd, file_name, file_offset, addr, bytes, |
1511 read_only, allow_exec); | 1529 read_only, allow_exec); |
1512 } | 1530 } |
1513 | 1531 |
1514 bool os::unmap_memory(char *addr, size_t bytes) { | 1532 bool os::unmap_memory(char *addr, size_t bytes) { |
1515 MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker(); | 1533 bool result; |
1516 bool result = pd_unmap_memory(addr, bytes); | 1534 if (MemTracker::tracking_level() > NMT_minimal) { |
1517 if (result) { | 1535 Tracker tkr = MemTracker::get_virtual_memory_release_tracker(); |
1518 tkr.record((address)addr, bytes); | 1536 result = pd_unmap_memory(addr, bytes); |
1537 if (result) { | |
1538 tkr.record((address)addr, bytes); | |
1539 } | |
1519 } else { | 1540 } else { |
1520 tkr.discard(); | 1541 result = pd_unmap_memory(addr, bytes); |
1521 } | 1542 } |
1522 return result; | 1543 return result; |
1523 } | 1544 } |
1524 | 1545 |
1525 void os::free_memory(char *addr, size_t bytes, size_t alignment_hint) { | 1546 void os::free_memory(char *addr, size_t bytes, size_t alignment_hint) { |