1 /* 2 * Copyright (c) 2018, 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_SHARED_WEAKPROCESSOR_INLINE_HPP 26 #define SHARE_GC_SHARED_WEAKPROCESSOR_INLINE_HPP 27 28 #include "classfile/stringTable.hpp" 29 #include "gc/shared/oopStorage.inline.hpp" 30 #include "gc/shared/oopStorageParState.inline.hpp" 31 #include "gc/shared/oopStorageSet.hpp" 32 #include "gc/shared/weakProcessor.hpp" 33 #include "gc/shared/weakProcessorPhases.hpp" 34 #include "gc/shared/weakProcessorPhaseTimes.hpp" 35 #include "gc/shared/workgroup.hpp" 36 #include "prims/resolvedMethodTable.hpp" 37 #include "utilities/debug.hpp" 38 39 class BoolObjectClosure; 40 class OopClosure; 41 42 template<typename IsAlive> 43 class CountingIsAliveClosure : public BoolObjectClosure { 44 IsAlive* _inner; 45 46 size_t _num_dead; 47 size_t _num_total; 48 49 public: 50 CountingIsAliveClosure(IsAlive* cl) : _inner(cl), _num_dead(0), _num_total(0) { } 51 52 virtual bool do_object_b(oop obj) { 53 bool result = _inner->do_object_b(obj); 54 _num_dead += !result; 55 _num_total++; 56 return result; 57 } 58 59 size_t num_dead() const { return _num_dead; } 60 size_t num_total() const { return _num_total; } 61 }; 62 63 template <typename IsAlive, typename KeepAlive> 64 class CountingSkippedIsAliveClosure : public Closure { 65 CountingIsAliveClosure<IsAlive> _counting_is_alive; 66 KeepAlive* _keep_alive; 67 68 size_t _num_skipped; 69 70 public: 71 CountingSkippedIsAliveClosure(IsAlive* is_alive, KeepAlive* keep_alive) : 72 _counting_is_alive(is_alive), _keep_alive(keep_alive), _num_skipped(0) { } 73 74 void do_oop(oop* p) { 75 oop obj = *p; 76 if (obj == NULL) { 77 _num_skipped++; 78 } else if (_counting_is_alive.do_object_b(obj)) { 79 _keep_alive->do_oop(p); 80 } else { 81 *p = NULL; 82 } 83 } 84 85 size_t num_dead() const { return _counting_is_alive.num_dead(); } 86 size_t num_skipped() const { return _num_skipped; } 87 size_t num_total() const { return _counting_is_alive.num_total() + num_skipped(); } 88 }; 89 90 template<typename IsAlive, typename KeepAlive> 91 void WeakProcessor::Task::work(uint worker_id, 92 IsAlive* is_alive, 93 KeepAlive* keep_alive) { 94 assert(worker_id < _nworkers, 95 "worker_id (%u) exceeds task's configured workers (%u)", 96 worker_id, _nworkers); 97 98 typedef WeakProcessorPhases::Iterator Iterator; 99 100 for (Iterator it = WeakProcessorPhases::serial_iterator(); !it.is_end(); ++it) { 101 WeakProcessorPhase phase = *it; 102 CountingIsAliveClosure<IsAlive> cl(is_alive); 103 uint serial_index = WeakProcessorPhases::serial_index(phase); 104 if (_serial_phases_done.try_claim_task(serial_index)) { 105 WeakProcessorPhaseTimeTracker pt(_phase_times, phase); 106 WeakProcessorPhases::processor(phase)(&cl, keep_alive); 107 if (_phase_times != NULL) { 108 _phase_times->record_phase_items(phase, cl.num_dead(), cl.num_total()); 109 } 110 } 111 } 112 113 for (Iterator it = WeakProcessorPhases::oopstorage_iterator(); !it.is_end(); ++it) { 114 WeakProcessorPhase phase = *it; 115 CountingSkippedIsAliveClosure<IsAlive, KeepAlive> cl(is_alive, keep_alive); 116 WeakProcessorPhaseTimeTracker pt(_phase_times, phase, worker_id); 117 uint oopstorage_index = WeakProcessorPhases::oopstorage_index(phase); 118 StorageState& cur_state = _storage_states[oopstorage_index]; 119 cur_state.oops_do(&cl); 120 if (_phase_times != NULL) { 121 _phase_times->record_worker_items(worker_id, phase, cl.num_dead(), cl.num_total()); 122 } 123 const OopStorage* cur_storage = cur_state.storage(); 124 if (cur_storage->can_notify()) { 125 cur_state.increment_dead_counter(cl.num_dead()); 126 } 127 } 128 129 _serial_phases_done.all_tasks_completed(_nworkers); 130 } 131 132 class WeakProcessor::GangTask : public AbstractGangTask { 133 Task _task; 134 BoolObjectClosure* _is_alive; 135 OopClosure* _keep_alive; 136 void (*_erased_do_work)(GangTask* task, uint worker_id); 137 138 template<typename IsAlive, typename KeepAlive> 139 static void erased_do_work(GangTask* task, uint worker_id) { 140 task->_task.work(worker_id, 141 static_cast<IsAlive*>(task->_is_alive), 142 static_cast<KeepAlive*>(task->_keep_alive)); 143 } 144 145 public: 146 template<typename IsAlive, typename KeepAlive> 147 GangTask(const char* name, 148 IsAlive* is_alive, 149 KeepAlive* keep_alive, 150 WeakProcessorPhaseTimes* phase_times, 151 uint nworkers) : 152 AbstractGangTask(name), 153 _task(phase_times, nworkers), 154 _is_alive(is_alive), 155 _keep_alive(keep_alive), 156 _erased_do_work(&erased_do_work<IsAlive, KeepAlive>) 157 {} 158 159 virtual void work(uint worker_id); 160 }; 161 162 template<typename IsAlive, typename KeepAlive> 163 void WeakProcessor::weak_oops_do(WorkGang* workers, 164 IsAlive* is_alive, 165 KeepAlive* keep_alive, 166 WeakProcessorPhaseTimes* phase_times) { 167 WeakProcessorTimeTracker tt(phase_times); 168 169 uint nworkers = ergo_workers(MIN2(workers->active_workers(), 170 phase_times->max_threads())); 171 172 GangTask task("Weak Processor", is_alive, keep_alive, phase_times, nworkers); 173 workers->run_task(&task, nworkers); 174 } 175 176 template<typename IsAlive, typename KeepAlive> 177 void WeakProcessor::weak_oops_do(WorkGang* workers, 178 IsAlive* is_alive, 179 KeepAlive* keep_alive, 180 uint indent_log) { 181 uint nworkers = ergo_workers(workers->active_workers()); 182 WeakProcessorPhaseTimes pt(nworkers); 183 weak_oops_do(workers, is_alive, keep_alive, &pt); 184 pt.log_print_phases(indent_log); 185 } 186 187 #endif // SHARE_GC_SHARED_WEAKPROCESSOR_INLINE_HPP