1 /* 2 * Copyright (c) 2018, 2020, 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 "gc/shared/weakProcessor.hpp" 29 30 #include "classfile/stringTable.hpp" 31 #include "gc/shared/oopStorage.inline.hpp" 32 #include "gc/shared/oopStorageParState.inline.hpp" 33 #include "gc/shared/oopStorageSet.hpp" 34 #include "gc/shared/weakProcessorTimes.hpp" 35 #include "gc/shared/workgroup.hpp" 36 #include "prims/resolvedMethodTable.hpp" 37 #include "utilities/debug.hpp" 38 #include "utilities/enumIterator.hpp" 39 40 class BoolObjectClosure; 41 class OopClosure; 42 43 template <typename IsAlive, typename KeepAlive> 44 class WeakProcessor::CountingClosure : public Closure { 45 IsAlive* _is_alive; 46 KeepAlive* _keep_alive; 47 size_t _old_dead; 48 size_t _new_dead; 49 size_t _live; 50 51 public: 52 CountingClosure(IsAlive* is_alive, KeepAlive* keep_alive) : 53 _is_alive(is_alive), 54 _keep_alive(keep_alive), 55 _old_dead(0), 56 _new_dead(0), 57 _live(0) 58 {} 59 60 void do_oop(oop* p) { 61 oop obj = *p; 62 if (obj == NULL) { 63 ++_old_dead; 64 } else if (_is_alive->do_object_b(obj)) { 65 _keep_alive->do_oop(p); 66 ++_live; 67 } else { 68 *p = NULL; 69 ++_new_dead; 70 } 71 } 72 73 size_t dead() const { return _old_dead + _new_dead; } 74 size_t new_dead() const { return _new_dead; } 75 size_t total() const { return dead() + _live; } 76 }; 77 78 template<typename IsAlive, typename KeepAlive> 79 void WeakProcessor::Task::work(uint worker_id, 80 IsAlive* is_alive, 81 KeepAlive* keep_alive) { 82 assert(worker_id < _nworkers, 83 "worker_id (%u) exceeds task's configured workers (%u)", 84 worker_id, _nworkers); 85 86 for (auto id : EnumRange<OopStorageSet::WeakId>()) { 87 CountingClosure<IsAlive, KeepAlive> cl(is_alive, keep_alive); 88 WeakProcessorParTimeTracker pt(_times, id, worker_id); 89 StorageState* cur_state = _storage_states.par_state(id); 90 assert(cur_state->storage() == OopStorageSet::storage(id), "invariant"); 91 cur_state->oops_do(&cl); 92 cur_state->increment_num_dead(cl.dead()); 93 if (_times != NULL) { 94 _times->record_worker_items(worker_id, id, cl.new_dead(), cl.total()); 95 } 96 } 97 } 98 99 class WeakProcessor::GangTask : public AbstractGangTask { 100 Task _task; 101 BoolObjectClosure* _is_alive; 102 OopClosure* _keep_alive; 103 void (*_erased_do_work)(GangTask* task, uint worker_id); 104 105 template<typename IsAlive, typename KeepAlive> 106 static void erased_do_work(GangTask* task, uint worker_id) { 107 task->_task.work(worker_id, 108 static_cast<IsAlive*>(task->_is_alive), 109 static_cast<KeepAlive*>(task->_keep_alive)); 110 } 111 112 public: 113 template<typename IsAlive, typename KeepAlive> 114 GangTask(const char* name, 115 IsAlive* is_alive, 116 KeepAlive* keep_alive, 117 WeakProcessorTimes* times, 118 uint nworkers) : 119 AbstractGangTask(name), 120 _task(times, nworkers), 121 _is_alive(is_alive), 122 _keep_alive(keep_alive), 123 _erased_do_work(&erased_do_work<IsAlive, KeepAlive>) 124 {} 125 126 virtual void work(uint worker_id); 127 void report_num_dead() { _task.report_num_dead(); } 128 }; 129 130 template<typename IsAlive, typename KeepAlive> 131 void WeakProcessor::weak_oops_do(WorkGang* workers, 132 IsAlive* is_alive, 133 KeepAlive* keep_alive, 134 WeakProcessorTimes* times) { 135 WeakProcessorTimeTracker tt(times); 136 137 uint nworkers = ergo_workers(MIN2(workers->total_workers(), 138 times->max_threads())); 139 140 GangTask task("Weak Processor", is_alive, keep_alive, times, nworkers); 141 workers->run_task(&task, nworkers); 142 task.report_num_dead(); 143 } 144 145 template<typename IsAlive, typename KeepAlive> 146 void WeakProcessor::weak_oops_do(WorkGang* workers, 147 IsAlive* is_alive, 148 KeepAlive* keep_alive, 149 uint indent_log) { 150 uint nworkers = ergo_workers(workers->total_workers()); 151 WeakProcessorTimes times(nworkers); 152 weak_oops_do(workers, is_alive, keep_alive, ×); 153 times.log_subtotals(indent_log); // Caller logs total if desired. 154 } 155 156 #endif // SHARE_GC_SHARED_WEAKPROCESSOR_INLINE_HPP