--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu Dec 18 13:59:59 2008 -0800
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Dec 19 12:15:34 2008 -0800
@@ -726,7 +726,7 @@
size_t live_to_left = bitmap->live_words_in_range(search_start, oop(addr));
result += partial_obj_size + live_to_left;
- assert(result <= addr, "object cannot move to the right");
+ DEBUG_ONLY(PSParallelCompact::check_new_location(addr, result);)
return result;
}
@@ -1473,8 +1473,52 @@
}
void
+PSParallelCompact::provoke_split_fill_survivor(SpaceId id)
+{
+ if (total_invocations() % (ParallelOldGCSplitInterval * 3) != 0) {
+ return;
+ }
+
+ MutableSpace* const space = _space_info[id].space();
+ if (space->is_empty()) {
+ HeapWord* b = space->bottom();
+ HeapWord* t = b + space->capacity_in_words() / 2;
+ space->set_top(t);
+ if (ZapUnusedHeapArea) {
+ space->set_top_for_allocations();
+ }
+
+ size_t obj_len = 8;
+ while (b + obj_len <= t) {
+ CollectedHeap::fill_with_object(b, obj_len);
+ mark_bitmap()->mark_obj(b, obj_len);
+ summary_data().add_obj(b, obj_len);
+ b += obj_len;
+ obj_len = (obj_len & 0x18) + 8; // 8 16 24 32 8 16 24 32 ...
+ }
+ if (b < t) {
+ // The loop didn't completely fill to t (top); adjust top downward.
+ space->set_top(b);
+ if (ZapUnusedHeapArea) {
+ space->set_top_for_allocations();
+ }
+ }
+
+ HeapWord** nta = _space_info[id].new_top_addr();
+ bool result = summary_data().summarize(_space_info[id].split_info(),
+ space->bottom(), space->top(), NULL,
+ space->bottom(), space->end(), nta);
+ assert(result, "space must fit into itself");
+ }
+}
+
+void
PSParallelCompact::provoke_split(bool & max_compaction)
{
+ if (total_invocations() % ParallelOldGCSplitInterval != 0) {
+ return;
+ }
+
const size_t region_size = ParallelCompactData::RegionSize;
ParallelCompactData& sd = summary_data();
@@ -1587,6 +1631,12 @@
assert(result, "space must fit into itself");
_space_info[i].set_dense_prefix(space->bottom());
}
+
+#ifndef PRODUCT
+ if (ParallelOldGCSplitALot) {
+ provoke_split_fill_survivor(to_space_id);
+ }
+#endif // #ifndef PRODUCT
}
void PSParallelCompact::fill_dense_prefix_end(SpaceId id)
@@ -1794,9 +1844,7 @@
}
#ifndef PRODUCT
if (ParallelOldGCSplitALot && old_space_total_live < old_capacity) {
- if (total_invocations() % ParallelOldGCSplitInterval == 0) {
- provoke_split(maximum_compaction);
- }
+ provoke_split(maximum_compaction);
}
#endif // #ifndef PRODUCT
@@ -1828,14 +1876,6 @@
new_top_addr);
assert(done, "space must fit into old gen");
- // XXX - this is necessary because decrement_destination_counts() tests
- // source_region() to determine if a region will be filled. Probably
- // better to pass src_space->new_top() into decrement_destination_counts
- // and test that instead.
- //
- // Clear the source_region field for each region in the space.
- clear_source_region(space->bottom(), _space_info[id].new_top());
-
// Reset the new_top value for the space.
_space_info[id].set_new_top(space->bottom());
} else if (live > 0) {
@@ -1854,7 +1894,6 @@
dst_space_id = SpaceId(id);
dst_space_end = space->end();
new_top_addr = _space_info[id].new_top_addr();
- HeapWord* const clear_end = _space_info[id].new_top();
NOT_PRODUCT(summary_phase_msg(dst_space_id,
space->bottom(), dst_space_end,
SpaceId(id), next_src_addr, space->top());)
@@ -1865,13 +1904,6 @@
new_top_addr);
assert(done, "space must fit when compacted into itself");
assert(*new_top_addr <= space->top(), "usage should not grow");
-
- // XXX - this should go away. See comments above.
- //
- // Clear the source_region field in regions at the end of the space that
- // will not be filled.
- HeapWord* const clear_beg = _summary_data.region_align_up(*new_top_addr);
- clear_source_region(clear_beg, clear_end);
}
}
@@ -3051,19 +3083,34 @@
}
void PSParallelCompact::decrement_destination_counts(ParCompactionManager* cm,
+ SpaceId src_space_id,
size_t beg_region,
HeapWord* end_addr)
{
ParallelCompactData& sd = summary_data();
+
+#ifdef ASSERT
+ MutableSpace* const src_space = _space_info[src_space_id].space();
+ HeapWord* const beg_addr = sd.region_to_addr(beg_region);
+ assert(src_space->contains(beg_addr) || beg_addr == src_space->end(),
+ "src_space_id does not match beg_addr");
+ assert(src_space->contains(end_addr) || end_addr == src_space->end(),
+ "src_space_id does not match end_addr");
+#endif // #ifdef ASSERT
+
RegionData* const beg = sd.region(beg_region);
- HeapWord* const end_addr_aligned_up = sd.region_align_up(end_addr);
- RegionData* const end = sd.addr_to_region_ptr(end_addr_aligned_up);
- size_t cur_idx = beg_region;
- for (RegionData* cur = beg; cur < end; ++cur, ++cur_idx) {
+ RegionData* const end = sd.addr_to_region_ptr(sd.region_align_up(end_addr));
+
+ // Regions up to new_top() are enqueued if they become available.
+ HeapWord* const new_top = _space_info[src_space_id].new_top();
+ RegionData* const enqueue_end =
+ sd.addr_to_region_ptr(sd.region_align_up(new_top));
+
+ for (RegionData* cur = beg; cur < end; ++cur) {
assert(cur->data_size() > 0, "region must have live data");
cur->decrement_destination_count();
- if (cur_idx <= cur->source_region() && cur->available() && cur->claim()) {
- cm->save_for_processing(cur_idx);
+ if (cur < enqueue_end && cur->available() && cur->claim()) {
+ cm->save_for_processing(sd.region(cur));
}
}
}
@@ -3178,7 +3225,8 @@
HeapWord* const old_src_addr = closure.source();
closure.copy_partial_obj();
if (closure.is_full()) {
- decrement_destination_counts(cm, src_region_idx, closure.source());
+ decrement_destination_counts(cm, src_space_id, src_region_idx,
+ closure.source());
region_ptr->set_deferred_obj_addr(NULL);
region_ptr->set_completed();
return;
@@ -3187,7 +3235,7 @@
HeapWord* const end_addr = sd.region_align_down(closure.source());
if (sd.region_align_down(old_src_addr) != end_addr) {
// The partial object was copied from more than one source region.
- decrement_destination_counts(cm, src_region_idx, end_addr);
+ decrement_destination_counts(cm, src_space_id, src_region_idx, end_addr);
// Move to the next source region, possibly switching spaces as well. All
// args except end_addr may be modified.
@@ -3227,19 +3275,21 @@
region_ptr->set_deferred_obj_addr(closure.destination());
status = closure.copy_until_full(); // copies from closure.source()
- decrement_destination_counts(cm, src_region_idx, closure.source());
+ decrement_destination_counts(cm, src_space_id, src_region_idx,
+ closure.source());
region_ptr->set_completed();
return;
}
if (status == ParMarkBitMap::full) {
- decrement_destination_counts(cm, src_region_idx, closure.source());
+ decrement_destination_counts(cm, src_space_id, src_region_idx,
+ closure.source());
region_ptr->set_deferred_obj_addr(NULL);
region_ptr->set_completed();
return;
}
- decrement_destination_counts(cm, src_region_idx, end_addr);
+ decrement_destination_counts(cm, src_space_id, src_region_idx, end_addr);
// Move to the next source region, possibly switching spaces as well. All
// args except end_addr may be modified.
@@ -3318,7 +3368,7 @@
ParMarkBitMap::IterationStatus MoveAndUpdateClosure::copy_until_full()
{
if (source() != destination()) {
- assert(source() > destination(), "must copy to the left");
+ DEBUG_ONLY(PSParallelCompact::check_new_location(source(), destination());)
Copy::aligned_conjoint_words(source(), destination(), words_remaining());
}
update_state(words_remaining());
@@ -3339,7 +3389,7 @@
// This test is necessary; if omitted, the pointer updates to a partial object
// that crosses the dense prefix boundary could be overwritten.
if (source() != destination()) {
- assert(source() > destination(), "must copy to the left");
+ DEBUG_ONLY(PSParallelCompact::check_new_location(source(), destination());)
Copy::aligned_conjoint_words(source(), destination(), words);
}
update_state(words);
@@ -3364,7 +3414,7 @@
}
if (destination() != source()) {
- assert(destination() < source(), "must copy to the left");
+ DEBUG_ONLY(PSParallelCompact::check_new_location(source(), destination());)
Copy::aligned_conjoint_words(source(), destination(), words);
}
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Thu Dec 18 13:59:59 2008 -0800
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Fri Dec 19 12:15:34 2008 -0800
@@ -978,6 +978,10 @@
// Include the new objects in the summary data.
static void summarize_new_objects(SpaceId id, HeapWord* start);
+ // Add live objects to a survivor space since it's rare that both survivors
+ // are non-empty.
+ static void provoke_split_fill_survivor(SpaceId id);
+
// Add live objects and/or choose the dense prefix to provoke splitting.
static void provoke_split(bool & maximum_compaction);
#endif
@@ -1154,8 +1158,10 @@
HeapWord* end_addr);
// Decrement the destination count for each non-empty source region in the
- // range [beg_region, region(region_align_up(end_addr))).
+ // range [beg_region, region(region_align_up(end_addr))). If the destination
+ // count for a region goes to 0 and it needs to be filled, enqueue it.
static void decrement_destination_counts(ParCompactionManager* cm,
+ SpaceId src_space_id,
size_t beg_region,
HeapWord* end_addr);
@@ -1230,6 +1236,8 @@
#endif // #ifndef PRODUCT
#ifdef ASSERT
+ // Sanity check the new location of a word in the heap.
+ static inline void check_new_location(HeapWord* old_addr, HeapWord* new_addr);
// Verify that all the regions have been emptied.
static void verify_complete(SpaceId space_id);
#endif // #ifdef ASSERT
@@ -1397,6 +1405,15 @@
}
}
+#ifdef ASSERT
+inline void
+PSParallelCompact::check_new_location(HeapWord* old_addr, HeapWord* new_addr)
+{
+ assert(old_addr >= new_addr || space_id(old_addr) != space_id(new_addr),
+ "must move left or to a different space");
+}
+#endif // ASSERT
+
class MoveAndUpdateClosure: public ParMarkBitMapClosure {
public:
inline MoveAndUpdateClosure(ParMarkBitMap* bitmap, ParCompactionManager* cm,
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp Thu Dec 18 13:59:59 2008 -0800
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp Fri Dec 19 12:15:34 2008 -0800
@@ -178,8 +178,7 @@
// Set the length first for concurrent GC.
((arrayOop)start)->set_length((int)len);
- post_allocation_setup_common(Universe::fillerArrayKlassObj(), start,
- words);
+ post_allocation_setup_common(Universe::intArrayKlassObj(), start, words);
DEBUG_ONLY(zap_filler_array(start, words);)
}
--- a/hotspot/src/share/vm/memory/universe.cpp Thu Dec 18 13:59:59 2008 -0800
+++ b/hotspot/src/share/vm/memory/universe.cpp Fri Dec 19 12:15:34 2008 -0800
@@ -49,7 +49,6 @@
klassOop Universe::_constantPoolCacheKlassObj = NULL;
klassOop Universe::_compiledICHolderKlassObj = NULL;
klassOop Universe::_systemObjArrayKlassObj = NULL;
-klassOop Universe::_fillerArrayKlassObj = NULL;
oop Universe::_int_mirror = NULL;
oop Universe::_float_mirror = NULL;
oop Universe::_double_mirror = NULL;
@@ -127,7 +126,6 @@
f(instanceKlassKlassObj());
f(constantPoolKlassObj());
f(systemObjArrayKlassObj());
- f(fillerArrayKlassObj());
}
void Universe::oops_do(OopClosure* f, bool do_all) {
@@ -182,7 +180,6 @@
f->do_oop((oop*)&_constantPoolCacheKlassObj);
f->do_oop((oop*)&_compiledICHolderKlassObj);
f->do_oop((oop*)&_systemObjArrayKlassObj);
- f->do_oop((oop*)&_fillerArrayKlassObj);
f->do_oop((oop*)&_the_empty_byte_array);
f->do_oop((oop*)&_the_empty_short_array);
f->do_oop((oop*)&_the_empty_int_array);
@@ -268,7 +265,6 @@
_compiledICHolderKlassObj = compiledICHolderKlass::create_klass(CHECK);
_systemObjArrayKlassObj = objArrayKlassKlass::cast(objArrayKlassKlassObj())->allocate_system_objArray_klass(CHECK);
- _fillerArrayKlassObj = typeArrayKlass::create_klass(T_INT, sizeof(jint), "<filler>", CHECK);
_the_empty_byte_array = oopFactory::new_permanent_byteArray(0, CHECK);
_the_empty_short_array = oopFactory::new_permanent_shortArray(0, CHECK);
--- a/hotspot/src/share/vm/memory/universe.hpp Thu Dec 18 13:59:59 2008 -0800
+++ b/hotspot/src/share/vm/memory/universe.hpp Fri Dec 19 12:15:34 2008 -0800
@@ -133,7 +133,6 @@
static klassOop _constantPoolCacheKlassObj;
static klassOop _compiledICHolderKlassObj;
static klassOop _systemObjArrayKlassObj;
- static klassOop _fillerArrayKlassObj;
// Known objects in the VM
@@ -266,7 +265,6 @@
static klassOop constantPoolCacheKlassObj() { return _constantPoolCacheKlassObj; }
static klassOop compiledICHolderKlassObj() { return _compiledICHolderKlassObj; }
static klassOop systemObjArrayKlassObj() { return _systemObjArrayKlassObj; }
- static klassOop fillerArrayKlassObj() { return _fillerArrayKlassObj; }
// Known objects in tbe VM
static oop int_mirror() { return check_mirror(_int_mirror);