duke@435: /* coleenp@4037: * Copyright (c) 2005, 2012, 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: stefank@2314: #ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSCOMPACTIONMANAGER_HPP stefank@2314: #define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSCOMPACTIONMANAGER_HPP stefank@2314: stefank@2314: #include "memory/allocation.hpp" stefank@2314: #include "utilities/stack.hpp" stefank@2314: #include "utilities/taskqueue.hpp" stefank@2314: 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: zgu@3900: 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; jmasa@3294: friend class IdleGCTask; 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: 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@1993: #define QUEUE_SIZE (1 << NOT_LP64(12) LP64_ONLY(13)) zgu@3900: typedef OverflowTaskQueue ObjArrayTaskQueue; zgu@3900: typedef GenericTaskQueueSet ObjArrayTaskQueueSet; jcoomes@1993: #undef 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: zgu@3900: OverflowTaskQueue _marking_stack; jcoomes@1993: ObjArrayTaskQueue _objarray_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. jmasa@3294: RegionTaskQueue* _region_stack; jmasa@3294: jmasa@3294: static RegionTaskQueue** _region_list; jmasa@3294: // Index in _region_list for current _region_stack. jmasa@3294: uint _region_stack_index; jmasa@3294: jmasa@3294: // Indexes of recycled region stacks/overflow stacks jmasa@3294: // Stacks of regions to be compacted are embedded in the tasks doing jmasa@3294: // the compaction. A thread that executes the task extracts the jmasa@3294: // region stack and drains it. These threads keep these region jmasa@3294: // stacks for use during compaction task stealing. If a thread jmasa@3294: // gets a second draining task, it pushed its current region stack jmasa@3294: // index into the array _recycled_stack_index and gets a new jmasa@3294: // region stack from the task. A thread that is executing a jmasa@3294: // compaction stealing task without ever having executing a jmasa@3294: // draining task, will get a region stack from _recycled_stack_index. jmasa@3294: // jmasa@3294: // Array of indexes into the array of region stacks. jmasa@3294: static uint* _recycled_stack_index; jmasa@3294: // The index into _recycled_stack_index of the last region stack index jmasa@3294: // pushed. If -1, there are no entries into _recycled_stack_index. jmasa@3294: static int _recycled_top; jmasa@3294: // The index into _recycled_stack_index of the last region stack index jmasa@3294: // popped. If -1, there has not been any entry popped. jmasa@3294: static int _recycled_bottom; duke@435: 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; } zgu@3900: OverflowTaskQueue* marking_stack() { return &_marking_stack; } 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@1993: public: duke@435: Action action() { return _action; } duke@435: void set_action(Action v) { _action = v; } duke@435: jmasa@3294: RegionTaskQueue* region_stack() { return _region_stack; } jmasa@3294: void set_region_stack(RegionTaskQueue* v) { _region_stack = v; } jmasa@3294: duke@435: inline static ParCompactionManager* manager_array(int index); duke@435: jmasa@3294: inline static RegionTaskQueue* region_list(int index) { jmasa@3294: return _region_list[index]; jmasa@3294: } jmasa@3294: jmasa@3294: uint region_stack_index() { return _region_stack_index; } jmasa@3294: void set_region_stack_index(uint v) { _region_stack_index = v; } jmasa@3294: jmasa@3294: // Pop and push unique reusable stack index jmasa@3294: static int pop_recycled_stack_index(); jmasa@3294: static void push_recycled_stack_index(uint v); jmasa@3294: static void reset_recycled_stack_index() { jmasa@3294: _recycled_bottom = _recycled_top = -1; jmasa@3294: } jmasa@3294: duke@435: ParCompactionManager(); jmasa@3294: ~ParCompactionManager(); duke@435: jmasa@3294: // Pushes onto the region stack at the given index. If the jmasa@3294: // region stack is full, jmasa@3294: // pushes onto the region overflow stack. jmasa@3294: static void region_list_push(uint stack_index, size_t region_index); jmasa@3294: static void verify_region_list_empty(uint stack_index); duke@435: ParMarkBitMap* mark_bitmap() { return _mark_bitmap; } duke@435: duke@435: // void drain_stacks(); duke@435: duke@435: bool should_update(); duke@435: bool should_copy(); duke@435: jcoomes@1993: // Save for later processing. Must not fail. jcoomes@1993: inline void push(oop obj) { _marking_stack.push(obj); } jcoomes@1993: inline void push_objarray(oop objarray, size_t index); jcoomes@1993: inline void push_region(size_t index); duke@435: duke@435: // Access function for compaction managers duke@435: static ParCompactionManager* gc_thread_compaction_manager(int index); duke@435: jcoomes@1993: static bool steal(int queue_num, int* seed, oop& 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@1993: static bool steal(int queue_num, int* seed, size_t& region) { jcoomes@1993: return region_array()->steal(queue_num, seed, region); 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: }; 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@1993: return _marking_stack.is_empty() && _objarray_stack.is_empty(); jcoomes@1746: } stefank@2314: stefank@2314: #endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSCOMPACTIONMANAGER_HPP