mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-22 03:54:33 +02:00
4957990: Perm heap bloat in JVM
Treat ProfileData in MDO's as a source of weak, not strong, roots. Fixes the bug for stop-world collection -- the case of concurrent collection will be fixed separately. Reviewed-by: jcoomes, jmasa, kvn, never
This commit is contained in:
parent
2491751525
commit
c6763b5bad
27 changed files with 385 additions and 65 deletions
|
@ -58,9 +58,8 @@ void MarkFromRootsTask::do_it(GCTaskManager* manager, uint which) {
|
|||
PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty));
|
||||
ParCompactionManager* cm =
|
||||
ParCompactionManager::gc_thread_compaction_manager(which);
|
||||
// cm->allocate_stacks();
|
||||
assert(cm->stacks_have_been_allocated(),
|
||||
"Stack space has not been allocated");
|
||||
"Stack space has not been allocated");
|
||||
PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
|
||||
|
||||
switch (_root_type) {
|
||||
|
@ -129,9 +128,8 @@ void RefProcTaskProxy::do_it(GCTaskManager* manager, uint which)
|
|||
PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty));
|
||||
ParCompactionManager* cm =
|
||||
ParCompactionManager::gc_thread_compaction_manager(which);
|
||||
// cm->allocate_stacks();
|
||||
assert(cm->stacks_have_been_allocated(),
|
||||
"Stack space has not been allocated");
|
||||
"Stack space has not been allocated");
|
||||
PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
|
||||
PSParallelCompact::FollowStackClosure follow_stack_closure(cm);
|
||||
_rp_task.work(_work_id, *PSParallelCompact::is_alive_closure(),
|
||||
|
|
|
@ -61,12 +61,16 @@ ParCompactionManager::ParCompactionManager() :
|
|||
int size =
|
||||
(SystemDictionary::number_of_classes() * 2) * 2 / ParallelGCThreads;
|
||||
_revisit_klass_stack = new (ResourceObj::C_HEAP) GrowableArray<Klass*>(size, true);
|
||||
// From some experiments (#klass/k)^2 for k = 10 seems a better fit, but this will
|
||||
// have to do for now until we are able to investigate a more optimal setting.
|
||||
_revisit_mdo_stack = new (ResourceObj::C_HEAP) GrowableArray<DataLayout*>(size*2, true);
|
||||
|
||||
}
|
||||
|
||||
ParCompactionManager::~ParCompactionManager() {
|
||||
delete _overflow_stack;
|
||||
delete _revisit_klass_stack;
|
||||
delete _revisit_mdo_stack;
|
||||
// _manager_array and _stack_array are statics
|
||||
// shared with all instances of ParCompactionManager
|
||||
// should not be deallocated.
|
||||
|
@ -195,6 +199,7 @@ ParCompactionManager::gc_thread_compaction_manager(int index) {
|
|||
void ParCompactionManager::reset() {
|
||||
for(uint i=0; i<ParallelGCThreads+1; i++) {
|
||||
manager_array(i)->revisit_klass_stack()->clear();
|
||||
manager_array(i)->revisit_mdo_stack()->clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -296,6 +301,7 @@ void ParCompactionManager::drain_region_stacks() {
|
|||
|
||||
#ifdef ASSERT
|
||||
bool ParCompactionManager::stacks_have_been_allocated() {
|
||||
return (revisit_klass_stack()->data_addr() != NULL);
|
||||
return (revisit_klass_stack()->data_addr() != NULL &&
|
||||
revisit_mdo_stack()->data_addr() != NULL);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -93,6 +93,7 @@ class ParCompactionManager : public CHeapObj {
|
|||
|
||||
#if 1 // does this happen enough to need a per thread stack?
|
||||
GrowableArray<Klass*>* _revisit_klass_stack;
|
||||
GrowableArray<DataLayout*>* _revisit_mdo_stack;
|
||||
#endif
|
||||
static ParMarkBitMap* _mark_bitmap;
|
||||
|
||||
|
@ -154,6 +155,7 @@ class ParCompactionManager : public CHeapObj {
|
|||
#if 1
|
||||
// Probably stays as a growable array
|
||||
GrowableArray<Klass*>* revisit_klass_stack() { return _revisit_klass_stack; }
|
||||
GrowableArray<DataLayout*>* revisit_mdo_stack() { return _revisit_mdo_stack; }
|
||||
#endif
|
||||
|
||||
// Save oop for later processing. Must not fail.
|
||||
|
|
|
@ -482,6 +482,9 @@ void PSMarkSweep::allocate_stacks() {
|
|||
|
||||
int size = SystemDictionary::number_of_classes() * 2;
|
||||
_revisit_klass_stack = new (ResourceObj::C_HEAP) GrowableArray<Klass*>(size, true);
|
||||
// (#klass/k)^2, for k ~ 10 appears a better setting, but this will have to do for
|
||||
// now until we investigate a more optimal setting.
|
||||
_revisit_mdo_stack = new (ResourceObj::C_HEAP) GrowableArray<DataLayout*>(size*2, true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -495,6 +498,7 @@ void PSMarkSweep::deallocate_stacks() {
|
|||
|
||||
delete _marking_stack;
|
||||
delete _revisit_klass_stack;
|
||||
delete _revisit_mdo_stack;
|
||||
}
|
||||
|
||||
void PSMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
|
||||
|
@ -540,6 +544,10 @@ void PSMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
|
|||
follow_weak_klass_links();
|
||||
assert(_marking_stack->is_empty(), "just drained");
|
||||
|
||||
// Visit memoized mdo's and clear unmarked weak refs
|
||||
follow_mdo_weak_refs();
|
||||
assert(_marking_stack->is_empty(), "just drained");
|
||||
|
||||
// Visit symbol and interned string tables and delete unmarked oops
|
||||
SymbolTable::unlink(is_alive_closure());
|
||||
StringTable::unlink(is_alive_closure());
|
||||
|
|
|
@ -2378,7 +2378,10 @@ void PSParallelCompact::marking_phase(ParCompactionManager* cm,
|
|||
|
||||
// Update subklass/sibling/implementor links of live klasses
|
||||
// revisit_klass_stack is used in follow_weak_klass_links().
|
||||
follow_weak_klass_links(cm);
|
||||
follow_weak_klass_links();
|
||||
|
||||
// Revisit memoized MDO's and clear any unmarked weak refs
|
||||
follow_mdo_weak_refs();
|
||||
|
||||
// Visit symbol and interned string tables and delete unmarked oops
|
||||
SymbolTable::unlink(is_alive_closure());
|
||||
|
@ -2721,17 +2724,25 @@ void PSParallelCompact::follow_stack(ParCompactionManager* cm) {
|
|||
}
|
||||
|
||||
void
|
||||
PSParallelCompact::follow_weak_klass_links(ParCompactionManager* serial_cm) {
|
||||
PSParallelCompact::follow_weak_klass_links() {
|
||||
// All klasses on the revisit stack are marked at this point.
|
||||
// Update and follow all subklass, sibling and implementor links.
|
||||
for (uint i = 0; i < ParallelGCThreads+1; i++) {
|
||||
if (PrintRevisitStats) {
|
||||
gclog_or_tty->print_cr("#classes in system dictionary = %d", SystemDictionary::number_of_classes());
|
||||
}
|
||||
for (uint i = 0; i < ParallelGCThreads + 1; i++) {
|
||||
ParCompactionManager* cm = ParCompactionManager::manager_array(i);
|
||||
KeepAliveClosure keep_alive_closure(cm);
|
||||
for (int i = 0; i < cm->revisit_klass_stack()->length(); i++) {
|
||||
cm->revisit_klass_stack()->at(i)->follow_weak_klass_links(
|
||||
int length = cm->revisit_klass_stack()->length();
|
||||
if (PrintRevisitStats) {
|
||||
gclog_or_tty->print_cr("Revisit klass stack[%d] length = %d", i, length);
|
||||
}
|
||||
for (int j = 0; j < length; j++) {
|
||||
cm->revisit_klass_stack()->at(j)->follow_weak_klass_links(
|
||||
is_alive_closure(),
|
||||
&keep_alive_closure);
|
||||
}
|
||||
// revisit_klass_stack is cleared in reset()
|
||||
follow_stack(cm);
|
||||
}
|
||||
}
|
||||
|
@ -2741,6 +2752,35 @@ PSParallelCompact::revisit_weak_klass_link(ParCompactionManager* cm, Klass* k) {
|
|||
cm->revisit_klass_stack()->push(k);
|
||||
}
|
||||
|
||||
#if ( defined(COMPILER1) || defined(COMPILER2) )
|
||||
void PSParallelCompact::revisit_mdo(ParCompactionManager* cm, DataLayout* p) {
|
||||
cm->revisit_mdo_stack()->push(p);
|
||||
}
|
||||
|
||||
void PSParallelCompact::follow_mdo_weak_refs() {
|
||||
// All strongly reachable oops have been marked at this point;
|
||||
// we can visit and clear any weak references from MDO's which
|
||||
// we memoized during the strong marking phase.
|
||||
if (PrintRevisitStats) {
|
||||
gclog_or_tty->print_cr("#classes in system dictionary = %d", SystemDictionary::number_of_classes());
|
||||
}
|
||||
for (uint i = 0; i < ParallelGCThreads + 1; i++) {
|
||||
ParCompactionManager* cm = ParCompactionManager::manager_array(i);
|
||||
GrowableArray<DataLayout*>* rms = cm->revisit_mdo_stack();
|
||||
int length = rms->length();
|
||||
if (PrintRevisitStats) {
|
||||
gclog_or_tty->print_cr("Revisit MDO stack[%d] length = %d", i, length);
|
||||
}
|
||||
for (int j = 0; j < length; j++) {
|
||||
rms->at(j)->follow_weak_refs(is_alive_closure());
|
||||
}
|
||||
// revisit_mdo_stack is cleared in reset()
|
||||
follow_stack(cm);
|
||||
}
|
||||
}
|
||||
#endif // ( COMPILER1 || COMPILER2 )
|
||||
|
||||
|
||||
#ifdef VALIDATE_MARK_SWEEP
|
||||
|
||||
void PSParallelCompact::track_adjusted_pointer(void* p, bool isroot) {
|
||||
|
|
|
@ -901,7 +901,8 @@ class PSParallelCompact : AllStatic {
|
|||
static void marking_phase(ParCompactionManager* cm,
|
||||
bool maximum_heap_compaction);
|
||||
static void follow_stack(ParCompactionManager* cm);
|
||||
static void follow_weak_klass_links(ParCompactionManager* cm);
|
||||
static void follow_weak_klass_links();
|
||||
static void follow_mdo_weak_refs();
|
||||
|
||||
template <class T> static inline void adjust_pointer(T* p, bool is_root);
|
||||
static void adjust_root_pointer(oop* p) { adjust_pointer(p, true); }
|
||||
|
@ -1221,6 +1222,9 @@ class PSParallelCompact : AllStatic {
|
|||
// Update subklass/sibling/implementor links at end of marking.
|
||||
static void revisit_weak_klass_link(ParCompactionManager* cm, Klass* k);
|
||||
|
||||
// Clear unmarked oops in MDOs at the end of marking.
|
||||
static void revisit_mdo(ParCompactionManager* cm, DataLayout* p);
|
||||
|
||||
#ifndef PRODUCT
|
||||
// Debugging support.
|
||||
static const char* space_names[last_space_id];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue