Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
2cff96e1
D
dragonwell8_hotspot
项目概览
openanolis
/
dragonwell8_hotspot
通知
2
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_hotspot
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
2cff96e1
编写于
3月 24, 2014
作者:
J
jwilhelm
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
dc597682
0f5fc07e
变更
32
展开全部
隐藏空白更改
内联
并排
Showing
32 changed file
with
2915 addition
and
17 deletion
+2915
-17
make/excludeSrc.make
make/excludeSrc.make
+2
-1
src/share/vm/classfile/javaClasses.hpp
src/share/vm/classfile/javaClasses.hpp
+15
-5
src/share/vm/classfile/symbolTable.cpp
src/share/vm/classfile/symbolTable.cpp
+13
-1
src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
+43
-5
src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp
src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp
+24
-1
src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp
src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp
+19
-0
src/share/vm/gc_implementation/g1/g1MarkSweep.cpp
src/share/vm/gc_implementation/g1/g1MarkSweep.cpp
+6
-1
src/share/vm/gc_implementation/g1/g1StringDedup.cpp
src/share/vm/gc_implementation/g1/g1StringDedup.cpp
+208
-0
src/share/vm/gc_implementation/g1/g1StringDedup.hpp
src/share/vm/gc_implementation/g1/g1StringDedup.hpp
+202
-0
src/share/vm/gc_implementation/g1/g1StringDedupQueue.cpp
src/share/vm/gc_implementation/g1/g1StringDedupQueue.cpp
+162
-0
src/share/vm/gc_implementation/g1/g1StringDedupQueue.hpp
src/share/vm/gc_implementation/g1/g1StringDedupQueue.hpp
+97
-0
src/share/vm/gc_implementation/g1/g1StringDedupStat.cpp
src/share/vm/gc_implementation/g1/g1StringDedupStat.cpp
+162
-0
src/share/vm/gc_implementation/g1/g1StringDedupStat.hpp
src/share/vm/gc_implementation/g1/g1StringDedupStat.hpp
+142
-0
src/share/vm/gc_implementation/g1/g1StringDedupTable.cpp
src/share/vm/gc_implementation/g1/g1StringDedupTable.cpp
+569
-0
src/share/vm/gc_implementation/g1/g1StringDedupTable.hpp
src/share/vm/gc_implementation/g1/g1StringDedupTable.hpp
+230
-0
src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp
src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp
+124
-0
src/share/vm/gc_implementation/g1/g1StringDedupThread.hpp
src/share/vm/gc_implementation/g1/g1StringDedupThread.hpp
+56
-0
src/share/vm/gc_implementation/shared/markSweep.inline.hpp
src/share/vm/gc_implementation/shared/markSweep.inline.hpp
+9
-1
src/share/vm/runtime/arguments.cpp
src/share/vm/runtime/arguments.cpp
+2
-0
src/share/vm/runtime/globals.hpp
src/share/vm/runtime/globals.hpp
+16
-0
src/share/vm/runtime/mutexLocker.cpp
src/share/vm/runtime/mutexLocker.cpp
+6
-1
src/share/vm/runtime/mutexLocker.hpp
src/share/vm/runtime/mutexLocker.hpp
+3
-1
test/gc/g1/TestGCLogMessages.java
test/gc/g1/TestGCLogMessages.java
+5
-0
test/gc/g1/TestStringDeduplicationAgeThreshold.java
test/gc/g1/TestStringDeduplicationAgeThreshold.java
+36
-0
test/gc/g1/TestStringDeduplicationFullGC.java
test/gc/g1/TestStringDeduplicationFullGC.java
+36
-0
test/gc/g1/TestStringDeduplicationInterned.java
test/gc/g1/TestStringDeduplicationInterned.java
+36
-0
test/gc/g1/TestStringDeduplicationMemoryUsage.java
test/gc/g1/TestStringDeduplicationMemoryUsage.java
+36
-0
test/gc/g1/TestStringDeduplicationPrintOptions.java
test/gc/g1/TestStringDeduplicationPrintOptions.java
+36
-0
test/gc/g1/TestStringDeduplicationTableRehash.java
test/gc/g1/TestStringDeduplicationTableRehash.java
+36
-0
test/gc/g1/TestStringDeduplicationTableResize.java
test/gc/g1/TestStringDeduplicationTableResize.java
+36
-0
test/gc/g1/TestStringDeduplicationTools.java
test/gc/g1/TestStringDeduplicationTools.java
+512
-0
test/gc/g1/TestStringDeduplicationYoungGC.java
test/gc/g1/TestStringDeduplicationYoungGC.java
+36
-0
未找到文件。
make/excludeSrc.make
浏览文件 @
2cff96e1
...
...
@@ -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
\
...
...
src/share/vm/classfile/javaClasses.hpp
浏览文件 @
2cff96e1
/*
* Copyright (c) 1997, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
4
, 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
...
...
@@ -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
)
{
...
...
@@ -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"
);
...
...
src/share/vm/classfile/symbolTable.cpp
浏览文件 @
2cff96e1
/*
* Copyright (c) 1997, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
4
, 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
...
...
@@ -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
// --------------------------------------------------------------------------
...
...
@@ -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
);
...
...
src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
浏览文件 @
2cff96e1
...
...
@@ -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"
...
...
@@ -2172,6 +2173,8 @@ jint G1CollectedHeap::initialize() {
// values in the heap have been properly initialized.
_g1mm
=
new
G1MonitoringSupport
(
this
);
G1StringDedup
::
initialize
();
return
JNI_OK
;
}
...
...
@@ -3474,6 +3477,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
...
...
@@ -3491,8 +3499,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
(
") "
);
}
}
}
...
...
@@ -3585,6 +3598,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
{
...
...
@@ -3593,6 +3609,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
{
...
...
@@ -4773,6 +4792,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
;
...
...
@@ -5248,6 +5274,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
{
...
...
@@ -5871,6 +5901,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
);
...
...
@@ -6351,9 +6384,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
();
}
...
...
@@ -6407,6 +6441,10 @@ public:
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
);
...
...
src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp
浏览文件 @
2cff96e1
...
...
@@ -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
{
...
...
@@ -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"
);
}
...
...
@@ -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
);
}
...
...
@@ -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
;
...
...
@@ -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
);
...
...
src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp
浏览文件 @
2cff96e1
...
...
@@ -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
;
...
...
@@ -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
;
}
...
...
src/share/vm/gc_implementation/g1/g1MarkSweep.cpp
浏览文件 @
2cff96e1
/*
* Copyright (c) 2001, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 201
4
, 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
...
...
@@ -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"
...
...
@@ -320,6 +321,10 @@ void G1MarkSweep::mark_sweep_phase3() {
// have been cleared if they pointed to non-surviving objects.)
g1h
->
g1_process_weak_roots
(
&
GenMarkSweep
::
adjust_pointer_closure
);
if
(
G1StringDedup
::
is_enabled
())
{
G1StringDedup
::
oops_do
(
&
GenMarkSweep
::
adjust_pointer_closure
);
}
GenMarkSweep
::
adjust_marks
();
G1AdjustPointersClosure
blk
;
...
...
src/share/vm/gc_implementation/g1/g1StringDedup.cpp
0 → 100644
浏览文件 @
2cff96e1
/*
* 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.
*
*/
#include "precompiled.hpp"
#include "classfile/javaClasses.hpp"
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1GCPhaseTimes.hpp"
#include "gc_implementation/g1/g1StringDedup.hpp"
#include "gc_implementation/g1/g1StringDedupQueue.hpp"
#include "gc_implementation/g1/g1StringDedupStat.hpp"
#include "gc_implementation/g1/g1StringDedupTable.hpp"
#include "gc_implementation/g1/g1StringDedupThread.hpp"
bool
G1StringDedup
::
_enabled
=
false
;
void
G1StringDedup
::
initialize
()
{
assert
(
UseG1GC
,
"String deduplication only available with G1"
);
if
(
UseStringDeduplication
)
{
_enabled
=
true
;
G1StringDedupQueue
::
create
();
G1StringDedupTable
::
create
();
G1StringDedupThread
::
create
();
}
}
bool
G1StringDedup
::
is_candidate_from_mark
(
oop
obj
)
{
if
(
java_lang_String
::
is_instance
(
obj
))
{
bool
from_young
=
G1CollectedHeap
::
heap
()
->
heap_region_containing_raw
(
obj
)
->
is_young
();
if
(
from_young
&&
obj
->
age
()
<
StringDeduplicationAgeThreshold
)
{
// Candidate found. String is being evacuated from young to old but has not
// reached the deduplication age threshold, i.e. has not previously been a
// candidate during its life in the young generation.
return
true
;
}
}
// Not a candidate
return
false
;
}
void
G1StringDedup
::
enqueue_from_mark
(
oop
java_string
)
{
assert
(
is_enabled
(),
"String deduplication not enabled"
);
if
(
is_candidate_from_mark
(
java_string
))
{
G1StringDedupQueue
::
push
(
0
/* worker_id */
,
java_string
);
}
}
bool
G1StringDedup
::
is_candidate_from_evacuation
(
bool
from_young
,
bool
to_young
,
oop
obj
)
{
if
(
from_young
&&
java_lang_String
::
is_instance
(
obj
))
{
if
(
to_young
&&
obj
->
age
()
==
StringDeduplicationAgeThreshold
)
{
// Candidate found. String is being evacuated from young to young and just
// reached the deduplication age threshold.
return
true
;
}
if
(
!
to_young
&&
obj
->
age
()
<
StringDeduplicationAgeThreshold
)
{
// Candidate found. String is being evacuated from young to old but has not
// reached the deduplication age threshold, i.e. has not previously been a
// candidate during its life in the young generation.
return
true
;
}
}
// Not a candidate
return
false
;
}
void
G1StringDedup
::
enqueue_from_evacuation
(
bool
from_young
,
bool
to_young
,
uint
worker_id
,
oop
java_string
)
{
assert
(
is_enabled
(),
"String deduplication not enabled"
);
if
(
is_candidate_from_evacuation
(
from_young
,
to_young
,
java_string
))
{
G1StringDedupQueue
::
push
(
worker_id
,
java_string
);
}
}
void
G1StringDedup
::
deduplicate
(
oop
java_string
)
{
assert
(
is_enabled
(),
"String deduplication not enabled"
);
G1StringDedupStat
dummy
;
// Statistics from this path is never used
G1StringDedupTable
::
deduplicate
(
java_string
,
dummy
);
}
void
G1StringDedup
::
oops_do
(
OopClosure
*
keep_alive
)
{
assert
(
is_enabled
(),
"String deduplication not enabled"
);
unlink_or_oops_do
(
NULL
,
keep_alive
);
}
void
G1StringDedup
::
unlink
(
BoolObjectClosure
*
is_alive
)
{
assert
(
is_enabled
(),
"String deduplication not enabled"
);
// Don't allow a potential resize or rehash during unlink, as the unlink
// operation itself might remove enough entries to invalidate such a decision.
unlink_or_oops_do
(
is_alive
,
NULL
,
false
/* allow_resize_and_rehash */
);
}
//
// Task for parallel unlink_or_oops_do() operation on the deduplication queue
// and table.
//
class
G1StringDedupUnlinkOrOopsDoTask
:
public
AbstractGangTask
{
private:
G1StringDedupUnlinkOrOopsDoClosure
_cl
;
public:
G1StringDedupUnlinkOrOopsDoTask
(
BoolObjectClosure
*
is_alive
,
OopClosure
*
keep_alive
,
bool
allow_resize_and_rehash
)
:
AbstractGangTask
(
"G1StringDedupUnlinkOrOopsDoTask"
),
_cl
(
is_alive
,
keep_alive
,
allow_resize_and_rehash
)
{
}
virtual
void
work
(
uint
worker_id
)
{
double
queue_fixup_start
=
os
::
elapsedTime
();
G1StringDedupQueue
::
unlink_or_oops_do
(
&
_cl
);
double
table_fixup_start
=
os
::
elapsedTime
();
G1StringDedupTable
::
unlink_or_oops_do
(
&
_cl
,
worker_id
);
double
queue_fixup_time_ms
=
(
table_fixup_start
-
queue_fixup_start
)
*
1000.0
;
double
table_fixup_time_ms
=
(
os
::
elapsedTime
()
-
table_fixup_start
)
*
1000.0
;
G1CollectorPolicy
*
g1p
=
G1CollectedHeap
::
heap
()
->
g1_policy
();
g1p
->
phase_times
()
->
record_string_dedup_queue_fixup_worker_time
(
worker_id
,
queue_fixup_time_ms
);
g1p
->
phase_times
()
->
record_string_dedup_table_fixup_worker_time
(
worker_id
,
table_fixup_time_ms
);
}
};
void
G1StringDedup
::
unlink_or_oops_do
(
BoolObjectClosure
*
is_alive
,
OopClosure
*
keep_alive
,
bool
allow_resize_and_rehash
)
{
assert
(
is_enabled
(),
"String deduplication not enabled"
);
G1CollectorPolicy
*
g1p
=
G1CollectedHeap
::
heap
()
->
g1_policy
();
g1p
->
phase_times
()
->
note_string_dedup_fixup_start
();
double
fixup_start
=
os
::
elapsedTime
();
G1StringDedupUnlinkOrOopsDoTask
task
(
is_alive
,
keep_alive
,
allow_resize_and_rehash
);
if
(
G1CollectedHeap
::
use_parallel_gc_threads
())
{
G1CollectedHeap
*
g1h
=
G1CollectedHeap
::
heap
();
g1h
->
set_par_threads
();
g1h
->
workers
()
->
run_task
(
&
task
);
g1h
->
set_par_threads
(
0
);
}
else
{
task
.
work
(
0
);
}
double
fixup_time_ms
=
(
os
::
elapsedTime
()
-
fixup_start
)
*
1000.0
;
g1p
->
phase_times
()
->
record_string_dedup_fixup_time
(
fixup_time_ms
);
g1p
->
phase_times
()
->
note_string_dedup_fixup_end
();
}
void
G1StringDedup
::
threads_do
(
ThreadClosure
*
tc
)
{
assert
(
is_enabled
(),
"String deduplication not enabled"
);
tc
->
do_thread
(
G1StringDedupThread
::
thread
());
}
void
G1StringDedup
::
print_worker_threads_on
(
outputStream
*
st
)
{
assert
(
is_enabled
(),
"String deduplication not enabled"
);
G1StringDedupThread
::
thread
()
->
print_on
(
st
);
st
->
cr
();
}
void
G1StringDedup
::
verify
()
{
assert
(
is_enabled
(),
"String deduplication not enabled"
);
G1StringDedupQueue
::
verify
();
G1StringDedupTable
::
verify
();
}
G1StringDedupUnlinkOrOopsDoClosure
::
G1StringDedupUnlinkOrOopsDoClosure
(
BoolObjectClosure
*
is_alive
,
OopClosure
*
keep_alive
,
bool
allow_resize_and_rehash
)
:
_is_alive
(
is_alive
),
_keep_alive
(
keep_alive
),
_resized_table
(
NULL
),
_rehashed_table
(
NULL
),
_next_queue
(
0
),
_next_bucket
(
0
)
{
if
(
allow_resize_and_rehash
)
{
// If both resize and rehash is needed, only do resize. Rehash of
// the table will eventually happen if the situation persists.
_resized_table
=
G1StringDedupTable
::
prepare_resize
();
if
(
!
is_resizing
())
{
_rehashed_table
=
G1StringDedupTable
::
prepare_rehash
();
}
}
}
G1StringDedupUnlinkOrOopsDoClosure
::~
G1StringDedupUnlinkOrOopsDoClosure
()
{
assert
(
!
is_resizing
()
||
!
is_rehashing
(),
"Can not both resize and rehash"
);
if
(
is_resizing
())
{
G1StringDedupTable
::
finish_resize
(
_resized_table
);
}
else
if
(
is_rehashing
())
{
G1StringDedupTable
::
finish_rehash
(
_rehashed_table
);
}
}
src/share/vm/gc_implementation/g1/g1StringDedup.hpp
0 → 100644
浏览文件 @
2cff96e1
/*
* 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.
*
*/
#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUP_HPP
#define SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUP_HPP
//
// String Deduplication
//
// String deduplication aims to reduce the heap live-set by deduplicating identical
// instances of String so that they share the same backing character array.
//
// The deduplication process is divided in two main parts, 1) finding the objects to
// deduplicate, and 2) deduplicating those objects. The first part is done as part of
// a normal GC cycle when objects are marked or evacuated. At this time a check is
// applied on each object to check if it is a candidate for deduplication. If so, the
// object is placed on the deduplication queue for later processing. The second part,
// processing the objects on the deduplication queue, is a concurrent phase which
// starts right after the stop-the-wold marking/evacuation phase. This phase is
// executed by the deduplication thread, which pulls deduplication candidates of the
// deduplication queue and tries to deduplicate them.
//
// A deduplication hashtable is used to keep track of all unique character arrays
// used by String objects. When deduplicating, a lookup is made in this table to see
// if there is already an identical character array somewhere on the heap. If so, the
// String object is adjusted to point to that character array, releasing the reference
// to the original array allowing it to eventually be garbage collected. If the lookup
// fails the character array is instead inserted into the hashtable so that this array
// can be shared at some point in the future.
//
// Candidate selection
//
// An object is considered a deduplication candidate if all of the following
// statements are true:
//
// - The object is an instance of java.lang.String
//
// - The object is being evacuated from a young heap region
//
// - The object is being evacuated to a young/survivor heap region and the
// object's age is equal to the deduplication age threshold
//
// or
//
// The object is being evacuated to an old heap region and the object's age is
// less than the deduplication age threshold
//
// Once an string object has been promoted to an old region, or its age is higher
// than the deduplication age threshold, is will never become a candidate again.
// This approach avoids making the same object a candidate more than once.
//
// Interned strings are a bit special. They are explicitly deduplicated just before
// being inserted into the StringTable (to avoid counteracting C2 optimizations done
// on string literals), then they also become deduplication candidates if they reach
// the deduplication age threshold or are evacuated to an old heap region. The second
// attempt to deduplicate such strings will be in vain, but we have no fast way of
// filtering them out. This has not shown to be a problem, as the number of interned
// strings is usually dwarfed by the number of normal (non-interned) strings.
//
// For additional information on string deduplication, please see JEP 192,
// http://openjdk.java.net/jeps/192
//
#include "memory/allocation.hpp"
#include "oops/oop.hpp"
class
OopClosure
;
class
BoolObjectClosure
;
class
ThreadClosure
;
class
outputStream
;
class
G1StringDedupTable
;
//
// Main interface for interacting with string deduplication.
//
class
G1StringDedup
:
public
AllStatic
{
private:
// Single state for checking if both G1 and string deduplication is enabled.
static
bool
_enabled
;
// Candidate selection policies, returns true if the given object is
// candidate for string deduplication.
static
bool
is_candidate_from_mark
(
oop
obj
);
static
bool
is_candidate_from_evacuation
(
bool
from_young
,
bool
to_young
,
oop
obj
);
public:
// Returns true if both G1 and string deduplication is enabled.
static
bool
is_enabled
()
{
return
_enabled
;
}
static
void
initialize
();
// Immediately deduplicates the given String object, bypassing the
// the deduplication queue.
static
void
deduplicate
(
oop
java_string
);
// Enqueues a deduplication candidate for later processing by the deduplication
// thread. Before enqueuing, these functions apply the appropriate candidate
// selection policy to filters out non-candidates.
static
void
enqueue_from_mark
(
oop
java_string
);
static
void
enqueue_from_evacuation
(
bool
from_young
,
bool
to_young
,
unsigned
int
queue
,
oop
java_string
);
static
void
oops_do
(
OopClosure
*
keep_alive
);
static
void
unlink
(
BoolObjectClosure
*
is_alive
);
static
void
unlink_or_oops_do
(
BoolObjectClosure
*
is_alive
,
OopClosure
*
keep_alive
,
bool
allow_resize_and_rehash
=
true
);
static
void
threads_do
(
ThreadClosure
*
tc
);
static
void
print_worker_threads_on
(
outputStream
*
st
);
static
void
verify
();
};
//
// This closure encapsulates the state and the closures needed when scanning
// the deduplication queue and table during the unlink_or_oops_do() operation.
// A single instance of this closure is created and then shared by all worker
// threads participating in the scan. The _next_queue and _next_bucket fields
// provide a simple mechanism for GC workers to claim exclusive access to a
// queue or a table partition.
//
class
G1StringDedupUnlinkOrOopsDoClosure
:
public
StackObj
{
private:
BoolObjectClosure
*
_is_alive
;
OopClosure
*
_keep_alive
;
G1StringDedupTable
*
_resized_table
;
G1StringDedupTable
*
_rehashed_table
;
size_t
_next_queue
;
size_t
_next_bucket
;
public:
G1StringDedupUnlinkOrOopsDoClosure
(
BoolObjectClosure
*
is_alive
,
OopClosure
*
keep_alive
,
bool
allow_resize_and_rehash
);
~
G1StringDedupUnlinkOrOopsDoClosure
();
bool
is_resizing
()
{
return
_resized_table
!=
NULL
;
}
G1StringDedupTable
*
resized_table
()
{
return
_resized_table
;
}
bool
is_rehashing
()
{
return
_rehashed_table
!=
NULL
;
}
// Atomically claims the next available queue for exclusive access by
// the current thread. Returns the queue number of the claimed queue.
size_t
claim_queue
()
{
return
(
size_t
)
Atomic
::
add_ptr
(
1
,
&
_next_queue
)
-
1
;
}
// Atomically claims the next available table partition for exclusive
// access by the current thread. Returns the table bucket number where
// the claimed partition starts.
size_t
claim_table_partition
(
size_t
partition_size
)
{
return
(
size_t
)
Atomic
::
add_ptr
(
partition_size
,
&
_next_bucket
)
-
partition_size
;
}
// Applies and returns the result from the is_alive closure, or
// returns true if no such closure was provided.
bool
is_alive
(
oop
o
)
{
if
(
_is_alive
!=
NULL
)
{
return
_is_alive
->
do_object_b
(
o
);
}
return
true
;
}
// Applies the keep_alive closure, or does nothing if no such
// closure was provided.
void
keep_alive
(
oop
*
p
)
{
if
(
_keep_alive
!=
NULL
)
{
_keep_alive
->
do_oop
(
p
);
}
}
};
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUP_HPP
src/share/vm/gc_implementation/g1/g1StringDedupQueue.cpp
0 → 100644
浏览文件 @
2cff96e1
/*
* 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.
*
*/
#include "precompiled.hpp"
#include "classfile/javaClasses.hpp"
#include "gc_implementation/g1/g1StringDedupQueue.hpp"
#include "memory/gcLocker.hpp"
#include "runtime/mutexLocker.hpp"
#include "utilities/stack.inline.hpp"
G1StringDedupQueue
*
G1StringDedupQueue
::
_queue
=
NULL
;
const
size_t
G1StringDedupQueue
::
_max_size
=
1000000
;
// Max number of elements per queue
const
size_t
G1StringDedupQueue
::
_max_cache_size
=
0
;
// Max cache size per queue
G1StringDedupQueue
::
G1StringDedupQueue
()
:
_cursor
(
0
),
_empty
(
true
),
_dropped
(
0
)
{
_nqueues
=
MAX2
(
ParallelGCThreads
,
(
size_t
)
1
);
_queues
=
NEW_C_HEAP_ARRAY
(
G1StringDedupWorkerQueue
,
_nqueues
,
mtGC
);
for
(
size_t
i
=
0
;
i
<
_nqueues
;
i
++
)
{
new
(
_queues
+
i
)
G1StringDedupWorkerQueue
(
G1StringDedupWorkerQueue
::
default_segment_size
(),
_max_cache_size
,
_max_size
);
}
}
G1StringDedupQueue
::~
G1StringDedupQueue
()
{
ShouldNotReachHere
();
}
void
G1StringDedupQueue
::
create
()
{
assert
(
_queue
==
NULL
,
"One string deduplication queue allowed"
);
_queue
=
new
G1StringDedupQueue
();
}
void
G1StringDedupQueue
::
wait
()
{
MonitorLockerEx
ml
(
StringDedupQueue_lock
,
Mutex
::
_no_safepoint_check_flag
);
while
(
_queue
->
_empty
)
{
ml
.
wait
(
Mutex
::
_no_safepoint_check_flag
);
}
}
void
G1StringDedupQueue
::
push
(
uint
worker_id
,
oop
java_string
)
{
assert
(
SafepointSynchronize
::
is_at_safepoint
(),
"Must be at safepoint"
);
assert
(
worker_id
<
_queue
->
_nqueues
,
"Invalid queue"
);
// Push and notify waiter
G1StringDedupWorkerQueue
&
worker_queue
=
_queue
->
_queues
[
worker_id
];
if
(
!
worker_queue
.
is_full
())
{
worker_queue
.
push
(
java_string
);
if
(
_queue
->
_empty
)
{
MonitorLockerEx
ml
(
StringDedupQueue_lock
,
Mutex
::
_no_safepoint_check_flag
);
if
(
_queue
->
_empty
)
{
// Mark non-empty and notify waiter
_queue
->
_empty
=
false
;
ml
.
notify
();
}
}
}
else
{
// Queue is full, drop the string and update the statistics
Atomic
::
inc_ptr
(
&
_queue
->
_dropped
);
}
}
oop
G1StringDedupQueue
::
pop
()
{
assert
(
!
SafepointSynchronize
::
is_at_safepoint
(),
"Must not be at safepoint"
);
No_Safepoint_Verifier
nsv
;
// Try all queues before giving up
for
(
size_t
tries
=
0
;
tries
<
_queue
->
_nqueues
;
tries
++
)
{
// The cursor indicates where we left of last time
G1StringDedupWorkerQueue
*
queue
=
&
_queue
->
_queues
[
_queue
->
_cursor
];
while
(
!
queue
->
is_empty
())
{
oop
obj
=
queue
->
pop
();
// The oop we pop can be NULL if it was marked
// dead. Just ignore those and pop the next oop.
if
(
obj
!=
NULL
)
{
return
obj
;
}
}
// Try next queue
_queue
->
_cursor
=
(
_queue
->
_cursor
+
1
)
%
_queue
->
_nqueues
;
}
// Mark empty
_queue
->
_empty
=
true
;
return
NULL
;
}
void
G1StringDedupQueue
::
unlink_or_oops_do
(
G1StringDedupUnlinkOrOopsDoClosure
*
cl
)
{
// A worker thread first claims a queue, which ensures exclusive
// access to that queue, then continues to process it.
for
(;;)
{
// Grab next queue to scan
size_t
queue
=
cl
->
claim_queue
();
if
(
queue
>=
_queue
->
_nqueues
)
{
// End of queues
break
;
}
// Scan the queue
unlink_or_oops_do
(
cl
,
queue
);
}
}
void
G1StringDedupQueue
::
unlink_or_oops_do
(
G1StringDedupUnlinkOrOopsDoClosure
*
cl
,
size_t
queue
)
{
assert
(
queue
<
_queue
->
_nqueues
,
"Invalid queue"
);
StackIterator
<
oop
,
mtGC
>
iter
(
_queue
->
_queues
[
queue
]);
while
(
!
iter
.
is_empty
())
{
oop
*
p
=
iter
.
next_addr
();
if
(
*
p
!=
NULL
)
{
if
(
cl
->
is_alive
(
*
p
))
{
cl
->
keep_alive
(
p
);
}
else
{
// Clear dead reference
*
p
=
NULL
;
}
}
}
}
void
G1StringDedupQueue
::
print_statistics
(
outputStream
*
st
)
{
st
->
print_cr
(
" [Queue]
\n
"
" [Dropped: "
UINTX_FORMAT
"]"
,
_queue
->
_dropped
);
}
void
G1StringDedupQueue
::
verify
()
{
for
(
size_t
i
=
0
;
i
<
_queue
->
_nqueues
;
i
++
)
{
StackIterator
<
oop
,
mtGC
>
iter
(
_queue
->
_queues
[
i
]);
while
(
!
iter
.
is_empty
())
{
oop
obj
=
iter
.
next
();
if
(
obj
!=
NULL
)
{
guarantee
(
Universe
::
heap
()
->
is_in_reserved
(
obj
),
"Object must be on the heap"
);
guarantee
(
!
obj
->
is_forwarded
(),
"Object must not be forwarded"
);
guarantee
(
java_lang_String
::
is_instance
(
obj
),
"Object must be a String"
);
}
}
}
}
src/share/vm/gc_implementation/g1/g1StringDedupQueue.hpp
0 → 100644
浏览文件 @
2cff96e1
/*
* 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.
*
*/
#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUPQUEUE_HPP
#define SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUPQUEUE_HPP
#include "memory/allocation.hpp"
#include "oops/oop.hpp"
#include "utilities/stack.hpp"
class
G1StringDedupUnlinkOrOopsDoClosure
;
//
// The deduplication queue acts as the communication channel between the stop-the-world
// mark/evacuation phase and the concurrent deduplication phase. Deduplication candidates
// found during mark/evacuation are placed on this queue for later processing in the
// deduplication thread. A queue entry is an oop pointing to a String object (as opposed
// to entries in the deduplication hashtable which points to character arrays).
//
// While users of the queue treat it as a single queue, it is implemented as a set of
// queues, one queue per GC worker thread, to allow lock-free and cache-friendly enqueue
// operations by the GC workers.
//
// The oops in the queue are treated as weak pointers, meaning the objects they point to
// can become unreachable and pruned (cleared) before being popped by the deduplication
// thread.
//
// Pushing to the queue is thread safe (this relies on each thread using a unique worker
// id), but only allowed during a safepoint. Popping from the queue is NOT thread safe
// and can only be done by the deduplication thread outside a safepoint.
//
// The StringDedupQueue_lock is only used for blocking and waking up the deduplication
// thread in case the queue is empty or becomes non-empty, respectively. This lock does
// not otherwise protect the queue content.
//
class
G1StringDedupQueue
:
public
CHeapObj
<
mtGC
>
{
private:
typedef
Stack
<
oop
,
mtGC
>
G1StringDedupWorkerQueue
;
static
G1StringDedupQueue
*
_queue
;
static
const
size_t
_max_size
;
static
const
size_t
_max_cache_size
;
G1StringDedupWorkerQueue
*
_queues
;
size_t
_nqueues
;
size_t
_cursor
;
volatile
bool
_empty
;
// Statistics counter, only used for logging.
uintx
_dropped
;
G1StringDedupQueue
();
~
G1StringDedupQueue
();
static
void
unlink_or_oops_do
(
G1StringDedupUnlinkOrOopsDoClosure
*
cl
,
size_t
queue
);
public:
static
void
create
();
// Blocks and waits for the queue to become non-empty.
static
void
wait
();
// Pushes a deduplication candidate onto a specific GC worker queue.
static
void
push
(
uint
worker_id
,
oop
java_string
);
// Pops a deduplication candidate from any queue, returns NULL if
// all queues are empty.
static
oop
pop
();
static
void
unlink_or_oops_do
(
G1StringDedupUnlinkOrOopsDoClosure
*
cl
);
static
void
print_statistics
(
outputStream
*
st
);
static
void
verify
();
};
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUPQUEUE_HPP
src/share/vm/gc_implementation/g1/g1StringDedupStat.cpp
0 → 100644
浏览文件 @
2cff96e1
/*
* 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.
*
*/
#include "precompiled.hpp"
#include "gc_implementation/g1/g1StringDedupStat.hpp"
G1StringDedupStat
::
G1StringDedupStat
()
:
_inspected
(
0
),
_skipped
(
0
),
_hashed
(
0
),
_known
(
0
),
_new
(
0
),
_new_bytes
(
0
),
_deduped
(
0
),
_deduped_bytes
(
0
),
_deduped_young
(
0
),
_deduped_young_bytes
(
0
),
_deduped_old
(
0
),
_deduped_old_bytes
(
0
),
_idle
(
0
),
_exec
(
0
),
_block
(
0
),
_start
(
0.0
),
_idle_elapsed
(
0.0
),
_exec_elapsed
(
0.0
),
_block_elapsed
(
0.0
)
{
}
void
G1StringDedupStat
::
add
(
const
G1StringDedupStat
&
stat
)
{
_inspected
+=
stat
.
_inspected
;
_skipped
+=
stat
.
_skipped
;
_hashed
+=
stat
.
_hashed
;
_known
+=
stat
.
_known
;
_new
+=
stat
.
_new
;
_new_bytes
+=
stat
.
_new_bytes
;
_deduped
+=
stat
.
_deduped
;
_deduped_bytes
+=
stat
.
_deduped_bytes
;
_deduped_young
+=
stat
.
_deduped_young
;
_deduped_young_bytes
+=
stat
.
_deduped_young_bytes
;
_deduped_old
+=
stat
.
_deduped_old
;
_deduped_old_bytes
+=
stat
.
_deduped_old_bytes
;
_idle
+=
stat
.
_idle
;
_exec
+=
stat
.
_exec
;
_block
+=
stat
.
_block
;
_idle_elapsed
+=
stat
.
_idle_elapsed
;
_exec_elapsed
+=
stat
.
_exec_elapsed
;
_block_elapsed
+=
stat
.
_block_elapsed
;
}
void
G1StringDedupStat
::
print_summary
(
outputStream
*
st
,
const
G1StringDedupStat
&
last_stat
,
const
G1StringDedupStat
&
total_stat
)
{
double
total_deduped_bytes_percent
=
0.0
;
if
(
total_stat
.
_new_bytes
>
0
)
{
// Avoid division by zero
total_deduped_bytes_percent
=
(
double
)
total_stat
.
_deduped_bytes
/
(
double
)
total_stat
.
_new_bytes
*
100.0
;
}
st
->
date_stamp
(
PrintGCDateStamps
);
st
->
stamp
(
PrintGCTimeStamps
);
st
->
print_cr
(
"[GC concurrent-string-deduplication, "
G1_STRDEDUP_BYTES_FORMAT_NS
"->"
G1_STRDEDUP_BYTES_FORMAT_NS
"("
G1_STRDEDUP_BYTES_FORMAT_NS
"), avg "
G1_STRDEDUP_PERCENT_FORMAT_NS
", "
G1_STRDEDUP_TIME_FORMAT
"]"
,
G1_STRDEDUP_BYTES_PARAM
(
last_stat
.
_new_bytes
),
G1_STRDEDUP_BYTES_PARAM
(
last_stat
.
_new_bytes
-
last_stat
.
_deduped_bytes
),
G1_STRDEDUP_BYTES_PARAM
(
last_stat
.
_deduped_bytes
),
total_deduped_bytes_percent
,
last_stat
.
_exec_elapsed
);
}
void
G1StringDedupStat
::
print_statistics
(
outputStream
*
st
,
const
G1StringDedupStat
&
stat
,
bool
total
)
{
double
young_percent
=
0.0
;
double
old_percent
=
0.0
;
double
skipped_percent
=
0.0
;
double
hashed_percent
=
0.0
;
double
known_percent
=
0.0
;
double
new_percent
=
0.0
;
double
deduped_percent
=
0.0
;
double
deduped_bytes_percent
=
0.0
;
double
deduped_young_percent
=
0.0
;
double
deduped_young_bytes_percent
=
0.0
;
double
deduped_old_percent
=
0.0
;
double
deduped_old_bytes_percent
=
0.0
;
if
(
stat
.
_inspected
>
0
)
{
// Avoid division by zero
skipped_percent
=
(
double
)
stat
.
_skipped
/
(
double
)
stat
.
_inspected
*
100.0
;
hashed_percent
=
(
double
)
stat
.
_hashed
/
(
double
)
stat
.
_inspected
*
100.0
;
known_percent
=
(
double
)
stat
.
_known
/
(
double
)
stat
.
_inspected
*
100.0
;
new_percent
=
(
double
)
stat
.
_new
/
(
double
)
stat
.
_inspected
*
100.0
;
}
if
(
stat
.
_new
>
0
)
{
// Avoid division by zero
deduped_percent
=
(
double
)
stat
.
_deduped
/
(
double
)
stat
.
_new
*
100.0
;
}
if
(
stat
.
_deduped
>
0
)
{
// Avoid division by zero
deduped_young_percent
=
(
double
)
stat
.
_deduped_young
/
(
double
)
stat
.
_deduped
*
100.0
;
deduped_old_percent
=
(
double
)
stat
.
_deduped_old
/
(
double
)
stat
.
_deduped
*
100.0
;
}
if
(
stat
.
_new_bytes
>
0
)
{
// Avoid division by zero
deduped_bytes_percent
=
(
double
)
stat
.
_deduped_bytes
/
(
double
)
stat
.
_new_bytes
*
100.0
;
}
if
(
stat
.
_deduped_bytes
>
0
)
{
// Avoid division by zero
deduped_young_bytes_percent
=
(
double
)
stat
.
_deduped_young_bytes
/
(
double
)
stat
.
_deduped_bytes
*
100.0
;
deduped_old_bytes_percent
=
(
double
)
stat
.
_deduped_old_bytes
/
(
double
)
stat
.
_deduped_bytes
*
100.0
;
}
if
(
total
)
{
st
->
print_cr
(
" [Total Exec: "
UINTX_FORMAT
"/"
G1_STRDEDUP_TIME_FORMAT
", Idle: "
UINTX_FORMAT
"/"
G1_STRDEDUP_TIME_FORMAT
", Blocked: "
UINTX_FORMAT
"/"
G1_STRDEDUP_TIME_FORMAT
"]"
,
stat
.
_exec
,
stat
.
_exec_elapsed
,
stat
.
_idle
,
stat
.
_idle_elapsed
,
stat
.
_block
,
stat
.
_block_elapsed
);
}
else
{
st
->
print_cr
(
" [Last Exec: "
G1_STRDEDUP_TIME_FORMAT
", Idle: "
G1_STRDEDUP_TIME_FORMAT
", Blocked: "
UINTX_FORMAT
"/"
G1_STRDEDUP_TIME_FORMAT
"]"
,
stat
.
_exec_elapsed
,
stat
.
_idle_elapsed
,
stat
.
_block
,
stat
.
_block_elapsed
);
}
st
->
print_cr
(
" [Inspected: "
G1_STRDEDUP_OBJECTS_FORMAT
"]
\n
"
" [Skipped: "
G1_STRDEDUP_OBJECTS_FORMAT
"("
G1_STRDEDUP_PERCENT_FORMAT
")]
\n
"
" [Hashed: "
G1_STRDEDUP_OBJECTS_FORMAT
"("
G1_STRDEDUP_PERCENT_FORMAT
")]
\n
"
" [Known: "
G1_STRDEDUP_OBJECTS_FORMAT
"("
G1_STRDEDUP_PERCENT_FORMAT
")]
\n
"
" [New: "
G1_STRDEDUP_OBJECTS_FORMAT
"("
G1_STRDEDUP_PERCENT_FORMAT
") "
G1_STRDEDUP_BYTES_FORMAT
"]
\n
"
" [Deduplicated: "
G1_STRDEDUP_OBJECTS_FORMAT
"("
G1_STRDEDUP_PERCENT_FORMAT
") "
G1_STRDEDUP_BYTES_FORMAT
"("
G1_STRDEDUP_PERCENT_FORMAT
")]
\n
"
" [Young: "
G1_STRDEDUP_OBJECTS_FORMAT
"("
G1_STRDEDUP_PERCENT_FORMAT
") "
G1_STRDEDUP_BYTES_FORMAT
"("
G1_STRDEDUP_PERCENT_FORMAT
")]
\n
"
" [Old: "
G1_STRDEDUP_OBJECTS_FORMAT
"("
G1_STRDEDUP_PERCENT_FORMAT
") "
G1_STRDEDUP_BYTES_FORMAT
"("
G1_STRDEDUP_PERCENT_FORMAT
")]"
,
stat
.
_inspected
,
stat
.
_skipped
,
skipped_percent
,
stat
.
_hashed
,
hashed_percent
,
stat
.
_known
,
known_percent
,
stat
.
_new
,
new_percent
,
G1_STRDEDUP_BYTES_PARAM
(
stat
.
_new_bytes
),
stat
.
_deduped
,
deduped_percent
,
G1_STRDEDUP_BYTES_PARAM
(
stat
.
_deduped_bytes
),
deduped_bytes_percent
,
stat
.
_deduped_young
,
deduped_young_percent
,
G1_STRDEDUP_BYTES_PARAM
(
stat
.
_deduped_young_bytes
),
deduped_young_bytes_percent
,
stat
.
_deduped_old
,
deduped_old_percent
,
G1_STRDEDUP_BYTES_PARAM
(
stat
.
_deduped_old_bytes
),
deduped_old_bytes_percent
);
}
src/share/vm/gc_implementation/g1/g1StringDedupStat.hpp
0 → 100644
浏览文件 @
2cff96e1
/*
* 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.
*
*/
#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUPSTAT_HPP
#define SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUPSTAT_HPP
#include "memory/allocation.hpp"
#include "runtime/os.hpp"
// Macros for GC log output formating
#define G1_STRDEDUP_OBJECTS_FORMAT UINTX_FORMAT_W(12)
#define G1_STRDEDUP_TIME_FORMAT "%1.7lf secs"
#define G1_STRDEDUP_PERCENT_FORMAT "%5.1lf%%"
#define G1_STRDEDUP_PERCENT_FORMAT_NS "%.1lf%%"
#define G1_STRDEDUP_BYTES_FORMAT "%8.1lf%s"
#define G1_STRDEDUP_BYTES_FORMAT_NS "%.1lf%s"
#define G1_STRDEDUP_BYTES_PARAM(bytes) byte_size_in_proper_unit((double)(bytes)), proper_unit_for_byte_size((bytes))
//
// Statistics gathered by the deduplication thread.
//
class
G1StringDedupStat
:
public
StackObj
{
private:
// Counters
uintx
_inspected
;
uintx
_skipped
;
uintx
_hashed
;
uintx
_known
;
uintx
_new
;
uintx
_new_bytes
;
uintx
_deduped
;
uintx
_deduped_bytes
;
uintx
_deduped_young
;
uintx
_deduped_young_bytes
;
uintx
_deduped_old
;
uintx
_deduped_old_bytes
;
uintx
_idle
;
uintx
_exec
;
uintx
_block
;
// Time spent by the deduplication thread in different phases
double
_start
;
double
_idle_elapsed
;
double
_exec_elapsed
;
double
_block_elapsed
;
public:
G1StringDedupStat
();
void
inc_inspected
()
{
_inspected
++
;
}
void
inc_skipped
()
{
_skipped
++
;
}
void
inc_hashed
()
{
_hashed
++
;
}
void
inc_known
()
{
_known
++
;
}
void
inc_new
(
uintx
bytes
)
{
_new
++
;
_new_bytes
+=
bytes
;
}
void
inc_deduped_young
(
uintx
bytes
)
{
_deduped
++
;
_deduped_bytes
+=
bytes
;
_deduped_young
++
;
_deduped_young_bytes
+=
bytes
;
}
void
inc_deduped_old
(
uintx
bytes
)
{
_deduped
++
;
_deduped_bytes
+=
bytes
;
_deduped_old
++
;
_deduped_old_bytes
+=
bytes
;
}
void
mark_idle
()
{
_start
=
os
::
elapsedTime
();
_idle
++
;
}
void
mark_exec
()
{
double
now
=
os
::
elapsedTime
();
_idle_elapsed
=
now
-
_start
;
_start
=
now
;
_exec
++
;
}
void
mark_block
()
{
double
now
=
os
::
elapsedTime
();
_exec_elapsed
+=
now
-
_start
;
_start
=
now
;
_block
++
;
}
void
mark_unblock
()
{
double
now
=
os
::
elapsedTime
();
_block_elapsed
+=
now
-
_start
;
_start
=
now
;
}
void
mark_done
()
{
double
now
=
os
::
elapsedTime
();
_exec_elapsed
+=
now
-
_start
;
}
void
add
(
const
G1StringDedupStat
&
stat
);
static
void
print_summary
(
outputStream
*
st
,
const
G1StringDedupStat
&
last_stat
,
const
G1StringDedupStat
&
total_stat
);
static
void
print_statistics
(
outputStream
*
st
,
const
G1StringDedupStat
&
stat
,
bool
total
);
};
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUPSTAT_HPP
src/share/vm/gc_implementation/g1/g1StringDedupTable.cpp
0 → 100644
浏览文件 @
2cff96e1
此差异已折叠。
点击以展开。
src/share/vm/gc_implementation/g1/g1StringDedupTable.hpp
0 → 100644
浏览文件 @
2cff96e1
/*
* 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.
*
*/
#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUPTABLE_HPP
#define SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUPTABLE_HPP
#include "gc_implementation/g1/g1StringDedupStat.hpp"
#include "runtime/mutexLocker.hpp"
class
G1StringDedupEntryCache
;
//
// Table entry in the deduplication hashtable. Points weakly to the
// character array. Can be chained in a linked list in case of hash
// collisions or when placed in a freelist in the entry cache.
//
class
G1StringDedupEntry
:
public
CHeapObj
<
mtGC
>
{
private:
G1StringDedupEntry
*
_next
;
unsigned
int
_hash
;
typeArrayOop
_obj
;
public:
G1StringDedupEntry
()
:
_next
(
NULL
),
_hash
(
0
),
_obj
(
NULL
)
{
}
G1StringDedupEntry
*
next
()
{
return
_next
;
}
G1StringDedupEntry
**
next_addr
()
{
return
&
_next
;
}
void
set_next
(
G1StringDedupEntry
*
next
)
{
_next
=
next
;
}
unsigned
int
hash
()
{
return
_hash
;
}
void
set_hash
(
unsigned
int
hash
)
{
_hash
=
hash
;
}
typeArrayOop
obj
()
{
return
_obj
;
}
typeArrayOop
*
obj_addr
()
{
return
&
_obj
;
}
void
set_obj
(
typeArrayOop
obj
)
{
_obj
=
obj
;
}
};
//
// The deduplication hashtable keeps track of all unique character arrays used
// by String objects. Each table entry weakly points to an character array, allowing
// otherwise unreachable character arrays to be declared dead and pruned from the
// table.
//
// The table is dynamically resized to accommodate the current number of table entries.
// The table has hash buckets with chains for hash collision. If the average chain
// length goes above or below given thresholds the table grows or shrinks accordingly.
//
// The table is also dynamically rehashed (using a new hash seed) if it becomes severely
// unbalanced, i.e., a hash chain is significantly longer than average.
//
// All access to the table is protected by the StringDedupTable_lock, except under
// safepoints in which case GC workers are allowed to access a table partitions they
// have claimed without first acquiring the lock. Note however, that this applies only
// the table partition (i.e. a range of elements in _buckets), not other parts of the
// table such as the _entries field, statistics counters, etc.
//
class
G1StringDedupTable
:
public
CHeapObj
<
mtGC
>
{
private:
// The currently active hashtable instance. Only modified when
// the table is resizes or rehashed.
static
G1StringDedupTable
*
_table
;
// Cache for reuse and fast alloc/free of table entries.
static
G1StringDedupEntryCache
*
_entry_cache
;
G1StringDedupEntry
**
_buckets
;
size_t
_size
;
uintx
_entries
;
uintx
_shrink_threshold
;
uintx
_grow_threshold
;
bool
_rehash_needed
;
// The hash seed also dictates which hash function to use. A
// zero hash seed means we will use the Java compatible hash
// function (which doesn't use a seed), and a non-zero hash
// seed means we use the murmur3 hash function.
jint
_hash_seed
;
// Constants governing table resize/rehash/cache.
static
const
size_t
_min_size
;
static
const
size_t
_max_size
;
static
const
double
_grow_load_factor
;
static
const
double
_shrink_load_factor
;
static
const
uintx
_rehash_multiple
;
static
const
uintx
_rehash_threshold
;
static
const
double
_max_cache_factor
;
// Table statistics, only used for logging.
static
uintx
_entries_added
;
static
uintx
_entries_removed
;
static
uintx
_resize_count
;
static
uintx
_rehash_count
;
G1StringDedupTable
(
size_t
size
,
jint
hash_seed
=
0
);
~
G1StringDedupTable
();
// Returns the hash bucket at the given index.
G1StringDedupEntry
**
bucket
(
size_t
index
)
{
return
_buckets
+
index
;
}
// Returns the hash bucket index for the given hash code.
size_t
hash_to_index
(
unsigned
int
hash
)
{
return
(
size_t
)
hash
&
(
_size
-
1
);
}
// Adds a new table entry to the given hash bucket.
void
add
(
typeArrayOop
value
,
unsigned
int
hash
,
G1StringDedupEntry
**
list
);
// Removes the given table entry from the table.
void
remove
(
G1StringDedupEntry
**
pentry
,
uint
worker_id
);
// Transfers a table entry from the current table to the destination table.
void
transfer
(
G1StringDedupEntry
**
pentry
,
G1StringDedupTable
*
dest
);
// Returns an existing character array in the given hash bucket, or NULL
// if no matching character array exists.
typeArrayOop
lookup
(
typeArrayOop
value
,
unsigned
int
hash
,
G1StringDedupEntry
**
list
,
uintx
&
count
);
// Returns an existing character array in the table, or inserts a new
// table entry if no matching character array exists.
typeArrayOop
lookup_or_add_inner
(
typeArrayOop
value
,
unsigned
int
hash
);
// Thread safe lookup or add of table entry
static
typeArrayOop
lookup_or_add
(
typeArrayOop
value
,
unsigned
int
hash
)
{
// Protect the table from concurrent access. Also note that this lock
// acts as a fence for _table, which could have been replaced by a new
// instance if the table was resized or rehashed.
MutexLockerEx
ml
(
StringDedupTable_lock
,
Mutex
::
_no_safepoint_check_flag
);
return
_table
->
lookup_or_add_inner
(
value
,
hash
);
}
// Returns true if the hashtable is currently using a Java compatible
// hash function.
static
bool
use_java_hash
()
{
return
_table
->
_hash_seed
==
0
;
}
static
bool
equals
(
typeArrayOop
value1
,
typeArrayOop
value2
);
// Computes the hash code for the given character array, using the
// currently active hash function and hash seed.
static
unsigned
int
hash_code
(
typeArrayOop
value
);
static
uintx
unlink_or_oops_do
(
G1StringDedupUnlinkOrOopsDoClosure
*
cl
,
size_t
partition_begin
,
size_t
partition_end
,
uint
worker_id
);
public:
static
void
create
();
// Deduplicates the given String object, or adds its backing
// character array to the deduplication hashtable.
static
void
deduplicate
(
oop
java_string
,
G1StringDedupStat
&
stat
);
// If a table resize is needed, returns a newly allocated empty
// hashtable of the proper size.
static
G1StringDedupTable
*
prepare_resize
();
// Installs a newly resized table as the currently active table
// and deletes the previously active table.
static
void
finish_resize
(
G1StringDedupTable
*
resized_table
);
// If a table rehash is needed, returns a newly allocated empty
// hashtable and updates the hash seed.
static
G1StringDedupTable
*
prepare_rehash
();
// Transfers rehashed entries from the currently active table into
// the new table. Installs the new table as the currently active table
// and deletes the previously active table.
static
void
finish_rehash
(
G1StringDedupTable
*
rehashed_table
);
// If the table entry cache has grown too large, trim it down according to policy
static
void
trim_entry_cache
();
static
void
unlink_or_oops_do
(
G1StringDedupUnlinkOrOopsDoClosure
*
cl
,
uint
worker_id
);
static
void
print_statistics
(
outputStream
*
st
);
static
void
verify
();
};
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUPTABLE_HPP
src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp
0 → 100644
浏览文件 @
2cff96e1
/*
* 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.
*
*/
#include "precompiled.hpp"
#include "gc_implementation/g1/g1Log.hpp"
#include "gc_implementation/g1/g1StringDedup.hpp"
#include "gc_implementation/g1/g1StringDedupTable.hpp"
#include "gc_implementation/g1/g1StringDedupThread.hpp"
#include "gc_implementation/g1/g1StringDedupQueue.hpp"
G1StringDedupThread
*
G1StringDedupThread
::
_thread
=
NULL
;
G1StringDedupThread
::
G1StringDedupThread
()
:
ConcurrentGCThread
()
{
set_name
(
"String Deduplication Thread"
);
create_and_start
();
}
G1StringDedupThread
::~
G1StringDedupThread
()
{
ShouldNotReachHere
();
}
void
G1StringDedupThread
::
create
()
{
assert
(
G1StringDedup
::
is_enabled
(),
"String deduplication not enabled"
);
assert
(
_thread
==
NULL
,
"One string deduplication thread allowed"
);
_thread
=
new
G1StringDedupThread
();
}
G1StringDedupThread
*
G1StringDedupThread
::
thread
()
{
assert
(
G1StringDedup
::
is_enabled
(),
"String deduplication not enabled"
);
assert
(
_thread
!=
NULL
,
"String deduplication thread not created"
);
return
_thread
;
}
void
G1StringDedupThread
::
print_on
(
outputStream
*
st
)
const
{
st
->
print
(
"
\"
%s
\"
"
,
name
());
Thread
::
print_on
(
st
);
st
->
cr
();
}
void
G1StringDedupThread
::
run
()
{
G1StringDedupStat
total_stat
;
initialize_in_thread
();
wait_for_universe_init
();
// Main loop
for
(;;)
{
G1StringDedupStat
stat
;
stat
.
mark_idle
();
// Wait for the queue to become non-empty
G1StringDedupQueue
::
wait
();
// Include this thread in safepoints
stsJoin
();
stat
.
mark_exec
();
// Process the queue
for
(;;)
{
oop
java_string
=
G1StringDedupQueue
::
pop
();
if
(
java_string
==
NULL
)
{
break
;
}
G1StringDedupTable
::
deduplicate
(
java_string
,
stat
);
// Safepoint this thread if needed
if
(
stsShouldYield
())
{
stat
.
mark_block
();
stsYield
(
NULL
);
stat
.
mark_unblock
();
}
}
G1StringDedupTable
::
trim_entry_cache
();
stat
.
mark_done
();
// Print statistics
total_stat
.
add
(
stat
);
print
(
gclog_or_tty
,
stat
,
total_stat
);
// Exclude this thread from safepoints
stsLeave
();
}
ShouldNotReachHere
();
}
void
G1StringDedupThread
::
print
(
outputStream
*
st
,
const
G1StringDedupStat
&
last_stat
,
const
G1StringDedupStat
&
total_stat
)
{
if
(
G1Log
::
fine
()
||
PrintStringDeduplicationStatistics
)
{
G1StringDedupStat
::
print_summary
(
st
,
last_stat
,
total_stat
);
if
(
PrintStringDeduplicationStatistics
)
{
G1StringDedupStat
::
print_statistics
(
st
,
last_stat
,
false
);
G1StringDedupStat
::
print_statistics
(
st
,
total_stat
,
true
);
G1StringDedupTable
::
print_statistics
(
st
);
G1StringDedupQueue
::
print_statistics
(
st
);
}
}
}
src/share/vm/gc_implementation/g1/g1StringDedupThread.hpp
0 → 100644
浏览文件 @
2cff96e1
/*
* 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.
*
*/
#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUPTHREAD_HPP
#define SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUPTHREAD_HPP
#include "gc_implementation/g1/g1StringDedupStat.hpp"
#include "gc_implementation/shared/concurrentGCThread.hpp"
//
// The deduplication thread is where the actual deduplication occurs. It waits for
// deduplication candidates to appear on the deduplication queue, removes them from
// the queue and tries to deduplicate them. It uses the deduplication hashtable to
// find identical, already existing, character arrays on the heap. The thread runs
// concurrently with the Java application but participates in safepoints to allow
// the GC to adjust and unlink oops from the deduplication queue and table.
//
class
G1StringDedupThread
:
public
ConcurrentGCThread
{
private:
static
G1StringDedupThread
*
_thread
;
G1StringDedupThread
();
~
G1StringDedupThread
();
void
print
(
outputStream
*
st
,
const
G1StringDedupStat
&
last_stat
,
const
G1StringDedupStat
&
total_stat
);
public:
static
void
create
();
static
G1StringDedupThread
*
thread
();
virtual
void
run
();
virtual
void
print_on
(
outputStream
*
st
)
const
;
};
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUPTHREAD_HPP
src/share/vm/gc_implementation/shared/markSweep.inline.hpp
浏览文件 @
2cff96e1
/*
* Copyright (c) 2000, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 201
4
, 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
...
...
@@ -30,10 +30,18 @@
#include "utilities/stack.inline.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_ALL_GCS
#include "gc_implementation/g1/g1StringDedup.hpp"
#include "gc_implementation/parallelScavenge/psParallelCompact.hpp"
#endif // INCLUDE_ALL_GCS
inline
void
MarkSweep
::
mark_object
(
oop
obj
)
{
#if INCLUDE_ALL_GCS
if
(
G1StringDedup
::
is_enabled
())
{
// We must enqueue the object before it is marked
// as we otherwise can't read the object's age.
G1StringDedup
::
enqueue_from_mark
(
obj
);
}
#endif
// some marks may contain information we need to preserve so we store them away
// and overwrite the mark. We'll restore it at the end of markSweep.
markOop
mark
=
obj
->
mark
();
...
...
src/share/vm/runtime/arguments.cpp
浏览文件 @
2cff96e1
...
...
@@ -2217,6 +2217,8 @@ bool Arguments::check_vm_args_consistency() {
"G1ConcRSHotCardLimit"
);
status
=
status
&&
verify_interval
(
G1ConcRSLogCacheSize
,
0
,
31
,
"G1ConcRSLogCacheSize"
);
status
=
status
&&
verify_interval
(
StringDeduplicationAgeThreshold
,
1
,
markOopDesc
::
max_age
,
"StringDeduplicationAgeThreshold"
);
}
if
(
UseConcMarkSweepGC
)
{
status
=
status
&&
verify_min_value
(
CMSOldPLABNumRefills
,
1
,
"CMSOldPLABNumRefills"
);
...
...
src/share/vm/runtime/globals.hpp
浏览文件 @
2cff96e1
...
...
@@ -3812,6 +3812,22 @@ class CommandLineFlags {
experimental(uintx, SymbolTableSize, defaultSymbolTableSize, \
"Number of buckets in the JVM internal Symbol table") \
\
product(bool, UseStringDeduplication, false, \
"Use string deduplication") \
\
product(bool, PrintStringDeduplicationStatistics, false, \
"Print string deduplication statistics") \
\
product(uintx, StringDeduplicationAgeThreshold, 3, \
"A string must reach this age (or be promoted to an old region) " \
"to be considered for deduplication") \
\
diagnostic(bool, StringDeduplicationResizeALot, false, \
"Force table resize every time the table is scanned") \
\
diagnostic(bool, StringDeduplicationRehashALot, false, \
"Force table rehash every time the table is scanned") \
\
develop(bool, TraceDefaultMethods, false, \
"Trace the default method processing steps") \
\
...
...
src/share/vm/runtime/mutexLocker.cpp
浏览文件 @
2cff96e1
/*
* Copyright (c) 1997, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
4
, 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
...
...
@@ -58,6 +58,8 @@ Mutex* SignatureHandlerLibrary_lock = NULL;
Mutex
*
VtableStubs_lock
=
NULL
;
Mutex
*
SymbolTable_lock
=
NULL
;
Mutex
*
StringTable_lock
=
NULL
;
Monitor
*
StringDedupQueue_lock
=
NULL
;
Mutex
*
StringDedupTable_lock
=
NULL
;
Mutex
*
CodeCache_lock
=
NULL
;
Mutex
*
MethodData_lock
=
NULL
;
Mutex
*
RetData_lock
=
NULL
;
...
...
@@ -196,6 +198,9 @@ void mutex_init() {
def
(
MMUTracker_lock
,
Mutex
,
leaf
,
true
);
def
(
HotCardCache_lock
,
Mutex
,
special
,
true
);
def
(
EvacFailureStack_lock
,
Mutex
,
nonleaf
,
true
);
def
(
StringDedupQueue_lock
,
Monitor
,
leaf
,
true
);
def
(
StringDedupTable_lock
,
Mutex
,
leaf
,
true
);
}
def
(
ParGCRareEvent_lock
,
Mutex
,
leaf
,
true
);
def
(
DerivedPointerTableGC_lock
,
Mutex
,
leaf
,
true
);
...
...
src/share/vm/runtime/mutexLocker.hpp
浏览文件 @
2cff96e1
/*
* Copyright (c) 1997, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
4
, 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
...
...
@@ -63,6 +63,8 @@ extern Mutex* SignatureHandlerLibrary_lock; // a lock on the SignatureHandl
extern
Mutex
*
VtableStubs_lock
;
// a lock on the VtableStubs
extern
Mutex
*
SymbolTable_lock
;
// a lock on the symbol table
extern
Mutex
*
StringTable_lock
;
// a lock on the interned string table
extern
Monitor
*
StringDedupQueue_lock
;
// a lock on the string deduplication queue
extern
Mutex
*
StringDedupTable_lock
;
// a lock on the string deduplication table
extern
Mutex
*
CodeCache_lock
;
// a lock on the CodeCache, rank is special, use MutexLockerEx
extern
Mutex
*
MethodData_lock
;
// a lock on installation of method data
extern
Mutex
*
RetData_lock
;
// a lock on installation of RetData inside method data
...
...
test/gc/g1/TestGCLogMessages.java
浏览文件 @
2cff96e1
...
...
@@ -49,11 +49,13 @@ public class TestGCLogMessages {
output
.
shouldNotContain
(
"[Redirty Cards"
);
output
.
shouldNotContain
(
"[Code Root Purge"
);
output
.
shouldNotContain
(
"[String Dedup Fixup"
);
output
.
shouldNotContain
(
"[Young Free CSet"
);
output
.
shouldNotContain
(
"[Non-Young Free CSet"
);
output
.
shouldHaveExitValue
(
0
);
pb
=
ProcessTools
.
createJavaProcessBuilder
(
"-XX:+UseG1GC"
,
"-XX:+UseStringDeduplication"
,
"-Xmx10M"
,
"-XX:+PrintGCDetails"
,
GCTest
.
class
.
getName
());
...
...
@@ -62,11 +64,13 @@ public class TestGCLogMessages {
output
.
shouldContain
(
"[Redirty Cards"
);
output
.
shouldContain
(
"[Code Root Purge"
);
output
.
shouldContain
(
"[String Dedup Fixup"
);
output
.
shouldNotContain
(
"[Young Free CSet"
);
output
.
shouldNotContain
(
"[Non-Young Free CSet"
);
output
.
shouldHaveExitValue
(
0
);
pb
=
ProcessTools
.
createJavaProcessBuilder
(
"-XX:+UseG1GC"
,
"-XX:+UseStringDeduplication"
,
"-Xmx10M"
,
"-XX:+PrintGCDetails"
,
"-XX:+UnlockExperimentalVMOptions"
,
...
...
@@ -77,6 +81,7 @@ public class TestGCLogMessages {
output
.
shouldContain
(
"[Redirty Cards"
);
output
.
shouldContain
(
"[Code Root Purge"
);
output
.
shouldContain
(
"[String Dedup Fixup"
);
output
.
shouldContain
(
"[Young Free CSet"
);
output
.
shouldContain
(
"[Non-Young Free CSet"
);
...
...
test/gc/g1/TestStringDeduplicationAgeThreshold.java
0 → 100644
浏览文件 @
2cff96e1
/*
* 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 TestStringDeduplicationAgeThreshold
* @summary Test string deduplication age threshold
* @bug 8029075
* @key gc
* @library /testlibrary
*/
public
class
TestStringDeduplicationAgeThreshold
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
TestStringDeduplicationTools
.
testAgeThreshold
();
}
}
test/gc/g1/TestStringDeduplicationFullGC.java
0 → 100644
浏览文件 @
2cff96e1
/*
* 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 TestStringDeduplicationFullGC
* @summary Test string deduplication during full GC
* @bug 8029075
* @key gc
* @library /testlibrary
*/
public
class
TestStringDeduplicationFullGC
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
TestStringDeduplicationTools
.
testFullGC
();
}
}
test/gc/g1/TestStringDeduplicationInterned.java
0 → 100644
浏览文件 @
2cff96e1
/*
* 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 TestStringDeduplicationInterned
* @summary Test string deduplication of interned strings
* @bug 8029075
* @key gc
* @library /testlibrary
*/
public
class
TestStringDeduplicationInterned
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
TestStringDeduplicationTools
.
testInterned
();
}
}
test/gc/g1/TestStringDeduplicationMemoryUsage.java
0 → 100644
浏览文件 @
2cff96e1
/*
* 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 TestStringDeduplicationMemoryUsage
* @summary Test string deduplication memory usage
* @bug 8029075
* @key gc
* @library /testlibrary
*/
public
class
TestStringDeduplicationMemoryUsage
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
TestStringDeduplicationTools
.
testMemoryUsage
();
}
}
test/gc/g1/TestStringDeduplicationPrintOptions.java
0 → 100644
浏览文件 @
2cff96e1
/*
* 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 TestStringDeduplicationPrintOptions
* @summary Test string deduplication print options
* @bug 8029075
* @key gc
* @library /testlibrary
*/
public
class
TestStringDeduplicationPrintOptions
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
TestStringDeduplicationTools
.
testPrintOptions
();
}
}
test/gc/g1/TestStringDeduplicationTableRehash.java
0 → 100644
浏览文件 @
2cff96e1
/*
* 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 TestStringDeduplicationTableRehash
* @summary Test string deduplication table rehash
* @bug 8029075
* @key gc
* @library /testlibrary
*/
public
class
TestStringDeduplicationTableRehash
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
TestStringDeduplicationTools
.
testTableRehash
();
}
}
test/gc/g1/TestStringDeduplicationTableResize.java
0 → 100644
浏览文件 @
2cff96e1
/*
* 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 TestStringDeduplicationTableResize
* @summary Test string deduplication table resize
* @bug 8029075
* @key gc
* @library /testlibrary
*/
public
class
TestStringDeduplicationTableResize
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
TestStringDeduplicationTools
.
testTableResize
();
}
}
test/gc/g1/TestStringDeduplicationTools.java
0 → 100644
浏览文件 @
2cff96e1
此差异已折叠。
点击以展开。
test/gc/g1/TestStringDeduplicationYoungGC.java
0 → 100644
浏览文件 @
2cff96e1
/*
* 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 TestStringDeduplicationYoungGC
* @summary Test string deduplication during young GC
* @bug 8029075
* @key gc
* @library /testlibrary
*/
public
class
TestStringDeduplicationYoungGC
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
TestStringDeduplicationTools
.
testYoungGC
();
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录