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
--- a/hotspot/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp Mon Feb 07 10:25:39 2011 -0800
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp Mon Feb 07 10:34:39 2011 -0800
@@ -67,7 +67,6 @@
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.
--- a/hotspot/src/share/vm/memory/allocation.cpp Mon Feb 07 10:25:39 2011 -0800
+++ b/hotspot/src/share/vm/memory/allocation.cpp Mon Feb 07 10:34:39 2011 -0800
@@ -1,5 +1,5 @@
/*
- * 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 @@
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 @@
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_mallocs = os::num_mallocs;
+ start_frees = os::num_frees;
start_malloc_bytes = os::alloc_bytes;
- start_res_bytes = Arena::_bytes_allocated;
+ 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);
}
--- a/hotspot/src/share/vm/memory/allocation.hpp Mon Feb 07 10:25:39 2011 -0800
+++ b/hotspot/src/share/vm/memory/allocation.hpp Mon Feb 07 10:34:39 2011 -0800
@@ -1,5 +1,5 @@
/*
- * 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 @@
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 @@
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 @@
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 @@
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 @@
// 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
--- a/hotspot/src/share/vm/memory/allocation.inline.hpp Mon Feb 07 10:25:39 2011 -0800
+++ b/hotspot/src/share/vm/memory/allocation.inline.hpp Mon Feb 07 10:34:39 2011 -0800
@@ -1,5 +1,5 @@
/*
- * 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) {
--- a/hotspot/src/share/vm/opto/indexSet.cpp Mon Feb 07 10:25:39 2011 -0800
+++ b/hotspot/src/share/vm/opto/indexSet.cpp Mon Feb 07 10:34:39 2011 -0800
@@ -1,5 +1,5 @@
/*
- * 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 @@
#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 @@
#ifdef ASSERT
if (CollectIndexSetStatistics) {
- _alloc_new += bitblock_alloc_chunk_size;
+ inc_stat_counter(&_alloc_new, bitblock_alloc_chunk_size);
}
#endif
}
@@ -154,7 +154,7 @@
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 @@
// 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 @@
// 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() -----------------------------
--- a/hotspot/src/share/vm/opto/indexSet.hpp Mon Feb 07 10:25:39 2011 -0800
+++ b/hotspot/src/share/vm/opto/indexSet.hpp Mon Feb 07 10:34:39 2011 -0800
@@ -1,5 +1,5 @@
/*
- * 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 @@
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;
--- a/hotspot/src/share/vm/runtime/globals.hpp Mon Feb 07 10:25:39 2011 -0800
+++ b/hotspot/src/share/vm/runtime/globals.hpp Mon Feb 07 10:34:39 2011 -0800
@@ -1,5 +1,5 @@
/*
- * 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 @@
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") \
\
--- a/hotspot/src/share/vm/runtime/java.cpp Mon Feb 07 10:25:39 2011 -0800
+++ b/hotspot/src/share/vm/runtime/java.cpp Mon Feb 07 10:34:39 2011 -0800
@@ -320,7 +320,7 @@
}
print_bytecode_count();
- if (WizardMode) {
+ if (PrintMallocStatistics) {
tty->print("allocation stats: ");
alloc_stats.print();
tty->cr();
--- a/hotspot/src/share/vm/runtime/os.cpp Mon Feb 07 10:25:39 2011 -0800
+++ b/hotspot/src/share/vm/runtime/os.cpp Mon Feb 07 10:34:39 2011 -0800
@@ -1,5 +1,5 @@
/*
- * 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 @@
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 @@
}
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 @@
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 @@
#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 @@
#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 @@
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::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 @@
*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);
--- a/hotspot/src/share/vm/runtime/os.hpp Mon Feb 07 10:25:39 2011 -0800
+++ b/hotspot/src/share/vm/runtime/os.hpp Mon Feb 07 10:34:39 2011 -0800
@@ -1,5 +1,5 @@
/*
- * 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 @@
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 )