# HG changeset patch # User kvn # Date 1297103679 28800 # Node ID 544210b4dd4875464365f8323bfce2fec07808ca # Parent aedb3bd871bcc2d03c6136c47d8319812e8bdb1e 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 diff -r aedb3bd871bc -r 544210b4dd48 hotspot/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp --- 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. diff -r aedb3bd871bc -r 544210b4dd48 hotspot/src/share/vm/memory/allocation.cpp --- 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); } diff -r aedb3bd871bc -r 544210b4dd48 hotspot/src/share/vm/memory/allocation.hpp --- 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 diff -r aedb3bd871bc -r 544210b4dd48 hotspot/src/share/vm/memory/allocation.inline.hpp --- 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) { diff -r aedb3bd871bc -r 544210b4dd48 hotspot/src/share/vm/opto/indexSet.cpp --- 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() ----------------------------- diff -r aedb3bd871bc -r 544210b4dd48 hotspot/src/share/vm/opto/indexSet.hpp --- 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; diff -r aedb3bd871bc -r 544210b4dd48 hotspot/src/share/vm/runtime/globals.hpp --- 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") \ \ diff -r aedb3bd871bc -r 544210b4dd48 hotspot/src/share/vm/runtime/java.cpp --- 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(); diff -r aedb3bd871bc -r 544210b4dd48 hotspot/src/share/vm/runtime/os.cpp --- 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); diff -r aedb3bd871bc -r 544210b4dd48 hotspot/src/share/vm/runtime/os.hpp --- 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 )