# HG changeset patch # User tonyp # Date 1283187651 14400 # Node ID 75107ee8712ff20a76c50bfefee8f15d0be8ee01 # Parent b4099f5786daf2b2c16f2999cd139aed331a2aa7# Parent af586a7893cfbb62c8e75cebb088586a3ea4b4f8 Merge diff -r b4099f5786da -r 75107ee8712f src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Wed Aug 25 10:31:45 2010 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Mon Aug 30 13:00:51 2010 -0400 @@ -252,12 +252,13 @@ class ChunkArray: public CHeapObj { size_t _index; size_t _capacity; + size_t _overflows; HeapWord** _array; // storage for array public: - ChunkArray() : _index(0), _capacity(0), _array(NULL) {} + ChunkArray() : _index(0), _capacity(0), _overflows(0), _array(NULL) {} ChunkArray(HeapWord** a, size_t c): - _index(0), _capacity(c), _array(a) {} + _index(0), _capacity(c), _overflows(0), _array(a) {} HeapWord** array() { return _array; } void set_array(HeapWord** a) { _array = a; } @@ -266,7 +267,9 @@ void set_capacity(size_t c) { _capacity = c; } size_t end() { - assert(_index < capacity(), "_index out of bounds"); + assert(_index <= capacity(), + err_msg("_index (" SIZE_FORMAT ") > _capacity (" SIZE_FORMAT "): out of bounds", + _index, _capacity)); return _index; } // exclusive @@ -277,12 +280,23 @@ void reset() { _index = 0; + if (_overflows > 0 && PrintCMSStatistics > 1) { + warning("CMS: ChunkArray[" SIZE_FORMAT "] overflowed " SIZE_FORMAT " times", + _capacity, _overflows); + } + _overflows = 0; } void record_sample(HeapWord* p, size_t sz) { // For now we do not do anything with the size if (_index < _capacity) { _array[_index++] = p; + } else { + ++_overflows; + assert(_index == _capacity, + err_msg("_index (" SIZE_FORMAT ") > _capacity (" SIZE_FORMAT + "): out of bounds at overflow#" SIZE_FORMAT, + _index, _capacity, _overflows)); } } }; diff -r b4099f5786da -r 75107ee8712f src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Aug 25 10:31:45 2010 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Mon Aug 30 13:00:51 2010 -0400 @@ -2753,7 +2753,7 @@ print_taskqueue_stats_hdr(st); TaskQueueStats totals; - const int n = MAX2(workers()->total_workers(), 1); + const int n = workers() != NULL ? workers()->total_workers() : 1; for (int i = 0; i < n; ++i) { st->print("%3d ", i); task_queue(i)->stats.print(st); st->cr(); totals += task_queue(i)->stats; @@ -2764,7 +2764,7 @@ } void G1CollectedHeap::reset_taskqueue_stats() { - const int n = MAX2(workers()->total_workers(), 1); + const int n = workers() != NULL ? workers()->total_workers() : 1; for (int i = 0; i < n; ++i) { task_queue(i)->stats.reset(); } diff -r b4099f5786da -r 75107ee8712f src/share/vm/services/g1MemoryPool.cpp --- a/src/share/vm/services/g1MemoryPool.cpp Wed Aug 25 10:31:45 2010 -0700 +++ b/src/share/vm/services/g1MemoryPool.cpp Mon Aug 30 13:00:51 2010 -0400 @@ -28,12 +28,11 @@ G1MemoryPoolSuper::G1MemoryPoolSuper(G1CollectedHeap* g1h, const char* name, size_t init_size, - size_t max_size, bool support_usage_threshold) : _g1h(g1h), CollectedMemoryPool(name, MemoryPool::Heap, init_size, - max_size, + undefined_max(), support_usage_threshold) { assert(UseG1GC, "sanity"); } @@ -53,13 +52,6 @@ } // See the comment at the top of g1MemoryPool.hpp -size_t G1MemoryPoolSuper::eden_space_max(G1CollectedHeap* g1h) { - // This should ensure that it returns a value no smaller than the - // region size. Currently, eden_space_committed() guarantees that. - return eden_space_committed(g1h); -} - -// See the comment at the top of g1MemoryPool.hpp size_t G1MemoryPoolSuper::survivor_space_committed(G1CollectedHeap* g1h) { return MAX2(survivor_space_used(g1h), (size_t) HeapRegion::GrainBytes); } @@ -72,13 +64,6 @@ } // See the comment at the top of g1MemoryPool.hpp -size_t G1MemoryPoolSuper::survivor_space_max(G1CollectedHeap* g1h) { - // This should ensure that it returns a value no smaller than the - // region size. Currently, survivor_space_committed() guarantees that. - return survivor_space_committed(g1h); -} - -// See the comment at the top of g1MemoryPool.hpp size_t G1MemoryPoolSuper::old_space_committed(G1CollectedHeap* g1h) { size_t committed = overall_committed(g1h); size_t eden_committed = eden_space_committed(g1h); @@ -99,24 +84,11 @@ return used; } -// See the comment at the top of g1MemoryPool.hpp -size_t G1MemoryPoolSuper::old_space_max(G1CollectedHeap* g1h) { - size_t max = overall_max(g1h); - size_t eden_max = eden_space_max(g1h); - size_t survivor_max = survivor_space_max(g1h); - max = subtract_up_to_zero(max, eden_max); - max = subtract_up_to_zero(max, survivor_max); - max = MAX2(max, (size_t) HeapRegion::GrainBytes); - return max; -} - G1EdenPool::G1EdenPool(G1CollectedHeap* g1h) : G1MemoryPoolSuper(g1h, "G1 Eden", eden_space_committed(g1h), /* init_size */ - eden_space_max(g1h), /* max_size */ - false /* support_usage_threshold */) { -} + false /* support_usage_threshold */) { } MemoryUsage G1EdenPool::get_memory_usage() { size_t initial_sz = initial_size(); @@ -131,9 +103,7 @@ G1MemoryPoolSuper(g1h, "G1 Survivor", survivor_space_committed(g1h), /* init_size */ - survivor_space_max(g1h), /* max_size */ - false /* support_usage_threshold */) { -} + false /* support_usage_threshold */) { } MemoryUsage G1SurvivorPool::get_memory_usage() { size_t initial_sz = initial_size(); @@ -148,9 +118,7 @@ G1MemoryPoolSuper(g1h, "G1 Old Gen", old_space_committed(g1h), /* init_size */ - old_space_max(g1h), /* max_size */ - true /* support_usage_threshold */) { -} + true /* support_usage_threshold */) { } MemoryUsage G1OldGenPool::get_memory_usage() { size_t initial_sz = initial_size(); diff -r b4099f5786da -r 75107ee8712f src/share/vm/services/g1MemoryPool.hpp --- a/src/share/vm/services/g1MemoryPool.hpp Wed Aug 25 10:31:45 2010 -0700 +++ b/src/share/vm/services/g1MemoryPool.hpp Mon Aug 30 13:00:51 2010 -0400 @@ -74,14 +74,20 @@ // in the future. // // 3) Another decision that is again not straightforward is what is -// the max size that each memory pool can grow to. Right now, we set -// that the committed size for the eden and the survivors and -// calculate the old gen max as follows (basically, it's a similar -// pattern to what we use for the committed space, as described -// above): +// the max size that each memory pool can grow to. One way to do this +// would be to use the committed size for the max for the eden and +// survivors and calculate the old gen max as follows (basically, it's +// a similar pattern to what we use for the committed space, as +// described above): // // old_gen_max = overall_max - eden_max - survivor_max // +// Unfortunately, the above makes the max of each pool fluctuate over +// time and, even though this is allowed according to the spec, it +// broke several assumptions in the M&M framework (there were cases +// where used would reach a value greater than max). So, for max we +// use -1, which means "undefined" according to the spec. +// // 4) Now, there is a very subtle issue with all the above. The // framework will call get_memory_usage() on the three pools // asynchronously. As a result, each call might get a different value @@ -125,33 +131,30 @@ G1MemoryPoolSuper(G1CollectedHeap* g1h, const char* name, size_t init_size, - size_t max_size, bool support_usage_threshold); // The reason why all the code is in static methods is so that it // can be safely called from the constructors of the subclasses. + static size_t undefined_max() { + return (size_t) -1; + } + static size_t overall_committed(G1CollectedHeap* g1h) { return g1h->capacity(); } static size_t overall_used(G1CollectedHeap* g1h) { return g1h->used_unlocked(); } - static size_t overall_max(G1CollectedHeap* g1h) { - return g1h->g1_reserved_obj_bytes(); - } static size_t eden_space_committed(G1CollectedHeap* g1h); static size_t eden_space_used(G1CollectedHeap* g1h); - static size_t eden_space_max(G1CollectedHeap* g1h); static size_t survivor_space_committed(G1CollectedHeap* g1h); static size_t survivor_space_used(G1CollectedHeap* g1h); - static size_t survivor_space_max(G1CollectedHeap* g1h); static size_t old_space_committed(G1CollectedHeap* g1h); static size_t old_space_used(G1CollectedHeap* g1h); - static size_t old_space_max(G1CollectedHeap* g1h); }; // Memory pool that represents the G1 eden. @@ -163,7 +166,7 @@ return eden_space_used(_g1h); } size_t max_size() const { - return eden_space_max(_g1h); + return undefined_max(); } MemoryUsage get_memory_usage(); }; @@ -177,7 +180,7 @@ return survivor_space_used(_g1h); } size_t max_size() const { - return survivor_space_max(_g1h); + return undefined_max(); } MemoryUsage get_memory_usage(); }; @@ -191,7 +194,7 @@ return old_space_used(_g1h); } size_t max_size() const { - return old_space_max(_g1h); + return undefined_max(); } MemoryUsage get_memory_usage(); }; diff -r b4099f5786da -r 75107ee8712f src/share/vm/services/management.cpp --- a/src/share/vm/services/management.cpp Wed Aug 25 10:31:45 2010 -0700 +++ b/src/share/vm/services/management.cpp Mon Aug 30 13:00:51 2010 -0400 @@ -785,10 +785,11 @@ } } - // In our current implementation, all pools should have - // defined init and max size - assert(!has_undefined_init_size, "Undefined init size"); - assert(!has_undefined_max_size, "Undefined max size"); + // In our current implementation, we make sure that all non-heap + // pools have defined init and max sizes. Heap pools do not matter, + // as we never use total_init and total_max for them. + assert(heap || !has_undefined_init_size, "Undefined init size"); + assert(heap || !has_undefined_max_size, "Undefined max size"); MemoryUsage usage((heap ? InitialHeapSize : total_init), total_used, diff -r b4099f5786da -r 75107ee8712f test/gc/6581734/Test6581734.java --- a/test/gc/6581734/Test6581734.java Wed Aug 25 10:31:45 2010 -0700 +++ b/test/gc/6581734/Test6581734.java Mon Aug 30 13:00:51 2010 -0400 @@ -121,7 +121,7 @@ } if (collectorsWithTime