< prev index next >
src/hotspot/share/gc/g1/g1RemSet.cpp
Print this page
rev 56898 : 8087198: G1 card refinement: batching, sorting
Reviewed-by: tschatzl
@@ -1259,29 +1259,28 @@
p2i(ct->addr_for(card_ptr)),
g1h->addr_to_region(ct->addr_for(card_ptr)));
#endif
}
-void G1RemSet::refine_card_concurrently(CardValue* card_ptr,
- uint worker_id) {
+bool G1RemSet::clean_card_before_refine(CardValue*& card_ptr) {
assert(!_g1h->is_gc_active(), "Only call concurrently");
- // Construct the region representing the card.
+ // Find the start address represented by the card.
HeapWord* start = _ct->addr_for(card_ptr);
// And find the region containing it.
HeapRegion* r = _g1h->heap_region_containing_or_null(start);
// If this is a (stale) card into an uncommitted region, exit.
if (r == NULL) {
- return;
+ return false;
}
check_card_ptr(card_ptr, _ct);
// If the card is no longer dirty, nothing to do.
if (*card_ptr != G1CardTable::dirty_card_val()) {
- return;
+ return false;
}
// This check is needed for some uncommon cases where we should
// ignore the card.
//
@@ -1300,11 +1299,11 @@
//
// In the normal (non-stale) case, the synchronization between the
// enqueueing of the card and processing it here will have ensured
// we see the up-to-date region type here.
if (!r->is_old_or_humongous_or_archive()) {
- return;
+ return false;
}
// The result from the hot card cache insert call is either:
// * pointer to the current card
// (implying that the current card is not 'hot'),
@@ -1319,21 +1318,21 @@
const CardValue* orig_card_ptr = card_ptr;
card_ptr = _hot_card_cache->insert(card_ptr);
if (card_ptr == NULL) {
// There was no eviction. Nothing to do.
- return;
+ return false;
} else if (card_ptr != orig_card_ptr) {
// Original card was inserted and an old card was evicted.
start = _ct->addr_for(card_ptr);
r = _g1h->heap_region_containing(start);
// Check whether the region formerly in the cache should be
// ignored, as discussed earlier for the original card. The
// region could have been freed while in the cache.
if (!r->is_old_or_humongous_or_archive()) {
- return;
+ return false;
}
} // Else we still have the original card.
}
// Trim the region designated by the card to what's been allocated
@@ -1350,25 +1349,33 @@
// we see the up-to-date top here.
HeapWord* scan_limit = r->top();
if (scan_limit <= start) {
// If the trimmed region is empty, the card must be stale.
- return;
+ return false;
}
// Okay to clean and process the card now. There are still some
// stale card cases that may be detected by iteration and dealt with
// as iteration failure.
*const_cast<volatile CardValue*>(card_ptr) = G1CardTable::clean_card_val();
- // This fence serves two purposes. First, the card must be cleaned
- // before processing the contents. Second, we can't proceed with
- // processing until after the read of top, for synchronization with
- // possibly concurrent humongous object allocation. It's okay that
- // reading top and reading type were racy wrto each other. We need
- // both set, in any order, to proceed.
- OrderAccess::fence();
+ return true;
+}
+
+void G1RemSet::refine_card_concurrently(CardValue* const card_ptr,
+ const uint worker_id) {
+ assert(!_g1h->is_gc_active(), "Only call concurrently");
+ check_card_ptr(card_ptr, _ct);
+
+ // Construct the MemRegion representing the card.
+ HeapWord* start = _ct->addr_for(card_ptr);
+ // And find the region containing it.
+ HeapRegion* r = _g1h->heap_region_containing(start);
+ HeapWord* scan_limit = r->top();
+ // top() can only increase since last read of top() before cleaning the card.
+ assert(scan_limit > start, "sanity");
// Don't use addr_for(card_ptr + 1) which can ask for
// a card beyond the heap.
HeapWord* end = start + G1CardTable::card_size_in_words;
MemRegion dirty_region(start, MIN2(scan_limit, end));
< prev index next >