Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp
41155 views
1
/*
2
* Copyright (c) 2014, 2021, 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/classLoaderDataGraph.hpp"
27
#include "classfile/stringTable.hpp"
28
#include "gc/shared/oopStorage.inline.hpp"
29
#include "gc/shared/oopStorageSet.hpp"
30
#include "gc/shared/strongRootsScope.hpp"
31
#include "jfr/leakprofiler/utilities/unifiedOopRef.inline.hpp"
32
#include "jfr/leakprofiler/checkpoint/rootResolver.hpp"
33
#include "jfr/utilities/jfrThreadIterator.hpp"
34
#include "memory/iterator.hpp"
35
#include "prims/jvmtiDeferredUpdates.hpp"
36
#include "oops/klass.hpp"
37
#include "oops/oop.hpp"
38
#include "prims/jvmtiThreadState.hpp"
39
#include "runtime/frame.inline.hpp"
40
#include "runtime/jniHandles.hpp"
41
#include "runtime/mutexLocker.hpp"
42
#include "runtime/stackFrameStream.inline.hpp"
43
#include "runtime/vframe_hp.hpp"
44
#include "services/management.hpp"
45
#include "utilities/enumIterator.hpp"
46
#include "utilities/growableArray.hpp"
47
48
class ReferenceLocateClosure : public OopClosure {
49
protected:
50
RootCallback& _callback;
51
RootCallbackInfo _info;
52
bool _complete;
53
54
void do_oop_shared(UnifiedOopRef ref);
55
56
public:
57
ReferenceLocateClosure(RootCallback& callback,
58
OldObjectRoot::System system,
59
OldObjectRoot::Type type,
60
const void* context) : _callback(callback),
61
_info(),
62
_complete(false) {
63
_info._high = NULL;
64
_info._low = NULL;
65
_info._system = system;
66
_info._type = type;
67
_info._context = context;
68
}
69
70
virtual void do_oop(oop* ref);
71
virtual void do_oop(narrowOop* ref);
72
73
bool complete() const {
74
return _complete;
75
}
76
};
77
78
void ReferenceLocateClosure::do_oop_shared(UnifiedOopRef ref) {
79
assert(!ref.is_null(), "invariant");
80
if (!_complete) {
81
_info._high = ref.addr<address>();
82
_complete = _callback.process(_info);
83
}
84
}
85
86
void ReferenceLocateClosure::do_oop(oop* ref) {
87
do_oop_shared(UnifiedOopRef::encode_in_native(ref));
88
}
89
90
void ReferenceLocateClosure::do_oop(narrowOop* ref) {
91
do_oop_shared(UnifiedOopRef::encode_in_native(ref));
92
}
93
94
class ReferenceToRootClosure : public StackObj {
95
private:
96
RootCallback& _callback;
97
RootCallbackInfo _info;
98
bool _complete;
99
100
bool do_cldg_roots();
101
bool do_oop_storage_roots();
102
bool do_string_table_roots();
103
104
bool do_roots();
105
106
public:
107
ReferenceToRootClosure(RootCallback& callback) : _callback(callback),
108
_info(),
109
_complete(false) {
110
_info._high = NULL;
111
_info._low = NULL;
112
_info._context = NULL;
113
_info._system = OldObjectRoot::_system_undetermined;
114
_info._type = OldObjectRoot::_type_undetermined;
115
116
assert_locked_or_safepoint(Threads_lock);
117
do_roots();
118
}
119
120
bool complete() const {
121
return _complete;
122
}
123
};
124
125
bool ReferenceToRootClosure::do_cldg_roots() {
126
assert(!complete(), "invariant");
127
ReferenceLocateClosure rlc(_callback, OldObjectRoot::_class_loader_data, OldObjectRoot::_type_undetermined, NULL);
128
CLDToOopClosure cldt_closure(&rlc, ClassLoaderData::_claim_none);
129
ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure);
130
return rlc.complete();
131
}
132
133
bool ReferenceToRootClosure::do_oop_storage_roots() {
134
using Range = EnumRange<OopStorageSet::StrongId>;
135
for (auto id : Range()) {
136
assert(!complete(), "invariant");
137
OopStorage* oop_storage = OopStorageSet::storage(id);
138
OldObjectRoot::Type type = JNIHandles::is_global_storage(oop_storage) ?
139
OldObjectRoot::_global_jni_handle :
140
OldObjectRoot::_global_oop_handle;
141
OldObjectRoot::System system = OldObjectRoot::System(OldObjectRoot::_strong_oop_storage_set_first + Range().index(id));
142
ReferenceLocateClosure rlc(_callback, system, type, NULL);
143
oop_storage->oops_do(&rlc);
144
if (rlc.complete()) {
145
return true;
146
}
147
}
148
return false;
149
}
150
151
bool ReferenceToRootClosure::do_roots() {
152
assert(!complete(), "invariant");
153
assert(OldObjectRoot::_system_undetermined == _info._system, "invariant");
154
assert(OldObjectRoot::_type_undetermined == _info._type, "invariant");
155
156
if (do_cldg_roots()) {
157
_complete = true;
158
return true;
159
}
160
161
if (do_oop_storage_roots()) {
162
_complete = true;
163
return true;
164
}
165
166
return false;
167
}
168
169
class ReferenceToThreadRootClosure : public StackObj {
170
private:
171
RootCallback& _callback;
172
bool _complete;
173
174
bool do_java_threads_oops(JavaThread* jt);
175
bool do_thread_roots(JavaThread* jt);
176
bool do_thread_stack_fast(JavaThread* jt);
177
bool do_thread_stack_detailed(JavaThread* jt);
178
bool do_thread_jni_handles(JavaThread* jt);
179
bool do_thread_handle_area(JavaThread* jt);
180
181
public:
182
ReferenceToThreadRootClosure(RootCallback& callback) :_callback(callback), _complete(false) {
183
assert_locked_or_safepoint(Threads_lock);
184
JfrJavaThreadIterator iter;
185
while (iter.has_next()) {
186
if (do_thread_roots(iter.next())) {
187
return;
188
}
189
}
190
}
191
192
bool complete() const {
193
return _complete;
194
}
195
};
196
197
bool ReferenceToThreadRootClosure::do_thread_handle_area(JavaThread* jt) {
198
assert(jt != NULL, "invariant");
199
assert(!complete(), "invariant");
200
ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_handle_area, jt);
201
jt->handle_area()->oops_do(&rcl);
202
return rcl.complete();
203
}
204
205
bool ReferenceToThreadRootClosure::do_thread_jni_handles(JavaThread* jt) {
206
assert(jt != NULL, "invariant");
207
assert(!complete(), "invariant");
208
209
ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_local_jni_handle, jt);
210
jt->active_handles()->oops_do(&rcl);
211
return rcl.complete();
212
}
213
214
bool ReferenceToThreadRootClosure::do_thread_stack_fast(JavaThread* jt) {
215
assert(jt != NULL, "invariant");
216
assert(!complete(), "invariant");
217
218
if (_callback.entries() == 0) {
219
_complete = true;
220
return true;
221
}
222
223
RootCallbackInfo info;
224
info._high = NULL;
225
info._low = NULL;
226
info._context = jt;
227
info._system = OldObjectRoot::_threads;
228
info._type = OldObjectRoot::_stack_variable;
229
230
for (int i = 0; i < _callback.entries(); ++i) {
231
const address adr = _callback.at(i).addr<address>();
232
if (jt->is_in_usable_stack(adr)) {
233
info._high = adr;
234
_complete = _callback.process(info);
235
if (_complete) {
236
return true;
237
}
238
}
239
}
240
assert(!complete(), "invariant");
241
return false;
242
}
243
244
bool ReferenceToThreadRootClosure::do_thread_stack_detailed(JavaThread* jt) {
245
assert(jt != NULL, "invariant");
246
assert(!complete(), "invariant");
247
248
ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_stack_variable, jt);
249
250
if (jt->has_last_Java_frame()) {
251
// Traverse the monitor chunks
252
MonitorChunk* chunk = jt->monitor_chunks();
253
for (; chunk != NULL; chunk = chunk->next()) {
254
chunk->oops_do(&rcl);
255
}
256
257
if (rcl.complete()) {
258
return true;
259
}
260
261
// Traverse the execution stack
262
for (StackFrameStream fst(jt, true /* update */, true /* process_frames */); !fst.is_done(); fst.next()) {
263
fst.current()->oops_do(&rcl, NULL, fst.register_map());
264
}
265
266
} // last java frame
267
268
if (rcl.complete()) {
269
return true;
270
}
271
272
GrowableArray<jvmtiDeferredLocalVariableSet*>* const list = JvmtiDeferredUpdates::deferred_locals(jt);
273
if (list != NULL) {
274
for (int i = 0; i < list->length(); i++) {
275
list->at(i)->oops_do(&rcl);
276
}
277
}
278
279
if (rcl.complete()) {
280
return true;
281
}
282
283
// Traverse instance variables at the end since the GC may be moving things
284
// around using this function
285
/*
286
* // can't reach these oop* from the outside
287
f->do_oop((oop*) &_vm_result);
288
f->do_oop((oop*) &_exception_oop);
289
f->do_oop((oop*) &_pending_async_exception);
290
*/
291
292
JvmtiThreadState* const jvmti_thread_state = jt->jvmti_thread_state();
293
if (jvmti_thread_state != NULL) {
294
jvmti_thread_state->oops_do(&rcl, NULL);
295
}
296
297
return rcl.complete();
298
}
299
300
bool ReferenceToThreadRootClosure::do_java_threads_oops(JavaThread* jt) {
301
assert(jt != NULL, "invariant");
302
assert(!complete(), "invariant");
303
304
ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_global_jni_handle, jt);
305
jt->oops_do(&rcl, NULL);
306
return rcl.complete();
307
}
308
309
bool ReferenceToThreadRootClosure::do_thread_roots(JavaThread* jt) {
310
assert(jt != NULL, "invariant");
311
312
if (do_thread_stack_fast(jt)) {
313
_complete = true;
314
return true;
315
}
316
317
if (do_thread_jni_handles(jt)) {
318
_complete = true;
319
return true;
320
}
321
322
if (do_thread_handle_area(jt)) {
323
_complete = true;
324
return true;
325
}
326
327
if (do_thread_stack_detailed(jt)) {
328
_complete = true;
329
return true;
330
}
331
332
return false;
333
}
334
335
class RootResolverMarkScope : public MarkScope {
336
};
337
338
void RootResolver::resolve(RootCallback& callback) {
339
RootResolverMarkScope mark_scope;
340
341
// thread local roots
342
ReferenceToThreadRootClosure rtrc(callback);
343
if (rtrc.complete()) {
344
return;
345
}
346
// system global roots
347
ReferenceToRootClosure rrc(callback);
348
}
349
350