# HG changeset patch # User kvn # Date 1349456636 25200 # Node ID 685457683e86f7c941024d1f43819f08dcba6eb0 # Parent ca70b919819f370ba8efedec8199b31a799f2dca# Parent bf2edd3c9b0f316a67b81e6210d97b20024c226d Merge diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp Fri Oct 05 10:03:56 2012 -0700 @@ -1195,9 +1195,9 @@ set_promo_size(desired_promo_size); } -int CMSAdaptiveSizePolicy::compute_survivor_space_size_and_threshold( +uint CMSAdaptiveSizePolicy::compute_survivor_space_size_and_threshold( bool is_survivor_overflow, - int tenuring_threshold, + uint tenuring_threshold, size_t survivor_limit) { assert(survivor_limit >= generation_alignment(), "survivor_limit too small"); @@ -1315,7 +1315,7 @@ gclog_or_tty->print( " avg_promoted_padded_avg: %f" " avg_pretenured_padded_avg: %f" - " tenuring_thresh: %d" + " tenuring_thresh: %u" " target_size: " SIZE_FORMAT " survivor_limit: " SIZE_FORMAT, gch->gc_stats(1)->avg_promoted()->padded_average(), diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.hpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.hpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.hpp Fri Oct 05 10:03:56 2012 -0700 @@ -440,9 +440,9 @@ size_t max_eden_size); // Calculates new survivor space size; returns a new tenuring threshold // value. Stores new survivor size in _survivor_size. - virtual int compute_survivor_space_size_and_threshold( + virtual uint compute_survivor_space_size_and_threshold( bool is_survivor_overflow, - int tenuring_threshold, + uint tenuring_threshold, size_t survivor_limit); virtual void compute_tenured_generation_free_space(size_t cur_tenured_free, diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/g1/concurrentMark.cpp --- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Oct 05 10:03:56 2012 -0700 @@ -1188,29 +1188,14 @@ // liveness counting data. class CMCountDataClosureBase: public HeapRegionClosure { protected: + G1CollectedHeap* _g1h; ConcurrentMark* _cm; + CardTableModRefBS* _ct_bs; + BitMap* _region_bm; BitMap* _card_bm; - void set_card_bitmap_range(BitMap::idx_t start_idx, BitMap::idx_t last_idx) { - assert(start_idx <= last_idx, "sanity"); - - // Set the inclusive bit range [start_idx, last_idx]. - // For small ranges (up to 8 cards) use a simple loop; otherwise - // use par_at_put_range. - if ((last_idx - start_idx) < 8) { - for (BitMap::idx_t i = start_idx; i <= last_idx; i += 1) { - _card_bm->par_set_bit(i); - } - } else { - assert(last_idx < _card_bm->size(), "sanity"); - // Note BitMap::par_at_put_range() is exclusive. - BitMap::idx_t max_idx = MAX2(last_idx+1, _card_bm->size()); - _card_bm->par_at_put_range(start_idx, max_idx, true); - } - } - - // It takes a region that's not empty (i.e., it has at least one + // Takes a region that's not empty (i.e., it has at least one // live object in it and sets its corresponding bit on the region // bitmap to 1. If the region is "starts humongous" it will also set // to 1 the bits on the region bitmap that correspond to its @@ -1231,9 +1216,11 @@ } public: - CMCountDataClosureBase(ConcurrentMark *cm, + CMCountDataClosureBase(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm): - _cm(cm), _region_bm(region_bm), _card_bm(card_bm) { } + _g1h(g1h), _cm(g1h->concurrent_mark()), + _ct_bs((CardTableModRefBS*) (g1h->barrier_set())), + _region_bm(region_bm), _card_bm(card_bm) { } }; // Closure that calculates the # live objects per region. Used @@ -1243,9 +1230,9 @@ size_t _region_marked_bytes; public: - CalcLiveObjectsClosure(CMBitMapRO *bm, ConcurrentMark *cm, + CalcLiveObjectsClosure(CMBitMapRO *bm, G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm) : - CMCountDataClosureBase(cm, region_bm, card_bm), + CMCountDataClosureBase(g1h, region_bm, card_bm), _bm(bm), _region_marked_bytes(0) { } bool doHeapRegion(HeapRegion* hr) { @@ -1261,44 +1248,63 @@ return false; } - HeapWord* nextTop = hr->next_top_at_mark_start(); - HeapWord* start = hr->bottom(); - - assert(start <= hr->end() && start <= nextTop && nextTop <= hr->end(), + HeapWord* ntams = hr->next_top_at_mark_start(); + HeapWord* start = hr->bottom(); + + assert(start <= hr->end() && start <= ntams && ntams <= hr->end(), err_msg("Preconditions not met - " - "start: "PTR_FORMAT", nextTop: "PTR_FORMAT", end: "PTR_FORMAT, - start, nextTop, hr->end())); + "start: "PTR_FORMAT", ntams: "PTR_FORMAT", end: "PTR_FORMAT, + start, ntams, hr->end())); // Find the first marked object at or after "start". - start = _bm->getNextMarkedWordAddress(start, nextTop); + start = _bm->getNextMarkedWordAddress(start, ntams); size_t marked_bytes = 0; - while (start < nextTop) { + while (start < ntams) { oop obj = oop(start); int obj_sz = obj->size(); - HeapWord* obj_last = start + obj_sz - 1; + HeapWord* obj_end = start + obj_sz; BitMap::idx_t start_idx = _cm->card_bitmap_index_for(start); - BitMap::idx_t last_idx = _cm->card_bitmap_index_for(obj_last); - - // Set the bits in the card BM for this object (inclusive). - set_card_bitmap_range(start_idx, last_idx); + BitMap::idx_t end_idx = _cm->card_bitmap_index_for(obj_end); + + // Note: if we're looking at the last region in heap - obj_end + // could be actually just beyond the end of the heap; end_idx + // will then correspond to a (non-existent) card that is also + // just beyond the heap. + if (_g1h->is_in_g1_reserved(obj_end) && !_ct_bs->is_card_aligned(obj_end)) { + // end of object is not card aligned - increment to cover + // all the cards spanned by the object + end_idx += 1; + } + + // Set the bits in the card BM for the cards spanned by this object. + _cm->set_card_bitmap_range(_card_bm, start_idx, end_idx, true /* is_par */); // Add the size of this object to the number of marked bytes. marked_bytes += (size_t)obj_sz * HeapWordSize; // Find the next marked object after this one. - start = _bm->getNextMarkedWordAddress(obj_last + 1, nextTop); + start = _bm->getNextMarkedWordAddress(obj_end, ntams); } // Mark the allocated-since-marking portion... HeapWord* top = hr->top(); - if (nextTop < top) { - BitMap::idx_t start_idx = _cm->card_bitmap_index_for(nextTop); - BitMap::idx_t last_idx = _cm->card_bitmap_index_for(top - 1); - - set_card_bitmap_range(start_idx, last_idx); + if (ntams < top) { + BitMap::idx_t start_idx = _cm->card_bitmap_index_for(ntams); + BitMap::idx_t end_idx = _cm->card_bitmap_index_for(top); + + // Note: if we're looking at the last region in heap - top + // could be actually just beyond the end of the heap; end_idx + // will then correspond to a (non-existent) card that is also + // just beyond the heap. + if (_g1h->is_in_g1_reserved(top) && !_ct_bs->is_card_aligned(top)) { + // end of object is not card aligned - increment to cover + // all the cards spanned by the object + end_idx += 1; + } + _cm->set_card_bitmap_range(_card_bm, start_idx, end_idx, true /* is_par */); // This definitely means the region has live objects. set_bit_for_region(hr); @@ -1325,6 +1331,7 @@ // regions during the STW cleanup pause. class VerifyLiveObjectDataHRClosure: public HeapRegionClosure { + G1CollectedHeap* _g1h; ConcurrentMark* _cm; CalcLiveObjectsClosure _calc_cl; BitMap* _region_bm; // Region BM to be verified @@ -1337,14 +1344,14 @@ int _failures; public: - VerifyLiveObjectDataHRClosure(ConcurrentMark* cm, + VerifyLiveObjectDataHRClosure(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm, BitMap* exp_region_bm, BitMap* exp_card_bm, bool verbose) : - _cm(cm), - _calc_cl(_cm->nextMarkBitMap(), _cm, exp_region_bm, exp_card_bm), + _g1h(g1h), _cm(g1h->concurrent_mark()), + _calc_cl(_cm->nextMarkBitMap(), g1h, exp_region_bm, exp_card_bm), _region_bm(region_bm), _card_bm(card_bm), _verbose(verbose), _exp_region_bm(exp_region_bm), _exp_card_bm(exp_card_bm), _failures(0) { } @@ -1491,7 +1498,7 @@ void work(uint worker_id) { assert(worker_id < _n_workers, "invariant"); - VerifyLiveObjectDataHRClosure verify_cl(_cm, + VerifyLiveObjectDataHRClosure verify_cl(_g1h, _actual_region_bm, _actual_card_bm, _expected_region_bm, _expected_card_bm, @@ -1521,10 +1528,10 @@ class FinalCountDataUpdateClosure: public CMCountDataClosureBase { public: - FinalCountDataUpdateClosure(ConcurrentMark* cm, + FinalCountDataUpdateClosure(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm) : - CMCountDataClosureBase(cm, region_bm, card_bm) { } + CMCountDataClosureBase(g1h, region_bm, card_bm) { } bool doHeapRegion(HeapRegion* hr) { @@ -1548,24 +1555,29 @@ if (ntams < top) { // This definitely means the region has live objects. set_bit_for_region(hr); - } - - // Now set the bits for [ntams, top] - BitMap::idx_t start_idx = _cm->card_bitmap_index_for(ntams); - // set_card_bitmap_range() expects the last_idx to be with - // the range of the bit map (see assertion in set_card_bitmap_range()), - // so limit it to that range with this application of MIN2. - BitMap::idx_t last_idx = MIN2(_cm->card_bitmap_index_for(top), - _card_bm->size()-1); - if (start_idx < _card_bm->size()) { - set_card_bitmap_range(start_idx, last_idx); - } else { - // To reach here start_idx must be beyond the end of - // the bit map and last_idx must have been limited by - // the MIN2(). - assert(start_idx == last_idx + 1, - err_msg("Not beyond end start_idx " SIZE_FORMAT " last_idx " - SIZE_FORMAT, start_idx, last_idx)); + + // Now set the bits in the card bitmap for [ntams, top) + BitMap::idx_t start_idx = _cm->card_bitmap_index_for(ntams); + BitMap::idx_t end_idx = _cm->card_bitmap_index_for(top); + + // Note: if we're looking at the last region in heap - top + // could be actually just beyond the end of the heap; end_idx + // will then correspond to a (non-existent) card that is also + // just beyond the heap. + if (_g1h->is_in_g1_reserved(top) && !_ct_bs->is_card_aligned(top)) { + // end of object is not card aligned - increment to cover + // all the cards spanned by the object + end_idx += 1; + } + + assert(end_idx <= _card_bm->size(), + err_msg("oob: end_idx= "SIZE_FORMAT", bitmap size= "SIZE_FORMAT, + end_idx, _card_bm->size())); + assert(start_idx < _card_bm->size(), + err_msg("oob: start_idx= "SIZE_FORMAT", bitmap size= "SIZE_FORMAT, + start_idx, _card_bm->size())); + + _cm->set_card_bitmap_range(_card_bm, start_idx, end_idx, true /* is_par */); } // Set the bit for the region if it contains live data @@ -1606,7 +1618,7 @@ void work(uint worker_id) { assert(worker_id < _n_workers, "invariant"); - FinalCountDataUpdateClosure final_update_cl(_cm, + FinalCountDataUpdateClosure final_update_cl(_g1h, _actual_region_bm, _actual_card_bm); @@ -2846,20 +2858,19 @@ // Aggregate the counting data that was constructed concurrently // with marking. class AggregateCountDataHRClosure: public HeapRegionClosure { + G1CollectedHeap* _g1h; ConcurrentMark* _cm; + CardTableModRefBS* _ct_bs; BitMap* _cm_card_bm; size_t _max_task_num; public: - AggregateCountDataHRClosure(ConcurrentMark *cm, + AggregateCountDataHRClosure(G1CollectedHeap* g1h, BitMap* cm_card_bm, size_t max_task_num) : - _cm(cm), _cm_card_bm(cm_card_bm), - _max_task_num(max_task_num) { } - - bool is_card_aligned(HeapWord* p) { - return ((uintptr_t(p) & (CardTableModRefBS::card_size - 1)) == 0); - } + _g1h(g1h), _cm(g1h->concurrent_mark()), + _ct_bs((CardTableModRefBS*) (g1h->barrier_set())), + _cm_card_bm(cm_card_bm), _max_task_num(max_task_num) { } bool doHeapRegion(HeapRegion* hr) { if (hr->continuesHumongous()) { @@ -2890,16 +2901,23 @@ return false; } - assert(is_card_aligned(start), "sanity"); - assert(is_card_aligned(end), "sanity"); + // 'start' should be in the heap. + assert(_g1h->is_in_g1_reserved(start) && _ct_bs->is_card_aligned(start), "sanity"); + // 'end' *may* be just beyone the end of the heap (if hr is the last region) + assert(!_g1h->is_in_g1_reserved(end) || _ct_bs->is_card_aligned(end), "sanity"); BitMap::idx_t start_idx = _cm->card_bitmap_index_for(start); BitMap::idx_t limit_idx = _cm->card_bitmap_index_for(limit); BitMap::idx_t end_idx = _cm->card_bitmap_index_for(end); - // If ntams is not card aligned then we bump the index for - // limit so that we get the card spanning ntams. - if (!is_card_aligned(limit)) { + // If ntams is not card aligned then we bump card bitmap index + // for limit so that we get the all the cards spanned by + // the object ending at ntams. + // Note: if this is the last region in the heap then ntams + // could be actually just beyond the end of the the heap; + // limit_idx will then correspond to a (non-existent) card + // that is also outside the heap. + if (_g1h->is_in_g1_reserved(limit) && !_ct_bs->is_card_aligned(limit)) { limit_idx += 1; } @@ -2928,7 +2946,7 @@ // BitMap::get_next_one_offset() can handle the case when // its left_offset parameter is greater than its right_offset - // parameter. If does, however, have an early exit if + // parameter. It does, however, have an early exit if // left_offset == right_offset. So let's limit the value // passed in for left offset here. BitMap::idx_t next_idx = MIN2(scan_idx + 1, limit_idx); @@ -2964,7 +2982,7 @@ _active_workers(n_workers) { } void work(uint worker_id) { - AggregateCountDataHRClosure cl(_cm, _cm_card_bm, _max_task_num); + AggregateCountDataHRClosure cl(_g1h, _cm_card_bm, _max_task_num); if (G1CollectedHeap::use_parallel_gc_threads()) { _g1h->heap_region_par_iterate_chunked(&cl, worker_id, diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/g1/concurrentMark.hpp --- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp Fri Oct 05 10:03:56 2012 -0700 @@ -806,7 +806,14 @@ return _MARKING_VERBOSE_ && _verbose_level >= high_verbose; } - // Counting data structure accessors + // Liveness counting + + // Utility routine to set an exclusive range of cards on the given + // card liveness bitmap + inline void set_card_bitmap_range(BitMap* card_bm, + BitMap::idx_t start_idx, + BitMap::idx_t end_idx, + bool is_par); // Returns the card number of the bottom of the G1 heap. // Used in biasing indices into accounting card bitmaps. diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp --- a/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp Fri Oct 05 10:03:56 2012 -0700 @@ -28,6 +28,42 @@ #include "gc_implementation/g1/concurrentMark.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" +// Utility routine to set an exclusive range of cards on the given +// card liveness bitmap +inline void ConcurrentMark::set_card_bitmap_range(BitMap* card_bm, + BitMap::idx_t start_idx, + BitMap::idx_t end_idx, + bool is_par) { + + // Set the exclusive bit range [start_idx, end_idx). + assert((end_idx - start_idx) > 0, "at least one card"); + assert(end_idx <= card_bm->size(), "sanity"); + + // Silently clip the end index + end_idx = MIN2(end_idx, card_bm->size()); + + // For small ranges use a simple loop; otherwise use set_range or + // use par_at_put_range (if parallel). The range is made up of the + // cards that are spanned by an object/mem region so 8 cards will + // allow up to object sizes up to 4K to be handled using the loop. + if ((end_idx - start_idx) <= 8) { + for (BitMap::idx_t i = start_idx; i < end_idx; i += 1) { + if (is_par) { + card_bm->par_set_bit(i); + } else { + card_bm->set_bit(i); + } + } + } else { + // Note BitMap::par_at_put_range() and BitMap::set_range() are exclusive. + if (is_par) { + card_bm->par_at_put_range(start_idx, end_idx, true); + } else { + card_bm->set_range(start_idx, end_idx); + } + } +} + // Returns the index in the liveness accounting card bitmap // for the given address inline BitMap::idx_t ConcurrentMark::card_bitmap_index_for(HeapWord* addr) { @@ -35,7 +71,6 @@ // by the card shift -- address 0 corresponds to card number 0. One // must subtract the card num of the bottom of the heap to obtain a // card table index. - intptr_t card_num = intptr_t(uintptr_t(addr) >> CardTableModRefBS::card_shift); return card_num - heap_bottom_card_num(); } @@ -46,8 +81,10 @@ size_t* marked_bytes_array, BitMap* task_card_bm) { G1CollectedHeap* g1h = _g1h; + CardTableModRefBS* ct_bs = (CardTableModRefBS*) (g1h->barrier_set()); + HeapWord* start = mr.start(); - HeapWord* last = mr.last(); + HeapWord* end = mr.end(); size_t region_size_bytes = mr.byte_size(); uint index = hr->hrs_index(); @@ -61,24 +98,21 @@ marked_bytes_array[index] += region_size_bytes; BitMap::idx_t start_idx = card_bitmap_index_for(start); - BitMap::idx_t last_idx = card_bitmap_index_for(last); + BitMap::idx_t end_idx = card_bitmap_index_for(end); - // The card bitmap is task/worker specific => no need to use 'par' routines. - // Set bits in the inclusive bit range [start_idx, last_idx]. - // - // For small ranges use a simple loop; otherwise use set_range - // The range are the cards that are spanned by the object/region - // so 8 cards will allow objects/regions up to 4K to be handled - // using the loop. - if ((last_idx - start_idx) <= 8) { - for (BitMap::idx_t i = start_idx; i <= last_idx; i += 1) { - task_card_bm->set_bit(i); - } - } else { - assert(last_idx < task_card_bm->size(), "sanity"); - // Note: BitMap::set_range() is exclusive. - task_card_bm->set_range(start_idx, last_idx+1); + // Note: if we're looking at the last region in heap - end + // could be actually just beyond the end of the heap; end_idx + // will then correspond to a (non-existent) card that is also + // just beyond the heap. + if (g1h->is_in_g1_reserved(end) && !ct_bs->is_card_aligned(end)) { + // end of region is not card aligned - incremement to cover + // all the cards spanned by the region. + end_idx += 1; } + // The card bitmap is task/worker specific => no need to use + // the 'par' BitMap routines. + // Set bits in the exclusive bit range [start_idx, end_idx). + set_card_bitmap_range(task_card_bm, start_idx, end_idx, false /* is_par */); } // Counts the given memory region in the task/worker counting diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Oct 05 10:03:56 2012 -0700 @@ -4151,7 +4151,7 @@ } } -void G1CollectedHeap::release_gc_alloc_regions() { +void G1CollectedHeap::release_gc_alloc_regions(uint no_of_gc_workers) { _survivor_gc_alloc_region.release(); // If we have an old GC alloc region to release, we'll save it in // _retained_old_gc_alloc_region. If we don't @@ -4161,8 +4161,8 @@ _retained_old_gc_alloc_region = _old_gc_alloc_region.release(); if (ResizePLAB) { - _survivor_plab_stats.adjust_desired_plab_sz(); - _old_plab_stats.adjust_desired_plab_sz(); + _survivor_plab_stats.adjust_desired_plab_sz(no_of_gc_workers); + _old_plab_stats.adjust_desired_plab_sz(no_of_gc_workers); } } @@ -5427,7 +5427,7 @@ }; // Weak Reference processing during an evacuation pause (part 1). -void G1CollectedHeap::process_discovered_references() { +void G1CollectedHeap::process_discovered_references(uint no_of_gc_workers) { double ref_proc_start = os::elapsedTime(); ReferenceProcessor* rp = _ref_processor_stw; @@ -5454,15 +5454,14 @@ // referents points to another object which is also referenced by an // object discovered by the STW ref processor. - uint active_workers = (G1CollectedHeap::use_parallel_gc_threads() ? - workers()->active_workers() : 1); - assert(!G1CollectedHeap::use_parallel_gc_threads() || - active_workers == workers()->active_workers(), - "Need to reset active_workers"); - - set_par_threads(active_workers); - G1ParPreserveCMReferentsTask keep_cm_referents(this, active_workers, _task_queues); + no_of_gc_workers == workers()->active_workers(), + "Need to reset active GC workers"); + + set_par_threads(no_of_gc_workers); + G1ParPreserveCMReferentsTask keep_cm_referents(this, + no_of_gc_workers, + _task_queues); if (G1CollectedHeap::use_parallel_gc_threads()) { workers()->run_task(&keep_cm_referents); @@ -5528,10 +5527,10 @@ NULL); } else { // Parallel reference processing - assert(rp->num_q() == active_workers, "sanity"); - assert(active_workers <= rp->max_num_q(), "sanity"); - - G1STWRefProcTaskExecutor par_task_executor(this, workers(), _task_queues, active_workers); + assert(rp->num_q() == no_of_gc_workers, "sanity"); + assert(no_of_gc_workers <= rp->max_num_q(), "sanity"); + + G1STWRefProcTaskExecutor par_task_executor(this, workers(), _task_queues, no_of_gc_workers); rp->process_discovered_references(&is_alive, &keep_alive, &drain_queue, &par_task_executor); } @@ -5546,7 +5545,7 @@ } // Weak Reference processing during an evacuation pause (part 2). -void G1CollectedHeap::enqueue_discovered_references() { +void G1CollectedHeap::enqueue_discovered_references(uint no_of_gc_workers) { double ref_enq_start = os::elapsedTime(); ReferenceProcessor* rp = _ref_processor_stw; @@ -5560,13 +5559,12 @@ } else { // Parallel reference enqueuing - uint active_workers = (ParallelGCThreads > 0 ? workers()->active_workers() : 1); - assert(active_workers == workers()->active_workers(), - "Need to reset active_workers"); - assert(rp->num_q() == active_workers, "sanity"); - assert(active_workers <= rp->max_num_q(), "sanity"); - - G1STWRefProcTaskExecutor par_task_executor(this, workers(), _task_queues, active_workers); + assert(no_of_gc_workers == workers()->active_workers(), + "Need to reset active workers"); + assert(rp->num_q() == no_of_gc_workers, "sanity"); + assert(no_of_gc_workers <= rp->max_num_q(), "sanity"); + + G1STWRefProcTaskExecutor par_task_executor(this, workers(), _task_queues, no_of_gc_workers); rp->enqueue_discovered_references(&par_task_executor); } @@ -5658,7 +5656,7 @@ // as we may have to copy some 'reachable' referent // objects (and their reachable sub-graphs) that were // not copied during the pause. - process_discovered_references(); + process_discovered_references(n_workers); // Weak root processing. // Note: when JSR 292 is enabled and code blobs can contain @@ -5670,7 +5668,7 @@ JNIHandles::weak_oops_do(&is_alive, &keep_alive); } - release_gc_alloc_regions(); + release_gc_alloc_regions(n_workers); g1_rem_set()->cleanup_after_oops_into_collection_set_do(); concurrent_g1_refine()->clear_hot_cache(); @@ -5694,7 +5692,7 @@ // will log these updates (and dirty their associated // cards). We need these updates logged to update any // RSets. - enqueue_discovered_references(); + enqueue_discovered_references(n_workers); if (G1DeferredRSUpdate) { RedirtyLoggedCardTableEntryFastClosure redirty; diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Oct 05 10:03:56 2012 -0700 @@ -326,7 +326,7 @@ void init_gc_alloc_regions(); // It releases the GC alloc regions at the end of a GC. - void release_gc_alloc_regions(); + void release_gc_alloc_regions(uint no_of_gc_workers); // It does any cleanup that needs to be done on the GC alloc regions // before a Full GC. @@ -652,11 +652,11 @@ // Process any reference objects discovered during // an incremental evacuation pause. - void process_discovered_references(); + void process_discovered_references(uint no_of_gc_workers); // Enqueue any remaining discovered references // after processing. - void enqueue_discovered_references(); + void enqueue_discovered_references(uint no_of_gc_workers); public: diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Fri Oct 05 10:03:56 2012 -0700 @@ -840,8 +840,8 @@ // // Current tenuring threshold, set to 0 if the collector reaches the - // maximum amount of suvivors regions. - int _tenuring_threshold; + // maximum amount of survivors regions. + uint _tenuring_threshold; // The limit on the number of regions allocated for survivors. uint _max_survivor_regions; @@ -851,7 +851,7 @@ size_t _survivor_bytes_before_gc; size_t _capacity_before_gc; - // The amount of survor regions after a collection. + // The amount of survivor regions after a collection. uint _recorded_survivor_regions; // List of survivor regions. HeapRegion* _recorded_survivor_head; @@ -862,7 +862,7 @@ public: inline GCAllocPurpose - evacuation_destination(HeapRegion* src_region, int age, size_t word_sz) { + evacuation_destination(HeapRegion* src_region, uint age, size_t word_sz) { if (age < _tenuring_threshold && src_region->is_young()) { return GCAllocForSurvived; } else { diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/parNew/parNewGeneration.cpp --- a/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Fri Oct 05 10:03:56 2012 -0700 @@ -1037,7 +1037,7 @@ adjust_desired_tenuring_threshold(); if (ResizePLAB) { - plab_stats()->adjust_desired_plab_sz(); + plab_stats()->adjust_desired_plab_sz(n_workers); } if (PrintGC && !PrintGCDetails) { diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp Fri Oct 05 10:03:56 2012 -0700 @@ -121,103 +121,12 @@ // We get passed the space_top value to prevent us from traversing into // the old_gen promotion labs, which cannot be safely parsed. -void CardTableExtension::scavenge_contents(ObjectStartArray* start_array, - MutableSpace* sp, - HeapWord* space_top, - PSPromotionManager* pm) -{ - assert(start_array != NULL && sp != NULL && pm != NULL, "Sanity"); - assert(start_array->covered_region().contains(sp->used_region()), - "ObjectStartArray does not cover space"); - if (sp->not_empty()) { - oop* sp_top = (oop*)space_top; - oop* prev_top = NULL; - jbyte* current_card = byte_for(sp->bottom()); - jbyte* end_card = byte_for(sp_top - 1); // sp_top is exclusive - // scan card marking array - while (current_card <= end_card) { - jbyte value = *current_card; - // skip clean cards - if (card_is_clean(value)) { - current_card++; - } else { - // we found a non-clean card - jbyte* first_nonclean_card = current_card++; - oop* bottom = (oop*)addr_for(first_nonclean_card); - // find object starting on card - oop* bottom_obj = (oop*)start_array->object_start((HeapWord*)bottom); - // bottom_obj = (oop*)start_array->object_start((HeapWord*)bottom); - assert(bottom_obj <= bottom, "just checking"); - // make sure we don't scan oops we already looked at - if (bottom < prev_top) bottom = prev_top; - // figure out when to stop scanning - jbyte* first_clean_card; - oop* top; - bool restart_scanning; - do { - restart_scanning = false; - // find a clean card - while (current_card <= end_card) { - value = *current_card; - if (card_is_clean(value)) break; - current_card++; - } - // check if we reached the end, if so we are done - if (current_card >= end_card) { - first_clean_card = end_card + 1; - current_card++; - top = sp_top; - } else { - // we have a clean card, find object starting on that card - first_clean_card = current_card++; - top = (oop*)addr_for(first_clean_card); - oop* top_obj = (oop*)start_array->object_start((HeapWord*)top); - // top_obj = (oop*)start_array->object_start((HeapWord*)top); - assert(top_obj <= top, "just checking"); - if (oop(top_obj)->is_objArray() || oop(top_obj)->is_typeArray()) { - // an arrayOop is starting on the clean card - since we do exact store - // checks for objArrays we are done - } else { - // otherwise, it is possible that the object starting on the clean card - // spans the entire card, and that the store happened on a later card. - // figure out where the object ends - top = top_obj + oop(top_obj)->size(); - jbyte* top_card = CardTableModRefBS::byte_for(top - 1); // top is exclusive - if (top_card > first_clean_card) { - // object ends a different card - current_card = top_card + 1; - if (card_is_clean(*top_card)) { - // the ending card is clean, we are done - first_clean_card = top_card; - } else { - // the ending card is not clean, continue scanning at start of do-while - restart_scanning = true; - } - } else { - // object ends on the clean card, we are done. - assert(first_clean_card == top_card, "just checking"); - } - } - } - } while (restart_scanning); - // we know which cards to scan, now clear them - while (first_nonclean_card < first_clean_card) { - *first_nonclean_card++ = clean_card; - } - // scan oops in objects - do { - oop(bottom_obj)->push_contents(pm); - bottom_obj += oop(bottom_obj)->size(); - assert(bottom_obj <= sp_top, "just checking"); - } while (bottom_obj < top); - pm->drain_stacks_cond_depth(); - // remember top oop* scanned - prev_top = top; - } - } - } -} +// Do not call this method if the space is empty. +// It is a waste to start tasks and get here only to +// do no work. If this method needs to be called +// when the space is empty, fix the calculation of +// end_card to allow sp_top == sp->bottom(). void CardTableExtension::scavenge_contents_parallel(ObjectStartArray* start_array, MutableSpace* sp, @@ -228,10 +137,11 @@ int ssize = 128; // Naked constant! Work unit = 64k. int dirty_card_count = 0; + // It is a waste to get here if empty. + assert(sp->bottom() < sp->top(), "Should not be called if empty"); oop* sp_top = (oop*)space_top; - oop* sp_last = sp->bottom() == space_top ? sp_top : sp_top - 1; jbyte* start_card = byte_for(sp->bottom()); - jbyte* end_card = byte_for(sp_last) + 1; + jbyte* end_card = byte_for(sp_top - 1) + 1; oop* last_scanned = NULL; // Prevent scanning objects more than once // The width of the stripe ssize*stripe_total must be // consistent with the number of stripes so that the complete slice @@ -255,6 +165,16 @@ HeapWord* slice_start = addr_for(worker_start_card); HeapWord* slice_end = MIN2((HeapWord*) sp_top, addr_for(worker_end_card)); +#ifdef ASSERT + if (GCWorkerDelayMillis > 0) { + // Delay 1 worker so that it proceeds after all the work + // has been completed. + if (stripe_number < 2) { + os::sleep(Thread::current(), GCWorkerDelayMillis, false); + } + } +#endif + // If there are not objects starting within the chunk, skip it. if (!start_array->object_starts_in_range(slice_start, slice_end)) { continue; diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.hpp --- a/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.hpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.hpp Fri Oct 05 10:03:56 2012 -0700 @@ -60,11 +60,6 @@ // BarrierSet::Name kind() { return BarrierSet::CardTableExtension; } // Scavenge support - void scavenge_contents(ObjectStartArray* start_array, - MutableSpace* sp, - HeapWord* space_top, - PSPromotionManager* pm); - void scavenge_contents_parallel(ObjectStartArray* start_array, MutableSpace* sp, HeapWord* space_top, diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp Fri Oct 05 10:03:56 2012 -0700 @@ -941,9 +941,9 @@ return promo_heap_delta; } -int PSAdaptiveSizePolicy::compute_survivor_space_size_and_threshold( +uint PSAdaptiveSizePolicy::compute_survivor_space_size_and_threshold( bool is_survivor_overflow, - int tenuring_threshold, + uint tenuring_threshold, size_t survivor_limit) { assert(survivor_limit >= _intra_generation_alignment, "survivor_limit too small"); diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp --- a/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp Fri Oct 05 10:03:56 2012 -0700 @@ -353,9 +353,9 @@ // Calculates new survivor space size; returns a new tenuring threshold // value. Stores new survivor size in _survivor_size. - int compute_survivor_space_size_and_threshold(bool is_survivor_overflow, - int tenuring_threshold, - size_t survivor_limit); + uint compute_survivor_space_size_and_threshold(bool is_survivor_overflow, + uint tenuring_threshold, + size_t survivor_limit); // Return the maximum size of a survivor space if the young generation were of // size gen_size. diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp --- a/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp Fri Oct 05 10:03:56 2012 -0700 @@ -85,7 +85,7 @@ if (!promote_immediately) { // Find the objects age, MT safe. - int age = (test_mark->has_displaced_mark_helper() /* o->has_displaced_mark() */) ? + uint age = (test_mark->has_displaced_mark_helper() /* o->has_displaced_mark() */) ? test_mark->displaced_mark_helper()->age() : test_mark->age(); // Try allocating obj in to-space (unless too old) @@ -136,6 +136,13 @@ HeapWord* lab_base = old_gen()->cas_allocate(OldPLABSize); if(lab_base != NULL) { +#ifdef ASSERT + // Delay the initialization of the promotion lab (plab). + // This exposes uninitialized plabs to card table processing. + if (GCWorkerDelayMillis > 0) { + os::sleep(Thread::current(), GCWorkerDelayMillis, false); + } +#endif _old_lab.initialize(MemRegion(lab_base, OldPLABSize)); // Try the old lab allocation again. new_obj = (oop) _old_lab.allocate(new_obj_size); diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Fri Oct 05 10:03:56 2012 -0700 @@ -59,7 +59,7 @@ ReferenceProcessor* PSScavenge::_ref_processor = NULL; CardTableExtension* PSScavenge::_card_table = NULL; bool PSScavenge::_survivor_overflow = false; -int PSScavenge::_tenuring_threshold = 0; +uint PSScavenge::_tenuring_threshold = 0; HeapWord* PSScavenge::_young_generation_boundary = NULL; elapsedTimer PSScavenge::_accumulated_time; Stack PSScavenge::_preserved_mark_stack; @@ -395,9 +395,13 @@ GCTaskQueue* q = GCTaskQueue::create(); - uint stripe_total = active_workers; - for(uint i=0; i < stripe_total; i++) { - q->enqueue(new OldToYoungRootsTask(old_gen, old_top, i, stripe_total)); + if (!old_gen->object_space()->is_empty()) { + // There are only old-to-young pointers if there are objects + // in the old gen. + uint stripe_total = active_workers; + for(uint i=0; i < stripe_total; i++) { + q->enqueue(new OldToYoungRootsTask(old_gen, old_top, i, stripe_total)); + } } q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::universe)); @@ -525,7 +529,7 @@ if (PrintTenuringDistribution) { gclog_or_tty->cr(); - gclog_or_tty->print_cr("Desired survivor size %ld bytes, new threshold %d (max %d)", + gclog_or_tty->print_cr("Desired survivor size %ld bytes, new threshold %u (max %u)", size_policy->calculated_survivor_size_in_bytes(), _tenuring_threshold, MaxTenuringThreshold); } diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/parallelScavenge/psScavenge.hpp --- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.hpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.hpp Fri Oct 05 10:03:56 2012 -0700 @@ -66,14 +66,14 @@ static PSIsAliveClosure _is_alive_closure; // Closure used for reference processing static CardTableExtension* _card_table; // We cache the card table for fast access. static bool _survivor_overflow; // Overflow this collection - static int _tenuring_threshold; // tenuring threshold for next scavenge + static uint _tenuring_threshold; // tenuring threshold for next scavenge static elapsedTimer _accumulated_time; // total time spent on scavenge static HeapWord* _young_generation_boundary; // The lowest address possible for the young_gen. // This is used to decide if an oop should be scavenged, // cards should be marked, etc. static Stack _preserved_mark_stack; // List of marks to be restored after failed promotion static Stack _preserved_oop_stack; // List of oops that need their mark restored. - static CollectorCounters* _counters; // collector performance counters + static CollectorCounters* _counters; // collector performance counters static bool _promotion_failed; static void clean_up_failed_promotion(); @@ -88,7 +88,7 @@ public: // Accessors - static int tenuring_threshold() { return _tenuring_threshold; } + static uint tenuring_threshold() { return _tenuring_threshold; } static elapsedTimer* accumulated_time() { return &_accumulated_time; } static bool promotion_failed() { return _promotion_failed; } static int consecutive_skipped_scavenges() diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp Fri Oct 05 10:03:56 2012 -0700 @@ -165,35 +165,13 @@ } // -// SerialOldToYoungRootsTask -// - -void SerialOldToYoungRootsTask::do_it(GCTaskManager* manager, uint which) { - assert(_gen != NULL, "Sanity"); - assert(_gen->object_space()->contains(_gen_top) || _gen_top == _gen->object_space()->top(), "Sanity"); - - { - PSPromotionManager* pm = PSPromotionManager::gc_thread_promotion_manager(which); - - assert(Universe::heap()->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); - CardTableExtension* card_table = (CardTableExtension *)Universe::heap()->barrier_set(); - // FIX ME! Assert that card_table is the type we believe it to be. - - card_table->scavenge_contents(_gen->start_array(), - _gen->object_space(), - _gen_top, - pm); - - // Do the real work - pm->drain_stacks(false); - } -} - -// // OldToYoungRootsTask // void OldToYoungRootsTask::do_it(GCTaskManager* manager, uint which) { + // There are not old-to-young pointers if the old gen is empty. + assert(!_gen->object_space()->is_empty(), + "Should not be called is there is no work"); assert(_gen != NULL, "Sanity"); assert(_gen->object_space()->contains(_gen_top) || _gen_top == _gen->object_space()->top(), "Sanity"); assert(_stripe_number < ParallelGCThreads, "Sanity"); diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/parallelScavenge/psTasks.hpp --- a/src/share/vm/gc_implementation/parallelScavenge/psTasks.hpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psTasks.hpp Fri Oct 05 10:03:56 2012 -0700 @@ -113,25 +113,6 @@ }; // -// SerialOldToYoungRootsTask -// -// This task is used to scan for roots in the perm gen - -class SerialOldToYoungRootsTask : public GCTask { - private: - PSOldGen* _gen; - HeapWord* _gen_top; - - public: - SerialOldToYoungRootsTask(PSOldGen *gen, HeapWord* gen_top) : - _gen(gen), _gen_top(gen_top) { } - - char* name() { return (char *)"serial-old-to-young-roots-task"; } - - virtual void do_it(GCTaskManager* manager, uint which); -}; - -// // OldToYoungRootsTask // // This task is used to scan old to young roots in parallel diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp --- a/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp Fri Oct 05 10:03:56 2012 -0700 @@ -642,7 +642,7 @@ bool AdaptiveSizePolicy::print_adaptive_size_policy_on( outputStream* st, - int tenuring_threshold_arg) const { + uint tenuring_threshold_arg) const { if (!AdaptiveSizePolicy::print_adaptive_size_policy_on(st)) { return false; } @@ -663,7 +663,7 @@ assert(!tenuring_threshold_change(), "(no change was attempted)"); } if (tenuring_threshold_changed) { - st->print_cr("%d", tenuring_threshold_arg); + st->print_cr("%u", tenuring_threshold_arg); } return true; } diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/shared/adaptiveSizePolicy.hpp --- a/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.hpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.hpp Fri Oct 05 10:03:56 2012 -0700 @@ -489,8 +489,8 @@ // Printing support virtual bool print_adaptive_size_policy_on(outputStream* st) const; - bool print_adaptive_size_policy_on(outputStream* st, int - tenuring_threshold) const; + bool print_adaptive_size_policy_on(outputStream* st, + uint tenuring_threshold) const; }; // Class that can be used to print information about the diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/shared/ageTable.cpp --- a/src/share/vm/gc_implementation/shared/ageTable.cpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/shared/ageTable.cpp Fri Oct 05 10:03:56 2012 -0700 @@ -78,10 +78,10 @@ } } -int ageTable::compute_tenuring_threshold(size_t survivor_capacity) { +uint ageTable::compute_tenuring_threshold(size_t survivor_capacity) { size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100); size_t total = 0; - int age = 1; + uint age = 1; assert(sizes[0] == 0, "no objects with age zero should be recorded"); while (age < table_size) { total += sizes[age]; @@ -90,13 +90,13 @@ if (total > desired_survivor_size) break; age++; } - int result = age < MaxTenuringThreshold ? age : MaxTenuringThreshold; + uint result = age < MaxTenuringThreshold ? age : MaxTenuringThreshold; if (PrintTenuringDistribution || UsePerfData) { if (PrintTenuringDistribution) { gclog_or_tty->cr(); - gclog_or_tty->print_cr("Desired survivor size %ld bytes, new threshold %d (max %d)", + gclog_or_tty->print_cr("Desired survivor size %ld bytes, new threshold %u (max %u)", desired_survivor_size*oopSize, result, MaxTenuringThreshold); } @@ -106,7 +106,7 @@ total += sizes[age]; if (sizes[age] > 0) { if (PrintTenuringDistribution) { - gclog_or_tty->print_cr("- age %3d: %10ld bytes, %10ld total", + gclog_or_tty->print_cr("- age %3u: %10ld bytes, %10ld total", age, sizes[age]*oopSize, total*oopSize); } } diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/shared/ageTable.hpp --- a/src/share/vm/gc_implementation/shared/ageTable.hpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/shared/ageTable.hpp Fri Oct 05 10:03:56 2012 -0700 @@ -55,7 +55,7 @@ // add entry void add(oop p, size_t oop_size) { - int age = p->age(); + uint age = p->age(); assert(age > 0 && age < table_size, "invalid age of object"); sizes[age] += oop_size; } @@ -66,7 +66,7 @@ void merge_par(ageTable* subTable); // calculate new tenuring threshold based on age information - int compute_tenuring_threshold(size_t survivor_capacity); + uint compute_tenuring_threshold(size_t survivor_capacity); private: PerfVariable* _perf_sizes[table_size]; diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/shared/gcAdaptivePolicyCounters.hpp --- a/src/share/vm/gc_implementation/shared/gcAdaptivePolicyCounters.hpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/shared/gcAdaptivePolicyCounters.hpp Fri Oct 05 10:03:56 2012 -0700 @@ -188,7 +188,7 @@ inline void update_survivor_overflowed(bool survivor_overflowed) { _survivor_overflowed_counter->set_value(survivor_overflowed); } - inline void update_tenuring_threshold(int threshold) { + inline void update_tenuring_threshold(uint threshold) { tenuring_threshold()->set_value(threshold); } inline void update_increment_tenuring_threshold_for_gc_cost() { diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/shared/parGCAllocBuffer.cpp --- a/src/share/vm/gc_implementation/shared/parGCAllocBuffer.cpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/shared/parGCAllocBuffer.cpp Fri Oct 05 10:03:56 2012 -0700 @@ -87,7 +87,7 @@ // Compute desired plab size and latch result for later // use. This should be called once at the end of parallel // scavenge; it clears the sensor accumulators. -void PLABStats::adjust_desired_plab_sz() { +void PLABStats::adjust_desired_plab_sz(uint no_of_gc_workers) { assert(ResizePLAB, "Not set"); if (_allocated == 0) { assert(_unused == 0, @@ -107,7 +107,7 @@ target_refills = 1; } _used = _allocated - _wasted - _unused; - size_t plab_sz = _used/(target_refills*ParallelGCThreads); + size_t plab_sz = _used/(target_refills*no_of_gc_workers); if (PrintPLAB) gclog_or_tty->print(" (plab_sz = %d ", plab_sz); // Take historical weighted average _filter.sample(plab_sz); diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp --- a/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp Fri Oct 05 10:03:56 2012 -0700 @@ -204,7 +204,8 @@ return _desired_plab_sz; } - void adjust_desired_plab_sz(); // filter computation, latches output to + void adjust_desired_plab_sz(uint no_of_gc_workers); + // filter computation, latches output to // _desired_plab_sz, clears sensor accumulators void add_allocated(size_t v) { diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/gc_implementation/shared/vmGCOperations.cpp --- a/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Fri Oct 05 10:03:56 2012 -0700 @@ -198,8 +198,6 @@ CollectedHeap* heap = Universe::heap(); GCCauseSetter gccs(heap, _gc_cause); - bool do_cms_concurrent = false; - // Check again if the space is available. Another thread // may have similarly failed a metadata allocation and induced // a GC that freed space for the allocation. @@ -208,23 +206,25 @@ } if (_result == NULL) { - if (!UseConcMarkSweepGC) { - // Don't clear the soft refs the first time. + if (UseConcMarkSweepGC) { + if (CMSClassUnloadingEnabled) { + MetaspaceGC::set_should_concurrent_collect(true); + } + // For CMS expand since the collection is going to be concurrent. + _result = + _loader_data->metaspace_non_null()->expand_and_allocate(_size, _mdtype); + } + if (_result == NULL) { + // Don't clear the soft refs. This GC is for reclaiming metadata + // and is unrelated to the fullness of the Java heap which should + // be the criteria for clearing SoftReferences. + if (Verbose && PrintGCDetails && UseConcMarkSweepGC) { + gclog_or_tty->print_cr("\nCMS full GC for Metaspace"); + } heap->collect_as_vm_thread(GCCause::_metadata_GC_threshold); _result = _loader_data->metaspace_non_null()->allocate(_size, _mdtype); - // Don't do this for now - // This seems too costly to do a second full GC - // Let the metaspace grow instead - // if (_result == NULL) { - // // If allocation fails again, clear soft refs - // heap->collect_as_vm_thread(GCCause::_last_ditch_collection); - // _result = _loader_data->metaspace_non_null()->allocate(_size, _mdtype); - // } - } else { - MetaspaceGC::set_should_concurrent_collect(true); - do_cms_concurrent = true; } - if (_result == NULL) { + if (_result == NULL && !UseConcMarkSweepGC /* CMS already tried */) { // If still failing, allow the Metaspace to expand. // See delta_capacity_until_GC() for explanation of the // amount of the expansion. @@ -233,18 +233,10 @@ _result = _loader_data->metaspace_non_null()->expand_and_allocate(_size, _mdtype); - if (do_cms_concurrent && _result == NULL) { - // Rather than fail with a metaspace out-of-memory, do a full - // GC for CMS. - heap->collect_as_vm_thread(GCCause::_metadata_GC_threshold); - _result = _loader_data->metaspace_non_null()->allocate(_size, _mdtype); - } - if (_result == NULL) { - if (PrintGCDetails) { - gclog_or_tty->print_cr("\nAfter Metaspace GC failed to allocate size " - SIZE_FORMAT, _size); - } - } + } + if (Verbose && PrintGCDetails && _result == NULL) { + gclog_or_tty->print_cr("\nAfter Metaspace GC failed to allocate size " + SIZE_FORMAT, _size); } } diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/memory/defNewGeneration.hpp --- a/src/share/vm/memory/defNewGeneration.hpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/memory/defNewGeneration.hpp Fri Oct 05 10:03:56 2012 -0700 @@ -43,7 +43,7 @@ protected: Generation* _next_gen; - int _tenuring_threshold; // Tenuring threshold for next collection. + uint _tenuring_threshold; // Tenuring threshold for next collection. ageTable _age_table; // Size of object to pretenure in words; command line provides bytes size_t _pretenure_size_threshold_words; @@ -325,7 +325,7 @@ bool parallel = false); oop copy_to_survivor_space(oop old); - int tenuring_threshold() { return _tenuring_threshold; } + uint tenuring_threshold() { return _tenuring_threshold; } // Performance Counter support void update_counters(); diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/memory/threadLocalAllocBuffer.hpp --- a/src/share/vm/memory/threadLocalAllocBuffer.hpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/memory/threadLocalAllocBuffer.hpp Fri Oct 05 10:03:56 2012 -0700 @@ -35,7 +35,7 @@ // the threads for allocation. // It is thread-private at any time, but maybe multiplexed over // time across multiple threads. The park()/unpark() pair is -// used to make it avaiable for such multiplexing. +// used to make it available for such multiplexing. class ThreadLocalAllocBuffer: public CHeapObj { friend class VMStructs; private: diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/oops/markOop.hpp --- a/src/share/vm/oops/markOop.hpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/oops/markOop.hpp Fri Oct 05 10:03:56 2012 -0700 @@ -318,7 +318,7 @@ intptr_t tmp = (intptr_t) monitor; return (markOop) (tmp | monitor_value); } - static markOop encode(JavaThread* thread, int age, int bias_epoch) { + static markOop encode(JavaThread* thread, uint age, int bias_epoch) { intptr_t tmp = (intptr_t) thread; assert(UseBiasedLocking && ((tmp & (epoch_mask_in_place | age_mask_in_place | biased_lock_mask_in_place)) == 0), "misaligned JavaThread pointer"); assert(age <= max_age, "age too large"); @@ -333,10 +333,10 @@ markOop set_marked() { return markOop((value() & ~lock_mask_in_place) | marked_value); } markOop set_unmarked() { return markOop((value() & ~lock_mask_in_place) | unlocked_value); } - int age() const { return mask_bits(value() >> age_shift, age_mask); } - markOop set_age(int v) const { + uint age() const { return mask_bits(value() >> age_shift, age_mask); } + markOop set_age(uint v) const { assert((v & ~age_mask) == 0, "shouldn't overflow age field"); - return markOop((value() & ~age_mask_in_place) | (((intptr_t)v & age_mask) << age_shift)); + return markOop((value() & ~age_mask_in_place) | (((uintptr_t)v & age_mask) << age_shift)); } markOop incr_age() const { return age() == max_age ? markOop(this) : set_age(age() + 1); } diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/oops/objArrayKlass.cpp --- a/src/share/vm/oops/objArrayKlass.cpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/oops/objArrayKlass.cpp Fri Oct 05 10:03:56 2012 -0700 @@ -646,7 +646,7 @@ } int remaining = oa->length() - print_len; if (remaining > 0) { - tty->print_cr(" - <%d more elements, increase MaxElementPrintSize to print>", remaining); + st->print_cr(" - <%d more elements, increase MaxElementPrintSize to print>", remaining); } } diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/oops/oop.hpp --- a/src/share/vm/oops/oop.hpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/oops/oop.hpp Fri Oct 05 10:03:56 2012 -0700 @@ -327,7 +327,7 @@ oop forwardee() const; // Age of object during scavenge - int age() const; + uint age() const; void incr_age(); // Adjust all pointers in this object to point at it's forwarded location and diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/oops/oop.inline.hpp --- a/src/share/vm/oops/oop.inline.hpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/oops/oop.inline.hpp Fri Oct 05 10:03:56 2012 -0700 @@ -693,7 +693,7 @@ } // The following method needs to be MT safe. -inline int oopDesc::age() const { +inline uint oopDesc::age() const { assert(!is_forwarded(), "Attempt to read age from forwarded mark"); if (has_displaced_mark()) { return displaced_mark()->age(); diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/oops/typeArrayKlass.cpp --- a/src/share/vm/oops/typeArrayKlass.cpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/oops/typeArrayKlass.cpp Fri Oct 05 10:03:56 2012 -0700 @@ -381,7 +381,7 @@ } int remaining = ta->length() - print_len; if (remaining > 0) { - tty->print_cr(" - <%d more elements, increase MaxElementPrintSize to print>", remaining); + st->print_cr(" - <%d more elements, increase MaxElementPrintSize to print>", remaining); } } diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/runtime/arguments.cpp Fri Oct 05 10:03:56 2012 -0700 @@ -1112,7 +1112,7 @@ // AlwaysTenure flag should make ParNew promote all at first collection. // See CR 6362902. if (AlwaysTenure) { - FLAG_SET_CMDLINE(intx, MaxTenuringThreshold, 0); + FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, 0); } // When using compressed oops, we use local overflow stacks, // rather than using a global overflow list chained through @@ -1231,7 +1231,7 @@ // promote all objects surviving "tenuring_default" scavenges. if (FLAG_IS_DEFAULT(MaxTenuringThreshold) && FLAG_IS_DEFAULT(SurvivorRatio)) { - FLAG_SET_ERGO(intx, MaxTenuringThreshold, tenuring_default); + FLAG_SET_ERGO(uintx, MaxTenuringThreshold, tenuring_default); } // If we decided above (or user explicitly requested) // `promote all' (via MaxTenuringThreshold := 0), diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/runtime/biasedLocking.cpp --- a/src/share/vm/runtime/biasedLocking.cpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/runtime/biasedLocking.cpp Fri Oct 05 10:03:56 2012 -0700 @@ -154,7 +154,7 @@ return BiasedLocking::NOT_BIASED; } - int age = mark->age(); + uint age = mark->age(); markOop biased_prototype = markOopDesc::biased_locking_prototype()->set_age(age); markOop unbiased_prototype = markOopDesc::prototype()->set_age(age); diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/runtime/globals.hpp Fri Oct 05 10:03:56 2012 -0700 @@ -473,7 +473,7 @@ develop(bool, CleanChunkPoolAsync, falseInEmbedded, \ "Whether to clean the chunk pool asynchronously") \ \ - /* Temporary: See 6948537 */ \ + /* Temporary: See 6948537 */ \ experimental(bool, UseMemSetInBOT, true, \ "(Unstable) uses memset in BOT updates in GC code") \ \ @@ -1626,7 +1626,7 @@ "Use BinaryTreeDictionary as default in the CMS generation") \ \ product(uintx, CMSIndexedFreeListReplenish, 4, \ - "Replenish an indexed free list with this number of chunks") \ + "Replenish an indexed free list with this number of chunks") \ \ product(bool, CMSReplenishIntermediate, true, \ "Replenish all intermediate free-list caches") \ @@ -2052,7 +2052,7 @@ product(uintx, TenuredGenerationSizeSupplementDecay, 2, \ "Decay factor to TenuredGenerationSizeIncrement") \ \ - product(uintx, MaxGCPauseMillis, max_uintx, \ + product(uintx, MaxGCPauseMillis, max_uintx, \ "Adaptive size policy maximum GC pause time goal in msec, " \ "or (G1 Only) the max. GC time per MMU time slice") \ \ @@ -2266,7 +2266,7 @@ develop(bool, TraceGCTaskQueue, false, \ "Trace actions of the GC task queues") \ \ - diagnostic(bool, TraceGCTaskThread, false, \ + diagnostic(bool, TraceGCTaskThread, false, \ "Trace actions of the GC task threads") \ \ product(bool, PrintParallelOldGCPhaseTimes, false, \ @@ -2781,7 +2781,7 @@ product(intx, SafepointTimeoutDelay, 10000, \ "Delay in milliseconds for option SafepointTimeout") \ \ - product(intx, NmethodSweepFraction, 16, \ + product(intx, NmethodSweepFraction, 16, \ "Number of invocations of sweeper to cover all nmethods") \ \ product(intx, NmethodSweepCheckInterval, 5, \ @@ -2904,7 +2904,7 @@ "if non-zero, start verifying C heap after Nth call to " \ "malloc/realloc/free") \ \ - product(intx, TypeProfileWidth, 2, \ + product(intx, TypeProfileWidth, 2, \ "number of receiver types to record in call/cast profile") \ \ develop(intx, BciProfileWidth, 2, \ @@ -3012,10 +3012,10 @@ product(uintx, MinHeapDeltaBytes, ScaleForWordSize(128*K), \ "Min change in heap space due to GC (in bytes)") \ \ - product(uintx, MinMetaspaceExpansion, ScaleForWordSize(256*K), \ + product(uintx, MinMetaspaceExpansion, ScaleForWordSize(256*K), \ "Min expansion of permanent heap (in bytes)") \ \ - product(uintx, MaxMetaspaceExpansion, ScaleForWordSize(4*M), \ + product(uintx, MaxMetaspaceExpansion, ScaleForWordSize(4*M), \ "Max expansion of permanent heap without full GC (in bytes)") \ \ product(intx, QueuedAllocationWarningCount, 0, \ @@ -3028,10 +3028,10 @@ diagnostic(intx, VerifyGCLevel, 0, \ "Generation level at which to start +VerifyBefore/AfterGC") \ \ - product(intx, MaxTenuringThreshold, 15, \ + product(uintx, MaxTenuringThreshold, 15, \ "Maximum value for tenuring threshold") \ \ - product(intx, InitialTenuringThreshold, 7, \ + product(uintx, InitialTenuringThreshold, 7, \ "Initial value for tenuring threshold") \ \ product(intx, TargetSurvivorRatio, 50, \ @@ -3065,6 +3065,9 @@ develop(uintx, GCExpandToAllocateDelayMillis, 0, \ "Delay in ms between expansion and allocation") \ \ + develop(uintx, GCWorkerDelayMillis, 0, \ + "Delay in ms in scheduling GC workers") \ + \ product(intx, DeferThrSuspendLoopCount, 4000, \ "(Unstable) Number of times to iterate in safepoint loop " \ " before blocking VM threads ") \ diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/runtime/os.cpp --- a/src/share/vm/runtime/os.cpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/runtime/os.cpp Fri Oct 05 10:03:56 2012 -0700 @@ -878,6 +878,7 @@ st->print(" for "); nm->method()->print_value_on(st); } + st->cr(); nm->print_nmethod(verbose); return; } @@ -898,7 +899,11 @@ print = true; } if (print) { - st->print_cr(INTPTR_FORMAT " is an oop", addr); + if (p == (HeapWord*) addr) { + st->print_cr(INTPTR_FORMAT " is an oop", addr); + } else { + st->print_cr(INTPTR_FORMAT " is pointing into object: " INTPTR_FORMAT, addr, p); + } oop(p)->print_on(st); return; } diff -r bf2edd3c9b0f -r 685457683e86 src/share/vm/runtime/vmStructs.cpp --- a/src/share/vm/runtime/vmStructs.cpp Thu Oct 04 06:31:07 2012 -0700 +++ b/src/share/vm/runtime/vmStructs.cpp Fri Oct 05 10:03:56 2012 -0700 @@ -508,7 +508,7 @@ nonstatic_field(ContiguousSpace, _saved_mark_word, HeapWord*) \ \ nonstatic_field(DefNewGeneration, _next_gen, Generation*) \ - nonstatic_field(DefNewGeneration, _tenuring_threshold, int) \ + nonstatic_field(DefNewGeneration, _tenuring_threshold, uint) \ nonstatic_field(DefNewGeneration, _age_table, ageTable) \ nonstatic_field(DefNewGeneration, _eden_space, EdenSpace*) \ nonstatic_field(DefNewGeneration, _from_space, ContiguousSpace*) \