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 ObjectMonitor::maybe_deflate_dead(p); 69 *p = NULL; 70 ++_new_dead; 71 } 72 } 73 74 size_t dead() const { return _old_dead + _new_dead; } 75 size_t new_dead() const { return _new_dead; } 76 size_t total() const { return dead() + _live; } 77 }; 78 79 template<typename IsAlive, typename KeepAlive> 80 void WeakProcessor::Task::work(uint worker_id, 81 IsAlive* is_alive, 82 KeepAlive* keep_alive) { 83 assert(worker_id < _nworkers, 84 "worker_id (%u) exceeds task's configured workers (%u)", 85 worker_id, _nworkers); 86 87 for (auto id : EnumRange<OopStorageSet::WeakId>()) { 88 CountingClosure<IsAlive, KeepAlive> cl(is_alive, keep_alive); 89 WeakProcessorParTimeTracker pt(_times, id, worker_id); 90 StorageState* cur_state = _storage_states.par_state(id); 91 assert(cur_state->storage() == OopStorageSet::storage(id), "invariant"); 92 cur_state->oops_do(&cl); 93 cur_state->increment_num_dead(cl.dead()); 94 if (_times != NULL) { 95 _times->record_worker_items(worker_id, id, cl.new_dead(), cl.total()); 96 } 97 } 98 } 99 100 class WeakProcessor::GangTask : public AbstractGangTask { 101 Task _task; 102 BoolObjectClosure* _is_alive; 103 OopClosure* _keep_alive; 104 void (*_erased_do_work)(GangTask* task, uint worker_id); 105 106 template<typename IsAlive, typename KeepAlive> 107 static void erased_do_work(GangTask* task, uint worker_id) { 108 task->_task.work(worker_id, 109 static_cast<IsAlive*>(task->_is_alive), 110 static_cast<KeepAlive*>(task->_keep_alive)); 111 } 112 113 public: 114 template<typename IsAlive, typename KeepAlive> 115 GangTask(const char* name, 116 IsAlive* is_alive, 117 KeepAlive* keep_alive, 118 WeakProcessorTimes* times, 119 uint nworkers) : 120 AbstractGangTask(name), 121 _task(times, nworkers), 122 _is_alive(is_alive), 123 _keep_alive(keep_alive), 124 _erased_do_work(&erased_do_work<IsAlive, KeepAlive>) 125 {} 126 127 virtual void work(uint worker_id); 128 void report_num_dead() { _task.report_num_dead(); } 129 }; 130 131 template<typename IsAlive, typename KeepAlive> 132 void WeakProcessor::weak_oops_do(WorkGang* workers, 133 IsAlive* is_alive, 134 KeepAlive* keep_alive, 135 WeakProcessorTimes* times) { 136 WeakProcessorTimeTracker tt(times); 137 138 uint nworkers = ergo_workers(MIN2(workers->total_workers(), 139 times->max_threads())); 140 141 GangTask task("Weak Processor", is_alive, keep_alive, times, nworkers); 142 workers->run_task(&task, nworkers); 143 task.report_num_dead(); 144 } 145 146 template<typename IsAlive, typename KeepAlive> 147 void WeakProcessor::weak_oops_do(WorkGang* workers, 148 IsAlive* is_alive, 149 KeepAlive* keep_alive, 150 uint indent_log) { 151 uint nworkers = ergo_workers(workers->total_workers()); 152 WeakProcessorTimes times(nworkers); 153 weak_oops_do(workers, is_alive, keep_alive, ×); 154 times.log_subtotals(indent_log); // Caller logs total if desired. 155 } 156 157 #endif // SHARE_GC_SHARED_WEAKPROCESSOR_INLINE_HPP