< prev index next >
src/share/vm/gc/shenandoah/shenandoahHeap.cpp
Print this page
rev 14453 : Remove secondary marking bitmap.
*** 80,103 ****
class ShenandoahPretouchTask : public AbstractGangTask {
private:
ShenandoahHeapRegionSet* _regions;
const size_t _bitmap_size;
const size_t _page_size;
! char* _bitmap0_base;
! char* _bitmap1_base;
public:
ShenandoahPretouchTask(ShenandoahHeapRegionSet* regions,
! char* bitmap0_base, char* bitmap1_base, size_t bitmap_size,
size_t page_size) :
AbstractGangTask("Shenandoah PreTouch",
Universe::is_fully_initialized() ? GCId::current_raw() :
// During VM initialization there is
// no GC cycle that this task can be
// associated with.
GCId::undefined()),
! _bitmap0_base(bitmap0_base),
! _bitmap1_base(bitmap1_base),
_regions(regions),
_bitmap_size(bitmap_size),
_page_size(page_size) {
_regions->clear_current_index();
};
--- 80,101 ----
class ShenandoahPretouchTask : public AbstractGangTask {
private:
ShenandoahHeapRegionSet* _regions;
const size_t _bitmap_size;
const size_t _page_size;
! char* _bitmap_base;
public:
ShenandoahPretouchTask(ShenandoahHeapRegionSet* regions,
! char* bitmap_base, size_t bitmap_size,
size_t page_size) :
AbstractGangTask("Shenandoah PreTouch",
Universe::is_fully_initialized() ? GCId::current_raw() :
// During VM initialization there is
// no GC cycle that this task can be
// associated with.
GCId::undefined()),
! _bitmap_base(bitmap_base),
_regions(regions),
_bitmap_size(bitmap_size),
_page_size(page_size) {
_regions->clear_current_index();
};
*** 112,127 ****
size_t start = r->region_number() * ShenandoahHeapRegion::region_size_bytes() / MarkBitMap::heap_map_factor();
size_t end = (r->region_number() + 1) * ShenandoahHeapRegion::region_size_bytes() / MarkBitMap::heap_map_factor();
assert (end <= _bitmap_size, "end is sane: " SIZE_FORMAT " < " SIZE_FORMAT, end, _bitmap_size);
log_trace(gc, heap)("Pretouch bitmap under region " SIZE_FORMAT ": " PTR_FORMAT " -> " PTR_FORMAT,
! r->region_number(), p2i(_bitmap0_base + start), p2i(_bitmap0_base + end));
! os::pretouch_memory(_bitmap0_base + start, _bitmap0_base + end, _page_size);
!
! log_trace(gc, heap)("Pretouch bitmap under region " SIZE_FORMAT ": " PTR_FORMAT " -> " PTR_FORMAT,
! r->region_number(), p2i(_bitmap1_base + start), p2i(_bitmap1_base + end));
! os::pretouch_memory(_bitmap1_base + start, _bitmap1_base + end, _page_size);
r = _regions->claim_next();
}
}
};
--- 110,121 ----
size_t start = r->region_number() * ShenandoahHeapRegion::region_size_bytes() / MarkBitMap::heap_map_factor();
size_t end = (r->region_number() + 1) * ShenandoahHeapRegion::region_size_bytes() / MarkBitMap::heap_map_factor();
assert (end <= _bitmap_size, "end is sane: " SIZE_FORMAT " < " SIZE_FORMAT, end, _bitmap_size);
log_trace(gc, heap)("Pretouch bitmap under region " SIZE_FORMAT ": " PTR_FORMAT " -> " PTR_FORMAT,
! r->region_number(), p2i(_bitmap_base + start), p2i(_bitmap_base + end));
! os::pretouch_memory(_bitmap_base + start, _bitmap_base + end, _page_size);
r = _regions->claim_next();
}
}
};
*** 169,197 ****
_ordered_regions = new ShenandoahHeapRegionSet(_num_regions);
_free_regions = new ShenandoahFreeSet(_ordered_regions, _num_regions);
_collection_set = new ShenandoahCollectionSet(this, (HeapWord*)pgc_rs.base());
! _next_top_at_mark_starts_base = NEW_C_HEAP_ARRAY(HeapWord*, _num_regions, mtGC);
! _next_top_at_mark_starts = _next_top_at_mark_starts_base -
((uintx) pgc_rs.base() >> ShenandoahHeapRegion::region_size_bytes_shift());
- _complete_top_at_mark_starts_base = NEW_C_HEAP_ARRAY(HeapWord*, _num_regions, mtGC);
- _complete_top_at_mark_starts = _complete_top_at_mark_starts_base -
- ((uintx) pgc_rs.base() >> ShenandoahHeapRegion::region_size_bytes_shift());
{
ShenandoahHeapLocker locker(lock());
for (size_t i = 0; i < _num_regions; i++) {
ShenandoahHeapRegion* r = new ShenandoahHeapRegion(this,
(HeapWord*) pgc_rs.base() + reg_size_words * i,
reg_size_words,
i,
i < num_committed_regions);
! _complete_top_at_mark_starts_base[i] = r->bottom();
! _next_top_at_mark_starts_base[i] = r->bottom();
// Add to ordered regions first.
// We use the active size of ordered regions as the number of active regions in heap,
// free set and collection set use the number to assert the correctness of incoming regions.
_ordered_regions->add_region(r);
--- 163,187 ----
_ordered_regions = new ShenandoahHeapRegionSet(_num_regions);
_free_regions = new ShenandoahFreeSet(_ordered_regions, _num_regions);
_collection_set = new ShenandoahCollectionSet(this, (HeapWord*)pgc_rs.base());
! _top_at_mark_starts_base = NEW_C_HEAP_ARRAY(HeapWord*, _num_regions, mtGC);
! _top_at_mark_starts = _top_at_mark_starts_base -
((uintx) pgc_rs.base() >> ShenandoahHeapRegion::region_size_bytes_shift());
{
ShenandoahHeapLocker locker(lock());
for (size_t i = 0; i < _num_regions; i++) {
ShenandoahHeapRegion* r = new ShenandoahHeapRegion(this,
(HeapWord*) pgc_rs.base() + reg_size_words * i,
reg_size_words,
i,
i < num_committed_regions);
! _top_at_mark_starts_base[i] = r->bottom();
// Add to ordered regions first.
// We use the active size of ordered regions as the number of active regions in heap,
// free set and collection set use the number to assert the correctness of incoming regions.
_ordered_regions->add_region(r);
*** 241,257 ****
"Bitmap words per region Should be power of two: " SIZE_FORMAT, _bitmap_words_per_region);
size_t bitmap_page_size = UseLargePages && (bitmap_bytes_per_region >= (size_t)os::large_page_size()) ?
(size_t)os::large_page_size() : (size_t)os::vm_page_size();
! ReservedSpace bitmap0(_bitmap_size, bitmap_page_size);
! MemTracker::record_virtual_memory_type(bitmap0.base(), mtGC);
! _bitmap0_region = MemRegion((HeapWord*) bitmap0.base(), bitmap0.size() / HeapWordSize);
!
! ReservedSpace bitmap1(_bitmap_size, bitmap_page_size);
! MemTracker::record_virtual_memory_type(bitmap1.base(), mtGC);
! _bitmap1_region = MemRegion((HeapWord*) bitmap1.base(), bitmap1.size() / HeapWordSize);
{
ShenandoahHeapLocker locker(lock());
for (size_t i = 0; i < _num_regions; i++) {
ShenandoahHeapRegion* r = _ordered_regions->get(i);
--- 231,243 ----
"Bitmap words per region Should be power of two: " SIZE_FORMAT, _bitmap_words_per_region);
size_t bitmap_page_size = UseLargePages && (bitmap_bytes_per_region >= (size_t)os::large_page_size()) ?
(size_t)os::large_page_size() : (size_t)os::vm_page_size();
! ReservedSpace bitmap(_bitmap_size, bitmap_page_size);
! MemTracker::record_virtual_memory_type(bitmap.base(), mtGC);
! _bitmap_region = MemRegion((HeapWord*) bitmap.base(), bitmap.size() / HeapWordSize);
{
ShenandoahHeapLocker locker(lock());
for (size_t i = 0; i < _num_regions; i++) {
ShenandoahHeapRegion* r = _ordered_regions->get(i);
*** 280,298 ****
// before initialize() below zeroes it with initializing thread. For any given region,
// we touch the region and the corresponding bitmaps from the same thread.
log_info(gc, heap)("Parallel pretouch " SIZE_FORMAT " regions with " SIZE_FORMAT " byte pages",
_ordered_regions->count(), page_size);
! ShenandoahPretouchTask cl(_ordered_regions, bitmap0.base(), bitmap1.base(), _bitmap_size, page_size);
_workers->run_task(&cl);
}
! _mark_bit_map0.initialize(_heap_region, _bitmap0_region);
! _complete_mark_bit_map = &_mark_bit_map0;
! _mark_bit_map1.initialize(_heap_region, _bitmap1_region);
! _next_mark_bit_map = &_mark_bit_map1;
if (UseShenandoahMatrix) {
_connection_matrix = new ShenandoahConnectionMatrix(_num_regions);
} else {
_connection_matrix = NULL;
--- 266,286 ----
// before initialize() below zeroes it with initializing thread. For any given region,
// we touch the region and the corresponding bitmaps from the same thread.
log_info(gc, heap)("Parallel pretouch " SIZE_FORMAT " regions with " SIZE_FORMAT " byte pages",
_ordered_regions->count(), page_size);
! ShenandoahPretouchTask cl(_ordered_regions, bitmap.base(), _bitmap_size, page_size);
_workers->run_task(&cl);
}
! _mark_bit_map.initialize(_heap_region, _bitmap_region);
! // Reserve aux bitmap for use in object_iterate(). We don't commit it here.
! ReservedSpace aux_bitmap(_bitmap_size, bitmap_page_size);
! MemTracker::record_virtual_memory_type(aux_bitmap.base(), mtGC);
! _aux_bitmap_region = MemRegion((HeapWord*) aux_bitmap.base(), aux_bitmap.size() / HeapWordSize);
! _aux_bit_map.initialize(_heap_region, _aux_bitmap_region);
if (UseShenandoahMatrix) {
_connection_matrix = new ShenandoahConnectionMatrix(_num_regions);
} else {
_connection_matrix = NULL;
*** 335,354 ****
_bytes_allocated_during_cm(0),
_allocated_last_gc(0),
_used_start_gc(0),
_max_workers(MAX2(ConcGCThreads, ParallelGCThreads)),
_ref_processor(NULL),
! _next_top_at_mark_starts(NULL),
! _next_top_at_mark_starts_base(NULL),
! _complete_top_at_mark_starts(NULL),
! _complete_top_at_mark_starts_base(NULL),
! _mark_bit_map0(),
! _mark_bit_map1(),
_connection_matrix(NULL),
_cancelled_concgc(0),
_need_update_refs(false),
! _need_reset_bitmaps(false),
_verifier(NULL),
_heap_lock(0),
_used_at_last_gc(0),
_alloc_seq_at_last_gc_start(0),
_alloc_seq_at_last_gc_end(0),
--- 323,341 ----
_bytes_allocated_during_cm(0),
_allocated_last_gc(0),
_used_start_gc(0),
_max_workers(MAX2(ConcGCThreads, ParallelGCThreads)),
_ref_processor(NULL),
! _top_at_mark_starts(NULL),
! _top_at_mark_starts_base(NULL),
! _mark_bit_map(),
! _aux_bit_map(),
_connection_matrix(NULL),
_cancelled_concgc(0),
_need_update_refs(false),
! _need_reset_bitmap(false),
! _bitmap_valid(true),
_verifier(NULL),
_heap_lock(0),
_used_at_last_gc(0),
_alloc_seq_at_last_gc_start(0),
_alloc_seq_at_last_gc_end(0),
*** 384,399 ****
false, false);
_safepoint_workers->initialize_workers();
}
}
! class ShenandoahResetNextBitmapTask : public AbstractGangTask {
private:
ShenandoahHeapRegionSet* _regions;
public:
! ShenandoahResetNextBitmapTask(ShenandoahHeapRegionSet* regions) :
AbstractGangTask("Parallel Reset Bitmap Task"),
_regions(regions) {
_regions->clear_current_index();
}
--- 371,386 ----
false, false);
_safepoint_workers->initialize_workers();
}
}
! class ShenandoahResetBitmapTask : public AbstractGangTask {
private:
ShenandoahHeapRegionSet* _regions;
public:
! ShenandoahResetBitmapTask(ShenandoahHeapRegionSet* regions) :
AbstractGangTask("Parallel Reset Bitmap Task"),
_regions(regions) {
_regions->clear_current_index();
}
*** 401,479 ****
ShenandoahHeapRegion* region = _regions->claim_next();
ShenandoahHeap* heap = ShenandoahHeap::heap();
while (region != NULL) {
if (region->is_committed()) {
HeapWord* bottom = region->bottom();
! HeapWord* top = heap->next_top_at_mark_start(region->bottom());
if (top > bottom) {
! heap->next_mark_bit_map()->clear_range_large(MemRegion(bottom, top));
}
! assert(heap->is_next_bitmap_clear_range(bottom, region->end()), "must be clear");
}
region = _regions->claim_next();
}
}
};
! void ShenandoahHeap::reset_next_mark_bitmap(WorkGang* workers) {
assert_gc_workers(workers->active_workers());
! ShenandoahResetNextBitmapTask task = ShenandoahResetNextBitmapTask(_ordered_regions);
workers->run_task(&task);
}
! class ShenandoahResetCompleteBitmapTask : public AbstractGangTask {
! private:
! ShenandoahHeapRegionSet* _regions;
!
! public:
! ShenandoahResetCompleteBitmapTask(ShenandoahHeapRegionSet* regions) :
! AbstractGangTask("Parallel Reset Bitmap Task"),
! _regions(regions) {
! _regions->clear_current_index();
! }
!
! void work(uint worker_id) {
! ShenandoahHeapRegion* region = _regions->claim_next();
! ShenandoahHeap* heap = ShenandoahHeap::heap();
! while (region != NULL) {
! if (region->is_committed()) {
! HeapWord* bottom = region->bottom();
! HeapWord* top = heap->complete_top_at_mark_start(region->bottom());
! if (top > bottom) {
! heap->complete_mark_bit_map()->clear_range_large(MemRegion(bottom, top));
! }
! assert(heap->is_complete_bitmap_clear_range(bottom, region->end()), "must be clear");
! }
! region = _regions->claim_next();
! }
! }
! };
!
! void ShenandoahHeap::reset_complete_mark_bitmap(WorkGang* workers) {
! assert_gc_workers(workers->active_workers());
!
! ShenandoahResetCompleteBitmapTask task = ShenandoahResetCompleteBitmapTask(_ordered_regions);
! workers->run_task(&task);
! }
!
! bool ShenandoahHeap::is_next_bitmap_clear() {
for (size_t idx = 0; idx < _num_regions; idx++) {
ShenandoahHeapRegion* r = _ordered_regions->get(idx);
! if (r->is_committed() && !is_next_bitmap_clear_range(r->bottom(), r->end())) {
return false;
}
}
return true;
}
! bool ShenandoahHeap::is_next_bitmap_clear_range(HeapWord* start, HeapWord* end) {
! return _next_mark_bit_map->getNextMarkedWordAddress(start, end) == end;
! }
!
! bool ShenandoahHeap::is_complete_bitmap_clear_range(HeapWord* start, HeapWord* end) {
! return _complete_mark_bit_map->getNextMarkedWordAddress(start, end) == end;
}
void ShenandoahHeap::print_on(outputStream* st) const {
st->print_cr("Shenandoah Heap");
st->print_cr(" " SIZE_FORMAT "K total, " SIZE_FORMAT "K committed, " SIZE_FORMAT "K used",
--- 388,428 ----
ShenandoahHeapRegion* region = _regions->claim_next();
ShenandoahHeap* heap = ShenandoahHeap::heap();
while (region != NULL) {
if (region->is_committed()) {
HeapWord* bottom = region->bottom();
! HeapWord* top = heap->top_at_mark_start(region->bottom());
if (top > bottom) {
! heap->mark_bit_map()->clear_range_large(MemRegion(bottom, top));
}
! assert(heap->is_bitmap_clear_range(bottom, region->end()), "must be clear");
! heap->set_top_at_mark_start(region->bottom(), region->bottom());
}
region = _regions->claim_next();
}
}
};
! void ShenandoahHeap::reset_mark_bitmap(WorkGang* workers) {
assert_gc_workers(workers->active_workers());
! ShenandoahResetBitmapTask task = ShenandoahResetBitmapTask(_ordered_regions);
workers->run_task(&task);
}
! bool ShenandoahHeap::is_bitmap_clear() {
for (size_t idx = 0; idx < _num_regions; idx++) {
ShenandoahHeapRegion* r = _ordered_regions->get(idx);
! if (r->is_committed() && !is_bitmap_clear_range(r->bottom(), r->end())) {
return false;
}
}
return true;
}
! bool ShenandoahHeap::is_bitmap_clear_range(HeapWord* start, HeapWord* end) {
! return _mark_bit_map.getNextMarkedWordAddress(start, end) == end;
}
void ShenandoahHeap::print_on(outputStream* st) const {
st->print_cr("Shenandoah Heap");
st->print_cr(" " SIZE_FORMAT "K total, " SIZE_FORMAT "K committed, " SIZE_FORMAT "K used",
*** 785,796 ****
T o = oopDesc::load_heap_oop(p);
if (! oopDesc::is_null(o)) {
oop obj = oopDesc::decode_heap_oop_not_null(o);
if (_heap->in_collection_set(obj)) {
! assert(_heap->is_marked_complete(obj), "only evacuate marked objects %d %d",
! _heap->is_marked_complete(obj), _heap->is_marked_complete(ShenandoahBarrierSet::resolve_oop_static_not_null(obj)));
oop resolved = ShenandoahBarrierSet::resolve_oop_static_not_null(obj);
if (oopDesc::unsafe_equals(resolved, obj)) {
bool evac;
resolved = _heap->evacuate_object(obj, _thread, evac);
}
--- 734,745 ----
T o = oopDesc::load_heap_oop(p);
if (! oopDesc::is_null(o)) {
oop obj = oopDesc::decode_heap_oop_not_null(o);
if (_heap->in_collection_set(obj)) {
! assert(_heap->is_marked(obj), "only evacuate marked objects %d %d",
! _heap->is_marked(obj), _heap->is_marked(ShenandoahBarrierSet::resolve_oop_static_not_null(obj)));
oop resolved = ShenandoahBarrierSet::resolve_oop_static_not_null(obj);
if (oopDesc::unsafe_equals(resolved, obj)) {
bool evac;
resolved = _heap->evacuate_object(obj, _thread, evac);
}
*** 849,859 ****
public:
ShenandoahParallelEvacuateRegionObjectClosure(ShenandoahHeap* heap) :
_heap(heap), _thread(Thread::current()) {}
void do_object(oop p) {
! assert(_heap->is_marked_complete(p), "expect only marked objects");
if (oopDesc::unsafe_equals(p, ShenandoahBarrierSet::resolve_oop_static_not_null(p))) {
bool evac;
_heap->evacuate_object(p, _thread, evac);
}
}
--- 798,808 ----
public:
ShenandoahParallelEvacuateRegionObjectClosure(ShenandoahHeap* heap) :
_heap(heap), _thread(Thread::current()) {}
void do_object(oop p) {
! assert(_heap->is_marked(p), "expect only marked objects");
if (oopDesc::unsafe_equals(p, ShenandoahBarrierSet::resolve_oop_static_not_null(p))) {
bool evac;
_heap->evacuate_object(p, _thread, evac);
}
}
*** 979,989 ****
if (!cancelled_concgc()) {
// Allocations might have happened before we STWed here, record peak:
shenandoahPolicy()->record_peak_occupancy();
! ensure_parsability(true);
if (ShenandoahVerify) {
verifier()->verify_after_concmark();
}
--- 928,938 ----
if (!cancelled_concgc()) {
// Allocations might have happened before we STWed here, record peak:
shenandoahPolicy()->record_peak_occupancy();
! make_tlabs_parsable(true);
if (ShenandoahVerify) {
verifier()->verify_after_concmark();
}
*** 1035,1045 ****
assert(thread->gclab().is_initialized(), "GCLAB should be initialized for %s", thread->name());
thread->gclab().make_parsable(_retire);
}
};
! void ShenandoahHeap::ensure_parsability(bool retire_tlabs) {
if (UseTLAB) {
CollectedHeap::ensure_parsability(retire_tlabs);
ShenandoahRetireTLABClosure cl(retire_tlabs);
Threads::java_threads_do(&cl);
gc_threads_do(&cl);
--- 984,994 ----
assert(thread->gclab().is_initialized(), "GCLAB should be initialized for %s", thread->name());
thread->gclab().make_parsable(_retire);
}
};
! void ShenandoahHeap::make_tlabs_parsable(bool retire_tlabs) {
if (UseTLAB) {
CollectedHeap::ensure_parsability(retire_tlabs);
ShenandoahRetireTLABClosure cl(retire_tlabs);
Threads::java_threads_do(&cl);
gc_threads_do(&cl);
*** 1301,1311 ****
return 0;
}
void ShenandoahHeap::prepare_for_verify() {
if (SafepointSynchronize::is_at_safepoint() || ! UseTLAB) {
! ensure_parsability(false);
}
}
void ShenandoahHeap::print_gc_threads_on(outputStream* st) const {
workers()->print_worker_threads_on(st);
--- 1250,1260 ----
return 0;
}
void ShenandoahHeap::prepare_for_verify() {
if (SafepointSynchronize::is_at_safepoint() || ! UseTLAB) {
! make_tlabs_parsable(false);
}
}
void ShenandoahHeap::print_gc_threads_on(outputStream* st) const {
workers()->print_worker_threads_on(st);
*** 1362,1434 ****
ShenandoahHeap::heap()->marked_object_iterate(r, _cl);
return false;
}
};
! void ShenandoahHeap::object_iterate(ObjectClosure* cl) {
! ShenandoahIterateObjectClosureRegionClosure blk(cl);
! heap_region_iterate(&blk, false, true);
! }
!
! class ShenandoahSafeObjectIterateAdjustPtrsClosure : public MetadataAwareOopClosure {
private:
! ShenandoahHeap* _heap;
- public:
- ShenandoahSafeObjectIterateAdjustPtrsClosure() : _heap(ShenandoahHeap::heap()) {}
-
- private:
template <class T>
! inline void do_oop_work(T* p) {
T o = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(o)) {
oop obj = oopDesc::decode_heap_oop_not_null(o);
! oopDesc::encode_store_heap_oop(p, BrooksPointer::forwardee(obj));
}
}
- public:
- void do_oop(oop* p) {
- do_oop_work(p);
}
- void do_oop(narrowOop* p) {
- do_oop_work(p);
- }
- };
- class ShenandoahSafeObjectIterateAndUpdate : public ObjectClosure {
- private:
- ObjectClosure* _cl;
public:
! ShenandoahSafeObjectIterateAndUpdate(ObjectClosure *cl) : _cl(cl) {}
! virtual void do_object(oop obj) {
! assert (oopDesc::unsafe_equals(obj, BrooksPointer::forwardee(obj)),
! "avoid double-counting: only non-forwarded objects here");
!
! // Fix up the ptrs.
! ShenandoahSafeObjectIterateAdjustPtrsClosure adjust_ptrs;
! obj->oop_iterate(&adjust_ptrs);
- // Can reply the object now:
- _cl->do_object(obj);
- }
- };
! void ShenandoahHeap::safe_object_iterate(ObjectClosure* cl) {
assert(SafepointSynchronize::is_at_safepoint(), "safe iteration is only available during safepoints");
! // Safe iteration does objects only with correct references.
! // This is why we skip collection set regions that have stale copies of objects,
! // and fix up the pointers in the returned objects.
!
! ShenandoahSafeObjectIterateAndUpdate safe_cl(cl);
! ShenandoahIterateObjectClosureRegionClosure blk(&safe_cl);
! heap_region_iterate(&blk,
! /* skip_cset_regions = */ true,
! /* skip_humongous_continuations = */ true);
! _need_update_refs = false; // already updated the references
}
// Apply blk->heap_region_do() on all committed regions in address order,
// terminating the iteration early if heap_region_do() returns true.
void ShenandoahHeap::heap_region_iterate(ShenandoahHeapRegionClosure* blk, bool skip_cset_regions, bool skip_humongous_continuation) const {
--- 1311,1408 ----
ShenandoahHeap::heap()->marked_object_iterate(r, _cl);
return false;
}
};
! class ObjectIterateScanRootClosure : public ExtendedOopClosure {
private:
! MarkBitMap* _bitmap;
! Stack<oop,mtGC>* _oop_stack;
template <class T>
! void do_oop_work(T* p) {
T o = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(o)) {
oop obj = oopDesc::decode_heap_oop_not_null(o);
! obj = ShenandoahBarrierSet::resolve_oop_static_not_null(obj);
! assert(oopDesc::is_oop(obj), "must be a valid oop");
! if (!_bitmap->isMarked((HeapWord*) obj)) {
! _bitmap->mark((HeapWord*) obj);
! _oop_stack->push(obj);
}
}
}
public:
! ObjectIterateScanRootClosure(MarkBitMap* bitmap, Stack<oop,mtGC>* oop_stack) :
! _bitmap(bitmap), _oop_stack(oop_stack) {}
! void do_oop(oop* p) { do_oop_work(p); }
! void do_oop(narrowOop* p) { do_oop_work(p); }
! };
! /*
! * This is public API, used in preparation of object_iterate().
! * Since we don't do linear scan of heap in object_iterate() (see comment below), we don't
! * need to make the heap parsable. For Shenandoah-internal linear heap scans that we can
! * control, we call SH::make_tlabs_parsable().
! */
! void ShenandoahHeap::ensure_parsability(bool retire_tlabs) {
! // No-op.
! }
! /*
! * Iterates objects in the heap. This is public API, used for, e.g., heap dumping.
! *
! * We cannot safely iterate objects by doing a linear scan at random points in time. Linear
! * scanning needs to deal with dead objects, which may have dead Klass* pointers (e.g.
! * calling oopDesc::size() would crash) or dangling reference fields (crashes) etc. Linear
! * scanning therefore depends on having a valid marking bitmap to support it. However, we only
! * have a valid marking bitmap after successful marking. In particular, we *don't* have a valid
! * marking bitmap during marking, after aborted marking or during/after cleanup (when we just
! * wiped the bitmap in preparation for next marking).
! *
! * For all those reasons, we implement object iteration as a single marking traversal, reporting
! * objects as we mark+traverse through the heap, starting from GC roots. This is ok. JVMTI
! * IterateThroughHeap is allowed to report dead objects, but is not required to do so.
! */
! void ShenandoahHeap::object_iterate(ObjectClosure* cl) {
assert(SafepointSynchronize::is_at_safepoint(), "safe iteration is only available during safepoints");
+ if (!os::commit_memory((char*)_aux_bitmap_region.start(), _aux_bitmap_region.byte_size(), false)) {
+ log_warning(gc)("Hold my beer, we are about to crash this VM.");
+ log_warning(gc)("Could not commit native memory for auxiliary marking bitmap for heap iteration");
+ return;
+ }
! Stack<oop,mtGC> oop_stack;
! // First, we process all GC roots. This populates the work stack with initial objects.
! ShenandoahRootProcessor rp(this, 1, ShenandoahPhaseTimings::_num_phases);
! ObjectIterateScanRootClosure oops(&_aux_bit_map, &oop_stack);
! CLDToOopClosure clds(&oops, false);
! CodeBlobToOopClosure blobs(&oops, false);
! rp.process_all_roots(&oops, &oops, &clds, &blobs, 0);
!
! // Work through the oop stack to traverse heap.
! while (! oop_stack.is_empty()) {
! oop obj = oop_stack.pop();
! assert(oopDesc::is_oop(obj), "must be a valid oop");
! cl->do_object(obj);
! obj->oop_iterate(&oops);
! }
!
! assert(oop_stack.is_empty(), "should be empty");
!
! if (!os::uncommit_memory((char*)_aux_bitmap_region.start(), _aux_bitmap_region.byte_size())) {
! log_warning(gc)("Hold my beer, we are about to crash this VM.");
! log_warning(gc)("Could not uncommit native memory for auxiliary marking bitmap for heap iteration");
! }
! }
!
! void ShenandoahHeap::safe_object_iterate(ObjectClosure* cl) {
! assert(SafepointSynchronize::is_at_safepoint(), "safe iteration is only available during safepoints");
! object_iterate(cl);
}
// Apply blk->heap_region_do() on all committed regions in address order,
// terminating the iteration early if heap_region_do() returns true.
void ShenandoahHeap::heap_region_iterate(ShenandoahHeapRegionClosure* blk, bool skip_cset_regions, bool skip_humongous_continuation) const {
*** 1452,1462 ****
public:
ShenandoahClearLivenessClosure(ShenandoahHeap* heap) : sh(heap) {}
bool heap_region_do(ShenandoahHeapRegion* r) {
r->clear_live_data();
! sh->set_next_top_at_mark_start(r->bottom(), r->top());
return false;
}
};
void ShenandoahHeap::start_concurrent_marking() {
--- 1426,1436 ----
public:
ShenandoahClearLivenessClosure(ShenandoahHeap* heap) : sh(heap) {}
bool heap_region_do(ShenandoahHeapRegion* r) {
r->clear_live_data();
! sh->set_top_at_mark_start(r->bottom(), r->top());
return false;
}
};
void ShenandoahHeap::start_concurrent_marking() {
*** 1471,1481 ****
set_concurrent_mark_in_progress(true);
// We need to reset all TLABs because we'd lose marks on all objects allocated in them.
if (UseTLAB) {
ShenandoahGCPhase phase(ShenandoahPhaseTimings::make_parsable);
! ensure_parsability(true);
}
_shenandoah_policy->record_bytes_allocated(_bytes_allocated_since_cm);
_used_start_gc = used();
--- 1445,1455 ----
set_concurrent_mark_in_progress(true);
// We need to reset all TLABs because we'd lose marks on all objects allocated in them.
if (UseTLAB) {
ShenandoahGCPhase phase(ShenandoahPhaseTimings::make_parsable);
! make_tlabs_parsable(true);
}
_shenandoah_policy->record_bytes_allocated(_bytes_allocated_since_cm);
_used_start_gc = used();
*** 1494,1527 ****
ShenandoahGCPhase phase(ShenandoahPhaseTimings::resize_tlabs);
resize_all_tlabs();
}
}
- void ShenandoahHeap::swap_mark_bitmaps() {
- // Swap bitmaps.
- MarkBitMap* tmp1 = _complete_mark_bit_map;
- _complete_mark_bit_map = _next_mark_bit_map;
- _next_mark_bit_map = tmp1;
-
- // Swap top-at-mark-start pointers
- HeapWord** tmp2 = _complete_top_at_mark_starts;
- _complete_top_at_mark_starts = _next_top_at_mark_starts;
- _next_top_at_mark_starts = tmp2;
-
- HeapWord** tmp3 = _complete_top_at_mark_starts_base;
- _complete_top_at_mark_starts_base = _next_top_at_mark_starts_base;
- _next_top_at_mark_starts_base = tmp3;
- }
-
-
void ShenandoahHeap::stop_concurrent_marking() {
assert(concurrent_mark_in_progress(), "How else could we get here?");
if (! cancelled_concgc()) {
// If we needed to update refs, and concurrent marking has been cancelled,
// we need to finish updating references.
set_need_update_refs(false);
- swap_mark_bitmaps();
}
set_concurrent_mark_in_progress(false);
LogTarget(Trace, gc, region) lt;
if (lt.is_enabled()) {
--- 1468,1483 ----
*** 1605,1626 ****
if (_heap->concurrent_mark_in_progress()) {
assert(oopDesc::unsafe_equals(obj, ShenandoahBarrierSet::resolve_oop_static_not_null(obj)), "only query to-space");
}
#endif
assert(!oopDesc::is_null(obj), "null");
! return _heap->is_marked_next(obj);
}
ShenandoahIsAliveClosure::ShenandoahIsAliveClosure() :
_heap(ShenandoahHeap::heap_no_check()) {
}
bool ShenandoahIsAliveClosure::do_object_b(oop obj) {
assert(_heap != NULL, "sanity");
assert(!oopDesc::is_null(obj), "null");
assert(oopDesc::unsafe_equals(obj, ShenandoahBarrierSet::resolve_oop_static_not_null(obj)), "only query to-space");
! return _heap->is_marked_next(obj);
}
BoolObjectClosure* ShenandoahHeap::is_alive_closure() {
return need_update_refs() ?
(BoolObjectClosure*) &_forwarded_is_alive :
--- 1561,1582 ----
if (_heap->concurrent_mark_in_progress()) {
assert(oopDesc::unsafe_equals(obj, ShenandoahBarrierSet::resolve_oop_static_not_null(obj)), "only query to-space");
}
#endif
assert(!oopDesc::is_null(obj), "null");
! return _heap->is_marked(obj);
}
ShenandoahIsAliveClosure::ShenandoahIsAliveClosure() :
_heap(ShenandoahHeap::heap_no_check()) {
}
bool ShenandoahIsAliveClosure::do_object_b(oop obj) {
assert(_heap != NULL, "sanity");
assert(!oopDesc::is_null(obj), "null");
assert(oopDesc::unsafe_equals(obj, ShenandoahBarrierSet::resolve_oop_static_not_null(obj)), "only query to-space");
! return _heap->is_marked(obj);
}
BoolObjectClosure* ShenandoahHeap::is_alive_closure() {
return need_update_refs() ?
(BoolObjectClosure*) &_forwarded_is_alive :
*** 1803,1818 ****
ShenandoahMonitoringSupport* ShenandoahHeap::monitoring_support() {
return _monitoring_support;
}
! MarkBitMap* ShenandoahHeap::complete_mark_bit_map() {
! return _complete_mark_bit_map;
! }
!
! MarkBitMap* ShenandoahHeap::next_mark_bit_map() {
! return _next_mark_bit_map;
}
void ShenandoahHeap::add_free_region(ShenandoahHeapRegion* r) {
_free_regions->add_region(r);
}
--- 1759,1770 ----
ShenandoahMonitoringSupport* ShenandoahHeap::monitoring_support() {
return _monitoring_support;
}
! MarkBitMap* ShenandoahHeap::mark_bit_map() {
! return &_mark_bit_map;
}
void ShenandoahHeap::add_free_region(ShenandoahHeapRegion* r) {
_free_regions->add_region(r);
}
*** 1842,1869 ****
void ShenandoahHeap::set_bytes_allocated_since_cm(size_t bytes) {
_bytes_allocated_since_cm = bytes;
}
! void ShenandoahHeap::set_next_top_at_mark_start(HeapWord* region_base, HeapWord* addr) {
uintx index = ((uintx) region_base) >> ShenandoahHeapRegion::region_size_bytes_shift();
! _next_top_at_mark_starts[index] = addr;
}
! HeapWord* ShenandoahHeap::next_top_at_mark_start(HeapWord* region_base) {
uintx index = ((uintx) region_base) >> ShenandoahHeapRegion::region_size_bytes_shift();
! return _next_top_at_mark_starts[index];
! }
!
! void ShenandoahHeap::set_complete_top_at_mark_start(HeapWord* region_base, HeapWord* addr) {
! uintx index = ((uintx) region_base) >> ShenandoahHeapRegion::region_size_bytes_shift();
! _complete_top_at_mark_starts[index] = addr;
! }
!
! HeapWord* ShenandoahHeap::complete_top_at_mark_start(HeapWord* region_base) {
! uintx index = ((uintx) region_base) >> ShenandoahHeapRegion::region_size_bytes_shift();
! return _complete_top_at_mark_starts[index];
}
void ShenandoahHeap::set_full_gc_in_progress(bool in_progress) {
_full_gc_in_progress = in_progress;
}
--- 1794,1811 ----
void ShenandoahHeap::set_bytes_allocated_since_cm(size_t bytes) {
_bytes_allocated_since_cm = bytes;
}
! void ShenandoahHeap::set_top_at_mark_start(HeapWord* region_base, HeapWord* addr) {
uintx index = ((uintx) region_base) >> ShenandoahHeapRegion::region_size_bytes_shift();
! _top_at_mark_starts[index] = addr;
}
! HeapWord* ShenandoahHeap::top_at_mark_start(HeapWord* region_base) {
uintx index = ((uintx) region_base) >> ShenandoahHeapRegion::region_size_bytes_shift();
! return _top_at_mark_starts[index];
}
void ShenandoahHeap::set_full_gc_in_progress(bool in_progress) {
_full_gc_in_progress = in_progress;
}
*** 1985,1997 ****
SuspendibleThreadSetJoiner stsj(_concurrent && ShenandoahSuspendibleWorkers);
ShenandoahHeapRegion* r = _regions->claim_next();
while (r != NULL) {
if (_heap->in_collection_set(r)) {
HeapWord* bottom = r->bottom();
! HeapWord* top = _heap->complete_top_at_mark_start(r->bottom());
if (top > bottom) {
! _heap->complete_mark_bit_map()->clear_range_large(MemRegion(bottom, top));
}
} else {
if (r->is_active()) {
_heap->marked_object_oop_safe_iterate(r, &cl);
}
--- 1927,1939 ----
SuspendibleThreadSetJoiner stsj(_concurrent && ShenandoahSuspendibleWorkers);
ShenandoahHeapRegion* r = _regions->claim_next();
while (r != NULL) {
if (_heap->in_collection_set(r)) {
HeapWord* bottom = r->bottom();
! HeapWord* top = _heap->top_at_mark_start(r->bottom());
if (top > bottom) {
! _heap->mark_bit_map()->clear_range_large(MemRegion(bottom, top));
}
} else {
if (r->is_active()) {
_heap->marked_object_oop_safe_iterate(r, &cl);
}
*** 2028,2038 ****
verifier()->verify_before_updaterefs();
}
set_evacuation_in_progress_at_safepoint(false);
set_update_refs_in_progress(true);
! ensure_parsability(true);
if (UseShenandoahMatrix) {
connection_matrix()->clear_all();
}
for (uint i = 0; i < num_regions(); i++) {
ShenandoahHeapRegion* r = _ordered_regions->get(i);
--- 1970,1980 ----
verifier()->verify_before_updaterefs();
}
set_evacuation_in_progress_at_safepoint(false);
set_update_refs_in_progress(true);
! make_tlabs_parsable(true);
if (UseShenandoahMatrix) {
connection_matrix()->clear_all();
}
for (uint i = 0; i < num_regions(); i++) {
ShenandoahHeapRegion* r = _ordered_regions->get(i);
*** 2193,2217 ****
}
bool ShenandoahHeap::commit_bitmaps(ShenandoahHeapRegion* r) {
size_t len = _bitmap_words_per_region * HeapWordSize;
size_t off = r->region_number() * _bitmap_words_per_region;
! if (!os::commit_memory((char*)(_bitmap0_region.start() + off), len, false)) {
! return false;
! }
! if (!os::commit_memory((char*)(_bitmap1_region.start() + off), len, false)) {
return false;
}
return true;
}
bool ShenandoahHeap::uncommit_bitmaps(ShenandoahHeapRegion* r) {
size_t len = _bitmap_words_per_region * HeapWordSize;
size_t off = r->region_number() * _bitmap_words_per_region;
! if (!os::uncommit_memory((char*)(_bitmap0_region.start() + off), len)) {
! return false;
! }
! if (!os::uncommit_memory((char*)(_bitmap1_region.start() + off), len)) {
return false;
}
return true;
}
--- 2135,2153 ----
}
bool ShenandoahHeap::commit_bitmaps(ShenandoahHeapRegion* r) {
size_t len = _bitmap_words_per_region * HeapWordSize;
size_t off = r->region_number() * _bitmap_words_per_region;
! if (!os::commit_memory((char*)(_bitmap_region.start() + off), len, false)) {
return false;
}
return true;
}
bool ShenandoahHeap::uncommit_bitmaps(ShenandoahHeapRegion* r) {
size_t len = _bitmap_words_per_region * HeapWordSize;
size_t off = r->region_number() * _bitmap_words_per_region;
! if (!os::uncommit_memory((char*)(_bitmap_region.start() + off), len)) {
return false;
}
return true;
}
< prev index next >