src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
Print this page
rev 6140 : 8029075: String deduplication in G1
Implementation of JEP 192, http://openjdk.java.net/jeps/192
*** 37,46 ****
--- 37,47 ----
#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"
*** 2171,2180 ****
--- 2172,2183 ----
// 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();
*** 3455,3464 ****
--- 3458,3472 ----
}
}
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().
*** 3472,3483 ****
#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) ");
}
}
void G1CollectedHeap::verify(bool silent) {
verify(silent, VerifyOption_G1UsePrevMarking);
--- 3480,3496 ----
#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 (G1StringDedup::is_enabled()) {
! gclog_or_tty->print(", StrDedup");
! }
! gclog_or_tty->print(") ");
! }
}
}
void G1CollectedHeap::verify(bool silent) {
verify(silent, VerifyOption_G1UsePrevMarking);
*** 3566,3583 ****
--- 3579,3602 ----
}
_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) {
*** 4754,4763 ****
--- 4773,4789 ----
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
*** 5217,5226 ****
--- 5243,5256 ----
"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);
+ }
}
class RedirtyLoggedCardTableEntryFastClosure : public CardTableEntryClosure {
public:
bool do_card_ptr(jbyte* card_ptr, int worker_i) {
*** 5840,5849 ****
--- 5870,5882 ----
// 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();
*** 6320,6332 ****
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();
}
_free_list.remove_all();
}
class RebuildRegionSetsClosure : public HeapRegionClosure {
--- 6353,6366 ----
if (!free_list_only) {
TearDownRegionSetsClosure cl(&_old_set);
heap_region_iterate(&cl);
! // 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 {
*** 6376,6385 ****
--- 6410,6423 ----
};
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();