duke@435: /* trims@1907: * Copyright (c) 2005, 2009, Oracle and/or its affiliates. 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: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * 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: 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@1746: // 32-bit: 4K * 8 = 32KiB; 64-bit: 8K * 16 = 128KiB jcoomes@1746: #define OBJARRAY_QUEUE_SIZE (1 << NOT_LP64(12) LP64_ONLY(13)) jcoomes@1746: typedef GenericTaskQueue ObjArrayTaskQueue; jcoomes@1746: typedef GenericTaskQueueSet ObjArrayTaskQueueSet; jcoomes@1746: #undef OBJARRAY_QUEUE_SIZE jcoomes@1746: jcoomes@810: static ParCompactionManager** _manager_array; jcoomes@810: static OopTaskQueueSet* _stack_array; jcoomes@1746: static ObjArrayTaskQueueSet* _objarray_queues; jcoomes@810: static ObjectStartArray* _start_array; jcoomes@810: static RegionTaskQueueSet* _region_array; jcoomes@810: static PSOldGen* _old_gen; duke@435: jcoomes@1746: private: jcoomes@810: OopTaskQueue _marking_stack; jcoomes@810: GrowableArray* _overflow_stack; jcoomes@1746: jcoomes@1746: typedef GrowableArray ObjArrayOverflowStack; jcoomes@1746: ObjArrayTaskQueue _objarray_queue; jcoomes@1746: ObjArrayOverflowStack* _objarray_overflow_stack; jcoomes@1746: 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: jcoomes@1746: public: 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@1746: inline void push_objarray(oop obj, size_t index); jcoomes@1746: 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@1746: static bool steal_objarray(int queue_num, int* seed, ObjArrayTask& t) { jcoomes@1746: return _objarray_queues->steal(queue_num, seed, t); jcoomes@1746: } jcoomes@1746: 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: jcoomes@1746: // Process tasks remaining on any marking stack jcoomes@1746: void follow_marking_stacks(); jcoomes@1746: inline bool marking_stacks_empty() const; 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: } jcoomes@1746: jcoomes@1746: bool ParCompactionManager::marking_stacks_empty() const { jcoomes@1746: return _marking_stack.size() == 0 && _overflow_stack->is_empty() && jcoomes@1746: _objarray_queue.size() == 0 && _objarray_overflow_stack->is_empty(); jcoomes@1746: }