Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
bee8b017
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看板
提交
bee8b017
编写于
9月 30, 2008
作者:
J
jcoomes
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
6725697: par compact - rename class ChunkData to RegionData
Reviewed-by: iveresov, tonyp
上级
a039f22b
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
1057 addition
and
1048 deletion
+1057
-1048
src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp
src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp
+20
-21
src/share/vm/gc_implementation/parallelScavenge/pcTasks.hpp
src/share/vm/gc_implementation/parallelScavenge/pcTasks.hpp
+11
-11
src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp
...c_implementation/parallelScavenge/psCompactionManager.cpp
+48
-48
src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp
...c_implementation/parallelScavenge/psCompactionManager.hpp
+36
-35
src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
.../gc_implementation/parallelScavenge/psParallelCompact.cpp
+627
-613
src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp
.../gc_implementation/parallelScavenge/psParallelCompact.hpp
+269
-274
src/share/vm/runtime/globals.hpp
src/share/vm/runtime/globals.hpp
+5
-5
src/share/vm/utilities/taskqueue.cpp
src/share/vm/utilities/taskqueue.cpp
+27
-27
src/share/vm/utilities/taskqueue.hpp
src/share/vm/utilities/taskqueue.hpp
+14
-14
未找到文件。
src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp
浏览文件 @
bee8b017
...
...
@@ -146,7 +146,7 @@ void RefProcTaskExecutor::execute(ProcessTask& task)
{
ParallelScavengeHeap
*
heap
=
PSParallelCompact
::
gc_heap
();
uint
parallel_gc_threads
=
heap
->
gc_task_manager
()
->
workers
();
ChunkTaskQueueSet
*
qset
=
ParCompactionManager
::
chunk
_array
();
RegionTaskQueueSet
*
qset
=
ParCompactionManager
::
region
_array
();
ParallelTaskTerminator
terminator
(
parallel_gc_threads
,
qset
);
GCTaskQueue
*
q
=
GCTaskQueue
::
create
();
for
(
uint
i
=
0
;
i
<
parallel_gc_threads
;
i
++
)
{
...
...
@@ -205,38 +205,38 @@ void StealMarkingTask::do_it(GCTaskManager* manager, uint which) {
}
//
// Steal
Chunk
CompactionTask
// Steal
Region
CompactionTask
//
Steal
ChunkCompactionTask
::
StealChunkCompactionTask
(
ParallelTaskTerminator
*
t
)
:
_terminator
(
t
)
{}
;
Steal
RegionCompactionTask
::
StealRegionCompactionTask
(
ParallelTaskTerminator
*
t
)
:
_terminator
(
t
)
{}
void
Steal
Chunk
CompactionTask
::
do_it
(
GCTaskManager
*
manager
,
uint
which
)
{
void
Steal
Region
CompactionTask
::
do_it
(
GCTaskManager
*
manager
,
uint
which
)
{
assert
(
Universe
::
heap
()
->
is_gc_active
(),
"called outside gc"
);
NOT_PRODUCT
(
TraceTime
tm
(
"Steal
Chunk
CompactionTask"
,
NOT_PRODUCT
(
TraceTime
tm
(
"Steal
Region
CompactionTask"
,
PrintGCDetails
&&
TraceParallelOldGCTasks
,
true
,
gclog_or_tty
));
ParCompactionManager
*
cm
=
ParCompactionManager
::
gc_thread_compaction_manager
(
which
);
// Has to drain stacks first because there may be
chunk
s on
// Has to drain stacks first because there may be
region
s on
// preloaded onto the stack and this thread may never have
// done a draining task. Are the draining tasks needed?
cm
->
drain_
chunk
_stacks
();
cm
->
drain_
region
_stacks
();
size_t
chunk
_index
=
0
;
size_t
region
_index
=
0
;
int
random_seed
=
17
;
// If we're the termination task, try 10 rounds of stealing before
// setting the termination flag
while
(
true
)
{
if
(
ParCompactionManager
::
steal
(
which
,
&
random_seed
,
chunk
_index
))
{
PSParallelCompact
::
fill_and_update_
chunk
(
cm
,
chunk
_index
);
cm
->
drain_
chunk
_stacks
();
if
(
ParCompactionManager
::
steal
(
which
,
&
random_seed
,
region
_index
))
{
PSParallelCompact
::
fill_and_update_
region
(
cm
,
region
_index
);
cm
->
drain_
region
_stacks
();
}
else
{
if
(
terminator
()
->
offer_termination
())
{
break
;
...
...
@@ -249,11 +249,10 @@ void StealChunkCompactionTask::do_it(GCTaskManager* manager, uint which) {
UpdateDensePrefixTask
::
UpdateDensePrefixTask
(
PSParallelCompact
::
SpaceId
space_id
,
size_t
chunk_index_start
,
size_t
chunk_index_end
)
:
_space_id
(
space_id
),
_chunk_index_start
(
chunk_index_start
),
_chunk_index_end
(
chunk_index_end
)
{}
size_t
region_index_start
,
size_t
region_index_end
)
:
_space_id
(
space_id
),
_region_index_start
(
region_index_start
),
_region_index_end
(
region_index_end
)
{}
void
UpdateDensePrefixTask
::
do_it
(
GCTaskManager
*
manager
,
uint
which
)
{
...
...
@@ -265,8 +264,8 @@ void UpdateDensePrefixTask::do_it(GCTaskManager* manager, uint which) {
PSParallelCompact
::
update_and_deadwood_in_dense_prefix
(
cm
,
_space_id
,
_
chunk
_index_start
,
_
chunk
_index_end
);
_
region
_index_start
,
_
region
_index_end
);
}
void
DrainStacksCompactionTask
::
do_it
(
GCTaskManager
*
manager
,
uint
which
)
{
...
...
@@ -278,6 +277,6 @@ void DrainStacksCompactionTask::do_it(GCTaskManager* manager, uint which) {
ParCompactionManager
*
cm
=
ParCompactionManager
::
gc_thread_compaction_manager
(
which
);
// Process any
chunk
s already in the compaction managers stacks.
cm
->
drain_
chunk
_stacks
();
// Process any
region
s already in the compaction managers stacks.
cm
->
drain_
region
_stacks
();
}
src/share/vm/gc_implementation/parallelScavenge/pcTasks.hpp
浏览文件 @
bee8b017
...
...
@@ -188,18 +188,18 @@ class StealMarkingTask : public GCTask {
};
//
// Steal
Chunk
CompactionTask
// Steal
Region
CompactionTask
//
// This task is used to distribute work to idle threads.
//
class
Steal
Chunk
CompactionTask
:
public
GCTask
{
class
Steal
Region
CompactionTask
:
public
GCTask
{
private:
ParallelTaskTerminator
*
const
_terminator
;
public:
Steal
Chunk
CompactionTask
(
ParallelTaskTerminator
*
t
);
Steal
Region
CompactionTask
(
ParallelTaskTerminator
*
t
);
char
*
name
()
{
return
(
char
*
)
"steal-
chunk
-task"
;
}
char
*
name
()
{
return
(
char
*
)
"steal-
region
-task"
;
}
ParallelTaskTerminator
*
terminator
()
{
return
_terminator
;
}
virtual
void
do_it
(
GCTaskManager
*
manager
,
uint
which
);
...
...
@@ -215,15 +215,15 @@ class StealChunkCompactionTask : public GCTask {
class
UpdateDensePrefixTask
:
public
GCTask
{
private:
PSParallelCompact
::
SpaceId
_space_id
;
size_t
_
chunk
_index_start
;
size_t
_
chunk
_index_end
;
size_t
_
region
_index_start
;
size_t
_
region
_index_end
;
public:
char
*
name
()
{
return
(
char
*
)
"update-dense_prefix-task"
;
}
UpdateDensePrefixTask
(
PSParallelCompact
::
SpaceId
space_id
,
size_t
chunk
_index_start
,
size_t
chunk
_index_end
);
size_t
region
_index_start
,
size_t
region
_index_end
);
virtual
void
do_it
(
GCTaskManager
*
manager
,
uint
which
);
};
...
...
@@ -231,17 +231,17 @@ class UpdateDensePrefixTask : public GCTask {
//
// DrainStacksCompactionTask
//
// This task processes
chunk
s that have been added to the stacks of each
// This task processes
region
s that have been added to the stacks of each
// compaction manager.
//
// Trying to use one draining thread does not work because there are no
// guarantees about which task will be picked up by which thread. For example,
// if thread A gets all the preloaded
chunk
s, thread A may not get a draining
// if thread A gets all the preloaded
region
s, thread A may not get a draining
// task (they may all be done by other threads).
//
class
DrainStacksCompactionTask
:
public
GCTask
{
public:
char
*
name
()
{
return
(
char
*
)
"drain-
chunk
-task"
;
}
char
*
name
()
{
return
(
char
*
)
"drain-
region
-task"
;
}
virtual
void
do_it
(
GCTaskManager
*
manager
,
uint
which
);
};
src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp
浏览文件 @
bee8b017
...
...
@@ -30,7 +30,7 @@ ParCompactionManager** ParCompactionManager::_manager_array = NULL;
OopTaskQueueSet
*
ParCompactionManager
::
_stack_array
=
NULL
;
ObjectStartArray
*
ParCompactionManager
::
_start_array
=
NULL
;
ParMarkBitMap
*
ParCompactionManager
::
_mark_bitmap
=
NULL
;
ChunkTaskQueueSet
*
ParCompactionManager
::
_chunk
_array
=
NULL
;
RegionTaskQueueSet
*
ParCompactionManager
::
_region
_array
=
NULL
;
ParCompactionManager
::
ParCompactionManager
()
:
_action
(
CopyAndUpdate
)
{
...
...
@@ -46,13 +46,13 @@ ParCompactionManager::ParCompactionManager() :
// We want the overflow stack to be permanent
_overflow_stack
=
new
(
ResourceObj
::
C_HEAP
)
GrowableArray
<
oop
>
(
10
,
true
);
#ifdef USE_
Chunk
TaskQueueWithOverflow
chunk
_stack
()
->
initialize
();
#ifdef USE_
Region
TaskQueueWithOverflow
region
_stack
()
->
initialize
();
#else
chunk
_stack
()
->
initialize
();
region
_stack
()
->
initialize
();
// We want the overflow stack to be permanent
_
chunk
_overflow_stack
=
_
region
_overflow_stack
=
new
(
ResourceObj
::
C_HEAP
)
GrowableArray
<
size_t
>
(
10
,
true
);
#endif
...
...
@@ -86,18 +86,18 @@ void ParCompactionManager::initialize(ParMarkBitMap* mbm) {
_stack_array
=
new
OopTaskQueueSet
(
parallel_gc_threads
);
guarantee
(
_stack_array
!=
NULL
,
"Count not initialize promotion manager"
);
_
chunk_array
=
new
Chunk
TaskQueueSet
(
parallel_gc_threads
);
guarantee
(
_
chunk
_array
!=
NULL
,
"Count not initialize promotion manager"
);
_
region_array
=
new
Region
TaskQueueSet
(
parallel_gc_threads
);
guarantee
(
_
region
_array
!=
NULL
,
"Count not initialize promotion manager"
);
// Create and register the ParCompactionManager(s) for the worker threads.
for
(
uint
i
=
0
;
i
<
parallel_gc_threads
;
i
++
)
{
_manager_array
[
i
]
=
new
ParCompactionManager
();
guarantee
(
_manager_array
[
i
]
!=
NULL
,
"Could not create ParCompactionManager"
);
stack_array
()
->
register_queue
(
i
,
_manager_array
[
i
]
->
marking_stack
());
#ifdef USE_
Chunk
TaskQueueWithOverflow
chunk_array
()
->
register_queue
(
i
,
_manager_array
[
i
]
->
chunk
_stack
()
->
task_queue
());
#ifdef USE_
Region
TaskQueueWithOverflow
region_array
()
->
register_queue
(
i
,
_manager_array
[
i
]
->
region
_stack
()
->
task_queue
());
#else
chunk_array
()
->
register_queue
(
i
,
_manager_array
[
i
]
->
chunk
_stack
());
region_array
()
->
register_queue
(
i
,
_manager_array
[
i
]
->
region
_stack
());
#endif
}
...
...
@@ -153,31 +153,31 @@ oop ParCompactionManager::retrieve_for_scanning() {
return
NULL
;
}
// Save
chunk
on a stack
void
ParCompactionManager
::
save_for_processing
(
size_t
chunk
_index
)
{
// Save
region
on a stack
void
ParCompactionManager
::
save_for_processing
(
size_t
region
_index
)
{
#ifdef ASSERT
const
ParallelCompactData
&
sd
=
PSParallelCompact
::
summary_data
();
ParallelCompactData
::
ChunkData
*
const
chunk_ptr
=
sd
.
chunk
(
chunk
_index
);
assert
(
chunk
_ptr
->
claimed
(),
"must be claimed"
);
assert
(
chunk
_ptr
->
_pushed
++
==
0
,
"should only be pushed once"
);
ParallelCompactData
::
RegionData
*
const
region_ptr
=
sd
.
region
(
region
_index
);
assert
(
region
_ptr
->
claimed
(),
"must be claimed"
);
assert
(
region
_ptr
->
_pushed
++
==
0
,
"should only be pushed once"
);
#endif
chunk_stack_push
(
chunk
_index
);
region_stack_push
(
region
_index
);
}
void
ParCompactionManager
::
chunk_stack_push
(
size_t
chunk
_index
)
{
void
ParCompactionManager
::
region_stack_push
(
size_t
region
_index
)
{
#ifdef USE_
Chunk
TaskQueueWithOverflow
chunk_stack
()
->
save
(
chunk
_index
);
#ifdef USE_
Region
TaskQueueWithOverflow
region_stack
()
->
save
(
region
_index
);
#else
if
(
!
chunk_stack
()
->
push
(
chunk
_index
))
{
chunk_overflow_stack
()
->
push
(
chunk
_index
);
if
(
!
region_stack
()
->
push
(
region
_index
))
{
region_overflow_stack
()
->
push
(
region
_index
);
}
#endif
}
bool
ParCompactionManager
::
retrieve_for_processing
(
size_t
&
chunk
_index
)
{
#ifdef USE_
Chunk
TaskQueueWithOverflow
return
chunk_stack
()
->
retrieve
(
chunk
_index
);
bool
ParCompactionManager
::
retrieve_for_processing
(
size_t
&
region
_index
)
{
#ifdef USE_
Region
TaskQueueWithOverflow
return
region_stack
()
->
retrieve
(
region
_index
);
#else
// Should not be used in the parallel case
ShouldNotReachHere
();
...
...
@@ -230,14 +230,14 @@ void ParCompactionManager::drain_marking_stacks(OopClosure* blk) {
assert
(
overflow_stack
()
->
length
()
==
0
,
"Sanity"
);
}
void
ParCompactionManager
::
drain_
chunk
_overflow_stack
()
{
size_t
chunk
_index
=
(
size_t
)
-
1
;
while
(
chunk_stack
()
->
retrieve_from_overflow
(
chunk
_index
))
{
PSParallelCompact
::
fill_and_update_
chunk
(
this
,
chunk
_index
);
void
ParCompactionManager
::
drain_
region
_overflow_stack
()
{
size_t
region
_index
=
(
size_t
)
-
1
;
while
(
region_stack
()
->
retrieve_from_overflow
(
region
_index
))
{
PSParallelCompact
::
fill_and_update_
region
(
this
,
region
_index
);
}
}
void
ParCompactionManager
::
drain_
chunk
_stacks
()
{
void
ParCompactionManager
::
drain_
region
_stacks
()
{
#ifdef ASSERT
ParallelScavengeHeap
*
heap
=
(
ParallelScavengeHeap
*
)
Universe
::
heap
();
assert
(
heap
->
kind
()
==
CollectedHeap
::
ParallelScavengeHeap
,
"Sanity"
);
...
...
@@ -249,42 +249,42 @@ void ParCompactionManager::drain_chunk_stacks() {
#if 1 // def DO_PARALLEL - the serial code hasn't been updated
do
{
#ifdef USE_
Chunk
TaskQueueWithOverflow
#ifdef USE_
Region
TaskQueueWithOverflow
// Drain overflow stack first, so other threads can steal from
// claimed stack while we work.
size_t
chunk
_index
=
(
size_t
)
-
1
;
while
(
chunk_stack
()
->
retrieve_from_overflow
(
chunk
_index
))
{
PSParallelCompact
::
fill_and_update_
chunk
(
this
,
chunk
_index
);
size_t
region
_index
=
(
size_t
)
-
1
;
while
(
region_stack
()
->
retrieve_from_overflow
(
region
_index
))
{
PSParallelCompact
::
fill_and_update_
region
(
this
,
region
_index
);
}
while
(
chunk_stack
()
->
retrieve_from_stealable_queue
(
chunk
_index
))
{
PSParallelCompact
::
fill_and_update_
chunk
(
this
,
chunk
_index
);
while
(
region_stack
()
->
retrieve_from_stealable_queue
(
region
_index
))
{
PSParallelCompact
::
fill_and_update_
region
(
this
,
region
_index
);
}
}
while
(
!
chunk
_stack
()
->
is_empty
());
}
while
(
!
region
_stack
()
->
is_empty
());
#else
// Drain overflow stack first, so other threads can steal from
// claimed stack while we work.
while
(
!
chunk
_overflow_stack
()
->
is_empty
())
{
size_t
chunk_index
=
chunk
_overflow_stack
()
->
pop
();
PSParallelCompact
::
fill_and_update_
chunk
(
this
,
chunk
_index
);
while
(
!
region
_overflow_stack
()
->
is_empty
())
{
size_t
region_index
=
region
_overflow_stack
()
->
pop
();
PSParallelCompact
::
fill_and_update_
region
(
this
,
region
_index
);
}
size_t
chunk
_index
=
-
1
;
size_t
region
_index
=
-
1
;
// obj is a reference!!!
while
(
chunk_stack
()
->
pop_local
(
chunk
_index
))
{
while
(
region_stack
()
->
pop_local
(
region
_index
))
{
// It would be nice to assert about the type of objects we might
// pop, but they can come from anywhere, unfortunately.
PSParallelCompact
::
fill_and_update_
chunk
(
this
,
chunk
_index
);
PSParallelCompact
::
fill_and_update_
region
(
this
,
region
_index
);
}
}
while
((
chunk
_stack
()
->
size
()
!=
0
)
||
(
chunk
_overflow_stack
()
->
length
()
!=
0
));
}
while
((
region
_stack
()
->
size
()
!=
0
)
||
(
region
_overflow_stack
()
->
length
()
!=
0
));
#endif
#ifdef USE_
Chunk
TaskQueueWithOverflow
assert
(
chunk
_stack
()
->
is_empty
(),
"Sanity"
);
#ifdef USE_
Region
TaskQueueWithOverflow
assert
(
region
_stack
()
->
is_empty
(),
"Sanity"
);
#else
assert
(
chunk
_stack
()
->
size
()
==
0
,
"Sanity"
);
assert
(
chunk
_overflow_stack
()
->
length
()
==
0
,
"Sanity"
);
assert
(
region
_stack
()
->
size
()
==
0
,
"Sanity"
);
assert
(
region
_overflow_stack
()
->
length
()
==
0
,
"Sanity"
);
#endif
#else
oop
obj
;
...
...
src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp
浏览文件 @
bee8b017
...
...
@@ -52,7 +52,7 @@ class ParCompactionManager : public CHeapObj {
friend
class
ParallelTaskTerminator
;
friend
class
ParMarkBitMap
;
friend
class
PSParallelCompact
;
friend
class
Steal
Chunk
CompactionTask
;
friend
class
Steal
Region
CompactionTask
;
friend
class
UpdateAndFillClosure
;
friend
class
RefProcTaskExecutor
;
...
...
@@ -72,27 +72,27 @@ class ParCompactionManager : public CHeapObj {
// ------------------------ End don't putback if not needed
private:
static
ParCompactionManager
**
_manager_array
;
static
OopTaskQueueSet
*
_stack_array
;
static
ObjectStartArray
*
_start_array
;
static
ChunkTaskQueueSet
*
_chunk
_array
;
static
PSOldGen
*
_old_gen
;
OopTaskQueue
_marking_stack
;
GrowableArray
<
oop
>*
_overflow_stack
;
static
ParCompactionManager
**
_manager_array
;
static
OopTaskQueueSet
*
_stack_array
;
static
ObjectStartArray
*
_start_array
;
static
RegionTaskQueueSet
*
_region
_array
;
static
PSOldGen
*
_old_gen
;
OopTaskQueue
_marking_stack
;
GrowableArray
<
oop
>*
_overflow_stack
;
// Is there a way to reuse the _marking_stack for the
// saving empty
chunk
s? For now just create a different
// saving empty
region
s? For now just create a different
// type of TaskQueue.
#ifdef USE_
Chunk
TaskQueueWithOverflow
ChunkTaskQueueWithOverflow
_chunk
_stack
;
#ifdef USE_
Region
TaskQueueWithOverflow
RegionTaskQueueWithOverflow
_region
_stack
;
#else
ChunkTaskQueue
_chunk
_stack
;
GrowableArray
<
size_t
>*
_chunk
_overflow_stack
;
RegionTaskQueue
_region
_stack
;
GrowableArray
<
size_t
>*
_region
_overflow_stack
;
#endif
#if 1 // does this happen enough to need a per thread stack?
GrowableArray
<
Klass
*>*
_revisit_klass_stack
;
GrowableArray
<
Klass
*>*
_revisit_klass_stack
;
#endif
static
ParMarkBitMap
*
_mark_bitmap
;
...
...
@@ -100,21 +100,22 @@ class ParCompactionManager : public CHeapObj {
static
PSOldGen
*
old_gen
()
{
return
_old_gen
;
}
static
ObjectStartArray
*
start_array
()
{
return
_start_array
;
}
static
OopTaskQueueSet
*
stack_array
()
{
return
_stack_array
;
}
static
OopTaskQueueSet
*
stack_array
()
{
return
_stack_array
;
}
static
void
initialize
(
ParMarkBitMap
*
mbm
);
protected:
// Array of tasks. Needed by the ParallelTaskTerminator.
static
ChunkTaskQueueSet
*
chunk_array
()
{
return
_chunk_array
;
}
OopTaskQueue
*
marking_stack
()
{
return
&
_marking_stack
;
}
GrowableArray
<
oop
>*
overflow_stack
()
{
return
_overflow_stack
;
}
#ifdef USE_ChunkTaskQueueWithOverflow
ChunkTaskQueueWithOverflow
*
chunk_stack
()
{
return
&
_chunk_stack
;
}
static
RegionTaskQueueSet
*
region_array
()
{
return
_region_array
;
}
OopTaskQueue
*
marking_stack
()
{
return
&
_marking_stack
;
}
GrowableArray
<
oop
>*
overflow_stack
()
{
return
_overflow_stack
;
}
#ifdef USE_RegionTaskQueueWithOverflow
RegionTaskQueueWithOverflow
*
region_stack
()
{
return
&
_region_stack
;
}
#else
ChunkTaskQueue
*
chunk_stack
()
{
return
&
_chunk_stack
;
}
GrowableArray
<
size_t
>*
chunk_overflow_stack
()
{
return
_chunk_overflow_stack
;
}
RegionTaskQueue
*
region_stack
()
{
return
&
_region_stack
;
}
GrowableArray
<
size_t
>*
region_overflow_stack
()
{
return
_region_overflow_stack
;
}
#endif
// Pushes onto the marking stack. If the marking stack is full,
...
...
@@ -123,9 +124,9 @@ class ParCompactionManager : public CHeapObj {
// Do not implement an equivalent stack_pop. Deal with the
// marking stack and overflow stack directly.
// Pushes onto the
chunk stack. If the chunk
stack is full,
// pushes onto the
chunk
overflow stack.
void
chunk_stack_push
(
size_t
chunk
_index
);
// Pushes onto the
region stack. If the region
stack is full,
// pushes onto the
region
overflow stack.
void
region_stack_push
(
size_t
region
_index
);
public:
Action
action
()
{
return
_action
;
}
...
...
@@ -160,10 +161,10 @@ class ParCompactionManager : public CHeapObj {
// Get a oop for scanning. If returns null, no oop were found.
oop
retrieve_for_scanning
();
// Save
chunk
for later processing. Must not fail.
void
save_for_processing
(
size_t
chunk
_index
);
// Get a
chunk for processing. If returns null, no chunk
were found.
bool
retrieve_for_processing
(
size_t
&
chunk
_index
);
// Save
region
for later processing. Must not fail.
void
save_for_processing
(
size_t
region
_index
);
// Get a
region for processing. If returns null, no region
were found.
bool
retrieve_for_processing
(
size_t
&
region
_index
);
// Access function for compaction managers
static
ParCompactionManager
*
gc_thread_compaction_manager
(
int
index
);
...
...
@@ -172,18 +173,18 @@ class ParCompactionManager : public CHeapObj {
return
stack_array
()
->
steal
(
queue_num
,
seed
,
t
);
}
static
bool
steal
(
int
queue_num
,
int
*
seed
,
Chunk
Task
&
t
)
{
return
chunk
_array
()
->
steal
(
queue_num
,
seed
,
t
);
static
bool
steal
(
int
queue_num
,
int
*
seed
,
Region
Task
&
t
)
{
return
region
_array
()
->
steal
(
queue_num
,
seed
,
t
);
}
// Process tasks remaining on any stack
void
drain_marking_stacks
(
OopClosure
*
blk
);
// Process tasks remaining on any stack
void
drain_
chunk
_stacks
();
void
drain_
region
_stacks
();
// Process tasks remaining on any stack
void
drain_
chunk
_overflow_stack
();
void
drain_
region
_overflow_stack
();
// Debugging support
#ifdef ASSERT
...
...
src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
浏览文件 @
bee8b017
...
...
@@ -28,12 +28,13 @@
#include <math.h>
// All sizes are in HeapWords.
const
size_t
ParallelCompactData
::
Log2ChunkSize
=
9
;
// 512 words
const
size_t
ParallelCompactData
::
ChunkSize
=
(
size_t
)
1
<<
Log2ChunkSize
;
const
size_t
ParallelCompactData
::
ChunkSizeBytes
=
ChunkSize
<<
LogHeapWordSize
;
const
size_t
ParallelCompactData
::
ChunkSizeOffsetMask
=
ChunkSize
-
1
;
const
size_t
ParallelCompactData
::
ChunkAddrOffsetMask
=
ChunkSizeBytes
-
1
;
const
size_t
ParallelCompactData
::
ChunkAddrMask
=
~
ChunkAddrOffsetMask
;
const
size_t
ParallelCompactData
::
Log2RegionSize
=
9
;
// 512 words
const
size_t
ParallelCompactData
::
RegionSize
=
(
size_t
)
1
<<
Log2RegionSize
;
const
size_t
ParallelCompactData
::
RegionSizeBytes
=
RegionSize
<<
LogHeapWordSize
;
const
size_t
ParallelCompactData
::
RegionSizeOffsetMask
=
RegionSize
-
1
;
const
size_t
ParallelCompactData
::
RegionAddrOffsetMask
=
RegionSizeBytes
-
1
;
const
size_t
ParallelCompactData
::
RegionAddrMask
=
~
RegionAddrOffsetMask
;
// 32-bit: 128 words covers 4 bitmap words
// 64-bit: 128 words covers 2 bitmap words
...
...
@@ -42,25 +43,25 @@ const size_t ParallelCompactData::BlockSize = (size_t)1 << Log2BlockSize;
const
size_t
ParallelCompactData
::
BlockOffsetMask
=
BlockSize
-
1
;
const
size_t
ParallelCompactData
::
BlockMask
=
~
BlockOffsetMask
;
const
size_t
ParallelCompactData
::
BlocksPer
Chunk
=
Chunk
Size
/
BlockSize
;
const
size_t
ParallelCompactData
::
BlocksPer
Region
=
Region
Size
/
BlockSize
;
const
ParallelCompactData
::
ChunkData
::
chunk
_sz_t
ParallelCompactData
::
Chunk
Data
::
dc_shift
=
27
;
const
ParallelCompactData
::
RegionData
::
region
_sz_t
ParallelCompactData
::
Region
Data
::
dc_shift
=
27
;
const
ParallelCompactData
::
ChunkData
::
chunk
_sz_t
ParallelCompactData
::
Chunk
Data
::
dc_mask
=
~
0U
<<
dc_shift
;
const
ParallelCompactData
::
RegionData
::
region
_sz_t
ParallelCompactData
::
Region
Data
::
dc_mask
=
~
0U
<<
dc_shift
;
const
ParallelCompactData
::
ChunkData
::
chunk
_sz_t
ParallelCompactData
::
Chunk
Data
::
dc_one
=
0x1U
<<
dc_shift
;
const
ParallelCompactData
::
RegionData
::
region
_sz_t
ParallelCompactData
::
Region
Data
::
dc_one
=
0x1U
<<
dc_shift
;
const
ParallelCompactData
::
ChunkData
::
chunk
_sz_t
ParallelCompactData
::
Chunk
Data
::
los_mask
=
~
dc_mask
;
const
ParallelCompactData
::
RegionData
::
region
_sz_t
ParallelCompactData
::
Region
Data
::
los_mask
=
~
dc_mask
;
const
ParallelCompactData
::
ChunkData
::
chunk
_sz_t
ParallelCompactData
::
Chunk
Data
::
dc_claimed
=
0x8U
<<
dc_shift
;
const
ParallelCompactData
::
RegionData
::
region
_sz_t
ParallelCompactData
::
Region
Data
::
dc_claimed
=
0x8U
<<
dc_shift
;
const
ParallelCompactData
::
ChunkData
::
chunk
_sz_t
ParallelCompactData
::
Chunk
Data
::
dc_completed
=
0xcU
<<
dc_shift
;
const
ParallelCompactData
::
RegionData
::
region
_sz_t
ParallelCompactData
::
Region
Data
::
dc_completed
=
0xcU
<<
dc_shift
;
#ifdef ASSERT
short
ParallelCompactData
::
BlockData
::
_cur_phase
=
0
;
...
...
@@ -105,7 +106,7 @@ const char* PSParallelCompact::space_names[] = {
"perm"
,
"old "
,
"eden"
,
"from"
,
"to "
};
void
PSParallelCompact
::
print_
chunk
_ranges
()
void
PSParallelCompact
::
print_
region
_ranges
()
{
tty
->
print_cr
(
"space bottom top end new_top"
);
tty
->
print_cr
(
"------ ---------- ---------- ---------- ----------"
);
...
...
@@ -116,31 +117,31 @@ void PSParallelCompact::print_chunk_ranges()
SIZE_FORMAT_W
(
10
)
" "
SIZE_FORMAT_W
(
10
)
" "
SIZE_FORMAT_W
(
10
)
" "
SIZE_FORMAT_W
(
10
)
" "
,
id
,
space_names
[
id
],
summary_data
().
addr_to_
chunk
_idx
(
space
->
bottom
()),
summary_data
().
addr_to_
chunk
_idx
(
space
->
top
()),
summary_data
().
addr_to_
chunk
_idx
(
space
->
end
()),
summary_data
().
addr_to_
chunk
_idx
(
_space_info
[
id
].
new_top
()));
summary_data
().
addr_to_
region
_idx
(
space
->
bottom
()),
summary_data
().
addr_to_
region
_idx
(
space
->
top
()),
summary_data
().
addr_to_
region
_idx
(
space
->
end
()),
summary_data
().
addr_to_
region
_idx
(
_space_info
[
id
].
new_top
()));
}
}
void
print_generic_summary_
chunk
(
size_t
i
,
const
ParallelCompactData
::
Chunk
Data
*
c
)
print_generic_summary_
region
(
size_t
i
,
const
ParallelCompactData
::
Region
Data
*
c
)
{
#define
CHUNK
_IDX_FORMAT SIZE_FORMAT_W(7)
#define
CHUNK
_DATA_FORMAT SIZE_FORMAT_W(5)
#define
REGION
_IDX_FORMAT SIZE_FORMAT_W(7)
#define
REGION
_DATA_FORMAT SIZE_FORMAT_W(5)
ParallelCompactData
&
sd
=
PSParallelCompact
::
summary_data
();
size_t
dci
=
c
->
destination
()
?
sd
.
addr_to_
chunk
_idx
(
c
->
destination
())
:
0
;
tty
->
print_cr
(
CHUNK
_IDX_FORMAT
" "
PTR_FORMAT
" "
CHUNK
_IDX_FORMAT
" "
PTR_FORMAT
" "
CHUNK_DATA_FORMAT
" "
CHUNK
_DATA_FORMAT
" "
CHUNK_DATA_FORMAT
" "
CHUNK
_IDX_FORMAT
" %d"
,
size_t
dci
=
c
->
destination
()
?
sd
.
addr_to_
region
_idx
(
c
->
destination
())
:
0
;
tty
->
print_cr
(
REGION
_IDX_FORMAT
" "
PTR_FORMAT
" "
REGION
_IDX_FORMAT
" "
PTR_FORMAT
" "
REGION_DATA_FORMAT
" "
REGION
_DATA_FORMAT
" "
REGION_DATA_FORMAT
" "
REGION
_IDX_FORMAT
" %d"
,
i
,
c
->
data_location
(),
dci
,
c
->
destination
(),
c
->
partial_obj_size
(),
c
->
live_obj_size
(),
c
->
data_size
(),
c
->
source_
chunk
(),
c
->
destination_count
());
c
->
data_size
(),
c
->
source_
region
(),
c
->
destination_count
());
#undef
CHUNK
_IDX_FORMAT
#undef
CHUNK
_DATA_FORMAT
#undef
REGION
_IDX_FORMAT
#undef
REGION
_DATA_FORMAT
}
void
...
...
@@ -149,14 +150,14 @@ print_generic_summary_data(ParallelCompactData& summary_data,
HeapWord
*
const
end_addr
)
{
size_t
total_words
=
0
;
size_t
i
=
summary_data
.
addr_to_
chunk
_idx
(
beg_addr
);
const
size_t
last
=
summary_data
.
addr_to_
chunk
_idx
(
end_addr
);
size_t
i
=
summary_data
.
addr_to_
region
_idx
(
beg_addr
);
const
size_t
last
=
summary_data
.
addr_to_
region
_idx
(
end_addr
);
HeapWord
*
pdest
=
0
;
while
(
i
<=
last
)
{
ParallelCompactData
::
ChunkData
*
c
=
summary_data
.
chunk
(
i
);
ParallelCompactData
::
RegionData
*
c
=
summary_data
.
region
(
i
);
if
(
c
->
data_size
()
!=
0
||
c
->
destination
()
!=
pdest
)
{
print_generic_summary_
chunk
(
i
,
c
);
print_generic_summary_
region
(
i
,
c
);
total_words
+=
c
->
data_size
();
pdest
=
c
->
destination
();
}
...
...
@@ -178,16 +179,16 @@ print_generic_summary_data(ParallelCompactData& summary_data,
}
void
print_initial_summary_
chunk
(
size_t
i
,
const
ParallelCompactData
::
Chunk
Data
*
c
,
bool
newline
=
true
)
print_initial_summary_
region
(
size_t
i
,
const
ParallelCompactData
::
Region
Data
*
c
,
bool
newline
=
true
)
{
tty
->
print
(
SIZE_FORMAT_W
(
5
)
" "
PTR_FORMAT
" "
SIZE_FORMAT_W
(
5
)
" "
SIZE_FORMAT_W
(
5
)
" "
SIZE_FORMAT_W
(
5
)
" "
SIZE_FORMAT_W
(
5
)
" %d"
,
i
,
c
->
destination
(),
c
->
partial_obj_size
(),
c
->
live_obj_size
(),
c
->
data_size
(),
c
->
source_
chunk
(),
c
->
destination_count
());
c
->
data_size
(),
c
->
source_
region
(),
c
->
destination_count
());
if
(
newline
)
tty
->
cr
();
}
...
...
@@ -198,47 +199,48 @@ print_initial_summary_data(ParallelCompactData& summary_data,
return
;
}
const
size_t
chunk_size
=
ParallelCompactData
::
ChunkSize
;
HeapWord
*
const
top_aligned_up
=
summary_data
.
chunk_align_up
(
space
->
top
());
const
size_t
end_chunk
=
summary_data
.
addr_to_chunk_idx
(
top_aligned_up
);
const
ParallelCompactData
::
ChunkData
*
c
=
summary_data
.
chunk
(
end_chunk
-
1
);
const
size_t
region_size
=
ParallelCompactData
::
RegionSize
;
typedef
ParallelCompactData
::
RegionData
RegionData
;
HeapWord
*
const
top_aligned_up
=
summary_data
.
region_align_up
(
space
->
top
());
const
size_t
end_region
=
summary_data
.
addr_to_region_idx
(
top_aligned_up
);
const
RegionData
*
c
=
summary_data
.
region
(
end_region
-
1
);
HeapWord
*
end_addr
=
c
->
destination
()
+
c
->
data_size
();
const
size_t
live_in_space
=
pointer_delta
(
end_addr
,
space
->
bottom
());
// Print (and count) the full
chunk
s at the beginning of the space.
size_t
full_
chunk
_count
=
0
;
size_t
i
=
summary_data
.
addr_to_
chunk
_idx
(
space
->
bottom
());
while
(
i
<
end_
chunk
&&
summary_data
.
chunk
(
i
)
->
data_size
()
==
chunk
_size
)
{
print_initial_summary_
chunk
(
i
,
summary_data
.
chunk
(
i
));
++
full_
chunk
_count
;
// Print (and count) the full
region
s at the beginning of the space.
size_t
full_
region
_count
=
0
;
size_t
i
=
summary_data
.
addr_to_
region
_idx
(
space
->
bottom
());
while
(
i
<
end_
region
&&
summary_data
.
region
(
i
)
->
data_size
()
==
region
_size
)
{
print_initial_summary_
region
(
i
,
summary_data
.
region
(
i
));
++
full_
region
_count
;
++
i
;
}
size_t
live_to_right
=
live_in_space
-
full_
chunk_count
*
chunk
_size
;
size_t
live_to_right
=
live_in_space
-
full_
region_count
*
region
_size
;
double
max_reclaimed_ratio
=
0.0
;
size_t
max_reclaimed_ratio_
chunk
=
0
;
size_t
max_reclaimed_ratio_
region
=
0
;
size_t
max_dead_to_right
=
0
;
size_t
max_live_to_right
=
0
;
// Print the 'reclaimed ratio' for
chunks while there is something live in the
//
chunk or to the right of it. The remaining chunk
s are empty (and
// Print the 'reclaimed ratio' for
regions while there is something live in
//
the region or to the right of it. The remaining region
s are empty (and
// uninteresting), and computing the ratio will result in division by 0.
while
(
i
<
end_
chunk
&&
live_to_right
>
0
)
{
c
=
summary_data
.
chunk
(
i
);
HeapWord
*
const
chunk_addr
=
summary_data
.
chunk
_to_addr
(
i
);
const
size_t
used_to_right
=
pointer_delta
(
space
->
top
(),
chunk
_addr
);
while
(
i
<
end_
region
&&
live_to_right
>
0
)
{
c
=
summary_data
.
region
(
i
);
HeapWord
*
const
region_addr
=
summary_data
.
region
_to_addr
(
i
);
const
size_t
used_to_right
=
pointer_delta
(
space
->
top
(),
region
_addr
);
const
size_t
dead_to_right
=
used_to_right
-
live_to_right
;
const
double
reclaimed_ratio
=
double
(
dead_to_right
)
/
live_to_right
;
if
(
reclaimed_ratio
>
max_reclaimed_ratio
)
{
max_reclaimed_ratio
=
reclaimed_ratio
;
max_reclaimed_ratio_
chunk
=
i
;
max_reclaimed_ratio_
region
=
i
;
max_dead_to_right
=
dead_to_right
;
max_live_to_right
=
live_to_right
;
}
print_initial_summary_
chunk
(
i
,
c
,
false
);
print_initial_summary_
region
(
i
,
c
,
false
);
tty
->
print_cr
(
" %12.10f "
SIZE_FORMAT_W
(
10
)
" "
SIZE_FORMAT_W
(
10
),
reclaimed_ratio
,
dead_to_right
,
live_to_right
);
...
...
@@ -246,14 +248,14 @@ print_initial_summary_data(ParallelCompactData& summary_data,
++
i
;
}
// Any remaining
chunk
s are empty. Print one more if there is one.
if
(
i
<
end_
chunk
)
{
print_initial_summary_
chunk
(
i
,
summary_data
.
chunk
(
i
));
// Any remaining
region
s are empty. Print one more if there is one.
if
(
i
<
end_
region
)
{
print_initial_summary_
region
(
i
,
summary_data
.
region
(
i
));
}
tty
->
print_cr
(
"max: "
SIZE_FORMAT_W
(
4
)
" d2r="
SIZE_FORMAT_W
(
10
)
" "
"l2r="
SIZE_FORMAT_W
(
10
)
" max_ratio=%14.12f"
,
max_reclaimed_ratio_
chunk
,
max_dead_to_right
,
max_reclaimed_ratio_
region
,
max_dead_to_right
,
max_live_to_right
,
max_reclaimed_ratio
);
}
...
...
@@ -285,9 +287,9 @@ ParallelCompactData::ParallelCompactData()
{
_region_start
=
0
;
_
chunk
_vspace
=
0
;
_
chunk
_data
=
0
;
_
chunk
_count
=
0
;
_
region
_vspace
=
0
;
_
region
_data
=
0
;
_
region
_count
=
0
;
_block_vspace
=
0
;
_block_data
=
0
;
...
...
@@ -300,16 +302,16 @@ bool ParallelCompactData::initialize(MemRegion covered_region)
const
size_t
region_size
=
covered_region
.
word_size
();
DEBUG_ONLY
(
_region_end
=
_region_start
+
region_size
;)
assert
(
chunk
_align_down
(
_region_start
)
==
_region_start
,
assert
(
region
_align_down
(
_region_start
)
==
_region_start
,
"region start not aligned"
);
assert
((
region_size
&
Chunk
SizeOffsetMask
)
==
0
,
"region size not a multiple of
Chunk
Size"
);
assert
((
region_size
&
Region
SizeOffsetMask
)
==
0
,
"region size not a multiple of
Region
Size"
);
bool
result
=
initialize_
chunk
_data
(
region_size
);
bool
result
=
initialize_
region
_data
(
region_size
);
// Initialize the block data if it will be used for updating pointers, or if
// this is a debug build.
if
(
!
UseParallelOldGC
Chunk
PointerCalc
||
trueInDebug
)
{
if
(
!
UseParallelOldGC
Region
PointerCalc
||
trueInDebug
)
{
result
=
result
&&
initialize_block_data
(
region_size
);
}
...
...
@@ -342,13 +344,13 @@ ParallelCompactData::create_vspace(size_t count, size_t element_size)
return
0
;
}
bool
ParallelCompactData
::
initialize_
chunk
_data
(
size_t
region_size
)
bool
ParallelCompactData
::
initialize_
region
_data
(
size_t
region_size
)
{
const
size_t
count
=
(
region_size
+
ChunkSizeOffsetMask
)
>>
Log2Chunk
Size
;
_
chunk_vspace
=
create_vspace
(
count
,
sizeof
(
Chunk
Data
));
if
(
_
chunk
_vspace
!=
0
)
{
_
chunk_data
=
(
ChunkData
*
)
_chunk
_vspace
->
reserved_low_addr
();
_
chunk
_count
=
count
;
const
size_t
count
=
(
region_size
+
RegionSizeOffsetMask
)
>>
Log2Region
Size
;
_
region_vspace
=
create_vspace
(
count
,
sizeof
(
Region
Data
));
if
(
_
region
_vspace
!=
0
)
{
_
region_data
=
(
RegionData
*
)
_region
_vspace
->
reserved_low_addr
();
_
region
_count
=
count
;
return
true
;
}
return
false
;
...
...
@@ -371,35 +373,35 @@ void ParallelCompactData::clear()
if
(
_block_data
)
{
memset
(
_block_data
,
0
,
_block_vspace
->
committed_size
());
}
memset
(
_
chunk_data
,
0
,
_chunk
_vspace
->
committed_size
());
memset
(
_
region_data
,
0
,
_region
_vspace
->
committed_size
());
}
void
ParallelCompactData
::
clear_range
(
size_t
beg_
chunk
,
size_t
end_chunk
)
{
assert
(
beg_
chunk
<=
_chunk_count
,
"beg_chunk
out of range"
);
assert
(
end_
chunk
<=
_chunk_count
,
"end_chunk
out of range"
);
assert
(
ChunkSize
%
BlockSize
==
0
,
"Chunk
Size not a multiple of BlockSize"
);
void
ParallelCompactData
::
clear_range
(
size_t
beg_
region
,
size_t
end_region
)
{
assert
(
beg_
region
<=
_region_count
,
"beg_region
out of range"
);
assert
(
end_
region
<=
_region_count
,
"end_region
out of range"
);
assert
(
RegionSize
%
BlockSize
==
0
,
"Region
Size not a multiple of BlockSize"
);
const
size_t
chunk_cnt
=
end_chunk
-
beg_chunk
;
const
size_t
region_cnt
=
end_region
-
beg_region
;
if
(
_block_data
)
{
const
size_t
blocks_per_
chunk
=
Chunk
Size
/
BlockSize
;
const
size_t
beg_block
=
beg_
chunk
*
blocks_per_chunk
;
const
size_t
block_cnt
=
chunk_cnt
*
blocks_per_chunk
;
const
size_t
blocks_per_
region
=
Region
Size
/
BlockSize
;
const
size_t
beg_block
=
beg_
region
*
blocks_per_region
;
const
size_t
block_cnt
=
region_cnt
*
blocks_per_region
;
memset
(
_block_data
+
beg_block
,
0
,
block_cnt
*
sizeof
(
BlockData
));
}
memset
(
_
chunk_data
+
beg_chunk
,
0
,
chunk_cnt
*
sizeof
(
Chunk
Data
));
memset
(
_
region_data
+
beg_region
,
0
,
region_cnt
*
sizeof
(
Region
Data
));
}
HeapWord
*
ParallelCompactData
::
partial_obj_end
(
size_t
chunk
_idx
)
const
HeapWord
*
ParallelCompactData
::
partial_obj_end
(
size_t
region
_idx
)
const
{
const
ChunkData
*
cur_cp
=
chunk
(
chunk
_idx
);
const
ChunkData
*
const
end_cp
=
chunk
(
chunk
_count
()
-
1
);
const
RegionData
*
cur_cp
=
region
(
region
_idx
);
const
RegionData
*
const
end_cp
=
region
(
region
_count
()
-
1
);
HeapWord
*
result
=
chunk_to_addr
(
chunk
_idx
);
HeapWord
*
result
=
region_to_addr
(
region
_idx
);
if
(
cur_cp
<
end_cp
)
{
do
{
result
+=
cur_cp
->
partial_obj_size
();
}
while
(
cur_cp
->
partial_obj_size
()
==
Chunk
Size
&&
++
cur_cp
<
end_cp
);
}
while
(
cur_cp
->
partial_obj_size
()
==
Region
Size
&&
++
cur_cp
<
end_cp
);
}
return
result
;
}
...
...
@@ -407,56 +409,56 @@ HeapWord* ParallelCompactData::partial_obj_end(size_t chunk_idx) const
void
ParallelCompactData
::
add_obj
(
HeapWord
*
addr
,
size_t
len
)
{
const
size_t
obj_ofs
=
pointer_delta
(
addr
,
_region_start
);
const
size_t
beg_
chunk
=
obj_ofs
>>
Log2Chunk
Size
;
const
size_t
end_
chunk
=
(
obj_ofs
+
len
-
1
)
>>
Log2Chunk
Size
;
const
size_t
beg_
region
=
obj_ofs
>>
Log2Region
Size
;
const
size_t
end_
region
=
(
obj_ofs
+
len
-
1
)
>>
Log2Region
Size
;
DEBUG_ONLY
(
Atomic
::
inc_ptr
(
&
add_obj_count
);)
DEBUG_ONLY
(
Atomic
::
add_ptr
(
len
,
&
add_obj_size
);)
if
(
beg_
chunk
==
end_chunk
)
{
// All in one
chunk
.
_
chunk_data
[
beg_chunk
].
add_live_obj
(
len
);
if
(
beg_
region
==
end_region
)
{
// All in one
region
.
_
region_data
[
beg_region
].
add_live_obj
(
len
);
return
;
}
// First
chunk
.
const
size_t
beg_ofs
=
chunk
_offset
(
addr
);
_
chunk_data
[
beg_chunk
].
add_live_obj
(
Chunk
Size
-
beg_ofs
);
// First
region
.
const
size_t
beg_ofs
=
region
_offset
(
addr
);
_
region_data
[
beg_region
].
add_live_obj
(
Region
Size
-
beg_ofs
);
klassOop
klass
=
((
oop
)
addr
)
->
klass
();
// Middle
chunk
s--completely spanned by this object.
for
(
size_t
chunk
=
beg_chunk
+
1
;
chunk
<
end_chunk
;
++
chunk
)
{
_
chunk_data
[
chunk
].
set_partial_obj_size
(
Chunk
Size
);
_
chunk_data
[
chunk
].
set_partial_obj_addr
(
addr
);
// Middle
region
s--completely spanned by this object.
for
(
size_t
region
=
beg_region
+
1
;
region
<
end_region
;
++
region
)
{
_
region_data
[
region
].
set_partial_obj_size
(
Region
Size
);
_
region_data
[
region
].
set_partial_obj_addr
(
addr
);
}
// Last
chunk
.
const
size_t
end_ofs
=
chunk
_offset
(
addr
+
len
-
1
);
_
chunk_data
[
end_chunk
].
set_partial_obj_size
(
end_ofs
+
1
);
_
chunk_data
[
end_chunk
].
set_partial_obj_addr
(
addr
);
// Last
region
.
const
size_t
end_ofs
=
region
_offset
(
addr
+
len
-
1
);
_
region_data
[
end_region
].
set_partial_obj_size
(
end_ofs
+
1
);
_
region_data
[
end_region
].
set_partial_obj_addr
(
addr
);
}
void
ParallelCompactData
::
summarize_dense_prefix
(
HeapWord
*
beg
,
HeapWord
*
end
)
{
assert
(
chunk_offset
(
beg
)
==
0
,
"not Chunk
Size aligned"
);
assert
(
chunk_offset
(
end
)
==
0
,
"not Chunk
Size aligned"
);
assert
(
region_offset
(
beg
)
==
0
,
"not Region
Size aligned"
);
assert
(
region_offset
(
end
)
==
0
,
"not Region
Size aligned"
);
size_t
cur_
chunk
=
addr_to_chunk
_idx
(
beg
);
const
size_t
end_
chunk
=
addr_to_chunk
_idx
(
end
);
size_t
cur_
region
=
addr_to_region
_idx
(
beg
);
const
size_t
end_
region
=
addr_to_region
_idx
(
end
);
HeapWord
*
addr
=
beg
;
while
(
cur_
chunk
<
end_chunk
)
{
_
chunk_data
[
cur_chunk
].
set_destination
(
addr
);
_
chunk_data
[
cur_chunk
].
set_destination_count
(
0
);
_
chunk_data
[
cur_chunk
].
set_source_chunk
(
cur_chunk
);
_
chunk_data
[
cur_chunk
].
set_data_location
(
addr
);
while
(
cur_
region
<
end_region
)
{
_
region_data
[
cur_region
].
set_destination
(
addr
);
_
region_data
[
cur_region
].
set_destination_count
(
0
);
_
region_data
[
cur_region
].
set_source_region
(
cur_region
);
_
region_data
[
cur_region
].
set_data_location
(
addr
);
// Update live_obj_size so the
chunk
appears completely full.
size_t
live_size
=
ChunkSize
-
_chunk_data
[
cur_chunk
].
partial_obj_size
();
_
chunk_data
[
cur_chunk
].
set_live_obj_size
(
live_size
);
// Update live_obj_size so the
region
appears completely full.
size_t
live_size
=
RegionSize
-
_region_data
[
cur_region
].
partial_obj_size
();
_
region_data
[
cur_region
].
set_live_obj_size
(
live_size
);
++
cur_
chunk
;
addr
+=
Chunk
Size
;
++
cur_
region
;
addr
+=
Region
Size
;
}
}
...
...
@@ -465,7 +467,7 @@ bool ParallelCompactData::summarize(HeapWord* target_beg, HeapWord* target_end,
HeapWord
**
target_next
,
HeapWord
**
source_next
)
{
// This is too strict.
// assert(
chunk_offset(source_beg) == 0, "not Chunk
Size aligned");
// assert(
region_offset(source_beg) == 0, "not Region
Size aligned");
if
(
TraceParallelOldGCSummaryPhase
)
{
tty
->
print_cr
(
"tb="
PTR_FORMAT
" te="
PTR_FORMAT
" "
...
...
@@ -477,85 +479,86 @@ bool ParallelCompactData::summarize(HeapWord* target_beg, HeapWord* target_end,
source_next
!=
0
?
*
source_next
:
(
HeapWord
*
)
0
);
}
size_t
cur_
chunk
=
addr_to_chunk
_idx
(
source_beg
);
const
size_t
end_
chunk
=
addr_to_chunk_idx
(
chunk
_align_up
(
source_end
));
size_t
cur_
region
=
addr_to_region
_idx
(
source_beg
);
const
size_t
end_
region
=
addr_to_region_idx
(
region
_align_up
(
source_end
));
HeapWord
*
dest_addr
=
target_beg
;
while
(
cur_
chunk
<
end_chunk
)
{
size_t
words
=
_
chunk_data
[
cur_chunk
].
data_size
();
while
(
cur_
region
<
end_region
)
{
size_t
words
=
_
region_data
[
cur_region
].
data_size
();
#if 1
assert
(
pointer_delta
(
target_end
,
dest_addr
)
>=
words
,
"source region does not fit into target region"
);
#else
// XXX - need some work on the corner cases here. If the chunk does not
// fit, then must either make sure any partial_obj from the chunk fits, or
// 'undo' the initial part of the partial_obj that is in the previous chunk.
// XXX - need some work on the corner cases here. If the region does not
// fit, then must either make sure any partial_obj from the region fits, or
// "undo" the initial part of the partial_obj that is in the previous
// region.
if
(
dest_addr
+
words
>=
target_end
)
{
// Let the caller know where to continue.
*
target_next
=
dest_addr
;
*
source_next
=
chunk_to_addr
(
cur_chunk
);
*
source_next
=
region_to_addr
(
cur_region
);
return
false
;
}
#endif // #if 1
_
chunk_data
[
cur_chunk
].
set_destination
(
dest_addr
);
_
region_data
[
cur_region
].
set_destination
(
dest_addr
);
// Set the destination_count for cur_
chunk
, and if necessary, update
// source_
chunk for a destination chunk. The source_chunk field is updated
//
if cur_chunk is the first (left-most) chunk to be copied to a destination
//
chunk
.
// Set the destination_count for cur_
region
, and if necessary, update
// source_
region for a destination region. The source_region field is
//
updated if cur_region is the first (left-most) region to be copied to a
//
destination region
.
//
// The destination_count calculation is a bit subtle. A
chunk that has data
//
that compacts into itself does not count itself as a destination. This
//
maintains the invariant that a zero count means the chunk is available
// and can be claimed and then filled.
// The destination_count calculation is a bit subtle. A
region that has
//
data that compacts into itself does not count itself as a destination.
//
This maintains the invariant that a zero count means the region is
// a
vailable a
nd can be claimed and then filled.
if
(
words
>
0
)
{
HeapWord
*
const
last_addr
=
dest_addr
+
words
-
1
;
const
size_t
dest_
chunk_1
=
addr_to_chunk
_idx
(
dest_addr
);
const
size_t
dest_
chunk_2
=
addr_to_chunk
_idx
(
last_addr
);
const
size_t
dest_
region_1
=
addr_to_region
_idx
(
dest_addr
);
const
size_t
dest_
region_2
=
addr_to_region
_idx
(
last_addr
);
#if 0
// Initially assume that the destination
chunk
s will be the same and
// Initially assume that the destination
region
s will be the same and
// adjust the value below if necessary. Under this assumption, if
// cur_
chunk == dest_chunk_2, then cur_chunk will be compacted completely
// into itself.
uint
destination_count
=
cur_
chunk
==
dest_chunk
_2
?
0
:
1
;
if
(
dest_
chunk_1
!=
dest_chunk
_2
)
{
// Destination
chunk
s differ; adjust destination_count.
// cur_
region == dest_region_2, then cur_region will be compacted
//
completely
into itself.
uint
destination_count
=
cur_
region
==
dest_region
_2
?
0
:
1
;
if
(
dest_
region_1
!=
dest_region
_2
)
{
// Destination
region
s differ; adjust destination_count.
destination_count
+=
1
;
// Data from cur_
chunk will be copied to the start of dest_chunk
_2.
_
chunk_data
[
dest_chunk_2
].
set_source_chunk
(
cur_chunk
);
}
else
if
(
chunk
_offset
(
dest_addr
)
==
0
)
{
// Data from cur_
chunk
will be copied to the start of the destination
//
chunk
.
_
chunk_data
[
dest_chunk_1
].
set_source_chunk
(
cur_chunk
);
// Data from cur_
region will be copied to the start of dest_region
_2.
_
region_data
[
dest_region_2
].
set_source_region
(
cur_region
);
}
else
if
(
region
_offset
(
dest_addr
)
==
0
)
{
// Data from cur_
region
will be copied to the start of the destination
//
region
.
_
region_data
[
dest_region_1
].
set_source_region
(
cur_region
);
}
#else
// Initially assume that the destination
chunk
s will be different and
// Initially assume that the destination
region
s will be different and
// adjust the value below if necessary. Under this assumption, if
// cur_
chunk == dest_chunk2, then cur_chunk
will be compacted partially
// into dest_
chunk
_1 and partially into itself.
uint
destination_count
=
cur_
chunk
==
dest_chunk
_2
?
1
:
2
;
if
(
dest_
chunk_1
!=
dest_chunk
_2
)
{
// Data from cur_
chunk will be copied to the start of dest_chunk
_2.
_
chunk_data
[
dest_chunk_2
].
set_source_chunk
(
cur_chunk
);
// cur_
region == dest_region2, then cur_region
will be compacted partially
// into dest_
region
_1 and partially into itself.
uint
destination_count
=
cur_
region
==
dest_region
_2
?
1
:
2
;
if
(
dest_
region_1
!=
dest_region
_2
)
{
// Data from cur_
region will be copied to the start of dest_region
_2.
_
region_data
[
dest_region_2
].
set_source_region
(
cur_region
);
}
else
{
// Destination
chunk
s are the same; adjust destination_count.
// Destination
region
s are the same; adjust destination_count.
destination_count
-=
1
;
if
(
chunk
_offset
(
dest_addr
)
==
0
)
{
// Data from cur_
chunk
will be copied to the start of the destination
//
chunk
.
_
chunk_data
[
dest_chunk_1
].
set_source_chunk
(
cur_chunk
);
if
(
region
_offset
(
dest_addr
)
==
0
)
{
// Data from cur_
region
will be copied to the start of the destination
//
region
.
_
region_data
[
dest_region_1
].
set_source_region
(
cur_region
);
}
}
#endif // #if 0
_
chunk_data
[
cur_chunk
].
set_destination_count
(
destination_count
);
_
chunk_data
[
cur_chunk
].
set_data_location
(
chunk_to_addr
(
cur_chunk
));
_
region_data
[
cur_region
].
set_destination_count
(
destination_count
);
_
region_data
[
cur_region
].
set_data_location
(
region_to_addr
(
cur_region
));
dest_addr
+=
words
;
}
++
cur_
chunk
;
++
cur_
region
;
}
*
target_next
=
dest_addr
;
...
...
@@ -565,8 +568,8 @@ bool ParallelCompactData::summarize(HeapWord* target_beg, HeapWord* target_end,
bool
ParallelCompactData
::
partial_obj_ends_in_block
(
size_t
block_index
)
{
HeapWord
*
block_addr
=
block_to_addr
(
block_index
);
HeapWord
*
block_end_addr
=
block_addr
+
BlockSize
;
size_t
chunk_index
=
addr_to_chunk
_idx
(
block_addr
);
HeapWord
*
partial_obj_end_addr
=
partial_obj_end
(
chunk
_index
);
size_t
region_index
=
addr_to_region
_idx
(
block_addr
);
HeapWord
*
partial_obj_end_addr
=
partial_obj_end
(
region
_index
);
// An object that ends at the end of the block, ends
// in the block (the last word of the object is to
...
...
@@ -581,8 +584,8 @@ bool ParallelCompactData::partial_obj_ends_in_block(size_t block_index) {
HeapWord
*
ParallelCompactData
::
calc_new_pointer
(
HeapWord
*
addr
)
{
HeapWord
*
result
=
NULL
;
if
(
UseParallelOldGC
Chunk
PointerCalc
)
{
result
=
chunk
_calc_new_pointer
(
addr
);
if
(
UseParallelOldGC
Region
PointerCalc
)
{
result
=
region
_calc_new_pointer
(
addr
);
}
else
{
result
=
block_calc_new_pointer
(
addr
);
}
...
...
@@ -595,7 +598,7 @@ HeapWord* ParallelCompactData::calc_new_pointer(HeapWord* addr) {
// the object is dead. But don't wast the cycles to explicitly check
// that it is dead since only live objects should be passed in.
HeapWord
*
ParallelCompactData
::
chunk
_calc_new_pointer
(
HeapWord
*
addr
)
{
HeapWord
*
ParallelCompactData
::
region
_calc_new_pointer
(
HeapWord
*
addr
)
{
assert
(
addr
!=
NULL
,
"Should detect NULL oop earlier"
);
assert
(
PSParallelCompact
::
gc_heap
()
->
is_in
(
addr
),
"addr not in heap"
);
#ifdef ASSERT
...
...
@@ -605,30 +608,30 @@ HeapWord* ParallelCompactData::chunk_calc_new_pointer(HeapWord* addr) {
#endif
assert
(
PSParallelCompact
::
mark_bitmap
()
->
is_marked
(
addr
),
"obj not marked"
);
//
Chunk
covering the object.
size_t
chunk_index
=
addr_to_chunk
_idx
(
addr
);
const
ChunkData
*
const
chunk_ptr
=
chunk
(
chunk
_index
);
HeapWord
*
const
chunk_addr
=
chunk
_align_down
(
addr
);
//
Region
covering the object.
size_t
region_index
=
addr_to_region
_idx
(
addr
);
const
RegionData
*
const
region_ptr
=
region
(
region
_index
);
HeapWord
*
const
region_addr
=
region
_align_down
(
addr
);
assert
(
addr
<
chunk_addr
+
ChunkSize
,
"Chunk
does not cover object"
);
assert
(
addr_to_
chunk_ptr
(
chunk_addr
)
==
chunk
_ptr
,
"sanity check"
);
assert
(
addr
<
region_addr
+
RegionSize
,
"Region
does not cover object"
);
assert
(
addr_to_
region_ptr
(
region_addr
)
==
region
_ptr
,
"sanity check"
);
HeapWord
*
result
=
chunk
_ptr
->
destination
();
HeapWord
*
result
=
region
_ptr
->
destination
();
// If all the data in the
chunk
is live, then the new location of the object
// can be calculated from the destination of the
chunk
plus the offset of the
// object in the
chunk
.
if
(
chunk_ptr
->
data_size
()
==
Chunk
Size
)
{
result
+=
pointer_delta
(
addr
,
chunk
_addr
);
// If all the data in the
region
is live, then the new location of the object
// can be calculated from the destination of the
region
plus the offset of the
// object in the
region
.
if
(
region_ptr
->
data_size
()
==
Region
Size
)
{
result
+=
pointer_delta
(
addr
,
region
_addr
);
return
result
;
}
// The new location of the object is
//
chunk
destination +
// size of the partial object extending onto the
chunk
+
// sizes of the live objects in the
Chunk
that are to the left of addr
const
size_t
partial_obj_size
=
chunk
_ptr
->
partial_obj_size
();
HeapWord
*
const
search_start
=
chunk
_addr
+
partial_obj_size
;
//
region
destination +
// size of the partial object extending onto the
region
+
// sizes of the live objects in the
Region
that are to the left of addr
const
size_t
partial_obj_size
=
region
_ptr
->
partial_obj_size
();
HeapWord
*
const
search_start
=
region
_addr
+
partial_obj_size
;
const
ParMarkBitMap
*
bitmap
=
PSParallelCompact
::
mark_bitmap
();
size_t
live_to_left
=
bitmap
->
live_words_in_range
(
search_start
,
oop
(
addr
));
...
...
@@ -648,37 +651,37 @@ HeapWord* ParallelCompactData::block_calc_new_pointer(HeapWord* addr) {
#endif
assert
(
PSParallelCompact
::
mark_bitmap
()
->
is_marked
(
addr
),
"obj not marked"
);
//
Chunk
covering the object.
size_t
chunk_index
=
addr_to_chunk
_idx
(
addr
);
const
ChunkData
*
const
chunk_ptr
=
chunk
(
chunk
_index
);
HeapWord
*
const
chunk_addr
=
chunk
_align_down
(
addr
);
//
Region
covering the object.
size_t
region_index
=
addr_to_region
_idx
(
addr
);
const
RegionData
*
const
region_ptr
=
region
(
region
_index
);
HeapWord
*
const
region_addr
=
region
_align_down
(
addr
);
assert
(
addr
<
chunk_addr
+
ChunkSize
,
"Chunk
does not cover object"
);
assert
(
addr_to_
chunk_ptr
(
chunk_addr
)
==
chunk
_ptr
,
"sanity check"
);
assert
(
addr
<
region_addr
+
RegionSize
,
"Region
does not cover object"
);
assert
(
addr_to_
region_ptr
(
region_addr
)
==
region
_ptr
,
"sanity check"
);
HeapWord
*
result
=
chunk
_ptr
->
destination
();
HeapWord
*
result
=
region
_ptr
->
destination
();
// If all the data in the
chunk
is live, then the new location of the object
// can be calculated from the destination of the
chunk
plus the offset of the
// object in the
chunk
.
if
(
chunk_ptr
->
data_size
()
==
Chunk
Size
)
{
result
+=
pointer_delta
(
addr
,
chunk
_addr
);
// If all the data in the
region
is live, then the new location of the object
// can be calculated from the destination of the
region
plus the offset of the
// object in the
region
.
if
(
region_ptr
->
data_size
()
==
Region
Size
)
{
result
+=
pointer_delta
(
addr
,
region
_addr
);
return
result
;
}
// The new location of the object is
//
chunk
destination +
//
region
destination +
// block offset +
// sizes of the live objects in the Block that are to the left of addr
const
size_t
block_offset
=
addr_to_block_ptr
(
addr
)
->
offset
();
HeapWord
*
const
search_start
=
chunk
_addr
+
block_offset
;
HeapWord
*
const
search_start
=
region
_addr
+
block_offset
;
const
ParMarkBitMap
*
bitmap
=
PSParallelCompact
::
mark_bitmap
();
size_t
live_to_left
=
bitmap
->
live_words_in_range
(
search_start
,
oop
(
addr
));
result
+=
block_offset
+
live_to_left
;
assert
(
result
<=
addr
,
"object cannot move to the right"
);
assert
(
result
==
chunk
_calc_new_pointer
(
addr
),
"Should match"
);
assert
(
result
==
region
_calc_new_pointer
(
addr
),
"Should match"
);
return
result
;
}
...
...
@@ -705,15 +708,15 @@ void ParallelCompactData::verify_clear(const PSVirtualSpace* vspace)
void
ParallelCompactData
::
verify_clear
()
{
verify_clear
(
_
chunk
_vspace
);
verify_clear
(
_
region
_vspace
);
verify_clear
(
_block_vspace
);
}
#endif // #ifdef ASSERT
#ifdef NOT_PRODUCT
ParallelCompactData
::
ChunkData
*
debug_chunk
(
size_t
chunk
_index
)
{
ParallelCompactData
::
RegionData
*
debug_region
(
size_t
region
_index
)
{
ParallelCompactData
&
sd
=
PSParallelCompact
::
summary_data
();
return
sd
.
chunk
(
chunk
_index
);
return
sd
.
region
(
region
_index
);
}
#endif
...
...
@@ -866,10 +869,10 @@ PSParallelCompact::clear_data_covering_space(SpaceId id)
const
idx_t
end_bit
=
BitMap
::
word_align_up
(
_mark_bitmap
.
addr_to_bit
(
top
));
_mark_bitmap
.
clear_range
(
beg_bit
,
end_bit
);
const
size_t
beg_
chunk
=
_summary_data
.
addr_to_chunk
_idx
(
bot
);
const
size_t
end_
chunk
=
_summary_data
.
addr_to_
chunk_idx
(
_summary_data
.
chunk
_align_up
(
max_top
));
_summary_data
.
clear_range
(
beg_
chunk
,
end_chunk
);
const
size_t
beg_
region
=
_summary_data
.
addr_to_region
_idx
(
bot
);
const
size_t
end_
region
=
_summary_data
.
addr_to_
region_idx
(
_summary_data
.
region
_align_up
(
max_top
));
_summary_data
.
clear_range
(
beg_
region
,
end_region
);
}
void
PSParallelCompact
::
pre_compact
(
PreGCValues
*
pre_gc_values
)
...
...
@@ -985,19 +988,19 @@ HeapWord*
PSParallelCompact
::
compute_dense_prefix_via_density
(
const
SpaceId
id
,
bool
maximum_compaction
)
{
const
size_t
chunk_size
=
ParallelCompactData
::
Chunk
Size
;
const
size_t
region_size
=
ParallelCompactData
::
Region
Size
;
const
ParallelCompactData
&
sd
=
summary_data
();
const
MutableSpace
*
const
space
=
_space_info
[
id
].
space
();
HeapWord
*
const
top_aligned_up
=
sd
.
chunk
_align_up
(
space
->
top
());
const
ChunkData
*
const
beg_cp
=
sd
.
addr_to_chunk
_ptr
(
space
->
bottom
());
const
ChunkData
*
const
end_cp
=
sd
.
addr_to_chunk
_ptr
(
top_aligned_up
);
HeapWord
*
const
top_aligned_up
=
sd
.
region
_align_up
(
space
->
top
());
const
RegionData
*
const
beg_cp
=
sd
.
addr_to_region
_ptr
(
space
->
bottom
());
const
RegionData
*
const
end_cp
=
sd
.
addr_to_region
_ptr
(
top_aligned_up
);
// Skip full
chunk
s at the beginning of the space--they are necessarily part
// Skip full
region
s at the beginning of the space--they are necessarily part
// of the dense prefix.
size_t
full_count
=
0
;
const
Chunk
Data
*
cp
;
for
(
cp
=
beg_cp
;
cp
<
end_cp
&&
cp
->
data_size
()
==
chunk
_size
;
++
cp
)
{
const
Region
Data
*
cp
;
for
(
cp
=
beg_cp
;
cp
<
end_cp
&&
cp
->
data_size
()
==
region
_size
;
++
cp
)
{
++
full_count
;
}
...
...
@@ -1006,7 +1009,7 @@ PSParallelCompact::compute_dense_prefix_via_density(const SpaceId id,
const
bool
interval_ended
=
gcs_since_max
>
HeapMaximumCompactionInterval
;
if
(
maximum_compaction
||
cp
==
end_cp
||
interval_ended
)
{
_maximum_compaction_gc_num
=
total_invocations
();
return
sd
.
chunk
_to_addr
(
cp
);
return
sd
.
region
_to_addr
(
cp
);
}
HeapWord
*
const
new_top
=
_space_info
[
id
].
new_top
();
...
...
@@ -1029,52 +1032,53 @@ PSParallelCompact::compute_dense_prefix_via_density(const SpaceId id,
}
// XXX - Use binary search?
HeapWord
*
dense_prefix
=
sd
.
chunk
_to_addr
(
cp
);
const
Chunk
Data
*
full_cp
=
cp
;
const
ChunkData
*
const
top_cp
=
sd
.
addr_to_chunk
_ptr
(
space
->
top
()
-
1
);
HeapWord
*
dense_prefix
=
sd
.
region
_to_addr
(
cp
);
const
Region
Data
*
full_cp
=
cp
;
const
RegionData
*
const
top_cp
=
sd
.
addr_to_region
_ptr
(
space
->
top
()
-
1
);
while
(
cp
<
end_cp
)
{
HeapWord
*
chunk
_destination
=
cp
->
destination
();
const
size_t
cur_deadwood
=
pointer_delta
(
dense_prefix
,
chunk
_destination
);
HeapWord
*
region
_destination
=
cp
->
destination
();
const
size_t
cur_deadwood
=
pointer_delta
(
dense_prefix
,
region
_destination
);
if
(
TraceParallelOldGCDensePrefix
&&
Verbose
)
{
tty
->
print_cr
(
"c#="
SIZE_FORMAT_W
(
4
)
" dst="
PTR_FORMAT
" "
"dp="
SIZE_FORMAT_W
(
8
)
" "
"cdw="
SIZE_FORMAT_W
(
8
),
sd
.
chunk
(
cp
),
chunk
_destination
,
sd
.
region
(
cp
),
region
_destination
,
dense_prefix
,
cur_deadwood
);
}
if
(
cur_deadwood
>=
deadwood_goal
)
{
// Found the
chunk
that has the correct amount of deadwood to the left.
// This typically occurs after crossing a fairly sparse set of
chunk
s, so
// iterate backwards over those sparse
chunks, looking for the chunk that
// has the lowest density of live objects 'to the right.'
size_t
space_to_left
=
sd
.
chunk
(
cp
)
*
chunk
_size
;
// Found the
region
that has the correct amount of deadwood to the left.
// This typically occurs after crossing a fairly sparse set of
region
s, so
// iterate backwards over those sparse
regions, looking for the region
//
that
has the lowest density of live objects 'to the right.'
size_t
space_to_left
=
sd
.
region
(
cp
)
*
region
_size
;
size_t
live_to_left
=
space_to_left
-
cur_deadwood
;
size_t
space_to_right
=
space_capacity
-
space_to_left
;
size_t
live_to_right
=
space_live
-
live_to_left
;
double
density_to_right
=
double
(
live_to_right
)
/
space_to_right
;
while
(
cp
>
full_cp
)
{
--
cp
;
const
size_t
prev_chunk_live_to_right
=
live_to_right
-
cp
->
data_size
();
const
size_t
prev_chunk_space_to_right
=
space_to_right
+
chunk_size
;
double
prev_chunk_density_to_right
=
double
(
prev_chunk_live_to_right
)
/
prev_chunk_space_to_right
;
if
(
density_to_right
<=
prev_chunk_density_to_right
)
{
const
size_t
prev_region_live_to_right
=
live_to_right
-
cp
->
data_size
();
const
size_t
prev_region_space_to_right
=
space_to_right
+
region_size
;
double
prev_region_density_to_right
=
double
(
prev_region_live_to_right
)
/
prev_region_space_to_right
;
if
(
density_to_right
<=
prev_region_density_to_right
)
{
return
dense_prefix
;
}
if
(
TraceParallelOldGCDensePrefix
&&
Verbose
)
{
tty
->
print_cr
(
"backing up from c="
SIZE_FORMAT_W
(
4
)
" d2r=%10.8f "
"pc_d2r=%10.8f"
,
sd
.
chunk
(
cp
),
density_to_right
,
prev_
chunk
_density_to_right
);
"pc_d2r=%10.8f"
,
sd
.
region
(
cp
),
density_to_right
,
prev_
region
_density_to_right
);
}
dense_prefix
-=
chunk
_size
;
live_to_right
=
prev_
chunk
_live_to_right
;
space_to_right
=
prev_
chunk
_space_to_right
;
density_to_right
=
prev_
chunk
_density_to_right
;
dense_prefix
-=
region
_size
;
live_to_right
=
prev_
region
_live_to_right
;
space_to_right
=
prev_
region
_space_to_right
;
density_to_right
=
prev_
region
_density_to_right
;
}
return
dense_prefix
;
}
dense_prefix
+=
chunk
_size
;
dense_prefix
+=
region
_size
;
++
cp
;
}
...
...
@@ -1087,8 +1091,8 @@ void PSParallelCompact::print_dense_prefix_stats(const char* const algorithm,
const
bool
maximum_compaction
,
HeapWord
*
const
addr
)
{
const
size_t
chunk_idx
=
summary_data
().
addr_to_chunk
_idx
(
addr
);
ChunkData
*
const
cp
=
summary_data
().
chunk
(
chunk
_idx
);
const
size_t
region_idx
=
summary_data
().
addr_to_region
_idx
(
addr
);
RegionData
*
const
cp
=
summary_data
().
region
(
region
_idx
);
const
MutableSpace
*
const
space
=
_space_info
[
id
].
space
();
HeapWord
*
const
new_top
=
_space_info
[
id
].
new_top
();
...
...
@@ -1104,7 +1108,7 @@ void PSParallelCompact::print_dense_prefix_stats(const char* const algorithm,
"d2l="
SIZE_FORMAT
" d2l%%=%6.4f "
"d2r="
SIZE_FORMAT
" l2r="
SIZE_FORMAT
" ratio=%10.8f"
,
algorithm
,
addr
,
chunk
_idx
,
algorithm
,
addr
,
region
_idx
,
space_live
,
dead_to_left
,
dead_to_left_pct
,
dead_to_right
,
live_to_right
,
...
...
@@ -1166,52 +1170,52 @@ double PSParallelCompact::dead_wood_limiter(double density, size_t min_percent)
return
MAX2
(
limit
,
0.0
);
}
ParallelCompactData
::
Chunk
Data
*
PSParallelCompact
::
first_dead_space_
chunk
(
const
Chunk
Data
*
beg
,
const
Chunk
Data
*
end
)
ParallelCompactData
::
Region
Data
*
PSParallelCompact
::
first_dead_space_
region
(
const
Region
Data
*
beg
,
const
Region
Data
*
end
)
{
const
size_t
chunk_size
=
ParallelCompactData
::
Chunk
Size
;
const
size_t
region_size
=
ParallelCompactData
::
Region
Size
;
ParallelCompactData
&
sd
=
summary_data
();
size_t
left
=
sd
.
chunk
(
beg
);
size_t
right
=
end
>
beg
?
sd
.
chunk
(
end
)
-
1
:
left
;
size_t
left
=
sd
.
region
(
beg
);
size_t
right
=
end
>
beg
?
sd
.
region
(
end
)
-
1
:
left
;
// Binary search.
while
(
left
<
right
)
{
// Equivalent to (left + right) / 2, but does not overflow.
const
size_t
middle
=
left
+
(
right
-
left
)
/
2
;
ChunkData
*
const
middle_ptr
=
sd
.
chunk
(
middle
);
RegionData
*
const
middle_ptr
=
sd
.
region
(
middle
);
HeapWord
*
const
dest
=
middle_ptr
->
destination
();
HeapWord
*
const
addr
=
sd
.
chunk
_to_addr
(
middle
);
HeapWord
*
const
addr
=
sd
.
region
_to_addr
(
middle
);
assert
(
dest
!=
NULL
,
"sanity"
);
assert
(
dest
<=
addr
,
"must move left"
);
if
(
middle
>
left
&&
dest
<
addr
)
{
right
=
middle
-
1
;
}
else
if
(
middle
<
right
&&
middle_ptr
->
data_size
()
==
chunk
_size
)
{
}
else
if
(
middle
<
right
&&
middle_ptr
->
data_size
()
==
region
_size
)
{
left
=
middle
+
1
;
}
else
{
return
middle_ptr
;
}
}
return
sd
.
chunk
(
left
);
return
sd
.
region
(
left
);
}
ParallelCompactData
::
Chunk
Data
*
PSParallelCompact
::
dead_wood_limit_
chunk
(
const
Chunk
Data
*
beg
,
const
Chunk
Data
*
end
,
size_t
dead_words
)
ParallelCompactData
::
Region
Data
*
PSParallelCompact
::
dead_wood_limit_
region
(
const
Region
Data
*
beg
,
const
Region
Data
*
end
,
size_t
dead_words
)
{
ParallelCompactData
&
sd
=
summary_data
();
size_t
left
=
sd
.
chunk
(
beg
);
size_t
right
=
end
>
beg
?
sd
.
chunk
(
end
)
-
1
:
left
;
size_t
left
=
sd
.
region
(
beg
);
size_t
right
=
end
>
beg
?
sd
.
region
(
end
)
-
1
:
left
;
// Binary search.
while
(
left
<
right
)
{
// Equivalent to (left + right) / 2, but does not overflow.
const
size_t
middle
=
left
+
(
right
-
left
)
/
2
;
ChunkData
*
const
middle_ptr
=
sd
.
chunk
(
middle
);
RegionData
*
const
middle_ptr
=
sd
.
region
(
middle
);
HeapWord
*
const
dest
=
middle_ptr
->
destination
();
HeapWord
*
const
addr
=
sd
.
chunk
_to_addr
(
middle
);
HeapWord
*
const
addr
=
sd
.
region
_to_addr
(
middle
);
assert
(
dest
!=
NULL
,
"sanity"
);
assert
(
dest
<=
addr
,
"must move left"
);
...
...
@@ -1224,13 +1228,13 @@ PSParallelCompact::dead_wood_limit_chunk(const ChunkData* beg,
return
middle_ptr
;
}
}
return
sd
.
chunk
(
left
);
return
sd
.
region
(
left
);
}
// The result is valid during the summary phase, after the initial summarization
// of each space into itself, and before final summarization.
inline
double
PSParallelCompact
::
reclaimed_ratio
(
const
Chunk
Data
*
const
cp
,
PSParallelCompact
::
reclaimed_ratio
(
const
Region
Data
*
const
cp
,
HeapWord
*
const
bottom
,
HeapWord
*
const
top
,
HeapWord
*
const
new_top
)
...
...
@@ -1244,12 +1248,13 @@ PSParallelCompact::reclaimed_ratio(const ChunkData* const cp,
assert
(
top
>=
new_top
,
"summary data problem?"
);
assert
(
new_top
>
bottom
,
"space is empty; should not be here"
);
assert
(
new_top
>=
cp
->
destination
(),
"sanity"
);
assert
(
top
>=
sd
.
chunk
_to_addr
(
cp
),
"sanity"
);
assert
(
top
>=
sd
.
region
_to_addr
(
cp
),
"sanity"
);
HeapWord
*
const
destination
=
cp
->
destination
();
const
size_t
dense_prefix_live
=
pointer_delta
(
destination
,
bottom
);
const
size_t
compacted_region_live
=
pointer_delta
(
new_top
,
destination
);
const
size_t
compacted_region_used
=
pointer_delta
(
top
,
sd
.
chunk_to_addr
(
cp
));
const
size_t
compacted_region_used
=
pointer_delta
(
top
,
sd
.
region_to_addr
(
cp
));
const
size_t
reclaimable
=
compacted_region_used
-
compacted_region_live
;
const
double
divisor
=
dense_prefix_live
+
1.25
*
compacted_region_live
;
...
...
@@ -1257,39 +1262,40 @@ PSParallelCompact::reclaimed_ratio(const ChunkData* const cp,
}
// Return the address of the end of the dense prefix, a.k.a. the start of the
// compacted region. The address is always on a
chunk
boundary.
// compacted region. The address is always on a
region
boundary.
//
// Completely full
chunks at the left are skipped, since no compaction can occur
//
in those chunks. Then the maximum amount of dead wood to allow is computed,
//
based on the density (amount live / capacity) of the generation; the chunk
//
with approximately that amount of dead space to the left is identified as the
//
limit chunk. Chunks between the last completely full chunk and the limit
//
chunk are scanned and the one that has the best (maximum) reclaimed_ratio()
// is selected.
// Completely full
regions at the left are skipped, since no compaction can
//
occur in those regions. Then the maximum amount of dead wood to allow is
//
computed, based on the density (amount live / capacity) of the generation;
//
the region with approximately that amount of dead space to the left is
//
identified as the limit region. Regions between the last completely full
//
region and the limit region are scanned and the one that has the best
//
(maximum) reclaimed_ratio()
is selected.
HeapWord
*
PSParallelCompact
::
compute_dense_prefix
(
const
SpaceId
id
,
bool
maximum_compaction
)
{
const
size_t
chunk_size
=
ParallelCompactData
::
Chunk
Size
;
const
size_t
region_size
=
ParallelCompactData
::
Region
Size
;
const
ParallelCompactData
&
sd
=
summary_data
();
const
MutableSpace
*
const
space
=
_space_info
[
id
].
space
();
HeapWord
*
const
top
=
space
->
top
();
HeapWord
*
const
top_aligned_up
=
sd
.
chunk
_align_up
(
top
);
HeapWord
*
const
top_aligned_up
=
sd
.
region
_align_up
(
top
);
HeapWord
*
const
new_top
=
_space_info
[
id
].
new_top
();
HeapWord
*
const
new_top_aligned_up
=
sd
.
chunk
_align_up
(
new_top
);
HeapWord
*
const
new_top_aligned_up
=
sd
.
region
_align_up
(
new_top
);
HeapWord
*
const
bottom
=
space
->
bottom
();
const
ChunkData
*
const
beg_cp
=
sd
.
addr_to_chunk_ptr
(
bottom
);
const
ChunkData
*
const
top_cp
=
sd
.
addr_to_chunk_ptr
(
top_aligned_up
);
const
ChunkData
*
const
new_top_cp
=
sd
.
addr_to_chunk_ptr
(
new_top_aligned_up
);
const
RegionData
*
const
beg_cp
=
sd
.
addr_to_region_ptr
(
bottom
);
const
RegionData
*
const
top_cp
=
sd
.
addr_to_region_ptr
(
top_aligned_up
);
const
RegionData
*
const
new_top_cp
=
sd
.
addr_to_region_ptr
(
new_top_aligned_up
);
// Skip full
chunk
s at the beginning of the space--they are necessarily part
// Skip full
region
s at the beginning of the space--they are necessarily part
// of the dense prefix.
const
ChunkData
*
const
full_cp
=
first_dead_space_chunk
(
beg_cp
,
new_top_cp
);
assert
(
full_cp
->
destination
()
==
sd
.
chunk
_to_addr
(
full_cp
)
||
const
RegionData
*
const
full_cp
=
first_dead_space_region
(
beg_cp
,
new_top_cp
);
assert
(
full_cp
->
destination
()
==
sd
.
region
_to_addr
(
full_cp
)
||
space
->
is_empty
(),
"no dead space allowed to the left"
);
assert
(
full_cp
->
data_size
()
<
chunk
_size
||
full_cp
==
new_top_cp
-
1
,
"
chunk
must have dead space"
);
assert
(
full_cp
->
data_size
()
<
region
_size
||
full_cp
==
new_top_cp
-
1
,
"
region
must have dead space"
);
// The gc number is saved whenever a maximum compaction is done, and used to
// determine when the maximum compaction interval has expired. This avoids
...
...
@@ -1300,7 +1306,7 @@ PSParallelCompact::compute_dense_prefix(const SpaceId id,
total_invocations
()
==
HeapFirstMaximumCompactionCount
;
if
(
maximum_compaction
||
full_cp
==
top_cp
||
interval_ended
)
{
_maximum_compaction_gc_num
=
total_invocations
();
return
sd
.
chunk
_to_addr
(
full_cp
);
return
sd
.
region
_to_addr
(
full_cp
);
}
const
size_t
space_live
=
pointer_delta
(
new_top
,
bottom
);
...
...
@@ -1326,15 +1332,15 @@ PSParallelCompact::compute_dense_prefix(const SpaceId id,
dead_wood_max
,
dead_wood_limit
);
}
// Locate the
chunk
with the desired amount of dead space to the left.
const
Chunk
Data
*
const
limit_cp
=
dead_wood_limit_
chunk
(
full_cp
,
top_cp
,
dead_wood_limit
);
// Locate the
region
with the desired amount of dead space to the left.
const
Region
Data
*
const
limit_cp
=
dead_wood_limit_
region
(
full_cp
,
top_cp
,
dead_wood_limit
);
// Scan from the first
chunk with dead space to the limit chunk
and find the
// Scan from the first
region with dead space to the limit region
and find the
// one with the best (largest) reclaimed ratio.
double
best_ratio
=
0.0
;
const
Chunk
Data
*
best_cp
=
full_cp
;
for
(
const
Chunk
Data
*
cp
=
full_cp
;
cp
<
limit_cp
;
++
cp
)
{
const
Region
Data
*
best_cp
=
full_cp
;
for
(
const
Region
Data
*
cp
=
full_cp
;
cp
<
limit_cp
;
++
cp
)
{
double
tmp_ratio
=
reclaimed_ratio
(
cp
,
bottom
,
top
,
new_top
);
if
(
tmp_ratio
>
best_ratio
)
{
best_cp
=
cp
;
...
...
@@ -1343,18 +1349,18 @@ PSParallelCompact::compute_dense_prefix(const SpaceId id,
}
#if 0
// Something to consider: if the
chunk
with the best ratio is 'close to' the
// first
chunk w/free space, choose the first chunk
with free space
// ("first-free"). The first-free
chunk
is usually near the start of the
// Something to consider: if the
region
with the best ratio is 'close to' the
// first
region w/free space, choose the first region
with free space
// ("first-free"). The first-free
region
is usually near the start of the
// heap, which means we are copying most of the heap already, so copy a bit
// more to get complete compaction.
if
(
pointer_delta
(
best_cp
,
full_cp
,
sizeof
(
Chunk
Data
))
<
4
)
{
if
(
pointer_delta
(
best_cp
,
full_cp
,
sizeof
(
Region
Data
))
<
4
)
{
_maximum_compaction_gc_num
=
total_invocations
();
best_cp
=
full_cp
;
}
#endif // #if 0
return
sd
.
chunk
_to_addr
(
best_cp
);
return
sd
.
region
_to_addr
(
best_cp
);
}
void
PSParallelCompact
::
summarize_spaces_quick
()
...
...
@@ -1372,9 +1378,9 @@ void PSParallelCompact::summarize_spaces_quick()
void
PSParallelCompact
::
fill_dense_prefix_end
(
SpaceId
id
)
{
HeapWord
*
const
dense_prefix_end
=
dense_prefix
(
id
);
const
ChunkData
*
chunk
=
_summary_data
.
addr_to_chunk
_ptr
(
dense_prefix_end
);
const
RegionData
*
region
=
_summary_data
.
addr_to_region
_ptr
(
dense_prefix_end
);
const
idx_t
dense_prefix_bit
=
_mark_bitmap
.
addr_to_bit
(
dense_prefix_end
);
if
(
dead_space_crosses_boundary
(
chunk
,
dense_prefix_bit
))
{
if
(
dead_space_crosses_boundary
(
region
,
dense_prefix_bit
))
{
// Only enough dead space is filled so that any remaining dead space to the
// left is larger than the minimum filler object. (The remainder is filled
// during the copy/update phase.)
...
...
@@ -1465,7 +1471,7 @@ PSParallelCompact::summarize_space(SpaceId id, bool maximum_compaction)
fill_dense_prefix_end
(
id
);
}
// Compute the destination of each
Chunk
, and thus each object.
// Compute the destination of each
Region
, and thus each object.
_summary_data
.
summarize_dense_prefix
(
space
->
bottom
(),
dense_prefix_end
);
_summary_data
.
summarize
(
dense_prefix_end
,
space
->
end
(),
dense_prefix_end
,
space
->
top
(),
...
...
@@ -1473,19 +1479,19 @@ PSParallelCompact::summarize_space(SpaceId id, bool maximum_compaction)
}
if
(
TraceParallelOldGCSummaryPhase
)
{
const
size_t
chunk_size
=
ParallelCompactData
::
Chunk
Size
;
const
size_t
region_size
=
ParallelCompactData
::
Region
Size
;
HeapWord
*
const
dense_prefix_end
=
_space_info
[
id
].
dense_prefix
();
const
size_t
dp_
chunk
=
_summary_data
.
addr_to_chunk
_idx
(
dense_prefix_end
);
const
size_t
dp_
region
=
_summary_data
.
addr_to_region
_idx
(
dense_prefix_end
);
const
size_t
dp_words
=
pointer_delta
(
dense_prefix_end
,
space
->
bottom
());
HeapWord
*
const
new_top
=
_space_info
[
id
].
new_top
();
const
HeapWord
*
nt_aligned_up
=
_summary_data
.
chunk
_align_up
(
new_top
);
const
HeapWord
*
nt_aligned_up
=
_summary_data
.
region
_align_up
(
new_top
);
const
size_t
cr_words
=
pointer_delta
(
nt_aligned_up
,
dense_prefix_end
);
tty
->
print_cr
(
"id=%d cap="
SIZE_FORMAT
" dp="
PTR_FORMAT
" "
"dp_
chunk
="
SIZE_FORMAT
" "
"dp_count="
SIZE_FORMAT
" "
"dp_
region
="
SIZE_FORMAT
" "
"dp_count="
SIZE_FORMAT
" "
"cr_count="
SIZE_FORMAT
" "
"nt="
PTR_FORMAT
,
id
,
space
->
capacity_in_words
(),
dense_prefix_end
,
dp_
chunk
,
dp_words
/
chunk
_size
,
cr_words
/
chunk
_size
,
new_top
);
dp_
region
,
dp_words
/
region
_size
,
cr_words
/
region
_size
,
new_top
);
}
}
...
...
@@ -1513,7 +1519,7 @@ void PSParallelCompact::summary_phase(ParCompactionManager* cm,
if
(
TraceParallelOldGCSummaryPhase
)
{
tty
->
print_cr
(
"summary_phase: after summarizing each space to self"
);
Universe
::
print
();
NOT_PRODUCT
(
print_
chunk
_ranges
());
NOT_PRODUCT
(
print_
region
_ranges
());
if
(
Verbose
)
{
NOT_PRODUCT
(
print_initial_summary_data
(
_summary_data
,
_space_info
));
}
...
...
@@ -1559,14 +1565,15 @@ void PSParallelCompact::summary_phase(ParCompactionManager* cm,
space
->
bottom
(),
space
->
top
(),
new_top_addr
);
// Clear the source_
chunk field for each chunk
in the space.
// Clear the source_
region field for each region
in the space.
HeapWord
*
const
new_top
=
_space_info
[
id
].
new_top
();
HeapWord
*
const
clear_end
=
_summary_data
.
chunk_align_up
(
new_top
);
ChunkData
*
beg_chunk
=
_summary_data
.
addr_to_chunk_ptr
(
space
->
bottom
());
ChunkData
*
end_chunk
=
_summary_data
.
addr_to_chunk_ptr
(
clear_end
);
while
(
beg_chunk
<
end_chunk
)
{
beg_chunk
->
set_source_chunk
(
0
);
++
beg_chunk
;
HeapWord
*
const
clear_end
=
_summary_data
.
region_align_up
(
new_top
);
RegionData
*
beg_region
=
_summary_data
.
addr_to_region_ptr
(
space
->
bottom
());
RegionData
*
end_region
=
_summary_data
.
addr_to_region_ptr
(
clear_end
);
while
(
beg_region
<
end_region
)
{
beg_region
->
set_source_region
(
0
);
++
beg_region
;
}
// Reset the new_top value for the space.
...
...
@@ -1574,13 +1581,13 @@ void PSParallelCompact::summary_phase(ParCompactionManager* cm,
}
}
// Fill in the block data after any changes to the
chunk
s have
// Fill in the block data after any changes to the
region
s have
// been made.
#ifdef ASSERT
summarize_blocks
(
cm
,
perm_space_id
);
summarize_blocks
(
cm
,
old_space_id
);
#else
if
(
!
UseParallelOldGC
Chunk
PointerCalc
)
{
if
(
!
UseParallelOldGC
Region
PointerCalc
)
{
summarize_blocks
(
cm
,
perm_space_id
);
summarize_blocks
(
cm
,
old_space_id
);
}
...
...
@@ -1589,7 +1596,7 @@ void PSParallelCompact::summary_phase(ParCompactionManager* cm,
if
(
TraceParallelOldGCSummaryPhase
)
{
tty
->
print_cr
(
"summary_phase: after final summarization"
);
Universe
::
print
();
NOT_PRODUCT
(
print_
chunk
_ranges
());
NOT_PRODUCT
(
print_
region
_ranges
());
if
(
Verbose
)
{
NOT_PRODUCT
(
print_generic_summary_data
(
_summary_data
,
_space_info
));
}
...
...
@@ -1598,7 +1605,7 @@ void PSParallelCompact::summary_phase(ParCompactionManager* cm,
// Fill in the BlockData.
// Iterate over the spaces and within each space iterate over
// the
chunks and fill in the BlockData for each chunk
.
// the
regions and fill in the BlockData for each region
.
void
PSParallelCompact
::
summarize_blocks
(
ParCompactionManager
*
cm
,
SpaceId
first_compaction_space_id
)
{
...
...
@@ -1607,40 +1614,41 @@ void PSParallelCompact::summarize_blocks(ParCompactionManager* cm,
for
(
SpaceId
cur_space_id
=
first_compaction_space_id
;
cur_space_id
!=
last_space_id
;
cur_space_id
=
next_compaction_space_id
(
cur_space_id
))
{
// Iterate over the
chunk
s in the space
size_t
start_
chunk
_index
=
_summary_data
.
addr_to_
chunk
_idx
(
space
(
cur_space_id
)
->
bottom
());
// Iterate over the
region
s in the space
size_t
start_
region
_index
=
_summary_data
.
addr_to_
region
_idx
(
space
(
cur_space_id
)
->
bottom
());
BitBlockUpdateClosure
bbu
(
mark_bitmap
(),
cm
,
start_
chunk
_index
);
start_
region
_index
);
// Iterate over blocks.
for
(
size_t
chunk_index
=
start_chunk_index
;
chunk_index
<
_summary_data
.
chunk_count
()
&&
_summary_data
.
chunk_to_addr
(
chunk_index
)
<
space
(
cur_space_id
)
->
top
();
chunk_index
++
)
{
// Reset the closure for the new chunk. Note that the closure
// maintains some data that does not get reset for each chunk
for
(
size_t
region_index
=
start_region_index
;
region_index
<
_summary_data
.
region_count
()
&&
_summary_data
.
region_to_addr
(
region_index
)
<
space
(
cur_space_id
)
->
top
();
region_index
++
)
{
// Reset the closure for the new region. Note that the closure
// maintains some data that does not get reset for each region
// so a new instance of the closure is no appropriate.
bbu
.
reset_
chunk
(
chunk
_index
);
bbu
.
reset_
region
(
region
_index
);
// Start the iteration with the first live object. This
// may return the end of the
chunk
. That is acceptable since
// may return the end of the
region
. That is acceptable since
// it will properly limit the iterations.
ParMarkBitMap
::
idx_t
left_offset
=
mark_bitmap
()
->
addr_to_bit
(
_summary_data
.
first_live_or_end_in_
chunk
(
chunk
_index
));
_summary_data
.
first_live_or_end_in_
region
(
region
_index
));
// End the iteration at the end of the
chunk
.
HeapWord
*
chunk_addr
=
_summary_data
.
chunk_to_addr
(
chunk
_index
);
HeapWord
*
chunk_end
=
chunk_addr
+
ParallelCompactData
::
Chunk
Size
;
// End the iteration at the end of the
region
.
HeapWord
*
region_addr
=
_summary_data
.
region_to_addr
(
region
_index
);
HeapWord
*
region_end
=
region_addr
+
ParallelCompactData
::
Region
Size
;
ParMarkBitMap
::
idx_t
right_offset
=
mark_bitmap
()
->
addr_to_bit
(
chunk
_end
);
mark_bitmap
()
->
addr_to_bit
(
region
_end
);
// Blocks that have not objects starting in them can be
// skipped because their data will never be used.
if
(
left_offset
<
right_offset
)
{
// Iterate through the objects in the
chunk
.
// Iterate through the objects in the
region
.
ParMarkBitMap
::
idx_t
last_offset
=
mark_bitmap
()
->
pair_iterate
(
&
bbu
,
left_offset
,
right_offset
);
...
...
@@ -1649,7 +1657,7 @@ void PSParallelCompact::summarize_blocks(ParCompactionManager* cm,
// is then the offset for the last start bit. In this situation
// the "offset" field for the next block to the right (_cur_block + 1)
// will not have been update although there may be live data
// to the left of the
chunk
.
// to the left of the
region
.
size_t
cur_block_plus_1
=
bbu
.
cur_block
()
+
1
;
HeapWord
*
cur_block_plus_1_addr
=
...
...
@@ -1669,23 +1677,23 @@ void PSParallelCompact::summarize_blocks(ParCompactionManager* cm,
#else
// The current block has already been updated. The only block
// that remains to be updated is the block where the last
// object in the
chunk
starts.
// object in the
region
starts.
size_t
last_block
=
_summary_data
.
addr_to_block_idx
(
last_offset_addr
);
#endif
assert_bit_is_start
(
last_offset
);
assert
((
last_block
==
_summary_data
.
block_count
())
||
(
_summary_data
.
block
(
last_block
)
->
raw_offset
()
==
0
),
"Should not have been set"
);
// Is the last block still in the current
chunk
? If still
// in this
chunk
, update the last block (the counting that
// Is the last block still in the current
region
? If still
// in this
region
, update the last block (the counting that
// included the current block is meant for the offset of the last
// block). If not in this
chunk
, do nothing. Should not
// update a block in the next
chunk
.
if
(
ParallelCompactData
::
chunk_contains_block
(
bbu
.
chunk
_index
(),
last_block
))
{
// block). If not in this
region
, do nothing. Should not
// update a block in the next
region
.
if
(
ParallelCompactData
::
region_contains_block
(
bbu
.
region
_index
(),
last_block
))
{
if
(
last_offset
<
right_offset
)
{
// The last object started in this
chunk
but ends beyond
// this
chunk
. Update the block for this last object.
// The last object started in this
region
but ends beyond
// this
region
. Update the block for this last object.
assert
(
mark_bitmap
()
->
is_marked
(
last_offset
),
"Should be marked"
);
// No end bit was found. The closure takes care of
// the cases where
...
...
@@ -1693,7 +1701,7 @@ void PSParallelCompact::summarize_blocks(ParCompactionManager* cm,
// an objects starts and ends in the next block
// It does not handle the case where an object is
// the first object in a later block and extends
// past the end of the
chunk
(i.e., the closure
// past the end of the
region
(i.e., the closure
// only handles complete objects that are in the range
// it is given). That object is handed back here
// for any special consideration necessary.
...
...
@@ -1709,7 +1717,7 @@ void PSParallelCompact::summarize_blocks(ParCompactionManager* cm,
// the AA+1 is the trigger that updates AA. Objects are being
// counted in the current block for updaing a following
// block. An object may start in later block
// block but may extend beyond the last block in the
chunk
.
// block but may extend beyond the last block in the
region
.
// Updates are only done when the end of an object has been
// found. If the last object (covered by block L) starts
// beyond the current block, then no object ends in L (otherwise
...
...
@@ -1717,7 +1725,7 @@ void PSParallelCompact::summarize_blocks(ParCompactionManager* cm,
// a start bit.
//
// Else the last objects start in the current block and ends
// beyond the
chunk
. The current block has already been
// beyond the
region
. The current block has already been
// updated and there is no later block (with an object
// starting in it) that needs to be updated.
//
...
...
@@ -1728,14 +1736,14 @@ void PSParallelCompact::summarize_blocks(ParCompactionManager* cm,
// The start of the object is on a later block
// (to the right of the current block and there are no
// complete live objects to the left of this last object
// within the
chunk
.
// within the
region
.
// The first bit in the block is for the start of the
// last object.
_summary_data
.
block
(
last_block
)
->
set_start_bit_offset
(
bbu
.
live_data_left
());
}
else
{
// The start of the last object was found in
// the current
chunk
(which has already
// the current
region
(which has already
// been updated).
assert
(
bbu
.
cur_block
()
==
_summary_data
.
addr_to_block_idx
(
last_offset_addr
),
...
...
@@ -1743,15 +1751,15 @@ void PSParallelCompact::summarize_blocks(ParCompactionManager* cm,
}
#ifdef ASSERT
// Is there enough block information to find this object?
// The destination of the
chunk
has not been set so the
// The destination of the
region
has not been set so the
// values returned by calc_new_pointer() and
// block_calc_new_pointer() will only be
// offsets. But they should agree.
HeapWord
*
moved_obj_with_
chunk
s
=
_summary_data
.
chunk
_calc_new_pointer
(
last_offset_addr
);
HeapWord
*
moved_obj_with_
region
s
=
_summary_data
.
region
_calc_new_pointer
(
last_offset_addr
);
HeapWord
*
moved_obj_with_blocks
=
_summary_data
.
calc_new_pointer
(
last_offset_addr
);
assert
(
moved_obj_with_
chunk
s
==
moved_obj_with_blocks
,
assert
(
moved_obj_with_
region
s
==
moved_obj_with_blocks
,
"Block calculation is wrong"
);
#endif
}
else
if
(
last_block
<
_summary_data
.
block_count
())
{
...
...
@@ -1764,38 +1772,38 @@ void PSParallelCompact::summarize_blocks(ParCompactionManager* cm,
#ifdef ASSERT
// Is there enough block information to find this object?
HeapWord
*
left_offset_addr
=
mark_bitmap
()
->
bit_to_addr
(
left_offset
);
HeapWord
*
moved_obj_with_
chunk
s
=
HeapWord
*
moved_obj_with_
region
s
=
_summary_data
.
calc_new_pointer
(
left_offset_addr
);
HeapWord
*
moved_obj_with_blocks
=
_summary_data
.
calc_new_pointer
(
left_offset_addr
);
assert
(
moved_obj_with_
chunk
s
==
moved_obj_with_blocks
,
assert
(
moved_obj_with_
region
s
==
moved_obj_with_blocks
,
"Block calculation is wrong"
);
#endif
// Is there another block after the end of this
chunk
?
// Is there another block after the end of this
region
?
#ifdef ASSERT
if
(
last_block
<
_summary_data
.
block_count
())
{
// No object may have been found in a block. If that
// block is at the end of the
chunk
, the iteration will
// block is at the end of the
region
, the iteration will
// terminate without incrementing the current block so
// that the current block is not the last block in the
//
chunk
. That situation precludes asserting that the
// current block is the last block in the
chunk
. Assert
//
region
. That situation precludes asserting that the
// current block is the last block in the
region
. Assert
// the lesser condition that the current block does not
// exceed the
chunk
.
// exceed the
region
.
assert
(
_summary_data
.
block_to_addr
(
last_block
)
<=
(
_summary_data
.
chunk_to_addr
(
chunk
_index
)
+
ParallelCompactData
::
Chunk
Size
),
"
Chunk
and block inconsistency"
);
(
_summary_data
.
region_to_addr
(
region
_index
)
+
ParallelCompactData
::
Region
Size
),
"
Region
and block inconsistency"
);
assert
(
last_offset
<=
right_offset
,
"Iteration over ran end"
);
}
#endif
}
#ifdef ASSERT
if
(
PrintGCDetails
&&
Verbose
)
{
if
(
_summary_data
.
chunk
(
chunk
_index
)
->
partial_obj_size
()
==
1
)
{
if
(
_summary_data
.
region
(
region
_index
)
->
partial_obj_size
()
==
1
)
{
size_t
first_block
=
chunk_index
/
ParallelCompactData
::
BlocksPerChunk
;
region_index
/
ParallelCompactData
::
BlocksPerRegion
;
gclog_or_tty
->
print_cr
(
"first_block "
PTR_FORMAT
" _offset "
PTR_FORMAT
"_first_is_start_bit %d"
,
...
...
@@ -1845,18 +1853,18 @@ void PSParallelCompact::invoke(bool maximum_heap_compaction) {
}
}
bool
ParallelCompactData
::
chunk_contains
(
size_t
chunk
_index
,
HeapWord
*
addr
)
{
size_t
addr_
chunk_index
=
addr_to_chunk
_idx
(
addr
);
return
chunk_index
==
addr_chunk
_index
;
bool
ParallelCompactData
::
region_contains
(
size_t
region
_index
,
HeapWord
*
addr
)
{
size_t
addr_
region_index
=
addr_to_region
_idx
(
addr
);
return
region_index
==
addr_region
_index
;
}
bool
ParallelCompactData
::
chunk_contains_block
(
size_t
chunk
_index
,
size_t
block_index
)
{
size_t
first_block_in_
chunk
=
chunk_index
*
BlocksPerChunk
;
size_t
last_block_in_
chunk
=
(
chunk_index
+
1
)
*
BlocksPerChunk
-
1
;
bool
ParallelCompactData
::
region_contains_block
(
size_t
region
_index
,
size_t
block_index
)
{
size_t
first_block_in_
region
=
region_index
*
BlocksPerRegion
;
size_t
last_block_in_
region
=
(
region_index
+
1
)
*
BlocksPerRegion
-
1
;
return
(
first_block_in_
chunk
<=
block_index
)
&&
(
block_index
<=
last_block_in_
chunk
);
return
(
first_block_in_
region
<=
block_index
)
&&
(
block_index
<=
last_block_in_
region
);
}
// This method contains no policy. You should probably
...
...
@@ -2205,7 +2213,7 @@ void PSParallelCompact::marking_phase(ParCompactionManager* cm,
ParallelScavengeHeap
*
heap
=
gc_heap
();
uint
parallel_gc_threads
=
heap
->
gc_task_manager
()
->
workers
();
TaskQueueSetSuper
*
qset
=
ParCompactionManager
::
chunk
_array
();
TaskQueueSetSuper
*
qset
=
ParCompactionManager
::
region
_array
();
ParallelTaskTerminator
terminator
(
parallel_gc_threads
,
qset
);
PSParallelCompact
::
MarkAndPushClosure
mark_and_push_closure
(
cm
);
...
...
@@ -2343,8 +2351,9 @@ void PSParallelCompact::compact_perm(ParCompactionManager* cm) {
move_and_update
(
cm
,
perm_space_id
);
}
void
PSParallelCompact
::
enqueue_chunk_draining_tasks
(
GCTaskQueue
*
q
,
uint
parallel_gc_threads
)
{
void
PSParallelCompact
::
enqueue_region_draining_tasks
(
GCTaskQueue
*
q
,
uint
parallel_gc_threads
)
{
TraceTime
tm
(
"drain task setup"
,
print_phases
(),
true
,
gclog_or_tty
);
const
unsigned
int
task_count
=
MAX2
(
parallel_gc_threads
,
1U
);
...
...
@@ -2352,13 +2361,13 @@ void PSParallelCompact::enqueue_chunk_draining_tasks(GCTaskQueue* q,
q
->
enqueue
(
new
DrainStacksCompactionTask
());
}
// Find all
chunk
s that are available (can be filled immediately) and
// Find all
region
s that are available (can be filled immediately) and
// distribute them to the thread stacks. The iteration is done in reverse
// order (high to low) so the
chunk
s will be removed in ascending order.
// order (high to low) so the
region
s will be removed in ascending order.
const
ParallelCompactData
&
sd
=
PSParallelCompact
::
summary_data
();
size_t
fillable_
chunk
s
=
0
;
// A count for diagnostic purposes.
size_t
fillable_
region
s
=
0
;
// A count for diagnostic purposes.
unsigned
int
which
=
0
;
// The worker thread number.
for
(
unsigned
int
id
=
to_space_id
;
id
>
perm_space_id
;
--
id
)
{
...
...
@@ -2366,25 +2375,26 @@ void PSParallelCompact::enqueue_chunk_draining_tasks(GCTaskQueue* q,
MutableSpace
*
const
space
=
space_info
->
space
();
HeapWord
*
const
new_top
=
space_info
->
new_top
();
const
size_t
beg_chunk
=
sd
.
addr_to_chunk_idx
(
space_info
->
dense_prefix
());
const
size_t
end_chunk
=
sd
.
addr_to_chunk_idx
(
sd
.
chunk_align_up
(
new_top
));
assert
(
end_chunk
>
0
,
"perm gen cannot be empty"
);
const
size_t
beg_region
=
sd
.
addr_to_region_idx
(
space_info
->
dense_prefix
());
const
size_t
end_region
=
sd
.
addr_to_region_idx
(
sd
.
region_align_up
(
new_top
));
assert
(
end_region
>
0
,
"perm gen cannot be empty"
);
for
(
size_t
cur
=
end_
chunk
-
1
;
cur
>=
beg_chunk
;
--
cur
)
{
if
(
sd
.
chunk
(
cur
)
->
claim_unsafe
())
{
for
(
size_t
cur
=
end_
region
-
1
;
cur
>=
beg_region
;
--
cur
)
{
if
(
sd
.
region
(
cur
)
->
claim_unsafe
())
{
ParCompactionManager
*
cm
=
ParCompactionManager
::
manager_array
(
which
);
cm
->
save_for_processing
(
cur
);
if
(
TraceParallelOldGCCompactionPhase
&&
Verbose
)
{
const
size_t
count_mod_8
=
fillable_
chunk
s
&
7
;
const
size_t
count_mod_8
=
fillable_
region
s
&
7
;
if
(
count_mod_8
==
0
)
gclog_or_tty
->
print
(
"fillable: "
);
gclog_or_tty
->
print
(
" "
SIZE_FORMAT_W
(
7
),
cur
);
if
(
count_mod_8
==
7
)
gclog_or_tty
->
cr
();
}
NOT_PRODUCT
(
++
fillable_
chunk
s
;)
NOT_PRODUCT
(
++
fillable_
region
s
;)
// Assign
chunk
s to threads in round-robin fashion.
// Assign
region
s to threads in round-robin fashion.
if
(
++
which
==
task_count
)
{
which
=
0
;
}
...
...
@@ -2393,8 +2403,8 @@ void PSParallelCompact::enqueue_chunk_draining_tasks(GCTaskQueue* q,
}
if
(
TraceParallelOldGCCompactionPhase
)
{
if
(
Verbose
&&
(
fillable_
chunk
s
&
7
)
!=
0
)
gclog_or_tty
->
cr
();
gclog_or_tty
->
print_cr
(
"%u initially fillable
chunks"
,
fillable_chunk
s
);
if
(
Verbose
&&
(
fillable_
region
s
&
7
)
!=
0
)
gclog_or_tty
->
cr
();
gclog_or_tty
->
print_cr
(
"%u initially fillable
regions"
,
fillable_region
s
);
}
}
...
...
@@ -2407,7 +2417,7 @@ void PSParallelCompact::enqueue_dense_prefix_tasks(GCTaskQueue* q,
ParallelCompactData
&
sd
=
PSParallelCompact
::
summary_data
();
// Iterate over all the spaces adding tasks for updating
//
chunk
s in the dense prefix. Assume that 1 gc thread
//
region
s in the dense prefix. Assume that 1 gc thread
// will work on opening the gaps and the remaining gc threads
// will work on the dense prefix.
SpaceId
space_id
=
old_space_id
;
...
...
@@ -2421,30 +2431,31 @@ void PSParallelCompact::enqueue_dense_prefix_tasks(GCTaskQueue* q,
continue
;
}
// The dense prefix is before this chunk.
size_t
chunk_index_end_dense_prefix
=
sd
.
addr_to_chunk_idx
(
dense_prefix_end
);
ChunkData
*
const
dense_prefix_cp
=
sd
.
chunk
(
chunk_index_end_dense_prefix
);
// The dense prefix is before this region.
size_t
region_index_end_dense_prefix
=
sd
.
addr_to_region_idx
(
dense_prefix_end
);
RegionData
*
const
dense_prefix_cp
=
sd
.
region
(
region_index_end_dense_prefix
);
assert
(
dense_prefix_end
==
space
->
end
()
||
dense_prefix_cp
->
available
()
||
dense_prefix_cp
->
claimed
(),
"The
chunk
after the dense prefix should always be ready to fill"
);
"The
region
after the dense prefix should always be ready to fill"
);
size_t
chunk_index_start
=
sd
.
addr_to_chunk
_idx
(
space
->
bottom
());
size_t
region_index_start
=
sd
.
addr_to_region
_idx
(
space
->
bottom
());
// Is there dense prefix work?
size_t
total_dense_prefix_
chunk
s
=
chunk_index_end_dense_prefix
-
chunk
_index_start
;
// How many
chunk
s of the dense prefix should be given to
size_t
total_dense_prefix_
region
s
=
region_index_end_dense_prefix
-
region
_index_start
;
// How many
region
s of the dense prefix should be given to
// each thread?
if
(
total_dense_prefix_
chunk
s
>
0
)
{
if
(
total_dense_prefix_
region
s
>
0
)
{
uint
tasks_for_dense_prefix
=
1
;
if
(
UseParallelDensePrefixUpdate
)
{
if
(
total_dense_prefix_
chunk
s
<=
if
(
total_dense_prefix_
region
s
<=
(
parallel_gc_threads
*
PAR_OLD_DENSE_PREFIX_OVER_PARTITIONING
))
{
// Don't over partition. This assumes that
// PAR_OLD_DENSE_PREFIX_OVER_PARTITIONING is a small integer value
// so there are not many
chunk
s to process.
// so there are not many
region
s to process.
tasks_for_dense_prefix
=
parallel_gc_threads
;
}
else
{
// Over partition
...
...
@@ -2452,50 +2463,50 @@ void PSParallelCompact::enqueue_dense_prefix_tasks(GCTaskQueue* q,
PAR_OLD_DENSE_PREFIX_OVER_PARTITIONING
;
}
}
size_t
chunks_per_thread
=
total_dense_prefix_chunk
s
/
size_t
regions_per_thread
=
total_dense_prefix_region
s
/
tasks_for_dense_prefix
;
// Give each thread at least 1
chunk
.
if
(
chunk
s_per_thread
==
0
)
{
chunk
s_per_thread
=
1
;
// Give each thread at least 1
region
.
if
(
region
s_per_thread
==
0
)
{
region
s_per_thread
=
1
;
}
for
(
uint
k
=
0
;
k
<
tasks_for_dense_prefix
;
k
++
)
{
if
(
chunk_index_start
>=
chunk
_index_end_dense_prefix
)
{
if
(
region_index_start
>=
region
_index_end_dense_prefix
)
{
break
;
}
//
chunk
_index_end is not processed
size_t
chunk_index_end
=
MIN2
(
chunk_index_start
+
chunk
s_per_thread
,
chunk
_index_end_dense_prefix
);
//
region
_index_end is not processed
size_t
region_index_end
=
MIN2
(
region_index_start
+
region
s_per_thread
,
region
_index_end_dense_prefix
);
q
->
enqueue
(
new
UpdateDensePrefixTask
(
space_id
,
chunk
_index_start
,
chunk
_index_end
));
chunk_index_start
=
chunk
_index_end
;
region
_index_start
,
region
_index_end
));
region_index_start
=
region
_index_end
;
}
}
// This gets any part of the dense prefix that did not
// fit evenly.
if
(
chunk_index_start
<
chunk
_index_end_dense_prefix
)
{
if
(
region_index_start
<
region
_index_end_dense_prefix
)
{
q
->
enqueue
(
new
UpdateDensePrefixTask
(
space_id
,
chunk
_index_start
,
chunk
_index_end_dense_prefix
));
region
_index_start
,
region
_index_end_dense_prefix
));
}
space_id
=
next_compaction_space_id
(
space_id
);
}
// End tasks for dense prefix
}
void
PSParallelCompact
::
enqueue_
chunk
_stealing_tasks
(
void
PSParallelCompact
::
enqueue_
region
_stealing_tasks
(
GCTaskQueue
*
q
,
ParallelTaskTerminator
*
terminator_ptr
,
uint
parallel_gc_threads
)
{
TraceTime
tm
(
"steal task setup"
,
print_phases
(),
true
,
gclog_or_tty
);
// Once a thread has drained it's stack, it should try to steal
chunk
s from
// Once a thread has drained it's stack, it should try to steal
region
s from
// other threads.
if
(
parallel_gc_threads
>
1
)
{
for
(
uint
j
=
0
;
j
<
parallel_gc_threads
;
j
++
)
{
q
->
enqueue
(
new
Steal
Chunk
CompactionTask
(
terminator_ptr
));
q
->
enqueue
(
new
Steal
Region
CompactionTask
(
terminator_ptr
));
}
}
}
...
...
@@ -2510,13 +2521,13 @@ void PSParallelCompact::compact() {
PSOldGen
*
old_gen
=
heap
->
old_gen
();
old_gen
->
start_array
()
->
reset
();
uint
parallel_gc_threads
=
heap
->
gc_task_manager
()
->
workers
();
TaskQueueSetSuper
*
qset
=
ParCompactionManager
::
chunk
_array
();
TaskQueueSetSuper
*
qset
=
ParCompactionManager
::
region
_array
();
ParallelTaskTerminator
terminator
(
parallel_gc_threads
,
qset
);
GCTaskQueue
*
q
=
GCTaskQueue
::
create
();
enqueue_
chunk
_draining_tasks
(
q
,
parallel_gc_threads
);
enqueue_
region
_draining_tasks
(
q
,
parallel_gc_threads
);
enqueue_dense_prefix_tasks
(
q
,
parallel_gc_threads
);
enqueue_
chunk
_stealing_tasks
(
q
,
&
terminator
,
parallel_gc_threads
);
enqueue_
region
_stealing_tasks
(
q
,
&
terminator
,
parallel_gc_threads
);
{
TraceTime
tm_pc
(
"par compact"
,
print_phases
(),
true
,
gclog_or_tty
);
...
...
@@ -2532,9 +2543,9 @@ void PSParallelCompact::compact() {
WaitForBarrierGCTask
::
destroy
(
fin
);
#ifdef ASSERT
// Verify that all
chunk
s have been processed before the deferred updates.
// Verify that all
region
s have been processed before the deferred updates.
// Note that perm_space_id is skipped; this type of verification is not
// valid until the perm gen is compacted by
chunk
s.
// valid until the perm gen is compacted by
region
s.
for
(
unsigned
int
id
=
old_space_id
;
id
<
last_space_id
;
++
id
)
{
verify_complete
(
SpaceId
(
id
));
}
...
...
@@ -2553,42 +2564,42 @@ void PSParallelCompact::compact() {
#ifdef ASSERT
void
PSParallelCompact
::
verify_complete
(
SpaceId
space_id
)
{
// All
Chunk
s between space bottom() to new_top() should be marked as filled
// and all
Chunk
s between new_top() and top() should be available (i.e.,
// All
Region
s between space bottom() to new_top() should be marked as filled
// and all
Region
s between new_top() and top() should be available (i.e.,
// should have been emptied).
ParallelCompactData
&
sd
=
summary_data
();
SpaceInfo
si
=
_space_info
[
space_id
];
HeapWord
*
new_top_addr
=
sd
.
chunk
_align_up
(
si
.
new_top
());
HeapWord
*
old_top_addr
=
sd
.
chunk
_align_up
(
si
.
space
()
->
top
());
const
size_t
beg_
chunk
=
sd
.
addr_to_chunk
_idx
(
si
.
space
()
->
bottom
());
const
size_t
new_top_
chunk
=
sd
.
addr_to_chunk
_idx
(
new_top_addr
);
const
size_t
old_top_
chunk
=
sd
.
addr_to_chunk
_idx
(
old_top_addr
);
HeapWord
*
new_top_addr
=
sd
.
region
_align_up
(
si
.
new_top
());
HeapWord
*
old_top_addr
=
sd
.
region
_align_up
(
si
.
space
()
->
top
());
const
size_t
beg_
region
=
sd
.
addr_to_region
_idx
(
si
.
space
()
->
bottom
());
const
size_t
new_top_
region
=
sd
.
addr_to_region
_idx
(
new_top_addr
);
const
size_t
old_top_
region
=
sd
.
addr_to_region
_idx
(
old_top_addr
);
bool
issued_a_warning
=
false
;
size_t
cur_
chunk
;
for
(
cur_
chunk
=
beg_chunk
;
cur_chunk
<
new_top_chunk
;
++
cur_chunk
)
{
const
ChunkData
*
const
c
=
sd
.
chunk
(
cur_chunk
);
size_t
cur_
region
;
for
(
cur_
region
=
beg_region
;
cur_region
<
new_top_region
;
++
cur_region
)
{
const
RegionData
*
const
c
=
sd
.
region
(
cur_region
);
if
(
!
c
->
completed
())
{
warning
(
"
chunk
"
SIZE_FORMAT
" not filled: "
warning
(
"
region
"
SIZE_FORMAT
" not filled: "
"destination_count="
SIZE_FORMAT
,
cur_
chunk
,
c
->
destination_count
());
cur_
region
,
c
->
destination_count
());
issued_a_warning
=
true
;
}
}
for
(
cur_
chunk
=
new_top_chunk
;
cur_chunk
<
old_top_chunk
;
++
cur_chunk
)
{
const
ChunkData
*
const
c
=
sd
.
chunk
(
cur_chunk
);
for
(
cur_
region
=
new_top_region
;
cur_region
<
old_top_region
;
++
cur_region
)
{
const
RegionData
*
const
c
=
sd
.
region
(
cur_region
);
if
(
!
c
->
available
())
{
warning
(
"
chunk
"
SIZE_FORMAT
" not empty: "
warning
(
"
region
"
SIZE_FORMAT
" not empty: "
"destination_count="
SIZE_FORMAT
,
cur_
chunk
,
c
->
destination_count
());
cur_
region
,
c
->
destination_count
());
issued_a_warning
=
true
;
}
}
if
(
issued_a_warning
)
{
print_
chunk
_ranges
();
print_
region
_ranges
();
}
}
#endif // #ifdef ASSERT
...
...
@@ -2789,46 +2800,47 @@ void PSParallelCompact::print_new_location_of_heap_address(HeapWord* q) {
}
#endif //VALIDATE_MARK_SWEEP
// Update interior oops in the ranges of
chunks [beg_chunk, end_chunk
).
// Update interior oops in the ranges of
regions [beg_region, end_region
).
void
PSParallelCompact
::
update_and_deadwood_in_dense_prefix
(
ParCompactionManager
*
cm
,
SpaceId
space_id
,
size_t
beg_
chunk
,
size_t
end_
chunk
)
{
size_t
beg_
region
,
size_t
end_
region
)
{
ParallelCompactData
&
sd
=
summary_data
();
ParMarkBitMap
*
const
mbm
=
mark_bitmap
();
HeapWord
*
beg_addr
=
sd
.
chunk_to_addr
(
beg_chunk
);
HeapWord
*
const
end_addr
=
sd
.
chunk_to_addr
(
end_chunk
);
assert
(
beg_
chunk
<=
end_chunk
,
"bad chunk
range"
);
HeapWord
*
beg_addr
=
sd
.
region_to_addr
(
beg_region
);
HeapWord
*
const
end_addr
=
sd
.
region_to_addr
(
end_region
);
assert
(
beg_
region
<=
end_region
,
"bad region
range"
);
assert
(
end_addr
<=
dense_prefix
(
space_id
),
"not in the dense prefix"
);
#ifdef ASSERT
// Claim the
chunk
s to avoid triggering an assert when they are marked as
// Claim the
region
s to avoid triggering an assert when they are marked as
// filled.
for
(
size_t
claim_
chunk
=
beg_chunk
;
claim_chunk
<
end_chunk
;
++
claim_chunk
)
{
assert
(
sd
.
chunk
(
claim_chunk
)
->
claim_unsafe
(),
"claim() failed"
);
for
(
size_t
claim_
region
=
beg_region
;
claim_region
<
end_region
;
++
claim_region
)
{
assert
(
sd
.
region
(
claim_region
)
->
claim_unsafe
(),
"claim() failed"
);
}
#endif // #ifdef ASSERT
if
(
beg_addr
!=
space
(
space_id
)
->
bottom
())
{
// Find the first live object or block of dead space that *starts* in this
// range of chunks. If a partial object crosses onto the chunk, skip it; it
// will be marked for 'deferred update' when the object head is processed.
// If dead space crosses onto the chunk, it is also skipped; it will be
// filled when the prior chunk is processed. If neither of those apply, the
// first word in the chunk is the start of a live object or dead space.
// range of regions. If a partial object crosses onto the region, skip it;
// it will be marked for 'deferred update' when the object head is
// processed. If dead space crosses onto the region, it is also skipped; it
// will be filled when the prior region is processed. If neither of those
// apply, the first word in the region is the start of a live object or dead
// space.
assert
(
beg_addr
>
space
(
space_id
)
->
bottom
(),
"sanity"
);
const
ChunkData
*
const
cp
=
sd
.
chunk
(
beg_chunk
);
const
RegionData
*
const
cp
=
sd
.
region
(
beg_region
);
if
(
cp
->
partial_obj_size
()
!=
0
)
{
beg_addr
=
sd
.
partial_obj_end
(
beg_
chunk
);
beg_addr
=
sd
.
partial_obj_end
(
beg_
region
);
}
else
if
(
dead_space_crosses_boundary
(
cp
,
mbm
->
addr_to_bit
(
beg_addr
)))
{
beg_addr
=
mbm
->
find_obj_beg
(
beg_addr
,
end_addr
);
}
}
if
(
beg_addr
<
end_addr
)
{
// A live object or block of dead space starts in this range of
Chunk
s.
// A live object or block of dead space starts in this range of
Region
s.
HeapWord
*
const
dense_prefix_end
=
dense_prefix
(
space_id
);
// Create closures and iterate.
...
...
@@ -2842,10 +2854,10 @@ PSParallelCompact::update_and_deadwood_in_dense_prefix(ParCompactionManager* cm,
}
}
// Mark the
chunk
s as filled.
ChunkData
*
const
beg_cp
=
sd
.
chunk
(
beg_chunk
);
ChunkData
*
const
end_cp
=
sd
.
chunk
(
end_chunk
);
for
(
Chunk
Data
*
cp
=
beg_cp
;
cp
<
end_cp
;
++
cp
)
{
// Mark the
region
s as filled.
RegionData
*
const
beg_cp
=
sd
.
region
(
beg_region
);
RegionData
*
const
end_cp
=
sd
.
region
(
end_region
);
for
(
Region
Data
*
cp
=
beg_cp
;
cp
<
end_cp
;
++
cp
)
{
cp
->
set_completed
();
}
}
...
...
@@ -2877,13 +2889,13 @@ void PSParallelCompact::update_deferred_objects(ParCompactionManager* cm,
const
MutableSpace
*
const
space
=
space_info
->
space
();
assert
(
space_info
->
dense_prefix
()
>=
space
->
bottom
(),
"dense_prefix not set"
);
HeapWord
*
const
beg_addr
=
space_info
->
dense_prefix
();
HeapWord
*
const
end_addr
=
sd
.
chunk
_align_up
(
space_info
->
new_top
());
HeapWord
*
const
end_addr
=
sd
.
region
_align_up
(
space_info
->
new_top
());
const
ChunkData
*
const
beg_chunk
=
sd
.
addr_to_chunk
_ptr
(
beg_addr
);
const
ChunkData
*
const
end_chunk
=
sd
.
addr_to_chunk
_ptr
(
end_addr
);
const
ChunkData
*
cur_chunk
;
for
(
cur_
chunk
=
beg_chunk
;
cur_chunk
<
end_chunk
;
++
cur_chunk
)
{
HeapWord
*
const
addr
=
cur_
chunk
->
deferred_obj_addr
();
const
RegionData
*
const
beg_region
=
sd
.
addr_to_region
_ptr
(
beg_addr
);
const
RegionData
*
const
end_region
=
sd
.
addr_to_region
_ptr
(
end_addr
);
const
RegionData
*
cur_region
;
for
(
cur_
region
=
beg_region
;
cur_region
<
end_region
;
++
cur_region
)
{
HeapWord
*
const
addr
=
cur_
region
->
deferred_obj_addr
();
if
(
addr
!=
NULL
)
{
if
(
start_array
!=
NULL
)
{
start_array
->
allocate_block
(
addr
);
...
...
@@ -2929,45 +2941,45 @@ PSParallelCompact::skip_live_words(HeapWord* beg, HeapWord* end, size_t count)
HeapWord
*
PSParallelCompact
::
first_src_addr
(
HeapWord
*
const
dest_addr
,
size_t
src_
chunk
_idx
)
size_t
src_
region
_idx
)
{
ParMarkBitMap
*
const
bitmap
=
mark_bitmap
();
const
ParallelCompactData
&
sd
=
summary_data
();
const
size_t
ChunkSize
=
ParallelCompactData
::
Chunk
Size
;
const
size_t
RegionSize
=
ParallelCompactData
::
Region
Size
;
assert
(
sd
.
is_
chunk
_aligned
(
dest_addr
),
"not aligned"
);
assert
(
sd
.
is_
region
_aligned
(
dest_addr
),
"not aligned"
);
const
ChunkData
*
const
src_chunk_ptr
=
sd
.
chunk
(
src_chunk
_idx
);
const
size_t
partial_obj_size
=
src_
chunk
_ptr
->
partial_obj_size
();
HeapWord
*
const
src_
chunk_destination
=
src_chunk
_ptr
->
destination
();
const
RegionData
*
const
src_region_ptr
=
sd
.
region
(
src_region
_idx
);
const
size_t
partial_obj_size
=
src_
region
_ptr
->
partial_obj_size
();
HeapWord
*
const
src_
region_destination
=
src_region
_ptr
->
destination
();
assert
(
dest_addr
>=
src_
chunk_destination
,
"wrong src chunk
"
);
assert
(
src_
chunk_ptr
->
data_size
()
>
0
,
"src chunk
cannot be empty"
);
assert
(
dest_addr
>=
src_
region_destination
,
"wrong src region
"
);
assert
(
src_
region_ptr
->
data_size
()
>
0
,
"src region
cannot be empty"
);
HeapWord
*
const
src_
chunk_beg
=
sd
.
chunk_to_addr
(
src_chunk
_idx
);
HeapWord
*
const
src_
chunk_end
=
src_chunk_beg
+
Chunk
Size
;
HeapWord
*
const
src_
region_beg
=
sd
.
region_to_addr
(
src_region
_idx
);
HeapWord
*
const
src_
region_end
=
src_region_beg
+
Region
Size
;
HeapWord
*
addr
=
src_
chunk
_beg
;
if
(
dest_addr
==
src_
chunk
_destination
)
{
// Return the first live word in the source
chunk
.
HeapWord
*
addr
=
src_
region
_beg
;
if
(
dest_addr
==
src_
region
_destination
)
{
// Return the first live word in the source
region
.
if
(
partial_obj_size
==
0
)
{
addr
=
bitmap
->
find_obj_beg
(
addr
,
src_
chunk
_end
);
assert
(
addr
<
src_
chunk_end
,
"no objects start in src chunk
"
);
addr
=
bitmap
->
find_obj_beg
(
addr
,
src_
region
_end
);
assert
(
addr
<
src_
region_end
,
"no objects start in src region
"
);
}
return
addr
;
}
// Must skip some live data.
size_t
words_to_skip
=
dest_addr
-
src_
chunk
_destination
;
assert
(
src_
chunk_ptr
->
data_size
()
>
words_to_skip
,
"wrong src chunk
"
);
size_t
words_to_skip
=
dest_addr
-
src_
region
_destination
;
assert
(
src_
region_ptr
->
data_size
()
>
words_to_skip
,
"wrong src region
"
);
if
(
partial_obj_size
>=
words_to_skip
)
{
// All the live words to skip are part of the partial object.
addr
+=
words_to_skip
;
if
(
partial_obj_size
==
words_to_skip
)
{
// Find the first live word past the partial object.
addr
=
bitmap
->
find_obj_beg
(
addr
,
src_
chunk
_end
);
assert
(
addr
<
src_
chunk_end
,
"wrong src chunk
"
);
addr
=
bitmap
->
find_obj_beg
(
addr
,
src_
region
_end
);
assert
(
addr
<
src_
region_end
,
"wrong src region
"
);
}
return
addr
;
}
...
...
@@ -2978,63 +2990,64 @@ PSParallelCompact::first_src_addr(HeapWord* const dest_addr,
addr
+=
partial_obj_size
;
}
// Skip over live words due to objects that start in the
chunk
.
addr
=
skip_live_words
(
addr
,
src_
chunk
_end
,
words_to_skip
);
assert
(
addr
<
src_
chunk_end
,
"wrong src chunk
"
);
// Skip over live words due to objects that start in the
region
.
addr
=
skip_live_words
(
addr
,
src_
region
_end
,
words_to_skip
);
assert
(
addr
<
src_
region_end
,
"wrong src region
"
);
return
addr
;
}
void
PSParallelCompact
::
decrement_destination_counts
(
ParCompactionManager
*
cm
,
size_t
beg_
chunk
,
size_t
beg_
region
,
HeapWord
*
end_addr
)
{
ParallelCompactData
&
sd
=
summary_data
();
ChunkData
*
const
beg
=
sd
.
chunk
(
beg_chunk
);
HeapWord
*
const
end_addr_aligned_up
=
sd
.
chunk
_align_up
(
end_addr
);
ChunkData
*
const
end
=
sd
.
addr_to_chunk
_ptr
(
end_addr_aligned_up
);
size_t
cur_idx
=
beg_
chunk
;
for
(
Chunk
Data
*
cur
=
beg
;
cur
<
end
;
++
cur
,
++
cur_idx
)
{
assert
(
cur
->
data_size
()
>
0
,
"
chunk
must have live data"
);
RegionData
*
const
beg
=
sd
.
region
(
beg_region
);
HeapWord
*
const
end_addr_aligned_up
=
sd
.
region
_align_up
(
end_addr
);
RegionData
*
const
end
=
sd
.
addr_to_region
_ptr
(
end_addr_aligned_up
);
size_t
cur_idx
=
beg_
region
;
for
(
Region
Data
*
cur
=
beg
;
cur
<
end
;
++
cur
,
++
cur_idx
)
{
assert
(
cur
->
data_size
()
>
0
,
"
region
must have live data"
);
cur
->
decrement_destination_count
();
if
(
cur_idx
<=
cur
->
source_
chunk
()
&&
cur
->
available
()
&&
cur
->
claim
())
{
if
(
cur_idx
<=
cur
->
source_
region
()
&&
cur
->
available
()
&&
cur
->
claim
())
{
cm
->
save_for_processing
(
cur_idx
);
}
}
}
size_t
PSParallelCompact
::
next_src_
chunk
(
MoveAndUpdateClosure
&
closure
,
SpaceId
&
src_space_id
,
HeapWord
*&
src_space_top
,
HeapWord
*
end_addr
)
size_t
PSParallelCompact
::
next_src_
region
(
MoveAndUpdateClosure
&
closure
,
SpaceId
&
src_space_id
,
HeapWord
*&
src_space_top
,
HeapWord
*
end_addr
)
{
typedef
ParallelCompactData
::
ChunkData
Chunk
Data
;
typedef
ParallelCompactData
::
RegionData
Region
Data
;
ParallelCompactData
&
sd
=
PSParallelCompact
::
summary_data
();
const
size_t
chunk_size
=
ParallelCompactData
::
ChunkSize
;
size_t
src_chunk_idx
=
0
;
// Skip empty chunks (if any) up to the top of the space.
HeapWord
*
const
src_aligned_up
=
sd
.
chunk_align_up
(
end_addr
);
ChunkData
*
src_chunk_ptr
=
sd
.
addr_to_chunk_ptr
(
src_aligned_up
);
HeapWord
*
const
top_aligned_up
=
sd
.
chunk_align_up
(
src_space_top
);
const
ChunkData
*
const
top_chunk_ptr
=
sd
.
addr_to_chunk_ptr
(
top_aligned_up
);
while
(
src_chunk_ptr
<
top_chunk_ptr
&&
src_chunk_ptr
->
data_size
()
==
0
)
{
++
src_chunk_ptr
;
}
if
(
src_chunk_ptr
<
top_chunk_ptr
)
{
// The next source chunk is in the current space. Update src_chunk_idx and
// the source address to match src_chunk_ptr.
src_chunk_idx
=
sd
.
chunk
(
src_chunk_ptr
);
HeapWord
*
const
src_chunk_addr
=
sd
.
chunk_to_addr
(
src_chunk_idx
);
if
(
src_chunk_addr
>
closure
.
source
())
{
closure
.
set_source
(
src_chunk_addr
);
const
size_t
region_size
=
ParallelCompactData
::
RegionSize
;
size_t
src_region_idx
=
0
;
// Skip empty regions (if any) up to the top of the space.
HeapWord
*
const
src_aligned_up
=
sd
.
region_align_up
(
end_addr
);
RegionData
*
src_region_ptr
=
sd
.
addr_to_region_ptr
(
src_aligned_up
);
HeapWord
*
const
top_aligned_up
=
sd
.
region_align_up
(
src_space_top
);
const
RegionData
*
const
top_region_ptr
=
sd
.
addr_to_region_ptr
(
top_aligned_up
);
while
(
src_region_ptr
<
top_region_ptr
&&
src_region_ptr
->
data_size
()
==
0
)
{
++
src_region_ptr
;
}
if
(
src_region_ptr
<
top_region_ptr
)
{
// The next source region is in the current space. Update src_region_idx
// and the source address to match src_region_ptr.
src_region_idx
=
sd
.
region
(
src_region_ptr
);
HeapWord
*
const
src_region_addr
=
sd
.
region_to_addr
(
src_region_idx
);
if
(
src_region_addr
>
closure
.
source
())
{
closure
.
set_source
(
src_region_addr
);
}
return
src_
chunk
_idx
;
return
src_
region
_idx
;
}
// Switch to a new source space and find the first non-empty
chunk
.
// Switch to a new source space and find the first non-empty
region
.
unsigned
int
space_id
=
src_space_id
+
1
;
assert
(
space_id
<
last_space_id
,
"not enough spaces"
);
...
...
@@ -3043,14 +3056,14 @@ size_t PSParallelCompact::next_src_chunk(MoveAndUpdateClosure& closure,
do
{
MutableSpace
*
space
=
_space_info
[
space_id
].
space
();
HeapWord
*
const
bottom
=
space
->
bottom
();
const
ChunkData
*
const
bottom_cp
=
sd
.
addr_to_chunk
_ptr
(
bottom
);
const
RegionData
*
const
bottom_cp
=
sd
.
addr_to_region
_ptr
(
bottom
);
// Iterate over the spaces that do not compact into themselves.
if
(
bottom_cp
->
destination
()
!=
bottom
)
{
HeapWord
*
const
top_aligned_up
=
sd
.
chunk
_align_up
(
space
->
top
());
const
ChunkData
*
const
top_cp
=
sd
.
addr_to_chunk
_ptr
(
top_aligned_up
);
HeapWord
*
const
top_aligned_up
=
sd
.
region
_align_up
(
space
->
top
());
const
RegionData
*
const
top_cp
=
sd
.
addr_to_region
_ptr
(
top_aligned_up
);
for
(
const
Chunk
Data
*
src_cp
=
bottom_cp
;
src_cp
<
top_cp
;
++
src_cp
)
{
for
(
const
Region
Data
*
src_cp
=
bottom_cp
;
src_cp
<
top_cp
;
++
src_cp
)
{
if
(
src_cp
->
live_obj_size
()
>
0
)
{
// Found it.
assert
(
src_cp
->
destination
()
==
destination
,
...
...
@@ -3060,9 +3073,9 @@ size_t PSParallelCompact::next_src_chunk(MoveAndUpdateClosure& closure,
src_space_id
=
SpaceId
(
space_id
);
src_space_top
=
space
->
top
();
const
size_t
src_
chunk_idx
=
sd
.
chunk
(
src_cp
);
closure
.
set_source
(
sd
.
chunk_to_addr
(
src_chunk
_idx
));
return
src_
chunk
_idx
;
const
size_t
src_
region_idx
=
sd
.
region
(
src_cp
);
closure
.
set_source
(
sd
.
region_to_addr
(
src_region
_idx
));
return
src_
region
_idx
;
}
else
{
assert
(
src_cp
->
data_size
()
==
0
,
"sanity"
);
}
...
...
@@ -3070,38 +3083,38 @@ size_t PSParallelCompact::next_src_chunk(MoveAndUpdateClosure& closure,
}
}
while
(
++
space_id
<
last_space_id
);
assert
(
false
,
"no source
chunk
was found"
);
assert
(
false
,
"no source
region
was found"
);
return
0
;
}
void
PSParallelCompact
::
fill_
chunk
(
ParCompactionManager
*
cm
,
size_t
chunk
_idx
)
void
PSParallelCompact
::
fill_
region
(
ParCompactionManager
*
cm
,
size_t
region
_idx
)
{
typedef
ParMarkBitMap
::
IterationStatus
IterationStatus
;
const
size_t
ChunkSize
=
ParallelCompactData
::
Chunk
Size
;
const
size_t
RegionSize
=
ParallelCompactData
::
Region
Size
;
ParMarkBitMap
*
const
bitmap
=
mark_bitmap
();
ParallelCompactData
&
sd
=
summary_data
();
ChunkData
*
const
chunk_ptr
=
sd
.
chunk
(
chunk
_idx
);
RegionData
*
const
region_ptr
=
sd
.
region
(
region
_idx
);
// Get the items needed to construct the closure.
HeapWord
*
dest_addr
=
sd
.
chunk_to_addr
(
chunk
_idx
);
HeapWord
*
dest_addr
=
sd
.
region_to_addr
(
region
_idx
);
SpaceId
dest_space_id
=
space_id
(
dest_addr
);
ObjectStartArray
*
start_array
=
_space_info
[
dest_space_id
].
start_array
();
HeapWord
*
new_top
=
_space_info
[
dest_space_id
].
new_top
();
assert
(
dest_addr
<
new_top
,
"sanity"
);
const
size_t
words
=
MIN2
(
pointer_delta
(
new_top
,
dest_addr
),
Chunk
Size
);
const
size_t
words
=
MIN2
(
pointer_delta
(
new_top
,
dest_addr
),
Region
Size
);
// Get the source
chunk
and related info.
size_t
src_
chunk_idx
=
chunk_ptr
->
source_chunk
();
SpaceId
src_space_id
=
space_id
(
sd
.
chunk_to_addr
(
src_chunk
_idx
));
// Get the source
region
and related info.
size_t
src_
region_idx
=
region_ptr
->
source_region
();
SpaceId
src_space_id
=
space_id
(
sd
.
region_to_addr
(
src_region
_idx
));
HeapWord
*
src_space_top
=
_space_info
[
src_space_id
].
space
()
->
top
();
MoveAndUpdateClosure
closure
(
bitmap
,
cm
,
start_array
,
dest_addr
,
words
);
closure
.
set_source
(
first_src_addr
(
dest_addr
,
src_
chunk
_idx
));
closure
.
set_source
(
first_src_addr
(
dest_addr
,
src_
region
_idx
));
// Adjust src_
chunk
_idx to prepare for decrementing destination counts (the
// destination count is not decremented when a
chunk
is copied to itself).
if
(
src_
chunk_idx
==
chunk
_idx
)
{
src_
chunk
_idx
+=
1
;
// Adjust src_
region
_idx to prepare for decrementing destination counts (the
// destination count is not decremented when a
region
is copied to itself).
if
(
src_
region_idx
==
region
_idx
)
{
src_
region
_idx
+=
1
;
}
if
(
bitmap
->
is_unmarked
(
closure
.
source
()))
{
...
...
@@ -3111,32 +3124,33 @@ void PSParallelCompact::fill_chunk(ParCompactionManager* cm, size_t chunk_idx)
HeapWord
*
const
old_src_addr
=
closure
.
source
();
closure
.
copy_partial_obj
();
if
(
closure
.
is_full
())
{
decrement_destination_counts
(
cm
,
src_
chunk
_idx
,
closure
.
source
());
chunk
_ptr
->
set_deferred_obj_addr
(
NULL
);
chunk
_ptr
->
set_completed
();
decrement_destination_counts
(
cm
,
src_
region
_idx
,
closure
.
source
());
region
_ptr
->
set_deferred_obj_addr
(
NULL
);
region
_ptr
->
set_completed
();
return
;
}
HeapWord
*
const
end_addr
=
sd
.
chunk
_align_down
(
closure
.
source
());
if
(
sd
.
chunk
_align_down
(
old_src_addr
)
!=
end_addr
)
{
// The partial object was copied from more than one source
chunk
.
decrement_destination_counts
(
cm
,
src_
chunk
_idx
,
end_addr
);
HeapWord
*
const
end_addr
=
sd
.
region
_align_down
(
closure
.
source
());
if
(
sd
.
region
_align_down
(
old_src_addr
)
!=
end_addr
)
{
// The partial object was copied from more than one source
region
.
decrement_destination_counts
(
cm
,
src_
region
_idx
,
end_addr
);
// Move to the next source
chunk
, possibly switching spaces as well. All
// Move to the next source
region
, possibly switching spaces as well. All
// args except end_addr may be modified.
src_
chunk_idx
=
next_src_chunk
(
closure
,
src_space_id
,
src_space_top
,
end_addr
);
src_
region_idx
=
next_src_region
(
closure
,
src_space_id
,
src_space_top
,
end_addr
);
}
}
do
{
HeapWord
*
const
cur_addr
=
closure
.
source
();
HeapWord
*
const
end_addr
=
MIN2
(
sd
.
chunk
_align_up
(
cur_addr
+
1
),
HeapWord
*
const
end_addr
=
MIN2
(
sd
.
region
_align_up
(
cur_addr
+
1
),
src_space_top
);
IterationStatus
status
=
bitmap
->
iterate
(
&
closure
,
cur_addr
,
end_addr
);
if
(
status
==
ParMarkBitMap
::
incomplete
)
{
// The last obj that starts in the source chunk does not end in the chunk.
// The last obj that starts in the source region does not end in the
// region.
assert
(
closure
.
source
()
<
end_addr
,
"sanity"
)
HeapWord
*
const
obj_beg
=
closure
.
source
();
HeapWord
*
const
range_end
=
MIN2
(
obj_beg
+
closure
.
words_remaining
(),
...
...
@@ -3155,28 +3169,28 @@ void PSParallelCompact::fill_chunk(ParCompactionManager* cm, size_t chunk_idx)
if
(
status
==
ParMarkBitMap
::
would_overflow
)
{
// The last object did not fit. Note that interior oop updates were
// deferred, then copy enough of the object to fill the
chunk
.
chunk
_ptr
->
set_deferred_obj_addr
(
closure
.
destination
());
// deferred, then copy enough of the object to fill the
region
.
region
_ptr
->
set_deferred_obj_addr
(
closure
.
destination
());
status
=
closure
.
copy_until_full
();
// copies from closure.source()
decrement_destination_counts
(
cm
,
src_
chunk
_idx
,
closure
.
source
());
chunk
_ptr
->
set_completed
();
decrement_destination_counts
(
cm
,
src_
region
_idx
,
closure
.
source
());
region
_ptr
->
set_completed
();
return
;
}
if
(
status
==
ParMarkBitMap
::
full
)
{
decrement_destination_counts
(
cm
,
src_
chunk
_idx
,
closure
.
source
());
chunk
_ptr
->
set_deferred_obj_addr
(
NULL
);
chunk
_ptr
->
set_completed
();
decrement_destination_counts
(
cm
,
src_
region
_idx
,
closure
.
source
());
region
_ptr
->
set_deferred_obj_addr
(
NULL
);
region
_ptr
->
set_completed
();
return
;
}
decrement_destination_counts
(
cm
,
src_
chunk
_idx
,
end_addr
);
decrement_destination_counts
(
cm
,
src_
region
_idx
,
end_addr
);
// Move to the next source
chunk
, possibly switching spaces as well. All
// Move to the next source
region
, possibly switching spaces as well. All
// args except end_addr may be modified.
src_
chunk_idx
=
next_src_chunk
(
closure
,
src_space_id
,
src_space_top
,
end_addr
);
src_
region_idx
=
next_src_region
(
closure
,
src_space_id
,
src_space_top
,
end_addr
);
}
while
(
true
);
}
...
...
@@ -3208,15 +3222,15 @@ PSParallelCompact::move_and_update(ParCompactionManager* cm, SpaceId space_id) {
}
#endif
const
size_t
beg_
chunk
=
sd
.
addr_to_chunk
_idx
(
beg_addr
);
const
size_t
dp_
chunk
=
sd
.
addr_to_chunk
_idx
(
dp_addr
);
if
(
beg_
chunk
<
dp_chunk
)
{
update_and_deadwood_in_dense_prefix
(
cm
,
space_id
,
beg_
chunk
,
dp_chunk
);
const
size_t
beg_
region
=
sd
.
addr_to_region
_idx
(
beg_addr
);
const
size_t
dp_
region
=
sd
.
addr_to_region
_idx
(
dp_addr
);
if
(
beg_
region
<
dp_region
)
{
update_and_deadwood_in_dense_prefix
(
cm
,
space_id
,
beg_
region
,
dp_region
);
}
// The destination of the first live object that starts in the
chunk
is one
// past the end of the partial object entering the
chunk
(if any).
HeapWord
*
const
dest_addr
=
sd
.
partial_obj_end
(
dp_
chunk
);
// The destination of the first live object that starts in the
region
is one
// past the end of the partial object entering the
region
(if any).
HeapWord
*
const
dest_addr
=
sd
.
partial_obj_end
(
dp_
region
);
HeapWord
*
const
new_top
=
_space_info
[
space_id
].
new_top
();
assert
(
new_top
>=
dest_addr
,
"bad new_top value"
);
const
size_t
words
=
pointer_delta
(
new_top
,
dest_addr
);
...
...
@@ -3327,41 +3341,41 @@ UpdateOnlyClosure::do_addr(HeapWord* addr, size_t words) {
BitBlockUpdateClosure
::
BitBlockUpdateClosure
(
ParMarkBitMap
*
mbm
,
ParCompactionManager
*
cm
,
size_t
chunk
_index
)
:
size_t
region
_index
)
:
ParMarkBitMapClosure
(
mbm
,
cm
),
_live_data_left
(
0
),
_cur_block
(
0
)
{
_
chunk
_start
=
PSParallelCompact
::
summary_data
().
chunk_to_addr
(
chunk
_index
);
_
chunk
_end
=
PSParallelCompact
::
summary_data
().
chunk_to_addr
(
chunk
_index
)
+
ParallelCompactData
::
Chunk
Size
;
_
chunk_index
=
chunk
_index
;
_
region
_start
=
PSParallelCompact
::
summary_data
().
region_to_addr
(
region
_index
);
_
region
_end
=
PSParallelCompact
::
summary_data
().
region_to_addr
(
region
_index
)
+
ParallelCompactData
::
Region
Size
;
_
region_index
=
region
_index
;
_cur_block
=
PSParallelCompact
::
summary_data
().
addr_to_block_idx
(
_
chunk
_start
);
PSParallelCompact
::
summary_data
().
addr_to_block_idx
(
_
region
_start
);
}
bool
BitBlockUpdateClosure
::
chunk
_contains_cur_block
()
{
return
ParallelCompactData
::
chunk_contains_block
(
_chunk
_index
,
_cur_block
);
bool
BitBlockUpdateClosure
::
region
_contains_cur_block
()
{
return
ParallelCompactData
::
region_contains_block
(
_region
_index
,
_cur_block
);
}
void
BitBlockUpdateClosure
::
reset_
chunk
(
size_t
chunk
_index
)
{
void
BitBlockUpdateClosure
::
reset_
region
(
size_t
region
_index
)
{
DEBUG_ONLY
(
ParallelCompactData
::
BlockData
::
set_cur_phase
(
7
);)
ParallelCompactData
&
sd
=
PSParallelCompact
::
summary_data
();
_
chunk_index
=
chunk
_index
;
_
region_index
=
region
_index
;
_live_data_left
=
0
;
_
chunk_start
=
sd
.
chunk_to_addr
(
chunk
_index
);
_
chunk_end
=
sd
.
chunk_to_addr
(
chunk_index
)
+
ParallelCompactData
::
Chunk
Size
;
_
region_start
=
sd
.
region_to_addr
(
region
_index
);
_
region_end
=
sd
.
region_to_addr
(
region_index
)
+
ParallelCompactData
::
Region
Size
;
// The first block in this
chunk
size_t
first_block
=
sd
.
addr_to_block_idx
(
_
chunk
_start
);
size_t
partial_live_size
=
sd
.
chunk
(
chunk
_index
)
->
partial_obj_size
();
// The first block in this
region
size_t
first_block
=
sd
.
addr_to_block_idx
(
_
region
_start
);
size_t
partial_live_size
=
sd
.
region
(
region
_index
)
->
partial_obj_size
();
// Set the offset to 0. By definition it should have that value
// but it may have been written while processing an earlier
chunk
.
// but it may have been written while processing an earlier
region
.
if
(
partial_live_size
==
0
)
{
// No live object extends onto the
chunk
. The first bit
// in the bit map for the first
chunk
must be a start bit.
// No live object extends onto the
region
. The first bit
// in the bit map for the first
region
must be a start bit.
// Although there may not be any marked bits, it is safe
// to set it as a start bit.
sd
.
block
(
first_block
)
->
set_start_bit_offset
(
0
);
...
...
@@ -3413,8 +3427,8 @@ BitBlockUpdateClosure::do_addr(HeapWord* addr, size_t words) {
ParallelCompactData
&
sd
=
PSParallelCompact
::
summary_data
();
assert
(
bitmap
()
->
obj_size
(
obj
)
==
words
,
"bad size"
);
assert
(
_
chunk_start
<=
obj
,
"object is not in chunk
"
);
assert
(
obj
+
words
<=
_
chunk_end
,
"object is not in chunk
"
);
assert
(
_
region_start
<=
obj
,
"object is not in region
"
);
assert
(
obj
+
words
<=
_
region_end
,
"object is not in region
"
);
// Update the live data to the left
size_t
prev_live_data_left
=
_live_data_left
;
...
...
@@ -3432,7 +3446,7 @@ BitBlockUpdateClosure::do_addr(HeapWord* addr, size_t words) {
// the new block with the data size that does not include this object.
//
// The first bit in block_of_obj is a start bit except in the
// case where the partial object for the
chunk
extends into
// case where the partial object for the
region
extends into
// this block.
if
(
sd
.
partial_obj_ends_in_block
(
block_of_obj
))
{
sd
.
block
(
block_of_obj
)
->
set_end_bit_offset
(
prev_live_data_left
);
...
...
@@ -3449,9 +3463,9 @@ BitBlockUpdateClosure::do_addr(HeapWord* addr, size_t words) {
// The offset for blocks with no objects starting in them
// (e.g., blocks between _cur_block and block_of_obj_last)
// should not be needed.
// Note that block_of_obj_last may be in another
chunk
. If so,
// Note that block_of_obj_last may be in another
region
. If so,
// it should be overwritten later. This is a problem (writting
// into a block in a later
chunk
) for parallel execution.
// into a block in a later
region
) for parallel execution.
assert
(
obj
<
block_of_obj_last_addr
,
"Object should start in previous block"
);
...
...
@@ -3485,7 +3499,7 @@ BitBlockUpdateClosure::do_addr(HeapWord* addr, size_t words) {
}
// Return incomplete if there are more blocks to be done.
if
(
chunk
_contains_cur_block
())
{
if
(
region
_contains_cur_block
())
{
return
ParMarkBitMap
::
incomplete
;
}
return
ParMarkBitMap
::
complete
;
...
...
src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp
浏览文件 @
bee8b017
...
...
@@ -76,87 +76,87 @@ class ParallelCompactData
{
public:
// Sizes are in HeapWords, unless indicated otherwise.
static
const
size_t
Log2
Chunk
Size
;
static
const
size_t
Chunk
Size
;
static
const
size_t
Chunk
SizeBytes
;
static
const
size_t
Log2
Region
Size
;
static
const
size_t
Region
Size
;
static
const
size_t
Region
SizeBytes
;
// Mask for the bits in a size_t to get an offset within a
chunk
.
static
const
size_t
Chunk
SizeOffsetMask
;
// Mask for the bits in a pointer to get an offset within a
chunk
.
static
const
size_t
Chunk
AddrOffsetMask
;
// Mask for the bits in a pointer to get the address of the start of a
chunk
.
static
const
size_t
Chunk
AddrMask
;
// Mask for the bits in a size_t to get an offset within a
region
.
static
const
size_t
Region
SizeOffsetMask
;
// Mask for the bits in a pointer to get an offset within a
region
.
static
const
size_t
Region
AddrOffsetMask
;
// Mask for the bits in a pointer to get the address of the start of a
region
.
static
const
size_t
Region
AddrMask
;
static
const
size_t
Log2BlockSize
;
static
const
size_t
BlockSize
;
static
const
size_t
BlockOffsetMask
;
static
const
size_t
BlockMask
;
static
const
size_t
BlocksPer
Chunk
;
static
const
size_t
BlocksPer
Region
;
class
Chunk
Data
class
Region
Data
{
public:
// Destination address of the
chunk
.
// Destination address of the
region
.
HeapWord
*
destination
()
const
{
return
_destination
;
}
// The first
chunk containing data destined for this chunk
.
size_t
source_
chunk
()
const
{
return
_source_chunk
;
}
// The first
region containing data destined for this region
.
size_t
source_
region
()
const
{
return
_source_region
;
}
// The object (if any) starting in this
chunk
and ending in a different
//
chunk
that could not be updated during the main (parallel) compaction
// The object (if any) starting in this
region
and ending in a different
//
region
that could not be updated during the main (parallel) compaction
// phase. This is different from _partial_obj_addr, which is an object that
// extends onto a source
chunk
. However, the two uses do not overlap in
// extends onto a source
region
. However, the two uses do not overlap in
// time, so the same field is used to save space.
HeapWord
*
deferred_obj_addr
()
const
{
return
_partial_obj_addr
;
}
// The starting address of the partial object extending onto the
chunk
.
// The starting address of the partial object extending onto the
region
.
HeapWord
*
partial_obj_addr
()
const
{
return
_partial_obj_addr
;
}
// Size of the partial object extending onto the
chunk
(words).
// Size of the partial object extending onto the
region
(words).
size_t
partial_obj_size
()
const
{
return
_partial_obj_size
;
}
// Size of live data that lies within this
chunk
due to objects that start
// in this
chunk
(words). This does not include the partial object
// extending onto the
chunk
(if any), or the part of an object that extends
// onto the next
chunk
(if any).
// Size of live data that lies within this
region
due to objects that start
// in this
region
(words). This does not include the partial object
// extending onto the
region
(if any), or the part of an object that extends
// onto the next
region
(if any).
size_t
live_obj_size
()
const
{
return
_dc_and_los
&
los_mask
;
}
// Total live data that lies within the
chunk
(words).
// Total live data that lies within the
region
(words).
size_t
data_size
()
const
{
return
partial_obj_size
()
+
live_obj_size
();
}
// The destination_count is the number of other
chunk
s to which data from
// this
chunk
will be copied. At the end of the summary phase, the valid
// The destination_count is the number of other
region
s to which data from
// this
region
will be copied. At the end of the summary phase, the valid
// values of destination_count are
//
// 0 - data from the
chunk
will be compacted completely into itself, or the
//
chunk is empty. The chunk
can be claimed and then filled.
// 1 - data from the
chunk will be compacted into 1 other chunk
; some
// data from the
chunk may also be compacted into the chunk
itself.
// 2 - data from the
chunk will be copied to 2 other chunk
s.
// 0 - data from the
region
will be compacted completely into itself, or the
//
region is empty. The region
can be claimed and then filled.
// 1 - data from the
region will be compacted into 1 other region
; some
// data from the
region may also be compacted into the region
itself.
// 2 - data from the
region will be copied to 2 other region
s.
//
// During compaction as
chunk
s are emptied, the destination_count is
// During compaction as
region
s are emptied, the destination_count is
// decremented (atomically) and when it reaches 0, it can be claimed and
// then filled.
//
// A
chunk
is claimed for processing by atomically changing the
// destination_count to the claimed value (dc_claimed). After a
chunk
has
// A
region
is claimed for processing by atomically changing the
// destination_count to the claimed value (dc_claimed). After a
region
has
// been filled, the destination_count should be set to the completed value
// (dc_completed).
inline
uint
destination_count
()
const
;
inline
uint
destination_count_raw
()
const
;
// The location of the java heap data that corresponds to this
chunk
.
// The location of the java heap data that corresponds to this
region
.
inline
HeapWord
*
data_location
()
const
;
// The highest address referenced by objects in this
chunk
.
// The highest address referenced by objects in this
region
.
inline
HeapWord
*
highest_ref
()
const
;
// Whether this
chunk
is available to be claimed, has been claimed, or has
// Whether this
region
is available to be claimed, has been claimed, or has
// been completed.
//
// Minor subtlety: claimed() returns true if the
chunk
is marked
// completed(), which is desirable since a
chunk
must be claimed before it
// Minor subtlety: claimed() returns true if the
region
is marked
// completed(), which is desirable since a
region
must be claimed before it
// can be completed.
bool
available
()
const
{
return
_dc_and_los
<
dc_one
;
}
bool
claimed
()
const
{
return
_dc_and_los
>=
dc_claimed
;
}
...
...
@@ -164,11 +164,11 @@ public:
// These are not atomic.
void
set_destination
(
HeapWord
*
addr
)
{
_destination
=
addr
;
}
void
set_source_
chunk
(
size_t
chunk
)
{
_source_chunk
=
chunk
;
}
void
set_source_
region
(
size_t
region
)
{
_source_region
=
region
;
}
void
set_deferred_obj_addr
(
HeapWord
*
addr
)
{
_partial_obj_addr
=
addr
;
}
void
set_partial_obj_addr
(
HeapWord
*
addr
)
{
_partial_obj_addr
=
addr
;
}
void
set_partial_obj_size
(
size_t
words
)
{
_partial_obj_size
=
(
chunk
_sz_t
)
words
;
_partial_obj_size
=
(
region
_sz_t
)
words
;
}
inline
void
set_destination_count
(
uint
count
);
...
...
@@ -184,44 +184,44 @@ public:
inline
bool
claim
();
private:
// The type used to represent object sizes within a
chunk
.
typedef
uint
chunk
_sz_t
;
// The type used to represent object sizes within a
region
.
typedef
uint
region
_sz_t
;
// Constants for manipulating the _dc_and_los field, which holds both the
// destination count and live obj size. The live obj size lives at the
// least significant end so no masking is necessary when adding.
static
const
chunk
_sz_t
dc_shift
;
// Shift amount.
static
const
chunk
_sz_t
dc_mask
;
// Mask for destination count.
static
const
chunk
_sz_t
dc_one
;
// 1, shifted appropriately.
static
const
chunk_sz_t
dc_claimed
;
// Chunk
has been claimed.
static
const
chunk_sz_t
dc_completed
;
// Chunk
has been completed.
static
const
chunk
_sz_t
los_mask
;
// Mask for live obj size.
HeapWord
*
_destination
;
size_t
_source_chunk
;
HeapWord
*
_partial_obj_addr
;
chunk
_sz_t
_partial_obj_size
;
chunk
_sz_t
volatile
_dc_and_los
;
static
const
region
_sz_t
dc_shift
;
// Shift amount.
static
const
region
_sz_t
dc_mask
;
// Mask for destination count.
static
const
region
_sz_t
dc_one
;
// 1, shifted appropriately.
static
const
region_sz_t
dc_claimed
;
// Region
has been claimed.
static
const
region_sz_t
dc_completed
;
// Region
has been completed.
static
const
region
_sz_t
los_mask
;
// Mask for live obj size.
HeapWord
*
_destination
;
size_t
_source_region
;
HeapWord
*
_partial_obj_addr
;
region
_sz_t
_partial_obj_size
;
region
_sz_t
volatile
_dc_and_los
;
#ifdef ASSERT
// These enable optimizations that are only partially implemented. Use
// debug builds to prevent the code fragments from breaking.
HeapWord
*
_data_location
;
HeapWord
*
_highest_ref
;
HeapWord
*
_data_location
;
HeapWord
*
_highest_ref
;
#endif // #ifdef ASSERT
#ifdef ASSERT
public:
uint
_pushed
;
// 0 until chunk
is pushed onto a worker's stack
uint
_pushed
;
// 0 until region
is pushed onto a worker's stack
private:
#endif
};
// 'Blocks' allow shorter sections of the bitmap to be searched. Each Block
// holds an offset, which is the amount of live data in the
Chunk
to the left
// holds an offset, which is the amount of live data in the
Region
to the left
// of the first live object in the Block. This amount of live data will
// include any object extending into the block. The first block in
// a
chunk
does not include any partial object extending into the
// the
chunk
.
// a
region
does not include any partial object extending into the
// the
region
.
//
// The offset also encodes the
// 'parity' of the first 1 bit in the Block: a positive offset means the
...
...
@@ -286,27 +286,27 @@ public:
ParallelCompactData
();
bool
initialize
(
MemRegion
covered_region
);
size_t
chunk_count
()
const
{
return
_chunk
_count
;
}
size_t
region_count
()
const
{
return
_region
_count
;
}
// Convert
chunk indices to/from Chunk
Data pointers.
inline
ChunkData
*
chunk
(
size_t
chunk
_idx
)
const
;
inline
size_t
chunk
(
const
ChunkData
*
const
chunk
_ptr
)
const
;
// Convert
region indices to/from Region
Data pointers.
inline
RegionData
*
region
(
size_t
region
_idx
)
const
;
inline
size_t
region
(
const
RegionData
*
const
region
_ptr
)
const
;
// Returns true if the given address is contained within the
chunk
bool
chunk_contains
(
size_t
chunk
_index
,
HeapWord
*
addr
);
// Returns true if the given address is contained within the
region
bool
region_contains
(
size_t
region
_index
,
HeapWord
*
addr
);
size_t
block_count
()
const
{
return
_block_count
;
}
inline
BlockData
*
block
(
size_t
n
)
const
;
// Returns true if the given block is in the given
chunk
.
static
bool
chunk_contains_block
(
size_t
chunk
_index
,
size_t
block_index
);
// Returns true if the given block is in the given
region
.
static
bool
region_contains_block
(
size_t
region
_index
,
size_t
block_index
);
void
add_obj
(
HeapWord
*
addr
,
size_t
len
);
void
add_obj
(
oop
p
,
size_t
len
)
{
add_obj
((
HeapWord
*
)
p
,
len
);
}
// Fill in the
chunk
s covering [beg, end) so that no data moves; i.e., the
// destination of
chunk n is simply the start of chunk
n. The argument beg
// must be
chunk
-aligned; end need not be.
// Fill in the
region
s covering [beg, end) so that no data moves; i.e., the
// destination of
region n is simply the start of region
n. The argument beg
// must be
region
-aligned; end need not be.
void
summarize_dense_prefix
(
HeapWord
*
beg
,
HeapWord
*
end
);
bool
summarize
(
HeapWord
*
target_beg
,
HeapWord
*
target_end
,
...
...
@@ -314,27 +314,27 @@ public:
HeapWord
**
target_next
,
HeapWord
**
source_next
=
0
);
void
clear
();
void
clear_range
(
size_t
beg_
chunk
,
size_t
end_chunk
);
void
clear_range
(
size_t
beg_
region
,
size_t
end_region
);
void
clear_range
(
HeapWord
*
beg
,
HeapWord
*
end
)
{
clear_range
(
addr_to_
chunk_idx
(
beg
),
addr_to_chunk
_idx
(
end
));
clear_range
(
addr_to_
region_idx
(
beg
),
addr_to_region
_idx
(
end
));
}
// Return the number of words between addr and the start of the
chunk
// Return the number of words between addr and the start of the
region
// containing addr.
inline
size_t
chunk
_offset
(
const
HeapWord
*
addr
)
const
;
inline
size_t
region
_offset
(
const
HeapWord
*
addr
)
const
;
// Convert addresses to/from a
chunk index or chunk
pointer.
inline
size_t
addr_to_
chunk
_idx
(
const
HeapWord
*
addr
)
const
;
inline
ChunkData
*
addr_to_chunk
_ptr
(
const
HeapWord
*
addr
)
const
;
inline
HeapWord
*
chunk_to_addr
(
size_t
chunk
)
const
;
inline
HeapWord
*
chunk_to_addr
(
size_t
chunk
,
size_t
offset
)
const
;
inline
HeapWord
*
chunk_to_addr
(
const
ChunkData
*
chunk
)
const
;
// Convert addresses to/from a
region index or region
pointer.
inline
size_t
addr_to_
region
_idx
(
const
HeapWord
*
addr
)
const
;
inline
RegionData
*
addr_to_region
_ptr
(
const
HeapWord
*
addr
)
const
;
inline
HeapWord
*
region_to_addr
(
size_t
region
)
const
;
inline
HeapWord
*
region_to_addr
(
size_t
region
,
size_t
offset
)
const
;
inline
HeapWord
*
region_to_addr
(
const
RegionData
*
region
)
const
;
inline
HeapWord
*
chunk
_align_down
(
HeapWord
*
addr
)
const
;
inline
HeapWord
*
chunk
_align_up
(
HeapWord
*
addr
)
const
;
inline
bool
is_
chunk
_aligned
(
HeapWord
*
addr
)
const
;
inline
HeapWord
*
region
_align_down
(
HeapWord
*
addr
)
const
;
inline
HeapWord
*
region
_align_up
(
HeapWord
*
addr
)
const
;
inline
bool
is_
region
_aligned
(
HeapWord
*
addr
)
const
;
// Analogous to
chunk
_offset() for blocks.
// Analogous to
region
_offset() for blocks.
size_t
block_offset
(
const
HeapWord
*
addr
)
const
;
size_t
addr_to_block_idx
(
const
HeapWord
*
addr
)
const
;
size_t
addr_to_block_idx
(
const
oop
obj
)
const
{
...
...
@@ -344,7 +344,7 @@ public:
inline
HeapWord
*
block_to_addr
(
size_t
block
)
const
;
// Return the address one past the end of the partial object.
HeapWord
*
partial_obj_end
(
size_t
chunk
_idx
)
const
;
HeapWord
*
partial_obj_end
(
size_t
region
_idx
)
const
;
// Return the new location of the object p after the
// the compaction.
...
...
@@ -353,8 +353,8 @@ public:
// Same as calc_new_pointer() using blocks.
HeapWord
*
block_calc_new_pointer
(
HeapWord
*
addr
);
// Same as calc_new_pointer() using
chunk
s.
HeapWord
*
chunk
_calc_new_pointer
(
HeapWord
*
addr
);
// Same as calc_new_pointer() using
region
s.
HeapWord
*
region
_calc_new_pointer
(
HeapWord
*
addr
);
HeapWord
*
calc_new_pointer
(
oop
p
)
{
return
calc_new_pointer
((
HeapWord
*
)
p
);
...
...
@@ -364,7 +364,7 @@ public:
klassOop
calc_new_klass
(
klassOop
);
// Given a block returns true if the partial object for the
// corresponding
chunk
ends in the block. Returns false, otherwise
// corresponding
region
ends in the block. Returns false, otherwise
// If there is no partial object, returns false.
bool
partial_obj_ends_in_block
(
size_t
block_index
);
...
...
@@ -378,7 +378,7 @@ public:
private:
bool
initialize_block_data
(
size_t
region_size
);
bool
initialize_
chunk
_data
(
size_t
region_size
);
bool
initialize_
region
_data
(
size_t
region_size
);
PSVirtualSpace
*
create_vspace
(
size_t
count
,
size_t
element_size
);
private:
...
...
@@ -387,9 +387,9 @@ private:
HeapWord
*
_region_end
;
#endif // #ifdef ASSERT
PSVirtualSpace
*
_
chunk
_vspace
;
ChunkData
*
_chunk
_data
;
size_t
_
chunk
_count
;
PSVirtualSpace
*
_
region
_vspace
;
RegionData
*
_region
_data
;
size_t
_
region
_count
;
PSVirtualSpace
*
_block_vspace
;
BlockData
*
_block_data
;
...
...
@@ -397,64 +397,64 @@ private:
};
inline
uint
ParallelCompactData
::
Chunk
Data
::
destination_count_raw
()
const
ParallelCompactData
::
Region
Data
::
destination_count_raw
()
const
{
return
_dc_and_los
&
dc_mask
;
}
inline
uint
ParallelCompactData
::
Chunk
Data
::
destination_count
()
const
ParallelCompactData
::
Region
Data
::
destination_count
()
const
{
return
destination_count_raw
()
>>
dc_shift
;
}
inline
void
ParallelCompactData
::
Chunk
Data
::
set_destination_count
(
uint
count
)
ParallelCompactData
::
Region
Data
::
set_destination_count
(
uint
count
)
{
assert
(
count
<=
(
dc_completed
>>
dc_shift
),
"count too large"
);
const
chunk_sz_t
live_sz
=
(
chunk
_sz_t
)
live_obj_size
();
const
region_sz_t
live_sz
=
(
region
_sz_t
)
live_obj_size
();
_dc_and_los
=
(
count
<<
dc_shift
)
|
live_sz
;
}
inline
void
ParallelCompactData
::
Chunk
Data
::
set_live_obj_size
(
size_t
words
)
inline
void
ParallelCompactData
::
Region
Data
::
set_live_obj_size
(
size_t
words
)
{
assert
(
words
<=
los_mask
,
"would overflow"
);
_dc_and_los
=
destination_count_raw
()
|
(
chunk
_sz_t
)
words
;
_dc_and_los
=
destination_count_raw
()
|
(
region
_sz_t
)
words
;
}
inline
void
ParallelCompactData
::
Chunk
Data
::
decrement_destination_count
()
inline
void
ParallelCompactData
::
Region
Data
::
decrement_destination_count
()
{
assert
(
_dc_and_los
<
dc_claimed
,
"already claimed"
);
assert
(
_dc_and_los
>=
dc_one
,
"count would go negative"
);
Atomic
::
add
((
int
)
dc_mask
,
(
volatile
int
*
)
&
_dc_and_los
);
}
inline
HeapWord
*
ParallelCompactData
::
Chunk
Data
::
data_location
()
const
inline
HeapWord
*
ParallelCompactData
::
Region
Data
::
data_location
()
const
{
DEBUG_ONLY
(
return
_data_location
;)
NOT_DEBUG
(
return
NULL
;)
}
inline
HeapWord
*
ParallelCompactData
::
Chunk
Data
::
highest_ref
()
const
inline
HeapWord
*
ParallelCompactData
::
Region
Data
::
highest_ref
()
const
{
DEBUG_ONLY
(
return
_highest_ref
;)
NOT_DEBUG
(
return
NULL
;)
}
inline
void
ParallelCompactData
::
Chunk
Data
::
set_data_location
(
HeapWord
*
addr
)
inline
void
ParallelCompactData
::
Region
Data
::
set_data_location
(
HeapWord
*
addr
)
{
DEBUG_ONLY
(
_data_location
=
addr
;)
}
inline
void
ParallelCompactData
::
Chunk
Data
::
set_completed
()
inline
void
ParallelCompactData
::
Region
Data
::
set_completed
()
{
assert
(
claimed
(),
"must be claimed first"
);
_dc_and_los
=
dc_completed
|
(
chunk
_sz_t
)
live_obj_size
();
_dc_and_los
=
dc_completed
|
(
region
_sz_t
)
live_obj_size
();
}
// MT-unsafe claiming of a
chunk
. Should only be used during single threaded
// MT-unsafe claiming of a
region
. Should only be used during single threaded
// execution.
inline
bool
ParallelCompactData
::
Chunk
Data
::
claim_unsafe
()
inline
bool
ParallelCompactData
::
Region
Data
::
claim_unsafe
()
{
if
(
available
())
{
_dc_and_los
|=
dc_claimed
;
...
...
@@ -463,13 +463,13 @@ inline bool ParallelCompactData::ChunkData::claim_unsafe()
return
false
;
}
inline
void
ParallelCompactData
::
Chunk
Data
::
add_live_obj
(
size_t
words
)
inline
void
ParallelCompactData
::
Region
Data
::
add_live_obj
(
size_t
words
)
{
assert
(
words
<=
(
size_t
)
los_mask
-
live_obj_size
(),
"overflow"
);
Atomic
::
add
((
int
)
words
,
(
volatile
int
*
)
&
_dc_and_los
);
}
inline
void
ParallelCompactData
::
Chunk
Data
::
set_highest_ref
(
HeapWord
*
addr
)
inline
void
ParallelCompactData
::
Region
Data
::
set_highest_ref
(
HeapWord
*
addr
)
{
#ifdef ASSERT
HeapWord
*
tmp
=
_highest_ref
;
...
...
@@ -479,7 +479,7 @@ inline void ParallelCompactData::ChunkData::set_highest_ref(HeapWord* addr)
#endif // #ifdef ASSERT
}
inline
bool
ParallelCompactData
::
Chunk
Data
::
claim
()
inline
bool
ParallelCompactData
::
Region
Data
::
claim
()
{
const
int
los
=
(
int
)
live_obj_size
();
const
int
old
=
Atomic
::
cmpxchg
(
dc_claimed
|
los
,
...
...
@@ -487,19 +487,19 @@ inline bool ParallelCompactData::ChunkData::claim()
return
old
==
los
;
}
inline
ParallelCompactData
::
Chunk
Data
*
ParallelCompactData
::
chunk
(
size_t
chunk
_idx
)
const
inline
ParallelCompactData
::
Region
Data
*
ParallelCompactData
::
region
(
size_t
region
_idx
)
const
{
assert
(
chunk_idx
<=
chunk
_count
(),
"bad arg"
);
return
_
chunk_data
+
chunk
_idx
;
assert
(
region_idx
<=
region
_count
(),
"bad arg"
);
return
_
region_data
+
region
_idx
;
}
inline
size_t
ParallelCompactData
::
chunk
(
const
ChunkData
*
const
chunk
_ptr
)
const
ParallelCompactData
::
region
(
const
RegionData
*
const
region
_ptr
)
const
{
assert
(
chunk_ptr
>=
_chunk
_data
,
"bad arg"
);
assert
(
chunk_ptr
<=
_chunk_data
+
chunk
_count
(),
"bad arg"
);
return
pointer_delta
(
chunk_ptr
,
_chunk_data
,
sizeof
(
Chunk
Data
));
assert
(
region_ptr
>=
_region
_data
,
"bad arg"
);
assert
(
region_ptr
<=
_region_data
+
region
_count
(),
"bad arg"
);
return
pointer_delta
(
region_ptr
,
_region_data
,
sizeof
(
Region
Data
));
}
inline
ParallelCompactData
::
BlockData
*
...
...
@@ -509,68 +509,69 @@ ParallelCompactData::block(size_t n) const {
}
inline
size_t
ParallelCompactData
::
chunk
_offset
(
const
HeapWord
*
addr
)
const
ParallelCompactData
::
region
_offset
(
const
HeapWord
*
addr
)
const
{
assert
(
addr
>=
_region_start
,
"bad addr"
);
assert
(
addr
<=
_region_end
,
"bad addr"
);
return
(
size_t
(
addr
)
&
Chunk
AddrOffsetMask
)
>>
LogHeapWordSize
;
return
(
size_t
(
addr
)
&
Region
AddrOffsetMask
)
>>
LogHeapWordSize
;
}
inline
size_t
ParallelCompactData
::
addr_to_
chunk
_idx
(
const
HeapWord
*
addr
)
const
ParallelCompactData
::
addr_to_
region
_idx
(
const
HeapWord
*
addr
)
const
{
assert
(
addr
>=
_region_start
,
"bad addr"
);
assert
(
addr
<=
_region_end
,
"bad addr"
);
return
pointer_delta
(
addr
,
_region_start
)
>>
Log2
Chunk
Size
;
return
pointer_delta
(
addr
,
_region_start
)
>>
Log2
Region
Size
;
}
inline
ParallelCompactData
::
Chunk
Data
*
ParallelCompactData
::
addr_to_
chunk
_ptr
(
const
HeapWord
*
addr
)
const
inline
ParallelCompactData
::
Region
Data
*
ParallelCompactData
::
addr_to_
region
_ptr
(
const
HeapWord
*
addr
)
const
{
return
chunk
(
addr_to_chunk
_idx
(
addr
));
return
region
(
addr_to_region
_idx
(
addr
));
}
inline
HeapWord
*
ParallelCompactData
::
chunk_to_addr
(
size_t
chunk
)
const
ParallelCompactData
::
region_to_addr
(
size_t
region
)
const
{
assert
(
chunk
<=
_chunk_count
,
"chunk
out of range"
);
return
_region_start
+
(
chunk
<<
Log2Chunk
Size
);
assert
(
region
<=
_region_count
,
"region
out of range"
);
return
_region_start
+
(
region
<<
Log2Region
Size
);
}
inline
HeapWord
*
ParallelCompactData
::
chunk_to_addr
(
const
ChunkData
*
chunk
)
const
ParallelCompactData
::
region_to_addr
(
const
RegionData
*
region
)
const
{
return
chunk_to_addr
(
pointer_delta
(
chunk
,
_chunk_data
,
sizeof
(
ChunkData
)));
return
region_to_addr
(
pointer_delta
(
region
,
_region_data
,
sizeof
(
RegionData
)));
}
inline
HeapWord
*
ParallelCompactData
::
chunk_to_addr
(
size_t
chunk
,
size_t
offset
)
const
ParallelCompactData
::
region_to_addr
(
size_t
region
,
size_t
offset
)
const
{
assert
(
chunk
<=
_chunk_count
,
"chunk
out of range"
);
assert
(
offset
<
Chunk
Size
,
"offset too big"
);
// This may be too strict.
return
chunk_to_addr
(
chunk
)
+
offset
;
assert
(
region
<=
_region_count
,
"region
out of range"
);
assert
(
offset
<
Region
Size
,
"offset too big"
);
// This may be too strict.
return
region_to_addr
(
region
)
+
offset
;
}
inline
HeapWord
*
ParallelCompactData
::
chunk
_align_down
(
HeapWord
*
addr
)
const
ParallelCompactData
::
region
_align_down
(
HeapWord
*
addr
)
const
{
assert
(
addr
>=
_region_start
,
"bad addr"
);
assert
(
addr
<
_region_end
+
Chunk
Size
,
"bad addr"
);
return
(
HeapWord
*
)(
size_t
(
addr
)
&
Chunk
AddrMask
);
assert
(
addr
<
_region_end
+
Region
Size
,
"bad addr"
);
return
(
HeapWord
*
)(
size_t
(
addr
)
&
Region
AddrMask
);
}
inline
HeapWord
*
ParallelCompactData
::
chunk
_align_up
(
HeapWord
*
addr
)
const
ParallelCompactData
::
region
_align_up
(
HeapWord
*
addr
)
const
{
assert
(
addr
>=
_region_start
,
"bad addr"
);
assert
(
addr
<=
_region_end
,
"bad addr"
);
return
chunk_align_down
(
addr
+
Chunk
SizeOffsetMask
);
return
region_align_down
(
addr
+
Region
SizeOffsetMask
);
}
inline
bool
ParallelCompactData
::
is_
chunk
_aligned
(
HeapWord
*
addr
)
const
ParallelCompactData
::
is_
region
_aligned
(
HeapWord
*
addr
)
const
{
return
chunk
_offset
(
addr
)
==
0
;
return
region
_offset
(
addr
)
==
0
;
}
inline
size_t
...
...
@@ -692,40 +693,39 @@ class BitBlockUpdateClosure: public ParMarkBitMapClosure {
// ParallelCompactData::BlockData::blk_ofs_t _live_data_left;
size_t
_live_data_left
;
size_t
_cur_block
;
HeapWord
*
_
chunk
_start
;
HeapWord
*
_
chunk
_end
;
size_t
_
chunk
_index
;
HeapWord
*
_
region
_start
;
HeapWord
*
_
region
_end
;
size_t
_
region
_index
;
public:
BitBlockUpdateClosure
(
ParMarkBitMap
*
mbm
,
ParCompactionManager
*
cm
,
size_t
chunk
_index
);
size_t
region
_index
);
size_t
cur_block
()
{
return
_cur_block
;
}
size_t
chunk_index
()
{
return
_chunk
_index
;
}
size_t
region_index
()
{
return
_region
_index
;
}
size_t
live_data_left
()
{
return
_live_data_left
;
}
// Returns true the first bit in the current block (cur_block) is
// a start bit.
// Returns true if the current block is within the
chunk
for the closure;
bool
chunk
_contains_cur_block
();
// Returns true if the current block is within the
region
for the closure;
bool
region
_contains_cur_block
();
// Set the
chunk index and related chunk
values for
// a new
chunk
.
void
reset_
chunk
(
size_t
chunk
_index
);
// Set the
region index and related region
values for
// a new
region
.
void
reset_
region
(
size_t
region
_index
);
virtual
IterationStatus
do_addr
(
HeapWord
*
addr
,
size_t
words
);
};
// The UseParallelOldGC collector is a stop-the-world garbage
// collector that does parts of the collection using parallel threads.
// The collection includes the tenured generation and the young
// generation. The permanent generation is collected at the same
// time as the other two generations but the permanent generation
// is collect by a single GC thread. The permanent generation is
// collected serially because of the requirement that during the
// processing of a klass AAA, any objects reference by AAA must
// already have been processed. This requirement is enforced by
// a left (lower address) to right (higher address) sliding compaction.
// The UseParallelOldGC collector is a stop-the-world garbage collector that
// does parts of the collection using parallel threads. The collection includes
// the tenured generation and the young generation. The permanent generation is
// collected at the same time as the other two generations but the permanent
// generation is collect by a single GC thread. The permanent generation is
// collected serially because of the requirement that during the processing of a
// klass AAA, any objects reference by AAA must already have been processed.
// This requirement is enforced by a left (lower address) to right (higher
// address) sliding compaction.
//
// There are four phases of the collection.
//
...
...
@@ -740,80 +740,75 @@ class BitBlockUpdateClosure: public ParMarkBitMapClosure {
// - move the objects to their destination
// - update some references and reinitialize some variables
//
// These three phases are invoked in PSParallelCompact::invoke_no_policy().
//
The marking phase is implemented in PSParallelCompact::marking_phase()
//
and does a complete marking of the heap.
//
The summary phase is implemented in PSParallelCompact::summary_phase().
//
The move and update phase is implemented
in PSParallelCompact::compact().
// These three phases are invoked in PSParallelCompact::invoke_no_policy().
The
//
marking phase is implemented in PSParallelCompact::marking_phase() and does a
//
complete marking of the heap. The summary phase is implemented in
//
PSParallelCompact::summary_phase(). The move and update phase is implemented
// in PSParallelCompact::compact().
//
// A space that is being collected is divided into chunks and with
// each chunk is associated an object of type ParallelCompactData.
// Each chunk is of a fixed size and typically will contain more than
// 1 object and may have parts of objects at the front and back of the
// chunk.
// A space that is being collected is divided into regions and with each region
// is associated an object of type ParallelCompactData. Each region is of a
// fixed size and typically will contain more than 1 object and may have parts
// of objects at the front and back of the region.
//
//
chunk
-----+---------------------+----------
//
region
-----+---------------------+----------
// objects covered [ AAA )[ BBB )[ CCC )[ DDD )
//
// The marking phase does a complete marking of all live objects in the
// heap. The marking also compiles the size of the data for
// all live objects covered by the chunk. This size includes the
// part of any live object spanning onto the chunk (part of AAA
// if it is live) from the front, all live objects contained in the chunk
// (BBB and/or CCC if they are live), and the part of any live objects
// covered by the chunk that extends off the chunk (part of DDD if it is
// live). The marking phase uses multiple GC threads and marking is
// done in a bit array of type ParMarkBitMap. The marking of the
// bit map is done atomically as is the accumulation of the size of the
// live objects covered by a chunk.
// The marking phase does a complete marking of all live objects in the heap.
// The marking also compiles the size of the data for all live objects covered
// by the region. This size includes the part of any live object spanning onto
// the region (part of AAA if it is live) from the front, all live objects
// contained in the region (BBB and/or CCC if they are live), and the part of
// any live objects covered by the region that extends off the region (part of
// DDD if it is live). The marking phase uses multiple GC threads and marking
// is done in a bit array of type ParMarkBitMap. The marking of the bit map is
// done atomically as is the accumulation of the size of the live objects
// covered by a region.
//
// The summary phase calculates the total live data to the left of
//
each chunk XXX. Based on that total and the bottom of the space,
//
it can calculate the starting location of the live data in XXX.
//
The summary phase calculates for each chunk
XXX quantites such as
// The summary phase calculates the total live data to the left of
each region
//
XXX. Based on that total and the bottom of the space, it can calculate the
//
starting location of the live data in XXX. The summary phase calculates for
//
each region
XXX quantites such as
//
// - the amount of live data at the beginning of a
chunk
from an object
//
entering the chunk
.
// - the location of the first live data on the
chunk
// - a count of the number of
chunk
s receiving live data from XXX.
// - the amount of live data at the beginning of a
region
from an object
//
entering the region
.
// - the location of the first live data on the
region
// - a count of the number of
region
s receiving live data from XXX.
//
// See ParallelCompactData for precise details. The summary phase also
// calculates the dense prefix for the compaction. The dense prefix
//
is a portion at the beginning of the space that is not moved. T
he
//
objects in the dense prefix do need to have their object references
//
updated. See method
summarize_dense_prefix().
// calculates the dense prefix for the compaction. The dense prefix
is a
//
portion at the beginning of the space that is not moved. The objects in t
he
//
dense prefix do need to have their object references updated. See method
// summarize_dense_prefix().
//
// The summary phase is done using 1 GC thread.
//
// The compaction phase moves objects to their new location and updates
//
all
references in the object.
// The compaction phase moves objects to their new location and updates
all
// references in the object.
//
// A current exception is that objects that cross a chunk boundary
// are moved but do not have their references updated. References are
// not updated because it cannot easily be determined if the klass
// pointer KKK for the object AAA has been updated. KKK likely resides
// in a chunk to the left of the chunk containing AAA. These AAA's
// have there references updated at the end in a clean up phase.
// See the method PSParallelCompact::update_deferred_objects(). An
// alternate strategy is being investigated for this deferral of updating.
//
// Compaction is done on a chunk basis. A chunk that is ready to be
// filled is put on a ready list and GC threads take chunk off the list
// and fill them. A chunk is ready to be filled if it
// empty of live objects. Such a chunk may have been initially
// empty (only contained
// dead objects) or may have had all its live objects copied out already.
// A chunk that compacts into itself is also ready for filling. The
// ready list is initially filled with empty chunks and chunks compacting
// into themselves. There is always at least 1 chunk that can be put on
// the ready list. The chunks are atomically added and removed from
// the ready list.
// A current exception is that objects that cross a region boundary are moved
// but do not have their references updated. References are not updated because
// it cannot easily be determined if the klass pointer KKK for the object AAA
// has been updated. KKK likely resides in a region to the left of the region
// containing AAA. These AAA's have there references updated at the end in a
// clean up phase. See the method PSParallelCompact::update_deferred_objects().
// An alternate strategy is being investigated for this deferral of updating.
//
// Compaction is done on a region basis. A region that is ready to be filled is
// put on a ready list and GC threads take region off the list and fill them. A
// region is ready to be filled if it empty of live objects. Such a region may
// have been initially empty (only contained dead objects) or may have had all
// its live objects copied out already. A region that compacts into itself is
// also ready for filling. The ready list is initially filled with empty
// regions and regions compacting into themselves. There is always at least 1
// region that can be put on the ready list. The regions are atomically added
// and removed from the ready list.
class
PSParallelCompact
:
AllStatic
{
public:
// Convenient access to type names.
typedef
ParMarkBitMap
::
idx_t
idx_t
;
typedef
ParallelCompactData
::
ChunkData
Chunk
Data
;
typedef
ParallelCompactData
::
RegionData
Region
Data
;
typedef
ParallelCompactData
::
BlockData
BlockData
;
typedef
enum
{
...
...
@@ -977,26 +972,26 @@ class PSParallelCompact : AllStatic {
// not reclaimed).
static
double
dead_wood_limiter
(
double
density
,
size_t
min_percent
);
// Find the first (left-most)
chunk
in the range [beg, end) that has at least
// Find the first (left-most)
region
in the range [beg, end) that has at least
// dead_words of dead space to the left. The argument beg must be the first
//
chunk
in the space that is not completely live.
static
ChunkData
*
dead_wood_limit_chunk
(
const
Chunk
Data
*
beg
,
const
Chunk
Data
*
end
,
size_t
dead_words
);
//
region
in the space that is not completely live.
static
RegionData
*
dead_wood_limit_region
(
const
Region
Data
*
beg
,
const
Region
Data
*
end
,
size_t
dead_words
);
// Return a pointer to the first
chunk
in the range [beg, end) that is not
// Return a pointer to the first
region
in the range [beg, end) that is not
// completely full.
static
ChunkData
*
first_dead_space_chunk
(
const
Chunk
Data
*
beg
,
const
Chunk
Data
*
end
);
static
RegionData
*
first_dead_space_region
(
const
Region
Data
*
beg
,
const
Region
Data
*
end
);
// Return a value indicating the benefit or 'yield' if the compacted region
// were to start (or equivalently if the dense prefix were to end) at the
// candidate
chunk
. Higher values are better.
// candidate
region
. Higher values are better.
//
// The value is based on the amount of space reclaimed vs. the costs of (a)
// updating references in the dense prefix plus (b) copying objects and
// updating references in the compacted region.
static
inline
double
reclaimed_ratio
(
const
Chunk
Data
*
const
candidate
,
static
inline
double
reclaimed_ratio
(
const
Region
Data
*
const
candidate
,
HeapWord
*
const
bottom
,
HeapWord
*
const
top
,
HeapWord
*
const
new_top
);
...
...
@@ -1005,9 +1000,9 @@ class PSParallelCompact : AllStatic {
static
HeapWord
*
compute_dense_prefix
(
const
SpaceId
id
,
bool
maximum_compaction
);
// Return true if dead space crosses onto the specified
Chunk; bit must be th
e
//
bit index corresponding to the first word of the Chunk
.
static
inline
bool
dead_space_crosses_boundary
(
const
ChunkData
*
chunk
,
// Return true if dead space crosses onto the specified
Region; bit must b
e
//
the bit index corresponding to the first word of the Region
.
static
inline
bool
dead_space_crosses_boundary
(
const
RegionData
*
region
,
idx_t
bit
);
// Summary phase utility routine to fill dead space (if any) at the dense
...
...
@@ -1038,16 +1033,16 @@ class PSParallelCompact : AllStatic {
static
void
compact_perm
(
ParCompactionManager
*
cm
);
static
void
compact
();
// Add available
chunk
s to the stack and draining tasks to the task queue.
static
void
enqueue_
chunk
_draining_tasks
(
GCTaskQueue
*
q
,
uint
parallel_gc_threads
);
// Add available
region
s to the stack and draining tasks to the task queue.
static
void
enqueue_
region
_draining_tasks
(
GCTaskQueue
*
q
,
uint
parallel_gc_threads
);
// Add dense prefix update tasks to the task queue.
static
void
enqueue_dense_prefix_tasks
(
GCTaskQueue
*
q
,
uint
parallel_gc_threads
);
// Add
chunk
stealing tasks to the task queue.
static
void
enqueue_
chunk
_stealing_tasks
(
// Add
region
stealing tasks to the task queue.
static
void
enqueue_
region
_stealing_tasks
(
GCTaskQueue
*
q
,
ParallelTaskTerminator
*
terminator_ptr
,
uint
parallel_gc_threads
);
...
...
@@ -1154,56 +1149,56 @@ class PSParallelCompact : AllStatic {
// Move and update the live objects in the specified space.
static
void
move_and_update
(
ParCompactionManager
*
cm
,
SpaceId
space_id
);
// Process the end of the given
chunk
range in the dense prefix.
// Process the end of the given
region
range in the dense prefix.
// This includes saving any object not updated.
static
void
dense_prefix_
chunk
s_epilogue
(
ParCompactionManager
*
cm
,
size_t
chunk
_start_index
,
size_t
chunk
_end_index
,
idx_t
exiting_object_offset
,
idx_t
chunk
_offset_start
,
idx_t
chunk
_offset_end
);
// Update a
chunk
in the dense prefix. For each live object
// in the
chunk
, update it's interior references. For each
static
void
dense_prefix_
region
s_epilogue
(
ParCompactionManager
*
cm
,
size_t
region
_start_index
,
size_t
region
_end_index
,
idx_t
exiting_object_offset
,
idx_t
region
_offset_start
,
idx_t
region
_offset_end
);
// Update a
region
in the dense prefix. For each live object
// in the
region
, update it's interior references. For each
// dead object, fill it with deadwood. Dead space at the end
// of a
chunk
range will be filled to the start of the next
// live object regardless of the
chunk
_index_end. None of the
// of a
region
range will be filled to the start of the next
// live object regardless of the
region
_index_end. None of the
// objects in the dense prefix move and dead space is dead
// (holds only dead objects that don't need any processing), so
// dead space can be filled in any order.
static
void
update_and_deadwood_in_dense_prefix
(
ParCompactionManager
*
cm
,
SpaceId
space_id
,
size_t
chunk
_index_start
,
size_t
chunk
_index_end
);
size_t
region
_index_start
,
size_t
region
_index_end
);
// Return the address of the count + 1st live word in the range [beg, end).
static
HeapWord
*
skip_live_words
(
HeapWord
*
beg
,
HeapWord
*
end
,
size_t
count
);
// Return the address of the word to be copied to dest_addr, which must be
// aligned to a
chunk
boundary.
// aligned to a
region
boundary.
static
HeapWord
*
first_src_addr
(
HeapWord
*
const
dest_addr
,
size_t
src_
chunk
_idx
);
size_t
src_
region
_idx
);
// Determine the next source
chunk
, set closure.source() to the start of the
// new
chunk return the chunk
index. Parameter end_addr is the address one
// Determine the next source
region
, set closure.source() to the start of the
// new
region return the region
index. Parameter end_addr is the address one
// beyond the end of source range just processed. If necessary, switch to a
// new source space and set src_space_id (in-out parameter) and src_space_top
// (out parameter) accordingly.
static
size_t
next_src_
chunk
(
MoveAndUpdateClosure
&
closure
,
SpaceId
&
src_space_id
,
HeapWord
*&
src_space_top
,
HeapWord
*
end_addr
);
static
size_t
next_src_
region
(
MoveAndUpdateClosure
&
closure
,
SpaceId
&
src_space_id
,
HeapWord
*&
src_space_top
,
HeapWord
*
end_addr
);
// Decrement the destination count for each non-empty source
chunk
in the
// range [beg_
chunk, chunk(chunk
_align_up(end_addr))).
// Decrement the destination count for each non-empty source
region
in the
// range [beg_
region, region(region
_align_up(end_addr))).
static
void
decrement_destination_counts
(
ParCompactionManager
*
cm
,
size_t
beg_
chunk
,
size_t
beg_
region
,
HeapWord
*
end_addr
);
// Fill a
chunk, copying objects from one or more source chunk
s.
static
void
fill_
chunk
(
ParCompactionManager
*
cm
,
size_t
chunk
_idx
);
static
void
fill_and_update_
chunk
(
ParCompactionManager
*
cm
,
size_t
chunk
)
{
fill_
chunk
(
cm
,
chunk
);
// Fill a
region, copying objects from one or more source region
s.
static
void
fill_
region
(
ParCompactionManager
*
cm
,
size_t
region
_idx
);
static
void
fill_and_update_
region
(
ParCompactionManager
*
cm
,
size_t
region
)
{
fill_
region
(
cm
,
region
);
}
// Update the deferred objects in the space.
...
...
@@ -1259,7 +1254,7 @@ class PSParallelCompact : AllStatic {
#ifndef PRODUCT
// Debugging support.
static
const
char
*
space_names
[
last_space_id
];
static
void
print_
chunk
_ranges
();
static
void
print_
region
_ranges
();
static
void
print_dense_prefix_stats
(
const
char
*
const
algorithm
,
const
SpaceId
id
,
const
bool
maximum_compaction
,
...
...
@@ -1267,7 +1262,7 @@ class PSParallelCompact : AllStatic {
#endif // #ifndef PRODUCT
#ifdef ASSERT
// Verify that all the
chunk
s have been emptied.
// Verify that all the
region
s have been emptied.
static
void
verify_complete
(
SpaceId
space_id
);
#endif // #ifdef ASSERT
};
...
...
@@ -1376,17 +1371,17 @@ inline double PSParallelCompact::normal_distribution(double density) {
}
inline
bool
PSParallelCompact
::
dead_space_crosses_boundary
(
const
ChunkData
*
chunk
,
PSParallelCompact
::
dead_space_crosses_boundary
(
const
RegionData
*
region
,
idx_t
bit
)
{
assert
(
bit
>
0
,
"cannot call this for the first bit/
chunk
"
);
assert
(
_summary_data
.
chunk_to_addr
(
chunk
)
==
_mark_bitmap
.
bit_to_addr
(
bit
),
assert
(
bit
>
0
,
"cannot call this for the first bit/
region
"
);
assert
(
_summary_data
.
region_to_addr
(
region
)
==
_mark_bitmap
.
bit_to_addr
(
bit
),
"sanity check"
);
// Dead space crosses the boundary if (1) a partial object does not extend
// onto the
chunk, (2) an object does not start at the beginning of the chunk,
//
and (3) an object does not end at the end of the prior chunk
.
return
chunk
->
partial_obj_size
()
==
0
&&
// onto the
region, (2) an object does not start at the beginning of the
//
region, and (3) an object does not end at the end of the prior region
.
return
region
->
partial_obj_size
()
==
0
&&
!
_mark_bitmap
.
is_obj_beg
(
bit
)
&&
!
_mark_bitmap
.
is_obj_end
(
bit
-
1
);
}
...
...
src/share/vm/runtime/globals.hpp
浏览文件 @
bee8b017
...
...
@@ -1157,9 +1157,9 @@ class CommandLineFlags {
"In the Parallel Old garbage collector use parallel dense" \
" prefix update") \
\
develop(bool, UseParallelOldGC
ChunkPointerCalc, true,
\
"In the Parallel Old garbage collector use
chucks to calculate"
\
"
new object locations")
\
develop(bool, UseParallelOldGC
RegionPointerCalc, true,
\
"In the Parallel Old garbage collector use
regions to calculate"
\
"
new object locations")
\
\
product(uintx, HeapMaximumCompactionInterval, 20, \
"How often should we maximally compact the heap (not allowing " \
...
...
@@ -1195,8 +1195,8 @@ class CommandLineFlags {
develop(bool, ParallelOldMTUnsafeUpdateLiveData, false, \
"Use the Parallel Old MT unsafe in update of live size") \
\
develop(bool, Trace
ChunkTasksQueuing, false,
\
"Trace the queuing of the
chunk tasks")
\
develop(bool, Trace
RegionTasksQueuing, false,
\
"Trace the queuing of the
region tasks")
\
\
product(uintx, ParallelMarkingThreads, 0, \
"Number of marking threads concurrent gc will use") \
...
...
src/share/vm/utilities/taskqueue.cpp
浏览文件 @
bee8b017
...
...
@@ -109,72 +109,72 @@ void ParallelTaskTerminator::reset_for_reuse() {
}
}
bool
Chunk
TaskQueueWithOverflow
::
is_empty
()
{
return
(
_
chunk
_queue
.
size
()
==
0
)
&&
bool
Region
TaskQueueWithOverflow
::
is_empty
()
{
return
(
_
region
_queue
.
size
()
==
0
)
&&
(
_overflow_stack
->
length
()
==
0
);
}
bool
Chunk
TaskQueueWithOverflow
::
stealable_is_empty
()
{
return
_
chunk
_queue
.
size
()
==
0
;
bool
Region
TaskQueueWithOverflow
::
stealable_is_empty
()
{
return
_
region
_queue
.
size
()
==
0
;
}
bool
Chunk
TaskQueueWithOverflow
::
overflow_is_empty
()
{
bool
Region
TaskQueueWithOverflow
::
overflow_is_empty
()
{
return
_overflow_stack
->
length
()
==
0
;
}
void
Chunk
TaskQueueWithOverflow
::
initialize
()
{
_
chunk
_queue
.
initialize
();
void
Region
TaskQueueWithOverflow
::
initialize
()
{
_
region
_queue
.
initialize
();
assert
(
_overflow_stack
==
0
,
"Creating memory leak"
);
_overflow_stack
=
new
(
ResourceObj
::
C_HEAP
)
GrowableArray
<
Chunk
Task
>
(
10
,
true
);
new
(
ResourceObj
::
C_HEAP
)
GrowableArray
<
Region
Task
>
(
10
,
true
);
}
void
ChunkTaskQueueWithOverflow
::
save
(
Chunk
Task
t
)
{
if
(
Trace
Chunk
TasksQueuing
&&
Verbose
)
{
void
RegionTaskQueueWithOverflow
::
save
(
Region
Task
t
)
{
if
(
Trace
Region
TasksQueuing
&&
Verbose
)
{
gclog_or_tty
->
print_cr
(
"CTQ: save "
PTR_FORMAT
,
t
);
}
if
(
!
_
chunk
_queue
.
push
(
t
))
{
if
(
!
_
region
_queue
.
push
(
t
))
{
_overflow_stack
->
push
(
t
);
}
}
// Note that using this method will retrieve all
chunk
s
// Note that using this method will retrieve all
region
s
// that have been saved but that it will always check
// the overflow stack. It may be more efficient to
// check the stealable queue and the overflow stack
// separately.
bool
ChunkTaskQueueWithOverflow
::
retrieve
(
ChunkTask
&
chunk
_task
)
{
bool
result
=
retrieve_from_overflow
(
chunk
_task
);
bool
RegionTaskQueueWithOverflow
::
retrieve
(
RegionTask
&
region
_task
)
{
bool
result
=
retrieve_from_overflow
(
region
_task
);
if
(
!
result
)
{
result
=
retrieve_from_stealable_queue
(
chunk
_task
);
result
=
retrieve_from_stealable_queue
(
region
_task
);
}
if
(
Trace
Chunk
TasksQueuing
&&
Verbose
&&
result
)
{
if
(
Trace
Region
TasksQueuing
&&
Verbose
&&
result
)
{
gclog_or_tty
->
print_cr
(
" CTQ: retrieve "
PTR_FORMAT
,
result
);
}
return
result
;
}
bool
Chunk
TaskQueueWithOverflow
::
retrieve_from_stealable_queue
(
ChunkTask
&
chunk
_task
)
{
bool
result
=
_
chunk_queue
.
pop_local
(
chunk
_task
);
if
(
Trace
Chunk
TasksQueuing
&&
Verbose
)
{
gclog_or_tty
->
print_cr
(
"CTQ: retrieve_stealable "
PTR_FORMAT
,
chunk
_task
);
bool
Region
TaskQueueWithOverflow
::
retrieve_from_stealable_queue
(
RegionTask
&
region
_task
)
{
bool
result
=
_
region_queue
.
pop_local
(
region
_task
);
if
(
Trace
Region
TasksQueuing
&&
Verbose
)
{
gclog_or_tty
->
print_cr
(
"CTQ: retrieve_stealable "
PTR_FORMAT
,
region
_task
);
}
return
result
;
}
bool
ChunkTaskQueueWithOverflow
::
retrieve_from_overflow
(
ChunkTask
&
chunk
_task
)
{
bool
RegionTaskQueueWithOverflow
::
retrieve_from_overflow
(
RegionTask
&
region
_task
)
{
bool
result
;
if
(
!
_overflow_stack
->
is_empty
())
{
chunk
_task
=
_overflow_stack
->
pop
();
region
_task
=
_overflow_stack
->
pop
();
result
=
true
;
}
else
{
chunk_task
=
(
Chunk
Task
)
NULL
;
region_task
=
(
Region
Task
)
NULL
;
result
=
false
;
}
if
(
Trace
Chunk
TasksQueuing
&&
Verbose
)
{
gclog_or_tty
->
print_cr
(
"CTQ: retrieve_stealable "
PTR_FORMAT
,
chunk
_task
);
if
(
Trace
Region
TasksQueuing
&&
Verbose
)
{
gclog_or_tty
->
print_cr
(
"CTQ: retrieve_stealable "
PTR_FORMAT
,
region
_task
);
}
return
result
;
}
src/share/vm/utilities/taskqueue.hpp
浏览文件 @
bee8b017
...
...
@@ -557,32 +557,32 @@ class StarTask {
typedef
GenericTaskQueue
<
StarTask
>
OopStarTaskQueue
;
typedef
GenericTaskQueueSet
<
StarTask
>
OopStarTaskQueueSet
;
typedef
size_t
ChunkTask
;
// index for chunk
typedef
GenericTaskQueue
<
ChunkTask
>
Chunk
TaskQueue
;
typedef
GenericTaskQueueSet
<
ChunkTask
>
Chunk
TaskQueueSet
;
typedef
size_t
RegionTask
;
// index for region
typedef
GenericTaskQueue
<
RegionTask
>
Region
TaskQueue
;
typedef
GenericTaskQueueSet
<
RegionTask
>
Region
TaskQueueSet
;
class
Chunk
TaskQueueWithOverflow
:
public
CHeapObj
{
class
Region
TaskQueueWithOverflow
:
public
CHeapObj
{
protected:
ChunkTaskQueue
_chunk
_queue
;
GrowableArray
<
Chunk
Task
>*
_overflow_stack
;
RegionTaskQueue
_region
_queue
;
GrowableArray
<
Region
Task
>*
_overflow_stack
;
public:
Chunk
TaskQueueWithOverflow
()
:
_overflow_stack
(
NULL
)
{}
Region
TaskQueueWithOverflow
()
:
_overflow_stack
(
NULL
)
{}
// Initialize both stealable queue and overflow
void
initialize
();
// Save first to stealable queue and then to overflow
void
save
(
Chunk
Task
t
);
void
save
(
Region
Task
t
);
// Retrieve first from overflow and then from stealable queue
bool
retrieve
(
ChunkTask
&
chunk
_index
);
bool
retrieve
(
RegionTask
&
region
_index
);
// Retrieve from stealable queue
bool
retrieve_from_stealable_queue
(
ChunkTask
&
chunk
_index
);
bool
retrieve_from_stealable_queue
(
RegionTask
&
region
_index
);
// Retrieve from overflow
bool
retrieve_from_overflow
(
ChunkTask
&
chunk
_index
);
bool
retrieve_from_overflow
(
RegionTask
&
region
_index
);
bool
is_empty
();
bool
stealable_is_empty
();
bool
overflow_is_empty
();
juint
stealable_size
()
{
return
_
chunk
_queue
.
size
();
}
ChunkTaskQueue
*
task_queue
()
{
return
&
_chunk
_queue
;
}
juint
stealable_size
()
{
return
_
region
_queue
.
size
();
}
RegionTaskQueue
*
task_queue
()
{
return
&
_region
_queue
;
}
};
#define USE_
Chunk
TaskQueueWithOverflow
#define USE_
Region
TaskQueueWithOverflow
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录