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/weakProcessor.hpp" 32 #include "gc/shared/weakProcessorPhases.hpp" 33 #include "gc/shared/weakProcessorPhaseTimes.hpp" 34 #include "gc/shared/workgroup.hpp" 35 #include "utilities/debug.hpp" 36 37 class BoolObjectClosure; 38 class OopClosure; 39 40 template<typename IsAlive> 41 class CountingIsAliveClosure : public BoolObjectClosure { 42 IsAlive* _inner; 43 44 size_t _num_dead; 45 size_t _num_total; 46 47 public: 48 CountingIsAliveClosure(IsAlive* cl) : _inner(cl), _num_dead(0), _num_total(0) { } 49 50 virtual bool do_object_b(oop obj) { 51 bool result = _inner->do_object_b(obj); 52 _num_dead += !result; 53 _num_total++; 54 return result; 55 } 56 57 size_t num_dead() const { return _num_dead; } 58 size_t num_total() const { return _num_total; } 59 }; 60 61 template <typename IsAlive, typename KeepAlive> 62 class CountingSkippedIsAliveClosure : public Closure { 63 CountingIsAliveClosure<IsAlive> _counting_is_alive; 64 KeepAlive* _keep_alive; 65 66 size_t _num_skipped; 67 68 public: 69 CountingSkippedIsAliveClosure(IsAlive* is_alive, KeepAlive* keep_alive) : 70 _counting_is_alive(is_alive), _keep_alive(keep_alive), _num_skipped(0) { } 71 72 void do_oop(oop* p) { 73 oop obj = *p; 74 if (obj == NULL) { 75 _num_skipped++; 76 return; 77 } 78 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 FOR_EACH_WEAK_PROCESSOR_PHASE(phase) { 99 if (WeakProcessorPhases::is_serial(phase)) { 100 CountingIsAliveClosure<IsAlive> cl(is_alive); 101 uint serial_index = WeakProcessorPhases::serial_index(phase); 102 if (_serial_phases_done.try_claim_task(serial_index)) { 103 WeakProcessorPhaseTimeTracker pt(_phase_times, phase); 104 WeakProcessorPhases::processor(phase)(&cl, keep_alive); 105 if (_phase_times != NULL) { 106 _phase_times->record_phase_items(phase, cl.num_dead(), cl.num_total()); 107 } 108 } 109 } else { 110 CountingSkippedIsAliveClosure<IsAlive, KeepAlive> cl(is_alive, keep_alive); 111 WeakProcessorPhaseTimeTracker pt(_phase_times, phase, worker_id); 112 uint storage_index = WeakProcessorPhases::oop_storage_index(phase); 113 _storage_states[storage_index].oops_do(&cl); 114 if (_phase_times != NULL) { 115 _phase_times->record_worker_items(worker_id, phase, cl.num_dead(), cl.num_total()); 116 } 117 if (WeakProcessorPhases::is_stringtable(phase)) { 118 StringTable::inc_dead_counter(cl.num_dead() + cl.num_skipped()); 119 } 120 } 121 } 122 123 _serial_phases_done.all_tasks_completed(_nworkers); 124 } 125 126 class WeakProcessor::GangTask : public AbstractGangTask { 127 Task _task; 128 BoolObjectClosure* _is_alive; 129 OopClosure* _keep_alive; 130 void (*_erased_do_work)(GangTask* task, uint worker_id); 131 132 template<typename IsAlive, typename KeepAlive> 133 static void erased_do_work(GangTask* task, uint worker_id) { 134 task->_task.work(worker_id, 135 static_cast<IsAlive*>(task->_is_alive), 136 static_cast<KeepAlive*>(task->_keep_alive)); 137 } 138 139 public: 140 template<typename IsAlive, typename KeepAlive> 141 GangTask(const char* name, 142 IsAlive* is_alive, 143 KeepAlive* keep_alive, 144 WeakProcessorPhaseTimes* phase_times, 145 uint nworkers) : 146 AbstractGangTask(name), 147 _task(phase_times, nworkers), 148 _is_alive(is_alive), 149 _keep_alive(keep_alive), 150 _erased_do_work(&erased_do_work<IsAlive, KeepAlive>) 151 {} 152 153 virtual void work(uint worker_id); 154 }; 155 156 template<typename IsAlive, typename KeepAlive> 157 void WeakProcessor::weak_oops_do(WorkGang* workers, 158 IsAlive* is_alive, 159 KeepAlive* keep_alive, 160 WeakProcessorPhaseTimes* phase_times) { 161 WeakProcessorTimeTracker tt(phase_times); 162 163 uint nworkers = ergo_workers(MIN2(workers->active_workers(), 164 phase_times->max_threads())); 165 166 GangTask task("Weak Processor", is_alive, keep_alive, phase_times, nworkers); 167 workers->run_task(&task, nworkers); 168 } 169 170 template<typename IsAlive, typename KeepAlive> 171 void WeakProcessor::weak_oops_do(WorkGang* workers, 172 IsAlive* is_alive, 173 KeepAlive* keep_alive, 174 uint indent_log) { 175 uint nworkers = ergo_workers(workers->active_workers()); 176 WeakProcessorPhaseTimes pt(nworkers); 177 weak_oops_do(workers, is_alive, keep_alive, &pt); 178 pt.log_print_phases(indent_log); 179 } 180 181 #endif // SHARE_GC_SHARED_WEAKPROCESSOR_INLINE_HPP