duke@435: /* xdono@905: * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * duke@435: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@435: * CA 95054 USA or visit www.sun.com if you need additional information or duke@435: * have any questions. duke@435: * duke@435: */ duke@435: duke@435: // duke@435: // psPromotionManager is used by a single thread to manage object survival duke@435: // during a scavenge. The promotion manager contains thread local data only. duke@435: // duke@435: // NOTE! Be carefull when allocating the stacks on cheap. If you are going duke@435: // to use a promotion manager in more than one thread, the stacks MUST be duke@435: // on cheap. This can lead to memory leaks, though, as they are not auto duke@435: // deallocated. duke@435: // duke@435: // FIX ME FIX ME Add a destructor, and don't rely on the user to drain/flush/deallocate! duke@435: // duke@435: duke@435: // Move to some global location duke@435: #define HAS_BEEN_MOVED 0x1501d01d duke@435: // End move to some global location duke@435: duke@435: duke@435: class MutableSpace; duke@435: class PSOldGen; duke@435: class ParCompactionManager; duke@435: class ObjectStartArray; duke@435: class ParallelCompactData; duke@435: class ParMarkBitMap; duke@435: duke@435: // Move to it's own file if this works out. duke@435: duke@435: class ParCompactionManager : public CHeapObj { duke@435: friend class ParallelTaskTerminator; duke@435: friend class ParMarkBitMap; duke@435: friend class PSParallelCompact; jcoomes@810: friend class StealRegionCompactionTask; duke@435: friend class UpdateAndFillClosure; duke@435: friend class RefProcTaskExecutor; duke@435: duke@435: public: duke@435: duke@435: // ------------------------ Don't putback if not needed duke@435: // Actions that the compaction manager should take. duke@435: enum Action { duke@435: Update, duke@435: Copy, duke@435: UpdateAndCopy, duke@435: CopyAndUpdate, duke@435: VerifyUpdate, duke@435: ResetObjects, duke@435: NotValid duke@435: }; duke@435: // ------------------------ End don't putback if not needed duke@435: duke@435: private: jcoomes@810: static ParCompactionManager** _manager_array; jcoomes@810: static OopTaskQueueSet* _stack_array; jcoomes@810: static ObjectStartArray* _start_array; jcoomes@810: static RegionTaskQueueSet* _region_array; jcoomes@810: static PSOldGen* _old_gen; duke@435: jcoomes@810: OopTaskQueue _marking_stack; jcoomes@810: GrowableArray* _overflow_stack; duke@435: // Is there a way to reuse the _marking_stack for the jcoomes@810: // saving empty regions? For now just create a different duke@435: // type of TaskQueue. duke@435: jcoomes@810: #ifdef USE_RegionTaskQueueWithOverflow jcoomes@810: RegionTaskQueueWithOverflow _region_stack; duke@435: #else jcoomes@810: RegionTaskQueue _region_stack; jcoomes@810: GrowableArray* _region_overflow_stack; duke@435: #endif duke@435: duke@435: #if 1 // does this happen enough to need a per thread stack? jcoomes@810: GrowableArray* _revisit_klass_stack; ysr@1376: GrowableArray* _revisit_mdo_stack; duke@435: #endif duke@435: static ParMarkBitMap* _mark_bitmap; duke@435: duke@435: Action _action; duke@435: duke@435: static PSOldGen* old_gen() { return _old_gen; } duke@435: static ObjectStartArray* start_array() { return _start_array; } jcoomes@810: static OopTaskQueueSet* stack_array() { return _stack_array; } duke@435: duke@435: static void initialize(ParMarkBitMap* mbm); duke@435: duke@435: protected: duke@435: // Array of tasks. Needed by the ParallelTaskTerminator. jcoomes@810: static RegionTaskQueueSet* region_array() { return _region_array; } jcoomes@810: OopTaskQueue* marking_stack() { return &_marking_stack; } jcoomes@810: GrowableArray* overflow_stack() { return _overflow_stack; } jcoomes@810: #ifdef USE_RegionTaskQueueWithOverflow jcoomes@810: RegionTaskQueueWithOverflow* region_stack() { return &_region_stack; } duke@435: #else jcoomes@810: RegionTaskQueue* region_stack() { return &_region_stack; } jcoomes@810: GrowableArray* region_overflow_stack() { jcoomes@810: return _region_overflow_stack; jcoomes@810: } duke@435: #endif duke@435: duke@435: // Pushes onto the marking stack. If the marking stack is full, duke@435: // pushes onto the overflow stack. duke@435: void stack_push(oop obj); duke@435: // Do not implement an equivalent stack_pop. Deal with the duke@435: // marking stack and overflow stack directly. duke@435: jcoomes@810: // Pushes onto the region stack. If the region stack is full, jcoomes@810: // pushes onto the region overflow stack. jcoomes@810: void region_stack_push(size_t region_index); duke@435: public: duke@435: duke@435: Action action() { return _action; } duke@435: void set_action(Action v) { _action = v; } duke@435: duke@435: inline static ParCompactionManager* manager_array(int index); duke@435: duke@435: ParCompactionManager(); duke@435: ~ParCompactionManager(); duke@435: duke@435: void allocate_stacks(); duke@435: void deallocate_stacks(); duke@435: ParMarkBitMap* mark_bitmap() { return _mark_bitmap; } duke@435: duke@435: // Take actions in preparation for a compaction. duke@435: static void reset(); duke@435: duke@435: // void drain_stacks(); duke@435: duke@435: bool should_update(); duke@435: bool should_copy(); duke@435: bool should_verify_only(); duke@435: bool should_reset_only(); duke@435: duke@435: #if 1 duke@435: // Probably stays as a growable array duke@435: GrowableArray* revisit_klass_stack() { return _revisit_klass_stack; } ysr@1376: GrowableArray* revisit_mdo_stack() { return _revisit_mdo_stack; } duke@435: #endif duke@435: duke@435: // Save oop for later processing. Must not fail. duke@435: void save_for_scanning(oop m); duke@435: // Get a oop for scanning. If returns null, no oop were found. duke@435: oop retrieve_for_scanning(); duke@435: jcoomes@810: // Save region for later processing. Must not fail. jcoomes@810: void save_for_processing(size_t region_index); jcoomes@810: // Get a region for processing. If returns null, no region were found. jcoomes@810: bool retrieve_for_processing(size_t& region_index); duke@435: duke@435: // Access function for compaction managers duke@435: static ParCompactionManager* gc_thread_compaction_manager(int index); duke@435: duke@435: static bool steal(int queue_num, int* seed, Task& t) { duke@435: return stack_array()->steal(queue_num, seed, t); duke@435: } duke@435: jcoomes@810: static bool steal(int queue_num, int* seed, RegionTask& t) { jcoomes@810: return region_array()->steal(queue_num, seed, t); duke@435: } duke@435: duke@435: // Process tasks remaining on any stack duke@435: void drain_marking_stacks(OopClosure *blk); duke@435: duke@435: // Process tasks remaining on any stack jcoomes@810: void drain_region_stacks(); duke@435: duke@435: // Process tasks remaining on any stack jcoomes@810: void drain_region_overflow_stack(); duke@435: duke@435: // Debugging support duke@435: #ifdef ASSERT duke@435: bool stacks_have_been_allocated(); duke@435: #endif duke@435: }; duke@435: duke@435: inline ParCompactionManager* ParCompactionManager::manager_array(int index) { duke@435: assert(_manager_array != NULL, "access of NULL manager_array"); duke@435: assert(index >= 0 && index <= (int)ParallelGCThreads, duke@435: "out of range manager_array access"); duke@435: return _manager_array[index]; duke@435: }