Mercurial > hg > truffle
comparison 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 |
comparison
equal
deleted
inserted
replaced
1289:d47555d7aca8 | 1311:2a1472c30599 |
---|---|
26 #include "incls/_psCompactionManager.cpp.incl" | 26 #include "incls/_psCompactionManager.cpp.incl" |
27 | 27 |
28 PSOldGen* ParCompactionManager::_old_gen = NULL; | 28 PSOldGen* ParCompactionManager::_old_gen = NULL; |
29 ParCompactionManager** ParCompactionManager::_manager_array = NULL; | 29 ParCompactionManager** ParCompactionManager::_manager_array = NULL; |
30 OopTaskQueueSet* ParCompactionManager::_stack_array = NULL; | 30 OopTaskQueueSet* ParCompactionManager::_stack_array = NULL; |
31 ParCompactionManager::ObjArrayTaskQueueSet* | |
32 ParCompactionManager::_objarray_queues = NULL; | |
31 ObjectStartArray* ParCompactionManager::_start_array = NULL; | 33 ObjectStartArray* ParCompactionManager::_start_array = NULL; |
32 ParMarkBitMap* ParCompactionManager::_mark_bitmap = NULL; | 34 ParMarkBitMap* ParCompactionManager::_mark_bitmap = NULL; |
33 RegionTaskQueueSet* ParCompactionManager::_region_array = NULL; | 35 RegionTaskQueueSet* ParCompactionManager::_region_array = NULL; |
34 | 36 |
35 ParCompactionManager::ParCompactionManager() : | 37 ParCompactionManager::ParCompactionManager() : |
44 | 46 |
45 marking_stack()->initialize(); | 47 marking_stack()->initialize(); |
46 | 48 |
47 // We want the overflow stack to be permanent | 49 // We want the overflow stack to be permanent |
48 _overflow_stack = new (ResourceObj::C_HEAP) GrowableArray<oop>(10, true); | 50 _overflow_stack = new (ResourceObj::C_HEAP) GrowableArray<oop>(10, true); |
51 | |
52 _objarray_queue.initialize(); | |
53 _objarray_overflow_stack = | |
54 new (ResourceObj::C_HEAP) ObjArrayOverflowStack(10, true); | |
55 | |
49 #ifdef USE_RegionTaskQueueWithOverflow | 56 #ifdef USE_RegionTaskQueueWithOverflow |
50 region_stack()->initialize(); | 57 region_stack()->initialize(); |
51 #else | 58 #else |
52 region_stack()->initialize(); | 59 region_stack()->initialize(); |
53 | 60 |
67 | 74 |
68 } | 75 } |
69 | 76 |
70 ParCompactionManager::~ParCompactionManager() { | 77 ParCompactionManager::~ParCompactionManager() { |
71 delete _overflow_stack; | 78 delete _overflow_stack; |
79 delete _objarray_overflow_stack; | |
72 delete _revisit_klass_stack; | 80 delete _revisit_klass_stack; |
73 delete _revisit_mdo_stack; | 81 delete _revisit_mdo_stack; |
74 // _manager_array and _stack_array are statics | 82 // _manager_array and _stack_array are statics |
75 // shared with all instances of ParCompactionManager | 83 // shared with all instances of ParCompactionManager |
76 // should not be deallocated. | 84 // should not be deallocated. |
84 | 92 |
85 uint parallel_gc_threads = PSParallelCompact::gc_task_manager()->workers(); | 93 uint parallel_gc_threads = PSParallelCompact::gc_task_manager()->workers(); |
86 | 94 |
87 assert(_manager_array == NULL, "Attempt to initialize twice"); | 95 assert(_manager_array == NULL, "Attempt to initialize twice"); |
88 _manager_array = NEW_C_HEAP_ARRAY(ParCompactionManager*, parallel_gc_threads+1 ); | 96 _manager_array = NEW_C_HEAP_ARRAY(ParCompactionManager*, parallel_gc_threads+1 ); |
89 guarantee(_manager_array != NULL, "Could not initialize promotion manager"); | 97 guarantee(_manager_array != NULL, "Could not allocate manager_array"); |
90 | 98 |
91 _stack_array = new OopTaskQueueSet(parallel_gc_threads); | 99 _stack_array = new OopTaskQueueSet(parallel_gc_threads); |
92 guarantee(_stack_array != NULL, "Count not initialize promotion manager"); | 100 guarantee(_stack_array != NULL, "Could not allocate stack_array"); |
101 _objarray_queues = new ObjArrayTaskQueueSet(parallel_gc_threads); | |
102 guarantee(_objarray_queues != NULL, "Could not allocate objarray_queues"); | |
93 _region_array = new RegionTaskQueueSet(parallel_gc_threads); | 103 _region_array = new RegionTaskQueueSet(parallel_gc_threads); |
94 guarantee(_region_array != NULL, "Count not initialize promotion manager"); | 104 guarantee(_region_array != NULL, "Could not allocate region_array"); |
95 | 105 |
96 // Create and register the ParCompactionManager(s) for the worker threads. | 106 // Create and register the ParCompactionManager(s) for the worker threads. |
97 for(uint i=0; i<parallel_gc_threads; i++) { | 107 for(uint i=0; i<parallel_gc_threads; i++) { |
98 _manager_array[i] = new ParCompactionManager(); | 108 _manager_array[i] = new ParCompactionManager(); |
99 guarantee(_manager_array[i] != NULL, "Could not create ParCompactionManager"); | 109 guarantee(_manager_array[i] != NULL, "Could not create ParCompactionManager"); |
100 stack_array()->register_queue(i, _manager_array[i]->marking_stack()); | 110 stack_array()->register_queue(i, _manager_array[i]->marking_stack()); |
111 _objarray_queues->register_queue(i, &_manager_array[i]->_objarray_queue); | |
101 #ifdef USE_RegionTaskQueueWithOverflow | 112 #ifdef USE_RegionTaskQueueWithOverflow |
102 region_array()->register_queue(i, _manager_array[i]->region_stack()->task_queue()); | 113 region_array()->register_queue(i, _manager_array[i]->region_stack()->task_queue()); |
103 #else | 114 #else |
104 region_array()->register_queue(i, _manager_array[i]->region_stack()); | 115 region_array()->register_queue(i, _manager_array[i]->region_stack()); |
105 #endif | 116 #endif |
201 manager_array(i)->revisit_klass_stack()->clear(); | 212 manager_array(i)->revisit_klass_stack()->clear(); |
202 manager_array(i)->revisit_mdo_stack()->clear(); | 213 manager_array(i)->revisit_mdo_stack()->clear(); |
203 } | 214 } |
204 } | 215 } |
205 | 216 |
206 void ParCompactionManager::drain_marking_stacks(OopClosure* blk) { | 217 void ParCompactionManager::follow_marking_stacks() { |
207 #ifdef ASSERT | |
208 ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); | |
209 assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); | |
210 MutableSpace* to_space = heap->young_gen()->to_space(); | |
211 MutableSpace* old_space = heap->old_gen()->object_space(); | |
212 MutableSpace* perm_space = heap->perm_gen()->object_space(); | |
213 #endif /* ASSERT */ | |
214 | |
215 | |
216 do { | 218 do { |
217 | 219 // Drain the overflow stack first, to allow stealing from the marking stack. |
218 // Drain overflow stack first, so other threads can steal from | 220 while (!overflow_stack()->is_empty()) { |
219 // claimed stack while we work. | 221 overflow_stack()->pop()->follow_contents(this); |
220 while(!overflow_stack()->is_empty()) { | 222 } |
221 oop obj = overflow_stack()->pop(); | 223 oop obj; |
224 while (marking_stack()->pop_local(obj)) { | |
222 obj->follow_contents(this); | 225 obj->follow_contents(this); |
223 } | 226 } |
224 | 227 |
225 oop obj; | 228 ObjArrayTask task; |
226 // obj is a reference!!! | 229 while (!_objarray_overflow_stack->is_empty()) { |
227 while (marking_stack()->pop_local(obj)) { | 230 task = _objarray_overflow_stack->pop(); |
228 // It would be nice to assert about the type of objects we might | 231 objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint(); |
229 // pop, but they can come from anywhere, unfortunately. | 232 k->oop_follow_contents(this, task.obj(), task.index()); |
230 obj->follow_contents(this); | 233 } |
231 } | 234 while (_objarray_queue.pop_local(task)) { |
232 } while((marking_stack()->size() != 0) || (overflow_stack()->length() != 0)); | 235 objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint(); |
233 | 236 k->oop_follow_contents(this, task.obj(), task.index()); |
234 assert(marking_stack()->size() == 0, "Sanity"); | 237 } |
235 assert(overflow_stack()->length() == 0, "Sanity"); | 238 } while (!marking_stacks_empty()); |
239 | |
240 assert(marking_stacks_empty(), "Sanity"); | |
236 } | 241 } |
237 | 242 |
238 void ParCompactionManager::drain_region_overflow_stack() { | 243 void ParCompactionManager::drain_region_overflow_stack() { |
239 size_t region_index = (size_t) -1; | 244 size_t region_index = (size_t) -1; |
240 while(region_stack()->retrieve_from_overflow(region_index)) { | 245 while(region_stack()->retrieve_from_overflow(region_index)) { |