提交 84e2c844 编写于 作者: K kvn

7017124: Fix some VM stats to avoid 32-bit overflow

Summary: Added new method inc_stat_counter() to increment long statistic values and use atomic long load and store.
Reviewed-by: dholmes, jrose, phh, never
上级 1b653533
......@@ -67,7 +67,6 @@ extern "C" void _Atomic_move_long_v9(volatile jlong* src, volatile jlong* dst);
inline void Atomic_move_long(volatile jlong* src, volatile jlong* dst) {
#ifdef COMPILER2
// Compiler2 does not support v8, it is used only for v9.
assert (VM_Version::v9_instructions_work(), "only supported on v9");
_Atomic_move_long_v9(src, dst);
#else
// The branch is cheaper then emulated LDD.
......
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -157,7 +157,7 @@ ResourceObj::~ResourceObj() {
void trace_heap_malloc(size_t size, const char* name, void* p) {
// A lock is not needed here - tty uses a lock internally
tty->print_cr("Heap malloc " INTPTR_FORMAT " %7d %s", p, size, name == NULL ? "" : name);
tty->print_cr("Heap malloc " INTPTR_FORMAT " " SIZE_FORMAT " %s", p, size, name == NULL ? "" : name);
}
......@@ -573,22 +573,27 @@ void AllocatedObj::print_value_on(outputStream* st) const {
st->print("AllocatedObj(" INTPTR_FORMAT ")", this);
}
size_t Arena::_bytes_allocated = 0;
julong Arena::_bytes_allocated = 0;
void Arena::inc_bytes_allocated(size_t x) { inc_stat_counter(&_bytes_allocated, x); }
AllocStats::AllocStats() {
start_mallocs = os::num_mallocs;
start_frees = os::num_frees;
start_malloc_bytes = os::alloc_bytes;
start_mfree_bytes = os::free_bytes;
start_res_bytes = Arena::_bytes_allocated;
}
int AllocStats::num_mallocs() { return os::num_mallocs - start_mallocs; }
size_t AllocStats::alloc_bytes() { return os::alloc_bytes - start_malloc_bytes; }
size_t AllocStats::resource_bytes() { return Arena::_bytes_allocated - start_res_bytes; }
int AllocStats::num_frees() { return os::num_frees - start_frees; }
julong AllocStats::num_mallocs() { return os::num_mallocs - start_mallocs; }
julong AllocStats::alloc_bytes() { return os::alloc_bytes - start_malloc_bytes; }
julong AllocStats::num_frees() { return os::num_frees - start_frees; }
julong AllocStats::free_bytes() { return os::free_bytes - start_mfree_bytes; }
julong AllocStats::resource_bytes() { return Arena::_bytes_allocated - start_res_bytes; }
void AllocStats::print() {
tty->print("%d mallocs (%ldK), %d frees, %ldK resrc",
num_mallocs(), alloc_bytes()/K, num_frees(), resource_bytes()/K);
tty->print_cr(UINT64_FORMAT " mallocs (" UINT64_FORMAT "MB), "
UINT64_FORMAT" frees (" UINT64_FORMAT "MB), " UINT64_FORMAT "MB resrc",
num_mallocs(), alloc_bytes()/M, num_frees(), free_bytes()/M, resource_bytes()/M);
}
......
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -202,10 +202,11 @@ protected:
char *_hwm, *_max; // High water mark and max in current chunk
void* grow(size_t x); // Get a new Chunk of at least size x
NOT_PRODUCT(size_t _size_in_bytes;) // Size of arena (used for memory usage tracing)
NOT_PRODUCT(static size_t _bytes_allocated;) // total #bytes allocated since start
NOT_PRODUCT(static julong _bytes_allocated;) // total #bytes allocated since start
friend class AllocStats;
debug_only(void* malloc(size_t size);)
debug_only(void* internal_malloc_4(size_t x);)
NOT_PRODUCT(void inc_bytes_allocated(size_t x);)
public:
Arena();
Arena(size_t init_size);
......@@ -219,7 +220,7 @@ protected:
assert(is_power_of_2(ARENA_AMALLOC_ALIGNMENT) , "should be a power of 2");
x = ARENA_ALIGN(x);
debug_only(if (UseMallocOnly) return malloc(x);)
NOT_PRODUCT(_bytes_allocated += x);
NOT_PRODUCT(inc_bytes_allocated(x);)
if (_hwm + x > _max) {
return grow(x);
} else {
......@@ -232,7 +233,7 @@ protected:
void *Amalloc_4(size_t x) {
assert( (x&(sizeof(char*)-1)) == 0, "misaligned size" );
debug_only(if (UseMallocOnly) return malloc(x);)
NOT_PRODUCT(_bytes_allocated += x);
NOT_PRODUCT(inc_bytes_allocated(x);)
if (_hwm + x > _max) {
return grow(x);
} else {
......@@ -252,7 +253,7 @@ protected:
size_t delta = (((size_t)_hwm + DALIGN_M1) & ~DALIGN_M1) - (size_t)_hwm;
x += delta;
#endif
NOT_PRODUCT(_bytes_allocated += x);
NOT_PRODUCT(inc_bytes_allocated(x);)
if (_hwm + x > _max) {
return grow(x); // grow() returns a result aligned >= 8 bytes.
} else {
......@@ -406,15 +407,16 @@ extern bool warn_new_operator;
// for statistics
#ifndef PRODUCT
class AllocStats : StackObj {
int start_mallocs, start_frees;
size_t start_malloc_bytes, start_res_bytes;
julong start_mallocs, start_frees;
julong start_malloc_bytes, start_mfree_bytes, start_res_bytes;
public:
AllocStats();
int num_mallocs(); // since creation of receiver
size_t alloc_bytes();
size_t resource_bytes();
int num_frees();
julong num_mallocs(); // since creation of receiver
julong alloc_bytes();
julong num_frees();
julong free_bytes();
julong resource_bytes();
void print();
};
#endif
......
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -32,6 +32,12 @@
void trace_heap_malloc(size_t size, const char* name, void *p);
void trace_heap_free(void *p);
// Increments unsigned long value for statistics (not atomic on MP).
inline void inc_stat_counter(volatile julong* dest, julong add_value) {
julong value = Atomic::load((volatile jlong*)dest);
value += add_value;
Atomic::store((jlong)value, (volatile jlong*)dest);
}
// allocate using malloc; will fail if no memory available
inline char* AllocateHeap(size_t size, const char* name = NULL) {
......
/*
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -39,12 +39,12 @@ IndexSet::BitBlock IndexSet::_empty_block = IndexSet::BitBlock();
#ifdef ASSERT
// Initialize statistics counters
uint IndexSet::_alloc_new = 0;
uint IndexSet::_alloc_total = 0;
julong IndexSet::_alloc_new = 0;
julong IndexSet::_alloc_total = 0;
long IndexSet::_total_bits = 0;
long IndexSet::_total_used_blocks = 0;
long IndexSet::_total_unused_blocks = 0;
julong IndexSet::_total_bits = 0;
julong IndexSet::_total_used_blocks = 0;
julong IndexSet::_total_unused_blocks = 0;
// Per set, or all sets operation tracing
int IndexSet::_serial_count = 1;
......@@ -141,7 +141,7 @@ void IndexSet::populate_free_list() {
#ifdef ASSERT
if (CollectIndexSetStatistics) {
_alloc_new += bitblock_alloc_chunk_size;
inc_stat_counter(&_alloc_new, bitblock_alloc_chunk_size);
}
#endif
}
......@@ -154,7 +154,7 @@ void IndexSet::populate_free_list() {
IndexSet::BitBlock *IndexSet::alloc_block() {
#ifdef ASSERT
if (CollectIndexSetStatistics) {
_alloc_total++;
inc_stat_counter(&_alloc_total, 1);
}
#endif
Compile *compile = Compile::current();
......@@ -391,13 +391,13 @@ void IndexSet::dump() const {
// Update block/bit counts to reflect that this set has been iterated over.
void IndexSet::tally_iteration_statistics() const {
_total_bits += count();
inc_stat_counter(&_total_bits, count());
for (uint i = 0; i < _max_blocks; i++) {
if (_blocks[i] != &_empty_block) {
_total_used_blocks++;
inc_stat_counter(&_total_used_blocks, 1);
} else {
_total_unused_blocks++;
inc_stat_counter(&_total_unused_blocks, 1);
}
}
}
......@@ -406,17 +406,17 @@ void IndexSet::tally_iteration_statistics() const {
// Print statistics about IndexSet usage.
void IndexSet::print_statistics() {
long total_blocks = _total_used_blocks + _total_unused_blocks;
julong total_blocks = _total_used_blocks + _total_unused_blocks;
tty->print_cr ("Accumulated IndexSet usage statistics:");
tty->print_cr ("--------------------------------------");
tty->print_cr (" Iteration:");
tty->print_cr (" blocks visited: %d", total_blocks);
tty->print_cr (" blocks empty: %4.2f%%", 100.0*_total_unused_blocks/total_blocks);
tty->print_cr (" bit density (bits/used blocks): %4.2f%%", (double)_total_bits/_total_used_blocks);
tty->print_cr (" bit density (bits/all blocks): %4.2f%%", (double)_total_bits/total_blocks);
tty->print_cr (" blocks visited: " UINT64_FORMAT, total_blocks);
tty->print_cr (" blocks empty: %4.2f%%", 100.0*(double)_total_unused_blocks/total_blocks);
tty->print_cr (" bit density (bits/used blocks): %4.2f", (double)_total_bits/_total_used_blocks);
tty->print_cr (" bit density (bits/all blocks): %4.2f", (double)_total_bits/total_blocks);
tty->print_cr (" Allocation:");
tty->print_cr (" blocks allocated: %d", _alloc_new);
tty->print_cr (" blocks used/reused: %d", _alloc_total);
tty->print_cr (" blocks allocated: " UINT64_FORMAT, _alloc_new);
tty->print_cr (" blocks used/reused: " UINT64_FORMAT, _alloc_total);
}
//---------------------------- IndexSet::verify() -----------------------------
......
/*
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -352,13 +352,13 @@ class IndexSet : public ResourceObj {
void tally_iteration_statistics() const;
// BitBlock allocation statistics
static uint _alloc_new;
static uint _alloc_total;
static julong _alloc_new;
static julong _alloc_total;
// Block density statistics
static long _total_bits;
static long _total_used_blocks;
static long _total_unused_blocks;
static julong _total_bits;
static julong _total_used_blocks;
static julong _total_unused_blocks;
// Sanity tests
void verify() const;
......
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -712,6 +712,9 @@ class CommandLineFlags {
develop(bool, PrintMalloc, false, \
"print all malloc/free calls") \
\
develop(bool, PrintMallocStatistics, false, \
"print malloc/free statistics") \
\
develop(bool, ZapResourceArea, trueInDebug, \
"Zap freed resource/arena space with 0xABABABAB") \
\
......
......@@ -320,7 +320,7 @@ void print_statistics() {
}
print_bytecode_count();
if (WizardMode) {
if (PrintMallocStatistics) {
tty->print("allocation stats: ");
alloc_stats.print();
tty->cr();
......
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -72,9 +72,10 @@ int os::_processor_count = 0;
size_t os::_page_sizes[os::page_sizes_max];
#ifndef PRODUCT
int os::num_mallocs = 0; // # of calls to malloc/realloc
size_t os::alloc_bytes = 0; // # of bytes allocated
int os::num_frees = 0; // # of calls to free
julong os::num_mallocs = 0; // # of calls to malloc/realloc
julong os::alloc_bytes = 0; // # of bytes allocated
julong os::num_frees = 0; // # of calls to free
julong os::free_bytes = 0; // # of bytes freed
#endif
// Fill in buffer with current local time as an ISO-8601 string.
......@@ -490,9 +491,9 @@ void print_neighbor_blocks(void* ptr) {
}
if (start_of_prev_block + space_before + size + space_after == start_of_this_block) {
tty->print_cr("### previous object: %p (%ld bytes)", obj, size);
tty->print_cr("### previous object: " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", obj, size);
} else {
tty->print_cr("### previous object (not sure if correct): %p (%ld bytes)", obj, size);
tty->print_cr("### previous object (not sure if correct): " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", obj, size);
}
// now find successor block
......@@ -504,16 +505,16 @@ void print_neighbor_blocks(void* ptr) {
start_of_next_block[1] == badResourceValue &&
start_of_next_block[2] == badResourceValue &&
start_of_next_block[3] == badResourceValue) {
tty->print_cr("### next object: %p (%ld bytes)", next_obj, next_size);
tty->print_cr("### next object: " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", next_obj, next_size);
} else {
tty->print_cr("### next object (not sure if correct): %p (%ld bytes)", next_obj, next_size);
tty->print_cr("### next object (not sure if correct): " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", next_obj, next_size);
}
}
void report_heap_error(void* memblock, void* bad, const char* where) {
tty->print_cr("## nof_mallocs = %d, nof_frees = %d", os::num_mallocs, os::num_frees);
tty->print_cr("## memory stomp: byte at %p %s object %p", bad, where, memblock);
tty->print_cr("## nof_mallocs = " UINT64_FORMAT ", nof_frees = " UINT64_FORMAT, os::num_mallocs, os::num_frees);
tty->print_cr("## memory stomp: byte at " PTR_FORMAT " %s object " PTR_FORMAT, bad, where, memblock);
print_neighbor_blocks(memblock);
fatal("memory stomping error");
}
......@@ -538,8 +539,8 @@ void verify_block(void* memblock) {
#endif
void* os::malloc(size_t size) {
NOT_PRODUCT(num_mallocs++);
NOT_PRODUCT(alloc_bytes += size);
NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
if (size == 0) {
// return a valid pointer if size is zero
......@@ -562,26 +563,26 @@ void* os::malloc(size_t size) {
#endif
u_char* memblock = ptr + space_before;
if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) {
tty->print_cr("os::malloc caught, %lu bytes --> %p", size, memblock);
tty->print_cr("os::malloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, memblock);
breakpoint();
}
debug_only(if (paranoid) verify_block(memblock));
if (PrintMalloc && tty != NULL) tty->print_cr("os::malloc %lu bytes --> %p", size, memblock);
if (PrintMalloc && tty != NULL) tty->print_cr("os::malloc " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, memblock);
return memblock;
}
void* os::realloc(void *memblock, size_t size) {
NOT_PRODUCT(num_mallocs++);
NOT_PRODUCT(alloc_bytes += size);
#ifndef ASSERT
NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
return ::realloc(memblock, size);
#else
if (memblock == NULL) {
return os::malloc(size);
return malloc(size);
}
if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) {
tty->print_cr("os::realloc caught %p", memblock);
tty->print_cr("os::realloc caught " PTR_FORMAT, memblock);
breakpoint();
}
verify_block(memblock);
......@@ -589,13 +590,13 @@ void* os::realloc(void *memblock, size_t size) {
if (size == 0) return NULL;
// always move the block
void* ptr = malloc(size);
if (PrintMalloc) tty->print_cr("os::remalloc %lu bytes, %p --> %p", size, memblock, ptr);
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 ) {
memcpy(ptr, memblock, MIN2(size, get_size(memblock)));
if (paranoid) verify_block(ptr);
if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) {
tty->print_cr("os::realloc caught, %lu bytes --> %p", size, ptr);
tty->print_cr("os::realloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr);
breakpoint();
}
free(memblock);
......@@ -606,17 +607,14 @@ void* os::realloc(void *memblock, size_t size) {
void os::free(void *memblock) {
NOT_PRODUCT(num_frees++);
NOT_PRODUCT(inc_stat_counter(&num_frees, 1));
#ifdef ASSERT
if (memblock == NULL) return;
if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) {
if (tty != NULL) tty->print_cr("os::free caught %p", memblock);
if (tty != NULL) tty->print_cr("os::free caught " PTR_FORMAT, memblock);
breakpoint();
}
verify_block(memblock);
if (PrintMalloc && tty != NULL)
// tty->print_cr("os::free %p", memblock);
fprintf(stderr, "os::free %p\n", memblock);
NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap());
// Added by detlefs.
if (MallocCushion) {
......@@ -627,12 +625,18 @@ void os::free(void *memblock) {
*p = (u_char)freeBlockPad;
}
size_t size = get_size(memblock);
inc_stat_counter(&free_bytes, size);
u_char* end = ptr + space_before + size;
for (u_char* q = end; q < end + MallocCushion; q++) {
guarantee(*q == badResourceValue,
"Thing freed should be malloc result.");
*q = (u_char)freeBlockPad;
}
if (PrintMalloc && tty != NULL)
fprintf(stderr, "os::free " SIZE_FORMAT " bytes --> " PTR_FORMAT "\n", size, memblock);
} else if (PrintMalloc && tty != NULL) {
// tty->print_cr("os::free %p", memblock);
fprintf(stderr, "os::free " PTR_FORMAT "\n", memblock);
}
#endif
::free((char*)memblock - space_before);
......
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -559,9 +559,10 @@ class os: AllStatic {
static char* strdup(const char *); // Like strdup
#ifndef PRODUCT
static int num_mallocs; // # of calls to malloc/realloc
static size_t alloc_bytes; // # of bytes allocated
static int num_frees; // # of calls to free
static julong num_mallocs; // # of calls to malloc/realloc
static julong alloc_bytes; // # of bytes allocated
static julong num_frees; // # of calls to free
static julong free_bytes; // # of bytes freed
#endif
// SocketInterface (ex HPI SocketInterface )
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册