Skip to content

Commit

Permalink
8029075: String deduplication in G1
Browse files Browse the repository at this point in the history
Implementation of JEP 192, http://openjdk.java.net/jeps/192

Reviewed-by: brutisso, tschatzl, coleenp
  • Loading branch information
pliden committed Mar 18, 2014
1 parent 1e1ad7f commit 4a4c0fc
Show file tree
Hide file tree
Showing 32 changed files with 2,915 additions and 17 deletions.
3 changes: 2 additions & 1 deletion hotspot/make/excludeSrc.make
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ ifeq ($(INCLUDE_ALL_GCS), false)
g1BlockOffsetTable.cpp g1CardCounts.cpp g1CollectedHeap.cpp g1CollectorPolicy.cpp \
g1ErgoVerbose.cpp g1GCPhaseTimes.cpp g1HRPrinter.cpp g1HotCardCache.cpp g1Log.cpp \
g1MMUTracker.cpp g1MarkSweep.cpp g1MemoryPool.cpp g1MonitoringSupport.cpp g1OopClosures.cpp \
g1RemSet.cpp g1RemSetSummary.cpp g1SATBCardTableModRefBS.cpp g1_globals.cpp heapRegion.cpp \
g1RemSet.cpp g1RemSetSummary.cpp g1SATBCardTableModRefBS.cpp g1StringDedup.cpp g1StringDedupStat.cpp \
g1StringDedupTable.cpp g1StringDedupThread.cpp g1StringDedupQueue.cpp g1_globals.cpp heapRegion.cpp \
g1BiasedArray.cpp heapRegionRemSet.cpp heapRegionSeq.cpp heapRegionSet.cpp heapRegionSets.cpp \
ptrQueue.cpp satbQueue.cpp sparsePRT.cpp survRateGroup.cpp vm_operations_g1.cpp g1CodeCacheRemSet.cpp \
adjoiningGenerations.cpp adjoiningVirtualSpaces.cpp asPSOldGen.cpp asPSYoungGen.cpp \
Expand Down
20 changes: 15 additions & 5 deletions hotspot/src/share/vm/classfile/javaClasses.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
Expand Down Expand Up @@ -61,10 +61,6 @@ class java_lang_String : AllStatic {

static Handle basic_create(int length, TRAPS);

static void set_value( oop string, typeArrayOop buffer) {
assert(initialized, "Must be initialized");
string->obj_field_put(value_offset, (oop)buffer);
}
static void set_offset(oop string, int offset) {
assert(initialized, "Must be initialized");
if (offset_offset > 0) {
Expand Down Expand Up @@ -122,12 +118,26 @@ class java_lang_String : AllStatic {
return hash_offset;
}

static void set_value(oop string, typeArrayOop buffer) {
assert(initialized && (value_offset > 0), "Must be initialized");
string->obj_field_put(value_offset, (oop)buffer);
}
static void set_hash(oop string, unsigned int hash) {
assert(initialized && (hash_offset > 0), "Must be initialized");
string->int_field_put(hash_offset, hash);
}

// Accessors
static typeArrayOop value(oop java_string) {
assert(initialized && (value_offset > 0), "Must be initialized");
assert(is_instance(java_string), "must be java_string");
return (typeArrayOop) java_string->obj_field(value_offset);
}
static unsigned int hash(oop java_string) {
assert(initialized && (hash_offset > 0), "Must be initialized");
assert(is_instance(java_string), "must be java_string");
return java_string->int_field(hash_offset);
}
static int offset(oop java_string) {
assert(initialized, "Must be initialized");
assert(is_instance(java_string), "must be java_string");
Expand Down
14 changes: 13 additions & 1 deletion hotspot/src/share/vm/classfile/symbolTable.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
Expand Down Expand Up @@ -35,6 +35,9 @@
#include "oops/oop.inline2.hpp"
#include "runtime/mutexLocker.hpp"
#include "utilities/hashtable.inline.hpp"
#if INCLUDE_ALL_GCS
#include "gc_implementation/g1/g1StringDedup.hpp"
#endif

// --------------------------------------------------------------------------

Expand Down Expand Up @@ -728,6 +731,15 @@ oop StringTable::intern(Handle string_or_null, jchar* name,
string = java_lang_String::create_from_unicode(name, len, CHECK_NULL);
}

#if INCLUDE_ALL_GCS
if (G1StringDedup::is_enabled()) {
// Deduplicate the string before it is interned. Note that we should never
// deduplicate a string after it has been interned. Doing so will counteract
// compiler optimizations done on e.g. interned string literals.
G1StringDedup::deduplicate(string());
}
#endif

// Grab the StringTable_lock before getting the_table() because it could
// change at safepoint.
MutexLocker ml(StringTable_lock, THREAD);
Expand Down
48 changes: 43 additions & 5 deletions hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#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"
Expand Down Expand Up @@ -2172,6 +2173,8 @@ jint G1CollectedHeap::initialize() {
// values in the heap have been properly initialized.
_g1mm = new G1MonitoringSupport(this);

G1StringDedup::initialize();

return JNI_OK;
}

Expand Down Expand Up @@ -3456,6 +3459,11 @@ void G1CollectedHeap::verify(bool silent, VerifyOption vo) {
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
Expand All @@ -3473,8 +3481,13 @@ void G1CollectedHeap::verify(bool silent, VerifyOption vo) {
}
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(") ");
}
}
}

Expand Down Expand Up @@ -3567,6 +3580,9 @@ void G1CollectedHeap::print_gc_threads_on(outputStream* st) const {
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 {
Expand All @@ -3575,6 +3591,9 @@ void G1CollectedHeap::gc_threads_do(ThreadClosure* tc) const {
}
tc->do_thread(_cmThread);
_cg1r->threads_do(tc);
if (G1StringDedup::is_enabled()) {
G1StringDedup::threads_do(tc);
}
}

void G1CollectedHeap::print_tracing_info() const {
Expand Down Expand Up @@ -4755,6 +4774,13 @@ oop G1ParScanThreadState::copy_to_survivor_space(oop const old) {
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;

Expand Down Expand Up @@ -5218,6 +5244,10 @@ void G1CollectedHeap::unlink_string_and_symbol_table(BoolObjectClosure* is_alive
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 {
Expand Down Expand Up @@ -5841,6 +5871,9 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) {
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);
Expand Down Expand Up @@ -6321,9 +6354,10 @@ void G1CollectedHeap::tear_down_region_sets(bool 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();
}
Expand Down Expand Up @@ -6377,6 +6411,10 @@ class RebuildRegionSetsClosure : public HeapRegionClosure {
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);

Expand Down
25 changes: 24 additions & 1 deletion hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1GCPhaseTimes.hpp"
#include "gc_implementation/g1/g1Log.hpp"
#include "gc_implementation/g1/g1StringDedup.hpp"

// Helper class for avoiding interleaved logging
class LineBuffer: public StackObj {
Expand Down Expand Up @@ -168,7 +169,9 @@ G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) :
_last_termination_attempts(_max_gc_threads, SIZE_FORMAT),
_last_gc_worker_end_times_ms(_max_gc_threads, "%.1lf", false),
_last_gc_worker_times_ms(_max_gc_threads, "%.1lf"),
_last_gc_worker_other_times_ms(_max_gc_threads, "%.1lf")
_last_gc_worker_other_times_ms(_max_gc_threads, "%.1lf"),
_cur_string_dedup_queue_fixup_worker_times_ms(_max_gc_threads, "%.1lf"),
_cur_string_dedup_table_fixup_worker_times_ms(_max_gc_threads, "%.1lf")
{
assert(max_gc_threads > 0, "Must have some GC threads");
}
Expand Down Expand Up @@ -229,6 +232,16 @@ void G1GCPhaseTimes::note_gc_end() {
_last_gc_worker_other_times_ms.verify();
}

void G1GCPhaseTimes::note_string_dedup_fixup_start() {
_cur_string_dedup_queue_fixup_worker_times_ms.reset();
_cur_string_dedup_table_fixup_worker_times_ms.reset();
}

void G1GCPhaseTimes::note_string_dedup_fixup_end() {
_cur_string_dedup_queue_fixup_worker_times_ms.verify();
_cur_string_dedup_table_fixup_worker_times_ms.verify();
}

void G1GCPhaseTimes::print_stats(int level, const char* str, double value) {
LineBuffer(level).append_and_print_cr("[%s: %.1lf ms]", str, value);
}
Expand All @@ -253,6 +266,11 @@ double G1GCPhaseTimes::accounted_time_ms() {
// Strong code root purge time
misc_time_ms += _cur_strong_code_root_purge_time_ms;

if (G1StringDedup::is_enabled()) {
// String dedup fixup time
misc_time_ms += _cur_string_dedup_fixup_time_ms;
}

// Subtract the time taken to clean the card table from the
// current value of "other time"
misc_time_ms += _cur_clear_ct_time_ms;
Expand Down Expand Up @@ -303,6 +321,11 @@ void G1GCPhaseTimes::print(double pause_time_sec) {
print_stats(1, "Code Root Fixup", _cur_collection_code_root_fixup_time_ms);
print_stats(1, "Code Root Migration", _cur_strong_code_root_migration_time_ms);
print_stats(1, "Code Root Purge", _cur_strong_code_root_purge_time_ms);
if (G1StringDedup::is_enabled()) {
print_stats(1, "String Dedup Fixup", _cur_string_dedup_fixup_time_ms, _active_gc_threads);
_cur_string_dedup_queue_fixup_worker_times_ms.print(2, "Queue Fixup (ms)");
_cur_string_dedup_table_fixup_worker_times_ms.print(2, "Table Fixup (ms)");
}
print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
double misc_time_ms = pause_time_sec * MILLIUNITS - accounted_time_ms();
print_stats(1, "Other", misc_time_ms);
Expand Down
19 changes: 19 additions & 0 deletions hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
double _cur_evac_fail_restore_remsets;
double _cur_evac_fail_remove_self_forwards;

double _cur_string_dedup_fixup_time_ms;
WorkerDataArray<double> _cur_string_dedup_queue_fixup_worker_times_ms;
WorkerDataArray<double> _cur_string_dedup_table_fixup_worker_times_ms;

double _cur_clear_ct_time_ms;
double _cur_ref_proc_time_ms;
double _cur_ref_enq_time_ms;
Expand Down Expand Up @@ -246,6 +250,21 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
_cur_evac_fail_remove_self_forwards = ms;
}

void note_string_dedup_fixup_start();
void note_string_dedup_fixup_end();

void record_string_dedup_fixup_time(double ms) {
_cur_string_dedup_fixup_time_ms = ms;
}

void record_string_dedup_queue_fixup_worker_time(uint worker_id, double ms) {
_cur_string_dedup_queue_fixup_worker_times_ms.set(worker_id, ms);
}

void record_string_dedup_table_fixup_worker_time(uint worker_id, double ms) {
_cur_string_dedup_table_fixup_worker_times_ms.set(worker_id, ms);
}

void record_ref_proc_time(double ms) {
_cur_ref_proc_time_ms = ms;
}
Expand Down
7 changes: 6 additions & 1 deletion hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 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
Expand Down Expand Up @@ -31,6 +31,7 @@
#include "code/icBuffer.hpp"
#include "gc_implementation/g1/g1Log.hpp"
#include "gc_implementation/g1/g1MarkSweep.hpp"
#include "gc_implementation/g1/g1StringDedup.hpp"
#include "gc_implementation/shared/gcHeapSummary.hpp"
#include "gc_implementation/shared/gcTimer.hpp"
#include "gc_implementation/shared/gcTrace.hpp"
Expand Down Expand Up @@ -316,6 +317,10 @@ void G1MarkSweep::mark_sweep_phase3() {
// have been cleared if they pointed to non-surviving objects.)
sh->process_weak_roots(&GenMarkSweep::adjust_pointer_closure);

if (G1StringDedup::is_enabled()) {
G1StringDedup::oops_do(&GenMarkSweep::adjust_pointer_closure);
}

GenMarkSweep::adjust_marks();

G1AdjustPointersClosure blk;
Expand Down
Loading

0 comments on commit 4a4c0fc

Please sign in to comment.