Mercurial > hg > graal-jvmci-8
diff src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp @ 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 | c18cbe5936b8 |
line wrap: on
line diff
--- a/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp Wed Mar 03 08:10:41 2010 -0800 +++ b/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp Wed Mar 03 14:48:26 2010 -0800 @@ -22,18 +22,6 @@ * */ -// -// psPromotionManager is used by a single thread to manage object survival -// during a scavenge. The promotion manager contains thread local data only. -// -// NOTE! Be carefull when allocating the stacks on cheap. If you are going -// to use a promotion manager in more than one thread, the stacks MUST be -// on cheap. This can lead to memory leaks, though, as they are not auto -// deallocated. -// -// FIX ME FIX ME Add a destructor, and don't rely on the user to drain/flush/deallocate! -// - // Move to some global location #define HAS_BEEN_MOVED 0x1501d01d // End move to some global location @@ -46,8 +34,6 @@ class ParallelCompactData; class ParMarkBitMap; -// Move to it's own file if this works out. - class ParCompactionManager : public CHeapObj { friend class ParallelTaskTerminator; friend class ParMarkBitMap; @@ -72,14 +58,27 @@ // ------------------------ End don't putback if not needed private: + // 32-bit: 4K * 8 = 32KiB; 64-bit: 8K * 16 = 128KiB + #define OBJARRAY_QUEUE_SIZE (1 << NOT_LP64(12) LP64_ONLY(13)) + typedef GenericTaskQueue<ObjArrayTask, OBJARRAY_QUEUE_SIZE> ObjArrayTaskQueue; + typedef GenericTaskQueueSet<ObjArrayTaskQueue> ObjArrayTaskQueueSet; + #undef OBJARRAY_QUEUE_SIZE + static ParCompactionManager** _manager_array; static OopTaskQueueSet* _stack_array; + static ObjArrayTaskQueueSet* _objarray_queues; static ObjectStartArray* _start_array; static RegionTaskQueueSet* _region_array; static PSOldGen* _old_gen; +private: OopTaskQueue _marking_stack; GrowableArray<oop>* _overflow_stack; + + typedef GrowableArray<ObjArrayTask> ObjArrayOverflowStack; + ObjArrayTaskQueue _objarray_queue; + ObjArrayOverflowStack* _objarray_overflow_stack; + // Is there a way to reuse the _marking_stack for the // saving empty regions? For now just create a different // type of TaskQueue. @@ -128,8 +127,8 @@ // 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: +public: Action action() { return _action; } void set_action(Action v) { _action = v; } @@ -163,6 +162,8 @@ // Get a oop for scanning. If returns null, no oop were found. oop retrieve_for_scanning(); + inline void push_objarray(oop obj, size_t 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. @@ -175,12 +176,17 @@ return stack_array()->steal(queue_num, seed, t); } + static bool steal_objarray(int queue_num, int* seed, ObjArrayTask& t) { + return _objarray_queues->steal(queue_num, seed, t); + } + static bool steal(int queue_num, int* seed, RegionTask& 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 marking stack + void follow_marking_stacks(); + inline bool marking_stacks_empty() const; // Process tasks remaining on any stack void drain_region_stacks(); @@ -200,3 +206,8 @@ "out of range manager_array access"); return _manager_array[index]; } + +bool ParCompactionManager::marking_stacks_empty() const { + return _marking_stack.size() == 0 && _overflow_stack->is_empty() && + _objarray_queue.size() == 0 && _objarray_overflow_stack->is_empty(); +}