< prev index next >
src/share/vm/gc_implementation/g1/concurrentMark.cpp
Print this page
rev 7327 : 8075215: SATB buffer processing found reclaimed humongous object
Summary: Don't assume SATB buffer entries are valid objects
Reviewed-by: brutisso, ecaspole
*** 2638,2673 ****
CMBitMapRO* temp = _prevMarkBitMap;
_prevMarkBitMap = (CMBitMapRO*)_nextMarkBitMap;
_nextMarkBitMap = (CMBitMap*) temp;
}
! class CMObjectClosure;
!
! // Closure for iterating over objects, currently only used for
! // processing SATB buffers.
! class CMObjectClosure : public ObjectClosure {
private:
CMTask* _task;
! public:
! void do_object(oop obj) {
! _task->deal_with_reference(obj);
}
! CMObjectClosure(CMTask* task) : _task(task) { }
};
class G1RemarkThreadsClosure : public ThreadClosure {
! CMObjectClosure _cm_obj;
G1CMOopClosure _cm_cl;
MarkingCodeBlobClosure _code_cl;
int _thread_parity;
bool _is_par;
public:
G1RemarkThreadsClosure(G1CollectedHeap* g1h, CMTask* task, bool is_par) :
! _cm_obj(task), _cm_cl(g1h, g1h->concurrent_mark(), task), _code_cl(&_cm_cl, !CodeBlobToOopClosure::FixRelocations),
_thread_parity(SharedHeap::heap()->strong_roots_parity()), _is_par(is_par) {}
void do_thread(Thread* thread) {
if (thread->is_Java_thread()) {
if (thread->claim_oops_do(_is_par, _thread_parity)) {
--- 2638,2692 ----
CMBitMapRO* temp = _prevMarkBitMap;
_prevMarkBitMap = (CMBitMapRO*)_nextMarkBitMap;
_nextMarkBitMap = (CMBitMap*) temp;
}
! // Closure for marking entries in SATB buffers.
! class CMSATBBufferClosure : public SATBBufferClosure {
private:
CMTask* _task;
+ G1CollectedHeap* _g1h;
! // This is very similar to CMTask::deal_with_reference, but with
! // more relaxed requirements for the argument, so this must be more
! // circumspect about treating the argument as an object.
! void do_entry(void* entry) const {
! _task->increment_refs_reached();
! HeapRegion* hr = _g1h->heap_region_containing_raw(entry);
! if (entry < hr->next_top_at_mark_start()) {
! // 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 */),
! err_msg("Invalid oop in SATB buffer: " PTR_FORMAT, p2i(obj)));
! _task->make_reference_grey(obj, hr);
! }
}
! public:
! CMSATBBufferClosure(CMTask* task, G1CollectedHeap* g1h)
! : _task(task), _g1h(g1h) { }
!
! virtual void do_buffer(void** buffer, size_t size) {
! for (size_t i = 0; i < size; ++i) {
! do_entry(buffer[i]);
! }
! }
};
class G1RemarkThreadsClosure : public ThreadClosure {
! CMSATBBufferClosure _cm_satb_cl;
G1CMOopClosure _cm_cl;
MarkingCodeBlobClosure _code_cl;
int _thread_parity;
bool _is_par;
public:
G1RemarkThreadsClosure(G1CollectedHeap* g1h, CMTask* task, bool is_par) :
! _cm_satb_cl(task, g1h),
! _cm_cl(g1h, g1h->concurrent_mark(), task),
! _code_cl(&_cm_cl, !CodeBlobToOopClosure::FixRelocations),
_thread_parity(SharedHeap::heap()->strong_roots_parity()), _is_par(is_par) {}
void do_thread(Thread* thread) {
if (thread->is_Java_thread()) {
if (thread->claim_oops_do(_is_par, _thread_parity)) {
*** 2679,2693 ****
// * Weakly reachable otherwise
// Some objects reachable from nmethods, such as the class loader (or klass_holder) of the receiver should be
// live by the SATB invariant but other oops recorded in nmethods may behave differently.
jt->nmethods_do(&_code_cl);
! jt->satb_mark_queue().apply_closure_and_empty(&_cm_obj);
}
} else if (thread->is_VM_thread()) {
if (thread->claim_oops_do(_is_par, _thread_parity)) {
! JavaThread::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(&_cm_obj);
}
}
}
};
--- 2698,2712 ----
// * Weakly reachable otherwise
// Some objects reachable from nmethods, such as the class loader (or klass_holder) of the receiver should be
// live by the SATB invariant but other oops recorded in nmethods may behave differently.
jt->nmethods_do(&_code_cl);
! jt->satb_mark_queue().apply_closure_and_empty(&_cm_satb_cl);
}
} else if (thread->is_VM_thread()) {
if (thread->claim_oops_do(_is_par, _thread_parity)) {
! JavaThread::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(&_cm_satb_cl);
}
}
}
};
*** 3974,3990 ****
// middle of draining buffers and doesn't set the abort flag when it
// notices that SATB buffers are available for draining. It'd be
// very counter productive if it did that. :-)
_draining_satb_buffers = true;
! CMObjectClosure oc(this);
SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
// This keeps claiming and applying the closure to completed buffers
// until we run out of buffers or we need to abort.
while (!has_aborted() &&
! satb_mq_set.apply_closure_to_completed_buffer(&oc)) {
if (_cm->verbose_medium()) {
gclog_or_tty->print_cr("[%u] processed an SATB buffer", _worker_id);
}
statsOnly( ++_satb_buffers_processed );
regular_clock_call();
--- 3993,4009 ----
// middle of draining buffers and doesn't set the abort flag when it
// notices that SATB buffers are available for draining. It'd be
// very counter productive if it did that. :-)
_draining_satb_buffers = true;
! CMSATBBufferClosure satb_cl(this, _g1h);
SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
// This keeps claiming and applying the closure to completed buffers
// until we run out of buffers or we need to abort.
while (!has_aborted() &&
! satb_mq_set.apply_closure_to_completed_buffer(&satb_cl)) {
if (_cm->verbose_medium()) {
gclog_or_tty->print_cr("[%u] processed an SATB buffer", _worker_id);
}
statsOnly( ++_satb_buffers_processed );
regular_clock_call();
< prev index next >