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#include "precompiled.hpp"
26#include "classfile/symbolTable.hpp"
27#include "classfile/stringTable.hpp"
28#include "code/codeCache.hpp"
29#include "gc/shared/parallelCleaning.hpp"
30#include "logging/log.hpp"
31#include "memory/resourceArea.hpp"
32#include "logging/log.hpp"
33#if INCLUDE_JVMCI
34#include "jvmci/jvmci.hpp"
35#endif
36
37StringDedupCleaningTask::StringDedupCleaningTask(BoolObjectClosure* is_alive,
38 OopClosure* keep_alive,
39 bool resize_table) :
40 AbstractGangTask("String Dedup Cleaning"),
41 _dedup_closure(is_alive, keep_alive) {
42
43 if (StringDedup::is_enabled()) {
44 StringDedup::gc_prologue(resize_table);
45 }
46}
47
48StringDedupCleaningTask::~StringDedupCleaningTask() {
49 if (StringDedup::is_enabled()) {
50 StringDedup::gc_epilogue();
51 }
52}
53
54void StringDedupCleaningTask::work(uint worker_id) {
55 if (StringDedup::is_enabled()) {
56 StringDedup::parallel_unlink(&_dedup_closure, worker_id);
57 }
58}
59
60CodeCacheUnloadingTask::CodeCacheUnloadingTask(uint num_workers, BoolObjectClosure* is_alive, bool unloading_occurred) :
61 _unloading_scope(is_alive),
62 _unloading_occurred(unloading_occurred),
63 _num_workers(num_workers),
64 _first_nmethod(NULL),
65 _claimed_nmethod(NULL) {
66 // Get first alive nmethod
67 CompiledMethodIterator iter(CompiledMethodIterator::only_alive);
68 if(iter.next()) {
69 _first_nmethod = iter.method();
70 }
71 _claimed_nmethod = _first_nmethod;
72}
73
74CodeCacheUnloadingTask::~CodeCacheUnloadingTask() {
75 CodeCache::verify_clean_inline_caches();
76 CodeCache::verify_icholder_relocations();
77}
78
79void CodeCacheUnloadingTask::claim_nmethods(CompiledMethod** claimed_nmethods, int *num_claimed_nmethods) {
80 CompiledMethod* first;
81 CompiledMethodIterator last(CompiledMethodIterator::only_alive);
82
83 do {
84 *num_claimed_nmethods = 0;
85
86 first = _claimed_nmethod;
87 last = CompiledMethodIterator(CompiledMethodIterator::only_alive, first);
88
89 if (first != NULL) {
90
91 for (int i = 0; i < MaxClaimNmethods; i++) {
92 if (!last.next()) {
93 break;
94 }
95 claimed_nmethods[i] = last.method();
96 (*num_claimed_nmethods)++;
97 }
98 }
99
100 } while (Atomic::cmpxchg(last.method(), &_claimed_nmethod, first) != first);
101}
102
103void CodeCacheUnloadingTask::work(uint worker_id) {
104 // The first nmethods is claimed by the first worker.
105 if (worker_id == 0 && _first_nmethod != NULL) {
106 _first_nmethod->do_unloading(_unloading_occurred);
107 _first_nmethod = NULL;
108 }
109
110 int num_claimed_nmethods;
111 CompiledMethod* claimed_nmethods[MaxClaimNmethods];
112
113 while (true) {
114 claim_nmethods(claimed_nmethods, &num_claimed_nmethods);
115
116 if (num_claimed_nmethods == 0) {
117 break;
118 }
119
120 for (int i = 0; i < num_claimed_nmethods; i++) {
121 claimed_nmethods[i]->do_unloading(_unloading_occurred);
122 }
123 }
124}
125
126KlassCleaningTask::KlassCleaningTask() :
127 _clean_klass_tree_claimed(0),
128 _klass_iterator() {
129}
130
131bool KlassCleaningTask::claim_clean_klass_tree_task() {
132 if (_clean_klass_tree_claimed) {
133 return false;
134 }
135
136 return Atomic::cmpxchg(1, &_clean_klass_tree_claimed, 0) == 0;
137}
138
139InstanceKlass* KlassCleaningTask::claim_next_klass() {
140 Klass* klass;
141 do {
142 klass =_klass_iterator.next_klass();
143 } while (klass != NULL && !klass->is_instance_klass());
144
145 // this can be null so don't call InstanceKlass::cast
146 return static_cast<InstanceKlass*>(klass);
147}
148
149void KlassCleaningTask::work() {
150 ResourceMark rm;
151
152 // One worker will clean the subklass/sibling klass tree.
153 if (claim_clean_klass_tree_task()) {
154 Klass::clean_subklass_tree();
155 }
156
157 // All workers will help cleaning the classes,
158 InstanceKlass* klass;
159 while ((klass = claim_next_klass()) != NULL) {
160 clean_klass(klass);
161 }
162}
163
164#if INCLUDE_JVMCI
165JVMCICleaningTask::JVMCICleaningTask() :
166 _cleaning_claimed(0) {
167}
168
169bool JVMCICleaningTask::claim_cleaning_task() {
170 if (_cleaning_claimed) {
171 return false;
172 }
173
174 return Atomic::cmpxchg(1, &_cleaning_claimed, 0) == 0;
175}
176
177void JVMCICleaningTask::work(bool unloading_occurred) {
178 // One worker will clean JVMCI metadata handles.
179 if (unloading_occurred && EnableJVMCI && claim_cleaning_task()) {
180 JVMCI::do_unloading(unloading_occurred);
181 }
182}
183#endif // INCLUDE_JVMCI
184
185ParallelCleaningTask::ParallelCleaningTask(BoolObjectClosure* is_alive,
186 uint num_workers,
187 bool unloading_occurred,
188 bool resize_dedup_table) :
189 AbstractGangTask("Parallel Cleaning"),
190 _unloading_occurred(unloading_occurred),
191 _string_dedup_task(is_alive, NULL, resize_dedup_table),
192 _code_cache_task(num_workers, is_alive, unloading_occurred),
193 JVMCI_ONLY(_jvmci_cleaning_task() COMMA)
194 _klass_cleaning_task() {
195}
196
197// The parallel work done by all worker threads.
198void ParallelCleaningTask::work(uint worker_id) {
199 // Clean JVMCI metadata handles.
200 // Execute this task first because it is serial task.
201 JVMCI_ONLY(_jvmci_cleaning_task.work(_unloading_occurred);)
202
203 // Do first pass of code cache cleaning.
204 _code_cache_task.work(worker_id);
205
206 // Clean the string dedup data structures.
207 _string_dedup_task.work(worker_id);
208
209 // Clean all klasses that were not unloaded.
210 // The weak metadata in klass doesn't need to be
211 // processed if there was no unloading.
212 if (_unloading_occurred) {
213 _klass_cleaning_task.work();
214 }
215}
216