Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
0d459bfa
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看板
体验新版 GitCode,发现更多精彩内容 >>
提交
0d459bfa
编写于
12月 03, 2012
作者:
J
jmasa
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8005082: NPG: Add specialized Metachunk sizes for reflection and anonymous classloaders
Reviewed-by: johnc, coleenp
上级
73ee7ee2
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
420 addition
and
227 deletion
+420
-227
src/share/vm/classfile/classLoaderData.cpp
src/share/vm/classfile/classLoaderData.cpp
+14
-5
src/share/vm/memory/binaryTreeDictionary.cpp
src/share/vm/memory/binaryTreeDictionary.cpp
+3
-2
src/share/vm/memory/collectorPolicy.cpp
src/share/vm/memory/collectorPolicy.cpp
+9
-0
src/share/vm/memory/metachunk.cpp
src/share/vm/memory/metachunk.cpp
+8
-3
src/share/vm/memory/metachunk.hpp
src/share/vm/memory/metachunk.hpp
+8
-6
src/share/vm/memory/metaspace.cpp
src/share/vm/memory/metaspace.cpp
+361
-207
src/share/vm/memory/metaspace.hpp
src/share/vm/memory/metaspace.hpp
+15
-3
src/share/vm/runtime/globals.hpp
src/share/vm/runtime/globals.hpp
+2
-1
未找到文件。
src/share/vm/classfile/classLoaderData.cpp
浏览文件 @
0d459bfa
...
@@ -330,10 +330,19 @@ Metaspace* ClassLoaderData::metaspace_non_null() {
...
@@ -330,10 +330,19 @@ Metaspace* ClassLoaderData::metaspace_non_null() {
}
}
if
(
this
==
the_null_class_loader_data
())
{
if
(
this
==
the_null_class_loader_data
())
{
assert
(
class_loader
()
==
NULL
,
"Must be"
);
assert
(
class_loader
()
==
NULL
,
"Must be"
);
size_t
word_size
=
Metaspace
::
first_chunk_word_size
();
set_metaspace
(
new
Metaspace
(
_metaspace_lock
,
Metaspace
::
BootMetaspaceType
));
set_metaspace
(
new
Metaspace
(
_metaspace_lock
,
word_size
));
}
else
if
(
is_anonymous
())
{
if
(
TraceClassLoaderData
&&
Verbose
&&
class_loader
()
!=
NULL
)
{
tty
->
print_cr
(
"is_anonymous: %s"
,
class_loader
()
->
klass
()
->
internal_name
());
}
set_metaspace
(
new
Metaspace
(
_metaspace_lock
,
Metaspace
::
AnonymousMetaspaceType
));
}
else
if
(
class_loader
()
->
is_a
(
SystemDictionary
::
reflect_DelegatingClassLoader_klass
()))
{
if
(
TraceClassLoaderData
&&
Verbose
&&
class_loader
()
!=
NULL
)
{
tty
->
print_cr
(
"is_reflection: %s"
,
class_loader
()
->
klass
()
->
internal_name
());
}
set_metaspace
(
new
Metaspace
(
_metaspace_lock
,
Metaspace
::
ReflectionMetaspaceType
));
}
else
{
}
else
{
set_metaspace
(
new
Metaspace
(
_metaspace_lock
));
// default size for now.
set_metaspace
(
new
Metaspace
(
_metaspace_lock
,
Metaspace
::
StandardMetaspaceType
));
}
}
}
}
return
_metaspace
;
return
_metaspace
;
...
@@ -672,8 +681,8 @@ void ClassLoaderData::initialize_shared_metaspaces() {
...
@@ -672,8 +681,8 @@ void ClassLoaderData::initialize_shared_metaspaces() {
"only supported for null loader data for now"
);
"only supported for null loader data for now"
);
assert
(
!
_shared_metaspaces_initialized
,
"only initialize once"
);
assert
(
!
_shared_metaspaces_initialized
,
"only initialize once"
);
MutexLockerEx
ml
(
metaspace_lock
(),
Mutex
::
_no_safepoint_check_flag
);
MutexLockerEx
ml
(
metaspace_lock
(),
Mutex
::
_no_safepoint_check_flag
);
_ro_metaspace
=
new
Metaspace
(
_metaspace_lock
,
SharedReadOnlySize
/
wordSiz
e
);
_ro_metaspace
=
new
Metaspace
(
_metaspace_lock
,
Metaspace
::
ROMetaspaceTyp
e
);
_rw_metaspace
=
new
Metaspace
(
_metaspace_lock
,
SharedReadWriteSize
/
wordSiz
e
);
_rw_metaspace
=
new
Metaspace
(
_metaspace_lock
,
Metaspace
::
ReadWriteMetaspaceTyp
e
);
_shared_metaspaces_initialized
=
true
;
_shared_metaspaces_initialized
=
true
;
}
}
...
...
src/share/vm/memory/binaryTreeDictionary.cpp
浏览文件 @
0d459bfa
...
@@ -67,7 +67,8 @@ void TreeChunk<Chunk_t, FreeList_t>::verify_tree_chunk_list() const {
...
@@ -67,7 +67,8 @@ void TreeChunk<Chunk_t, FreeList_t>::verify_tree_chunk_list() const {
}
}
template
<
class
Chunk_t
,
template
<
class
>
class
FreeList_t
>
template
<
class
Chunk_t
,
template
<
class
>
class
FreeList_t
>
TreeList
<
Chunk_t
,
FreeList_t
>::
TreeList
()
{}
TreeList
<
Chunk_t
,
FreeList_t
>::
TreeList
()
:
_parent
(
NULL
),
_left
(
NULL
),
_right
(
NULL
)
{}
template
<
class
Chunk_t
,
template
<
class
>
class
FreeList_t
>
template
<
class
Chunk_t
,
template
<
class
>
class
FreeList_t
>
TreeList
<
Chunk_t
,
FreeList_t
>*
TreeList
<
Chunk_t
,
FreeList_t
>*
...
@@ -82,7 +83,7 @@ TreeList<Chunk_t, FreeList_t>::as_TreeList(TreeChunk<Chunk_t,FreeList_t>* tc) {
...
@@ -82,7 +83,7 @@ TreeList<Chunk_t, FreeList_t>::as_TreeList(TreeChunk<Chunk_t,FreeList_t>* tc) {
tl
->
link_head
(
tc
);
tl
->
link_head
(
tc
);
tl
->
link_tail
(
tc
);
tl
->
link_tail
(
tc
);
tl
->
set_count
(
1
);
tl
->
set_count
(
1
);
assert
(
tl
->
parent
()
==
NULL
,
"Should be clear"
);
return
tl
;
return
tl
;
}
}
...
...
src/share/vm/memory/collectorPolicy.cpp
浏览文件 @
0d459bfa
...
@@ -777,6 +777,15 @@ MetaWord* CollectorPolicy::satisfy_failed_metadata_allocation(
...
@@ -777,6 +777,15 @@ MetaWord* CollectorPolicy::satisfy_failed_metadata_allocation(
full_gc_count
,
full_gc_count
,
GCCause
::
_metadata_GC_threshold
);
GCCause
::
_metadata_GC_threshold
);
VMThread
::
execute
(
&
op
);
VMThread
::
execute
(
&
op
);
// If GC was locked out, try again. Check
// before checking success because the prologue
// could have succeeded and the GC still have
// been locked out.
if
(
op
.
gc_locked
())
{
continue
;
}
if
(
op
.
prologue_succeeded
())
{
if
(
op
.
prologue_succeeded
())
{
return
op
.
result
();
return
op
.
result
();
}
}
...
...
src/share/vm/memory/metachunk.cpp
浏览文件 @
0d459bfa
...
@@ -56,6 +56,7 @@ Metachunk* Metachunk::initialize(MetaWord* ptr, size_t word_size) {
...
@@ -56,6 +56,7 @@ Metachunk* Metachunk::initialize(MetaWord* ptr, size_t word_size) {
assert
(
chunk_end
>
chunk_bottom
,
"Chunk must be too small"
);
assert
(
chunk_end
>
chunk_bottom
,
"Chunk must be too small"
);
chunk
->
set_end
(
chunk_end
);
chunk
->
set_end
(
chunk_end
);
chunk
->
set_next
(
NULL
);
chunk
->
set_next
(
NULL
);
chunk
->
set_prev
(
NULL
);
chunk
->
set_word_size
(
word_size
);
chunk
->
set_word_size
(
word_size
);
#ifdef ASSERT
#ifdef ASSERT
size_t
data_word_size
=
pointer_delta
(
chunk_end
,
chunk_bottom
,
sizeof
(
MetaWord
));
size_t
data_word_size
=
pointer_delta
(
chunk_end
,
chunk_bottom
,
sizeof
(
MetaWord
));
...
@@ -76,15 +77,15 @@ MetaWord* Metachunk::allocate(size_t word_size) {
...
@@ -76,15 +77,15 @@ MetaWord* Metachunk::allocate(size_t word_size) {
}
}
// _bottom points to the start of the chunk including the overhead.
// _bottom points to the start of the chunk including the overhead.
size_t
Metachunk
::
used_word_size
()
{
size_t
Metachunk
::
used_word_size
()
const
{
return
pointer_delta
(
_top
,
_bottom
,
sizeof
(
MetaWord
));
return
pointer_delta
(
_top
,
_bottom
,
sizeof
(
MetaWord
));
}
}
size_t
Metachunk
::
free_word_size
()
{
size_t
Metachunk
::
free_word_size
()
const
{
return
pointer_delta
(
_end
,
_top
,
sizeof
(
MetaWord
));
return
pointer_delta
(
_end
,
_top
,
sizeof
(
MetaWord
));
}
}
size_t
Metachunk
::
capacity_word_size
()
{
size_t
Metachunk
::
capacity_word_size
()
const
{
return
pointer_delta
(
_end
,
_bottom
,
sizeof
(
MetaWord
));
return
pointer_delta
(
_end
,
_bottom
,
sizeof
(
MetaWord
));
}
}
...
@@ -93,6 +94,10 @@ void Metachunk::print_on(outputStream* st) const {
...
@@ -93,6 +94,10 @@ void Metachunk::print_on(outputStream* st) const {
" bottom "
PTR_FORMAT
" top "
PTR_FORMAT
" bottom "
PTR_FORMAT
" top "
PTR_FORMAT
" end "
PTR_FORMAT
" size "
SIZE_FORMAT
,
" end "
PTR_FORMAT
" size "
SIZE_FORMAT
,
bottom
(),
top
(),
end
(),
word_size
());
bottom
(),
top
(),
end
(),
word_size
());
if
(
Verbose
)
{
st
->
print_cr
(
" used "
SIZE_FORMAT
" free "
SIZE_FORMAT
,
used_word_size
(),
free_word_size
());
}
}
}
#ifndef PRODUCT
#ifndef PRODUCT
...
...
src/share/vm/memory/metachunk.hpp
浏览文件 @
0d459bfa
...
@@ -67,9 +67,11 @@ class Metachunk VALUE_OBJ_CLASS_SPEC {
...
@@ -67,9 +67,11 @@ class Metachunk VALUE_OBJ_CLASS_SPEC {
void
set_word_size
(
size_t
v
)
{
_word_size
=
v
;
}
void
set_word_size
(
size_t
v
)
{
_word_size
=
v
;
}
public:
public:
#ifdef ASSERT
#ifdef ASSERT
Metachunk
()
:
_bottom
(
NULL
),
_end
(
NULL
),
_top
(
NULL
),
_is_free
(
false
)
{}
Metachunk
()
:
_bottom
(
NULL
),
_end
(
NULL
),
_top
(
NULL
),
_is_free
(
false
),
_next
(
NULL
),
_prev
(
NULL
)
{}
#else
#else
Metachunk
()
:
_bottom
(
NULL
),
_end
(
NULL
),
_top
(
NULL
)
{}
Metachunk
()
:
_bottom
(
NULL
),
_end
(
NULL
),
_top
(
NULL
),
_next
(
NULL
),
_prev
(
NULL
)
{}
#endif
#endif
// Used to add a Metachunk to a list of Metachunks
// Used to add a Metachunk to a list of Metachunks
...
@@ -102,15 +104,15 @@ class Metachunk VALUE_OBJ_CLASS_SPEC {
...
@@ -102,15 +104,15 @@ class Metachunk VALUE_OBJ_CLASS_SPEC {
}
}
// Reset top to bottom so chunk can be reused.
// Reset top to bottom so chunk can be reused.
void
reset_empty
()
{
_top
=
(
_bottom
+
_overhead
);
}
void
reset_empty
()
{
_top
=
(
_bottom
+
_overhead
);
_next
=
NULL
;
_prev
=
NULL
;
}
bool
is_empty
()
{
return
_top
==
(
_bottom
+
_overhead
);
}
bool
is_empty
()
{
return
_top
==
(
_bottom
+
_overhead
);
}
// used (has been allocated)
// used (has been allocated)
// free (available for future allocations)
// free (available for future allocations)
// capacity (total size of chunk)
// capacity (total size of chunk)
size_t
used_word_size
();
size_t
used_word_size
()
const
;
size_t
free_word_size
();
size_t
free_word_size
()
const
;
size_t
capacity_word_size
();
size_t
capacity_word_size
()
const
;
// Debug support
// Debug support
#ifdef ASSERT
#ifdef ASSERT
...
...
src/share/vm/memory/metaspace.cpp
浏览文件 @
0d459bfa
...
@@ -58,11 +58,23 @@ MetaWord* last_allocated = 0;
...
@@ -58,11 +58,23 @@ MetaWord* last_allocated = 0;
// Used in declarations in SpaceManager and ChunkManager
// Used in declarations in SpaceManager and ChunkManager
enum
ChunkIndex
{
enum
ChunkIndex
{
SmallIndex
=
0
,
ZeroIndex
=
0
,
MediumIndex
=
1
,
SpecializedIndex
=
ZeroIndex
,
HumongousIndex
=
2
,
SmallIndex
=
SpecializedIndex
+
1
,
NumberOfFreeLists
=
2
,
MediumIndex
=
SmallIndex
+
1
,
NumberOfInUseLists
=
3
HumongousIndex
=
MediumIndex
+
1
,
NumberOfFreeLists
=
3
,
NumberOfInUseLists
=
4
};
enum
ChunkSizes
{
// in words.
ClassSpecializedChunk
=
128
,
SpecializedChunk
=
128
,
ClassSmallChunk
=
256
,
SmallChunk
=
512
,
ClassMediumChunk
=
1
*
K
,
MediumChunk
=
8
*
K
,
HumongousChunkGranularity
=
8
};
};
static
ChunkIndex
next_chunk_index
(
ChunkIndex
i
)
{
static
ChunkIndex
next_chunk_index
(
ChunkIndex
i
)
{
...
@@ -126,6 +138,7 @@ class ChunkManager VALUE_OBJ_CLASS_SPEC {
...
@@ -126,6 +138,7 @@ class ChunkManager VALUE_OBJ_CLASS_SPEC {
// HumongousChunk
// HumongousChunk
ChunkList
_free_chunks
[
NumberOfFreeLists
];
ChunkList
_free_chunks
[
NumberOfFreeLists
];
// HumongousChunk
// HumongousChunk
ChunkTreeDictionary
_humongous_dictionary
;
ChunkTreeDictionary
_humongous_dictionary
;
...
@@ -169,6 +182,10 @@ class ChunkManager VALUE_OBJ_CLASS_SPEC {
...
@@ -169,6 +182,10 @@ class ChunkManager VALUE_OBJ_CLASS_SPEC {
Metachunk
*
chunk_freelist_allocate
(
size_t
word_size
);
Metachunk
*
chunk_freelist_allocate
(
size_t
word_size
);
void
chunk_freelist_deallocate
(
Metachunk
*
chunk
);
void
chunk_freelist_deallocate
(
Metachunk
*
chunk
);
// Map a size to a list index assuming that there are lists
// for special, small, medium, and humongous chunks.
static
ChunkIndex
list_index
(
size_t
size
);
// Total of the space in the free chunks list
// Total of the space in the free chunks list
size_t
free_chunks_total
();
size_t
free_chunks_total
();
size_t
free_chunks_total_in_bytes
();
size_t
free_chunks_total_in_bytes
();
...
@@ -180,8 +197,6 @@ class ChunkManager VALUE_OBJ_CLASS_SPEC {
...
@@ -180,8 +197,6 @@ class ChunkManager VALUE_OBJ_CLASS_SPEC {
Atomic
::
add_ptr
(
count
,
&
_free_chunks_count
);
Atomic
::
add_ptr
(
count
,
&
_free_chunks_count
);
Atomic
::
add_ptr
(
v
,
&
_free_chunks_total
);
Atomic
::
add_ptr
(
v
,
&
_free_chunks_total
);
}
}
ChunkList
*
free_medium_chunks
()
{
return
&
_free_chunks
[
1
];
}
ChunkList
*
free_small_chunks
()
{
return
&
_free_chunks
[
0
];
}
ChunkTreeDictionary
*
humongous_dictionary
()
{
ChunkTreeDictionary
*
humongous_dictionary
()
{
return
&
_humongous_dictionary
;
return
&
_humongous_dictionary
;
}
}
...
@@ -400,7 +415,14 @@ class VirtualSpaceList : public CHeapObj<mtClass> {
...
@@ -400,7 +415,14 @@ class VirtualSpaceList : public CHeapObj<mtClass> {
VirtualSpaceList
(
size_t
word_size
);
VirtualSpaceList
(
size_t
word_size
);
VirtualSpaceList
(
ReservedSpace
rs
);
VirtualSpaceList
(
ReservedSpace
rs
);
Metachunk
*
get_new_chunk
(
size_t
word_size
,
size_t
grow_chunks_by_words
);
Metachunk
*
get_new_chunk
(
size_t
word_size
,
size_t
grow_chunks_by_words
,
size_t
medium_chunk_bunch
);
// Get the first chunk for a Metaspace. Used for
// special cases such as the boot class loader, reflection
// class loader and anonymous class loader.
Metachunk
*
get_initialization_chunk
(
size_t
word_size
,
size_t
chunk_bunch
);
VirtualSpaceNode
*
current_virtual_space
()
{
VirtualSpaceNode
*
current_virtual_space
()
{
return
_current_virtual_space
;
return
_current_virtual_space
;
...
@@ -501,9 +523,13 @@ class SpaceManager : public CHeapObj<mtClass> {
...
@@ -501,9 +523,13 @@ class SpaceManager : public CHeapObj<mtClass> {
friend
class
Metadebug
;
friend
class
Metadebug
;
private:
private:
// protects allocations and contains.
// protects allocations and contains.
Mutex
*
const
_lock
;
Mutex
*
const
_lock
;
// Chunk related size
size_t
_medium_chunk_bunch
;
// List of chunks in use by this SpaceManager. Allocations
// List of chunks in use by this SpaceManager. Allocations
// are done from the current chunk. The list is used for deallocating
// are done from the current chunk. The list is used for deallocating
// chunks when the SpaceManager is freed.
// chunks when the SpaceManager is freed.
...
@@ -532,6 +558,7 @@ class SpaceManager : public CHeapObj<mtClass> {
...
@@ -532,6 +558,7 @@ class SpaceManager : public CHeapObj<mtClass> {
static
const
int
_expand_lock_rank
;
static
const
int
_expand_lock_rank
;
static
Mutex
*
const
_expand_lock
;
static
Mutex
*
const
_expand_lock
;
private:
// Accessors
// Accessors
Metachunk
*
chunks_in_use
(
ChunkIndex
index
)
const
{
return
_chunks_in_use
[
index
];
}
Metachunk
*
chunks_in_use
(
ChunkIndex
index
)
const
{
return
_chunks_in_use
[
index
];
}
void
set_chunks_in_use
(
ChunkIndex
index
,
Metachunk
*
v
)
{
_chunks_in_use
[
index
]
=
v
;
}
void
set_chunks_in_use
(
ChunkIndex
index
,
Metachunk
*
v
)
{
_chunks_in_use
[
index
]
=
v
;
}
...
@@ -554,23 +581,37 @@ class SpaceManager : public CHeapObj<mtClass> {
...
@@ -554,23 +581,37 @@ class SpaceManager : public CHeapObj<mtClass> {
Mutex
*
lock
()
const
{
return
_lock
;
}
Mutex
*
lock
()
const
{
return
_lock
;
}
const
char
*
chunk_size_name
(
ChunkIndex
index
)
const
;
protected:
void
initialize
();
public:
public:
SpaceManager
(
Mutex
*
lock
,
VirtualSpaceList
*
vs_list
);
SpaceManager
(
Mutex
*
lock
,
VirtualSpaceList
*
vs_list
);
~
SpaceManager
();
~
SpaceManager
();
enum
ChunkSizes
{
// in words.
enum
ChunkMultiples
{
SmallChunk
=
512
,
MediumChunkMultiple
=
4
MediumChunk
=
8
*
K
,
MediumChunkBunch
=
4
*
MediumChunk
};
};
// Accessors
// Accessors
size_t
specialized_chunk_size
()
{
return
SpecializedChunk
;
}
size_t
small_chunk_size
()
{
return
(
size_t
)
vs_list
()
->
is_class
()
?
ClassSmallChunk
:
SmallChunk
;
}
size_t
medium_chunk_size
()
{
return
(
size_t
)
vs_list
()
->
is_class
()
?
ClassMediumChunk
:
MediumChunk
;
}
size_t
medium_chunk_bunch
()
{
return
medium_chunk_size
()
*
MediumChunkMultiple
;
}
size_t
allocation_total
()
const
{
return
_allocation_total
;
}
size_t
allocation_total
()
const
{
return
_allocation_total
;
}
void
inc_allocation_total
(
size_t
v
)
{
Atomic
::
add_ptr
(
v
,
&
_allocation_total
);
}
void
inc_allocation_total
(
size_t
v
)
{
Atomic
::
add_ptr
(
v
,
&
_allocation_total
);
}
static
bool
is_humongous
(
size_t
word_size
)
{
return
word_size
>
MediumChunk
;
}
bool
is_humongous
(
size_t
word_size
)
{
return
word_size
>
medium_chunk_size
()
;
}
static
Mutex
*
expand_lock
()
{
return
_expand_lock
;
}
static
Mutex
*
expand_lock
()
{
return
_expand_lock
;
}
// Set the sizes for the initial chunks.
void
get_initial_chunk_sizes
(
Metaspace
::
MetaspaceType
type
,
size_t
*
chunk_word_size
,
size_t
*
class_chunk_word_size
);
size_t
sum_capacity_in_chunks_in_use
()
const
;
size_t
sum_capacity_in_chunks_in_use
()
const
;
size_t
sum_used_in_chunks_in_use
()
const
;
size_t
sum_used_in_chunks_in_use
()
const
;
size_t
sum_free_in_chunks_in_use
()
const
;
size_t
sum_free_in_chunks_in_use
()
const
;
...
@@ -580,6 +621,8 @@ class SpaceManager : public CHeapObj<mtClass> {
...
@@ -580,6 +621,8 @@ class SpaceManager : public CHeapObj<mtClass> {
size_t
sum_count_in_chunks_in_use
();
size_t
sum_count_in_chunks_in_use
();
size_t
sum_count_in_chunks_in_use
(
ChunkIndex
i
);
size_t
sum_count_in_chunks_in_use
(
ChunkIndex
i
);
Metachunk
*
get_new_chunk
(
size_t
word_size
,
size_t
grow_chunks_by_words
);
// Block allocation and deallocation.
// Block allocation and deallocation.
// Allocates a block from the current chunk
// Allocates a block from the current chunk
MetaWord
*
allocate
(
size_t
word_size
);
MetaWord
*
allocate
(
size_t
word_size
);
...
@@ -772,8 +815,10 @@ bool VirtualSpaceNode::initialize() {
...
@@ -772,8 +815,10 @@ bool VirtualSpaceNode::initialize() {
return
false
;
return
false
;
}
}
// Commit only 1 page instead of the whole reserved space _rs.size()
// An allocation out of this Virtualspace that is larger
size_t
committed_byte_size
=
os
::
vm_page_size
();
// than an initial commit size can waste that initial committed
// space.
size_t
committed_byte_size
=
0
;
bool
result
=
virtual_space
()
->
initialize
(
_rs
,
committed_byte_size
);
bool
result
=
virtual_space
()
->
initialize
(
_rs
,
committed_byte_size
);
if
(
result
)
{
if
(
result
)
{
set_top
((
MetaWord
*
)
virtual_space
()
->
low
());
set_top
((
MetaWord
*
)
virtual_space
()
->
low
());
...
@@ -799,7 +844,8 @@ void VirtualSpaceNode::print_on(outputStream* st) const {
...
@@ -799,7 +844,8 @@ void VirtualSpaceNode::print_on(outputStream* st) const {
st
->
print_cr
(
" space @ "
PTR_FORMAT
" "
SIZE_FORMAT
"K, %3d%% used "
st
->
print_cr
(
" space @ "
PTR_FORMAT
" "
SIZE_FORMAT
"K, %3d%% used "
"["
PTR_FORMAT
", "
PTR_FORMAT
", "
"["
PTR_FORMAT
", "
PTR_FORMAT
", "
PTR_FORMAT
", "
PTR_FORMAT
")"
,
PTR_FORMAT
", "
PTR_FORMAT
")"
,
vs
,
capacity
/
K
,
used
*
100
/
capacity
,
vs
,
capacity
/
K
,
capacity
==
0
?
0
:
used
*
100
/
capacity
,
bottom
(),
top
(),
end
(),
bottom
(),
top
(),
end
(),
vs
->
high_boundary
());
vs
->
high_boundary
());
}
}
...
@@ -922,7 +968,8 @@ void VirtualSpaceList::link_vs(VirtualSpaceNode* new_entry, size_t vs_word_size)
...
@@ -922,7 +968,8 @@ void VirtualSpaceList::link_vs(VirtualSpaceNode* new_entry, size_t vs_word_size)
}
}
Metachunk
*
VirtualSpaceList
::
get_new_chunk
(
size_t
word_size
,
Metachunk
*
VirtualSpaceList
::
get_new_chunk
(
size_t
word_size
,
size_t
grow_chunks_by_words
)
{
size_t
grow_chunks_by_words
,
size_t
medium_chunk_bunch
)
{
// Get a chunk from the chunk freelist
// Get a chunk from the chunk freelist
Metachunk
*
next
=
chunk_manager
()
->
chunk_freelist_allocate
(
grow_chunks_by_words
);
Metachunk
*
next
=
chunk_manager
()
->
chunk_freelist_allocate
(
grow_chunks_by_words
);
...
@@ -935,8 +982,8 @@ Metachunk* VirtualSpaceList::get_new_chunk(size_t word_size,
...
@@ -935,8 +982,8 @@ Metachunk* VirtualSpaceList::get_new_chunk(size_t word_size,
if
(
next
==
NULL
)
{
if
(
next
==
NULL
)
{
// Not enough room in current virtual space. Try to commit
// Not enough room in current virtual space. Try to commit
// more space.
// more space.
size_t
expand_vs_by_words
=
MAX2
(
(
size_t
)
SpaceManager
::
MediumChunkB
unch
,
size_t
expand_vs_by_words
=
MAX2
(
medium_chunk_b
unch
,
grow_chunks_by_words
);
grow_chunks_by_words
);
size_t
page_size_words
=
os
::
vm_page_size
()
/
BytesPerWord
;
size_t
page_size_words
=
os
::
vm_page_size
()
/
BytesPerWord
;
size_t
aligned_expand_vs_by_words
=
align_size_up
(
expand_vs_by_words
,
size_t
aligned_expand_vs_by_words
=
align_size_up
(
expand_vs_by_words
,
page_size_words
);
page_size_words
);
...
@@ -954,12 +1001,6 @@ Metachunk* VirtualSpaceList::get_new_chunk(size_t word_size,
...
@@ -954,12 +1001,6 @@ Metachunk* VirtualSpaceList::get_new_chunk(size_t word_size,
// Got it. It's on the list now. Get a chunk from it.
// Got it. It's on the list now. Get a chunk from it.
next
=
current_virtual_space
()
->
get_chunk_vs_with_expand
(
grow_chunks_by_words
);
next
=
current_virtual_space
()
->
get_chunk_vs_with_expand
(
grow_chunks_by_words
);
}
}
if
(
TraceMetadataHumongousAllocation
&&
SpaceManager
::
is_humongous
(
word_size
))
{
gclog_or_tty
->
print_cr
(
" aligned_expand_vs_by_words "
PTR_FORMAT
,
aligned_expand_vs_by_words
);
gclog_or_tty
->
print_cr
(
" grow_vs_words "
PTR_FORMAT
,
grow_vs_words
);
}
}
else
{
}
else
{
// Allocation will fail and induce a GC
// Allocation will fail and induce a GC
if
(
TraceMetadataChunkAllocation
&&
Verbose
)
{
if
(
TraceMetadataChunkAllocation
&&
Verbose
)
{
...
@@ -974,9 +1015,20 @@ Metachunk* VirtualSpaceList::get_new_chunk(size_t word_size,
...
@@ -974,9 +1015,20 @@ Metachunk* VirtualSpaceList::get_new_chunk(size_t word_size,
}
}
}
}
assert
(
next
==
NULL
||
(
next
->
next
()
==
NULL
&&
next
->
prev
()
==
NULL
),
"New chunk is still on some list"
);
return
next
;
return
next
;
}
}
Metachunk
*
VirtualSpaceList
::
get_initialization_chunk
(
size_t
chunk_word_size
,
size_t
chunk_bunch
)
{
// Get a chunk from the chunk freelist
Metachunk
*
new_chunk
=
get_new_chunk
(
chunk_word_size
,
chunk_word_size
,
chunk_bunch
);
return
new_chunk
;
}
void
VirtualSpaceList
::
print_on
(
outputStream
*
st
)
const
{
void
VirtualSpaceList
::
print_on
(
outputStream
*
st
)
const
{
if
(
TraceMetadataChunkAllocation
&&
Verbose
)
{
if
(
TraceMetadataChunkAllocation
&&
Verbose
)
{
VirtualSpaceListIterator
iter
(
virtual_space_list
());
VirtualSpaceListIterator
iter
(
virtual_space_list
());
...
@@ -1373,16 +1425,17 @@ size_t ChunkList::sum_list_capacity() {
...
@@ -1373,16 +1425,17 @@ size_t ChunkList::sum_list_capacity() {
void
ChunkList
::
add_at_head
(
Metachunk
*
head
,
Metachunk
*
tail
)
{
void
ChunkList
::
add_at_head
(
Metachunk
*
head
,
Metachunk
*
tail
)
{
assert_lock_strong
(
SpaceManager
::
expand_lock
());
assert_lock_strong
(
SpaceManager
::
expand_lock
());
assert
(
tail
->
next
()
==
NULL
,
"Not the tail"
);
assert
(
head
==
tail
||
tail
->
next
()
==
NULL
,
"Not the tail or the head has already been added to a list"
);
if
(
TraceMetadataChunkAllocation
&&
Verbose
)
{
if
(
TraceMetadataChunkAllocation
&&
Verbose
)
{
tty
->
print
(
"ChunkList::add_at_head
: "
);
gclog_or_tty
->
print
(
"ChunkList::add_at_head(head, tail)
: "
);
Metachunk
*
cur
=
head
;
Metachunk
*
cur
=
head
;
while
(
cur
!=
NULL
)
{
while
(
cur
!=
NULL
)
{
tty
->
print
(
PTR_FORMAT
" ("
SIZE_FORMAT
") "
,
cur
,
cur
->
word_size
());
gclog_or_
tty
->
print
(
PTR_FORMAT
" ("
SIZE_FORMAT
") "
,
cur
,
cur
->
word_size
());
cur
=
cur
->
next
();
cur
=
cur
->
next
();
}
}
tty
->
print_cr
(
""
);
gclog_or_
tty
->
print_cr
(
""
);
}
}
if
(
tail
!=
NULL
)
{
if
(
tail
!=
NULL
)
{
...
@@ -1486,13 +1539,13 @@ void ChunkManager::locked_verify() {
...
@@ -1486,13 +1539,13 @@ void ChunkManager::locked_verify() {
void
ChunkManager
::
locked_print_free_chunks
(
outputStream
*
st
)
{
void
ChunkManager
::
locked_print_free_chunks
(
outputStream
*
st
)
{
assert_lock_strong
(
SpaceManager
::
expand_lock
());
assert_lock_strong
(
SpaceManager
::
expand_lock
());
st
->
print_cr
(
"Free chunk total
0x%x count 0x%x"
,
st
->
print_cr
(
"Free chunk total
"
SIZE_FORMAT
" count "
SIZE_FORMAT
,
_free_chunks_total
,
_free_chunks_count
);
_free_chunks_total
,
_free_chunks_count
);
}
}
void
ChunkManager
::
locked_print_sum_free_chunks
(
outputStream
*
st
)
{
void
ChunkManager
::
locked_print_sum_free_chunks
(
outputStream
*
st
)
{
assert_lock_strong
(
SpaceManager
::
expand_lock
());
assert_lock_strong
(
SpaceManager
::
expand_lock
());
st
->
print_cr
(
"Sum free chunk total
0x%x count 0x%x"
,
st
->
print_cr
(
"Sum free chunk total
"
SIZE_FORMAT
" count "
SIZE_FORMAT
,
sum_free_chunks
(),
sum_free_chunks_count
());
sum_free_chunks
(),
sum_free_chunks_count
());
}
}
ChunkList
*
ChunkManager
::
free_chunks
(
ChunkIndex
index
)
{
ChunkList
*
ChunkManager
::
free_chunks
(
ChunkIndex
index
)
{
...
@@ -1504,7 +1557,7 @@ ChunkList* ChunkManager::free_chunks(ChunkIndex index) {
...
@@ -1504,7 +1557,7 @@ ChunkList* ChunkManager::free_chunks(ChunkIndex index) {
size_t
ChunkManager
::
sum_free_chunks
()
{
size_t
ChunkManager
::
sum_free_chunks
()
{
assert_lock_strong
(
SpaceManager
::
expand_lock
());
assert_lock_strong
(
SpaceManager
::
expand_lock
());
size_t
result
=
0
;
size_t
result
=
0
;
for
(
ChunkIndex
i
=
Small
Index
;
i
<
NumberOfFreeLists
;
i
=
next_chunk_index
(
i
))
{
for
(
ChunkIndex
i
=
Zero
Index
;
i
<
NumberOfFreeLists
;
i
=
next_chunk_index
(
i
))
{
ChunkList
*
list
=
free_chunks
(
i
);
ChunkList
*
list
=
free_chunks
(
i
);
if
(
list
==
NULL
)
{
if
(
list
==
NULL
)
{
...
@@ -1520,7 +1573,7 @@ size_t ChunkManager::sum_free_chunks() {
...
@@ -1520,7 +1573,7 @@ size_t ChunkManager::sum_free_chunks() {
size_t
ChunkManager
::
sum_free_chunks_count
()
{
size_t
ChunkManager
::
sum_free_chunks_count
()
{
assert_lock_strong
(
SpaceManager
::
expand_lock
());
assert_lock_strong
(
SpaceManager
::
expand_lock
());
size_t
count
=
0
;
size_t
count
=
0
;
for
(
ChunkIndex
i
=
Small
Index
;
i
<
NumberOfFreeLists
;
i
=
next_chunk_index
(
i
))
{
for
(
ChunkIndex
i
=
Zero
Index
;
i
<
NumberOfFreeLists
;
i
=
next_chunk_index
(
i
))
{
ChunkList
*
list
=
free_chunks
(
i
);
ChunkList
*
list
=
free_chunks
(
i
);
if
(
list
==
NULL
)
{
if
(
list
==
NULL
)
{
continue
;
continue
;
...
@@ -1532,15 +1585,9 @@ size_t ChunkManager::sum_free_chunks_count() {
...
@@ -1532,15 +1585,9 @@ size_t ChunkManager::sum_free_chunks_count() {
}
}
ChunkList
*
ChunkManager
::
find_free_chunks_list
(
size_t
word_size
)
{
ChunkList
*
ChunkManager
::
find_free_chunks_list
(
size_t
word_size
)
{
switch
(
word_size
)
{
ChunkIndex
index
=
list_index
(
word_size
);
case
SpaceManager
::
SmallChunk
:
assert
(
index
<
HumongousIndex
,
"No humongous list"
);
return
&
_free_chunks
[
0
];
return
free_chunks
(
index
);
case
SpaceManager
::
MediumChunk
:
return
&
_free_chunks
[
1
];
default:
assert
(
word_size
>
SpaceManager
::
MediumChunk
,
"List inconsistency"
);
return
&
_free_chunks
[
2
];
}
}
}
void
ChunkManager
::
free_chunks_put
(
Metachunk
*
chunk
)
{
void
ChunkManager
::
free_chunks_put
(
Metachunk
*
chunk
)
{
...
@@ -1574,7 +1621,7 @@ Metachunk* ChunkManager::free_chunks_get(size_t word_size) {
...
@@ -1574,7 +1621,7 @@ Metachunk* ChunkManager::free_chunks_get(size_t word_size) {
slow_locked_verify
();
slow_locked_verify
();
Metachunk
*
chunk
=
NULL
;
Metachunk
*
chunk
=
NULL
;
if
(
!
SpaceManager
::
is_humongous
(
word_size
)
)
{
if
(
list_index
(
word_size
)
!=
HumongousIndex
)
{
ChunkList
*
free_list
=
find_free_chunks_list
(
word_size
);
ChunkList
*
free_list
=
find_free_chunks_list
(
word_size
);
assert
(
free_list
!=
NULL
,
"Sanity check"
);
assert
(
free_list
!=
NULL
,
"Sanity check"
);
...
@@ -1587,8 +1634,8 @@ Metachunk* ChunkManager::free_chunks_get(size_t word_size) {
...
@@ -1587,8 +1634,8 @@ Metachunk* ChunkManager::free_chunks_get(size_t word_size) {
// Remove the chunk as the head of the list.
// Remove the chunk as the head of the list.
free_list
->
set_head
(
chunk
->
next
());
free_list
->
set_head
(
chunk
->
next
());
chunk
->
set_next
(
NULL
);
// Chunk
has been
removed from the chunks free list.
// Chunk
is being
removed from the chunks free list.
dec_free_chunks_total
(
chunk
->
capacity_word_size
());
dec_free_chunks_total
(
chunk
->
capacity_word_size
());
if
(
TraceMetadataChunkAllocation
&&
Verbose
)
{
if
(
TraceMetadataChunkAllocation
&&
Verbose
)
{
...
@@ -1614,8 +1661,14 @@ Metachunk* ChunkManager::free_chunks_get(size_t word_size) {
...
@@ -1614,8 +1661,14 @@ Metachunk* ChunkManager::free_chunks_get(size_t word_size) {
#ifdef ASSERT
#ifdef ASSERT
chunk
->
set_is_free
(
false
);
chunk
->
set_is_free
(
false
);
#endif
#endif
}
else
{
return
NULL
;
}
}
}
}
// Remove it from the links to this freelist
chunk
->
set_next
(
NULL
);
chunk
->
set_prev
(
NULL
);
slow_locked_verify
();
slow_locked_verify
();
return
chunk
;
return
chunk
;
}
}
...
@@ -1630,13 +1683,20 @@ Metachunk* ChunkManager::chunk_freelist_allocate(size_t word_size) {
...
@@ -1630,13 +1683,20 @@ Metachunk* ChunkManager::chunk_freelist_allocate(size_t word_size) {
return
NULL
;
return
NULL
;
}
}
assert
(
word_size
<=
chunk
->
word_size
(
)
||
assert
(
(
word_size
<=
chunk
->
word_size
()
)
||
SpaceManager
::
is_humongous
(
chunk
->
word_size
()
),
list_index
(
chunk
->
word_size
()
==
HumongousIndex
),
"Non-humongous variable sized chunk"
);
"Non-humongous variable sized chunk"
);
if
(
TraceMetadataChunkAllocation
)
{
if
(
TraceMetadataChunkAllocation
)
{
tty
->
print
(
"ChunkManager::chunk_freelist_allocate: chunk "
size_t
list_count
;
PTR_FORMAT
" size "
SIZE_FORMAT
" "
,
if
(
list_index
(
word_size
)
<
HumongousIndex
)
{
chunk
,
chunk
->
word_size
());
ChunkList
*
list
=
find_free_chunks_list
(
word_size
);
list_count
=
list
->
sum_list_count
();
}
else
{
list_count
=
humongous_dictionary
()
->
total_count
();
}
tty
->
print
(
"ChunkManager::chunk_freelist_allocate: "
PTR_FORMAT
" chunk "
PTR_FORMAT
" size "
SIZE_FORMAT
" count "
SIZE_FORMAT
" "
,
this
,
chunk
,
chunk
->
word_size
(),
list_count
);
locked_print_free_chunks
(
tty
);
locked_print_free_chunks
(
tty
);
}
}
...
@@ -1651,10 +1711,42 @@ void ChunkManager::print_on(outputStream* out) {
...
@@ -1651,10 +1711,42 @@ void ChunkManager::print_on(outputStream* out) {
// SpaceManager methods
// SpaceManager methods
void
SpaceManager
::
get_initial_chunk_sizes
(
Metaspace
::
MetaspaceType
type
,
size_t
*
chunk_word_size
,
size_t
*
class_chunk_word_size
)
{
switch
(
type
)
{
case
Metaspace
::
BootMetaspaceType
:
*
chunk_word_size
=
Metaspace
::
first_chunk_word_size
();
*
class_chunk_word_size
=
Metaspace
::
first_class_chunk_word_size
();
break
;
case
Metaspace
::
ROMetaspaceType
:
*
chunk_word_size
=
SharedReadOnlySize
/
wordSize
;
*
class_chunk_word_size
=
ClassSpecializedChunk
;
break
;
case
Metaspace
::
ReadWriteMetaspaceType
:
*
chunk_word_size
=
SharedReadWriteSize
/
wordSize
;
*
class_chunk_word_size
=
ClassSpecializedChunk
;
break
;
case
Metaspace
::
AnonymousMetaspaceType
:
case
Metaspace
::
ReflectionMetaspaceType
:
*
chunk_word_size
=
SpecializedChunk
;
*
class_chunk_word_size
=
ClassSpecializedChunk
;
break
;
default:
*
chunk_word_size
=
SmallChunk
;
*
class_chunk_word_size
=
ClassSmallChunk
;
break
;
}
assert
(
chunk_word_size
!=
0
&&
class_chunk_word_size
!=
0
,
err_msg
(
"Initial chunks sizes bad: data "
SIZE_FORMAT
" class "
SIZE_FORMAT
,
chunk_word_size
,
class_chunk_word_size
));
}
size_t
SpaceManager
::
sum_free_in_chunks_in_use
()
const
{
size_t
SpaceManager
::
sum_free_in_chunks_in_use
()
const
{
MutexLockerEx
cl
(
lock
(),
Mutex
::
_no_safepoint_check_flag
);
MutexLockerEx
cl
(
lock
(),
Mutex
::
_no_safepoint_check_flag
);
size_t
free
=
0
;
size_t
free
=
0
;
for
(
ChunkIndex
i
=
Small
Index
;
i
<
NumberOfInUseLists
;
i
=
next_chunk_index
(
i
))
{
for
(
ChunkIndex
i
=
Zero
Index
;
i
<
NumberOfInUseLists
;
i
=
next_chunk_index
(
i
))
{
Metachunk
*
chunk
=
chunks_in_use
(
i
);
Metachunk
*
chunk
=
chunks_in_use
(
i
);
while
(
chunk
!=
NULL
)
{
while
(
chunk
!=
NULL
)
{
free
+=
chunk
->
free_word_size
();
free
+=
chunk
->
free_word_size
();
...
@@ -1667,9 +1759,7 @@ size_t SpaceManager::sum_free_in_chunks_in_use() const {
...
@@ -1667,9 +1759,7 @@ size_t SpaceManager::sum_free_in_chunks_in_use() const {
size_t
SpaceManager
::
sum_waste_in_chunks_in_use
()
const
{
size_t
SpaceManager
::
sum_waste_in_chunks_in_use
()
const
{
MutexLockerEx
cl
(
lock
(),
Mutex
::
_no_safepoint_check_flag
);
MutexLockerEx
cl
(
lock
(),
Mutex
::
_no_safepoint_check_flag
);
size_t
result
=
0
;
size_t
result
=
0
;
for
(
ChunkIndex
i
=
SmallIndex
;
i
<
NumberOfInUseLists
;
i
=
next_chunk_index
(
i
))
{
for
(
ChunkIndex
i
=
ZeroIndex
;
i
<
NumberOfInUseLists
;
i
=
next_chunk_index
(
i
))
{
result
+=
sum_waste_in_chunks_in_use
(
i
);
result
+=
sum_waste_in_chunks_in_use
(
i
);
}
}
...
@@ -1678,7 +1768,6 @@ size_t SpaceManager::sum_waste_in_chunks_in_use() const {
...
@@ -1678,7 +1768,6 @@ size_t SpaceManager::sum_waste_in_chunks_in_use() const {
size_t
SpaceManager
::
sum_waste_in_chunks_in_use
(
ChunkIndex
index
)
const
{
size_t
SpaceManager
::
sum_waste_in_chunks_in_use
(
ChunkIndex
index
)
const
{
size_t
result
=
0
;
size_t
result
=
0
;
size_t
count
=
0
;
Metachunk
*
chunk
=
chunks_in_use
(
index
);
Metachunk
*
chunk
=
chunks_in_use
(
index
);
// Count the free space in all the chunk but not the
// Count the free space in all the chunk but not the
// current chunk from which allocations are still being done.
// current chunk from which allocations are still being done.
...
@@ -1688,7 +1777,6 @@ size_t SpaceManager::sum_waste_in_chunks_in_use(ChunkIndex index) const {
...
@@ -1688,7 +1777,6 @@ size_t SpaceManager::sum_waste_in_chunks_in_use(ChunkIndex index) const {
result
+=
chunk
->
free_word_size
();
result
+=
chunk
->
free_word_size
();
prev
=
chunk
;
prev
=
chunk
;
chunk
=
chunk
->
next
();
chunk
=
chunk
->
next
();
count
++
;
}
}
}
}
return
result
;
return
result
;
...
@@ -1697,7 +1785,7 @@ size_t SpaceManager::sum_waste_in_chunks_in_use(ChunkIndex index) const {
...
@@ -1697,7 +1785,7 @@ size_t SpaceManager::sum_waste_in_chunks_in_use(ChunkIndex index) const {
size_t
SpaceManager
::
sum_capacity_in_chunks_in_use
()
const
{
size_t
SpaceManager
::
sum_capacity_in_chunks_in_use
()
const
{
MutexLockerEx
cl
(
lock
(),
Mutex
::
_no_safepoint_check_flag
);
MutexLockerEx
cl
(
lock
(),
Mutex
::
_no_safepoint_check_flag
);
size_t
sum
=
0
;
size_t
sum
=
0
;
for
(
ChunkIndex
i
=
Small
Index
;
i
<
NumberOfInUseLists
;
i
=
next_chunk_index
(
i
))
{
for
(
ChunkIndex
i
=
Zero
Index
;
i
<
NumberOfInUseLists
;
i
=
next_chunk_index
(
i
))
{
Metachunk
*
chunk
=
chunks_in_use
(
i
);
Metachunk
*
chunk
=
chunks_in_use
(
i
);
while
(
chunk
!=
NULL
)
{
while
(
chunk
!=
NULL
)
{
// Just changed this sum += chunk->capacity_word_size();
// Just changed this sum += chunk->capacity_word_size();
...
@@ -1711,7 +1799,7 @@ size_t SpaceManager::sum_capacity_in_chunks_in_use() const {
...
@@ -1711,7 +1799,7 @@ size_t SpaceManager::sum_capacity_in_chunks_in_use() const {
size_t
SpaceManager
::
sum_count_in_chunks_in_use
()
{
size_t
SpaceManager
::
sum_count_in_chunks_in_use
()
{
size_t
count
=
0
;
size_t
count
=
0
;
for
(
ChunkIndex
i
=
Small
Index
;
i
<
NumberOfInUseLists
;
i
=
next_chunk_index
(
i
))
{
for
(
ChunkIndex
i
=
Zero
Index
;
i
<
NumberOfInUseLists
;
i
=
next_chunk_index
(
i
))
{
count
=
count
+
sum_count_in_chunks_in_use
(
i
);
count
=
count
+
sum_count_in_chunks_in_use
(
i
);
}
}
...
@@ -1732,7 +1820,7 @@ size_t SpaceManager::sum_count_in_chunks_in_use(ChunkIndex i) {
...
@@ -1732,7 +1820,7 @@ size_t SpaceManager::sum_count_in_chunks_in_use(ChunkIndex i) {
size_t
SpaceManager
::
sum_used_in_chunks_in_use
()
const
{
size_t
SpaceManager
::
sum_used_in_chunks_in_use
()
const
{
MutexLockerEx
cl
(
lock
(),
Mutex
::
_no_safepoint_check_flag
);
MutexLockerEx
cl
(
lock
(),
Mutex
::
_no_safepoint_check_flag
);
size_t
used
=
0
;
size_t
used
=
0
;
for
(
ChunkIndex
i
=
Small
Index
;
i
<
NumberOfInUseLists
;
i
=
next_chunk_index
(
i
))
{
for
(
ChunkIndex
i
=
Zero
Index
;
i
<
NumberOfInUseLists
;
i
=
next_chunk_index
(
i
))
{
Metachunk
*
chunk
=
chunks_in_use
(
i
);
Metachunk
*
chunk
=
chunks_in_use
(
i
);
while
(
chunk
!=
NULL
)
{
while
(
chunk
!=
NULL
)
{
used
+=
chunk
->
used_word_size
();
used
+=
chunk
->
used_word_size
();
...
@@ -1744,19 +1832,17 @@ size_t SpaceManager::sum_used_in_chunks_in_use() const {
...
@@ -1744,19 +1832,17 @@ size_t SpaceManager::sum_used_in_chunks_in_use() const {
void
SpaceManager
::
locked_print_chunks_in_use_on
(
outputStream
*
st
)
const
{
void
SpaceManager
::
locked_print_chunks_in_use_on
(
outputStream
*
st
)
const
{
Metachunk
*
small_chunk
=
chunks_in_use
(
SmallIndex
);
for
(
ChunkIndex
i
=
ZeroIndex
;
i
<
NumberOfInUseLists
;
i
=
next_chunk_index
(
i
))
{
st
->
print_cr
(
"SpaceManager: small chunk "
PTR_FORMAT
Metachunk
*
chunk
=
chunks_in_use
(
i
);
" free "
SIZE_FORMAT
,
st
->
print
(
"SpaceManager: %s "
PTR_FORMAT
,
small_chunk
,
chunk_size_name
(
i
),
chunk
);
small_chunk
->
free_word_size
());
if
(
chunk
!=
NULL
)
{
st
->
print_cr
(
" free "
SIZE_FORMAT
,
Metachunk
*
medium_chunk
=
chunks_in_use
(
MediumIndex
);
chunk
->
free_word_size
());
st
->
print
(
"medium chunk "
PTR_FORMAT
,
medium_chunk
);
}
else
{
Metachunk
*
tail
=
current_chunk
();
st
->
print_cr
(
""
);
st
->
print_cr
(
" current chunk "
PTR_FORMAT
,
tail
);
}
}
Metachunk
*
head
=
chunks_in_use
(
HumongousIndex
);
st
->
print_cr
(
"humongous chunk "
PTR_FORMAT
,
head
);
vs_list
()
->
chunk_manager
()
->
locked_print_free_chunks
(
st
);
vs_list
()
->
chunk_manager
()
->
locked_print_free_chunks
(
st
);
vs_list
()
->
chunk_manager
()
->
locked_print_sum_free_chunks
(
st
);
vs_list
()
->
chunk_manager
()
->
locked_print_sum_free_chunks
(
st
);
...
@@ -1772,18 +1858,28 @@ size_t SpaceManager::calc_chunk_size(size_t word_size) {
...
@@ -1772,18 +1858,28 @@ size_t SpaceManager::calc_chunk_size(size_t word_size) {
if
(
chunks_in_use
(
MediumIndex
)
==
NULL
&&
if
(
chunks_in_use
(
MediumIndex
)
==
NULL
&&
(
!
has_small_chunk_limit
()
||
(
!
has_small_chunk_limit
()
||
sum_count_in_chunks_in_use
(
SmallIndex
)
<
_small_chunk_limit
))
{
sum_count_in_chunks_in_use
(
SmallIndex
)
<
_small_chunk_limit
))
{
chunk_word_size
=
(
size_t
)
SpaceManager
::
SmallChunk
;
chunk_word_size
=
(
size_t
)
small_chunk_size
()
;
if
(
word_size
+
Metachunk
::
overhead
()
>
SpaceManager
::
SmallChunk
)
{
if
(
word_size
+
Metachunk
::
overhead
()
>
small_chunk_size
()
)
{
chunk_word_size
=
MediumChunk
;
chunk_word_size
=
medium_chunk_size
()
;
}
}
}
else
{
}
else
{
chunk_word_size
=
MediumChunk
;
chunk_word_size
=
medium_chunk_size
()
;
}
}
// Might still need a humongous chunk
// Might still need a humongous chunk. Enforce an
// eight word granularity to facilitate reuse (some
// wastage but better chance of reuse).
size_t
if_humongous_sized_chunk
=
align_size_up
(
word_size
+
Metachunk
::
overhead
(),
HumongousChunkGranularity
);
chunk_word_size
=
chunk_word_size
=
MAX2
((
size_t
)
chunk_word_size
,
word_size
+
Metachunk
::
overhead
()
);
MAX2
((
size_t
)
chunk_word_size
,
if_humongous_sized_chunk
);
assert
(
!
SpaceManager
::
is_humongous
(
word_size
)
||
chunk_word_size
==
if_humongous_sized_chunk
,
err_msg
(
"Size calculation is wrong, word_size "
SIZE_FORMAT
" chunk_word_size "
SIZE_FORMAT
,
word_size
,
chunk_word_size
));
if
(
TraceMetadataHumongousAllocation
&&
if
(
TraceMetadataHumongousAllocation
&&
SpaceManager
::
is_humongous
(
word_size
))
{
SpaceManager
::
is_humongous
(
word_size
))
{
gclog_or_tty
->
print_cr
(
"Metadata humongous allocation:"
);
gclog_or_tty
->
print_cr
(
"Metadata humongous allocation:"
);
...
@@ -1805,15 +1901,21 @@ MetaWord* SpaceManager::grow_and_allocate(size_t word_size) {
...
@@ -1805,15 +1901,21 @@ MetaWord* SpaceManager::grow_and_allocate(size_t word_size) {
MutexLockerEx
cl
(
SpaceManager
::
expand_lock
(),
Mutex
::
_no_safepoint_check_flag
);
MutexLockerEx
cl
(
SpaceManager
::
expand_lock
(),
Mutex
::
_no_safepoint_check_flag
);
if
(
TraceMetadataChunkAllocation
&&
Verbose
)
{
if
(
TraceMetadataChunkAllocation
&&
Verbose
)
{
size_t
words_left
=
0
;
size_t
words_used
=
0
;
if
(
current_chunk
()
!=
NULL
)
{
words_left
=
current_chunk
()
->
free_word_size
();
words_used
=
current_chunk
()
->
used_word_size
();
}
gclog_or_tty
->
print_cr
(
"SpaceManager::grow_and_allocate for "
SIZE_FORMAT
gclog_or_tty
->
print_cr
(
"SpaceManager::grow_and_allocate for "
SIZE_FORMAT
" words "
SIZE_FORMAT
"
space left"
,
" words "
SIZE_FORMAT
"
words used "
SIZE_FORMAT
word_size
,
current_chunk
()
!=
NULL
?
" words left"
,
current_chunk
()
->
free_word_size
()
:
0
);
word_size
,
words_used
,
words_left
);
}
}
// Get another chunk out of the virtual space
// Get another chunk out of the virtual space
size_t
grow_chunks_by_words
=
calc_chunk_size
(
word_size
);
size_t
grow_chunks_by_words
=
calc_chunk_size
(
word_size
);
Metachunk
*
next
=
vs_list
()
->
get_new_chunk
(
word_size
,
grow_chunks_by_words
);
Metachunk
*
next
=
get_new_chunk
(
word_size
,
grow_chunks_by_words
);
// If a chunk was available, add it to the in-use chunk list
// If a chunk was available, add it to the in-use chunk list
// and do an allocation from it.
// and do an allocation from it.
...
@@ -1828,7 +1930,7 @@ MetaWord* SpaceManager::grow_and_allocate(size_t word_size) {
...
@@ -1828,7 +1930,7 @@ MetaWord* SpaceManager::grow_and_allocate(size_t word_size) {
void
SpaceManager
::
print_on
(
outputStream
*
st
)
const
{
void
SpaceManager
::
print_on
(
outputStream
*
st
)
const
{
for
(
ChunkIndex
i
=
Small
Index
;
for
(
ChunkIndex
i
=
Zero
Index
;
i
<
NumberOfInUseLists
;
i
<
NumberOfInUseLists
;
i
=
next_chunk_index
(
i
)
)
{
i
=
next_chunk_index
(
i
)
)
{
st
->
print_cr
(
" chunks_in_use "
PTR_FORMAT
" chunk size "
PTR_FORMAT
,
st
->
print_cr
(
" chunks_in_use "
PTR_FORMAT
" chunk size "
PTR_FORMAT
,
...
@@ -1847,12 +1949,18 @@ void SpaceManager::print_on(outputStream* st) const {
...
@@ -1847,12 +1949,18 @@ void SpaceManager::print_on(outputStream* st) const {
}
}
}
}
SpaceManager
::
SpaceManager
(
Mutex
*
lock
,
VirtualSpaceList
*
vs_list
)
:
SpaceManager
::
SpaceManager
(
Mutex
*
lock
,
VirtualSpaceList
*
vs_list
)
:
_vs_list
(
vs_list
),
_vs_list
(
vs_list
),
_allocation_total
(
0
),
_allocation_total
(
0
),
_lock
(
lock
)
{
_lock
(
lock
)
{
initialize
();
}
void
SpaceManager
::
initialize
()
{
Metadebug
::
init_allocation_fail_alot_count
();
Metadebug
::
init_allocation_fail_alot_count
();
for
(
ChunkIndex
i
=
Small
Index
;
i
<
NumberOfInUseLists
;
i
=
next_chunk_index
(
i
))
{
for
(
ChunkIndex
i
=
Zero
Index
;
i
<
NumberOfInUseLists
;
i
=
next_chunk_index
(
i
))
{
_chunks_in_use
[
i
]
=
NULL
;
_chunks_in_use
[
i
]
=
NULL
;
}
}
_current_chunk
=
NULL
;
_current_chunk
=
NULL
;
...
@@ -1885,30 +1993,37 @@ SpaceManager::~SpaceManager() {
...
@@ -1885,30 +1993,37 @@ SpaceManager::~SpaceManager() {
// Add all the chunks in use by this space manager
// Add all the chunks in use by this space manager
// to the global list of free chunks.
// to the global list of free chunks.
// Small chunks. There is one _current_chunk for each
// Follow each list of chunks-in-use and add them to the
// Metaspace. It could point to a small or medium chunk.
// free lists. Each list is NULL terminated.
// Rather than determine which it is, follow the list of
// small chunks to add them to the free list
for
(
ChunkIndex
i
=
ZeroIndex
;
i
<
HumongousIndex
;
i
=
next_chunk_index
(
i
))
{
Metachunk
*
small_chunk
=
chunks_in_use
(
SmallIndex
);
if
(
TraceMetadataChunkAllocation
&&
Verbose
)
{
chunk_manager
->
free_small_chunks
()
->
add_at_head
(
small_chunk
);
gclog_or_tty
->
print_cr
(
"returned %d %s chunks to freelist"
,
set_chunks_in_use
(
SmallIndex
,
NULL
);
sum_count_in_chunks_in_use
(
i
),
chunk_size_name
(
i
));
// After the small chunk are the medium chunks
}
Metachunk
*
medium_chunk
=
chunks_in_use
(
MediumIndex
);
Metachunk
*
chunks
=
chunks_in_use
(
i
);
assert
(
medium_chunk
==
NULL
||
chunk_manager
->
free_chunks
(
i
)
->
add_at_head
(
chunks
);
medium_chunk
->
word_size
()
==
MediumChunk
,
set_chunks_in_use
(
i
,
NULL
);
"Chunk is on the wrong list"
);
if
(
TraceMetadataChunkAllocation
&&
Verbose
)
{
gclog_or_tty
->
print_cr
(
"updated freelist count %d %s"
,
if
(
medium_chunk
!=
NULL
)
{
chunk_manager
->
free_chunks
(
i
)
->
sum_list_count
(),
Metachunk
*
head
=
medium_chunk
;
chunk_size_name
(
i
));
// If there is a medium chunk then the _current_chunk can only
}
// point to the last medium chunk.
assert
(
i
!=
HumongousIndex
,
"Humongous chunks are handled explicitly later"
);
Metachunk
*
tail
=
current_chunk
();
chunk_manager
->
free_medium_chunks
()
->
add_at_head
(
head
,
tail
);
set_chunks_in_use
(
MediumIndex
,
NULL
);
}
}
// The medium chunk case may be optimized by passing the head and
// tail of the medium chunk list to add_at_head(). The tail is often
// the current chunk but there are probably exceptions.
// Humongous chunks
// Humongous chunks
if
(
TraceMetadataChunkAllocation
&&
Verbose
)
{
gclog_or_tty
->
print_cr
(
"returned %d %s humongous chunks to dictionary"
,
sum_count_in_chunks_in_use
(
HumongousIndex
),
chunk_size_name
(
HumongousIndex
));
gclog_or_tty
->
print
(
"Humongous chunk dictionary: "
);
}
// Humongous chunks are never the current chunk.
// Humongous chunks are never the current chunk.
Metachunk
*
humongous_chunks
=
chunks_in_use
(
HumongousIndex
);
Metachunk
*
humongous_chunks
=
chunks_in_use
(
HumongousIndex
);
...
@@ -1916,14 +2031,65 @@ SpaceManager::~SpaceManager() {
...
@@ -1916,14 +2031,65 @@ SpaceManager::~SpaceManager() {
#ifdef ASSERT
#ifdef ASSERT
humongous_chunks
->
set_is_free
(
true
);
humongous_chunks
->
set_is_free
(
true
);
#endif
#endif
if
(
TraceMetadataChunkAllocation
&&
Verbose
)
{
gclog_or_tty
->
print
(
PTR_FORMAT
" ("
SIZE_FORMAT
") "
,
humongous_chunks
,
humongous_chunks
->
word_size
());
}
assert
(
humongous_chunks
->
word_size
()
==
(
size_t
)
align_size_up
(
humongous_chunks
->
word_size
(),
HumongousChunkGranularity
),
err_msg
(
"Humongous chunk size is wrong: word size "
SIZE_FORMAT
" granularity "
SIZE_FORMAT
,
humongous_chunks
->
word_size
(),
HumongousChunkGranularity
));
Metachunk
*
next_humongous_chunks
=
humongous_chunks
->
next
();
Metachunk
*
next_humongous_chunks
=
humongous_chunks
->
next
();
chunk_manager
->
humongous_dictionary
()
->
return_chunk
(
humongous_chunks
);
chunk_manager
->
humongous_dictionary
()
->
return_chunk
(
humongous_chunks
);
humongous_chunks
=
next_humongous_chunks
;
humongous_chunks
=
next_humongous_chunks
;
}
}
if
(
TraceMetadataChunkAllocation
&&
Verbose
)
{
gclog_or_tty
->
print_cr
(
""
);
gclog_or_tty
->
print_cr
(
"updated dictionary count %d %s"
,
chunk_manager
->
humongous_dictionary
()
->
total_count
(),
chunk_size_name
(
HumongousIndex
));
}
set_chunks_in_use
(
HumongousIndex
,
NULL
);
set_chunks_in_use
(
HumongousIndex
,
NULL
);
chunk_manager
->
slow_locked_verify
();
chunk_manager
->
slow_locked_verify
();
}
}
const
char
*
SpaceManager
::
chunk_size_name
(
ChunkIndex
index
)
const
{
switch
(
index
)
{
case
SpecializedIndex
:
return
"Specialized"
;
case
SmallIndex
:
return
"Small"
;
case
MediumIndex
:
return
"Medium"
;
case
HumongousIndex
:
return
"Humongous"
;
default:
return
NULL
;
}
}
ChunkIndex
ChunkManager
::
list_index
(
size_t
size
)
{
switch
(
size
)
{
case
SpecializedChunk
:
assert
(
SpecializedChunk
==
ClassSpecializedChunk
,
"Need branch for ClassSpecializedChunk"
);
return
SpecializedIndex
;
case
SmallChunk
:
case
ClassSmallChunk
:
return
SmallIndex
;
case
MediumChunk
:
case
ClassMediumChunk
:
return
MediumIndex
;
default:
assert
(
size
>
MediumChunk
&&
size
>
ClassMediumChunk
,
"Not a humongous chunk"
);
return
HumongousIndex
;
}
}
void
SpaceManager
::
deallocate
(
MetaWord
*
p
,
size_t
word_size
)
{
void
SpaceManager
::
deallocate
(
MetaWord
*
p
,
size_t
word_size
)
{
assert_lock_strong
(
_lock
);
assert_lock_strong
(
_lock
);
size_t
min_size
=
TreeChunk
<
Metablock
,
FreeList
>::
min_size
();
size_t
min_size
=
TreeChunk
<
Metablock
,
FreeList
>::
min_size
();
...
@@ -1942,52 +2108,13 @@ void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) {
...
@@ -1942,52 +2108,13 @@ void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) {
// Find the correct list and and set the current
// Find the correct list and and set the current
// chunk for that list.
// chunk for that list.
switch
(
new_chunk
->
word_size
())
{
ChunkIndex
index
=
ChunkManager
::
list_index
(
new_chunk
->
word_size
());
case
SpaceManager
::
SmallChunk
:
if
(
chunks_in_use
(
SmallIndex
)
==
NULL
)
{
// First chunk to add to the list
set_chunks_in_use
(
SmallIndex
,
new_chunk
);
}
else
{
assert
(
current_chunk
()
->
word_size
()
==
SpaceManager
::
SmallChunk
,
err_msg
(
"Incorrect mix of sizes in chunk list "
SIZE_FORMAT
" new chunk "
SIZE_FORMAT
,
current_chunk
()
->
word_size
(),
new_chunk
->
word_size
()));
current_chunk
()
->
set_next
(
new_chunk
);
}
// Make current chunk
set_current_chunk
(
new_chunk
);
break
;
case
SpaceManager
::
MediumChunk
:
if
(
chunks_in_use
(
MediumIndex
)
==
NULL
)
{
// About to add the first medium chunk so teminate the
// small chunk list. In general once medium chunks are
// being added, we're past the need for small chunks.
if
(
current_chunk
()
!=
NULL
)
{
// Only a small chunk or the initial chunk could be
// the current chunk if this is the first medium chunk.
assert
(
current_chunk
()
->
word_size
()
==
SpaceManager
::
SmallChunk
||
chunks_in_use
(
SmallIndex
)
==
NULL
,
err_msg
(
"Should be a small chunk or initial chunk, current chunk "
SIZE_FORMAT
" new chunk "
SIZE_FORMAT
,
current_chunk
()
->
word_size
(),
new_chunk
->
word_size
()));
current_chunk
()
->
set_next
(
NULL
);
}
// First chunk to add to the list
set_chunks_in_use
(
MediumIndex
,
new_chunk
);
}
else
{
if
(
index
!=
HumongousIndex
)
{
// As a minimum the first medium chunk added would
// have become the _current_chunk
// so the _current_chunk has to be non-NULL here
// (although not necessarily still the first medium chunk).
assert
(
current_chunk
()
->
word_size
()
==
SpaceManager
::
MediumChunk
,
"A medium chunk should the current chunk"
);
current_chunk
()
->
set_next
(
new_chunk
);
}
// Make current chunk
set_current_chunk
(
new_chunk
);
set_current_chunk
(
new_chunk
);
break
;
new_chunk
->
set_next
(
chunks_in_use
(
index
));
default:
{
set_chunks_in_use
(
index
,
new_chunk
);
}
else
{
// For null class loader data and DumpSharedSpaces, the first chunk isn't
// For null class loader data and DumpSharedSpaces, the first chunk isn't
// small, so small will be null. Link this first chunk as the current
// small, so small will be null. Link this first chunk as the current
// chunk.
// chunk.
...
@@ -2004,7 +2131,6 @@ void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) {
...
@@ -2004,7 +2131,6 @@ void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) {
assert
(
new_chunk
->
word_size
()
>
MediumChunk
,
"List inconsistency"
);
assert
(
new_chunk
->
word_size
()
>
MediumChunk
,
"List inconsistency"
);
}
}
}
assert
(
new_chunk
->
is_empty
(),
"Not ready for reuse"
);
assert
(
new_chunk
->
is_empty
(),
"Not ready for reuse"
);
if
(
TraceMetadataChunkAllocation
&&
Verbose
)
{
if
(
TraceMetadataChunkAllocation
&&
Verbose
)
{
...
@@ -2015,6 +2141,22 @@ void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) {
...
@@ -2015,6 +2141,22 @@ void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) {
}
}
}
}
Metachunk
*
SpaceManager
::
get_new_chunk
(
size_t
word_size
,
size_t
grow_chunks_by_words
)
{
Metachunk
*
next
=
vs_list
()
->
get_new_chunk
(
word_size
,
grow_chunks_by_words
,
medium_chunk_bunch
());
if
(
TraceMetadataHumongousAllocation
&&
SpaceManager
::
is_humongous
(
next
->
word_size
()))
{
gclog_or_tty
->
print_cr
(
" new humongous chunk word size "
PTR_FORMAT
,
next
->
word_size
());
}
return
next
;
}
MetaWord
*
SpaceManager
::
allocate
(
size_t
word_size
)
{
MetaWord
*
SpaceManager
::
allocate
(
size_t
word_size
)
{
MutexLockerEx
cl
(
lock
(),
Mutex
::
_no_safepoint_check_flag
);
MutexLockerEx
cl
(
lock
(),
Mutex
::
_no_safepoint_check_flag
);
...
@@ -2090,12 +2232,7 @@ void SpaceManager::verify() {
...
@@ -2090,12 +2232,7 @@ void SpaceManager::verify() {
// verfication of chunks does not work since
// verfication of chunks does not work since
// being in the dictionary alters a chunk.
// being in the dictionary alters a chunk.
if
(
block_freelists
()
->
total_size
()
==
0
)
{
if
(
block_freelists
()
->
total_size
()
==
0
)
{
// Skip the small chunks because their next link points to
for
(
ChunkIndex
i
=
ZeroIndex
;
i
<
NumberOfInUseLists
;
i
=
next_chunk_index
(
i
))
{
// medium chunks. This is because the small chunk is the
// current chunk (for allocations) until it is full and the
// the addition of the next chunk does not NULL the next
// like of the small chunk.
for
(
ChunkIndex
i
=
MediumIndex
;
i
<
NumberOfInUseLists
;
i
=
next_chunk_index
(
i
))
{
Metachunk
*
curr
=
chunks_in_use
(
i
);
Metachunk
*
curr
=
chunks_in_use
(
i
);
while
(
curr
!=
NULL
)
{
while
(
curr
!=
NULL
)
{
curr
->
verify
();
curr
->
verify
();
...
@@ -2108,15 +2245,15 @@ void SpaceManager::verify() {
...
@@ -2108,15 +2245,15 @@ void SpaceManager::verify() {
void
SpaceManager
::
verify_chunk_size
(
Metachunk
*
chunk
)
{
void
SpaceManager
::
verify_chunk_size
(
Metachunk
*
chunk
)
{
assert
(
is_humongous
(
chunk
->
word_size
())
||
assert
(
is_humongous
(
chunk
->
word_size
())
||
chunk
->
word_size
()
==
MediumChunk
||
chunk
->
word_size
()
==
medium_chunk_size
()
||
chunk
->
word_size
()
==
SmallChunk
,
chunk
->
word_size
()
==
small_chunk_size
()
||
chunk
->
word_size
()
==
specialized_chunk_size
(),
"Chunk size is wrong"
);
"Chunk size is wrong"
);
return
;
return
;
}
}
#ifdef ASSERT
#ifdef ASSERT
void
SpaceManager
::
verify_allocation_total
()
{
void
SpaceManager
::
verify_allocation_total
()
{
#if 0
// Verification is only guaranteed at a safepoint.
// Verification is only guaranteed at a safepoint.
if
(
SafepointSynchronize
::
is_at_safepoint
())
{
if
(
SafepointSynchronize
::
is_at_safepoint
())
{
gclog_or_tty
->
print_cr
(
"Chunk "
PTR_FORMAT
" allocation_total "
SIZE_FORMAT
gclog_or_tty
->
print_cr
(
"Chunk "
PTR_FORMAT
" allocation_total "
SIZE_FORMAT
...
@@ -2129,7 +2266,6 @@ void SpaceManager::verify_allocation_total() {
...
@@ -2129,7 +2266,6 @@ void SpaceManager::verify_allocation_total() {
assert
(
allocation_total
()
==
sum_used_in_chunks_in_use
(),
assert
(
allocation_total
()
==
sum_used_in_chunks_in_use
(),
err_msg
(
"allocation total is not consistent %d vs %d"
,
err_msg
(
"allocation total is not consistent %d vs %d"
,
allocation_total
(),
sum_used_in_chunks_in_use
()));
allocation_total
(),
sum_used_in_chunks_in_use
()));
#endif
}
}
#endif
#endif
...
@@ -2142,7 +2278,7 @@ void SpaceManager::dump(outputStream* const out) const {
...
@@ -2142,7 +2278,7 @@ void SpaceManager::dump(outputStream* const out) const {
size_t
capacity
=
0
;
size_t
capacity
=
0
;
// Add up statistics for all chunks in this SpaceManager.
// Add up statistics for all chunks in this SpaceManager.
for
(
ChunkIndex
index
=
Small
Index
;
for
(
ChunkIndex
index
=
Zero
Index
;
index
<
NumberOfInUseLists
;
index
<
NumberOfInUseLists
;
index
=
next_chunk_index
(
index
))
{
index
=
next_chunk_index
(
index
))
{
for
(
Metachunk
*
curr
=
chunks_in_use
(
index
);
for
(
Metachunk
*
curr
=
chunks_in_use
(
index
);
...
@@ -2160,7 +2296,7 @@ void SpaceManager::dump(outputStream* const out) const {
...
@@ -2160,7 +2296,7 @@ void SpaceManager::dump(outputStream* const out) const {
}
}
}
}
size_t
free
=
current_chunk
()
->
free_word_size
();
size_t
free
=
current_chunk
()
==
NULL
?
0
:
current_chunk
()
->
free_word_size
();
// Free space isn't wasted.
// Free space isn't wasted.
waste
-=
free
;
waste
-=
free
;
...
@@ -2171,25 +2307,18 @@ void SpaceManager::dump(outputStream* const out) const {
...
@@ -2171,25 +2307,18 @@ void SpaceManager::dump(outputStream* const out) const {
#ifndef PRODUCT
#ifndef PRODUCT
void
SpaceManager
::
mangle_freed_chunks
()
{
void
SpaceManager
::
mangle_freed_chunks
()
{
for
(
ChunkIndex
index
=
Small
Index
;
for
(
ChunkIndex
index
=
Zero
Index
;
index
<
NumberOfInUseLists
;
index
<
NumberOfInUseLists
;
index
=
next_chunk_index
(
index
))
{
index
=
next_chunk_index
(
index
))
{
for
(
Metachunk
*
curr
=
chunks_in_use
(
index
);
for
(
Metachunk
*
curr
=
chunks_in_use
(
index
);
curr
!=
NULL
;
curr
!=
NULL
;
curr
=
curr
->
next
())
{
curr
=
curr
->
next
())
{
// Try to detect incorrectly terminated small chunk
// list.
assert
(
index
==
MediumIndex
||
curr
!=
chunks_in_use
(
MediumIndex
),
err_msg
(
"Mangling medium chunks in small chunks? "
"curr "
PTR_FORMAT
" medium list "
PTR_FORMAT
,
curr
,
chunks_in_use
(
MediumIndex
)));
curr
->
mangle
();
curr
->
mangle
();
}
}
}
}
}
}
#endif // PRODUCT
#endif // PRODUCT
// MetaspaceAux
// MetaspaceAux
size_t
MetaspaceAux
::
used_in_bytes
(
Metaspace
::
MetadataType
mdtype
)
{
size_t
MetaspaceAux
::
used_in_bytes
(
Metaspace
::
MetadataType
mdtype
)
{
...
@@ -2236,7 +2365,7 @@ size_t MetaspaceAux::reserved_in_bytes(Metaspace::MetadataType mdtype) {
...
@@ -2236,7 +2365,7 @@ size_t MetaspaceAux::reserved_in_bytes(Metaspace::MetadataType mdtype) {
return
reserved
*
BytesPerWord
;
return
reserved
*
BytesPerWord
;
}
}
size_t
MetaspaceAux
::
min_chunk_size
()
{
return
SpaceManager
::
MediumChunk
;
}
size_t
MetaspaceAux
::
min_chunk_size
()
{
return
Metaspace
::
first_chunk_word_size
()
;
}
size_t
MetaspaceAux
::
free_chunks_total
(
Metaspace
::
MetadataType
mdtype
)
{
size_t
MetaspaceAux
::
free_chunks_total
(
Metaspace
::
MetadataType
mdtype
)
{
ChunkManager
*
chunk
=
(
mdtype
==
Metaspace
::
ClassType
)
?
ChunkManager
*
chunk
=
(
mdtype
==
Metaspace
::
ClassType
)
?
...
@@ -2316,26 +2445,44 @@ void MetaspaceAux::print_on(outputStream* out, Metaspace::MetadataType mdtype) {
...
@@ -2316,26 +2445,44 @@ void MetaspaceAux::print_on(outputStream* out, Metaspace::MetadataType mdtype) {
// Print total fragmentation for class and data metaspaces separately
// Print total fragmentation for class and data metaspaces separately
void
MetaspaceAux
::
print_waste
(
outputStream
*
out
)
{
void
MetaspaceAux
::
print_waste
(
outputStream
*
out
)
{
size_t
small_waste
=
0
,
medium_waste
=
0
,
large_waste
=
0
;
size_t
specialized_waste
=
0
,
small_waste
=
0
,
medium_waste
=
0
,
large_waste
=
0
;
size_t
cls_small_waste
=
0
,
cls_medium_waste
=
0
,
cls_large_waste
=
0
;
size_t
specialized_count
=
0
,
small_count
=
0
,
medium_count
=
0
,
large_count
=
0
;
size_t
cls_specialized_waste
=
0
,
cls_small_waste
=
0
,
cls_medium_waste
=
0
,
cls_large_waste
=
0
;
size_t
cls_specialized_count
=
0
,
cls_small_count
=
0
,
cls_medium_count
=
0
,
cls_large_count
=
0
;
ClassLoaderDataGraphMetaspaceIterator
iter
;
ClassLoaderDataGraphMetaspaceIterator
iter
;
while
(
iter
.
repeat
())
{
while
(
iter
.
repeat
())
{
Metaspace
*
msp
=
iter
.
get_next
();
Metaspace
*
msp
=
iter
.
get_next
();
if
(
msp
!=
NULL
)
{
if
(
msp
!=
NULL
)
{
specialized_waste
+=
msp
->
vsm
()
->
sum_waste_in_chunks_in_use
(
SpecializedIndex
);
specialized_count
+=
msp
->
vsm
()
->
sum_count_in_chunks_in_use
(
SpecializedIndex
);
small_waste
+=
msp
->
vsm
()
->
sum_waste_in_chunks_in_use
(
SmallIndex
);
small_waste
+=
msp
->
vsm
()
->
sum_waste_in_chunks_in_use
(
SmallIndex
);
small_count
+=
msp
->
vsm
()
->
sum_count_in_chunks_in_use
(
SmallIndex
);
medium_waste
+=
msp
->
vsm
()
->
sum_waste_in_chunks_in_use
(
MediumIndex
);
medium_waste
+=
msp
->
vsm
()
->
sum_waste_in_chunks_in_use
(
MediumIndex
);
medium_count
+=
msp
->
vsm
()
->
sum_count_in_chunks_in_use
(
MediumIndex
);
large_waste
+=
msp
->
vsm
()
->
sum_waste_in_chunks_in_use
(
HumongousIndex
);
large_waste
+=
msp
->
vsm
()
->
sum_waste_in_chunks_in_use
(
HumongousIndex
);
large_count
+=
msp
->
vsm
()
->
sum_count_in_chunks_in_use
(
HumongousIndex
);
cls_specialized_waste
+=
msp
->
class_vsm
()
->
sum_waste_in_chunks_in_use
(
SpecializedIndex
);
cls_specialized_count
+=
msp
->
class_vsm
()
->
sum_count_in_chunks_in_use
(
SpecializedIndex
);
cls_small_waste
+=
msp
->
class_vsm
()
->
sum_waste_in_chunks_in_use
(
SmallIndex
);
cls_small_waste
+=
msp
->
class_vsm
()
->
sum_waste_in_chunks_in_use
(
SmallIndex
);
cls_small_count
+=
msp
->
class_vsm
()
->
sum_count_in_chunks_in_use
(
SmallIndex
);
cls_medium_waste
+=
msp
->
class_vsm
()
->
sum_waste_in_chunks_in_use
(
MediumIndex
);
cls_medium_waste
+=
msp
->
class_vsm
()
->
sum_waste_in_chunks_in_use
(
MediumIndex
);
cls_medium_count
+=
msp
->
class_vsm
()
->
sum_count_in_chunks_in_use
(
MediumIndex
);
cls_large_waste
+=
msp
->
class_vsm
()
->
sum_waste_in_chunks_in_use
(
HumongousIndex
);
cls_large_waste
+=
msp
->
class_vsm
()
->
sum_waste_in_chunks_in_use
(
HumongousIndex
);
cls_large_count
+=
msp
->
class_vsm
()
->
sum_count_in_chunks_in_use
(
HumongousIndex
);
}
}
}
}
out
->
print_cr
(
"Total fragmentation waste (words) doesn't count free space"
);
out
->
print_cr
(
"Total fragmentation waste (words) doesn't count free space"
);
out
->
print
(
" data: small "
SIZE_FORMAT
" medium "
SIZE_FORMAT
,
out
->
print_cr
(
" data: "
SIZE_FORMAT
" specialized(s) "
SIZE_FORMAT
", "
small_waste
,
medium_waste
);
SIZE_FORMAT
" small(s) "
SIZE_FORMAT
", "
out
->
print_cr
(
" class: small "
SIZE_FORMAT
,
cls_small_waste
);
SIZE_FORMAT
" medium(s) "
SIZE_FORMAT
,
specialized_count
,
specialized_waste
,
small_count
,
small_waste
,
medium_count
,
medium_waste
);
out
->
print_cr
(
" class: "
SIZE_FORMAT
" specialized(s) "
SIZE_FORMAT
", "
SIZE_FORMAT
" small(s) "
SIZE_FORMAT
,
cls_specialized_count
,
cls_specialized_waste
,
cls_small_count
,
cls_small_waste
);
}
}
// Dump global metaspace things from the end of ClassLoaderDataGraph
// Dump global metaspace things from the end of ClassLoaderDataGraph
...
@@ -2354,13 +2501,10 @@ void MetaspaceAux::verify_free_chunks() {
...
@@ -2354,13 +2501,10 @@ void MetaspaceAux::verify_free_chunks() {
// Metaspace methods
// Metaspace methods
size_t
Metaspace
::
_first_chunk_word_size
=
0
;
size_t
Metaspace
::
_first_chunk_word_size
=
0
;
size_t
Metaspace
::
_first_class_chunk_word_size
=
0
;
Metaspace
::
Metaspace
(
Mutex
*
lock
,
size_t
word_size
)
{
Metaspace
::
Metaspace
(
Mutex
*
lock
,
MetaspaceType
type
)
{
initialize
(
lock
,
word_size
);
initialize
(
lock
,
type
);
}
Metaspace
::
Metaspace
(
Mutex
*
lock
)
{
initialize
(
lock
);
}
}
Metaspace
::~
Metaspace
()
{
Metaspace
::~
Metaspace
()
{
...
@@ -2412,11 +2556,18 @@ void Metaspace::global_initialize() {
...
@@ -2412,11 +2556,18 @@ void Metaspace::global_initialize() {
}
}
}
}
// Initialize th
is
before initializing the VirtualSpaceList
// Initialize th
ese
before initializing the VirtualSpaceList
_first_chunk_word_size
=
InitialBootClassLoaderMetaspaceSize
/
BytesPerWord
;
_first_chunk_word_size
=
InitialBootClassLoaderMetaspaceSize
/
BytesPerWord
;
_first_chunk_word_size
=
align_word_size_up
(
_first_chunk_word_size
);
// Make the first class chunk bigger than a medium chunk so it's not put
// on the medium chunk list. The next chunk will be small and progress
// from there. This size calculated by -version.
_first_class_chunk_word_size
=
MIN2
((
size_t
)
MediumChunk
*
6
,
(
ClassMetaspaceSize
/
BytesPerWord
)
*
2
);
_first_class_chunk_word_size
=
align_word_size_up
(
_first_class_chunk_word_size
);
// Arbitrarily set the initial virtual space to a multiple
// Arbitrarily set the initial virtual space to a multiple
// of the boot class loader size.
// of the boot class loader size.
size_t
word_size
=
VIRTUALSPACEMULTIPLIER
*
Metaspace
::
first_chunk_word_size
();
size_t
word_size
=
VIRTUALSPACEMULTIPLIER
*
first_chunk_word_size
();
// Initialize the list of virtual spaces.
// Initialize the list of virtual spaces.
_space_list
=
new
VirtualSpaceList
(
word_size
);
_space_list
=
new
VirtualSpaceList
(
word_size
);
}
}
...
@@ -2431,23 +2582,8 @@ void Metaspace::initialize_class_space(ReservedSpace rs) {
...
@@ -2431,23 +2582,8 @@ void Metaspace::initialize_class_space(ReservedSpace rs) {
_class_space_list
=
new
VirtualSpaceList
(
rs
);
_class_space_list
=
new
VirtualSpaceList
(
rs
);
}
}
void
Metaspace
::
initialize
(
Mutex
*
lock
,
void
Metaspace
::
initialize
(
Mutex
*
lock
,
size_t
initial_size
)
{
MetaspaceType
type
)
{
// Use SmallChunk size if not specified. If specified, use this size for
// the data metaspace.
size_t
word_size
;
size_t
class_word_size
;
if
(
initial_size
==
0
)
{
word_size
=
(
size_t
)
SpaceManager
::
SmallChunk
;
class_word_size
=
(
size_t
)
SpaceManager
::
SmallChunk
;
}
else
{
word_size
=
initial_size
;
// Make the first class chunk bigger than a medium chunk so it's not put
// on the medium chunk list. The next chunk will be small and progress
// from there. This size calculated by -version.
class_word_size
=
MIN2
((
size_t
)
SpaceManager
::
MediumChunk
*
5
,
(
ClassMetaspaceSize
/
BytesPerWord
)
*
2
);
}
assert
(
space_list
()
!=
NULL
,
assert
(
space_list
()
!=
NULL
,
"Metadata VirtualSpaceList has not been initialized"
);
"Metadata VirtualSpaceList has not been initialized"
);
...
@@ -2456,6 +2592,11 @@ void Metaspace::initialize(Mutex* lock, size_t initial_size) {
...
@@ -2456,6 +2592,11 @@ void Metaspace::initialize(Mutex* lock, size_t initial_size) {
if
(
_vsm
==
NULL
)
{
if
(
_vsm
==
NULL
)
{
return
;
return
;
}
}
size_t
word_size
;
size_t
class_word_size
;
vsm
()
->
get_initial_chunk_sizes
(
type
,
&
word_size
,
&
class_word_size
);
assert
(
class_space_list
()
!=
NULL
,
assert
(
class_space_list
()
!=
NULL
,
"Class VirtualSpaceList has not been initialized"
);
"Class VirtualSpaceList has not been initialized"
);
...
@@ -2470,7 +2611,8 @@ void Metaspace::initialize(Mutex* lock, size_t initial_size) {
...
@@ -2470,7 +2611,8 @@ void Metaspace::initialize(Mutex* lock, size_t initial_size) {
// Allocate chunk for metadata objects
// Allocate chunk for metadata objects
Metachunk
*
new_chunk
=
Metachunk
*
new_chunk
=
space_list
()
->
current_virtual_space
()
->
get_chunk_vs_with_expand
(
word_size
);
space_list
()
->
get_initialization_chunk
(
word_size
,
vsm
()
->
medium_chunk_bunch
());
assert
(
!
DumpSharedSpaces
||
new_chunk
!=
NULL
,
"should have enough space for both chunks"
);
assert
(
!
DumpSharedSpaces
||
new_chunk
!=
NULL
,
"should have enough space for both chunks"
);
if
(
new_chunk
!=
NULL
)
{
if
(
new_chunk
!=
NULL
)
{
// Add to this manager's list of chunks in use and current_chunk().
// Add to this manager's list of chunks in use and current_chunk().
...
@@ -2479,12 +2621,18 @@ void Metaspace::initialize(Mutex* lock, size_t initial_size) {
...
@@ -2479,12 +2621,18 @@ void Metaspace::initialize(Mutex* lock, size_t initial_size) {
// Allocate chunk for class metadata objects
// Allocate chunk for class metadata objects
Metachunk
*
class_chunk
=
Metachunk
*
class_chunk
=
class_space_list
()
->
current_virtual_space
()
->
get_chunk_vs_with_expand
(
class_word_size
);
class_space_list
()
->
get_initialization_chunk
(
class_word_size
,
class_vsm
()
->
medium_chunk_bunch
());
if
(
class_chunk
!=
NULL
)
{
if
(
class_chunk
!=
NULL
)
{
class_vsm
()
->
add_chunk
(
class_chunk
,
true
);
class_vsm
()
->
add_chunk
(
class_chunk
,
true
);
}
}
}
}
size_t
Metaspace
::
align_word_size_up
(
size_t
word_size
)
{
size_t
byte_size
=
word_size
*
wordSize
;
return
ReservedSpace
::
allocation_align_size_up
(
byte_size
)
/
wordSize
;
}
MetaWord
*
Metaspace
::
allocate
(
size_t
word_size
,
MetadataType
mdtype
)
{
MetaWord
*
Metaspace
::
allocate
(
size_t
word_size
,
MetadataType
mdtype
)
{
// DumpSharedSpaces doesn't use class metadata area (yet)
// DumpSharedSpaces doesn't use class metadata area (yet)
if
(
mdtype
==
ClassType
&&
!
DumpSharedSpaces
)
{
if
(
mdtype
==
ClassType
&&
!
DumpSharedSpaces
)
{
...
@@ -2610,6 +2758,12 @@ Metablock* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size,
...
@@ -2610,6 +2758,12 @@ Metablock* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size,
// If result is still null, we are out of memory.
// If result is still null, we are out of memory.
if
(
result
==
NULL
)
{
if
(
result
==
NULL
)
{
if
(
Verbose
&&
TraceMetadataChunkAllocation
)
{
gclog_or_tty
->
print_cr
(
"Metaspace allocation failed for size "
SIZE_FORMAT
,
word_size
);
if
(
loader_data
->
metaspace_or_null
()
!=
NULL
)
loader_data
->
metaspace_or_null
()
->
dump
(
gclog_or_tty
);
MetaspaceAux
::
dump
(
gclog_or_tty
);
}
// -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support
// -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support
report_java_out_of_memory
(
"Metadata space"
);
report_java_out_of_memory
(
"Metadata space"
);
...
...
src/share/vm/memory/metaspace.hpp
浏览文件 @
0d459bfa
...
@@ -87,11 +87,23 @@ class Metaspace : public CHeapObj<mtClass> {
...
@@ -87,11 +87,23 @@ class Metaspace : public CHeapObj<mtClass> {
public:
public:
enum
MetadataType
{
ClassType
,
NonClassType
};
enum
MetadataType
{
ClassType
,
NonClassType
};
enum
MetaspaceType
{
StandardMetaspaceType
,
BootMetaspaceType
,
ROMetaspaceType
,
ReadWriteMetaspaceType
,
AnonymousMetaspaceType
,
ReflectionMetaspaceType
};
private:
private:
void
initialize
(
Mutex
*
lock
,
size_t
initial_size
=
0
);
void
initialize
(
Mutex
*
lock
,
MetaspaceType
type
);
// Align up the word size to the allocation word size
static
size_t
align_word_size_up
(
size_t
);
static
size_t
_first_chunk_word_size
;
static
size_t
_first_chunk_word_size
;
static
size_t
_first_class_chunk_word_size
;
SpaceManager
*
_vsm
;
SpaceManager
*
_vsm
;
SpaceManager
*
vsm
()
const
{
return
_vsm
;
}
SpaceManager
*
vsm
()
const
{
return
_vsm
;
}
...
@@ -110,8 +122,7 @@ class Metaspace : public CHeapObj<mtClass> {
...
@@ -110,8 +122,7 @@ class Metaspace : public CHeapObj<mtClass> {
public:
public:
Metaspace
(
Mutex
*
lock
,
size_t
initial_size
);
Metaspace
(
Mutex
*
lock
,
MetaspaceType
type
);
Metaspace
(
Mutex
*
lock
);
~
Metaspace
();
~
Metaspace
();
// Initialize globals for Metaspace
// Initialize globals for Metaspace
...
@@ -119,6 +130,7 @@ class Metaspace : public CHeapObj<mtClass> {
...
@@ -119,6 +130,7 @@ class Metaspace : public CHeapObj<mtClass> {
static
void
initialize_class_space
(
ReservedSpace
rs
);
static
void
initialize_class_space
(
ReservedSpace
rs
);
static
size_t
first_chunk_word_size
()
{
return
_first_chunk_word_size
;
}
static
size_t
first_chunk_word_size
()
{
return
_first_chunk_word_size
;
}
static
size_t
first_class_chunk_word_size
()
{
return
_first_class_chunk_word_size
;
}
char
*
bottom
()
const
;
char
*
bottom
()
const
;
size_t
used_words
(
MetadataType
mdtype
)
const
;
size_t
used_words
(
MetadataType
mdtype
)
const
;
...
...
src/share/vm/runtime/globals.hpp
浏览文件 @
0d459bfa
...
@@ -2217,7 +2217,8 @@ class CommandLineFlags {
...
@@ -2217,7 +2217,8 @@ class CommandLineFlags {
develop(bool, TraceClassLoaderData, false, \
develop(bool, TraceClassLoaderData, false, \
"Trace class loader loader_data lifetime") \
"Trace class loader loader_data lifetime") \
\
\
product(uintx, InitialBootClassLoaderMetaspaceSize, 3*M, \
product(uintx, InitialBootClassLoaderMetaspaceSize, \
NOT_LP64(2200*K) LP64_ONLY(4*M), \
"Initial size of the boot class loader data metaspace") \
"Initial size of the boot class loader data metaspace") \
\
\
product(bool, TraceGen0Time, false, \
product(bool, TraceGen0Time, false, \
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录