Mercurial > hg > truffle
diff src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp @ 1311:2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
Summary: Use an explicit stack for object arrays and process them in chunks.
Reviewed-by: iveresov, apetrusenko
author | jcoomes |
---|---|
date | Wed, 03 Mar 2010 14:48:26 -0800 |
parents | 89e0543e1737 |
children | c385bf94cfb8 |
line wrap: on
line diff
--- a/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp Wed Mar 03 08:10:41 2010 -0800 +++ b/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp Wed Mar 03 14:48:26 2010 -0800 @@ -28,6 +28,8 @@ PSOldGen* ParCompactionManager::_old_gen = NULL; ParCompactionManager** ParCompactionManager::_manager_array = NULL; OopTaskQueueSet* ParCompactionManager::_stack_array = NULL; +ParCompactionManager::ObjArrayTaskQueueSet* + ParCompactionManager::_objarray_queues = NULL; ObjectStartArray* ParCompactionManager::_start_array = NULL; ParMarkBitMap* ParCompactionManager::_mark_bitmap = NULL; RegionTaskQueueSet* ParCompactionManager::_region_array = NULL; @@ -46,6 +48,11 @@ // We want the overflow stack to be permanent _overflow_stack = new (ResourceObj::C_HEAP) GrowableArray<oop>(10, true); + + _objarray_queue.initialize(); + _objarray_overflow_stack = + new (ResourceObj::C_HEAP) ObjArrayOverflowStack(10, true); + #ifdef USE_RegionTaskQueueWithOverflow region_stack()->initialize(); #else @@ -69,6 +76,7 @@ ParCompactionManager::~ParCompactionManager() { delete _overflow_stack; + delete _objarray_overflow_stack; delete _revisit_klass_stack; delete _revisit_mdo_stack; // _manager_array and _stack_array are statics @@ -86,18 +94,21 @@ assert(_manager_array == NULL, "Attempt to initialize twice"); _manager_array = NEW_C_HEAP_ARRAY(ParCompactionManager*, parallel_gc_threads+1 ); - guarantee(_manager_array != NULL, "Could not initialize promotion manager"); + guarantee(_manager_array != NULL, "Could not allocate manager_array"); _stack_array = new OopTaskQueueSet(parallel_gc_threads); - guarantee(_stack_array != NULL, "Count not initialize promotion manager"); + guarantee(_stack_array != NULL, "Could not allocate stack_array"); + _objarray_queues = new ObjArrayTaskQueueSet(parallel_gc_threads); + guarantee(_objarray_queues != NULL, "Could not allocate objarray_queues"); _region_array = new RegionTaskQueueSet(parallel_gc_threads); - guarantee(_region_array != NULL, "Count not initialize promotion manager"); + guarantee(_region_array != NULL, "Could not allocate region_array"); // 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()); + _objarray_queues->register_queue(i, &_manager_array[i]->_objarray_queue); #ifdef USE_RegionTaskQueueWithOverflow region_array()->register_queue(i, _manager_array[i]->region_stack()->task_queue()); #else @@ -203,36 +214,30 @@ } } -void ParCompactionManager::drain_marking_stacks(OopClosure* blk) { -#ifdef ASSERT - ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); - assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); - MutableSpace* to_space = heap->young_gen()->to_space(); - MutableSpace* old_space = heap->old_gen()->object_space(); - MutableSpace* perm_space = heap->perm_gen()->object_space(); -#endif /* ASSERT */ - - +void ParCompactionManager::follow_marking_stacks() { do { - - // Drain overflow stack first, so other threads can steal from - // claimed stack while we work. - while(!overflow_stack()->is_empty()) { - oop obj = overflow_stack()->pop(); + // Drain the overflow stack first, to allow stealing from the marking stack. + while (!overflow_stack()->is_empty()) { + overflow_stack()->pop()->follow_contents(this); + } + oop obj; + while (marking_stack()->pop_local(obj)) { obj->follow_contents(this); } - oop obj; - // obj is a reference!!! - while (marking_stack()->pop_local(obj)) { - // It would be nice to assert about the type of objects we might - // pop, but they can come from anywhere, unfortunately. - obj->follow_contents(this); + ObjArrayTask task; + while (!_objarray_overflow_stack->is_empty()) { + task = _objarray_overflow_stack->pop(); + objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint(); + k->oop_follow_contents(this, task.obj(), task.index()); } - } while((marking_stack()->size() != 0) || (overflow_stack()->length() != 0)); + while (_objarray_queue.pop_local(task)) { + objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint(); + k->oop_follow_contents(this, task.obj(), task.index()); + } + } while (!marking_stacks_empty()); - assert(marking_stack()->size() == 0, "Sanity"); - assert(overflow_stack()->length() == 0, "Sanity"); + assert(marking_stacks_empty(), "Sanity"); } void ParCompactionManager::drain_region_overflow_stack() {