# HG changeset patch # User jcoomes # Date 1213995595 25200 # Node ID 0bf6e2e70558014f138d49d9092e092644f6e0d5 # Parent de226a6adb886c52c6ca1ef4fdac767455ff42d5# Parent dc1ba65c5d1e33864064d2471304c80cc45bde40 Merge diff -r de226a6adb88 -r 0bf6e2e70558 hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Jun 20 11:47:53 2008 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Jun 20 13:59:55 2008 -0700 @@ -1004,6 +1004,9 @@ DEBUG_ONLY(mark_bitmap()->verify_clear();) DEBUG_ONLY(summary_data().verify_clear();) + + // Have worker threads release resources the next time they run a task. + gc_task_manager()->release_all_resources(); } void PSParallelCompact::post_compact() @@ -1949,12 +1952,6 @@ TimeStamp compaction_start; TimeStamp collection_exit; - // "serial_CM" is needed until the parallel implementation - // of the move and update is done. - ParCompactionManager* serial_CM = new ParCompactionManager(); - // Don't initialize more than once. - // serial_CM->initialize(&summary_data(), mark_bitmap()); - ParallelScavengeHeap* heap = gc_heap(); GCCause::Cause gc_cause = heap->gc_cause(); PSYoungGen* young_gen = heap->young_gen(); @@ -1969,6 +1966,10 @@ PreGCValues pre_gc_values; pre_compact(&pre_gc_values); + // Get the compaction manager reserved for the VM thread. + ParCompactionManager* const vmthread_cm = + ParCompactionManager::manager_array(gc_task_manager()->workers()); + // Place after pre_compact() where the number of invocations is incremented. AdaptiveSizePolicyOutput(size_policy, heap->total_collections()); @@ -2008,7 +2009,7 @@ bool marked_for_unloading = false; marking_start.update(); - marking_phase(serial_CM, maximum_heap_compaction); + marking_phase(vmthread_cm, maximum_heap_compaction); #ifndef PRODUCT if (TraceParallelOldGCMarkingPhase) { @@ -2039,7 +2040,7 @@ #endif bool max_on_system_gc = UseMaximumCompactionOnSystemGC && is_system_gc; - summary_phase(serial_CM, maximum_heap_compaction || max_on_system_gc); + summary_phase(vmthread_cm, maximum_heap_compaction || max_on_system_gc); #ifdef ASSERT if (VerifyParallelOldWithMarkSweep && @@ -2067,13 +2068,13 @@ // code can use the the forwarding pointers to // check the new pointer calculation. The restore_marks() // has to be done before the real compact. - serial_CM->set_action(ParCompactionManager::VerifyUpdate); - compact_perm(serial_CM); - compact_serial(serial_CM); - serial_CM->set_action(ParCompactionManager::ResetObjects); - compact_perm(serial_CM); - compact_serial(serial_CM); - serial_CM->set_action(ParCompactionManager::UpdateAndCopy); + vmthread_cm->set_action(ParCompactionManager::VerifyUpdate); + compact_perm(vmthread_cm); + compact_serial(vmthread_cm); + vmthread_cm->set_action(ParCompactionManager::ResetObjects); + compact_perm(vmthread_cm); + compact_serial(vmthread_cm); + vmthread_cm->set_action(ParCompactionManager::UpdateAndCopy); // For debugging only PSMarkSweep::restore_marks(); @@ -2084,16 +2085,14 @@ compaction_start.update(); // Does the perm gen always have to be done serially because // klasses are used in the update of an object? - compact_perm(serial_CM); + compact_perm(vmthread_cm); if (UseParallelOldGCCompacting) { compact(); } else { - compact_serial(serial_CM); + compact_serial(vmthread_cm); } - delete serial_CM; - // Reset the mark bitmap, summary data, and do other bookkeeping. Must be // done before resizing. post_compact(); diff -r de226a6adb88 -r 0bf6e2e70558 hotspot/src/share/vm/memory/cardTableModRefBS.cpp --- a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp Fri Jun 20 11:47:53 2008 -0700 +++ b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp Fri Jun 20 13:59:55 2008 -0700 @@ -196,6 +196,8 @@ assert(_whole_heap.contains(new_region), "attempt to cover area not in reserved area"); debug_only(verify_guard();) + // collided is true if the expansion would push into another committed region + debug_only(bool collided = false;) int const ind = find_covering_region_by_base(new_region.start()); MemRegion const old_region = _covered[ind]; assert(old_region.start() == new_region.start(), "just checking"); @@ -211,12 +213,36 @@ } // Align the end up to a page size (starts are already aligned). jbyte* const new_end = byte_after(new_region.last()); - HeapWord* const new_end_aligned = + HeapWord* new_end_aligned = (HeapWord*) align_size_up((uintptr_t)new_end, _page_size); assert(new_end_aligned >= (HeapWord*) new_end, "align up, but less"); + int ri = 0; + for (ri = 0; ri < _cur_covered_regions; ri++) { + if (ri != ind) { + if (_committed[ri].contains(new_end_aligned)) { + assert((new_end_aligned >= _committed[ri].start()) && + (_committed[ri].start() > _committed[ind].start()), + "New end of committed region is inconsistent"); + new_end_aligned = _committed[ri].start(); + assert(new_end_aligned > _committed[ind].start(), + "New end of committed region is before start"); + debug_only(collided = true;) + // Should only collide with 1 region + break; + } + } + } +#ifdef ASSERT + for (++ri; ri < _cur_covered_regions; ri++) { + assert(!_committed[ri].contains(new_end_aligned), + "New end of committed region is in a second committed region"); + } +#endif // The guard page is always committed and should not be committed over. - HeapWord* const new_end_for_commit = MIN2(new_end_aligned, _guard_region.start()); + HeapWord* const new_end_for_commit = MIN2(new_end_aligned, + _guard_region.start()); + if (new_end_for_commit > cur_committed.end()) { // Must commit new pages. MemRegion const new_committed = @@ -239,9 +265,11 @@ if (!uncommit_region.is_empty()) { if (!os::uncommit_memory((char*)uncommit_region.start(), uncommit_region.byte_size())) { - // Do better than this for Merlin - vm_exit_out_of_memory(uncommit_region.byte_size(), - "card table contraction"); + assert(false, "Card table contraction failed"); + // The call failed so don't change the end of the + // committed region. This is better than taking the + // VM down. + new_end_aligned = _committed[ind].end(); } } } @@ -257,8 +285,25 @@ } assert(index_for(new_region.last()) < (int) _guard_index, "The guard card will be overwritten"); - jbyte* const end = byte_after(new_region.last()); + // This line commented out cleans the newly expanded region and + // not the aligned up expanded region. + // jbyte* const end = byte_after(new_region.last()); + jbyte* const end = (jbyte*) new_end_for_commit; + assert((end >= byte_after(new_region.last())) || collided, + "Expect to be beyond new region unless impacting another region"); // do nothing if we resized downward. +#ifdef ASSERT + for (int ri = 0; ri < _cur_covered_regions; ri++) { + if (ri != ind) { + // The end of the new committed region should not + // be in any existing region unless it matches + // the start of the next region. + assert(!_committed[ri].contains(end) || + (_committed[ri].start() == (HeapWord*) end), + "Overlapping committed regions"); + } + } +#endif if (entry < end) { memset(entry, clean_card, pointer_delta(end, entry, sizeof(jbyte))); }