src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
Print this page
rev 6083 : 8029075: String deduplication in G1
Implementation of JEP 192, http://openjdk.java.net/jeps/192
@@ -37,10 +37,11 @@
#include "gc_implementation/g1/g1GCPhaseTimes.hpp"
#include "gc_implementation/g1/g1Log.hpp"
#include "gc_implementation/g1/g1MarkSweep.hpp"
#include "gc_implementation/g1/g1OopClosures.inline.hpp"
#include "gc_implementation/g1/g1RemSet.inline.hpp"
+#include "gc_implementation/g1/g1StringDedup.hpp"
#include "gc_implementation/g1/g1YCTypes.hpp"
#include "gc_implementation/g1/heapRegion.inline.hpp"
#include "gc_implementation/g1/heapRegionRemSet.hpp"
#include "gc_implementation/g1/heapRegionSeq.inline.hpp"
#include "gc_implementation/g1/vm_operations_g1.hpp"
@@ -2179,10 +2180,12 @@
// Do create of the monitoring and management support so that
// values in the heap have been properly initialized.
_g1mm = new G1MonitoringSupport(this);
+ G1StringDedup::initialize();
+
return JNI_OK;
}
size_t G1CollectedHeap::conservative_max_heap_alignment() {
return HeapRegion::max_region_size();
@@ -3459,10 +3462,15 @@
}
}
if (!silent) gclog_or_tty->print("RemSet ");
rem_set()->verify();
+ if (G1StringDedup::is_enabled()) {
+ if (!silent) gclog_or_tty->print("StrDedup ");
+ G1StringDedup::verify();
+ }
+
if (failures) {
gclog_or_tty->print_cr("Heap:");
// It helps to have the per-region information in the output to
// help us track down what went wrong. This is why we call
// print_extended_on() instead of print_on().
@@ -3476,12 +3484,17 @@
#endif
gclog_or_tty->flush();
}
guarantee(!failures, "there should not have been any failures");
} else {
- if (!silent)
- gclog_or_tty->print("(SKIPPING roots, heapRegionSets, heapRegions, remset) ");
+ if (!silent) {
+ gclog_or_tty->print("(SKIPPING Roots, HeapRegionSets, HeapRegions, RemSet");
+ if (G1StringDedup::is_enabled()) {
+ gclog_or_tty->print(", StrDedup");
+ }
+ gclog_or_tty->print(") ");
+ }
}
}
void G1CollectedHeap::verify(bool silent) {
verify(silent, VerifyOption_G1UsePrevMarking);
@@ -3570,18 +3583,24 @@
}
_cmThread->print_on(st);
st->cr();
_cm->print_worker_threads_on(st);
_cg1r->print_worker_threads_on(st);
+ if (G1StringDedup::is_enabled()) {
+ G1StringDedup::print_worker_threads_on(st);
+ }
}
void G1CollectedHeap::gc_threads_do(ThreadClosure* tc) const {
if (G1CollectedHeap::use_parallel_gc_threads()) {
workers()->threads_do(tc);
}
tc->do_thread(_cmThread);
_cg1r->threads_do(tc);
+ if (G1StringDedup::is_enabled()) {
+ G1StringDedup::threads_do(tc);
+ }
}
void G1CollectedHeap::print_tracing_info() const {
// We'll overload this to mean "trace GC pause statistics."
if (TraceGen0Time || TraceGen1Time) {
@@ -4756,10 +4775,17 @@
age_table()->add(obj, word_sz);
} else {
obj->set_mark(m);
}
+ if (G1StringDedup::is_enabled()) {
+ G1StringDedup::enqueue_from_evacuation(from_region->is_young(),
+ to_region->is_young(),
+ queue_num(),
+ obj);
+ }
+
size_t* surv_young_words = surviving_young_words();
surv_young_words[young_index] += word_sz;
if (obj->is_objArray() && arrayOop(obj)->length() >= ParGCArrayScanChunk) {
// We keep track of the next start index in the length field of
@@ -5272,10 +5298,14 @@
"strings: "SIZE_FORMAT" processed, "SIZE_FORMAT" removed, "
"symbols: "SIZE_FORMAT" processed, "SIZE_FORMAT" removed",
g1_unlink_task.strings_processed(), g1_unlink_task.strings_removed(),
g1_unlink_task.symbols_processed(), g1_unlink_task.symbols_removed());
}
+
+ if (G1StringDedup::is_enabled()) {
+ G1StringDedup::unlink(is_alive);
+ }
}
// Weak Reference Processing support
// An always "is_alive" closure that is used to preserve referents.
@@ -5885,10 +5915,13 @@
// Weak root processing.
{
G1STWIsAliveClosure is_alive(this);
G1KeepAliveClosure keep_alive(this);
JNIHandles::weak_oops_do(&is_alive, &keep_alive);
+ if (G1StringDedup::is_enabled()) {
+ G1StringDedup::unlink_or_oops_do(&is_alive, &keep_alive);
+ }
}
release_gc_alloc_regions(n_workers, evacuation_info);
g1_rem_set()->cleanup_after_oops_into_collection_set_do();
@@ -6368,13 +6401,14 @@
if (!free_list_only) {
TearDownRegionSetsClosure cl(&_old_set);
heap_region_iterate(&cl);
- // Need to do this after the heap iteration to be able to
- // recognize the young regions and ignore them during the iteration.
- _young_list->empty_list();
+ // Note that emptying the _young_list is postponed and instead done as
+ // the first step when rebuilding the regions sets again. The reason for
+ // this is that during a full GC string deduplication needs to know if
+ // a collected region was young or old when the full GC was initiated.
}
_free_list.remove_all();
}
class RebuildRegionSetsClosure : public HeapRegionClosure {
@@ -6424,10 +6458,14 @@
};
void G1CollectedHeap::rebuild_region_sets(bool free_list_only) {
assert_at_safepoint(true /* should_be_vm_thread */);
+ if (!free_list_only) {
+ _young_list->empty_list();
+ }
+
RebuildRegionSetsClosure cl(free_list_only, &_old_set, &_free_list);
heap_region_iterate(&cl);
if (!free_list_only) {
_summary_bytes_used = cl.total_used();