1 | /* |
2 | * Copyright (c) 2017, 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 | #include "precompiled.hpp" |
26 | #include "classfile/stringTable.hpp" |
27 | #include "gc/shared/oopStorage.inline.hpp" |
28 | #include "gc/shared/oopStorageParState.inline.hpp" |
29 | #include "gc/shared/weakProcessor.inline.hpp" |
30 | #include "gc/shared/weakProcessorPhases.hpp" |
31 | #include "gc/shared/weakProcessorPhaseTimes.hpp" |
32 | #include "memory/allocation.inline.hpp" |
33 | #include "memory/iterator.hpp" |
34 | #include "prims/resolvedMethodTable.hpp" |
35 | #include "runtime/globals.hpp" |
36 | #include "utilities/macros.hpp" |
37 | |
38 | template <typename Container> |
39 | class OopsDoAndReportCounts { |
40 | public: |
41 | void operator()(BoolObjectClosure* is_alive, OopClosure* keep_alive, WeakProcessorPhase phase) { |
42 | Container::reset_dead_counter(); |
43 | |
44 | CountingSkippedIsAliveClosure<BoolObjectClosure, OopClosure> cl(is_alive, keep_alive); |
45 | WeakProcessorPhases::oop_storage(phase)->oops_do(&cl); |
46 | |
47 | Container::inc_dead_counter(cl.num_dead() + cl.num_skipped()); |
48 | Container::finish_dead_counter(); |
49 | } |
50 | }; |
51 | |
52 | void WeakProcessor::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive) { |
53 | FOR_EACH_WEAK_PROCESSOR_PHASE(phase) { |
54 | if (WeakProcessorPhases::is_serial(phase)) { |
55 | WeakProcessorPhases::processor(phase)(is_alive, keep_alive); |
56 | } else { |
57 | if (WeakProcessorPhases::is_stringtable(phase)) { |
58 | OopsDoAndReportCounts<StringTable>()(is_alive, keep_alive, phase); |
59 | } else if (WeakProcessorPhases::is_resolved_method_table(phase)){ |
60 | OopsDoAndReportCounts<ResolvedMethodTable>()(is_alive, keep_alive, phase); |
61 | } else { |
62 | WeakProcessorPhases::oop_storage(phase)->weak_oops_do(is_alive, keep_alive); |
63 | } |
64 | } |
65 | } |
66 | } |
67 | |
68 | void WeakProcessor::oops_do(OopClosure* closure) { |
69 | AlwaysTrueClosure always_true; |
70 | weak_oops_do(&always_true, closure); |
71 | } |
72 | |
73 | uint WeakProcessor::ergo_workers(uint max_workers) { |
74 | // Ignore ParallelRefProcEnabled; that's for j.l.r.Reference processing. |
75 | if (ReferencesPerThread == 0) { |
76 | // Configuration says always use all the threads. |
77 | return max_workers; |
78 | } |
79 | |
80 | // One thread per ReferencesPerThread references (or fraction thereof) |
81 | // in the various OopStorage objects, bounded by max_threads. |
82 | // |
83 | // Serial phases are ignored in this calculation, because of the |
84 | // cost of running unnecessary threads. These phases are normally |
85 | // small or empty (assuming they are configured to exist at all), |
86 | // and development oriented, so not allocating any threads |
87 | // specifically for them is okay. |
88 | size_t ref_count = 0; |
89 | FOR_EACH_WEAK_PROCESSOR_OOP_STORAGE_PHASE(phase) { |
90 | ref_count += WeakProcessorPhases::oop_storage(phase)->allocation_count(); |
91 | } |
92 | |
93 | // +1 to (approx) round up the ref per thread division. |
94 | size_t nworkers = 1 + (ref_count / ReferencesPerThread); |
95 | nworkers = MIN2(nworkers, static_cast<size_t>(max_workers)); |
96 | return static_cast<uint>(nworkers); |
97 | } |
98 | |
99 | void WeakProcessor::Task::initialize() { |
100 | assert(_nworkers != 0, "must be" ); |
101 | assert(_phase_times == NULL || _nworkers <= _phase_times->max_threads(), |
102 | "nworkers (%u) exceeds max threads (%u)" , |
103 | _nworkers, _phase_times->max_threads()); |
104 | |
105 | if (_phase_times) { |
106 | _phase_times->set_active_workers(_nworkers); |
107 | } |
108 | |
109 | uint storage_count = WeakProcessorPhases::oop_storage_phase_count; |
110 | _storage_states = NEW_C_HEAP_ARRAY(StorageState, storage_count, mtGC); |
111 | |
112 | StorageState* states = _storage_states; |
113 | FOR_EACH_WEAK_PROCESSOR_OOP_STORAGE_PHASE(phase) { |
114 | OopStorage* storage = WeakProcessorPhases::oop_storage(phase); |
115 | new (states++) StorageState(storage, _nworkers); |
116 | } |
117 | StringTable::reset_dead_counter(); |
118 | ResolvedMethodTable::reset_dead_counter(); |
119 | } |
120 | |
121 | WeakProcessor::Task::Task(uint nworkers) : |
122 | _phase_times(NULL), |
123 | _nworkers(nworkers), |
124 | _serial_phases_done(WeakProcessorPhases::serial_phase_count), |
125 | _storage_states(NULL) |
126 | { |
127 | initialize(); |
128 | } |
129 | |
130 | WeakProcessor::Task::Task(WeakProcessorPhaseTimes* phase_times, uint nworkers) : |
131 | _phase_times(phase_times), |
132 | _nworkers(nworkers), |
133 | _serial_phases_done(WeakProcessorPhases::serial_phase_count), |
134 | _storage_states(NULL) |
135 | { |
136 | initialize(); |
137 | } |
138 | |
139 | WeakProcessor::Task::~Task() { |
140 | if (_storage_states != NULL) { |
141 | StorageState* states = _storage_states; |
142 | FOR_EACH_WEAK_PROCESSOR_OOP_STORAGE_PHASE(phase) { |
143 | states->StorageState::~StorageState(); |
144 | ++states; |
145 | } |
146 | FREE_C_HEAP_ARRAY(StorageState, _storage_states); |
147 | } |
148 | StringTable::finish_dead_counter(); |
149 | ResolvedMethodTable::finish_dead_counter(); |
150 | } |
151 | |
152 | void WeakProcessor::GangTask::work(uint worker_id) { |
153 | _erased_do_work(this, worker_id); |
154 | } |
155 | |