< prev index next >

hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp

Print this page
rev 7368 : 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); } } } };
*** 3057,3069 **** } #ifndef PRODUCT enum VerifyNoCSetOopsPhase { VerifyNoCSetOopsStack, ! VerifyNoCSetOopsQueues, ! VerifyNoCSetOopsSATBCompleted, ! VerifyNoCSetOopsSATBThread }; class VerifyNoCSetOopsClosure : public OopClosure, public ObjectClosure { private: G1CollectedHeap* _g1h; --- 3076,3086 ---- } #ifndef PRODUCT enum VerifyNoCSetOopsPhase { VerifyNoCSetOopsStack, ! VerifyNoCSetOopsQueues }; class VerifyNoCSetOopsClosure : public OopClosure, public ObjectClosure { private: G1CollectedHeap* _g1h;
*** 3072,3083 **** const char* phase_str() { switch (_phase) { case VerifyNoCSetOopsStack: return "Stack"; case VerifyNoCSetOopsQueues: return "Queue"; - case VerifyNoCSetOopsSATBCompleted: return "Completed SATB Buffers"; - case VerifyNoCSetOopsSATBThread: return "Thread SATB Buffers"; default: ShouldNotReachHere(); } return NULL; } --- 3089,3098 ----
*** 3100,3157 **** do_object_work(obj); } virtual void do_oop(narrowOop* p) { // We should not come across narrow oops while scanning marking ! // stacks and SATB buffers. ShouldNotReachHere(); } virtual void do_object(oop obj) { do_object_work(obj); } }; ! void ConcurrentMark::verify_no_cset_oops(bool verify_stacks, ! bool verify_enqueued_buffers, ! bool verify_thread_buffers, ! bool verify_fingers) { assert(SafepointSynchronize::is_at_safepoint(), "should be at a safepoint"); if (!G1CollectedHeap::heap()->mark_in_progress()) { return; } VerifyNoCSetOopsClosure cl; - if (verify_stacks) { // Verify entries on the global mark stack cl.set_phase(VerifyNoCSetOopsStack); _markStack.oops_do(&cl); // Verify entries on the task queues for (uint i = 0; i < _max_worker_id; i += 1) { cl.set_phase(VerifyNoCSetOopsQueues, i); CMTaskQueue* queue = _task_queues->queue(i); queue->oops_do(&cl); } - } - SATBMarkQueueSet& satb_qs = JavaThread::satb_mark_queue_set(); - - // Verify entries on the enqueued SATB buffers - if (verify_enqueued_buffers) { - cl.set_phase(VerifyNoCSetOopsSATBCompleted); - satb_qs.iterate_completed_buffers_read_only(&cl); - } - - // Verify entries on the per-thread SATB buffers - if (verify_thread_buffers) { - cl.set_phase(VerifyNoCSetOopsSATBThread); - satb_qs.iterate_thread_buffers_read_only(&cl); - } - - if (verify_fingers) { // Verify the global finger HeapWord* global_finger = finger(); if (global_finger != NULL && global_finger < _heap_end) { // The global finger always points to a heap region boundary. We // use heap_region_containing_raw() to get the containing region --- 3115,3152 ---- do_object_work(obj); } virtual void do_oop(narrowOop* p) { // We should not come across narrow oops while scanning marking ! // stacks ShouldNotReachHere(); } virtual void do_object(oop obj) { do_object_work(obj); } }; ! void ConcurrentMark::verify_no_cset_oops() { assert(SafepointSynchronize::is_at_safepoint(), "should be at a safepoint"); if (!G1CollectedHeap::heap()->mark_in_progress()) { return; } VerifyNoCSetOopsClosure cl; // Verify entries on the global mark stack cl.set_phase(VerifyNoCSetOopsStack); _markStack.oops_do(&cl); // Verify entries on the task queues for (uint i = 0; i < _max_worker_id; i += 1) { cl.set_phase(VerifyNoCSetOopsQueues, i); CMTaskQueue* queue = _task_queues->queue(i); queue->oops_do(&cl); } // Verify the global finger HeapWord* global_finger = finger(); if (global_finger != NULL && global_finger < _heap_end) { // The global finger always points to a heap region boundary. We // use heap_region_containing_raw() to get the containing region
*** 3180,3190 **** !task_hr->in_collection_set(), err_msg("task finger: "PTR_FORMAT" region: "HR_FORMAT, p2i(task_finger), HR_FORMAT_PARAMS(task_hr))); } } - } } #endif // PRODUCT // Aggregate the counting data that was constructed concurrently // with marking. --- 3175,3184 ----
*** 3508,3533 **** } gclog_or_tty->cr(); } #endif ! void CMTask::scan_object(oop obj) { assert(_nextMarkBitMap->isMarked((HeapWord*) obj), "invariant"); if (_cm->verbose_high()) { ! gclog_or_tty->print_cr("[%u] we're scanning object "PTR_FORMAT, _worker_id, p2i((void*) obj)); } size_t obj_size = obj->size(); _words_scanned += obj_size; obj->oop_iterate(_cm_oop_closure); statsOnly( ++_objs_scanned ); check_limits(); } // Closure for iteration over bitmaps class CMBitMapClosure : public BitMapClosure { private: // the bitmap that is being iterated over CMBitMap* _nextMarkBitMap; --- 3502,3534 ---- } gclog_or_tty->cr(); } #endif ! template<bool scan> ! inline void CMTask::process_grey_object(oop obj) { ! assert(scan || obj->is_typeArray(), "Skipping scan of grey non-typeArray"); assert(_nextMarkBitMap->isMarked((HeapWord*) obj), "invariant"); if (_cm->verbose_high()) { ! gclog_or_tty->print_cr("[%u] processing grey object " PTR_FORMAT, _worker_id, p2i((void*) obj)); } size_t obj_size = obj->size(); _words_scanned += obj_size; + if (scan) { obj->oop_iterate(_cm_oop_closure); + } statsOnly( ++_objs_scanned ); check_limits(); } + template void CMTask::process_grey_object<true>(oop); + template void CMTask::process_grey_object<false>(oop); + // Closure for iteration over bitmaps class CMBitMapClosure : public BitMapClosure { private: // the bitmap that is being iterated over CMBitMap* _nextMarkBitMap;
*** 3992,4043 **** // 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(); - if (G1CollectedHeap::use_parallel_gc_threads()) { - satb_mq_set.set_par_closure(_worker_id, &oc); - } else { - satb_mq_set.set_closure(&oc); - } // This keeps claiming and applying the closure to completed buffers // until we run out of buffers or we need to abort. - if (G1CollectedHeap::use_parallel_gc_threads()) { while (!has_aborted() && ! satb_mq_set.par_apply_closure_to_completed_buffer(_worker_id)) { if (_cm->verbose_medium()) { gclog_or_tty->print_cr("[%u] processed an SATB buffer", _worker_id); } statsOnly( ++_satb_buffers_processed ); regular_clock_call(); } - } else { - while (!has_aborted() && - satb_mq_set.apply_closure_to_completed_buffer()) { - if (_cm->verbose_medium()) { - gclog_or_tty->print_cr("[%u] processed an SATB buffer", _worker_id); - } - statsOnly( ++_satb_buffers_processed ); - regular_clock_call(); - } - } _draining_satb_buffers = false; assert(has_aborted() || concurrent() || satb_mq_set.completed_buffers_num() == 0, "invariant"); - if (G1CollectedHeap::use_parallel_gc_threads()) { - satb_mq_set.set_par_closure(_worker_id, NULL); - } else { - satb_mq_set.set_closure(NULL); - } - // again, this was a potentially expensive operation, decrease the // limits to get the regular clock call early decrease_limits(); } --- 3993,4022 ---- // 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(); } _draining_satb_buffers = false; assert(has_aborted() || concurrent() || satb_mq_set.completed_buffers_num() == 0, "invariant"); // again, this was a potentially expensive operation, decrease the // limits to get the regular clock call early decrease_limits(); }
< prev index next >