mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-15 16:44:36 +02:00
6423256: GC stacks should use a better data structure
6942771: SEGV in ParScanThreadState::take_from_overflow_stack Reviewed-by: apetrusenko, ysr, pbk
This commit is contained in:
parent
aff36499e7
commit
1cdd538ea5
30 changed files with 718 additions and 402 deletions
|
@ -25,13 +25,13 @@
|
|||
#include "incls/_precompiled.incl"
|
||||
#include "incls/_markSweep.cpp.incl"
|
||||
|
||||
GrowableArray<oop>* MarkSweep::_marking_stack = NULL;
|
||||
GrowableArray<ObjArrayTask>* MarkSweep::_objarray_stack = NULL;
|
||||
GrowableArray<Klass*>* MarkSweep::_revisit_klass_stack = NULL;
|
||||
GrowableArray<DataLayout*>* MarkSweep::_revisit_mdo_stack = NULL;
|
||||
Stack<oop> MarkSweep::_marking_stack;
|
||||
Stack<DataLayout*> MarkSweep::_revisit_mdo_stack;
|
||||
Stack<Klass*> MarkSweep::_revisit_klass_stack;
|
||||
Stack<ObjArrayTask> MarkSweep::_objarray_stack;
|
||||
|
||||
GrowableArray<oop>* MarkSweep::_preserved_oop_stack = NULL;
|
||||
GrowableArray<markOop>* MarkSweep::_preserved_mark_stack= NULL;
|
||||
Stack<oop> MarkSweep::_preserved_oop_stack;
|
||||
Stack<markOop> MarkSweep::_preserved_mark_stack;
|
||||
size_t MarkSweep::_preserved_count = 0;
|
||||
size_t MarkSweep::_preserved_count_max = 0;
|
||||
PreservedMark* MarkSweep::_preserved_marks = NULL;
|
||||
|
@ -58,37 +58,42 @@ GrowableArray<size_t> * MarkSweep::_last_gc_live_oops_size = NULL;
|
|||
#endif
|
||||
|
||||
void MarkSweep::revisit_weak_klass_link(Klass* k) {
|
||||
_revisit_klass_stack->push(k);
|
||||
_revisit_klass_stack.push(k);
|
||||
}
|
||||
|
||||
void MarkSweep::follow_weak_klass_links() {
|
||||
// All klasses on the revisit stack are marked at this point.
|
||||
// Update and follow all subklass, sibling and implementor links.
|
||||
if (PrintRevisitStats) {
|
||||
gclog_or_tty->print_cr("#classes in system dictionary = %d", SystemDictionary::number_of_classes());
|
||||
gclog_or_tty->print_cr("Revisit klass stack length = %d", _revisit_klass_stack->length());
|
||||
gclog_or_tty->print_cr("#classes in system dictionary = %d",
|
||||
SystemDictionary::number_of_classes());
|
||||
gclog_or_tty->print_cr("Revisit klass stack size = " SIZE_FORMAT,
|
||||
_revisit_klass_stack.size());
|
||||
}
|
||||
for (int i = 0; i < _revisit_klass_stack->length(); i++) {
|
||||
_revisit_klass_stack->at(i)->follow_weak_klass_links(&is_alive,&keep_alive);
|
||||
while (!_revisit_klass_stack.is_empty()) {
|
||||
Klass* const k = _revisit_klass_stack.pop();
|
||||
k->follow_weak_klass_links(&is_alive, &keep_alive);
|
||||
}
|
||||
follow_stack();
|
||||
}
|
||||
|
||||
void MarkSweep::revisit_mdo(DataLayout* p) {
|
||||
_revisit_mdo_stack->push(p);
|
||||
_revisit_mdo_stack.push(p);
|
||||
}
|
||||
|
||||
void MarkSweep::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.
|
||||
assert(_marking_stack->is_empty(), "Marking stack should be empty");
|
||||
assert(_marking_stack.is_empty(), "Marking stack should be empty");
|
||||
if (PrintRevisitStats) {
|
||||
gclog_or_tty->print_cr("#classes in system dictionary = %d", SystemDictionary::number_of_classes());
|
||||
gclog_or_tty->print_cr("Revisit MDO stack length = %d", _revisit_mdo_stack->length());
|
||||
gclog_or_tty->print_cr("#classes in system dictionary = %d",
|
||||
SystemDictionary::number_of_classes());
|
||||
gclog_or_tty->print_cr("Revisit MDO stack size = " SIZE_FORMAT,
|
||||
_revisit_mdo_stack.size());
|
||||
}
|
||||
for (int i = 0; i < _revisit_mdo_stack->length(); i++) {
|
||||
_revisit_mdo_stack->at(i)->follow_weak_refs(&is_alive);
|
||||
while (!_revisit_mdo_stack.is_empty()) {
|
||||
_revisit_mdo_stack.pop()->follow_weak_refs(&is_alive);
|
||||
}
|
||||
follow_stack();
|
||||
}
|
||||
|
@ -106,41 +111,37 @@ void MarkSweep::MarkAndPushClosure::do_oop(narrowOop* p) { mark_and_push(p); }
|
|||
|
||||
void MarkSweep::follow_stack() {
|
||||
do {
|
||||
while (!_marking_stack->is_empty()) {
|
||||
oop obj = _marking_stack->pop();
|
||||
while (!_marking_stack.is_empty()) {
|
||||
oop obj = _marking_stack.pop();
|
||||
assert (obj->is_gc_marked(), "p must be marked");
|
||||
obj->follow_contents();
|
||||
}
|
||||
// Process ObjArrays one at a time to avoid marking stack bloat.
|
||||
if (!_objarray_stack->is_empty()) {
|
||||
ObjArrayTask task = _objarray_stack->pop();
|
||||
if (!_objarray_stack.is_empty()) {
|
||||
ObjArrayTask task = _objarray_stack.pop();
|
||||
objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint();
|
||||
k->oop_follow_contents(task.obj(), task.index());
|
||||
}
|
||||
} while (!_marking_stack->is_empty() || !_objarray_stack->is_empty());
|
||||
} while (!_marking_stack.is_empty() || !_objarray_stack.is_empty());
|
||||
}
|
||||
|
||||
MarkSweep::FollowStackClosure MarkSweep::follow_stack_closure;
|
||||
|
||||
void MarkSweep::FollowStackClosure::do_void() { follow_stack(); }
|
||||
|
||||
// We preserve the mark which should be replaced at the end and the location that it
|
||||
// will go. Note that the object that this markOop belongs to isn't currently at that
|
||||
// address but it will be after phase4
|
||||
// We preserve the mark which should be replaced at the end and the location
|
||||
// that it will go. Note that the object that this markOop belongs to isn't
|
||||
// currently at that address but it will be after phase4
|
||||
void MarkSweep::preserve_mark(oop obj, markOop mark) {
|
||||
// we try to store preserved marks in the to space of the new generation since this
|
||||
// is storage which should be available. Most of the time this should be sufficient
|
||||
// space for the marks we need to preserve but if it isn't we fall back in using
|
||||
// GrowableArrays to keep track of the overflow.
|
||||
// We try to store preserved marks in the to space of the new generation since
|
||||
// this is storage which should be available. Most of the time this should be
|
||||
// sufficient space for the marks we need to preserve but if it isn't we fall
|
||||
// back to using Stacks to keep track of the overflow.
|
||||
if (_preserved_count < _preserved_count_max) {
|
||||
_preserved_marks[_preserved_count++].init(obj, mark);
|
||||
} else {
|
||||
if (_preserved_mark_stack == NULL) {
|
||||
_preserved_mark_stack = new (ResourceObj::C_HEAP) GrowableArray<markOop>(40, true);
|
||||
_preserved_oop_stack = new (ResourceObj::C_HEAP) GrowableArray<oop>(40, true);
|
||||
}
|
||||
_preserved_mark_stack->push(mark);
|
||||
_preserved_oop_stack->push(obj);
|
||||
_preserved_mark_stack.push(mark);
|
||||
_preserved_oop_stack.push(obj);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,8 +152,7 @@ void MarkSweep::AdjustPointerClosure::do_oop(oop* p) { adjust_pointer(p, _
|
|||
void MarkSweep::AdjustPointerClosure::do_oop(narrowOop* p) { adjust_pointer(p, _is_root); }
|
||||
|
||||
void MarkSweep::adjust_marks() {
|
||||
assert(_preserved_oop_stack == NULL ||
|
||||
_preserved_oop_stack->length() == _preserved_mark_stack->length(),
|
||||
assert( _preserved_oop_stack.size() == _preserved_mark_stack.size(),
|
||||
"inconsistent preserved oop stacks");
|
||||
|
||||
// adjust the oops we saved earlier
|
||||
|
@ -161,21 +161,19 @@ void MarkSweep::adjust_marks() {
|
|||
}
|
||||
|
||||
// deal with the overflow stack
|
||||
if (_preserved_oop_stack) {
|
||||
for (int i = 0; i < _preserved_oop_stack->length(); i++) {
|
||||
oop* p = _preserved_oop_stack->adr_at(i);
|
||||
adjust_pointer(p);
|
||||
}
|
||||
StackIterator<oop> iter(_preserved_oop_stack);
|
||||
while (!iter.is_empty()) {
|
||||
oop* p = iter.next_addr();
|
||||
adjust_pointer(p);
|
||||
}
|
||||
}
|
||||
|
||||
void MarkSweep::restore_marks() {
|
||||
assert(_preserved_oop_stack == NULL ||
|
||||
_preserved_oop_stack->length() == _preserved_mark_stack->length(),
|
||||
assert(_preserved_oop_stack.size() == _preserved_mark_stack.size(),
|
||||
"inconsistent preserved oop stacks");
|
||||
if (PrintGC && Verbose) {
|
||||
gclog_or_tty->print_cr("Restoring %d marks", _preserved_count +
|
||||
(_preserved_oop_stack ? _preserved_oop_stack->length() : 0));
|
||||
gclog_or_tty->print_cr("Restoring %d marks",
|
||||
_preserved_count + _preserved_oop_stack.size());
|
||||
}
|
||||
|
||||
// restore the marks we saved earlier
|
||||
|
@ -184,12 +182,10 @@ void MarkSweep::restore_marks() {
|
|||
}
|
||||
|
||||
// deal with the overflow
|
||||
if (_preserved_oop_stack) {
|
||||
for (int i = 0; i < _preserved_oop_stack->length(); i++) {
|
||||
oop obj = _preserved_oop_stack->at(i);
|
||||
markOop mark = _preserved_mark_stack->at(i);
|
||||
obj->set_mark(mark);
|
||||
}
|
||||
while (!_preserved_oop_stack.is_empty()) {
|
||||
oop obj = _preserved_oop_stack.pop();
|
||||
markOop mark = _preserved_mark_stack.pop();
|
||||
obj->set_mark(mark);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue