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
38template <typename Container>
39class OopsDoAndReportCounts {
40public:
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
52void 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
68void WeakProcessor::oops_do(OopClosure* closure) {
69 AlwaysTrueClosure always_true;
70 weak_oops_do(&always_true, closure);
71}
72
73uint 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
99void 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
121WeakProcessor::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
130WeakProcessor::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
139WeakProcessor::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
152void WeakProcessor::GangTask::work(uint worker_id) {
153 _erased_do_work(this, worker_id);
154}
155