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 T> 41 class CountingIsAliveClosure : public BoolObjectClosure { 42 T* _inner; 43 44 size_t _num_dead; 45 size_t _num_total; 46 47 public: 48 CountingIsAliveClosure(T* 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 void WeakProcessor::Task::work(uint worker_id, 63 IsAlive* is_alive, 64 KeepAlive* keep_alive) { 65 assert(worker_id < _nworkers, 66 "worker_id (%u) exceeds task's configured workers (%u)", 67 worker_id, _nworkers); 68 69 FOR_EACH_WEAK_PROCESSOR_PHASE(phase) { 70 CountingIsAliveClosure<IsAlive> cl(is_alive); 71 if (WeakProcessorPhases::is_serial(phase)) { 72 uint serial_index = WeakProcessorPhases::serial_index(phase); 73 if (_serial_phases_done.try_claim_task(serial_index)) { 74 WeakProcessorPhaseTimeTracker pt(_phase_times, phase); 75 WeakProcessorPhases::processor(phase)(&cl, keep_alive); 76 if (_phase_times != NULL) { 77 _phase_times->record_phase_items(phase, cl.num_dead(), cl.num_total()); 78 } 79 } 80 } else { 81 WeakProcessorPhaseTimeTracker pt(_phase_times, phase, worker_id); 82 uint storage_index = WeakProcessorPhases::oop_storage_index(phase); 83 _storage_states[storage_index].weak_oops_do(&cl, keep_alive); 84 if (_phase_times != NULL) { 85 _phase_times->record_worker_items(worker_id, phase, cl.num_dead(), cl.num_total()); 86 } 87 } 88 if (WeakProcessorPhases::is_stringtable(phase)) { 89 StringTable::inc_dead_counter(cl.num_dead()); 90 } 91 } 92 93 _serial_phases_done.all_tasks_completed(_nworkers); 94 } 95 96 class WeakProcessor::GangTask : public AbstractGangTask { 97 Task _task; 98 BoolObjectClosure* _is_alive; 99 OopClosure* _keep_alive; 100 void (*_erased_do_work)(GangTask* task, uint worker_id); 101 102 template<typename IsAlive, typename KeepAlive> 103 static void erased_do_work(GangTask* task, uint worker_id) { 104 task->_task.work(worker_id, 105 static_cast<IsAlive*>(task->_is_alive), 106 static_cast<KeepAlive*>(task->_keep_alive)); 107 } 108 109 public: 110 template<typename IsAlive, typename KeepAlive> 111 GangTask(const char* name, 112 IsAlive* is_alive, 113 KeepAlive* keep_alive, 114 WeakProcessorPhaseTimes* phase_times, 115 uint nworkers) : 116 AbstractGangTask(name), 117 _task(phase_times, nworkers), 118 _is_alive(is_alive), 119 _keep_alive(keep_alive), 120 _erased_do_work(&erased_do_work<IsAlive, KeepAlive>) 121 {} 122 123 virtual void work(uint worker_id); 124 }; 125 126 template<typename IsAlive, typename KeepAlive> 127 void WeakProcessor::weak_oops_do(WorkGang* workers, 128 IsAlive* is_alive, 129 KeepAlive* keep_alive, 130 WeakProcessorPhaseTimes* phase_times) { 131 WeakProcessorTimeTracker tt(phase_times); 132 133 uint nworkers = ergo_workers(MIN2(workers->active_workers(), 134 phase_times->max_threads())); 135 136 GangTask task("Weak Processor", is_alive, keep_alive, phase_times, nworkers); 137 workers->run_task(&task, nworkers); 138 } 139 140 template<typename IsAlive, typename KeepAlive> 141 void WeakProcessor::weak_oops_do(WorkGang* workers, 142 IsAlive* is_alive, 143 KeepAlive* keep_alive, 144 uint indent_log) { 145 uint nworkers = ergo_workers(workers->active_workers()); 146 WeakProcessorPhaseTimes pt(nworkers); 147 weak_oops_do(workers, is_alive, keep_alive, &pt); 148 pt.log_print_phases(indent_log); 149 } 150 151 #endif // SHARE_GC_SHARED_WEAKPROCESSOR_INLINE_HPP