--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Wed Aug 25 10:31:45 2010 -0700
+++ b/hotspot/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));
}
}
};
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Aug 25 10:31:45 2010 -0700
+++ b/hotspot/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();
}
--- a/hotspot/src/share/vm/services/g1MemoryPool.cpp Wed Aug 25 10:31:45 2010 -0700
+++ b/hotspot/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();
--- a/hotspot/src/share/vm/services/g1MemoryPool.hpp Wed Aug 25 10:31:45 2010 -0700
+++ b/hotspot/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();
};
--- a/hotspot/src/share/vm/services/management.cpp Wed Aug 25 10:31:45 2010 -0700
+++ b/hotspot/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,
--- a/hotspot/test/gc/6581734/Test6581734.java Wed Aug 25 10:31:45 2010 -0700
+++ b/hotspot/test/gc/6581734/Test6581734.java Mon Aug 30 13:00:51 2010 -0400
@@ -121,7 +121,7 @@
}
if (collectorsWithTime<collectorsFound) {
- throw new RuntimeException("collectors found with zero time";
+ throw new RuntimeException("collectors found with zero time");
}
System.out.println("Test passed.");
}