| 1 | /* | 
|---|
| 2 | * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. | 
|---|
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 
|---|
| 4 | * | 
|---|
| 5 | * This code is free software; you can redistribute it and/or modify it | 
|---|
| 6 | * under the terms of the GNU General Public License version 2 only, as | 
|---|
| 7 | * published by the Free Software Foundation. | 
|---|
| 8 | * | 
|---|
| 9 | * This code is distributed in the hope that it will be useful, but WITHOUT | 
|---|
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
|---|
| 11 | * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | 
|---|
| 12 | * version 2 for more details (a copy is included in the LICENSE file that | 
|---|
| 13 | * accompanied this code). | 
|---|
| 14 | * | 
|---|
| 15 | * You should have received a copy of the GNU General Public License version | 
|---|
| 16 | * 2 along with this work; if not, write to the Free Software Foundation, | 
|---|
| 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 
|---|
| 18 | * | 
|---|
| 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | 
|---|
| 20 | * or visit www.oracle.com if you need additional information or have any | 
|---|
| 21 | * questions. | 
|---|
| 22 | * | 
|---|
| 23 | */ | 
|---|
| 24 |  | 
|---|
| 25 | #ifndef SHARE_GC_PARALLEL_PSCOMPACTIONMANAGER_HPP | 
|---|
| 26 | #define SHARE_GC_PARALLEL_PSCOMPACTIONMANAGER_HPP | 
|---|
| 27 |  | 
|---|
| 28 | #include "gc/shared/taskqueue.hpp" | 
|---|
| 29 | #include "memory/allocation.hpp" | 
|---|
| 30 | #include "utilities/stack.hpp" | 
|---|
| 31 |  | 
|---|
| 32 | class MutableSpace; | 
|---|
| 33 | class PSOldGen; | 
|---|
| 34 | class ParCompactionManager; | 
|---|
| 35 | class ObjectStartArray; | 
|---|
| 36 | class ParallelCompactData; | 
|---|
| 37 | class ParMarkBitMap; | 
|---|
| 38 |  | 
|---|
| 39 | class ParCompactionManager : public CHeapObj<mtGC> { | 
|---|
| 40 | friend class ParallelTaskTerminator; | 
|---|
| 41 | friend class ParMarkBitMap; | 
|---|
| 42 | friend class PSParallelCompact; | 
|---|
| 43 | friend class CompactionWithStealingTask; | 
|---|
| 44 | friend class UpdateAndFillClosure; | 
|---|
| 45 | friend class RefProcTaskExecutor; | 
|---|
| 46 | friend class IdleGCTask; | 
|---|
| 47 |  | 
|---|
| 48 | public: | 
|---|
| 49 |  | 
|---|
| 50 | // ------------------------  Don't putback if not needed | 
|---|
| 51 | // Actions that the compaction manager should take. | 
|---|
| 52 | enum Action { | 
|---|
| 53 | Update, | 
|---|
| 54 | Copy, | 
|---|
| 55 | UpdateAndCopy, | 
|---|
| 56 | CopyAndUpdate, | 
|---|
| 57 | NotValid | 
|---|
| 58 | }; | 
|---|
| 59 | // ------------------------  End don't putback if not needed | 
|---|
| 60 |  | 
|---|
| 61 | private: | 
|---|
| 62 | // 32-bit:  4K * 8 = 32KiB; 64-bit:  8K * 16 = 128KiB | 
|---|
| 63 | #define QUEUE_SIZE (1 << NOT_LP64(12) LP64_ONLY(13)) | 
|---|
| 64 | typedef OverflowTaskQueue<ObjArrayTask, mtGC, QUEUE_SIZE> ObjArrayTaskQueue; | 
|---|
| 65 | typedef GenericTaskQueueSet<ObjArrayTaskQueue, mtGC>      ObjArrayTaskQueueSet; | 
|---|
| 66 | #undef QUEUE_SIZE | 
|---|
| 67 |  | 
|---|
| 68 | static ParCompactionManager** _manager_array; | 
|---|
| 69 | static OopTaskQueueSet*       _stack_array; | 
|---|
| 70 | static ObjArrayTaskQueueSet*  _objarray_queues; | 
|---|
| 71 | static ObjectStartArray*      _start_array; | 
|---|
| 72 | static RegionTaskQueueSet*    _region_array; | 
|---|
| 73 | static PSOldGen*              _old_gen; | 
|---|
| 74 |  | 
|---|
| 75 | private: | 
|---|
| 76 | OverflowTaskQueue<oop, mtGC>        _marking_stack; | 
|---|
| 77 | ObjArrayTaskQueue             _objarray_stack; | 
|---|
| 78 |  | 
|---|
| 79 | // Is there a way to reuse the _marking_stack for the | 
|---|
| 80 | // saving empty regions?  For now just create a different | 
|---|
| 81 | // type of TaskQueue. | 
|---|
| 82 | RegionTaskQueue              _region_stack; | 
|---|
| 83 |  | 
|---|
| 84 | static ParMarkBitMap* _mark_bitmap; | 
|---|
| 85 |  | 
|---|
| 86 | Action _action; | 
|---|
| 87 |  | 
|---|
| 88 | HeapWord* _last_query_beg; | 
|---|
| 89 | oop _last_query_obj; | 
|---|
| 90 | size_t _last_query_ret; | 
|---|
| 91 |  | 
|---|
| 92 | static PSOldGen* old_gen()             { return _old_gen; } | 
|---|
| 93 | static ObjectStartArray* start_array() { return _start_array; } | 
|---|
| 94 | static OopTaskQueueSet* stack_array()  { return _stack_array; } | 
|---|
| 95 |  | 
|---|
| 96 | static void initialize(ParMarkBitMap* mbm); | 
|---|
| 97 |  | 
|---|
| 98 | protected: | 
|---|
| 99 | // Array of tasks.  Needed by the ParallelTaskTerminator. | 
|---|
| 100 | static RegionTaskQueueSet* region_array()      { return _region_array; } | 
|---|
| 101 | OverflowTaskQueue<oop, mtGC>*  marking_stack()       { return &_marking_stack; } | 
|---|
| 102 |  | 
|---|
| 103 | // Pushes onto the marking stack.  If the marking stack is full, | 
|---|
| 104 | // pushes onto the overflow stack. | 
|---|
| 105 | void stack_push(oop obj); | 
|---|
| 106 | // Do not implement an equivalent stack_pop.  Deal with the | 
|---|
| 107 | // marking stack and overflow stack directly. | 
|---|
| 108 |  | 
|---|
| 109 | public: | 
|---|
| 110 | void reset_bitmap_query_cache() { | 
|---|
| 111 | _last_query_beg = NULL; | 
|---|
| 112 | _last_query_obj = NULL; | 
|---|
| 113 | _last_query_ret = 0; | 
|---|
| 114 | } | 
|---|
| 115 |  | 
|---|
| 116 | Action action() { return _action; } | 
|---|
| 117 | void set_action(Action v) { _action = v; } | 
|---|
| 118 |  | 
|---|
| 119 | // Bitmap query support, cache last query and result | 
|---|
| 120 | HeapWord* last_query_begin() { return _last_query_beg; } | 
|---|
| 121 | oop last_query_object() { return _last_query_obj; } | 
|---|
| 122 | size_t last_query_return() { return _last_query_ret; } | 
|---|
| 123 |  | 
|---|
| 124 | void set_last_query_begin(HeapWord *new_beg) { _last_query_beg = new_beg; } | 
|---|
| 125 | void set_last_query_object(oop new_obj) { _last_query_obj = new_obj; } | 
|---|
| 126 | void set_last_query_return(size_t new_ret) { _last_query_ret = new_ret; } | 
|---|
| 127 |  | 
|---|
| 128 | static void reset_all_bitmap_query_caches(); | 
|---|
| 129 |  | 
|---|
| 130 | RegionTaskQueue* region_stack()                { return &_region_stack; } | 
|---|
| 131 |  | 
|---|
| 132 | inline static ParCompactionManager* manager_array(uint index); | 
|---|
| 133 |  | 
|---|
| 134 | ParCompactionManager(); | 
|---|
| 135 |  | 
|---|
| 136 | // Pushes onto the region stack at the given index.  If the | 
|---|
| 137 | // region stack is full, | 
|---|
| 138 | // pushes onto the region overflow stack. | 
|---|
| 139 | static void verify_region_list_empty(uint stack_index); | 
|---|
| 140 | ParMarkBitMap* mark_bitmap() { return _mark_bitmap; } | 
|---|
| 141 |  | 
|---|
| 142 | // void drain_stacks(); | 
|---|
| 143 |  | 
|---|
| 144 | bool should_update(); | 
|---|
| 145 | bool should_copy(); | 
|---|
| 146 |  | 
|---|
| 147 | // Save for later processing.  Must not fail. | 
|---|
| 148 | inline void push(oop obj); | 
|---|
| 149 | inline void push_objarray(oop objarray, size_t index); | 
|---|
| 150 | inline void push_region(size_t index); | 
|---|
| 151 |  | 
|---|
| 152 | // Check mark and maybe push on marking stack. | 
|---|
| 153 | template <typename T> inline void mark_and_push(T* p); | 
|---|
| 154 |  | 
|---|
| 155 | inline void follow_klass(Klass* klass); | 
|---|
| 156 |  | 
|---|
| 157 | void follow_class_loader(ClassLoaderData* klass); | 
|---|
| 158 |  | 
|---|
| 159 | // Access function for compaction managers | 
|---|
| 160 | static ParCompactionManager* gc_thread_compaction_manager(uint index); | 
|---|
| 161 |  | 
|---|
| 162 | static bool steal(int queue_num, oop& t); | 
|---|
| 163 | static bool steal_objarray(int queue_num, ObjArrayTask& t); | 
|---|
| 164 | static bool steal(int queue_num, size_t& region); | 
|---|
| 165 |  | 
|---|
| 166 | // Process tasks remaining on any marking stack | 
|---|
| 167 | void follow_marking_stacks(); | 
|---|
| 168 | inline bool marking_stacks_empty() const; | 
|---|
| 169 |  | 
|---|
| 170 | // Process tasks remaining on any stack | 
|---|
| 171 | void drain_region_stacks(); | 
|---|
| 172 |  | 
|---|
| 173 | void follow_contents(oop obj); | 
|---|
| 174 | void follow_array(objArrayOop array, int index); | 
|---|
| 175 |  | 
|---|
| 176 | void update_contents(oop obj); | 
|---|
| 177 |  | 
|---|
| 178 | class FollowStackClosure: public VoidClosure { | 
|---|
| 179 | private: | 
|---|
| 180 | ParCompactionManager* _compaction_manager; | 
|---|
| 181 | public: | 
|---|
| 182 | FollowStackClosure(ParCompactionManager* cm) : _compaction_manager(cm) { } | 
|---|
| 183 | virtual void do_void(); | 
|---|
| 184 | }; | 
|---|
| 185 | }; | 
|---|
| 186 |  | 
|---|
| 187 | inline ParCompactionManager* ParCompactionManager::manager_array(uint index) { | 
|---|
| 188 | assert(_manager_array != NULL, "access of NULL manager_array"); | 
|---|
| 189 | assert(index <= ParallelGCThreads, "out of range manager_array access"); | 
|---|
| 190 | return _manager_array[index]; | 
|---|
| 191 | } | 
|---|
| 192 |  | 
|---|
| 193 | bool ParCompactionManager::marking_stacks_empty() const { | 
|---|
| 194 | return _marking_stack.is_empty() && _objarray_stack.is_empty(); | 
|---|
| 195 | } | 
|---|
| 196 |  | 
|---|
| 197 | #endif // SHARE_GC_PARALLEL_PSCOMPACTIONMANAGER_HPP | 
|---|
| 198 |  | 
|---|