< prev index next >

src/hotspot/share/gc/g1/satbMarkQueue.cpp

Print this page

        

*** 33,42 **** --- 33,46 ---- #include "runtime/mutexLocker.hpp" #include "runtime/safepoint.hpp" #include "runtime/thread.hpp" #include "runtime/threadSMR.hpp" #include "runtime/vmThread.hpp" + #include "utilities/macros.hpp" + #if INCLUDE_SHENANDOAHGC + #include "gc/shenandoah/shenandoahHeap.inline.hpp" + #endif SATBMarkQueue::SATBMarkQueue(SATBMarkQueueSet* qset, bool permanent) : // SATB queues are only active during marking cycles. We create // them with their active field set to false. If a thread is // created during a cycle and its SATB queue needs to be activated
*** 84,121 **** // The stale reference cases are implicitly handled by the NTAMS // comparison. Because of the possibility of stale references, buffer // processing must be somewhat circumspect and not assume entries // in an unfiltered buffer refer to valid objects. ! inline bool requires_marking(const void* entry, G1CollectedHeap* heap) { ! // Includes rejection of NULL pointers. ! assert(heap->is_in_reserved(entry), ! "Non-heap pointer in SATB buffer: " PTR_FORMAT, p2i(entry)); ! ! HeapRegion* region = heap->heap_region_containing(entry); ! assert(region != NULL, "No region for " PTR_FORMAT, p2i(entry)); ! if (entry >= region->next_top_at_mark_start()) { ! return false; ! } ! ! assert(oopDesc::is_oop(oop(entry), true /* ignore mark word */), ! "Invalid oop in SATB buffer: " PTR_FORMAT, p2i(entry)); ! ! return true; } ! inline bool retain_entry(const void* entry, G1CollectedHeap* heap) { ! return requires_marking(entry, heap) && !heap->is_marked_next((oop)entry); } // This method removes entries from a SATB buffer that will not be // useful to the concurrent marking threads. Entries are retained if // they require marking and are not already marked. Retained entries // are compacted toward the top of the buffer. ! void SATBMarkQueue::filter() { ! G1CollectedHeap* g1h = G1CollectedHeap::heap(); void** buf = _buf; if (buf == NULL) { // nothing to do return; --- 88,122 ---- // The stale reference cases are implicitly handled by the NTAMS // comparison. Because of the possibility of stale references, buffer // processing must be somewhat circumspect and not assume entries // in an unfiltered buffer refer to valid objects. ! template <class HeapType> ! inline bool retain_entry(const void* entry, HeapType* heap) { ! return heap->requires_marking(entry); } ! void SATBMarkQueue::filter() { ! if (UseG1GC) { ! filter_impl<G1CollectedHeap>(); ! #if INCLUDE_SHENANDOAHGC ! } else if (UseShenandoahGC) { ! filter_impl<ShenandoahHeap>(); ! #endif ! } else { ! ShouldNotReachHere(); ! } } // This method removes entries from a SATB buffer that will not be // useful to the concurrent marking threads. Entries are retained if // they require marking and are not already marked. Retained entries // are compacted toward the top of the buffer. ! template <class HeapType> ! void SATBMarkQueue::filter_impl() { ! HeapType* heap = (HeapType*) Universe::heap(); void** buf = _buf; if (buf == NULL) { // nothing to do return;
*** 126,139 **** void** dst = &buf[capacity()]; assert(src <= dst, "invariant"); for ( ; src < dst; ++src) { // Search low to high for an entry to keep. void* entry = *src; ! if (retain_entry(entry, g1h)) { // Found keeper. Search high to low for an entry to discard. while (src < --dst) { ! if (!retain_entry(*dst, g1h)) { *dst = entry; // Replace discard with keeper. break; } } // If discard search failed (src == dst), the outer loop will also end. --- 127,140 ---- void** dst = &buf[capacity()]; assert(src <= dst, "invariant"); for ( ; src < dst; ++src) { // Search low to high for an entry to keep. void* entry = *src; ! if (retain_entry(entry, heap)) { // Found keeper. Search high to low for an entry to discard. while (src < --dst) { ! if (!retain_entry(*dst, heap)) { *dst = entry; // Replace discard with keeper. break; } } // If discard search failed (src == dst), the outer loop will also end.
*** 163,174 **** filter(); size_t cap = capacity(); size_t percent_used = ((cap - index()) * 100) / cap; ! bool should_enqueue = percent_used > G1SATBBufferEnqueueingThresholdPercent; ! return should_enqueue; } void SATBMarkQueue::apply_closure_and_empty(SATBBufferClosure* cl) { assert(SafepointSynchronize::is_at_safepoint(), "SATB queues must only be processed at safepoints"); --- 164,174 ---- filter(); size_t cap = capacity(); size_t percent_used = ((cap - index()) * 100) / cap; ! return percent_used > G1SATBBufferEnqueueingThresholdPercent; } void SATBMarkQueue::apply_closure_and_empty(SATBBufferClosure* cl) { assert(SafepointSynchronize::is_at_safepoint(), "SATB queues must only be processed at safepoints");
*** 205,225 **** Mutex* lock) { PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold, -1); _shared_satb_queue.set_lock(lock); } - void SATBMarkQueueSet::handle_zero_index_for_thread(JavaThread* t) { - G1ThreadLocalData::satb_mark_queue(t).handle_zero_index(); - } - #ifdef ASSERT void SATBMarkQueueSet::dump_active_states(bool expected_active) { log_error(gc, verify)("Expected SATB active state: %s", expected_active ? "ACTIVE" : "INACTIVE"); log_error(gc, verify)("Actual SATB active states:"); log_error(gc, verify)(" Queue set: %s", is_active() ? "ACTIVE" : "INACTIVE"); for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { ! log_error(gc, verify)(" Thread \"%s\" queue: %s", t->name(), G1ThreadLocalData::satb_mark_queue(t).is_active() ? "ACTIVE" : "INACTIVE"); } log_error(gc, verify)(" Shared queue: %s", shared_satb_queue()->is_active() ? "ACTIVE" : "INACTIVE"); } void SATBMarkQueueSet::verify_active_states(bool expected_active) { --- 205,221 ---- Mutex* lock) { PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold, -1); _shared_satb_queue.set_lock(lock); } #ifdef ASSERT void SATBMarkQueueSet::dump_active_states(bool expected_active) { log_error(gc, verify)("Expected SATB active state: %s", expected_active ? "ACTIVE" : "INACTIVE"); log_error(gc, verify)("Actual SATB active states:"); log_error(gc, verify)(" Queue set: %s", is_active() ? "ACTIVE" : "INACTIVE"); for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { ! log_error(gc, verify)(" Thread \"%s\" queue: %s", t->name(), satb_queue_for_thread(t).is_active() ? "ACTIVE" : "INACTIVE"); } log_error(gc, verify)(" Shared queue: %s", shared_satb_queue()->is_active() ? "ACTIVE" : "INACTIVE"); } void SATBMarkQueueSet::verify_active_states(bool expected_active) {
*** 229,239 **** guarantee(false, "SATB queue set has an unexpected active state"); } // Verify thread queue states for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { ! if (G1ThreadLocalData::satb_mark_queue(t).is_active() != expected_active) { dump_active_states(expected_active); guarantee(false, "Thread SATB queue has an unexpected active state"); } } --- 225,235 ---- guarantee(false, "SATB queue set has an unexpected active state"); } // Verify thread queue states for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { ! if (satb_queue_for_thread(t).is_active() != expected_active) { dump_active_states(expected_active); guarantee(false, "Thread SATB queue has an unexpected active state"); } }
*** 250,267 **** #ifdef ASSERT verify_active_states(expected_active); #endif // ASSERT _all_active = active; for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { ! G1ThreadLocalData::satb_mark_queue(t).set_active(active); } shared_satb_queue()->set_active(active); } void SATBMarkQueueSet::filter_thread_buffers() { for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { ! G1ThreadLocalData::satb_mark_queue(t).filter(); } shared_satb_queue()->filter(); } bool SATBMarkQueueSet::apply_closure_to_completed_buffer(SATBBufferClosure* cl) { --- 246,263 ---- #ifdef ASSERT verify_active_states(expected_active); #endif // ASSERT _all_active = active; for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { ! satb_queue_for_thread(t).set_active(active); } shared_satb_queue()->set_active(active); } void SATBMarkQueueSet::filter_thread_buffers() { for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { ! satb_queue_for_thread(t).filter(); } shared_satb_queue()->filter(); } bool SATBMarkQueueSet::apply_closure_to_completed_buffer(SATBBufferClosure* cl) {
*** 311,321 **** i += 1; } for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { jio_snprintf(buffer, SATB_PRINTER_BUFFER_SIZE, "Thread: %s", t->name()); ! G1ThreadLocalData::satb_mark_queue(t).print(buffer); } shared_satb_queue()->print("Shared"); tty->cr(); --- 307,317 ---- i += 1; } for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { jio_snprintf(buffer, SATB_PRINTER_BUFFER_SIZE, "Thread: %s", t->name()); ! satb_queue_for_thread(t).print(buffer); } shared_satb_queue()->print("Shared"); tty->cr();
*** 342,350 **** deallocate_buffer(nd); } assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); // So we can safely manipulate these queues. for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { ! G1ThreadLocalData::satb_mark_queue(t).reset(); } shared_satb_queue()->reset(); } --- 338,355 ---- deallocate_buffer(nd); } assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); // So we can safely manipulate these queues. for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { ! satb_queue_for_thread(t).reset(); } shared_satb_queue()->reset(); } + + void G1SATBMarkQueueSet::handle_zero_index_for_thread(JavaThread* t) { + G1ThreadLocalData::satb_mark_queue(t).handle_zero_index(); + } + + SATBMarkQueue& G1SATBMarkQueueSet::satb_queue_for_thread(Thread* t) { + return G1ThreadLocalData::satb_mark_queue(t); + } +
< prev index next >