6995781: Native Memory Tracking (Phase 1)

7151532: DCmd for hotspot native memory tracking

Implementation of native memory tracking phase 1, which tracks VM native memory usage, and related DCmd

Reviewed-by: acorn, coleenp, fparain
This commit is contained in:
Zhengyu Gu 2012-06-28 17:03:16 -04:00
parent 8e42425c92
commit a39b17624a
315 changed files with 7245 additions and 1477 deletions

View file

@ -45,6 +45,7 @@
#include "runtime/os.hpp"
#include "runtime/stubRoutines.hpp"
#include "services/attachListener.hpp"
#include "services/memTracker.hpp"
#include "services/threadService.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/events.hpp"
@ -433,9 +434,9 @@ void* os::native_java_library() {
// --------------------- heap allocation utilities ---------------------
char *os::strdup(const char *str) {
char *os::strdup(const char *str, MEMFLAGS flags) {
size_t size = strlen(str);
char *dup_str = (char *)malloc(size + 1);
char *dup_str = (char *)malloc(size + 1, flags);
if (dup_str == NULL) return NULL;
strcpy(dup_str, str);
return dup_str;
@ -559,7 +560,7 @@ void verify_block(void* memblock) {
}
#endif
void* os::malloc(size_t size) {
void* os::malloc(size_t size, MEMFLAGS memflags, address caller) {
NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
@ -571,6 +572,7 @@ void* os::malloc(size_t size) {
NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap());
u_char* ptr = (u_char*)::malloc(size + space_before + space_after);
#ifdef ASSERT
if (ptr == NULL) return NULL;
if (MallocCushion) {
@ -589,18 +591,29 @@ void* os::malloc(size_t size) {
}
debug_only(if (paranoid) verify_block(memblock));
if (PrintMalloc && tty != NULL) tty->print_cr("os::malloc " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, memblock);
// we do not track MallocCushion memory
if (MemTracker::is_on()) {
MemTracker::record_malloc((address)memblock, size, memflags, caller == 0 ? CALLER_PC : caller);
}
return memblock;
}
void* os::realloc(void *memblock, size_t size) {
void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, address caller) {
#ifndef ASSERT
NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
return ::realloc(memblock, size);
void* ptr = ::realloc(memblock, size);
if (ptr != NULL && MemTracker::is_on()) {
MemTracker::record_realloc((address)memblock, (address)ptr, size, memflags,
caller == 0 ? CALLER_PC : caller);
}
return ptr;
#else
if (memblock == NULL) {
return malloc(size);
return malloc(size, memflags, (caller == 0 ? CALLER_PC : caller));
}
if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) {
tty->print_cr("os::realloc caught " PTR_FORMAT, memblock);
@ -610,7 +623,7 @@ void* os::realloc(void *memblock, size_t size) {
NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap());
if (size == 0) return NULL;
// always move the block
void* ptr = malloc(size);
void* ptr = malloc(size, memflags, caller == 0 ? CALLER_PC : caller);
if (PrintMalloc) tty->print_cr("os::remalloc " SIZE_FORMAT " bytes, " PTR_FORMAT " --> " PTR_FORMAT, size, memblock, ptr);
// Copy to new memory if malloc didn't fail
if ( ptr != NULL ) {
@ -627,7 +640,7 @@ void* os::realloc(void *memblock, size_t size) {
}
void os::free(void *memblock) {
void os::free(void *memblock, MEMFLAGS memflags) {
NOT_PRODUCT(inc_stat_counter(&num_frees, 1));
#ifdef ASSERT
if (memblock == NULL) return;
@ -660,6 +673,8 @@ void os::free(void *memblock) {
fprintf(stderr, "os::free " PTR_FORMAT "\n", (uintptr_t)memblock);
}
#endif
MemTracker::record_free((address)memblock, memflags);
::free((char*)memblock - space_before);
}
@ -1048,7 +1063,7 @@ char* os::format_boot_path(const char* format_string,
++formatted_path_len;
}
char* formatted_path = NEW_C_HEAP_ARRAY(char, formatted_path_len + 1);
char* formatted_path = NEW_C_HEAP_ARRAY(char, formatted_path_len + 1, mtInternal);
if (formatted_path == NULL) {
return NULL;
}
@ -1127,7 +1142,7 @@ char** os::split_path(const char* path, int* n) {
return NULL;
}
const char psepchar = *os::path_separator();
char* inpath = (char*)NEW_C_HEAP_ARRAY(char, strlen(path) + 1);
char* inpath = (char*)NEW_C_HEAP_ARRAY(char, strlen(path) + 1, mtInternal);
if (inpath == NULL) {
return NULL;
}
@ -1140,7 +1155,7 @@ char** os::split_path(const char* path, int* n) {
p++;
p = strchr(p, psepchar);
}
char** opath = (char**) NEW_C_HEAP_ARRAY(char*, count);
char** opath = (char**) NEW_C_HEAP_ARRAY(char*, count, mtInternal);
if (opath == NULL) {
return NULL;
}
@ -1153,7 +1168,7 @@ char** os::split_path(const char* path, int* n) {
return NULL;
}
// allocate the string and add terminator storage
char* s = (char*)NEW_C_HEAP_ARRAY(char, len + 1);
char* s = (char*)NEW_C_HEAP_ARRAY(char, len + 1, mtInternal);
if (s == NULL) {
return NULL;
}
@ -1162,7 +1177,7 @@ char** os::split_path(const char* path, int* n) {
opath[i] = s;
p += len + 1;
}
FREE_C_HEAP_ARRAY(char, inpath);
FREE_C_HEAP_ARRAY(char, inpath, mtInternal);
*n = count;
return opath;
}
@ -1366,3 +1381,97 @@ int os::get_line_chars(int fd, char* buf, const size_t bsize){
return (int) i;
}
bool os::create_stack_guard_pages(char* addr, size_t bytes) {
return os::pd_create_stack_guard_pages(addr, bytes);
}
char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint) {
char* result = pd_reserve_memory(bytes, addr, alignment_hint);
if (result != NULL && MemTracker::is_on()) {
MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC);
}
return result;
}
char* os::attempt_reserve_memory_at(size_t bytes, char* addr) {
char* result = pd_attempt_reserve_memory_at(bytes, addr);
if (result != NULL && MemTracker::is_on()) {
MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC);
}
return result;
}
void os::split_reserved_memory(char *base, size_t size,
size_t split, bool realloc) {
pd_split_reserved_memory(base, size, split, realloc);
}
bool os::commit_memory(char* addr, size_t bytes, bool executable) {
bool res = pd_commit_memory(addr, bytes, executable);
if (res && MemTracker::is_on()) {
MemTracker::record_virtual_memory_commit((address)addr, bytes, CALLER_PC);
}
return res;
}
bool os::commit_memory(char* addr, size_t size, size_t alignment_hint,
bool executable) {
bool res = os::pd_commit_memory(addr, size, alignment_hint, executable);
if (res && MemTracker::is_on()) {
MemTracker::record_virtual_memory_commit((address)addr, size, CALLER_PC);
}
return res;
}
bool os::uncommit_memory(char* addr, size_t bytes) {
bool res = pd_uncommit_memory(addr, bytes);
if (res) {
MemTracker::record_virtual_memory_uncommit((address)addr, bytes);
}
return res;
}
bool os::release_memory(char* addr, size_t bytes) {
bool res = pd_release_memory(addr, bytes);
if (res) {
MemTracker::record_virtual_memory_release((address)addr, bytes);
}
return res;
}
char* os::map_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
bool allow_exec) {
char* result = pd_map_memory(fd, file_name, file_offset, addr, bytes, read_only, allow_exec);
if (result != NULL && MemTracker::is_on()) {
MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC);
}
return result;
}
char* os::remap_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
bool allow_exec) {
return pd_remap_memory(fd, file_name, file_offset, addr, bytes,
read_only, allow_exec);
}
bool os::unmap_memory(char *addr, size_t bytes) {
bool result = pd_unmap_memory(addr, bytes);
if (result) {
MemTracker::record_virtual_memory_release((address)addr, bytes);
}
return result;
}
void os::free_memory(char *addr, size_t bytes, size_t alignment_hint) {
pd_free_memory(addr, bytes, alignment_hint);
}
void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) {
pd_realign_memory(addr, bytes, alignment_hint);
}