Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
ef7c07c7
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看板
提交
ef7c07c7
编写于
10月 15, 2013
作者:
S
stefank
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8026391: The Metachunk header wastes memory
Reviewed-by: coleenp, jmasa
上级
ff919e46
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
227 addition
and
336 deletion
+227
-336
src/share/vm/memory/binaryTreeDictionary.cpp
src/share/vm/memory/binaryTreeDictionary.cpp
+0
-1
src/share/vm/memory/freeBlockDictionary.cpp
src/share/vm/memory/freeBlockDictionary.cpp
+0
-1
src/share/vm/memory/freeList.cpp
src/share/vm/memory/freeList.cpp
+0
-1
src/share/vm/memory/metablock.cpp
src/share/vm/memory/metablock.cpp
+0
-68
src/share/vm/memory/metablock.hpp
src/share/vm/memory/metablock.hpp
+0
-101
src/share/vm/memory/metachunk.cpp
src/share/vm/memory/metachunk.cpp
+80
-35
src/share/vm/memory/metachunk.hpp
src/share/vm/memory/metachunk.hpp
+107
-68
src/share/vm/memory/metaspace.cpp
src/share/vm/memory/metaspace.cpp
+35
-57
src/share/vm/memory/metaspace.hpp
src/share/vm/memory/metaspace.hpp
+2
-3
src/share/vm/prims/jni.cpp
src/share/vm/prims/jni.cpp
+2
-0
src/share/vm/runtime/vmStructs.cpp
src/share/vm/runtime/vmStructs.cpp
+1
-1
未找到文件。
src/share/vm/memory/binaryTreeDictionary.cpp
浏览文件 @
ef7c07c7
...
...
@@ -28,7 +28,6 @@
#include "memory/binaryTreeDictionary.hpp"
#include "memory/freeList.hpp"
#include "memory/freeBlockDictionary.hpp"
#include "memory/metablock.hpp"
#include "memory/metachunk.hpp"
#include "runtime/globals.hpp"
#include "utilities/ostream.hpp"
...
...
src/share/vm/memory/freeBlockDictionary.cpp
浏览文件 @
ef7c07c7
...
...
@@ -28,7 +28,6 @@
#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
#endif // INCLUDE_ALL_GCS
#include "memory/freeBlockDictionary.hpp"
#include "memory/metablock.hpp"
#include "memory/metachunk.hpp"
#include "runtime/thread.inline.hpp"
#include "utilities/macros.hpp"
...
...
src/share/vm/memory/freeList.cpp
浏览文件 @
ef7c07c7
...
...
@@ -25,7 +25,6 @@
#include "precompiled.hpp"
#include "memory/freeBlockDictionary.hpp"
#include "memory/freeList.hpp"
#include "memory/metablock.hpp"
#include "memory/metachunk.hpp"
#include "memory/sharedHeap.hpp"
#include "runtime/globals.hpp"
...
...
src/share/vm/memory/metablock.cpp
已删除
100644 → 0
浏览文件 @
ff919e46
/*
* Copyright (c) 2012, 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.
*
*/
#include "precompiled.hpp"
#include "memory/allocation.hpp"
#include "memory/metablock.hpp"
#include "utilities/copy.hpp"
#include "utilities/debug.hpp"
// Blocks of space for metadata are allocated out of Metachunks.
//
// Metachunk are allocated out of MetadataVirtualspaces and once
// allocated there is no explicit link between a Metachunk and
// the MetadataVirtualspaces from which it was allocated.
//
// Each SpaceManager maintains a
// list of the chunks it is using and the current chunk. The current
// chunk is the chunk from which allocations are done. Space freed in
// a chunk is placed on the free list of blocks (BlockFreelist) and
// reused from there.
//
// Future modification
//
// The Metachunk can conceivable be replaced by the Chunk in
// allocation.hpp. Note that the latter Chunk is the space for
// allocation (allocations from the chunk are out of the space in
// the Chunk after the header for the Chunk) where as Metachunks
// point to space in a VirtualSpace. To replace Metachunks with
// Chunks, change Chunks so that they can be allocated out of a VirtualSpace.
size_t
Metablock
::
_min_block_byte_size
=
sizeof
(
Metablock
);
// New blocks returned by the Metaspace are zero initialized.
// We should fix the constructors to not assume this instead.
Metablock
*
Metablock
::
initialize
(
MetaWord
*
p
,
size_t
word_size
)
{
if
(
p
==
NULL
)
{
return
NULL
;
}
Metablock
*
result
=
(
Metablock
*
)
p
;
// Clear the memory
Copy
::
fill_to_aligned_words
((
HeapWord
*
)
result
,
word_size
);
#ifdef ASSERT
result
->
set_word_size
(
word_size
);
#endif
return
result
;
}
src/share/vm/memory/metablock.hpp
已删除
100644 → 0
浏览文件 @
ff919e46
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_MEMORY_METABLOCK_HPP
#define SHARE_VM_MEMORY_METABLOCK_HPP
// Metablock are the unit of allocation from a Chunk. It is initialized
// with the size of the requested allocation. That size is overwritten
// once the allocation returns.
//
// A Metablock may be reused by its SpaceManager but are never moved between
// SpaceManagers. There is no explicit link to the Metachunk
// from which it was allocated. Metablock may be deallocated and
// put on a freelist but the space is never freed, rather
// the Metachunk it is a part of will be deallocated when it's
// associated class loader is collected.
class
Metablock
VALUE_OBJ_CLASS_SPEC
{
friend
class
VMStructs
;
private:
// Used to align the allocation (see below).
union
block_t
{
void
*
_data
[
3
];
struct
header_t
{
size_t
_word_size
;
Metablock
*
_next
;
Metablock
*
_prev
;
}
_header
;
}
_block
;
static
size_t
_min_block_byte_size
;
typedef
union
block_t
Block
;
typedef
struct
header_t
Header
;
const
Block
*
block
()
const
{
return
&
_block
;
}
const
Block
::
header_t
*
header
()
const
{
return
&
(
block
()
->
_header
);
}
public:
static
Metablock
*
initialize
(
MetaWord
*
p
,
size_t
word_size
);
// This places the body of the block at a 2 word boundary
// because every block starts on a 2 word boundary. Work out
// how to make the body on a 2 word boundary if the block
// starts on a arbitrary boundary. JJJ
size_t
word_size
()
const
{
return
header
()
->
_word_size
;
}
void
set_word_size
(
size_t
v
)
{
_block
.
_header
.
_word_size
=
v
;
}
size_t
size
()
const
volatile
{
return
_block
.
_header
.
_word_size
;
}
void
set_size
(
size_t
v
)
{
_block
.
_header
.
_word_size
=
v
;
}
Metablock
*
next
()
const
{
return
header
()
->
_next
;
}
void
set_next
(
Metablock
*
v
)
{
_block
.
_header
.
_next
=
v
;
}
Metablock
*
prev
()
const
{
return
header
()
->
_prev
;
}
void
set_prev
(
Metablock
*
v
)
{
_block
.
_header
.
_prev
=
v
;
}
static
size_t
min_block_byte_size
()
{
return
_min_block_byte_size
;
}
bool
is_free
()
{
return
header
()
->
_word_size
!=
0
;
}
void
clear_next
()
{
set_next
(
NULL
);
}
void
link_prev
(
Metablock
*
ptr
)
{
set_prev
(
ptr
);
}
uintptr_t
*
end
()
{
return
((
uintptr_t
*
)
this
)
+
size
();
}
bool
cantCoalesce
()
const
{
return
false
;
}
void
link_next
(
Metablock
*
ptr
)
{
set_next
(
ptr
);
}
void
link_after
(
Metablock
*
ptr
){
link_next
(
ptr
);
if
(
ptr
!=
NULL
)
ptr
->
link_prev
(
this
);
}
// Should not be needed in a free list of Metablocks
void
markNotFree
()
{
ShouldNotReachHere
();
}
// Debug support
#ifdef ASSERT
void
*
prev_addr
()
const
{
return
(
void
*
)
&
_block
.
_header
.
_prev
;
}
void
*
next_addr
()
const
{
return
(
void
*
)
&
_block
.
_header
.
_next
;
}
void
*
size_addr
()
const
{
return
(
void
*
)
&
_block
.
_header
.
_word_size
;
}
#endif
bool
verify_chunk_in_free_list
(
Metablock
*
tc
)
const
{
return
true
;
}
bool
verify_par_locked
()
{
return
true
;
}
void
assert_is_mangled
()
const
{
/* Don't check "\*/
}
};
#endif // SHARE_VM_MEMORY_METABLOCK_HPP
src/share/vm/memory/metachunk.cpp
浏览文件 @
ef7c07c7
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012,
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
...
...
@@ -29,42 +29,32 @@
#include "utilities/debug.hpp"
class
VirtualSpaceNode
;
//
// Future modification
//
// The Metachunk can conceivable be replaced by the Chunk in
// allocation.hpp. Note that the latter Chunk is the space for
// allocation (allocations from the chunk are out of the space in
// the Chunk after the header for the Chunk) where as Metachunks
// point to space in a VirtualSpace. To replace Metachunks with
// Chunks, change Chunks so that they can be allocated out of a VirtualSpace.
const
size_t
metadata_chunk_initialize
=
0xf7f7f7f7
;
size_t
Metachunk
::
_overhead
=
Chunk
::
aligned_overhead_size
(
sizeof
(
Metachunk
))
/
BytesPerWord
;
size_t
Metachunk
::
object_alignment
()
{
return
ARENA_AMALLOC_ALIGNMENT
;
}
size_t
Metachunk
::
overhead
()
{
return
align_size_up
(
sizeof
(
Metachunk
),
object_alignment
())
/
BytesPerWord
;
}
// Metachunk methods
Metachunk
::
Metachunk
(
size_t
word_size
,
VirtualSpaceNode
*
container
)
:
_word_size
(
word_size
),
_bottom
(
NULL
),
_end
(
NULL
),
VirtualSpaceNode
*
container
)
:
Metabase
<
Metachunk
>
(
word_size
),
_top
(
NULL
),
_next
(
NULL
),
_prev
(
NULL
),
_container
(
container
)
{
_bottom
=
(
MetaWord
*
)
this
;
_top
=
(
MetaWord
*
)
this
+
_overhead
;
_end
=
(
MetaWord
*
)
this
+
word_size
;
_top
=
initial_top
();
#ifdef ASSERT
set_is_free
(
false
);
set_is_
tagged_
free
(
false
);
size_t
data_word_size
=
pointer_delta
(
end
(),
top
()
,
_top
,
sizeof
(
MetaWord
));
Copy
::
fill_to_words
((
HeapWord
*
)
top
()
,
Copy
::
fill_to_words
((
HeapWord
*
)
_top
,
data_word_size
,
metadata_chunk_initialize
);
#endif
...
...
@@ -82,22 +72,18 @@ MetaWord* Metachunk::allocate(size_t word_size) {
// _bottom points to the start of the chunk including the overhead.
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
()
const
{
return
pointer_delta
(
_end
,
_top
,
sizeof
(
MetaWord
));
}
size_t
Metachunk
::
capacity_word_size
()
const
{
return
pointer_delta
(
_end
,
_bottom
,
sizeof
(
MetaWord
));
return
pointer_delta
(
end
(),
_top
,
sizeof
(
MetaWord
));
}
void
Metachunk
::
print_on
(
outputStream
*
st
)
const
{
st
->
print_cr
(
"Metachunk:"
" bottom "
PTR_FORMAT
" top "
PTR_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
());
...
...
@@ -109,8 +95,8 @@ void Metachunk::mangle() {
// Mangle the payload of the chunk and not the links that
// maintain list of chunks.
HeapWord
*
start
=
(
HeapWord
*
)(
bottom
()
+
overhead
());
size_t
word_size
=
capacity_
word_size
()
-
overhead
();
Copy
::
fill_to_words
(
start
,
word_
size
,
metadata_chunk_initialize
);
size_t
size
=
word_size
()
-
overhead
();
Copy
::
fill_to_words
(
start
,
size
,
metadata_chunk_initialize
);
}
#endif // PRODUCT
...
...
@@ -118,9 +104,68 @@ void Metachunk::verify() {
#ifdef ASSERT
// Cannot walk through the blocks unless the blocks have
// headers with sizes.
assert
(
_bottom
<=
_top
&&
_top
<=
_end
,
assert
(
bottom
()
<=
_top
&&
_top
<=
(
MetaWord
*
)
end
()
,
"Chunk has been smashed"
);
#endif
return
;
}
/////////////// Unit tests ///////////////
#ifndef PRODUCT
class
TestMetachunk
{
public:
static
void
test
()
{
size_t
size
=
2
*
1024
*
1024
;
void
*
memory
=
malloc
(
size
);
assert
(
memory
!=
NULL
,
"Failed to malloc 2MB"
);
Metachunk
*
metachunk
=
::
new
(
memory
)
Metachunk
(
size
/
BytesPerWord
,
NULL
);
assert
(
metachunk
->
bottom
()
==
(
MetaWord
*
)
metachunk
,
"assert"
);
assert
(
metachunk
->
end
()
==
(
uintptr_t
*
)
metachunk
+
metachunk
->
size
(),
"assert"
);
// Check sizes
assert
(
metachunk
->
size
()
==
metachunk
->
word_size
(),
"assert"
);
assert
(
metachunk
->
word_size
()
==
pointer_delta
(
metachunk
->
end
(),
metachunk
->
bottom
(),
sizeof
(
MetaWord
*
)),
"assert"
);
// Check usage
assert
(
metachunk
->
used_word_size
()
==
metachunk
->
overhead
(),
"assert"
);
assert
(
metachunk
->
free_word_size
()
==
metachunk
->
word_size
()
-
metachunk
->
used_word_size
(),
"assert"
);
assert
(
metachunk
->
top
()
==
metachunk
->
initial_top
(),
"assert"
);
assert
(
metachunk
->
is_empty
(),
"assert"
);
// Allocate
size_t
alloc_size
=
64
;
// Words
assert
(
is_size_aligned
(
alloc_size
,
Metachunk
::
object_alignment
()),
"assert"
);
MetaWord
*
mem
=
metachunk
->
allocate
(
alloc_size
);
// Check post alloc
assert
(
mem
==
metachunk
->
initial_top
(),
"assert"
);
assert
(
mem
+
alloc_size
==
metachunk
->
top
(),
"assert"
);
assert
(
metachunk
->
used_word_size
()
==
metachunk
->
overhead
()
+
alloc_size
,
"assert"
);
assert
(
metachunk
->
free_word_size
()
==
metachunk
->
word_size
()
-
metachunk
->
used_word_size
(),
"assert"
);
assert
(
!
metachunk
->
is_empty
(),
"assert"
);
// Clear chunk
metachunk
->
reset_empty
();
// Check post clear
assert
(
metachunk
->
used_word_size
()
==
metachunk
->
overhead
(),
"assert"
);
assert
(
metachunk
->
free_word_size
()
==
metachunk
->
word_size
()
-
metachunk
->
used_word_size
(),
"assert"
);
assert
(
metachunk
->
top
()
==
metachunk
->
initial_top
(),
"assert"
);
assert
(
metachunk
->
is_empty
(),
"assert"
);
free
(
memory
);
}
};
void
TestMetachunk_test
()
{
TestMetachunk
::
test
();
}
#endif
src/share/vm/memory/metachunk.hpp
浏览文件 @
ef7c07c7
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012,
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
...
...
@@ -24,104 +24,143 @@
#ifndef SHARE_VM_MEMORY_METACHUNK_HPP
#define SHARE_VM_MEMORY_METACHUNK_HPP
#include "memory/allocation.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
class
VirtualSpaceNode
;
// Super class of Metablock and Metachunk to allow them to
// be put on the FreeList and in the BinaryTreeDictionary.
template
<
class
T
>
class
Metabase
VALUE_OBJ_CLASS_SPEC
{
size_t
_word_size
;
T
*
_next
;
T
*
_prev
;
protected:
Metabase
(
size_t
word_size
)
:
_word_size
(
word_size
),
_next
(
NULL
),
_prev
(
NULL
)
{}
public:
T
*
next
()
const
{
return
_next
;
}
T
*
prev
()
const
{
return
_prev
;
}
void
set_next
(
T
*
v
)
{
_next
=
v
;
assert
(
v
!=
this
,
"Boom"
);}
void
set_prev
(
T
*
v
)
{
_prev
=
v
;
assert
(
v
!=
this
,
"Boom"
);}
void
clear_next
()
{
set_next
(
NULL
);
}
void
clear_prev
()
{
set_prev
(
NULL
);
}
size_t
size
()
const
volatile
{
return
_word_size
;
}
void
set_size
(
size_t
v
)
{
_word_size
=
v
;
}
void
link_next
(
T
*
ptr
)
{
set_next
(
ptr
);
}
void
link_prev
(
T
*
ptr
)
{
set_prev
(
ptr
);
}
void
link_after
(
T
*
ptr
)
{
link_next
(
ptr
);
if
(
ptr
!=
NULL
)
ptr
->
link_prev
((
T
*
)
this
);
}
uintptr_t
*
end
()
const
{
return
((
uintptr_t
*
)
this
)
+
size
();
}
bool
cantCoalesce
()
const
{
return
false
;
}
// Debug support
#ifdef ASSERT
void
*
prev_addr
()
const
{
return
(
void
*
)
&
_prev
;
}
void
*
next_addr
()
const
{
return
(
void
*
)
&
_next
;
}
void
*
size_addr
()
const
{
return
(
void
*
)
&
_word_size
;
}
#endif
bool
verify_chunk_in_free_list
(
T
*
tc
)
const
{
return
true
;
}
bool
verify_par_locked
()
{
return
true
;
}
void
assert_is_mangled
()
const
{
/* Don't check "\*/
}
bool
is_free
()
{
return
true
;
}
};
// Metachunk - Quantum of allocation from a Virtualspace
// Metachunks are reused (when freed are put on a global freelist) and
// have no permanent association to a SpaceManager.
// +--------------+ <- end
// | | --+ ---+
// | | | free |
// | | | |
// | | | | capacity
// | | | |
// | | <- top --+ |
// | | ---+ |
// | | | used |
// | | | |
// | | | |
// +--------------+ <- bottom ---+ ---+
class
VirtualSpaceNode
;
class
Metachunk
VALUE_OBJ_CLASS_SPEC
{
// link to support lists of chunks
Metachunk
*
_next
;
Metachunk
*
_prev
;
// +--------------+ <- end --+ --+
// | | | |
// | | | free |
// | | | |
// | | | | size | capacity
// | | | |
// | | <- top -- + |
// | | | |
// | | | used |
// | | | |
// | | | |
// +--------------+ <- bottom --+ --+
class
Metachunk
:
public
Metabase
<
Metachunk
>
{
friend
class
TestMetachunk
;
// The VirtualSpaceNode containing this chunk.
VirtualSpaceNode
*
_container
;
MetaWord
*
_bottom
;
MetaWord
*
_end
;
// Current allocation top.
MetaWord
*
_top
;
size_t
_word_size
;
// Used in a guarantee() so included in the Product builds
// even through it is only for debugging.
bool
_is_free
;
DEBUG_ONLY
(
bool
_is_tagged_free
;)
MetaWord
*
initial_top
()
const
{
return
(
MetaWord
*
)
this
+
overhead
();
}
MetaWord
*
top
()
const
{
return
_top
;
}
public:
// Metachunks are allocated out of a MetadataVirtualSpace and
// and use some of its space to describe itself (plus alignment
// considerations). Metadata is allocated in the rest of the chunk.
// This size is the overhead of maintaining the Metachunk within
// the space.
static
size_t
_overhead
;
public:
Metachunk
(
size_t
word_size
,
VirtualSpaceNode
*
container
);
// Alignment of each allocation in the chunks.
static
size_t
object_alignment
();
// Size of the Metachunk header, including alignment.
static
size_t
overhead
();
// Used to add a Metachunk to a list of Metachunks
void
set_next
(
Metachunk
*
v
)
{
_next
=
v
;
assert
(
v
!=
this
,
"Boom"
);}
void
set_prev
(
Metachunk
*
v
)
{
_prev
=
v
;
assert
(
v
!=
this
,
"Boom"
);}
void
set_container
(
VirtualSpaceNode
*
v
)
{
_container
=
v
;
}
Metachunk
(
size_t
word_size
,
VirtualSpaceNode
*
container
);
MetaWord
*
allocate
(
size_t
word_size
);
// Accessors
Metachunk
*
next
()
const
{
return
_next
;
}
Metachunk
*
prev
()
const
{
return
_prev
;
}
VirtualSpaceNode
*
container
()
const
{
return
_container
;
}
MetaWord
*
bottom
()
const
{
return
_bottom
;
}
MetaWord
*
end
()
const
{
return
_end
;
}
MetaWord
*
top
()
const
{
return
_top
;
}
size_t
word_size
()
const
{
return
_word_size
;
}
size_t
size
()
const
volatile
{
return
_word_size
;
}
void
set_size
(
size_t
v
)
{
_word_size
=
v
;
}
bool
is_free
()
{
return
_is_free
;
}
void
set_is_free
(
bool
v
)
{
_is_free
=
v
;
}
static
size_t
overhead
()
{
return
_overhead
;
}
void
clear_next
()
{
set_next
(
NULL
);
}
void
link_prev
(
Metachunk
*
ptr
)
{
set_prev
(
ptr
);
}
uintptr_t
*
end
()
{
return
((
uintptr_t
*
)
this
)
+
size
();
}
bool
cantCoalesce
()
const
{
return
false
;
}
void
link_next
(
Metachunk
*
ptr
)
{
set_next
(
ptr
);
}
void
link_after
(
Metachunk
*
ptr
){
link_next
(
ptr
);
if
(
ptr
!=
NULL
)
ptr
->
link_prev
(
this
);
}
MetaWord
*
bottom
()
const
{
return
(
MetaWord
*
)
this
;
}
// Reset top to bottom so chunk can be reused.
void
reset_empty
()
{
_top
=
(
_bottom
+
_overhead
);
_next
=
NULL
;
_prev
=
NULL
;
}
bool
is_empty
()
{
return
_top
==
(
_bottom
+
_overhead
);
}
void
reset_empty
()
{
_top
=
initial_top
();
clear_next
();
clear_prev
()
;
}
bool
is_empty
()
{
return
_top
==
initial_top
(
);
}
// used (has been allocated)
// free (available for future allocations)
// capacity (total size of chunk)
size_t
word_size
()
const
{
return
size
();
}
size_t
used_word_size
()
const
;
size_t
free_word_size
()
const
;
size_t
capacity_word_size
()
const
;
// Debug support
#ifdef ASSERT
void
*
prev_addr
()
const
{
return
(
void
*
)
&
_prev
;
}
void
*
next_addr
()
const
{
return
(
void
*
)
&
_next
;
}
void
*
size_addr
()
const
{
return
(
void
*
)
&
_word_size
;
}
void
mangle
();
bool
is_tagged_free
()
{
return
_is_tagged_free
;
}
void
set_is_tagged_free
(
bool
v
)
{
_is_tagged_free
=
v
;
}
#endif
bool
verify_chunk_in_free_list
(
Metachunk
*
tc
)
const
{
return
true
;
}
bool
verify_par_locked
()
{
return
true
;
}
void
assert_is_mangled
()
const
{
/* Don't check "\*/
}
NOT_PRODUCT
(
void
mangle
();)
void
print_on
(
outputStream
*
st
)
const
;
void
verify
();
};
// Metablock is the unit of allocation from a Chunk.
//
// A Metablock may be reused by its SpaceManager but are never moved between
// SpaceManagers. There is no explicit link to the Metachunk
// from which it was allocated. Metablock may be deallocated and
// put on a freelist but the space is never freed, rather
// the Metachunk it is a part of will be deallocated when it's
// associated class loader is collected.
class
Metablock
:
public
Metabase
<
Metablock
>
{
friend
class
VMStructs
;
public:
Metablock
(
size_t
word_size
)
:
Metabase
<
Metablock
>
(
word_size
)
{}
};
#endif // SHARE_VM_MEMORY_METACHUNK_HPP
src/share/vm/memory/metaspace.cpp
浏览文件 @
ef7c07c7
...
...
@@ -30,7 +30,6 @@
#include "memory/filemap.hpp"
#include "memory/freeList.hpp"
#include "memory/gcLocker.hpp"
#include "memory/metablock.hpp"
#include "memory/metachunk.hpp"
#include "memory/metaspace.hpp"
#include "memory/metaspaceShared.hpp"
...
...
@@ -49,8 +48,8 @@
typedef
BinaryTreeDictionary
<
Metablock
,
FreeList
>
BlockTreeDictionary
;
typedef
BinaryTreeDictionary
<
Metachunk
,
FreeList
>
ChunkTreeDictionary
;
// Define this macro to enable slow integrity checking of
// the free chunk lists
//
Set this constant to enable slow integrity checking of
the free chunk lists
const
bool
metaspace_slow_verify
=
false
;
// Parameters for stress mode testing
...
...
@@ -92,24 +91,9 @@ volatile intptr_t MetaspaceGC::_capacity_until_GC = 0;
uint
MetaspaceGC
::
_shrink_factor
=
0
;
bool
MetaspaceGC
::
_should_concurrent_collect
=
false
;
// Blocks of space for metadata are allocated out of Metachunks.
//
// Metachunk are allocated out of MetadataVirtualspaces and once
// allocated there is no explicit link between a Metachunk and
// the MetadataVirtualspaces from which it was allocated.
//
// Each SpaceManager maintains a
// list of the chunks it is using and the current chunk. The current
// chunk is the chunk from which allocations are done. Space freed in
// a chunk is placed on the free list of blocks (BlockFreelist) and
// reused from there.
typedef
class
FreeList
<
Metachunk
>
ChunkList
;
// Manages the global free lists of chunks.
// Has three lists of free chunks, and a total size and
// count that includes all three
class
ChunkManager
:
public
CHeapObj
<
mtInternal
>
{
// Free list of chunks of different sizes.
...
...
@@ -119,7 +103,6 @@ class ChunkManager : public CHeapObj<mtInternal> {
// HumongousChunk
ChunkList
_free_chunks
[
NumberOfFreeLists
];
// HumongousChunk
ChunkTreeDictionary
_humongous_dictionary
;
...
...
@@ -230,7 +213,6 @@ class ChunkManager : public CHeapObj<mtInternal> {
// to the allocation of a quantum of metadata).
class
BlockFreelist
VALUE_OBJ_CLASS_SPEC
{
BlockTreeDictionary
*
_dictionary
;
static
Metablock
*
initialize_free_chunk
(
MetaWord
*
p
,
size_t
word_size
);
// Only allocate and split from freelist if the size of the allocation
// is at least 1/4th the size of the available block.
...
...
@@ -258,6 +240,7 @@ class BlockFreelist VALUE_OBJ_CLASS_SPEC {
void
print_on
(
outputStream
*
st
)
const
;
};
// A VirtualSpaceList node.
class
VirtualSpaceNode
:
public
CHeapObj
<
mtClass
>
{
friend
class
VirtualSpaceList
;
...
...
@@ -414,13 +397,13 @@ void VirtualSpaceNode::purge(ChunkManager* chunk_manager) {
Metachunk
*
chunk
=
first_chunk
();
Metachunk
*
invalid_chunk
=
(
Metachunk
*
)
top
();
while
(
chunk
<
invalid_chunk
)
{
assert
(
chunk
->
is_
free
(),
"Should be mark
ed free"
);
MetaWord
*
next
=
((
MetaWord
*
)
chunk
)
+
chunk
->
word_size
();
chunk_manager
->
remove_chunk
(
chunk
);
assert
(
chunk
->
next
()
==
NULL
&&
chunk
->
prev
()
==
NULL
,
"Was not removed from its list"
);
chunk
=
(
Metachunk
*
)
next
;
assert
(
chunk
->
is_
tagged_free
(),
"Should be tagg
ed free"
);
MetaWord
*
next
=
((
MetaWord
*
)
chunk
)
+
chunk
->
word_size
();
chunk_manager
->
remove_chunk
(
chunk
);
assert
(
chunk
->
next
()
==
NULL
&&
chunk
->
prev
()
==
NULL
,
"Was not removed from its list"
);
chunk
=
(
Metachunk
*
)
next
;
}
}
...
...
@@ -434,7 +417,7 @@ uint VirtualSpaceNode::container_count_slow() {
// Don't count the chunks on the free lists. Those are
// still part of the VirtualSpaceNode but not currently
// counted.
if
(
!
chunk
->
is_free
())
{
if
(
!
chunk
->
is_
tagged_
free
())
{
count
++
;
}
chunk
=
(
Metachunk
*
)
next
;
...
...
@@ -753,14 +736,11 @@ class SpaceManager : public CHeapObj<mtClass> {
#endif
size_t
get_raw_word_size
(
size_t
word_size
)
{
// If only the dictionary is going to be used (i.e., no
// indexed free list), then there is a minimum size requirement.
// MinChunkSize is a placeholder for the real minimum size JJJ
size_t
byte_size
=
word_size
*
BytesPerWord
;
size_t
raw_bytes_size
=
MAX2
(
byte_size
,
Metablock
::
min_block_byte_size
());
raw_bytes_size
=
ARENA_ALIGN
(
raw_bytes_size
);
size_t
raw_bytes_size
=
MAX2
(
byte_size
,
sizeof
(
Metablock
));
raw_bytes_size
=
align_size_up
(
raw_bytes_size
,
Metachunk
::
object_alignment
());
size_t
raw_word_size
=
raw_bytes_size
/
BytesPerWord
;
assert
(
raw_word_size
*
BytesPerWord
==
raw_bytes_size
,
"Size problem"
);
...
...
@@ -813,17 +793,8 @@ BlockFreelist::~BlockFreelist() {
}
}
Metablock
*
BlockFreelist
::
initialize_free_chunk
(
MetaWord
*
p
,
size_t
word_size
)
{
Metablock
*
block
=
(
Metablock
*
)
p
;
block
->
set_word_size
(
word_size
);
block
->
set_prev
(
NULL
);
block
->
set_next
(
NULL
);
return
block
;
}
void
BlockFreelist
::
return_block
(
MetaWord
*
p
,
size_t
word_size
)
{
Metablock
*
free_chunk
=
initialize_free_chunk
(
p
,
word_size
);
Metablock
*
free_chunk
=
::
new
(
p
)
Metablock
(
word_size
);
if
(
dictionary
()
==
NULL
)
{
_dictionary
=
new
BlockTreeDictionary
();
}
...
...
@@ -1069,7 +1040,7 @@ void ChunkManager::remove_chunk(Metachunk* chunk) {
}
// Chunk is being removed from the chunks free list.
dec_free_chunks_total
(
chunk
->
capacity_
word_size
());
dec_free_chunks_total
(
chunk
->
word_size
());
}
// Walk the list of VirtualSpaceNodes and delete
...
...
@@ -1760,7 +1731,7 @@ void ChunkManager::free_chunks_put(Metachunk* chunk) {
chunk
->
set_next
(
free_list
->
head
());
free_list
->
set_head
(
chunk
);
// chunk is being returned to the chunk free list
inc_free_chunks_total
(
chunk
->
capacity_
word_size
());
inc_free_chunks_total
(
chunk
->
word_size
());
slow_locked_verify
();
}
...
...
@@ -1822,7 +1793,7 @@ Metachunk* ChunkManager::free_chunks_get(size_t word_size) {
}
// Chunk is being removed from the chunks free list.
dec_free_chunks_total
(
chunk
->
capacity_
word_size
());
dec_free_chunks_total
(
chunk
->
word_size
());
// Remove it from the links to this freelist
chunk
->
set_next
(
NULL
);
...
...
@@ -1830,7 +1801,7 @@ Metachunk* ChunkManager::free_chunks_get(size_t word_size) {
#ifdef ASSERT
// Chunk is no longer on any freelist. Setting to false make container_count_slow()
// work.
chunk
->
set_is_free
(
false
);
chunk
->
set_is_
tagged_
free
(
false
);
#endif
chunk
->
container
()
->
inc_container_count
();
...
...
@@ -1962,7 +1933,7 @@ size_t SpaceManager::sum_capacity_in_chunks_in_use() const {
for
(
ChunkIndex
i
=
ZeroIndex
;
i
<
NumberOfInUseLists
;
i
=
next_chunk_index
(
i
))
{
Metachunk
*
chunk
=
chunks_in_use
(
i
);
while
(
chunk
!=
NULL
)
{
sum
+=
chunk
->
capacity_
word_size
();
sum
+=
chunk
->
word_size
();
chunk
=
chunk
->
next
();
}
}
...
...
@@ -2210,7 +2181,7 @@ void ChunkManager::return_chunks(ChunkIndex index, Metachunk* chunks) {
// Capture the next link before it is changed
// by the call to return_chunk_at_head();
Metachunk
*
next
=
cur
->
next
();
cur
->
set_is_free
(
true
);
DEBUG_ONLY
(
cur
->
set_is_tagged_free
(
true
);)
list
->
return_chunk_at_head
(
cur
);
cur
=
next
;
}
...
...
@@ -2282,7 +2253,7 @@ SpaceManager::~SpaceManager() {
while
(
humongous_chunks
!=
NULL
)
{
#ifdef ASSERT
humongous_chunks
->
set_is_free
(
true
);
humongous_chunks
->
set_is_
tagged_
free
(
true
);
#endif
if
(
TraceMetadataChunkAllocation
&&
Verbose
)
{
gclog_or_tty
->
print
(
PTR_FORMAT
" ("
SIZE_FORMAT
") "
,
...
...
@@ -2545,7 +2516,7 @@ void SpaceManager::dump(outputStream* const out) const {
curr
->
print_on
(
out
);
curr_total
+=
curr
->
word_size
();
used
+=
curr
->
used_word_size
();
capacity
+=
curr
->
capacity_
word_size
();
capacity
+=
curr
->
word_size
();
waste
+=
curr
->
free_word_size
()
+
curr
->
overhead
();;
}
}
...
...
@@ -3396,7 +3367,7 @@ void Metaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) {
}
Meta
block
*
Metaspace
::
allocate
(
ClassLoaderData
*
loader_data
,
size_t
word_size
,
Meta
Word
*
Metaspace
::
allocate
(
ClassLoaderData
*
loader_data
,
size_t
word_size
,
bool
read_only
,
MetaspaceObj
::
Type
type
,
TRAPS
)
{
if
(
HAS_PENDING_EXCEPTION
)
{
assert
(
false
,
"Should not allocate with exception pending"
);
...
...
@@ -3415,10 +3386,14 @@ Metablock* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size,
MetaWord
*
result
=
space
->
allocate
(
word_size
,
NonClassType
);
if
(
result
==
NULL
)
{
report_out_of_shared_space
(
read_only
?
SharedReadOnly
:
SharedReadWrite
);
}
else
{
space
->
record_allocation
(
result
,
type
,
space
->
vsm
()
->
get_raw_word_size
(
word_size
));
}
return
Metablock
::
initialize
(
result
,
word_size
);
space
->
record_allocation
(
result
,
type
,
space
->
vsm
()
->
get_raw_word_size
(
word_size
));
// Zero initialize.
Copy
::
fill_to_aligned_words
((
HeapWord
*
)
result
,
word_size
,
0
);
return
result
;
}
MetadataType
mdtype
=
(
type
==
MetaspaceObj
::
ClassType
)
?
ClassType
:
NonClassType
;
...
...
@@ -3443,7 +3418,10 @@ Metablock* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size,
return
NULL
;
}
return
Metablock
::
initialize
(
result
,
word_size
);
// Zero initialize.
Copy
::
fill_to_aligned_words
((
HeapWord
*
)
result
,
word_size
,
0
);
return
result
;
}
void
Metaspace
::
report_metadata_oome
(
ClassLoaderData
*
loader_data
,
size_t
word_size
,
MetadataType
mdtype
,
TRAPS
)
{
...
...
src/share/vm/memory/metaspace.hpp
浏览文件 @
ef7c07c7
...
...
@@ -139,7 +139,6 @@ class Metaspace : public CHeapObj<mtClass> {
// Allocate space for metadata of type mdtype. This is space
// within a Metachunk and is used by
// allocate(ClassLoaderData*, size_t, bool, MetadataType, TRAPS)
// which returns a Metablock.
MetaWord
*
allocate
(
size_t
word_size
,
MetadataType
mdtype
);
// Virtual Space lists for both classes and other metadata
...
...
@@ -217,8 +216,8 @@ class Metaspace : public CHeapObj<mtClass> {
size_t
used_bytes_slow
(
MetadataType
mdtype
)
const
;
size_t
capacity_bytes_slow
(
MetadataType
mdtype
)
const
;
static
Meta
block
*
allocate
(
ClassLoaderData
*
loader_data
,
size_t
word_size
,
bool
read_only
,
MetaspaceObj
::
Type
type
,
TRAPS
);
static
Meta
Word
*
allocate
(
ClassLoaderData
*
loader_data
,
size_t
word_size
,
bool
read_only
,
MetaspaceObj
::
Type
type
,
TRAPS
);
void
deallocate
(
MetaWord
*
ptr
,
size_t
byte_size
,
bool
is_class
);
MetaWord
*
expand_and_allocate
(
size_t
size
,
...
...
src/share/vm/prims/jni.cpp
浏览文件 @
ef7c07c7
...
...
@@ -5059,6 +5059,7 @@ void TestReservedSpace_test();
void
TestReserveMemorySpecial_test
();
void
TestVirtualSpace_test
();
void
TestMetaspaceAux_test
();
void
TestMetachunk_test
();
#if INCLUDE_ALL_GCS
void
TestG1BiasedArray_test
();
#endif
...
...
@@ -5070,6 +5071,7 @@ void execute_internal_vm_tests() {
run_unit_test
(
TestReserveMemorySpecial_test
());
run_unit_test
(
TestVirtualSpace_test
());
run_unit_test
(
TestMetaspaceAux_test
());
run_unit_test
(
TestMetachunk_test
());
run_unit_test
(
GlobalDefinitions
::
test_globals
());
run_unit_test
(
GCTimerAllTest
::
all
());
run_unit_test
(
arrayOopDesc
::
test_max_array_length
());
...
...
src/share/vm/runtime/vmStructs.cpp
浏览文件 @
ef7c07c7
...
...
@@ -58,7 +58,7 @@
#include "memory/generation.hpp"
#include "memory/generationSpec.hpp"
#include "memory/heap.hpp"
#include "memory/meta
bloc
k.hpp"
#include "memory/meta
chun
k.hpp"
#include "memory/referenceType.hpp"
#include "memory/space.hpp"
#include "memory/tenuredGeneration.hpp"
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录