< 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 >