8051973: Eager reclaim leaves marks of marked but reclaimed objects on the next bitmap

Eager reclaim also needs to clear marks of eagerly reclaimed regions if they have already been marked during concurrent mark.

Reviewed-by: jmasa
This commit is contained in:
Thomas Schatzl 2014-07-31 09:23:24 +02:00
parent 071c3a3924
commit a959c0971e
2 changed files with 136 additions and 7 deletions

View file

@ -6536,6 +6536,9 @@ class G1FreeHumongousRegionClosure : public HeapRegionClosure {
G1CollectedHeap* g1h = G1CollectedHeap::heap(); G1CollectedHeap* g1h = G1CollectedHeap::heap();
oop obj = (oop)r->bottom();
CMBitMap* next_bitmap = g1h->concurrent_mark()->nextMarkBitMap();
// The following checks whether the humongous object is live are sufficient. // The following checks whether the humongous object is live are sufficient.
// The main additional check (in addition to having a reference from the roots // The main additional check (in addition to having a reference from the roots
// or the young gen) is whether the humongous object has a remembered set entry. // or the young gen) is whether the humongous object has a remembered set entry.
@ -6572,37 +6575,41 @@ class G1FreeHumongousRegionClosure : public HeapRegionClosure {
g1h->humongous_region_is_always_live(region_idx)) { g1h->humongous_region_is_always_live(region_idx)) {
if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) { if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) {
gclog_or_tty->print_cr("Live humongous %d region %d with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is dead-bitmap %d live-other %d obj array %d", gclog_or_tty->print_cr("Live humongous %d region %d with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d",
r->isHumongous(), r->isHumongous(),
region_idx, region_idx,
r->rem_set()->occupied(), r->rem_set()->occupied(),
r->rem_set()->strong_code_roots_list_length(), r->rem_set()->strong_code_roots_list_length(),
g1h->mark_in_progress() && !g1h->g1_policy()->during_initial_mark_pause(), next_bitmap->isMarked(r->bottom()),
g1h->humongous_is_live(region_idx), g1h->humongous_is_live(region_idx),
oop(r->bottom())->is_objArray() obj->is_objArray()
); );
} }
return false; return false;
} }
guarantee(!((oop)(r->bottom()))->is_objArray(), guarantee(!obj->is_objArray(),
err_msg("Eagerly reclaiming object arrays is not supported, but the object "PTR_FORMAT" is.", err_msg("Eagerly reclaiming object arrays is not supported, but the object "PTR_FORMAT" is.",
r->bottom())); r->bottom()));
if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) { if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) {
gclog_or_tty->print_cr("Reclaim humongous region %d start "PTR_FORMAT" region %d length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is dead-bitmap %d live-other %d obj array %d", gclog_or_tty->print_cr("Reclaim humongous region %d start "PTR_FORMAT" region %d length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d",
r->isHumongous(), r->isHumongous(),
r->bottom(), r->bottom(),
region_idx, region_idx,
r->region_num(), r->region_num(),
r->rem_set()->occupied(), r->rem_set()->occupied(),
r->rem_set()->strong_code_roots_list_length(), r->rem_set()->strong_code_roots_list_length(),
g1h->mark_in_progress() && !g1h->g1_policy()->during_initial_mark_pause(), next_bitmap->isMarked(r->bottom()),
g1h->humongous_is_live(region_idx), g1h->humongous_is_live(region_idx),
oop(r->bottom())->is_objArray() obj->is_objArray()
); );
} }
// Need to clear mark bit of the humongous object if already set.
if (next_bitmap->isMarked(r->bottom())) {
next_bitmap->clear(r->bottom());
}
_freed_bytes += r->used(); _freed_bytes += r->used();
r->set_containing_set(NULL); r->set_containing_set(NULL);
_humongous_regions_removed.increment(1u, r->capacity()); _humongous_regions_removed.increment(1u, r->capacity());

View file

@ -0,0 +1,122 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test TestEagerReclaimHumongousRegions2
* @bug 8051973
* @summary Test to make sure that eager reclaim of humongous objects correctly clears
* mark bitmaps at reclaim.
* @key gc
* @library /testlibrary
*/
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Random;
import com.oracle.java.testlibrary.OutputAnalyzer;
import com.oracle.java.testlibrary.ProcessTools;
// An object that has a few references to other instances to slow down marking.
class ObjectWithSomeRefs {
public ObjectWithSomeRefs other1;
public ObjectWithSomeRefs other2;
public ObjectWithSomeRefs other3;
public ObjectWithSomeRefs other4;
}
class ReclaimRegionFast {
public static final int M = 1024*1024;
public static LinkedList<Object> garbageList = new LinkedList<Object>();
public static void genGarbage(Object large) {
for (int i = 0; i < 64*1024; i++) {
Object[] garbage = new Object[50];
garbage[0] = large;
garbageList.add(garbage);
}
garbageList.clear();
}
public static ArrayList<ObjectWithSomeRefs> longList = new ArrayList<ObjectWithSomeRefs>();
public static void main(String[] args) {
for (int i = 0; i < 16*1024; i++) {
longList.add(new ObjectWithSomeRefs());
}
Random rnd = new Random();
for (int i = 0; i < longList.size(); i++) {
int len = longList.size();
longList.get(i).other1 = longList.get(rnd.nextInt(len));
longList.get(i).other2 = longList.get(rnd.nextInt(len));
longList.get(i).other3 = longList.get(rnd.nextInt(len));
longList.get(i).other4 = longList.get(rnd.nextInt(len));
}
int[] large1 = new int[M];
int[] large2 = null;
int[] large3 = null;
int[] large4 = null;
Object ref_from_stack = large1;
for (int i = 0; i < 20; i++) {
// A set of large objects that will be reclaimed eagerly - and hopefully marked.
large1 = new int[M - 20];
large2 = new int[M - 20];
large3 = new int[M - 20];
large4 = new int[M - 20];
genGarbage(large1);
// Make sure that the compiler cannot completely remove
// the allocation of the large object until here.
System.out.println(large1 + " " + large2 + " " + large3 + " " + large4);
}
// Keep the reference to the first object alive.
System.out.println(ref_from_stack);
}
}
public class TestEagerReclaimHumongousRegions2 {
public static void main(String[] args) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-XX:+UseG1GC",
"-Xms128M",
"-Xmx128M",
"-Xmn2M",
"-XX:G1HeapRegionSize=1M",
"-XX:InitiatingHeapOccupancyPercent=0", // Want to have as much as possible initial marks.
"-XX:+PrintGC",
"-XX:+VerifyAfterGC",
"-XX:ConcGCThreads=1", // Want to make marking as slow as possible.
"-XX:+IgnoreUnrecognizedVMOptions", // G1VerifyBitmaps is develop only.
"-XX:+G1VerifyBitmaps",
ReclaimRegionFast.class.getName());
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldHaveExitValue(0);
}
}