--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Mon Oct 21 15:11:42 2019 +0200
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Mon Oct 21 15:11:43 2019 +0200
@@ -1507,6 +1507,14 @@
make_parsable(true);
}
+ // We are about to select the collection set, make sure it knows about
+ // current pinning status. Also, this allows trashing more regions that
+ // now have their pinning status dropped.
+ {
+ ShenandoahGCPhase phase(ShenandoahPhaseTimings::sync_pinned);
+ sync_pinned_region_status();
+ }
+
// Trash the collection set left over from previous cycle, if any.
{
ShenandoahGCPhase phase(ShenandoahPhaseTimings::trash_cset);
@@ -1784,6 +1792,7 @@
// it, we fail degeneration right away and slide into Full GC to recover.
{
+ sync_pinned_region_status();
collection_set()->clear_current_index();
ShenandoahHeapRegion* r;
@@ -2148,16 +2157,45 @@
}
oop ShenandoahHeap::pin_object(JavaThread* thr, oop o) {
- ShenandoahHeapLocker locker(lock());
- heap_region_containing(o)->make_pinned();
+ heap_region_containing(o)->record_pin();
return o;
}
void ShenandoahHeap::unpin_object(JavaThread* thr, oop o) {
+ heap_region_containing(o)->record_unpin();
+}
+
+void ShenandoahHeap::sync_pinned_region_status() {
ShenandoahHeapLocker locker(lock());
- heap_region_containing(o)->make_unpinned();
+
+ for (size_t i = 0; i < num_regions(); i++) {
+ ShenandoahHeapRegion *r = get_region(i);
+ if (r->is_active()) {
+ if (r->is_pinned()) {
+ if (r->pin_count() == 0) {
+ r->make_unpinned();
+ }
+ } else {
+ if (r->pin_count() > 0) {
+ r->make_pinned();
+ }
+ }
+ }
+ }
+
+ assert_pinned_region_status();
}
+#ifdef ASSERT
+void ShenandoahHeap::assert_pinned_region_status() {
+ for (size_t i = 0; i < num_regions(); i++) {
+ ShenandoahHeapRegion* r = get_region(i);
+ assert((r->is_pinned() && r->pin_count() > 0) || (!r->is_pinned() && r->pin_count() == 0),
+ "Region " SIZE_FORMAT " pinning status is inconsistent", i);
+ }
+}
+#endif
+
GCTimer* ShenandoahHeap::gc_timer() const {
return _gc_timer;
}
@@ -2316,6 +2354,13 @@
verifier()->verify_roots_in_to_space();
}
+ // Drop unnecessary "pinned" state from regions that does not have CP marks
+ // anymore, as this would allow trashing them below.
+ {
+ ShenandoahGCPhase phase(ShenandoahPhaseTimings::final_update_refs_sync_pinned);
+ sync_pinned_region_status();
+ }
+
{
ShenandoahGCPhase phase(ShenandoahPhaseTimings::final_update_refs_trash_cset);
trash_cset_regions();