Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
fdde7db6
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看板
提交
fdde7db6
编写于
3月 13, 2014
作者:
K
kvn
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
a657cd07
6ae430cb
变更
38
展开全部
隐藏空白更改
内联
并排
Showing
38 changed file
with
1089 addition
and
384 deletion
+1089
-384
.hgtags
.hgtags
+6
-0
agent/src/share/classes/sun/jvm/hotspot/utilities/Hashtable.java
...rc/share/classes/sun/jvm/hotspot/utilities/Hashtable.java
+3
-2
make/excludeSrc.make
make/excludeSrc.make
+1
-1
make/hotspot_version
make/hotspot_version
+1
-1
src/cpu/sparc/vm/vm_version_sparc.hpp
src/cpu/sparc/vm/vm_version_sparc.hpp
+6
-2
src/os/bsd/vm/os_bsd.cpp
src/os/bsd/vm/os_bsd.cpp
+11
-0
src/os/linux/vm/os_linux.cpp
src/os/linux/vm/os_linux.cpp
+3
-0
src/os/posix/vm/os_posix.cpp
src/os/posix/vm/os_posix.cpp
+0
-4
src/os/solaris/vm/os_solaris.cpp
src/os/solaris/vm/os_solaris.cpp
+4
-0
src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp
src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp
+18
-5
src/share/vm/ci/ciMethod.cpp
src/share/vm/ci/ciMethod.cpp
+5
-0
src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp
...entation/concurrentMarkSweep/compactibleFreeListSpace.cpp
+4
-4
src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
+33
-37
src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp
src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp
+33
-113
src/share/vm/gc_implementation/g1/g1OopClosures.cpp
src/share/vm/gc_implementation/g1/g1OopClosures.cpp
+31
-0
src/share/vm/gc_implementation/g1/g1OopClosures.hpp
src/share/vm/gc_implementation/g1/g1OopClosures.hpp
+13
-26
src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp
src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp
+1
-1
src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp
src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp
+1
-1
src/share/vm/memory/binaryTreeDictionary.cpp
src/share/vm/memory/binaryTreeDictionary.cpp
+107
-120
src/share/vm/memory/binaryTreeDictionary.hpp
src/share/vm/memory/binaryTreeDictionary.hpp
+16
-16
src/share/vm/memory/metaspace.cpp
src/share/vm/memory/metaspace.cpp
+8
-8
src/share/vm/oops/constantPool.cpp
src/share/vm/oops/constantPool.cpp
+1
-0
src/share/vm/opto/c2_globals.hpp
src/share/vm/opto/c2_globals.hpp
+3
-0
src/share/vm/opto/output.cpp
src/share/vm/opto/output.cpp
+14
-1
src/share/vm/prims/jni.cpp
src/share/vm/prims/jni.cpp
+9
-5
src/share/vm/prims/jvm.cpp
src/share/vm/prims/jvm.cpp
+7
-1
src/share/vm/runtime/globals.cpp
src/share/vm/runtime/globals.cpp
+24
-0
src/share/vm/runtime/objectMonitor.cpp
src/share/vm/runtime/objectMonitor.cpp
+48
-16
src/share/vm/runtime/vmStructs.cpp
src/share/vm/runtime/vmStructs.cpp
+1
-1
src/share/vm/trace/trace.xml
src/share/vm/trace/trace.xml
+40
-0
src/share/vm/trace/tracetypes.xml
src/share/vm/trace/tracetypes.xml
+9
-17
test/compiler/inlining/InlineDefaultMethod1.java
test/compiler/inlining/InlineDefaultMethod1.java
+58
-0
test/serviceability/jvmti/TestRedefineWithUnresolvedClass.java
...serviceability/jvmti/TestRedefineWithUnresolvedClass.java
+82
-0
test/serviceability/jvmti/UnresolvedClassAgent.java
test/serviceability/jvmti/UnresolvedClassAgent.java
+69
-0
test/serviceability/jvmti/UnresolvedClassAgent.mf
test/serviceability/jvmti/UnresolvedClassAgent.mf
+3
-0
test/serviceability/sa/jmap-hashcode/Test8028623.java
test/serviceability/sa/jmap-hashcode/Test8028623.java
+74
-0
test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java
...testlibrary/com/oracle/java/testlibrary/ProcessTools.java
+79
-2
test/testlibrary/com/oracle/java/testlibrary/Utils.java
test/testlibrary/com/oracle/java/testlibrary/Utils.java
+263
-0
未找到文件。
.hgtags
浏览文件 @
fdde7db6
...
...
@@ -420,9 +420,15 @@ d45454002494d147c0761e6b37d8a73064f3cf92 hs25-b68
35038da7bb9ddd367a0a6bf926dfb281aee1d554 jdk8-b127
874c0b4a946c362bbf20d37c2a564b39093152e6 jdk8-b128
cb39165c4a65bbff8db356df411e762f9e5423b8 jdk8-b129
1dbaf664a611e5d9cab6d1be42537b67d0d05f94 jdk8-b130
b5e7ebfe185cb4c2eeb8a919025fc6a26be2fcef jdk8-b131
9f9179e8f0cfe74c08f3716cf3c38e21e1de4c4a hs25-b70
0c94c41dcd70e9a9b4d96e31275afd5a73daa72d jdk8-b132
412d3b5fe90e54c0ff9d9ac7374b98607c561d5a hs25.20-b01
4638c4d7ff106db0f29ef7f18b128dd7e69bc470 hs25.20-b02
e56d11f8cc2158d4280f80e56d196193349c150a hs25.20-b03
757fe22ae90681e2b6cff50699c5abbe2563dd2c jdk8u20-b01
9c2ddd17626e375554044a3082a6dc5e68184ed9 jdk8u20-b02
ecf3678d5736a645aea893b525a9eb5fa1a8e072 hs25.20-b04
51e1bb81df8680bd237630323de5e0704fb25607 jdk8u20-b03
54436d3b2a915ff50a8d6b34f61d5afb45be7bb6 hs25.20-b05
agent/src/share/classes/sun/jvm/hotspot/utilities/Hashtable.java
浏览文件 @
fdde7db6
/*
* Copyright (c) 2003, 201
2
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 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,8 +61,9 @@ public class Hashtable extends BasicHashtable {
long
h
=
0
;
int
s
=
0
;
int
len
=
buf
.
length
;
// Emulate the unsigned int in java_lang_String::hash_code
while
(
len
--
>
0
)
{
h
=
31
*
h
+
(
0xFF
L
&
buf
[
s
]);
h
=
31
*
h
+
(
0xFF
FFFFFF
L
&
buf
[
s
]);
s
++;
}
return
h
&
0xFFFFFFFF
L
;
...
...
make/excludeSrc.make
浏览文件 @
fdde7db6
...
...
@@ -86,7 +86,7 @@ ifeq ($(INCLUDE_ALL_GCS), false)
concurrentMark.cpp concurrentMarkThread.cpp dirtyCardQueue.cpp g1AllocRegion.cpp
\
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
\
g1MMUTracker.cpp g1MarkSweep.cpp g1MemoryPool.cpp g1MonitoringSupport.cpp
g1OopClosures.cpp
\
g1RemSet.cpp g1RemSetSummary.cpp g1SATBCardTableModRefBS.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
\
...
...
make/hotspot_version
浏览文件 @
fdde7db6
...
...
@@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2014
HS_MAJOR_VER=25
HS_MINOR_VER=20
HS_BUILD_NUMBER=0
4
HS_BUILD_NUMBER=0
5
JDK_MAJOR_VER=1
JDK_MINOR_VER=8
...
...
src/cpu/sparc/vm/vm_version_sparc.hpp
浏览文件 @
fdde7db6
...
...
@@ -49,7 +49,8 @@ protected:
M_family
=
15
,
T_family
=
16
,
T1_model
=
17
,
aes_instructions
=
18
sparc5_instructions
=
18
,
aes_instructions
=
19
};
enum
Feature_Flag_Set
{
...
...
@@ -74,6 +75,7 @@ protected:
M_family_m
=
1
<<
M_family
,
T_family_m
=
1
<<
T_family
,
T1_model_m
=
1
<<
T1_model
,
sparc5_instructions_m
=
1
<<
sparc5_instructions
,
aes_instructions_m
=
1
<<
aes_instructions
,
generic_v8_m
=
v8_instructions_m
|
hardware_mul32_m
|
hardware_div32_m
|
hardware_fsmuld_m
,
...
...
@@ -125,6 +127,7 @@ public:
static
bool
has_vis3
()
{
return
(
_features
&
vis3_instructions_m
)
!=
0
;
}
static
bool
has_blk_init
()
{
return
(
_features
&
blk_init_instructions_m
)
!=
0
;
}
static
bool
has_cbcond
()
{
return
(
_features
&
cbcond_instructions_m
)
!=
0
;
}
static
bool
has_sparc5_instr
()
{
return
(
_features
&
sparc5_instructions_m
)
!=
0
;
}
static
bool
has_aes
()
{
return
(
_features
&
aes_instructions_m
)
!=
0
;
}
static
bool
supports_compare_and_exchange
()
...
...
@@ -136,6 +139,7 @@ public:
static
bool
is_M_series
()
{
return
is_M_family
(
_features
);
}
static
bool
is_T4
()
{
return
is_T_family
(
_features
)
&&
has_cbcond
();
}
static
bool
is_T7
()
{
return
is_T_family
(
_features
)
&&
has_sparc5_instr
();
}
// Fujitsu SPARC64
static
bool
is_sparc64
()
{
return
(
_features
&
sparc64_family_m
)
!=
0
;
}
...
...
@@ -155,7 +159,7 @@ public:
static
const
char
*
cpu_features
()
{
return
_features_str
;
}
static
intx
prefetch_data_size
()
{
return
is_T4
()
?
32
:
64
;
// default prefetch block size on sparc
return
is_T4
()
&&
!
is_T7
()
?
32
:
64
;
// default prefetch block size on sparc
}
// Prefetch
...
...
src/os/bsd/vm/os_bsd.cpp
浏览文件 @
fdde7db6
...
...
@@ -1557,6 +1557,17 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen)
}
#endif
/* !__APPLE__ */
void
*
os
::
get_default_process_handle
()
{
#ifdef __APPLE__
// MacOS X needs to use RTLD_FIRST instead of RTLD_LAZY
// to avoid finding unexpected symbols on second (or later)
// loads of a library.
return
(
void
*
)
::
dlopen
(
NULL
,
RTLD_FIRST
);
#else
return
(
void
*
)
::
dlopen
(
NULL
,
RTLD_LAZY
);
#endif
}
// XXX: Do we need a lock around this as per Linux?
void
*
os
::
dll_lookup
(
void
*
handle
,
const
char
*
name
)
{
return
dlsym
(
handle
,
name
);
...
...
src/os/linux/vm/os_linux.cpp
浏览文件 @
fdde7db6
...
...
@@ -2109,6 +2109,9 @@ void* os::dll_lookup(void* handle, const char* name) {
return
res
;
}
void
*
os
::
get_default_process_handle
()
{
return
(
void
*
)
::
dlopen
(
NULL
,
RTLD_LAZY
);
}
static
bool
_print_ascii_file
(
const
char
*
filename
,
outputStream
*
st
)
{
int
fd
=
::
open
(
filename
,
O_RDONLY
);
...
...
src/os/posix/vm/os_posix.cpp
浏览文件 @
fdde7db6
...
...
@@ -270,10 +270,6 @@ FILE* os::open(int fd, const char* mode) {
return
::
fdopen
(
fd
,
mode
);
}
void
*
os
::
get_default_process_handle
()
{
return
(
void
*
)
::
dlopen
(
NULL
,
RTLD_LAZY
);
}
// Builds a platform dependent Agent_OnLoad_<lib_name> function name
// which is used to find statically linked in agents.
// Parameters:
...
...
src/os/solaris/vm/os_solaris.cpp
浏览文件 @
fdde7db6
...
...
@@ -2146,6 +2146,10 @@ void* os::dll_lookup(void* handle, const char* name) {
return
dlsym
(
handle
,
name
);
}
void
*
os
::
get_default_process_handle
()
{
return
(
void
*
)
::
dlopen
(
NULL
,
RTLD_LAZY
);
}
int
os
::
stat
(
const
char
*
path
,
struct
stat
*
sbuf
)
{
char
pathbuf
[
MAX_PATH
];
if
(
strlen
(
path
)
>
MAX_PATH
-
1
)
{
...
...
src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp
浏览文件 @
fdde7db6
...
...
@@ -75,13 +75,19 @@ int VM_Version::platform_features(int features) {
do_sysinfo
(
SI_ARCHITECTURE_64
,
"sparcv9"
,
&
features
,
generic_v9_m
);
// Extract valid instruction set extensions.
uint_t
av
;
uint_t
avn
=
os
::
Solaris
::
getisax
(
&
av
,
1
);
assert
(
avn
==
1
,
"should only return one av"
);
uint_t
avs
[
2
];
uint_t
avn
=
os
::
Solaris
::
getisax
(
avs
,
2
);
assert
(
avn
<=
2
,
"should return two or less av's"
);
uint_t
av
=
avs
[
0
];
#ifndef PRODUCT
if
(
PrintMiscellaneous
&&
Verbose
)
tty
->
print_cr
(
"getisax(2) returned: "
PTR32_FORMAT
,
av
);
if
(
PrintMiscellaneous
&&
Verbose
)
{
tty
->
print
(
"getisax(2) returned: "
PTR32_FORMAT
,
av
);
if
(
avn
>
1
)
{
tty
->
print
(
", "
PTR32_FORMAT
,
avs
[
1
]);
}
tty
->
cr
();
}
#endif
if
(
av
&
AV_SPARC_MUL32
)
features
|=
hardware_mul32_m
;
...
...
@@ -91,6 +97,13 @@ int VM_Version::platform_features(int features) {
if
(
av
&
AV_SPARC_POPC
)
features
|=
hardware_popc_m
;
if
(
av
&
AV_SPARC_VIS
)
features
|=
vis1_instructions_m
;
if
(
av
&
AV_SPARC_VIS2
)
features
|=
vis2_instructions_m
;
if
(
avn
>
1
)
{
uint_t
av2
=
avs
[
1
];
#ifndef AV2_SPARC_SPARC5
#define AV2_SPARC_SPARC5 0x00000008
/* The 29 new fp and sub instructions */
#endif
if
(
av2
&
AV2_SPARC_SPARC5
)
features
|=
sparc5_instructions_m
;
}
// Next values are not defined before Solaris 10
// but Solaris 8 is used for jdk6 update builds.
...
...
src/share/vm/ci/ciMethod.cpp
浏览文件 @
fdde7db6
...
...
@@ -724,6 +724,11 @@ ciMethod* ciMethod::find_monomorphic_target(ciInstanceKlass* caller,
VM_ENTRY_MARK
;
// Disable CHA for default methods for now
if
(
root_m
->
get_Method
()
->
is_default_method
())
{
return
NULL
;
}
methodHandle
target
;
{
MutexLocker
locker
(
Compile_lock
);
...
...
src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp
浏览文件 @
fdde7db6
...
...
@@ -1730,8 +1730,8 @@ CompactibleFreeListSpace::returnChunkToDictionary(FreeChunk* chunk) {
_dictionary
->
return_chunk
(
chunk
);
#ifndef PRODUCT
if
(
CMSCollector
::
abstract_state
()
!=
CMSCollector
::
Sweeping
)
{
TreeChunk
<
FreeChunk
,
AdaptiveFreeList
>*
tc
=
TreeChunk
<
FreeChunk
,
AdaptiveFreeList
>::
as_TreeChunk
(
chunk
);
TreeList
<
FreeChunk
,
AdaptiveFreeList
>*
tl
=
tc
->
list
();
TreeChunk
<
FreeChunk
,
AdaptiveFreeList
<
FreeChunk
>
>*
tc
=
TreeChunk
<
FreeChunk
,
AdaptiveFreeList
<
FreeChunk
>
>::
as_TreeChunk
(
chunk
);
TreeList
<
FreeChunk
,
AdaptiveFreeList
<
FreeChunk
>
>*
tl
=
tc
->
list
();
tl
->
verify_stats
();
}
#endif // PRODUCT
...
...
@@ -2541,10 +2541,10 @@ void CompactibleFreeListSpace::verifyIndexedFreeList(size_t size) const {
#ifndef PRODUCT
void
CompactibleFreeListSpace
::
check_free_list_consistency
()
const
{
assert
((
TreeChunk
<
FreeChunk
,
AdaptiveFreeList
>::
min_size
()
<=
IndexSetSize
),
assert
((
TreeChunk
<
FreeChunk
,
AdaptiveFreeList
<
FreeChunk
>
>::
min_size
()
<=
IndexSetSize
),
"Some sizes can't be allocated without recourse to"
" linear allocation buffers"
);
assert
((
TreeChunk
<
FreeChunk
,
AdaptiveFreeList
>::
min_size
()
*
HeapWordSize
==
sizeof
(
TreeChunk
<
FreeChunk
,
AdaptiveFreeList
>
)),
assert
((
TreeChunk
<
FreeChunk
,
AdaptiveFreeList
<
FreeChunk
>
>::
min_size
()
*
HeapWordSize
==
sizeof
(
TreeChunk
<
FreeChunk
,
AdaptiveFreeList
<
FreeChunk
>
>
)),
"else MIN_TREE_CHUNK_SIZE is wrong"
);
assert
(
IndexSetStart
!=
0
,
"IndexSetStart not initialized"
);
assert
(
IndexSetStride
!=
0
,
"IndexSetStride not initialized"
);
...
...
src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
浏览文件 @
fdde7db6
...
...
@@ -4539,7 +4539,7 @@ HeapWord* G1CollectedHeap::par_allocate_during_gc(GCAllocPurpose purpose,
G1ParGCAllocBuffer
::
G1ParGCAllocBuffer
(
size_t
gclab_word_size
)
:
ParGCAllocBuffer
(
gclab_word_size
),
_retired
(
false
)
{
}
G1ParScanThreadState
::
G1ParScanThreadState
(
G1CollectedHeap
*
g1h
,
uint
queue_num
)
G1ParScanThreadState
::
G1ParScanThreadState
(
G1CollectedHeap
*
g1h
,
uint
queue_num
,
ReferenceProcessor
*
rp
)
:
_g1h
(
g1h
),
_refs
(
g1h
->
task_queue
(
queue_num
)),
_dcq
(
&
g1h
->
dirty_card_queue_set
()),
...
...
@@ -4549,7 +4549,7 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num)
_term_attempts
(
0
),
_surviving_alloc_buffer
(
g1h
->
desired_plab_sz
(
GCAllocForSurvived
)),
_tenured_alloc_buffer
(
g1h
->
desired_plab_sz
(
GCAllocForTenured
)),
_age_table
(
false
),
_age_table
(
false
),
_scanner
(
g1h
,
this
,
rp
),
_strong_roots_time
(
0
),
_term_time
(
0
),
_alloc_buffer_waste
(
0
),
_undo_waste
(
0
)
{
// we allocate G1YoungSurvRateNumRegions plus one entries, since
...
...
@@ -4658,14 +4658,10 @@ void G1ParScanThreadState::trim_queue() {
G1ParClosureSuper
::
G1ParClosureSuper
(
G1CollectedHeap
*
g1
,
G1ParScanThreadState
*
par_scan_state
)
:
_g1
(
g1
),
_g1_rem
(
_g1
->
g1_rem_set
()),
_cm
(
_g1
->
concurrent_mark
()),
_par_scan_state
(
par_scan_state
),
_worker_id
(
par_scan_state
->
queue_num
()),
_during_initial_mark
(
_g1
->
g1_policy
()
->
during_initial_mark_pause
()),
_mark_in_progress
(
_g1
->
mark_in_progress
())
{
}
_g1
(
g1
),
_par_scan_state
(
par_scan_state
),
_worker_id
(
par_scan_state
->
queue_num
())
{
}
template
<
G1Barrier
barrier
,
bool
do_mark_object
>
void
G1ParCopyClosure
<
barrier
,
do_mark_object
>::
mark_object
(
oop
obj
)
{
void
G1ParCopyHelper
::
mark_object
(
oop
obj
)
{
#ifdef ASSERT
HeapRegion
*
hr
=
_g1
->
heap_region_containing
(
obj
);
assert
(
hr
!=
NULL
,
"sanity"
);
...
...
@@ -4676,9 +4672,7 @@ void G1ParCopyClosure<barrier, do_mark_object>::mark_object(oop obj) {
_cm
->
grayRoot
(
obj
,
(
size_t
)
obj
->
size
(),
_worker_id
);
}
template
<
G1Barrier
barrier
,
bool
do_mark_object
>
void
G1ParCopyClosure
<
barrier
,
do_mark_object
>
::
mark_forwarded_object
(
oop
from_obj
,
oop
to_obj
)
{
void
G1ParCopyHelper
::
mark_forwarded_object
(
oop
from_obj
,
oop
to_obj
)
{
#ifdef ASSERT
assert
(
from_obj
->
is_forwarded
(),
"from obj should be forwarded"
);
assert
(
from_obj
->
forwardee
()
==
to_obj
,
"to obj should be the forwardee"
);
...
...
@@ -4700,27 +4694,25 @@ void G1ParCopyClosure<barrier, do_mark_object>
_cm
->
grayRoot
(
to_obj
,
(
size_t
)
from_obj
->
size
(),
_worker_id
);
}
template
<
G1Barrier
barrier
,
bool
do_mark_object
>
oop
G1ParCopyClosure
<
barrier
,
do_mark_object
>
::
copy_to_survivor_space
(
oop
old
)
{
oop
G1ParScanThreadState
::
copy_to_survivor_space
(
oop
const
old
)
{
size_t
word_sz
=
old
->
size
();
HeapRegion
*
from_region
=
_g1
->
heap_region_containing_raw
(
old
);
HeapRegion
*
from_region
=
_g1
h
->
heap_region_containing_raw
(
old
);
// +1 to make the -1 indexes valid...
int
young_index
=
from_region
->
young_index_in_cset
()
+
1
;
assert
(
(
from_region
->
is_young
()
&&
young_index
>
0
)
||
(
!
from_region
->
is_young
()
&&
young_index
==
0
),
"invariant"
);
G1CollectorPolicy
*
g1p
=
_g1
->
g1_policy
();
G1CollectorPolicy
*
g1p
=
_g1
h
->
g1_policy
();
markOop
m
=
old
->
mark
();
int
age
=
m
->
has_displaced_mark_helper
()
?
m
->
displaced_mark_helper
()
->
age
()
:
m
->
age
();
GCAllocPurpose
alloc_purpose
=
g1p
->
evacuation_destination
(
from_region
,
age
,
word_sz
);
HeapWord
*
obj_ptr
=
_par_scan_state
->
allocate
(
alloc_purpose
,
word_sz
);
HeapWord
*
obj_ptr
=
allocate
(
alloc_purpose
,
word_sz
);
#ifndef PRODUCT
// Should this evacuation fail?
if
(
_g1
->
evacuation_should_fail
())
{
if
(
_g1
h
->
evacuation_should_fail
())
{
if
(
obj_ptr
!=
NULL
)
{
_par_scan_state
->
undo_allocation
(
alloc_purpose
,
obj_ptr
,
word_sz
);
undo_allocation
(
alloc_purpose
,
obj_ptr
,
word_sz
);
obj_ptr
=
NULL
;
}
}
...
...
@@ -4729,7 +4721,7 @@ oop G1ParCopyClosure<barrier, do_mark_object>
if
(
obj_ptr
==
NULL
)
{
// This will either forward-to-self, or detect that someone else has
// installed a forwarding pointer.
return
_g1
->
handle_evacuation_failure_par
(
_par_scan_state
,
old
);
return
_g1
h
->
handle_evacuation_failure_par
(
this
,
old
);
}
oop
obj
=
oop
(
obj_ptr
);
...
...
@@ -4762,12 +4754,12 @@ oop G1ParCopyClosure<barrier, do_mark_object>
m
=
m
->
incr_age
();
obj
->
set_mark
(
m
);
}
_par_scan_state
->
age_table
()
->
add
(
obj
,
word_sz
);
age_table
()
->
add
(
obj
,
word_sz
);
}
else
{
obj
->
set_mark
(
m
);
}
size_t
*
surv_young_words
=
_par_scan_state
->
surviving_young_words
();
size_t
*
surv_young_words
=
surviving_young_words
();
surv_young_words
[
young_index
]
+=
word_sz
;
if
(
obj
->
is_objArray
()
&&
arrayOop
(
obj
)
->
length
()
>=
ParGCArrayScanChunk
)
{
...
...
@@ -4776,15 +4768,15 @@ oop G1ParCopyClosure<barrier, do_mark_object>
// length field of the from-space object.
arrayOop
(
obj
)
->
set_length
(
0
);
oop
*
old_p
=
set_partial_array_mask
(
old
);
_par_scan_state
->
push_on_queue
(
old_p
);
push_on_queue
(
old_p
);
}
else
{
// No point in using the slower heap_region_containing() method,
// given that we know obj is in the heap.
_scanner
.
set_region
(
_g1
->
heap_region_containing_raw
(
obj
));
_scanner
.
set_region
(
_g1
h
->
heap_region_containing_raw
(
obj
));
obj
->
oop_iterate_backwards
(
&
_scanner
);
}
}
else
{
_par_scan_state
->
undo_allocation
(
alloc_purpose
,
obj_ptr
,
word_sz
);
undo_allocation
(
alloc_purpose
,
obj_ptr
,
word_sz
);
obj
=
forward_ptr
;
}
return
obj
;
...
...
@@ -4799,19 +4791,23 @@ void G1ParCopyHelper::do_klass_barrier(T* p, oop new_obj) {
template
<
G1Barrier
barrier
,
bool
do_mark_object
>
template
<
class
T
>
void
G1ParCopyClosure
<
barrier
,
do_mark_object
>
::
do_oop_work
(
T
*
p
)
{
oop
obj
=
oopDesc
::
load_decode_heap_oop
(
p
);
void
G1ParCopyClosure
<
barrier
,
do_mark_object
>::
do_oop_work
(
T
*
p
)
{
T
heap_oop
=
oopDesc
::
load_heap_oop
(
p
);
if
(
oopDesc
::
is_null
(
heap_oop
))
{
return
;
}
oop
obj
=
oopDesc
::
decode_heap_oop_not_null
(
heap_oop
);
assert
(
_worker_id
==
_par_scan_state
->
queue_num
(),
"sanity"
);
// here the null check is implicit in the cset_fast_test() test
if
(
_g1
->
in_cset_fast_test
(
obj
))
{
oop
forwardee
;
if
(
obj
->
is_forwarded
())
{
forwardee
=
obj
->
forwardee
();
}
else
{
forwardee
=
copy_to_survivor_space
(
obj
);
forwardee
=
_par_scan_state
->
copy_to_survivor_space
(
obj
);
}
assert
(
forwardee
!=
NULL
,
"forwardee should not be NULL"
);
oopDesc
::
encode_store_heap_oop
(
p
,
forwardee
);
...
...
@@ -4828,12 +4824,12 @@ void G1ParCopyClosure<barrier, do_mark_object>
// The object is not in collection set. If we're a root scanning
// closure during an initial mark pause (i.e. do_mark_object will
// be true) then attempt to mark the object.
if
(
do_mark_object
&&
_g1
->
is_in_g1_reserved
(
obj
)
)
{
if
(
do_mark_object
)
{
mark_object
(
obj
);
}
}
if
(
barrier
==
G1BarrierEvac
&&
obj
!=
NULL
)
{
if
(
barrier
==
G1BarrierEvac
)
{
_par_scan_state
->
update_rs
(
_from
,
p
,
_worker_id
);
}
}
...
...
@@ -5030,7 +5026,7 @@ public:
ReferenceProcessor
*
rp
=
_g1h
->
ref_processor_stw
();
G1ParScanThreadState
pss
(
_g1h
,
worker_id
);
G1ParScanThreadState
pss
(
_g1h
,
worker_id
,
rp
);
G1ParScanHeapEvacClosure
scan_evac_cl
(
_g1h
,
&
pss
,
rp
);
G1ParScanHeapEvacFailureClosure
evac_failure_cl
(
_g1h
,
&
pss
,
rp
);
G1ParScanPartialArrayClosure
partial_scan_cl
(
_g1h
,
&
pss
,
rp
);
...
...
@@ -5473,7 +5469,7 @@ public:
G1STWIsAliveClosure
is_alive
(
_g1h
);
G1ParScanThreadState
pss
(
_g1h
,
worker_id
);
G1ParScanThreadState
pss
(
_g1h
,
worker_id
,
NULL
);
G1ParScanHeapEvacClosure
scan_evac_cl
(
_g1h
,
&
pss
,
NULL
);
G1ParScanHeapEvacFailureClosure
evac_failure_cl
(
_g1h
,
&
pss
,
NULL
);
...
...
@@ -5585,7 +5581,7 @@ public:
ResourceMark
rm
;
HandleMark
hm
;
G1ParScanThreadState
pss
(
_g1h
,
worker_id
);
G1ParScanThreadState
pss
(
_g1h
,
worker_id
,
NULL
);
G1ParScanHeapEvacClosure
scan_evac_cl
(
_g1h
,
&
pss
,
NULL
);
G1ParScanHeapEvacFailureClosure
evac_failure_cl
(
_g1h
,
&
pss
,
NULL
);
G1ParScanPartialArrayClosure
partial_scan_cl
(
_g1h
,
&
pss
,
NULL
);
...
...
@@ -5711,7 +5707,7 @@ void G1CollectedHeap::process_discovered_references(uint no_of_gc_workers) {
// JNI refs.
// Use only a single queue for this PSS.
G1ParScanThreadState
pss
(
this
,
0
);
G1ParScanThreadState
pss
(
this
,
0
,
NULL
);
// We do not embed a reference processor in the copying/scanning
// closures while we're actually processing the discovered
...
...
src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp
浏览文件 @
fdde7db6
...
...
@@ -606,6 +606,11 @@ protected:
// may not be a humongous - it must fit into a single heap region.
HeapWord
*
par_allocate_during_gc
(
GCAllocPurpose
purpose
,
size_t
word_size
);
HeapWord
*
allocate_during_gc_slow
(
GCAllocPurpose
purpose
,
HeapRegion
*
alloc_region
,
bool
par
,
size_t
word_size
);
// Ensure that no further allocations can happen in "r", bearing in mind
// that parallel threads might be attempting allocations.
void
par_allocate_remaining_space
(
HeapRegion
*
r
);
...
...
@@ -698,23 +703,20 @@ public:
}
// This is a fast test on whether a reference points into the
// collection set or not.
It does not a
ssume that the reference
// points into the heap
; if it doesn't, it will return false
.
// collection set or not.
A
ssume that the reference
// points into the heap.
bool
in_cset_fast_test
(
oop
obj
)
{
assert
(
_in_cset_fast_test
!=
NULL
,
"sanity"
);
if
(
_g1_committed
.
contains
((
HeapWord
*
)
obj
))
{
// no need to subtract the bottom of the heap from obj,
// _in_cset_fast_test is biased
uintx
index
=
cast_from_oop
<
uintx
>
(
obj
)
>>
HeapRegion
::
LogOfHRGrainBytes
;
bool
ret
=
_in_cset_fast_test
[
index
];
// let's make sure the result is consistent with what the slower
// test returns
assert
(
ret
||
!
obj_in_cs
(
obj
),
"sanity"
);
assert
(
!
ret
||
obj_in_cs
(
obj
),
"sanity"
);
return
ret
;
}
else
{
return
false
;
}
assert
(
_g1_committed
.
contains
((
HeapWord
*
)
obj
),
err_msg
(
"Given reference outside of heap, is "
PTR_FORMAT
,
(
HeapWord
*
)
obj
));
// no need to subtract the bottom of the heap from obj,
// _in_cset_fast_test is biased
uintx
index
=
cast_from_oop
<
uintx
>
(
obj
)
>>
HeapRegion
::
LogOfHRGrainBytes
;
bool
ret
=
_in_cset_fast_test
[
index
];
// let's make sure the result is consistent with what the slower
// test returns
assert
(
ret
||
!
obj_in_cs
(
obj
),
"sanity"
);
assert
(
!
ret
||
obj_in_cs
(
obj
),
"sanity"
);
return
ret
;
}
void
clear_cset_fast_test
()
{
...
...
@@ -1786,95 +1788,6 @@ public:
ParGCAllocBuffer
::
retire
(
end_of_gc
,
retain
);
_retired
=
true
;
}
bool
is_retired
()
{
return
_retired
;
}
};
class
G1ParGCAllocBufferContainer
{
protected:
static
int
const
_priority_max
=
2
;
G1ParGCAllocBuffer
*
_priority_buffer
[
_priority_max
];
public:
G1ParGCAllocBufferContainer
(
size_t
gclab_word_size
)
{
for
(
int
pr
=
0
;
pr
<
_priority_max
;
++
pr
)
{
_priority_buffer
[
pr
]
=
new
G1ParGCAllocBuffer
(
gclab_word_size
);
}
}
~
G1ParGCAllocBufferContainer
()
{
for
(
int
pr
=
0
;
pr
<
_priority_max
;
++
pr
)
{
assert
(
_priority_buffer
[
pr
]
->
is_retired
(),
"alloc buffers should all retire at this point."
);
delete
_priority_buffer
[
pr
];
}
}
HeapWord
*
allocate
(
size_t
word_sz
)
{
HeapWord
*
obj
;
for
(
int
pr
=
0
;
pr
<
_priority_max
;
++
pr
)
{
obj
=
_priority_buffer
[
pr
]
->
allocate
(
word_sz
);
if
(
obj
!=
NULL
)
return
obj
;
}
return
obj
;
}
bool
contains
(
void
*
addr
)
{
for
(
int
pr
=
0
;
pr
<
_priority_max
;
++
pr
)
{
if
(
_priority_buffer
[
pr
]
->
contains
(
addr
))
return
true
;
}
return
false
;
}
void
undo_allocation
(
HeapWord
*
obj
,
size_t
word_sz
)
{
bool
finish_undo
;
for
(
int
pr
=
0
;
pr
<
_priority_max
;
++
pr
)
{
if
(
_priority_buffer
[
pr
]
->
contains
(
obj
))
{
_priority_buffer
[
pr
]
->
undo_allocation
(
obj
,
word_sz
);
finish_undo
=
true
;
}
}
if
(
!
finish_undo
)
ShouldNotReachHere
();
}
size_t
words_remaining
()
{
size_t
result
=
0
;
for
(
int
pr
=
0
;
pr
<
_priority_max
;
++
pr
)
{
result
+=
_priority_buffer
[
pr
]
->
words_remaining
();
}
return
result
;
}
size_t
words_remaining_in_retired_buffer
()
{
G1ParGCAllocBuffer
*
retired
=
_priority_buffer
[
0
];
return
retired
->
words_remaining
();
}
void
flush_stats_and_retire
(
PLABStats
*
stats
,
bool
end_of_gc
,
bool
retain
)
{
for
(
int
pr
=
0
;
pr
<
_priority_max
;
++
pr
)
{
_priority_buffer
[
pr
]
->
flush_stats_and_retire
(
stats
,
end_of_gc
,
retain
);
}
}
void
update
(
bool
end_of_gc
,
bool
retain
,
HeapWord
*
buf
,
size_t
word_sz
)
{
G1ParGCAllocBuffer
*
retired_and_set
=
_priority_buffer
[
0
];
retired_and_set
->
retire
(
end_of_gc
,
retain
);
retired_and_set
->
set_buf
(
buf
);
retired_and_set
->
set_word_size
(
word_sz
);
adjust_priority_order
();
}
private:
void
adjust_priority_order
()
{
G1ParGCAllocBuffer
*
retired_and_set
=
_priority_buffer
[
0
];
int
last
=
_priority_max
-
1
;
for
(
int
pr
=
0
;
pr
<
last
;
++
pr
)
{
_priority_buffer
[
pr
]
=
_priority_buffer
[
pr
+
1
];
}
_priority_buffer
[
last
]
=
retired_and_set
;
}
};
class
G1ParScanThreadState
:
public
StackObj
{
...
...
@@ -1885,11 +1798,13 @@ protected:
G1SATBCardTableModRefBS
*
_ct_bs
;
G1RemSet
*
_g1_rem
;
G1ParGCAllocBuffer
Container
_surviving_alloc_buffer
;
G1ParGCAllocBuffer
Container
_tenured_alloc_buffer
;
G1ParGCAllocBuffer
Container
*
_alloc_buffers
[
GCAllocPurposeCount
];
G1ParGCAllocBuffer
_surviving_alloc_buffer
;
G1ParGCAllocBuffer
_tenured_alloc_buffer
;
G1ParGCAllocBuffer
*
_alloc_buffers
[
GCAllocPurposeCount
];
ageTable
_age_table
;
G1ParScanClosure
_scanner
;
size_t
_alloc_buffer_waste
;
size_t
_undo_waste
;
...
...
@@ -1942,7 +1857,7 @@ protected:
}
public:
G1ParScanThreadState
(
G1CollectedHeap
*
g1h
,
uint
queue_num
);
G1ParScanThreadState
(
G1CollectedHeap
*
g1h
,
uint
queue_num
,
ReferenceProcessor
*
rp
);
~
G1ParScanThreadState
()
{
FREE_C_HEAP_ARRAY
(
size_t
,
_surviving_young_words_base
,
mtGC
);
...
...
@@ -1951,7 +1866,7 @@ public:
RefToScanQueue
*
refs
()
{
return
_refs
;
}
ageTable
*
age_table
()
{
return
&
_age_table
;
}
G1ParGCAllocBuffer
Container
*
alloc_buffer
(
GCAllocPurpose
purpose
)
{
G1ParGCAllocBuffer
*
alloc_buffer
(
GCAllocPurpose
purpose
)
{
return
_alloc_buffers
[
purpose
];
}
...
...
@@ -1981,13 +1896,15 @@ public:
HeapWord
*
obj
=
NULL
;
size_t
gclab_word_size
=
_g1h
->
desired_plab_sz
(
purpose
);
if
(
word_sz
*
100
<
gclab_word_size
*
ParallelGCBufferWastePct
)
{
G1ParGCAllocBufferContainer
*
alloc_buf
=
alloc_buffer
(
purpose
);
G1ParGCAllocBuffer
*
alloc_buf
=
alloc_buffer
(
purpose
);
add_to_alloc_buffer_waste
(
alloc_buf
->
words_remaining
());
alloc_buf
->
retire
(
false
/* end_of_gc */
,
false
/* retain */
);
HeapWord
*
buf
=
_g1h
->
par_allocate_during_gc
(
purpose
,
gclab_word_size
);
if
(
buf
==
NULL
)
return
NULL
;
// Let caller handle allocation failure.
a
dd_to_alloc_buffer_waste
(
alloc_buf
->
words_remaining_in_retired_buffer
()
);
alloc_buf
->
update
(
false
/* end_of_gc */
,
false
/* retain */
,
buf
,
gclab_word_size
);
// Otherwise.
a
lloc_buf
->
set_word_size
(
gclab_word_size
);
alloc_buf
->
set_buf
(
buf
);
obj
=
alloc_buf
->
allocate
(
word_sz
);
assert
(
obj
!=
NULL
,
"buffer was definitely big enough..."
);
...
...
@@ -2077,6 +1994,8 @@ public:
}
}
oop
copy_to_survivor_space
(
oop
const
obj
);
template
<
class
T
>
void
deal_with_reference
(
T
*
ref_to_scan
)
{
if
(
has_partial_array_mask
(
ref_to_scan
))
{
_partial_scan_cl
->
do_oop_nv
(
ref_to_scan
);
...
...
@@ -2099,6 +2018,7 @@ public:
}
}
public:
void
trim_queue
();
};
...
...
src/share/vm/gc_implementation/g1/g1OopClosures.cpp
0 → 100644
浏览文件 @
fdde7db6
/*
* 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/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1OopClosures.inline.hpp"
G1ParCopyHelper
::
G1ParCopyHelper
(
G1CollectedHeap
*
g1
,
G1ParScanThreadState
*
par_scan_state
)
:
G1ParClosureSuper
(
g1
,
par_scan_state
),
_scanned_klass
(
NULL
),
_cm
(
_g1
->
concurrent_mark
())
{}
src/share/vm/gc_implementation/g1/g1OopClosures.hpp
浏览文件 @
fdde7db6
...
...
@@ -48,12 +48,8 @@ public:
class
G1ParClosureSuper
:
public
OopsInHeapRegionClosure
{
protected:
G1CollectedHeap
*
_g1
;
G1RemSet
*
_g1_rem
;
ConcurrentMark
*
_cm
;
G1ParScanThreadState
*
_par_scan_state
;
uint
_worker_id
;
bool
_during_initial_mark
;
bool
_mark_in_progress
;
public:
G1ParClosureSuper
(
G1CollectedHeap
*
g1
,
G1ParScanThreadState
*
par_scan_state
);
bool
apply_to_weak_ref_discovered_field
()
{
return
true
;
}
...
...
@@ -133,23 +129,10 @@ public:
// Add back base class for metadata
class
G1ParCopyHelper
:
public
G1ParClosureSuper
{
protected:
Klass
*
_scanned_klass
;
ConcurrentMark
*
_cm
;
public:
G1ParCopyHelper
(
G1CollectedHeap
*
g1
,
G1ParScanThreadState
*
par_scan_state
)
:
_scanned_klass
(
NULL
),
G1ParClosureSuper
(
g1
,
par_scan_state
)
{}
void
set_scanned_klass
(
Klass
*
k
)
{
_scanned_klass
=
k
;
}
template
<
class
T
>
void
do_klass_barrier
(
T
*
p
,
oop
new_obj
);
};
template
<
G1Barrier
barrier
,
bool
do_mark_object
>
class
G1ParCopyClosure
:
public
G1ParCopyHelper
{
G1ParScanClosure
_scanner
;
template
<
class
T
>
void
do_oop_work
(
T
*
p
);
protected:
// Mark the object if it's not already marked. This is used to mark
// objects pointed to by roots that are guaranteed not to move
// during the GC (i.e., non-CSet objects). It is MT-safe.
...
...
@@ -159,22 +142,26 @@ protected:
// objects pointed to by roots that have been forwarded during a
// GC. It is MT-safe.
void
mark_forwarded_object
(
oop
from_obj
,
oop
to_obj
);
public:
G1ParCopyHelper
(
G1CollectedHeap
*
g1
,
G1ParScanThreadState
*
par_scan_state
);
oop
copy_to_survivor_space
(
oop
obj
);
void
set_scanned_klass
(
Klass
*
k
)
{
_scanned_klass
=
k
;
}
template
<
class
T
>
void
do_klass_barrier
(
T
*
p
,
oop
new_obj
);
};
template
<
G1Barrier
barrier
,
bool
do_mark_object
>
class
G1ParCopyClosure
:
public
G1ParCopyHelper
{
private:
template
<
class
T
>
void
do_oop_work
(
T
*
p
);
public:
G1ParCopyClosure
(
G1CollectedHeap
*
g1
,
G1ParScanThreadState
*
par_scan_state
,
ReferenceProcessor
*
rp
)
:
_scanner
(
g1
,
par_scan_state
,
rp
),
G1ParCopyHelper
(
g1
,
par_scan_state
)
{
assert
(
_ref_processor
==
NULL
,
"sanity"
);
}
G1ParScanClosure
*
scanner
()
{
return
&
_scanner
;
}
template
<
class
T
>
void
do_oop_nv
(
T
*
p
)
{
do_oop_work
(
p
);
}
template
<
class
T
>
void
do_oop_nv
(
T
*
p
)
{
do_oop_work
(
p
);
}
virtual
void
do_oop
(
oop
*
p
)
{
do_oop_nv
(
p
);
}
virtual
void
do_oop
(
narrowOop
*
p
)
{
do_oop_nv
(
p
);
}
};
...
...
src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp
浏览文件 @
fdde7db6
...
...
@@ -83,7 +83,7 @@ inline void G1ParScanClosure::do_oop_nv(T* p) {
_par_scan_state
->
push_on_queue
(
p
);
}
else
{
_par_scan_state
->
update_rs
(
_from
,
p
,
_
par_scan_state
->
queue_num
()
);
_par_scan_state
->
update_rs
(
_from
,
p
,
_
worker_id
);
}
}
}
...
...
src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp
浏览文件 @
fdde7db6
...
...
@@ -158,7 +158,7 @@ public:
// Fills in the unallocated portion of the buffer with a garbage object.
// If "end_of_gc" is TRUE, is after the last use in the GC. IF "retain"
// is true, attempt to re-use the unused portion in the next GC.
v
irtual
v
oid
retire
(
bool
end_of_gc
,
bool
retain
);
void
retire
(
bool
end_of_gc
,
bool
retain
);
void
print
()
PRODUCT_RETURN
;
};
...
...
src/share/vm/memory/binaryTreeDictionary.cpp
浏览文件 @
fdde7db6
此差异已折叠。
点击以展开。
src/share/vm/memory/binaryTreeDictionary.hpp
浏览文件 @
fdde7db6
...
...
@@ -37,18 +37,18 @@
// A TreeList is a FreeList which can be used to maintain a
// binary tree of free lists.
template
<
class
Chunk_t
,
template
<
class
>
class
FreeList_t
>
class
TreeChunk
;
template
<
class
Chunk_t
,
template
<
class
>
class
FreeList_t
>
class
BinaryTreeDictionary
;
template
<
class
Chunk_t
,
template
<
class
>
class
FreeList_t
>
class
AscendTreeCensusClosure
;
template
<
class
Chunk_t
,
template
<
class
>
class
FreeList_t
>
class
DescendTreeCensusClosure
;
template
<
class
Chunk_t
,
template
<
class
>
class
FreeList_t
>
class
DescendTreeSearchClosure
;
template
<
class
Chunk_t
,
class
FreeList_t
>
class
TreeChunk
;
template
<
class
Chunk_t
,
class
FreeList_t
>
class
BinaryTreeDictionary
;
template
<
class
Chunk_t
,
class
FreeList_t
>
class
AscendTreeCensusClosure
;
template
<
class
Chunk_t
,
class
FreeList_t
>
class
DescendTreeCensusClosure
;
template
<
class
Chunk_t
,
class
FreeList_t
>
class
DescendTreeSearchClosure
;
class
FreeChunk
;
template
<
class
>
class
AdaptiveFreeList
;
typedef
BinaryTreeDictionary
<
FreeChunk
,
AdaptiveFreeList
>
AFLBinaryTreeDictionary
;
typedef
BinaryTreeDictionary
<
FreeChunk
,
AdaptiveFreeList
<
FreeChunk
>
>
AFLBinaryTreeDictionary
;
template
<
class
Chunk_t
,
template
<
class
>
class
FreeList_t
>
class
TreeList
:
public
FreeList_t
<
Chunk_t
>
{
template
<
class
Chunk_t
,
class
FreeList_t
>
class
TreeList
:
public
FreeList_t
{
friend
class
TreeChunk
<
Chunk_t
,
FreeList_t
>
;
friend
class
BinaryTreeDictionary
<
Chunk_t
,
FreeList_t
>
;
friend
class
AscendTreeCensusClosure
<
Chunk_t
,
FreeList_t
>
;
...
...
@@ -66,12 +66,12 @@ class TreeList : public FreeList_t<Chunk_t> {
TreeList
<
Chunk_t
,
FreeList_t
>*
right
()
const
{
return
_right
;
}
// Wrapper on call to base class, to get the template to compile.
Chunk_t
*
head
()
const
{
return
FreeList_t
<
Chunk_t
>
::
head
();
}
Chunk_t
*
tail
()
const
{
return
FreeList_t
<
Chunk_t
>
::
tail
();
}
void
set_head
(
Chunk_t
*
head
)
{
FreeList_t
<
Chunk_t
>
::
set_head
(
head
);
}
void
set_tail
(
Chunk_t
*
tail
)
{
FreeList_t
<
Chunk_t
>
::
set_tail
(
tail
);
}
Chunk_t
*
head
()
const
{
return
FreeList_t
::
head
();
}
Chunk_t
*
tail
()
const
{
return
FreeList_t
::
tail
();
}
void
set_head
(
Chunk_t
*
head
)
{
FreeList_t
::
set_head
(
head
);
}
void
set_tail
(
Chunk_t
*
tail
)
{
FreeList_t
::
set_tail
(
tail
);
}
size_t
size
()
const
{
return
FreeList_t
<
Chunk_t
>
::
size
();
}
size_t
size
()
const
{
return
FreeList_t
::
size
();
}
// Accessors for links in tree.
...
...
@@ -90,7 +90,7 @@ class TreeList : public FreeList_t<Chunk_t> {
void
clear_left
()
{
_left
=
NULL
;
}
void
clear_right
()
{
_right
=
NULL
;
}
void
clear_parent
()
{
_parent
=
NULL
;
}
void
initialize
()
{
clear_left
();
clear_right
(),
clear_parent
();
FreeList_t
<
Chunk_t
>
::
initialize
();
}
void
initialize
()
{
clear_left
();
clear_right
(),
clear_parent
();
FreeList_t
::
initialize
();
}
// For constructing a TreeList from a Tree chunk or
// address and size.
...
...
@@ -139,7 +139,7 @@ class TreeList : public FreeList_t<Chunk_t> {
// on the free list for a node in the tree and is only removed if
// it is the last chunk on the free list.
template
<
class
Chunk_t
,
template
<
class
>
class
FreeList_t
>
template
<
class
Chunk_t
,
class
FreeList_t
>
class
TreeChunk
:
public
Chunk_t
{
friend
class
TreeList
<
Chunk_t
,
FreeList_t
>
;
TreeList
<
Chunk_t
,
FreeList_t
>*
_list
;
...
...
@@ -173,7 +173,7 @@ class TreeChunk : public Chunk_t {
};
template
<
class
Chunk_t
,
template
<
class
>
class
FreeList_t
>
template
<
class
Chunk_t
,
class
FreeList_t
>
class
BinaryTreeDictionary
:
public
FreeBlockDictionary
<
Chunk_t
>
{
friend
class
VMStructs
;
size_t
_total_size
;
...
...
src/share/vm/memory/metaspace.cpp
浏览文件 @
fdde7db6
...
...
@@ -46,8 +46,8 @@
#include "utilities/copy.hpp"
#include "utilities/debug.hpp"
typedef
BinaryTreeDictionary
<
Metablock
,
FreeList
>
BlockTreeDictionary
;
typedef
BinaryTreeDictionary
<
Metachunk
,
FreeList
>
ChunkTreeDictionary
;
typedef
BinaryTreeDictionary
<
Metablock
,
FreeList
<
Metablock
>
>
BlockTreeDictionary
;
typedef
BinaryTreeDictionary
<
Metachunk
,
FreeList
<
Metachunk
>
>
ChunkTreeDictionary
;
// Set this constant to enable slow integrity checking of the free chunk lists
const
bool
metaspace_slow_verify
=
false
;
...
...
@@ -790,7 +790,7 @@ MetaWord* BlockFreelist::get_block(size_t word_size) {
return
NULL
;
}
if
(
word_size
<
TreeChunk
<
Metablock
,
FreeList
>::
min_size
())
{
if
(
word_size
<
TreeChunk
<
Metablock
,
FreeList
<
Metablock
>
>::
min_size
())
{
// Dark matter. Too small for dictionary.
return
NULL
;
}
...
...
@@ -810,7 +810,7 @@ MetaWord* BlockFreelist::get_block(size_t word_size) {
MetaWord
*
new_block
=
(
MetaWord
*
)
free_block
;
assert
(
block_size
>=
word_size
,
"Incorrect size of block from freelist"
);
const
size_t
unused
=
block_size
-
word_size
;
if
(
unused
>=
TreeChunk
<
Metablock
,
FreeList
>::
min_size
())
{
if
(
unused
>=
TreeChunk
<
Metablock
,
FreeList
<
Metablock
>
>::
min_size
())
{
return_block
(
new_block
+
word_size
,
unused
);
}
...
...
@@ -2239,7 +2239,7 @@ ChunkIndex ChunkManager::list_index(size_t size) {
void
SpaceManager
::
deallocate
(
MetaWord
*
p
,
size_t
word_size
)
{
assert_lock_strong
(
_lock
);
size_t
raw_word_size
=
get_raw_word_size
(
word_size
);
size_t
min_size
=
TreeChunk
<
Metablock
,
FreeList
>::
min_size
();
size_t
min_size
=
TreeChunk
<
Metablock
,
FreeList
<
Metablock
>
>::
min_size
();
assert
(
raw_word_size
>=
min_size
,
err_msg
(
"Should not deallocate dark matter "
SIZE_FORMAT
"<"
SIZE_FORMAT
,
word_size
,
min_size
));
block_freelists
()
->
return_block
(
p
,
raw_word_size
);
...
...
@@ -2295,7 +2295,7 @@ void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) {
void
SpaceManager
::
retire_current_chunk
()
{
if
(
current_chunk
()
!=
NULL
)
{
size_t
remaining_words
=
current_chunk
()
->
free_word_size
();
if
(
remaining_words
>=
TreeChunk
<
Metablock
,
FreeList
>::
min_size
())
{
if
(
remaining_words
>=
TreeChunk
<
Metablock
,
FreeList
<
Metablock
>
>::
min_size
())
{
block_freelists
()
->
return_block
(
current_chunk
()
->
allocate
(
remaining_words
),
remaining_words
);
inc_used_metrics
(
remaining_words
);
}
...
...
@@ -3278,7 +3278,7 @@ void Metaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) {
assert
(
Thread
::
current
()
->
is_VM_thread
(),
"should be the VM thread"
);
// Don't take Heap_lock
MutexLockerEx
ml
(
vsm
()
->
lock
(),
Mutex
::
_no_safepoint_check_flag
);
if
(
word_size
<
TreeChunk
<
Metablock
,
FreeList
>::
min_size
())
{
if
(
word_size
<
TreeChunk
<
Metablock
,
FreeList
<
Metablock
>
>::
min_size
())
{
// Dark matter. Too small for dictionary.
#ifdef ASSERT
Copy
::
fill_to_words
((
HeapWord
*
)
ptr
,
word_size
,
0xf5f5f5f5
);
...
...
@@ -3293,7 +3293,7 @@ void Metaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) {
}
else
{
MutexLockerEx
ml
(
vsm
()
->
lock
(),
Mutex
::
_no_safepoint_check_flag
);
if
(
word_size
<
TreeChunk
<
Metablock
,
FreeList
>::
min_size
())
{
if
(
word_size
<
TreeChunk
<
Metablock
,
FreeList
<
Metablock
>
>::
min_size
())
{
// Dark matter. Too small for dictionary.
#ifdef ASSERT
Copy
::
fill_to_words
((
HeapWord
*
)
ptr
,
word_size
,
0xf5f5f5f5
);
...
...
src/share/vm/oops/constantPool.cpp
浏览文件 @
fdde7db6
...
...
@@ -1295,6 +1295,7 @@ void ConstantPool::copy_entry_to(constantPoolHandle from_cp, int from_i,
}
break
;
case
JVM_CONSTANT_UnresolvedClass
:
case
JVM_CONSTANT_UnresolvedClassInError
:
{
// Can be resolved after checking tag, so check the slot first.
CPSlot
entry
=
from_cp
->
slot_at
(
from_i
);
...
...
src/share/vm/opto/c2_globals.hpp
浏览文件 @
fdde7db6
...
...
@@ -357,6 +357,9 @@
"File to dump ideal graph to. If set overrides the " \
"use of the network") \
\
product(bool, UseOldInlining, true, \
"Enable the 1.3 inlining strategy") \
\
product(bool, UseBimorphicInlining, true, \
"Profiling based inlining for two receivers") \
\
...
...
src/share/vm/opto/output.cpp
浏览文件 @
fdde7db6
...
...
@@ -344,6 +344,11 @@ void Compile::shorten_branches(uint* blk_starts, int& code_size, int& reloc_size
uint
*
jmp_offset
=
NEW_RESOURCE_ARRAY
(
uint
,
nblocks
);
uint
*
jmp_size
=
NEW_RESOURCE_ARRAY
(
uint
,
nblocks
);
int
*
jmp_nidx
=
NEW_RESOURCE_ARRAY
(
int
,
nblocks
);
// Collect worst case block paddings
int
*
block_worst_case_pad
=
NEW_RESOURCE_ARRAY
(
int
,
nblocks
);
memset
(
block_worst_case_pad
,
0
,
nblocks
*
sizeof
(
int
));
DEBUG_ONLY
(
uint
*
jmp_target
=
NEW_RESOURCE_ARRAY
(
uint
,
nblocks
);
)
DEBUG_ONLY
(
uint
*
jmp_rule
=
NEW_RESOURCE_ARRAY
(
uint
,
nblocks
);
)
...
...
@@ -460,6 +465,7 @@ void Compile::shorten_branches(uint* blk_starts, int& code_size, int& reloc_size
last_avoid_back_to_back_adr
+=
max_loop_pad
;
}
blk_size
+=
max_loop_pad
;
block_worst_case_pad
[
i
+
1
]
=
max_loop_pad
;
}
}
...
...
@@ -499,9 +505,16 @@ void Compile::shorten_branches(uint* blk_starts, int& code_size, int& reloc_size
if
(
bnum
>
i
)
{
// adjust following block's offset
offset
-=
adjust_block_start
;
}
// This block can be a loop header, account for the padding
// in the previous block.
int
block_padding
=
block_worst_case_pad
[
i
];
assert
(
i
==
0
||
block_padding
==
0
||
br_offs
>=
block_padding
,
"Should have at least a padding on top"
);
// In the following code a nop could be inserted before
// the branch which will increase the backward distance.
bool
needs_padding
=
((
uint
)
br_offs
==
last_may_be_short_branch_adr
);
bool
needs_padding
=
((
uint
)(
br_offs
-
block_padding
)
==
last_may_be_short_branch_adr
);
assert
(
!
needs_padding
||
jmp_offset
[
i
]
==
0
,
"padding only branches at the beginning of block"
);
if
(
needs_padding
&&
offset
<=
0
)
offset
-=
nop_size
;
...
...
src/share/vm/prims/jni.cpp
浏览文件 @
fdde7db6
...
...
@@ -1356,9 +1356,13 @@ static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receive
// interface call
KlassHandle
h_holder
(
THREAD
,
holder
);
int
itbl_index
=
m
->
itable_index
();
Klass
*
k
=
h_recv
->
klass
();
selected_method
=
InstanceKlass
::
cast
(
k
)
->
method_at_itable
(
h_holder
(),
itbl_index
,
CHECK
);
if
(
call_type
==
JNI_VIRTUAL
)
{
int
itbl_index
=
m
->
itable_index
();
Klass
*
k
=
h_recv
->
klass
();
selected_method
=
InstanceKlass
::
cast
(
k
)
->
method_at_itable
(
h_holder
(),
itbl_index
,
CHECK
);
}
else
{
selected_method
=
m
;
}
}
}
...
...
@@ -5061,8 +5065,8 @@ void TestVirtualSpace_test();
void
TestMetaspaceAux_test
();
void
TestMetachunk_test
();
void
TestVirtualSpaceNode_test
();
void
TestOldFreeSpaceCalculation_test
();
#if INCLUDE_ALL_GCS
void
TestOldFreeSpaceCalculation_test
();
void
TestG1BiasedArray_test
();
#endif
...
...
@@ -5082,11 +5086,11 @@ void execute_internal_vm_tests() {
run_unit_test
(
QuickSort
::
test_quick_sort
());
run_unit_test
(
AltHashing
::
test_alt_hash
());
run_unit_test
(
test_loggc_filename
());
run_unit_test
(
TestOldFreeSpaceCalculation_test
());
#if INCLUDE_VM_STRUCTS
run_unit_test
(
VMStructs
::
test
());
#endif
#if INCLUDE_ALL_GCS
run_unit_test
(
TestOldFreeSpaceCalculation_test
());
run_unit_test
(
TestG1BiasedArray_test
());
run_unit_test
(
HeapRegionRemSet
::
test_prt
());
#endif
...
...
src/share/vm/prims/jvm.cpp
浏览文件 @
fdde7db6
/*
* 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
...
...
@@ -521,6 +521,12 @@ JVM_ENTRY(void, JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms))
JavaThreadInObjectWaitState
jtiows
(
thread
,
ms
!=
0
);
if
(
JvmtiExport
::
should_post_monitor_wait
())
{
JvmtiExport
::
post_monitor_wait
((
JavaThread
*
)
THREAD
,
(
oop
)
obj
(),
ms
);
// The current thread already owns the monitor and it has not yet
// been added to the wait queue so the current thread cannot be
// made the successor. This means that the JVMTI_EVENT_MONITOR_WAIT
// event handler cannot accidentally consume an unpark() meant for
// the ParkEvent associated with this ObjectMonitor.
}
ObjectSynchronizer
::
wait
(
obj
,
ms
,
CHECK
);
JVM_END
...
...
src/share/vm/runtime/globals.cpp
浏览文件 @
fdde7db6
...
...
@@ -31,6 +31,7 @@
#include "utilities/ostream.hpp"
#include "utilities/macros.hpp"
#include "utilities/top.hpp"
#include "trace/tracing.hpp"
#if INCLUDE_ALL_GCS
#include "gc_implementation/g1/g1_globals.hpp"
#endif // INCLUDE_ALL_GCS
...
...
@@ -593,6 +594,17 @@ bool CommandLineFlags::wasSetOnCmdline(const char* name, bool* value) {
return
true
;
}
template
<
class
E
,
class
T
>
static
void
trace_flag_changed
(
const
char
*
name
,
const
T
old_value
,
const
T
new_value
,
const
Flag
::
Flags
origin
)
{
E
e
;
e
.
set_name
(
name
);
e
.
set_old_value
(
old_value
);
e
.
set_new_value
(
new_value
);
e
.
set_origin
(
origin
);
e
.
commit
();
}
bool
CommandLineFlags
::
boolAt
(
char
*
name
,
size_t
len
,
bool
*
value
)
{
Flag
*
result
=
Flag
::
find_flag
(
name
,
len
);
if
(
result
==
NULL
)
return
false
;
...
...
@@ -606,6 +618,7 @@ bool CommandLineFlags::boolAtPut(char* name, size_t len, bool* value, Flag::Flag
if
(
result
==
NULL
)
return
false
;
if
(
!
result
->
is_bool
())
return
false
;
bool
old_value
=
result
->
get_bool
();
trace_flag_changed
<
EventBooleanFlagChanged
,
bool
>
(
name
,
old_value
,
*
value
,
origin
);
result
->
set_bool
(
*
value
);
*
value
=
old_value
;
result
->
set_origin
(
origin
);
...
...
@@ -615,6 +628,7 @@ bool CommandLineFlags::boolAtPut(char* name, size_t len, bool* value, Flag::Flag
void
CommandLineFlagsEx
::
boolAtPut
(
CommandLineFlagWithType
flag
,
bool
value
,
Flag
::
Flags
origin
)
{
Flag
*
faddr
=
address_of_flag
(
flag
);
guarantee
(
faddr
!=
NULL
&&
faddr
->
is_bool
(),
"wrong flag type"
);
trace_flag_changed
<
EventBooleanFlagChanged
,
bool
>
(
faddr
->
_name
,
faddr
->
get_bool
(),
value
,
origin
);
faddr
->
set_bool
(
value
);
faddr
->
set_origin
(
origin
);
}
...
...
@@ -632,6 +646,7 @@ bool CommandLineFlags::intxAtPut(char* name, size_t len, intx* value, Flag::Flag
if
(
result
==
NULL
)
return
false
;
if
(
!
result
->
is_intx
())
return
false
;
intx
old_value
=
result
->
get_intx
();
trace_flag_changed
<
EventLongFlagChanged
,
s8
>
(
name
,
old_value
,
*
value
,
origin
);
result
->
set_intx
(
*
value
);
*
value
=
old_value
;
result
->
set_origin
(
origin
);
...
...
@@ -641,6 +656,7 @@ bool CommandLineFlags::intxAtPut(char* name, size_t len, intx* value, Flag::Flag
void
CommandLineFlagsEx
::
intxAtPut
(
CommandLineFlagWithType
flag
,
intx
value
,
Flag
::
Flags
origin
)
{
Flag
*
faddr
=
address_of_flag
(
flag
);
guarantee
(
faddr
!=
NULL
&&
faddr
->
is_intx
(),
"wrong flag type"
);
trace_flag_changed
<
EventLongFlagChanged
,
s8
>
(
faddr
->
_name
,
faddr
->
get_intx
(),
value
,
origin
);
faddr
->
set_intx
(
value
);
faddr
->
set_origin
(
origin
);
}
...
...
@@ -658,6 +674,7 @@ bool CommandLineFlags::uintxAtPut(char* name, size_t len, uintx* value, Flag::Fl
if
(
result
==
NULL
)
return
false
;
if
(
!
result
->
is_uintx
())
return
false
;
uintx
old_value
=
result
->
get_uintx
();
trace_flag_changed
<
EventUnsignedLongFlagChanged
,
u8
>
(
name
,
old_value
,
*
value
,
origin
);
result
->
set_uintx
(
*
value
);
*
value
=
old_value
;
result
->
set_origin
(
origin
);
...
...
@@ -667,6 +684,7 @@ bool CommandLineFlags::uintxAtPut(char* name, size_t len, uintx* value, Flag::Fl
void
CommandLineFlagsEx
::
uintxAtPut
(
CommandLineFlagWithType
flag
,
uintx
value
,
Flag
::
Flags
origin
)
{
Flag
*
faddr
=
address_of_flag
(
flag
);
guarantee
(
faddr
!=
NULL
&&
faddr
->
is_uintx
(),
"wrong flag type"
);
trace_flag_changed
<
EventUnsignedLongFlagChanged
,
u8
>
(
faddr
->
_name
,
faddr
->
get_uintx
(),
value
,
origin
);
faddr
->
set_uintx
(
value
);
faddr
->
set_origin
(
origin
);
}
...
...
@@ -684,6 +702,7 @@ bool CommandLineFlags::uint64_tAtPut(char* name, size_t len, uint64_t* value, Fl
if
(
result
==
NULL
)
return
false
;
if
(
!
result
->
is_uint64_t
())
return
false
;
uint64_t
old_value
=
result
->
get_uint64_t
();
trace_flag_changed
<
EventUnsignedLongFlagChanged
,
u8
>
(
name
,
old_value
,
*
value
,
origin
);
result
->
set_uint64_t
(
*
value
);
*
value
=
old_value
;
result
->
set_origin
(
origin
);
...
...
@@ -693,6 +712,7 @@ bool CommandLineFlags::uint64_tAtPut(char* name, size_t len, uint64_t* value, Fl
void
CommandLineFlagsEx
::
uint64_tAtPut
(
CommandLineFlagWithType
flag
,
uint64_t
value
,
Flag
::
Flags
origin
)
{
Flag
*
faddr
=
address_of_flag
(
flag
);
guarantee
(
faddr
!=
NULL
&&
faddr
->
is_uint64_t
(),
"wrong flag type"
);
trace_flag_changed
<
EventUnsignedLongFlagChanged
,
u8
>
(
faddr
->
_name
,
faddr
->
get_uint64_t
(),
value
,
origin
);
faddr
->
set_uint64_t
(
value
);
faddr
->
set_origin
(
origin
);
}
...
...
@@ -710,6 +730,7 @@ bool CommandLineFlags::doubleAtPut(char* name, size_t len, double* value, Flag::
if
(
result
==
NULL
)
return
false
;
if
(
!
result
->
is_double
())
return
false
;
double
old_value
=
result
->
get_double
();
trace_flag_changed
<
EventDoubleFlagChanged
,
double
>
(
name
,
old_value
,
*
value
,
origin
);
result
->
set_double
(
*
value
);
*
value
=
old_value
;
result
->
set_origin
(
origin
);
...
...
@@ -719,6 +740,7 @@ bool CommandLineFlags::doubleAtPut(char* name, size_t len, double* value, Flag::
void
CommandLineFlagsEx
::
doubleAtPut
(
CommandLineFlagWithType
flag
,
double
value
,
Flag
::
Flags
origin
)
{
Flag
*
faddr
=
address_of_flag
(
flag
);
guarantee
(
faddr
!=
NULL
&&
faddr
->
is_double
(),
"wrong flag type"
);
trace_flag_changed
<
EventDoubleFlagChanged
,
double
>
(
faddr
->
_name
,
faddr
->
get_double
(),
value
,
origin
);
faddr
->
set_double
(
value
);
faddr
->
set_origin
(
origin
);
}
...
...
@@ -738,6 +760,7 @@ bool CommandLineFlags::ccstrAtPut(char* name, size_t len, ccstr* value, Flag::Fl
if
(
result
==
NULL
)
return
false
;
if
(
!
result
->
is_ccstr
())
return
false
;
ccstr
old_value
=
result
->
get_ccstr
();
trace_flag_changed
<
EventStringFlagChanged
,
const
char
*>
(
name
,
old_value
,
*
value
,
origin
);
char
*
new_value
=
NULL
;
if
(
*
value
!=
NULL
)
{
new_value
=
NEW_C_HEAP_ARRAY
(
char
,
strlen
(
*
value
)
+
1
,
mtInternal
);
...
...
@@ -760,6 +783,7 @@ void CommandLineFlagsEx::ccstrAtPut(CommandLineFlagWithType flag, ccstr value, F
Flag
*
faddr
=
address_of_flag
(
flag
);
guarantee
(
faddr
!=
NULL
&&
faddr
->
is_ccstr
(),
"wrong flag type"
);
ccstr
old_value
=
faddr
->
get_ccstr
();
trace_flag_changed
<
EventStringFlagChanged
,
const
char
*>
(
faddr
->
_name
,
old_value
,
value
,
origin
);
char
*
new_value
=
NEW_C_HEAP_ARRAY
(
char
,
strlen
(
value
)
+
1
,
mtInternal
);
strcpy
(
new_value
,
value
);
faddr
->
set_ccstr
(
new_value
);
...
...
src/share/vm/runtime/objectMonitor.cpp
浏览文件 @
fdde7db6
/*
* Copyright (c) 1998, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 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
...
...
@@ -382,6 +382,12 @@ void ATTR ObjectMonitor::enter(TRAPS) {
DTRACE_MONITOR_PROBE
(
contended__enter
,
this
,
object
(),
jt
);
if
(
JvmtiExport
::
should_post_monitor_contended_enter
())
{
JvmtiExport
::
post_monitor_contended_enter
(
jt
,
this
);
// The current thread does not yet own the monitor and does not
// yet appear on any queues that would get it made the successor.
// This means that the JVMTI_EVENT_MONITOR_CONTENDED_ENTER event
// handler cannot accidentally consume an unpark() meant for the
// ParkEvent associated with this ObjectMonitor.
}
OSThreadContendState
osts
(
Self
->
osthread
());
...
...
@@ -439,6 +445,12 @@ void ATTR ObjectMonitor::enter(TRAPS) {
DTRACE_MONITOR_PROBE
(
contended__entered
,
this
,
object
(),
jt
);
if
(
JvmtiExport
::
should_post_monitor_contended_entered
())
{
JvmtiExport
::
post_monitor_contended_entered
(
jt
,
this
);
// The current thread already owns the monitor and is not going to
// call park() for the remainder of the monitor enter protocol. So
// it doesn't matter if the JVMTI_EVENT_MONITOR_CONTENDED_ENTERED
// event handler consumed an unpark() issued by the thread that
// just exited the monitor.
}
if
(
event
.
should_commit
())
{
...
...
@@ -1456,6 +1468,14 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
// Note: 'false' parameter is passed here because the
// wait was not timed out due to thread interrupt.
JvmtiExport
::
post_monitor_waited
(
jt
,
this
,
false
);
// In this short circuit of the monitor wait protocol, the
// current thread never drops ownership of the monitor and
// never gets added to the wait queue so the current thread
// cannot be made the successor. This means that the
// JVMTI_EVENT_MONITOR_WAITED event handler cannot accidentally
// consume an unpark() meant for the ParkEvent associated with
// this ObjectMonitor.
}
if
(
event
.
should_commit
())
{
post_monitor_wait_event
(
&
event
,
0
,
millis
,
false
);
...
...
@@ -1499,21 +1519,6 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
exit
(
true
,
Self
)
;
// exit the monitor
guarantee
(
_owner
!=
Self
,
"invariant"
)
;
// As soon as the ObjectMonitor's ownership is dropped in the exit()
// call above, another thread can enter() the ObjectMonitor, do the
// notify(), and exit() the ObjectMonitor. If the other thread's
// exit() call chooses this thread as the successor and the unpark()
// call happens to occur while this thread is posting a
// MONITOR_CONTENDED_EXIT event, then we run the risk of the event
// handler using RawMonitors and consuming the unpark().
//
// To avoid the problem, we re-post the event. This does no harm
// even if the original unpark() was not consumed because we are the
// chosen successor for this monitor.
if
(
node
.
_notified
!=
0
&&
_succ
==
Self
)
{
node
.
_event
->
unpark
();
}
// The thread is on the WaitSet list - now park() it.
// On MP systems it's conceivable that a brief spin before we park
// could be profitable.
...
...
@@ -1597,6 +1602,33 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
JvmtiExport
::
post_monitor_waited
(
jt
,
this
,
ret
==
OS_TIMEOUT
);
}
// Without the fix for 8028280, it is possible for the above call:
//
// Thread::SpinAcquire (&_WaitSetLock, "WaitSet - unlink") ;
//
// to consume the unpark() that was done when the successor was set.
// The solution for this very rare possibility is to redo the unpark()
// outside of the JvmtiExport::should_post_monitor_waited() check.
//
if
(
node
.
_notified
!=
0
&&
_succ
==
Self
)
{
// In this part of the monitor wait-notify-reenter protocol it
// is possible (and normal) for another thread to do a fastpath
// monitor enter-exit while this thread is still trying to get
// to the reenter portion of the protocol.
//
// The ObjectMonitor was notified and the current thread is
// the successor which also means that an unpark() has already
// been done. The JVMTI_EVENT_MONITOR_WAITED event handler can
// consume the unpark() that was done when the successor was
// set because the same ParkEvent is shared between Java
// monitors and JVM/TI RawMonitors (for now).
//
// We redo the unpark() to ensure forward progress, i.e., we
// don't want all pending threads hanging (parked) with none
// entering the unlocked monitor.
node
.
_event
->
unpark
();
}
if
(
event
.
should_commit
())
{
post_monitor_wait_event
(
&
event
,
node
.
_notifier_tid
,
millis
,
ret
==
OS_TIMEOUT
);
}
...
...
src/share/vm/runtime/vmStructs.cpp
浏览文件 @
fdde7db6
...
...
@@ -248,7 +248,7 @@ typedef TwoOopHashtable<Klass*, mtClass> KlassTwoOopHashtable;
typedef
Hashtable
<
Klass
*
,
mtClass
>
KlassHashtable
;
typedef
HashtableEntry
<
Klass
*
,
mtClass
>
KlassHashtableEntry
;
typedef
TwoOopHashtable
<
Symbol
*
,
mtClass
>
SymbolTwoOopHashtable
;
typedef
BinaryTreeDictionary
<
Metablock
,
FreeList
>
MetablockTreeDictionary
;
typedef
BinaryTreeDictionary
<
Metablock
,
FreeList
<
Metablock
>
>
MetablockTreeDictionary
;
//--------------------------------------------------------------------------------
// VM_STRUCTS
...
...
src/share/vm/trace/trace.xml
浏览文件 @
fdde7db6
...
...
@@ -122,6 +122,46 @@ Declares a structure type that can be used in other events.
<value
type=
"CLASS"
field=
"definingClassLoader"
label=
"Defining Class Loader"
/>
</event>
<event
id=
"LongFlagChanged"
path=
"vm/flag/long_changed"
label=
"Long Flag Changed"
is_instant=
"true"
>
<value
type=
"UTF8"
field=
"name"
label=
"Name"
/>
<value
type=
"LONG"
field=
"old_value"
label=
"Old Value"
/>
<value
type=
"LONG"
field=
"new_value"
label=
"New Value"
/>
<value
type=
"FLAGVALUEORIGIN"
field=
"origin"
label=
"Origin"
/>
</event>
<event
id=
"UnsignedLongFlagChanged"
path=
"vm/flag/ulong_changed"
label=
"Unsigned Long Flag Changed"
is_instant=
"true"
>
<value
type=
"UTF8"
field=
"name"
label=
"Name"
/>
<value
type=
"ULONG"
field=
"old_value"
label=
"Old Value"
/>
<value
type=
"ULONG"
field=
"new_value"
label=
"New Value"
/>
<value
type=
"FLAGVALUEORIGIN"
field=
"origin"
label=
"Origin"
/>
</event>
<event
id=
"DoubleFlagChanged"
path=
"vm/flag/double_changed"
label=
"Double Flag Changed"
is_instant=
"true"
>
<value
type=
"UTF8"
field=
"name"
label=
"Name"
/>
<value
type=
"DOUBLE"
field=
"old_value"
label=
"Old Value"
/>
<value
type=
"DOUBLE"
field=
"new_value"
label=
"New Value"
/>
<value
type=
"FLAGVALUEORIGIN"
field=
"origin"
label=
"Origin"
/>
</event>
<event
id=
"BooleanFlagChanged"
path=
"vm/flag/boolean_changed"
label=
"Boolean Flag Changed"
is_instant=
"true"
>
<value
type=
"UTF8"
field=
"name"
label=
"Name"
/>
<value
type=
"BOOLEAN"
field=
"old_value"
label=
"Old Value"
/>
<value
type=
"BOOLEAN"
field=
"new_value"
label=
"New Value"
/>
<value
type=
"FLAGVALUEORIGIN"
field=
"origin"
label=
"Origin"
/>
</event>
<event
id=
"StringFlagChanged"
path=
"vm/flag/string_changed"
label=
"String Flag Changed"
is_instant=
"true"
>
<value
type=
"UTF8"
field=
"name"
label=
"Name"
/>
<value
type=
"UTF8"
field=
"old_value"
label=
"Old Value"
/>
<value
type=
"UTF8"
field=
"new_value"
label=
"New Value"
/>
<value
type=
"FLAGVALUEORIGIN"
field=
"origin"
label=
"Origin"
/>
</event>
<struct
id=
"VirtualSpace"
>
<value
type=
"ADDRESS"
field=
"start"
label=
"Start Address"
description=
"Start address of the virtual space"
/>
<value
type=
"ADDRESS"
field=
"committedEnd"
label=
"Committed End Address"
description=
"End address of the committed memory for the virtual space"
/>
...
...
src/share/vm/trace/tracetypes.xml
浏览文件 @
fdde7db6
...
...
@@ -85,12 +85,6 @@ Now we can use the content + data type in declaring event fields.
<value
type=
"UTF8"
field=
"name"
label=
"Name"
/>
</content_type>
<content_type
id=
"StackTrace"
hr_name=
"Stacktrace"
type=
"U8"
builtin_type=
"STACKTRACE"
>
<value
type=
"BOOLEAN"
field=
"truncated"
label=
"Truncated"
/>
<structarray
type=
"StackFrame"
field=
"frames"
label=
"Stack frames"
/>
</content_type>
<content_type
id=
"Class"
hr_name=
"Java class"
type=
"U8"
builtin_type=
"CLASS"
>
<value
type=
"CLASS"
field=
"loaderClass"
label=
"ClassLoader"
/>
...
...
@@ -116,17 +110,6 @@ Now we can use the content + data type in declaring event fields.
<value
type=
"UTF8"
field=
"name"
label=
"Name"
/>
</content_type>
<content_type
id=
"FrameType"
hr_name=
"Frame type"
type=
"U1"
jvm_type=
"FRAMETYPE"
>
<value
type=
"UTF8"
field=
"desc"
label=
"Description"
/>
</content_type>
<struct_type
id=
"StackFrame"
>
<value
type=
"METHOD"
field=
"method"
label=
"Java Method"
/>
<value
type=
"INTEGER"
field=
"line"
label=
"Line number"
/>
<value
type=
"FRAMETYPE"
field=
"type"
label=
"Frame type"
/>
</struct_type>
<content_type
id=
"GCName"
hr_name=
"GC Name"
type=
"U1"
jvm_type=
"GCNAME"
>
<value
type=
"UTF8"
field=
"name"
label=
"name"
/>
...
...
@@ -167,6 +150,11 @@ Now we can use the content + data type in declaring event fields.
<value
type=
"UTF8"
field=
"phase"
label=
"phase"
/>
</content_type>
<content_type
id=
"FlagValueOrigin"
hr_name=
"Flag Value Origin"
type=
"U1"
jvm_type=
"FLAGVALUEORIGIN"
>
<value
type=
"UTF8"
field=
"origin"
label=
"origin"
/>
</content_type>
</content_types>
...
...
@@ -351,6 +339,10 @@ Now we can use the content + data type in declaring event fields.
<!-- VMOPERATIONTYPE -->
<primary_type
symbol=
"VMOPERATIONTYPE"
datatype=
"U2"
contenttype=
"VMOPERATIONTYPE"
type=
"u2"
sizeop=
"sizeof(u2)"
/>
<!-- FLAGVALUEORIGIN -->
<primary_type
symbol=
"FLAGVALUEORIGIN"
datatype=
"U1"
contenttype=
"FLAGVALUEORIGIN"
type=
"u1"
sizeop=
"sizeof(u1)"
/>
</primary_types>
</types>
test/compiler/inlining/InlineDefaultMethod1.java
0 → 100644
浏览文件 @
fdde7db6
/*
* 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
* @bug 8036100
* @summary Default method returns true for a while, and then returns false
* @run main/othervm -Xcomp -XX:CompileOnly=InlineDefaultMethod1::test
* -XX:CompileOnly=I1::m -XX:CompileOnly=I2::m
* InlineDefaultMethod1
*/
interface
I1
{
default
public
int
m
()
{
return
0
;
}
}
interface
I2
extends
I1
{
default
public
int
m
()
{
return
1
;
}
}
abstract
class
A
implements
I1
{
}
class
B
extends
A
implements
I2
{
}
public
class
InlineDefaultMethod1
{
public
static
void
test
(
A
obj
)
{
int
id
=
obj
.
m
();
if
(
id
!=
1
)
{
throw
new
AssertionError
(
"Called wrong method: 1 != "
+
id
);
}
}
public
static
void
main
(
String
[]
args
)
throws
InterruptedException
{
test
(
new
B
());
System
.
out
.
println
(
"TEST PASSED"
);
}
}
test/serviceability/jvmti/TestRedefineWithUnresolvedClass.java
0 → 100644
浏览文件 @
fdde7db6
/*
* 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
* @summary Redefine a class with an UnresolvedClass reference in the constant pool.
* @bug 8035150
* @library /testlibrary
* @build UnresolvedClassAgent com.oracle.java.testlibrary.ProcessTools com.oracle.java.testlibrary.OutputAnalyzer
* @run main TestRedefineWithUnresolvedClass
*/
import
java.io.File
;
import
java.util.Arrays
;
import
com.oracle.java.testlibrary.OutputAnalyzer
;
import
com.oracle.java.testlibrary.ProcessTools
;
public
class
TestRedefineWithUnresolvedClass
{
final
static
String
slash
=
File
.
separator
;
final
static
String
testClasses
=
System
.
getProperty
(
"test.classes"
)
+
slash
;
public
static
void
main
(
String
...
args
)
throws
Throwable
{
// delete this class to cause a NoClassDefFoundError
File
unresolved
=
new
File
(
testClasses
,
"MyUnresolvedClass.class"
);
if
(
unresolved
.
exists
()
&&
!
unresolved
.
delete
())
{
throw
new
Exception
(
"Could not delete: "
+
unresolved
);
}
// build the javaagent
buildJar
(
"UnresolvedClassAgent"
);
// launch a VM with the javaagent
launchTest
();
}
private
static
void
buildJar
(
String
jarName
)
throws
Throwable
{
String
testSrc
=
System
.
getProperty
(
"test.src"
,
"?"
)
+
slash
;
String
jarPath
=
String
.
format
(
"%s%s.jar"
,
testClasses
,
jarName
);
String
manifestPath
=
String
.
format
(
"%s%s.mf"
,
testSrc
,
jarName
);
String
className
=
String
.
format
(
"%s.class"
,
jarName
);
String
[]
args
=
new
String
[]
{
"-cfm"
,
jarPath
,
manifestPath
,
"-C"
,
testClasses
,
className
};
System
.
out
.
println
(
"Running jar "
+
Arrays
.
toString
(
args
));
sun
.
tools
.
jar
.
Main
jarTool
=
new
sun
.
tools
.
jar
.
Main
(
System
.
out
,
System
.
err
,
"jar"
);
if
(!
jarTool
.
run
(
args
))
{
throw
new
Exception
(
"jar failed: args="
+
Arrays
.
toString
(
args
));
}
}
private
static
void
launchTest
()
throws
Throwable
{
String
[]
args
=
{
"-javaagent:"
+
testClasses
+
"UnresolvedClassAgent.jar"
,
"-Dtest.classes="
+
testClasses
,
"UnresolvedClassAgent"
};
OutputAnalyzer
output
=
ProcessTools
.
executeTestJvm
(
args
);
output
.
shouldHaveExitValue
(
0
);
}
}
test/serviceability/jvmti/UnresolvedClassAgent.java
0 → 100644
浏览文件 @
fdde7db6
/*
* 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.
*/
import
java.io.DataInputStream
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.lang.instrument.ClassDefinition
;
import
java.lang.instrument.Instrumentation
;
/*
* This class is present during compilation, but will be deleted before execution.
*/
class
MyUnresolvedClass
{
static
void
bar
()
{
}
}
class
MyRedefinedClass
{
static
void
foo
()
{
MyUnresolvedClass
.
bar
();
}
}
public
class
UnresolvedClassAgent
{
public
static
void
main
(
String
...
args
)
{
}
public
static
void
premain
(
String
args
,
Instrumentation
inst
)
throws
Exception
{
try
{
MyRedefinedClass
.
foo
();
}
catch
(
NoClassDefFoundError
err
)
{
System
.
out
.
println
(
"NoClassDefFoundError (expected)"
);
}
File
f
=
new
File
(
System
.
getProperty
(
"test.classes"
),
"MyRedefinedClass.class"
);
byte
[]
buf
=
new
byte
[(
int
)
f
.
length
()];
try
(
DataInputStream
dis
=
new
DataInputStream
(
new
FileInputStream
(
f
)))
{
dis
.
readFully
(
buf
);
}
ClassDefinition
cd
=
new
ClassDefinition
(
MyRedefinedClass
.
class
,
buf
);
inst
.
redefineClasses
(
new
ClassDefinition
[]
{
cd
});
try
{
MyRedefinedClass
.
foo
();
}
catch
(
NoClassDefFoundError
err
)
{
System
.
out
.
println
(
"NoClassDefFoundError (expected again)"
);
}
}
}
test/serviceability/jvmti/UnresolvedClassAgent.mf
0 → 100644
浏览文件 @
fdde7db6
Manifest-Version: 1.0
Premain-Class: UnresolvedClassAgent
Can-Redefine-Classes: true
test/serviceability/sa/jmap-hashcode/Test8028623.java
0 → 100644
浏览文件 @
fdde7db6
/*
* 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
* @bug 8028623
* @summary Test hashing of extended characters in Serviceability Agent.
* @library /testlibrary
* @compile -encoding utf8 Test8028623.java
* @run main Test8028623
*/
import
com.oracle.java.testlibrary.JDKToolLauncher
;
import
com.oracle.java.testlibrary.OutputBuffer
;
import
com.oracle.java.testlibrary.ProcessTools
;
import
java.io.File
;
public
class
Test8028623
{
public
static
int
Ã
=
1
;
public
static
String
dumpFile
=
"heap.out"
;
public
static
void
main
(
String
[]
args
)
{
System
.
out
.
println
(
Ã
);
try
{
int
pid
=
ProcessTools
.
getProcessId
();
JDKToolLauncher
jmap
=
JDKToolLauncher
.
create
(
"jmap"
)
.
addToolArg
(
"-F"
)
.
addToolArg
(
"-dump:live,format=b,file="
+
dumpFile
)
.
addToolArg
(
Integer
.
toString
(
pid
));
ProcessBuilder
pb
=
new
ProcessBuilder
(
jmap
.
getCommand
());
OutputBuffer
output
=
ProcessTools
.
getOutput
(
pb
);
Process
p
=
pb
.
start
();
int
e
=
p
.
waitFor
();
System
.
out
.
println
(
"stdout:"
);
System
.
out
.
println
(
output
.
getStdout
());
System
.
out
.
println
(
"stderr:"
);
System
.
out
.
println
(
output
.
getStderr
());
if
(
e
!=
0
)
{
throw
new
RuntimeException
(
"jmap returns: "
+
e
);
}
if
(!
new
File
(
dumpFile
).
exists
())
{
throw
new
RuntimeException
(
"dump file NOT created: '"
+
dumpFile
+
"'"
);
}
}
catch
(
Throwable
t
)
{
t
.
printStackTrace
();
throw
new
RuntimeException
(
"Test failed with: "
+
t
);
}
}
}
test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java
浏览文件 @
fdde7db6
...
...
@@ -151,11 +151,88 @@ public final class ProcessTools {
// Reporting
StringBuilder
cmdLine
=
new
StringBuilder
();
for
(
String
cmd
:
args
)
cmdLine
.
append
(
cmd
).
append
(
' '
);
for
(
String
cmd
:
args
)
{
cmdLine
.
append
(
cmd
).
append
(
' '
);
}
System
.
out
.
println
(
"Command line: ["
+
cmdLine
.
toString
()
+
"]"
);
return
new
ProcessBuilder
(
args
.
toArray
(
new
String
[
args
.
size
()]));
}
/**
* Executes a test jvm process, waits for it to finish and returns the process output.
* The default jvm options from jtreg, test.vm.opts and test.java.opts, are added.
* The java from the test.jdk is used to execute the command.
*
* The command line will be like:
* {test.jdk}/bin/java {test.vm.opts} {test.java.opts} cmds
*
* @param cmds User specifed arguments.
* @return The output from the process.
*/
public
static
OutputAnalyzer
executeTestJvm
(
String
...
cmds
)
throws
Throwable
{
ProcessBuilder
pb
=
createJavaProcessBuilder
(
Utils
.
addTestJavaOpts
(
cmds
));
return
executeProcess
(
pb
);
}
/**
* Executes a process, waits for it to finish and returns the process output.
* @param pb The ProcessBuilder to execute.
* @return The output from the process.
*/
public
static
OutputAnalyzer
executeProcess
(
ProcessBuilder
pb
)
throws
Throwable
{
OutputAnalyzer
output
=
null
;
try
{
output
=
new
OutputAnalyzer
(
pb
.
start
());
return
output
;
}
catch
(
Throwable
t
)
{
System
.
out
.
println
(
"executeProcess() failed: "
+
t
);
throw
t
;
}
finally
{
System
.
out
.
println
(
getProcessLog
(
pb
,
output
));
}
}
/**
* Executes a process, waits for it to finish and returns the process output.
* @param cmds The command line to execute.
* @return The output from the process.
*/
public
static
OutputAnalyzer
executeProcess
(
String
...
cmds
)
throws
Throwable
{
return
executeProcess
(
new
ProcessBuilder
(
cmds
));
}
/**
* Used to log command line, stdout, stderr and exit code from an executed process.
* @param pb The executed process.
* @param output The output from the process.
*/
public
static
String
getProcessLog
(
ProcessBuilder
pb
,
OutputAnalyzer
output
)
{
String
stderr
=
output
==
null
?
"null"
:
output
.
getStderr
();
String
stdout
=
output
==
null
?
"null"
:
output
.
getStdout
();
String
exitValue
=
output
==
null
?
"null"
:
Integer
.
toString
(
output
.
getExitValue
());
StringBuilder
logMsg
=
new
StringBuilder
();
final
String
nl
=
System
.
getProperty
(
"line.separator"
);
logMsg
.
append
(
"--- ProcessLog ---"
+
nl
);
logMsg
.
append
(
"cmd: "
+
getCommandLine
(
pb
)
+
nl
);
logMsg
.
append
(
"exitvalue: "
+
exitValue
+
nl
);
logMsg
.
append
(
"stderr: "
+
stderr
+
nl
);
logMsg
.
append
(
"stdout: "
+
stdout
+
nl
);
return
logMsg
.
toString
();
}
/**
* @return The full command line for the ProcessBuilder.
*/
public
static
String
getCommandLine
(
ProcessBuilder
pb
)
{
if
(
pb
==
null
)
{
return
"null"
;
}
StringBuilder
cmd
=
new
StringBuilder
();
for
(
String
s
:
pb
.
command
())
{
cmd
.
append
(
s
).
append
(
" "
);
}
return
cmd
.
toString
().
trim
();
}
}
test/testlibrary/com/oracle/java/testlibrary/Utils.java
0 → 100644
浏览文件 @
fdde7db6
/*
* Copyright (c) 2013, 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.
*/
package
com.oracle.java.testlibrary
;
import
static
com
.
oracle
.
java
.
testlibrary
.
Asserts
.
assertTrue
;
import
java.io.BufferedReader
;
import
java.io.File
;
import
java.io.FileReader
;
import
java.io.IOException
;
import
java.net.InetAddress
;
import
java.net.ServerSocket
;
import
java.net.UnknownHostException
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.regex.Pattern
;
import
java.util.regex.Matcher
;
/**
* Common library for various test helper functions.
*/
public
final
class
Utils
{
/**
* Returns the sequence used by operating system to separate lines.
*/
public
static
final
String
NEW_LINE
=
System
.
getProperty
(
"line.separator"
);
/**
* Returns the value of 'test.vm.opts'system property.
*/
public
static
final
String
VM_OPTIONS
=
System
.
getProperty
(
"test.vm.opts"
,
""
).
trim
();
/**
* Returns the value of 'test.java.opts'system property.
*/
public
static
final
String
JAVA_OPTIONS
=
System
.
getProperty
(
"test.java.opts"
,
""
).
trim
();
/**
* Returns the value of 'test.timeout.factor' system property
* converted to {@code double}.
*/
public
static
final
double
TIMEOUT_FACTOR
;
static
{
String
toFactor
=
System
.
getProperty
(
"test.timeout.factor"
,
"1.0"
);
TIMEOUT_FACTOR
=
Double
.
parseDouble
(
toFactor
);
}
private
Utils
()
{
// Private constructor to prevent class instantiation
}
/**
* Returns the list of VM options.
*
* @return List of VM options
*/
public
static
List
<
String
>
getVmOptions
()
{
return
Arrays
.
asList
(
safeSplitString
(
VM_OPTIONS
));
}
/**
* Returns the list of VM options with -J prefix.
*
* @return The list of VM options with -J prefix
*/
public
static
List
<
String
>
getForwardVmOptions
()
{
String
[]
opts
=
safeSplitString
(
VM_OPTIONS
);
for
(
int
i
=
0
;
i
<
opts
.
length
;
i
++)
{
opts
[
i
]
=
"-J"
+
opts
[
i
];
}
return
Arrays
.
asList
(
opts
);
}
/**
* Returns the default JTReg arguments for a jvm running a test.
* This is the combination of JTReg arguments test.vm.opts and test.java.opts.
* @return An array of options, or an empty array if no opptions.
*/
public
static
String
[]
getTestJavaOpts
()
{
List
<
String
>
opts
=
new
ArrayList
<
String
>();
Collections
.
addAll
(
opts
,
safeSplitString
(
VM_OPTIONS
));
Collections
.
addAll
(
opts
,
safeSplitString
(
JAVA_OPTIONS
));
return
opts
.
toArray
(
new
String
[
0
]);
}
/**
* Combines given arguments with default JTReg arguments for a jvm running a test.
* This is the combination of JTReg arguments test.vm.opts and test.java.opts
* @return The combination of JTReg test java options and user args.
*/
public
static
String
[]
addTestJavaOpts
(
String
...
userArgs
)
{
List
<
String
>
opts
=
new
ArrayList
<
String
>();
Collections
.
addAll
(
opts
,
getTestJavaOpts
());
Collections
.
addAll
(
opts
,
userArgs
);
return
opts
.
toArray
(
new
String
[
0
]);
}
/**
* Splits a string by white space.
* Works like String.split(), but returns an empty array
* if the string is null or empty.
*/
private
static
String
[]
safeSplitString
(
String
s
)
{
if
(
s
==
null
||
s
.
trim
().
isEmpty
())
{
return
new
String
[]
{};
}
return
s
.
trim
().
split
(
"\\s+"
);
}
/**
* @return The full command line for the ProcessBuilder.
*/
public
static
String
getCommandLine
(
ProcessBuilder
pb
)
{
StringBuilder
cmd
=
new
StringBuilder
();
for
(
String
s
:
pb
.
command
())
{
cmd
.
append
(
s
).
append
(
" "
);
}
return
cmd
.
toString
();
}
/**
* Returns the free port on the local host.
* The function will spin until a valid port number is found.
*
* @return The port number
* @throws InterruptedException if any thread has interrupted the current thread
* @throws IOException if an I/O error occurs when opening the socket
*/
public
static
int
getFreePort
()
throws
InterruptedException
,
IOException
{
int
port
=
-
1
;
while
(
port
<=
0
)
{
Thread
.
sleep
(
100
);
ServerSocket
serverSocket
=
null
;
try
{
serverSocket
=
new
ServerSocket
(
0
);
port
=
serverSocket
.
getLocalPort
();
}
finally
{
serverSocket
.
close
();
}
}
return
port
;
}
/**
* Returns the name of the local host.
*
* @return The host name
* @throws UnknownHostException if IP address of a host could not be determined
*/
public
static
String
getHostname
()
throws
UnknownHostException
{
InetAddress
inetAddress
=
InetAddress
.
getLocalHost
();
String
hostName
=
inetAddress
.
getHostName
();
assertTrue
((
hostName
!=
null
&&
!
hostName
.
isEmpty
()),
"Cannot get hostname"
);
return
hostName
;
}
/**
* Uses "jcmd -l" to search for a jvm pid. This function will wait
* forever (until jtreg timeout) for the pid to be found.
* @param key Regular expression to search for
* @return The found pid.
*/
public
static
int
waitForJvmPid
(
String
key
)
throws
Throwable
{
final
long
iterationSleepMillis
=
250
;
System
.
out
.
println
(
"waitForJvmPid: Waiting for key '"
+
key
+
"'"
);
System
.
out
.
flush
();
while
(
true
)
{
int
pid
=
tryFindJvmPid
(
key
);
if
(
pid
>=
0
)
{
return
pid
;
}
Thread
.
sleep
(
iterationSleepMillis
);
}
}
/**
* Searches for a jvm pid in the output from "jcmd -l".
*
* Example output from jcmd is:
* 12498 sun.tools.jcmd.JCmd -l
* 12254 /tmp/jdk8/tl/jdk/JTwork/classes/com/sun/tools/attach/Application.jar
*
* @param key A regular expression to search for.
* @return The found pid, or -1 if Enot found.
* @throws Exception If multiple matching jvms are found.
*/
public
static
int
tryFindJvmPid
(
String
key
)
throws
Throwable
{
OutputAnalyzer
output
=
null
;
try
{
JDKToolLauncher
jcmdLauncher
=
JDKToolLauncher
.
create
(
"jcmd"
);
jcmdLauncher
.
addToolArg
(
"-l"
);
output
=
ProcessTools
.
executeProcess
(
jcmdLauncher
.
getCommand
());
output
.
shouldHaveExitValue
(
0
);
// Search for a line starting with numbers (pid), follwed by the key.
Pattern
pattern
=
Pattern
.
compile
(
"([0-9]+)\\s.*("
+
key
+
").*\\r?\\n"
);
Matcher
matcher
=
pattern
.
matcher
(
output
.
getStdout
());
int
pid
=
-
1
;
if
(
matcher
.
find
())
{
pid
=
Integer
.
parseInt
(
matcher
.
group
(
1
));
System
.
out
.
println
(
"findJvmPid.pid: "
+
pid
);
if
(
matcher
.
find
())
{
throw
new
Exception
(
"Found multiple JVM pids for key: "
+
key
);
}
}
return
pid
;
}
catch
(
Throwable
t
)
{
System
.
out
.
println
(
String
.
format
(
"Utils.findJvmPid(%s) failed: %s"
,
key
,
t
));
throw
t
;
}
}
/**
* Returns file content as a list of strings
*
* @param file File to operate on
* @return List of strings
* @throws IOException
*/
public
static
List
<
String
>
fileAsList
(
File
file
)
throws
IOException
{
assertTrue
(
file
.
exists
()
&&
file
.
isFile
(),
file
.
getAbsolutePath
()
+
" does not exist or not a file"
);
List
<
String
>
output
=
new
ArrayList
<>();
try
(
BufferedReader
reader
=
new
BufferedReader
(
new
FileReader
(
file
.
getAbsolutePath
())))
{
while
(
reader
.
ready
())
{
output
.
add
(
reader
.
readLine
().
replace
(
NEW_LINE
,
""
));
}
}
return
output
;
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录