< prev index next >
src/share/vm/gc/g1/g1ConcurrentMark.cpp
Print this page
rev 10546 : [mq]: 8077144-concurrent-mark-thread-init-fix
rev 10547 : imported patch 8077144-mikael-review
*** 46,55 ****
--- 46,56 ----
#include "gc/shared/referencePolicy.hpp"
#include "gc/shared/strongRootsScope.hpp"
#include "gc/shared/taskqueue.inline.hpp"
#include "gc/shared/vmGCOperations.hpp"
#include "logging/log.hpp"
+ #include "logging/logTag.hpp"
#include "memory/allocation.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.inline.hpp"
#include "runtime/handles.inline.hpp"
*** 353,366 ****
_parallel_marking_threads(0),
_max_parallel_marking_threads(0),
_sleep_factor(0.0),
_marking_task_overhead(1.0),
_cleanup_list("Cleanup List"),
! _region_bm((BitMap::idx_t)(g1h->max_regions()), false /* in_resource_area*/),
! _card_bm((g1h->reserved_region().byte_size() + CardTableModRefBS::card_size - 1) >>
! CardTableModRefBS::card_shift,
! false /* in_resource_area*/),
_prevMarkBitMap(&_markBitMap1),
_nextMarkBitMap(&_markBitMap2),
_markStack(this),
--- 354,365 ----
_parallel_marking_threads(0),
_max_parallel_marking_threads(0),
_sleep_factor(0.0),
_marking_task_overhead(1.0),
_cleanup_list("Cleanup List"),
! _region_live_bm(),
! _card_live_bm(),
_prevMarkBitMap(&_markBitMap1),
_nextMarkBitMap(&_markBitMap2),
_markStack(this),
*** 388,399 ****
_total_counting_time(0.0),
_total_rs_scrub_time(0.0),
_parallel_workers(NULL),
- _count_card_bitmaps(NULL),
- _count_marked_bytes(NULL),
_completed_initialization(false) {
_markBitMap1.initialize(g1h->reserved_region(), prev_bitmap_storage);
_markBitMap2.initialize(g1h->reserved_region(), next_bitmap_storage);
--- 387,396 ----
*** 500,546 ****
if (!_markStack.allocate(MarkStackSize)) {
log_warning(gc)("Failed to allocate CM marking stack");
return;
}
! _tasks = NEW_C_HEAP_ARRAY(G1CMTask*, _max_worker_id, mtGC);
! _accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_worker_id, mtGC);
! _count_card_bitmaps = NEW_C_HEAP_ARRAY(BitMap, _max_worker_id, mtGC);
! _count_marked_bytes = NEW_C_HEAP_ARRAY(size_t*, _max_worker_id, mtGC);
! BitMap::idx_t card_bm_size = _card_bm.size();
// so that the assertion in MarkingTaskQueue::task_queue doesn't fail
_active_tasks = _max_worker_id;
- uint max_regions = _g1h->max_regions();
for (uint i = 0; i < _max_worker_id; ++i) {
G1CMTaskQueue* task_queue = new G1CMTaskQueue();
task_queue->initialize();
_task_queues->register_queue(i, task_queue);
! _count_card_bitmaps[i] = BitMap(card_bm_size, false);
! _count_marked_bytes[i] = NEW_C_HEAP_ARRAY(size_t, max_regions, mtGC);
!
! _tasks[i] = new G1CMTask(i, this,
! _count_marked_bytes[i],
! &_count_card_bitmaps[i],
! task_queue, _task_queues);
_accum_task_vtime[i] = 0.0;
}
- // Calculate the card number for the bottom of the heap. Used
- // in biasing indexes into the accounting card bitmaps.
- _heap_bottom_card_num =
- intptr_t(uintptr_t(_g1h->reserved_region().start()) >>
- CardTableModRefBS::card_shift);
-
- // Clear all the liveness counting data
- clear_all_count_data();
-
// so that the call below can read a sensible value
_heap_start = g1h->reserved_region().start();
set_non_marking_state();
_completed_initialization = true;
}
--- 497,528 ----
if (!_markStack.allocate(MarkStackSize)) {
log_warning(gc)("Failed to allocate CM marking stack");
return;
}
! allocate_internal_bitmaps();
! if (G1PretouchAuxiliaryMemory) {
! pretouch_internal_bitmaps();
! }
! _tasks = NEW_C_HEAP_ARRAY(G1CMTask*, _max_worker_id, mtGC);
! _accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_worker_id, mtGC);
// so that the assertion in MarkingTaskQueue::task_queue doesn't fail
_active_tasks = _max_worker_id;
for (uint i = 0; i < _max_worker_id; ++i) {
G1CMTaskQueue* task_queue = new G1CMTaskQueue();
task_queue->initialize();
_task_queues->register_queue(i, task_queue);
! _tasks[i] = new G1CMTask(i, this, task_queue, _task_queues);
_accum_task_vtime[i] = 0.0;
}
// so that the call below can read a sensible value
_heap_start = g1h->reserved_region().start();
set_non_marking_state();
_completed_initialization = true;
}
*** 714,727 ****
// is the case.
guarantee(!_g1h->collector_state()->mark_in_progress(), "invariant");
clear_bitmap(_nextMarkBitMap, _parallel_workers, true);
! // Clear the liveness counting data. If the marking has been aborted, the abort()
// call already did that.
if (!has_aborted()) {
! clear_all_count_data();
}
// Repeat the asserts from above.
guarantee(cmThread()->during_cycle(), "invariant");
guarantee(!_g1h->collector_state()->mark_in_progress(), "invariant");
--- 696,710 ----
// is the case.
guarantee(!_g1h->collector_state()->mark_in_progress(), "invariant");
clear_bitmap(_nextMarkBitMap, _parallel_workers, true);
! // Clear the live count data. If the marking has been aborted, the abort()
// call already did that.
if (!has_aborted()) {
! clear_all_live_data(_parallel_workers);
! DEBUG_ONLY(verify_all_live_data());
}
// Repeat the asserts from above.
guarantee(cmThread()->during_cycle(), "invariant");
guarantee(!_g1h->collector_state()->mark_in_progress(), "invariant");
*** 1105,1122 ****
// Clear the marking state because we will be restarting
// marking due to overflowing the global mark stack.
reset_marking_state();
} else {
- {
- GCTraceTime(Debug, gc) trace("Aggregate Data", _gc_timer_cm);
-
- // Aggregate the per-task counting data that we have accumulated
- // while marking.
- aggregate_count_data();
- }
-
SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
// We're done with marking.
// This is the end of the marking cycle, we're expected all
// threads to have SATB queues with active set to true.
satb_mq_set.set_active_all_threads(false, /* new active value */
--- 1088,1097 ----
*** 1148,1366 ****
G1CMIsAliveClosure is_alive(g1h);
_gc_tracer_cm->report_object_count_after_gc(&is_alive);
}
! // Base class of the closures that finalize and verify the
! // liveness counting data.
! class G1CMCountDataClosureBase: public HeapRegionClosure {
! protected:
! G1CollectedHeap* _g1h;
! G1ConcurrentMark* _cm;
! CardTableModRefBS* _ct_bs;
!
BitMap* _region_bm;
BitMap* _card_bm;
// 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.
void set_bit_for_region(HeapRegion* hr) {
BitMap::idx_t index = (BitMap::idx_t) hr->hrm_index();
_region_bm->par_at_put(index, true);
}
! public:
! G1CMCountDataClosureBase(G1CollectedHeap* g1h,
! BitMap* region_bm, BitMap* card_bm):
! _g1h(g1h), _cm(g1h->concurrent_mark()),
! _ct_bs(barrier_set_cast<CardTableModRefBS>(g1h->barrier_set())),
! _region_bm(region_bm), _card_bm(card_bm) { }
! };
! // Closure that calculates the # live objects per region. Used
! // for verification purposes during the cleanup pause.
! class CalcLiveObjectsClosure: public G1CMCountDataClosureBase {
! G1CMBitMapRO* _bm;
! size_t _region_marked_bytes;
! public:
! CalcLiveObjectsClosure(G1CMBitMapRO *bm, G1CollectedHeap* g1h,
! BitMap* region_bm, BitMap* card_bm) :
! G1CMCountDataClosureBase(g1h, region_bm, card_bm),
! _bm(bm), _region_marked_bytes(0) { }
- bool doHeapRegion(HeapRegion* hr) {
HeapWord* ntams = hr->next_top_at_mark_start();
HeapWord* start = hr->bottom();
assert(start <= hr->end() && start <= ntams && ntams <= hr->end(),
"Preconditions not met - "
"start: " PTR_FORMAT ", ntams: " PTR_FORMAT ", end: " PTR_FORMAT,
p2i(start), p2i(ntams), p2i(hr->end()));
// Find the first marked object at or after "start".
! start = _bm->getNextMarkedWordAddress(start, ntams);
!
! size_t marked_bytes = 0;
!
while (start < ntams) {
oop obj = oop(start);
int obj_sz = obj->size();
HeapWord* obj_end = start + obj_sz;
! BitMap::idx_t start_idx = _cm->card_bitmap_index_for(start);
! 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;
- // This will happen if we are handling a humongous object that spans
- // several heap regions.
- if (obj_end > hr->end()) {
- break;
- }
// Find the next marked object after this one.
! start = _bm->getNextMarkedWordAddress(obj_end, ntams);
}
! // Mark the allocated-since-marking portion...
! HeapWord* top = hr->top();
! 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);
- }
-
- // Update the live region bitmap.
- if (marked_bytes > 0) {
- set_bit_for_region(hr);
- }
-
- // Set the marked bytes for the current region so that
- // it can be queried by a calling verification routine
- _region_marked_bytes = marked_bytes;
! return false;
}
-
- size_t region_marked_bytes() const { return _region_marked_bytes; }
};
! // Heap region closure used for verifying the counting data
! // that was accumulated concurrently and aggregated during
// the remark pause. This closure is applied to the heap
// regions during the STW cleanup pause.
!
! class VerifyLiveObjectDataHRClosure: public HeapRegionClosure {
G1CollectedHeap* _g1h;
! G1ConcurrentMark* _cm;
! CalcLiveObjectsClosure _calc_cl;
! BitMap* _region_bm; // Region BM to be verified
! BitMap* _card_bm; // Card BM to be verified
BitMap* _exp_region_bm; // Expected Region BM values
BitMap* _exp_card_bm; // Expected card BM values
int _failures;
public:
! VerifyLiveObjectDataHRClosure(G1CollectedHeap* g1h,
! BitMap* region_bm,
! BitMap* card_bm,
BitMap* exp_region_bm,
BitMap* 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),
! _exp_region_bm(exp_region_bm), _exp_card_bm(exp_card_bm),
_failures(0) { }
int failures() const { return _failures; }
bool doHeapRegion(HeapRegion* hr) {
int failures = 0;
! // Call the CalcLiveObjectsClosure to walk the marking bitmap for
! // this region and set the corresponding bits in the expected region
! // and card bitmaps.
! bool res = _calc_cl.doHeapRegion(hr);
! assert(res == false, "should be continuing");
!
! // Verify the marked bytes for this region.
! size_t exp_marked_bytes = _calc_cl.region_marked_bytes();
size_t act_marked_bytes = hr->next_marked_bytes();
! if (exp_marked_bytes > act_marked_bytes) {
! if (hr->is_starts_humongous()) {
! // For start_humongous regions, the size of the whole object will be
! // in exp_marked_bytes.
! HeapRegion* region = hr;
! int num_regions;
! for (num_regions = 0; region != NULL; num_regions++) {
! region = _g1h->next_region_in_humongous(region);
! }
! if ((num_regions-1) * HeapRegion::GrainBytes >= exp_marked_bytes) {
failures += 1;
! } else if (num_regions * HeapRegion::GrainBytes < exp_marked_bytes) {
failures += 1;
}
- } else {
- // We're not OK if expected marked bytes > actual marked bytes. It means
- // we have missed accounting some objects during the actual marking.
- failures += 1;
- }
- }
// Verify the bit, for this region, in the actual and expected
// (which was just calculated) region bit maps.
// We're not OK if the bit in the calculated expected region
// bitmap is set and the bit in the actual region bitmap is not.
BitMap::idx_t index = (BitMap::idx_t) hr->hrm_index();
bool expected = _exp_region_bm->at(index);
! bool actual = _region_bm->at(index);
if (expected && !actual) {
failures += 1;
}
// Verify that the card bit maps for the cards spanned by the current
// region match. We have an error if we have a set bit in the expected
// bit map and the corresponding bit in the actual bitmap is not set.
! BitMap::idx_t start_idx = _cm->card_bitmap_index_for(hr->bottom());
! BitMap::idx_t end_idx = _cm->card_bitmap_index_for(hr->top());
for (BitMap::idx_t i = start_idx; i < end_idx; i+=1) {
expected = _exp_card_bm->at(i);
! actual = _card_bm->at(i);
if (expected && !actual) {
failures += 1;
}
}
--- 1123,1378 ----
G1CMIsAliveClosure is_alive(g1h);
_gc_tracer_cm->report_object_count_after_gc(&is_alive);
}
! // Helper class that provides functionality to generate the Live Data Count
! // information.
! class G1LiveDataHelper VALUE_OBJ_CLASS_SPEC {
! private:
BitMap* _region_bm;
BitMap* _card_bm;
+ // The card number of the bottom of the G1 heap. Used for converting addresses
+ // to bitmap indices quickly.
+ BitMap::idx_t _heap_card_bias;
+
+ // Utility routine to set an exclusive range of bits on the given
+ // bitmap, optimized for very small ranges.
+ // There must be at least one bit to set.
+ inline void set_card_bitmap_range(BitMap* bm,
+ BitMap::idx_t start_idx,
+ BitMap::idx_t end_idx) {
+
+ // Set the exclusive bit range [start_idx, end_idx).
+ assert((end_idx - start_idx) > 0, "at least one bit");
+ assert(end_idx <= bm->size(), "sanity");
+
+ // 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) {
+ bm->set_bit(i);
+ }
+ } else {
+ bm->set_range(start_idx, end_idx);
+ }
+ }
+
+ // We cache the last mark set. This avoids setting the same bit multiple times.
+ // This is particularly interesting for dense bitmaps, as this avoids doing
+ // lots of work most of the time.
+ BitMap::idx_t _last_marked_bit_idx;
+
+ // Mark the card liveness bitmap for the object spanning from start to end.
+ void mark_card_bitmap_range(HeapWord* start, HeapWord* end) {
+ BitMap::idx_t start_idx = card_live_bitmap_index_for(start);
+ BitMap::idx_t end_idx = card_live_bitmap_index_for((HeapWord*)align_ptr_up(end, CardTableModRefBS::card_size));
+
+ assert((end_idx - start_idx) > 0, "Trying to mark zero sized range.");
+
+ if (start_idx == _last_marked_bit_idx) {
+ start_idx++;
+ }
+ if (start_idx == end_idx) {
+ return;
+ }
+
+ // Set the bits in the card bitmap for the cards spanned by this object.
+ set_card_bitmap_range(_card_bm, start_idx, end_idx);
+ _last_marked_bit_idx = end_idx - 1;
+ }
+
+ void reset_mark_cache() {
+ _last_marked_bit_idx = (BitMap::idx_t)-1;
+ }
+
+ public:
+ // Returns the index in the per-card liveness count bitmap
+ // for the given address
+ inline BitMap::idx_t card_live_bitmap_index_for(HeapWord* addr) {
+ // Below, the term "card num" means the result of shifting an address
+ // 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.
+ BitMap::idx_t card_num = (BitMap::idx_t)(uintptr_t(addr) >> CardTableModRefBS::card_shift);
+ return card_num - _heap_card_bias;
+ }
+
// 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.
void set_bit_for_region(HeapRegion* hr) {
BitMap::idx_t index = (BitMap::idx_t) hr->hrm_index();
_region_bm->par_at_put(index, true);
}
! // Mark the range of bits covered by allocations done since the last marking
! // in the given heap region, i.e. from NTAMS to top of the given region.
! // Returns if there has been some allocation in this region since the last marking.
! bool mark_allocated_since_marking(HeapRegion* hr) {
! reset_mark_cache();
! HeapWord* ntams = hr->next_top_at_mark_start();
! HeapWord* top = hr->top();
! assert(hr->bottom() <= ntams && ntams <= hr->end(), "Preconditions.");
!
! // Mark the allocated-since-marking portion...
! if (ntams < top) {
! mark_card_bitmap_range(ntams, top);
! return true;
! } else {
! return false;
! }
! }
!
! // Mark the range of bits covered by live objects on the mark bitmap between
! // bottom and NTAMS of the given region.
! // Returns the number of live bytes marked within that area for the given
! // heap region.
! size_t mark_marked_during_marking(G1CMBitMap* mark_bitmap, HeapRegion* hr) {
! reset_mark_cache();
!
! size_t marked_bytes = 0;
HeapWord* ntams = hr->next_top_at_mark_start();
HeapWord* start = hr->bottom();
+ if (ntams <= start) {
+ // Skip empty regions.
+ return 0;
+ } else if (hr->is_humongous()) {
+ mark_card_bitmap_range(start, hr->top());
+ return pointer_delta(hr->top(), start, 1);
+ }
+
assert(start <= hr->end() && start <= ntams && ntams <= hr->end(),
"Preconditions not met - "
"start: " PTR_FORMAT ", ntams: " PTR_FORMAT ", end: " PTR_FORMAT,
p2i(start), p2i(ntams), p2i(hr->end()));
// Find the first marked object at or after "start".
! start = mark_bitmap->getNextMarkedWordAddress(start, ntams);
while (start < ntams) {
oop obj = oop(start);
int obj_sz = obj->size();
HeapWord* obj_end = start + obj_sz;
! assert(obj_end <= hr->end(), "Humongous objects must have been handled elsewhere.");
! mark_card_bitmap_range(start, obj_end);
// 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 = mark_bitmap->getNextMarkedWordAddress(obj_end, ntams);
}
! return marked_bytes;
}
! G1LiveDataHelper(BitMap* region_bm,
! BitMap* card_bm):
! _region_bm(region_bm),
! _card_bm(card_bm) {
! //assert(region_bm != NULL, "");
! assert(card_bm != NULL, "");
! // Calculate the card number for the bottom of the heap. Used
! // in biasing indexes into the accounting card bitmaps.
! _heap_card_bias =
! (BitMap::idx_t)(uintptr_t(G1CollectedHeap::heap()->reserved_region().start()) >> CardTableModRefBS::card_shift);
}
};
! // Heap region closure used for verifying the live count data
! // that was created concurrently and finalized during
// the remark pause. This closure is applied to the heap
// regions during the STW cleanup pause.
! class G1VerifyLiveDataHRClosure: public HeapRegionClosure {
! private:
G1CollectedHeap* _g1h;
! G1CMBitMap* _mark_bitmap;
! G1LiveDataHelper _calc_helper;
!
! BitMap* _act_region_bm; // Region BM to be verified
! BitMap* _act_card_bm; // Card BM to be verified
BitMap* _exp_region_bm; // Expected Region BM values
BitMap* _exp_card_bm; // Expected card BM values
int _failures;
+ // Updates the live data count for the given heap region and returns the number
+ // of bytes marked.
+ size_t create_live_data_count(HeapRegion* hr) {
+ size_t bytes_marked = _calc_helper.mark_marked_during_marking(_mark_bitmap, hr);
+ bool allocated_since_marking = _calc_helper.mark_allocated_since_marking(hr);
+ if (allocated_since_marking || bytes_marked > 0) {
+ _calc_helper.set_bit_for_region(hr);
+ }
+ return bytes_marked;
+ }
+
public:
! G1VerifyLiveDataHRClosure(G1CollectedHeap* g1h,
! G1CMBitMap* mark_bitmap,
! BitMap* act_region_bm,
! BitMap* act_card_bm,
BitMap* exp_region_bm,
BitMap* exp_card_bm) :
! _g1h(g1h),
! _mark_bitmap(mark_bitmap),
! _calc_helper(exp_region_bm, exp_card_bm),
! _act_region_bm(act_region_bm),
! _act_card_bm(act_card_bm),
! _exp_region_bm(exp_region_bm),
! _exp_card_bm(exp_card_bm),
_failures(0) { }
int failures() const { return _failures; }
bool doHeapRegion(HeapRegion* hr) {
int failures = 0;
! // Walk the marking bitmap for this region and set the corresponding bits
! // in the expected region and card bitmaps.
! size_t exp_marked_bytes = create_live_data_count(hr);
size_t act_marked_bytes = hr->next_marked_bytes();
+ // Verify the marked bytes for this region.
! if (exp_marked_bytes != act_marked_bytes) {
failures += 1;
! } else if (exp_marked_bytes > HeapRegion::GrainBytes) {
failures += 1;
}
// Verify the bit, for this region, in the actual and expected
// (which was just calculated) region bit maps.
// We're not OK if the bit in the calculated expected region
// bitmap is set and the bit in the actual region bitmap is not.
BitMap::idx_t index = (BitMap::idx_t) hr->hrm_index();
bool expected = _exp_region_bm->at(index);
! bool actual = _act_region_bm->at(index);
if (expected && !actual) {
failures += 1;
}
// Verify that the card bit maps for the cards spanned by the current
// region match. We have an error if we have a set bit in the expected
// bit map and the corresponding bit in the actual bitmap is not set.
! BitMap::idx_t start_idx = _calc_helper.card_live_bitmap_index_for(hr->bottom());
! BitMap::idx_t end_idx = _calc_helper.card_live_bitmap_index_for(hr->top());
for (BitMap::idx_t i = start_idx; i < end_idx; i+=1) {
expected = _exp_card_bm->at(i);
! actual = _act_card_bm->at(i);
if (expected && !actual) {
failures += 1;
}
}
*** 1371,1511 ****
// find the first violating region by returning true.
return false;
}
};
! class G1ParVerifyFinalCountTask: public AbstractGangTask {
protected:
G1CollectedHeap* _g1h;
! G1ConcurrentMark* _cm;
BitMap* _actual_region_bm;
BitMap* _actual_card_bm;
! uint _n_workers;
!
! BitMap* _expected_region_bm;
! BitMap* _expected_card_bm;
int _failures;
! HeapRegionClaimer _hrclaimer;
public:
! G1ParVerifyFinalCountTask(G1CollectedHeap* g1h,
! BitMap* region_bm, BitMap* card_bm,
! BitMap* expected_region_bm, BitMap* expected_card_bm)
: AbstractGangTask("G1 verify final counting"),
! _g1h(g1h), _cm(_g1h->concurrent_mark()),
! _actual_region_bm(region_bm), _actual_card_bm(card_bm),
! _expected_region_bm(expected_region_bm), _expected_card_bm(expected_card_bm),
_failures(0),
! _n_workers(_g1h->workers()->active_workers()), _hrclaimer(_n_workers) {
assert(VerifyDuringGC, "don't call this otherwise");
- assert(_expected_card_bm->size() == _actual_card_bm->size(), "sanity");
- assert(_expected_region_bm->size() == _actual_region_bm->size(), "sanity");
}
void work(uint worker_id) {
! assert(worker_id < _n_workers, "invariant");
!
! VerifyLiveObjectDataHRClosure verify_cl(_g1h,
! _actual_region_bm, _actual_card_bm,
! _expected_region_bm,
! _expected_card_bm);
!
! _g1h->heap_region_par_iterate(&verify_cl, worker_id, &_hrclaimer);
! Atomic::add(verify_cl.failures(), &_failures);
}
int failures() const { return _failures; }
};
! // Closure that finalizes the liveness counting data.
! // Used during the cleanup pause.
! // Sets the bits corresponding to the interval [NTAMS, top]
! // (which contains the implicitly live objects) in the
! // card liveness bitmap. Also sets the bit for each region,
! // containing live data, in the region liveness bitmap.
!
! class FinalCountDataUpdateClosure: public G1CMCountDataClosureBase {
public:
! FinalCountDataUpdateClosure(G1CollectedHeap* g1h,
BitMap* region_bm,
BitMap* card_bm) :
! G1CMCountDataClosureBase(g1h, region_bm, card_bm) { }
bool doHeapRegion(HeapRegion* hr) {
! HeapWord* ntams = hr->next_top_at_mark_start();
! HeapWord* top = hr->top();
!
! assert(hr->bottom() <= ntams && ntams <= hr->end(), "Preconditions.");
!
! // Mark the allocated-since-marking portion...
! if (ntams < top) {
! // This definitely means the region has live objects.
! set_bit_for_region(hr);
!
! // 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(),
! "oob: end_idx= " SIZE_FORMAT ", bitmap size= " SIZE_FORMAT,
! end_idx, _card_bm->size());
! assert(start_idx < _card_bm->size(),
! "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
! if (hr->next_marked_bytes() > 0) {
! set_bit_for_region(hr);
}
-
return false;
}
! };
- class G1ParFinalCountTask: public AbstractGangTask {
- protected:
- G1CollectedHeap* _g1h;
- G1ConcurrentMark* _cm;
BitMap* _actual_region_bm;
BitMap* _actual_card_bm;
! uint _n_workers;
! HeapRegionClaimer _hrclaimer;
public:
! G1ParFinalCountTask(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm)
! : AbstractGangTask("G1 final counting"),
! _g1h(g1h), _cm(_g1h->concurrent_mark()),
! _actual_region_bm(region_bm), _actual_card_bm(card_bm),
! _n_workers(_g1h->workers()->active_workers()), _hrclaimer(_n_workers) {
}
void work(uint worker_id) {
! assert(worker_id < _n_workers, "invariant");
!
! FinalCountDataUpdateClosure final_update_cl(_g1h,
_actual_region_bm,
_actual_card_bm);
! _g1h->heap_region_par_iterate(&final_update_cl, worker_id, &_hrclaimer);
}
};
class G1NoteEndOfConcMarkClosure : public HeapRegionClosure {
G1CollectedHeap* _g1;
--- 1383,1486 ----
// find the first violating region by returning true.
return false;
}
};
! class G1VerifyLiveDataTask: public AbstractGangTask {
protected:
G1CollectedHeap* _g1h;
! G1CMBitMap* _mark_bitmap;
BitMap* _actual_region_bm;
BitMap* _actual_card_bm;
! BitMap _expected_region_bm;
! BitMap _expected_card_bm;
int _failures;
! HeapRegionClaimer _hr_claimer;
public:
! G1VerifyLiveDataTask(G1CollectedHeap* g1h,
! G1CMBitMap* bitmap,
! BitMap* region_bm,
! BitMap* card_bm,
! uint n_workers)
: AbstractGangTask("G1 verify final counting"),
! _g1h(g1h),
! _mark_bitmap(bitmap),
! _actual_region_bm(region_bm),
! _actual_card_bm(card_bm),
! _expected_region_bm(region_bm->size(), true /* in_resource_area */),
! _expected_card_bm(card_bm->size(), true /* in_resource_area */),
_failures(0),
! _hr_claimer(n_workers) {
assert(VerifyDuringGC, "don't call this otherwise");
}
void work(uint worker_id) {
! G1VerifyLiveDataHRClosure cl(_g1h,
! _mark_bitmap,
! _actual_region_bm,
! _actual_card_bm,
! &_expected_region_bm,
! &_expected_card_bm);
! _g1h->heap_region_par_iterate(&cl, worker_id, &_hr_claimer);
! Atomic::add(cl.failures(), &_failures);
}
int failures() const { return _failures; }
};
! class G1FinalizeLiveDataTask: public AbstractGangTask {
! // Finalizes the liveness counting data.
! // Sets the bits corresponding to the interval [NTAMS, top]
! // (which contains the implicitly live objects) in the
! // card liveness bitmap. Also sets the bit for each region
! // containing live data, in the region liveness bitmap.
! class G1FinalizeCountDataClosure: public HeapRegionClosure {
! private:
! G1LiveDataHelper _helper;
public:
! G1FinalizeCountDataClosure(G1CMBitMap* bitmap,
BitMap* region_bm,
BitMap* card_bm) :
! HeapRegionClosure(),
! _helper(region_bm, card_bm) { }
bool doHeapRegion(HeapRegion* hr) {
! bool allocated_since_marking = _helper.mark_allocated_since_marking(hr);
! if (allocated_since_marking || hr->next_marked_bytes() > 0) {
! _helper.set_bit_for_region(hr);
}
return false;
}
! };
!
! G1CMBitMap* _bitmap;
BitMap* _actual_region_bm;
BitMap* _actual_card_bm;
! HeapRegionClaimer _hr_claimer;
public:
! G1FinalizeLiveDataTask(G1CMBitMap* bitmap, BitMap* region_bm, BitMap* card_bm, uint n_workers) :
! AbstractGangTask("G1 final counting"),
! _bitmap(bitmap),
! _actual_region_bm(region_bm),
! _actual_card_bm(card_bm),
! _hr_claimer(n_workers) {
}
void work(uint worker_id) {
! G1FinalizeCountDataClosure cl(_bitmap,
_actual_region_bm,
_actual_card_bm);
! G1CollectedHeap::heap()->heap_region_par_iterate(&cl, worker_id, &_hr_claimer);
}
};
class G1NoteEndOfConcMarkClosure : public HeapRegionClosure {
G1CollectedHeap* _g1;
*** 1635,1669 ****
double start = os::elapsedTime();
HeapRegionRemSet::reset_for_cleanup_tasks();
! // Do counting once more with the world stopped for good measure.
! G1ParFinalCountTask g1_par_count_task(g1h, &_region_bm, &_card_bm);
!
! g1h->workers()->run_task(&g1_par_count_task);
if (VerifyDuringGC) {
! // Verify that the counting data accumulated during marking matches
! // that calculated by walking the marking bitmap.
!
! // Bitmaps to hold expected values
! BitMap expected_region_bm(_region_bm.size(), true);
! BitMap expected_card_bm(_card_bm.size(), true);
!
! G1ParVerifyFinalCountTask g1_par_verify_task(g1h,
! &_region_bm,
! &_card_bm,
! &expected_region_bm,
! &expected_card_bm);
!
! g1h->workers()->run_task(&g1_par_verify_task);
! guarantee(g1_par_verify_task.failures() == 0, "Unexpected accounting failures");
}
- size_t start_used_bytes = g1h->used();
g1h->collector_state()->set_mark_in_progress(false);
double count_end = os::elapsedTime();
double this_final_counting_time = (count_end - start);
_total_counting_time += this_final_counting_time;
--- 1610,1642 ----
double start = os::elapsedTime();
HeapRegionRemSet::reset_for_cleanup_tasks();
! {
! // Finalize the live data.
! G1FinalizeLiveDataTask cl(_nextMarkBitMap,
! &_region_live_bm,
! &_card_live_bm,
! g1h->workers()->active_workers());
! g1h->workers()->run_task(&cl);
! }
if (VerifyDuringGC) {
! // Verify that the liveness count data created concurrently matches one created
! // during this safepoint.
! ResourceMark rm;
! G1VerifyLiveDataTask cl(G1CollectedHeap::heap(),
! _nextMarkBitMap,
! &_region_live_bm,
! &_card_live_bm,
! g1h->workers()->active_workers());
! g1h->workers()->run_task(&cl);
! guarantee(cl.failures() == 0, "Unexpected accounting failures");
}
g1h->collector_state()->set_mark_in_progress(false);
double count_end = os::elapsedTime();
double this_final_counting_time = (count_end - start);
_total_counting_time += this_final_counting_time;
*** 1694,1704 ****
// call below, since it affects the metric by which we sort the heap
// regions.
if (G1ScrubRemSets) {
double rs_scrub_start = os::elapsedTime();
! g1h->scrub_rem_set(&_region_bm, &_card_bm);
_total_rs_scrub_time += (os::elapsedTime() - rs_scrub_start);
}
// this will also free any regions totally full of garbage objects,
// and sort the regions.
--- 1667,1677 ----
// call below, since it affects the metric by which we sort the heap
// regions.
if (G1ScrubRemSets) {
double rs_scrub_start = os::elapsedTime();
! g1h->scrub_rem_set(&_region_live_bm, &_card_live_bm);
_total_rs_scrub_time += (os::elapsedTime() - rs_scrub_start);
}
// this will also free any regions totally full of garbage objects,
// and sort the regions.
*** 2144,2153 ****
--- 2117,2155 ----
G1CMBitMapRO* temp = _prevMarkBitMap;
_prevMarkBitMap = (G1CMBitMapRO*)_nextMarkBitMap;
_nextMarkBitMap = (G1CMBitMap*) temp;
}
+ BitMap G1ConcurrentMark::allocate_large_bitmap(BitMap::idx_t size_in_bits) {
+ size_t size_in_words = BitMap::size_in_words(size_in_bits);
+
+ BitMap::bm_word_t* map = MmapArrayAllocator<BitMap::bm_word_t, mtGC>::allocate(size_in_words);
+
+ return BitMap(map, size_in_bits);
+ }
+
+ void G1ConcurrentMark::allocate_internal_bitmaps() {
+ double start_time = os::elapsedTime();
+
+ _region_live_bm = allocate_large_bitmap(_g1h->max_regions());
+
+ guarantee(_g1h->max_capacity() % CardTableModRefBS::card_size == 0,
+ "Heap capacity must be aligned to card size.");
+ _card_live_bm = allocate_large_bitmap(_g1h->max_capacity() / CardTableModRefBS::card_size);
+
+ log_debug(gc, marking)("Allocating internal bitmaps took %1.2f seconds.", os::elapsedTime() - start_time);
+ }
+
+ void G1ConcurrentMark::pretouch_internal_bitmaps() {
+ double start_time = os::elapsedTime();
+
+ _region_live_bm.pretouch();
+ _card_live_bm.pretouch();
+
+ log_debug(gc, marking)("Pre-touching internal bitmaps took %1.2f seconds.", os::elapsedTime() - start_time);
+ }
+
// Closure for marking entries in SATB buffers.
class G1CMSATBBufferClosure : public SATBBufferClosure {
private:
G1CMTask* _task;
G1CollectedHeap* _g1h;
*** 2162,2172 ****
// Until we get here, we don't know whether entry refers to a valid
// object; it could instead have been a stale reference.
oop obj = static_cast<oop>(entry);
assert(obj->is_oop(true /* ignore mark word */),
"Invalid oop in SATB buffer: " PTR_FORMAT, p2i(obj));
! _task->make_reference_grey(obj, hr);
}
}
public:
G1CMSATBBufferClosure(G1CMTask* task, G1CollectedHeap* g1h)
--- 2164,2174 ----
// Until we get here, we don't know whether entry refers to a valid
// object; it could instead have been a stale reference.
oop obj = static_cast<oop>(entry);
assert(obj->is_oop(true /* ignore mark word */),
"Invalid oop in SATB buffer: " PTR_FORMAT, p2i(obj));
! _task->make_reference_grey(obj);
}
}
public:
G1CMSATBBufferClosure(G1CMTask* task, G1CollectedHeap* g1h)
*** 2404,2572 ****
}
}
}
#endif // PRODUCT
! // Aggregate the counting data that was constructed concurrently
! // with marking.
! class AggregateCountDataHRClosure: public HeapRegionClosure {
! G1CollectedHeap* _g1h;
! G1ConcurrentMark* _cm;
! CardTableModRefBS* _ct_bs;
! BitMap* _cm_card_bm;
! uint _max_worker_id;
public:
! AggregateCountDataHRClosure(G1CollectedHeap* g1h,
! BitMap* cm_card_bm,
! uint max_worker_id) :
! _g1h(g1h), _cm(g1h->concurrent_mark()),
! _ct_bs(barrier_set_cast<CardTableModRefBS>(g1h->barrier_set())),
! _cm_card_bm(cm_card_bm), _max_worker_id(max_worker_id) { }
bool doHeapRegion(HeapRegion* hr) {
! HeapWord* start = hr->bottom();
! HeapWord* limit = hr->next_top_at_mark_start();
! HeapWord* end = hr->end();
!
! assert(start <= limit && limit <= hr->top() && hr->top() <= hr->end(),
! "Preconditions not met - "
! "start: " PTR_FORMAT ", limit: " PTR_FORMAT ", "
! "top: " PTR_FORMAT ", end: " PTR_FORMAT,
! p2i(start), p2i(limit), p2i(hr->top()), p2i(hr->end()));
!
! assert(hr->next_marked_bytes() == 0, "Precondition");
!
! if (start == limit) {
! // NTAMS of this region has not been set so nothing to do.
! return false;
! }
!
! // 'start' should be in the heap.
! assert(_g1h->is_in_g1_reserved(start) && _ct_bs->is_card_aligned(start), "sanity");
! // 'end' *may* be just beyond 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 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;
}
! assert(limit_idx <= end_idx, "or else use atomics");
!
! // Aggregate the "stripe" in the count data associated with hr.
! uint hrm_index = hr->hrm_index();
! size_t marked_bytes = 0;
!
! for (uint i = 0; i < _max_worker_id; i += 1) {
! size_t* marked_bytes_array = _cm->count_marked_bytes_array_for(i);
! BitMap* task_card_bm = _cm->count_card_bitmap_for(i);
!
! // Fetch the marked_bytes in this region for task i and
! // add it to the running total for this region.
! marked_bytes += marked_bytes_array[hrm_index];
!
! // Now union the bitmaps[0,max_worker_id)[start_idx..limit_idx)
! // into the global card bitmap.
! BitMap::idx_t scan_idx = task_card_bm->get_next_one_offset(start_idx, limit_idx);
!
! while (scan_idx < limit_idx) {
! assert(task_card_bm->at(scan_idx) == true, "should be");
! _cm_card_bm->set_bit(scan_idx);
! assert(_cm_card_bm->at(scan_idx) == true, "should be");
!
! // BitMap::get_next_one_offset() can handle the case when
! // its left_offset parameter is greater than its right_offset
! // 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);
! scan_idx = task_card_bm->get_next_one_offset(next_idx, limit_idx);
! }
}
-
- // Update the marked bytes for this region.
- hr->add_to_marked_bytes(marked_bytes);
-
- // Next heap region
return false;
}
! };
- class G1AggregateCountDataTask: public AbstractGangTask {
- protected:
G1CollectedHeap* _g1h;
G1ConcurrentMark* _cm;
BitMap* _cm_card_bm;
! uint _max_worker_id;
! uint _active_workers;
! HeapRegionClaimer _hrclaimer;
public:
! G1AggregateCountDataTask(G1CollectedHeap* g1h,
! G1ConcurrentMark* cm,
BitMap* cm_card_bm,
- uint max_worker_id,
uint n_workers) :
! AbstractGangTask("Count Aggregation"),
! _g1h(g1h), _cm(cm), _cm_card_bm(cm_card_bm),
! _max_worker_id(max_worker_id),
! _active_workers(n_workers),
! _hrclaimer(_active_workers) {
}
void work(uint worker_id) {
! AggregateCountDataHRClosure cl(_g1h, _cm_card_bm, _max_worker_id);
! _g1h->heap_region_par_iterate(&cl, worker_id, &_hrclaimer);
}
};
! void G1ConcurrentMark::aggregate_count_data() {
! uint n_workers = _g1h->workers()->active_workers();
! G1AggregateCountDataTask g1_par_agg_task(_g1h, this, &_card_bm,
! _max_worker_id, n_workers);
!
! _g1h->workers()->run_task(&g1_par_agg_task);
}
! // Clear the per-worker arrays used to store the per-region counting data
! void G1ConcurrentMark::clear_all_count_data() {
! // Clear the global card bitmap - it will be filled during
! // liveness count aggregation (during remark) and the
! // final counting task.
! _card_bm.clear();
! // Clear the global region bitmap - it will be filled as part
! // of the final counting task.
! _region_bm.clear();
! uint max_regions = _g1h->max_regions();
! assert(_max_worker_id > 0, "uninitialized");
! for (uint i = 0; i < _max_worker_id; i += 1) {
! BitMap* task_card_bm = count_card_bitmap_for(i);
! size_t* marked_bytes_array = count_marked_bytes_array_for(i);
! assert(task_card_bm->size() == _card_bm.size(), "size mismatch");
! assert(marked_bytes_array != NULL, "uninitialized");
! memset(marked_bytes_array, 0, (size_t) max_regions * sizeof(size_t));
! task_card_bm->clear();
! }
}
void G1ConcurrentMark::print_stats() {
if (!log_is_enabled(Debug, gc, stats)) {
return;
--- 2406,2526 ----
}
}
}
#endif // PRODUCT
! class G1CreateLiveDataTask: public AbstractGangTask {
! // Aggregate the counting data that was constructed concurrently
! // with marking.
! class G1CreateLiveDataHRClosure: public HeapRegionClosure {
! G1LiveDataHelper _helper;
!
! G1CMBitMap* _mark_bitmap;
+ G1ConcurrentMark* _cm;
public:
! G1CreateLiveDataHRClosure(G1ConcurrentMark* cm,
! G1CMBitMap* mark_bitmap,
! BitMap* cm_card_bm) :
! HeapRegionClosure(),
! _helper(NULL, cm_card_bm),
! _mark_bitmap(mark_bitmap),
! _cm(cm) { }
bool doHeapRegion(HeapRegion* hr) {
! size_t marked_bytes = _helper.mark_marked_during_marking(_mark_bitmap, hr);
! if (marked_bytes > 0) {
! hr->add_to_marked_bytes(marked_bytes);
}
! if (_cm->do_yield_check() && _cm->has_aborted()) {
! return true;
}
return false;
}
! };
G1CollectedHeap* _g1h;
G1ConcurrentMark* _cm;
BitMap* _cm_card_bm;
! HeapRegionClaimer _hr_claimer;
public:
! G1CreateLiveDataTask(G1CollectedHeap* g1h,
BitMap* cm_card_bm,
uint n_workers) :
! AbstractGangTask("Create Live Data"),
! _g1h(g1h),
! _cm_card_bm(cm_card_bm),
! _hr_claimer(n_workers) {
}
void work(uint worker_id) {
! SuspendibleThreadSetJoiner sts_join;
! G1CreateLiveDataHRClosure cl(_g1h->concurrent_mark(), _g1h->concurrent_mark()->nextMarkBitMap(), _cm_card_bm);
! _g1h->heap_region_par_iterate(&cl, worker_id, &_hr_claimer);
}
};
! void G1ConcurrentMark::create_live_data() {
! uint n_workers = _parallel_workers->active_workers();
! G1CreateLiveDataTask cl(_g1h,
! &_card_live_bm,
! n_workers);
! _parallel_workers->run_task(&cl);
}
! class G1ClearAllLiveDataTask : public AbstractGangTask {
! BitMap* _bitmap;
! size_t _num_tasks;
! size_t _cur_task;
! public:
! G1ClearAllLiveDataTask(BitMap* bitmap, size_t num_tasks) :
! AbstractGangTask("Clear All Live Data"),
! _bitmap(bitmap),
! _num_tasks(num_tasks),
! _cur_task(0) {
! }
! virtual void work(uint worker_id) {
! while (true) {
! size_t to_process = Atomic::add(1, &_cur_task) - 1;
! if (to_process >= _num_tasks) {
! break;
! }
! BitMap::idx_t start = M * BitsPerByte * to_process;
! BitMap::idx_t end = MIN2(start + M * BitsPerByte, _bitmap->size());
! _bitmap->clear_range(start, end);
! }
! }
! };
! void G1ConcurrentMark::clear_all_live_data(WorkGang* workers) {
! double start_time = os::elapsedTime();
! guarantee(Universe::is_fully_initialized(), "Should not call this during initialization.");
! size_t const num_chunks = align_size_up(_card_live_bm.size_in_words() * HeapWordSize, M) / M;
!
! G1ClearAllLiveDataTask cl(&_card_live_bm, num_chunks);
! workers->run_task(&cl);
!
! // The region live bitmap is always very small, even for huge heaps. Clear
! // directly.
! _region_live_bm.clear();
!
!
! log_debug(gc, marking)("Clear Live Data took %.3fms", (os::elapsedTime() - start_time) * 1000.0);
! }
!
! void G1ConcurrentMark::verify_all_live_data() {
! assert(_card_live_bm.count_one_bits() == 0, "Master card bitmap not clear");
! assert(_region_live_bm.count_one_bits() == 0, "Master region bitmap not clear");
}
void G1ConcurrentMark::print_stats() {
if (!log_is_enabled(Debug, gc, stats)) {
return;
*** 2576,2586 ****
_tasks[i]->print_stats();
log_debug(gc, stats)("---------------------------------------------------------------------");
}
}
- // abandon current marking iteration due to a Full GC
void G1ConcurrentMark::abort() {
if (!cmThread()->during_cycle() || _has_aborted) {
// We haven't started a concurrent cycle or we have already aborted it. No need to do anything.
return;
}
--- 2530,2539 ----
*** 2591,2602 ****
// Note we cannot clear the previous marking bitmap here
// since VerifyDuringGC verifies the objects marked during
// a full GC against the previous bitmap.
! // Clear the liveness counting data
! clear_all_count_data();
// Empty mark stack
reset_marking_state();
for (uint i = 0; i < _max_worker_id; ++i) {
_tasks[i]->clear_region_fields();
}
--- 2544,2555 ----
// Note we cannot clear the previous marking bitmap here
// since VerifyDuringGC verifies the objects marked during
// a full GC against the previous bitmap.
! clear_all_live_data(_g1h->workers());
! DEBUG_ONLY(verify_all_live_data());
// Empty mark stack
reset_marking_state();
for (uint i = 0; i < _max_worker_id; ++i) {
_tasks[i]->clear_region_fields();
}
*** 2636,2646 ****
print_ms_time_info(" ", "final marks", _remark_mark_times);
print_ms_time_info(" ", "weak refs", _remark_weak_ref_times);
}
print_ms_time_info(" ", "cleanups", _cleanup_times);
! log.trace(" Final counting total time = %8.2f s (avg = %8.2f ms).",
_total_counting_time, (_cleanup_times.num() > 0 ? _total_counting_time * 1000.0 / (double)_cleanup_times.num() : 0.0));
if (G1ScrubRemSets) {
log.trace(" RS scrub total time = %8.2f s (avg = %8.2f ms).",
_total_rs_scrub_time, (_cleanup_times.num() > 0 ? _total_rs_scrub_time * 1000.0 / (double)_cleanup_times.num() : 0.0));
}
--- 2589,2599 ----
print_ms_time_info(" ", "final marks", _remark_mark_times);
print_ms_time_info(" ", "weak refs", _remark_weak_ref_times);
}
print_ms_time_info(" ", "cleanups", _cleanup_times);
! log.trace(" Finalize live data total time = %8.2f s (avg = %8.2f ms).",
_total_counting_time, (_cleanup_times.num() > 0 ? _total_counting_time * 1000.0 / (double)_cleanup_times.num() : 0.0));
if (G1ScrubRemSets) {
log.trace(" RS scrub total time = %8.2f s (avg = %8.2f ms).",
_total_rs_scrub_time, (_cleanup_times.num() > 0 ? _total_rs_scrub_time * 1000.0 / (double)_cleanup_times.num() : 0.0));
}
*** 3475,3497 ****
_claimed = false;
}
G1CMTask::G1CMTask(uint worker_id,
G1ConcurrentMark* cm,
- size_t* marked_bytes,
- BitMap* card_bm,
G1CMTaskQueue* task_queue,
G1CMTaskQueueSet* task_queues)
: _g1h(G1CollectedHeap::heap()),
_worker_id(worker_id), _cm(cm),
_claimed(false),
_nextMarkBitMap(NULL), _hash_seed(17),
_task_queue(task_queue),
_task_queues(task_queues),
! _cm_oop_closure(NULL),
! _marked_bytes_array(marked_bytes),
! _card_bm(card_bm) {
guarantee(task_queue != NULL, "invariant");
guarantee(task_queues != NULL, "invariant");
_marking_step_diffs_ms.add(0.5);
}
--- 3428,3446 ----
_claimed = false;
}
G1CMTask::G1CMTask(uint worker_id,
G1ConcurrentMark* cm,
G1CMTaskQueue* task_queue,
G1CMTaskQueueSet* task_queues)
: _g1h(G1CollectedHeap::heap()),
_worker_id(worker_id), _cm(cm),
_claimed(false),
_nextMarkBitMap(NULL), _hash_seed(17),
_task_queue(task_queue),
_task_queues(task_queues),
! _cm_oop_closure(NULL) {
guarantee(task_queue != NULL, "invariant");
guarantee(task_queues != NULL, "invariant");
_marking_step_diffs_ms.add(0.5);
}
< prev index next >