Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/jfr/leakprofiler/checkpoint/rootResolver.cpp
48074 views
1
/*
2
* Copyright (c) 2014, 2018, 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_interface/strongRootsScope.hpp"
28
#include "jfr/leakprofiler/utilities/unifiedOop.hpp"
29
#include "jfr/leakprofiler/checkpoint/rootResolver.hpp"
30
#include "memory/iterator.hpp"
31
#include "oops/klass.hpp"
32
#include "oops/markOop.hpp"
33
#include "oops/oop.hpp"
34
#include "prims/jvmtiThreadState.hpp"
35
#include "prims/privilegedStack.hpp"
36
#include "runtime/frame.inline.hpp"
37
#include "runtime/mutexLocker.hpp"
38
#include "runtime/vframe_hp.hpp"
39
#include "services/management.hpp"
40
#include "utilities/growableArray.hpp"
41
42
class ReferenceLocateClosure : public OopClosure {
43
protected:
44
RootCallback& _callback;
45
RootCallbackInfo _info;
46
bool _complete;
47
48
void do_oop_shared(const void* ref);
49
50
public:
51
ReferenceLocateClosure(RootCallback& callback,
52
OldObjectRoot::System system,
53
OldObjectRoot::Type type,
54
const void* context) : _callback(callback),
55
_info(),
56
_complete(false) {
57
_info._high = NULL;
58
_info._low = NULL;
59
_info._system = system;
60
_info._type = type;
61
_info._context = context;
62
}
63
64
virtual void do_oop(oop* ref);
65
virtual void do_oop(narrowOop* ref);
66
67
bool complete() const {
68
return _complete;
69
}
70
};
71
72
void ReferenceLocateClosure::do_oop_shared(const void* ref) {
73
assert(ref != NULL, "invariant");
74
if (!_complete) {
75
_info._high = ref;
76
_complete = _callback.process(_info);
77
}
78
}
79
80
void ReferenceLocateClosure::do_oop(oop* ref) {
81
do_oop_shared(ref);
82
}
83
84
void ReferenceLocateClosure::do_oop(narrowOop* ref) {
85
do_oop_shared(ref);
86
}
87
88
class ReferenceToRootClosure : public StackObj {
89
private:
90
RootCallback& _callback;
91
RootCallbackInfo _info;
92
bool _complete;
93
94
bool do_cldg_roots();
95
bool do_object_synchronizer_roots();
96
bool do_universe_roots();
97
bool do_jni_handle_roots();
98
bool do_jvmti_roots();
99
bool do_system_dictionary_roots();
100
bool do_management_roots();
101
bool do_string_table_roots();
102
// bool do_aot_loader_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);
129
ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure);
130
return rlc.complete();
131
}
132
133
bool ReferenceToRootClosure::do_object_synchronizer_roots() {
134
assert(!complete(), "invariant");
135
ReferenceLocateClosure rlc(_callback, OldObjectRoot::_object_synchronizer, OldObjectRoot::_type_undetermined, NULL);
136
ObjectSynchronizer::oops_do(&rlc);
137
return rlc.complete();
138
}
139
140
bool ReferenceToRootClosure::do_universe_roots() {
141
assert(!complete(), "invariant");
142
ReferenceLocateClosure rlc(_callback, OldObjectRoot::_universe, OldObjectRoot::_type_undetermined, NULL);
143
Universe::oops_do(&rlc);
144
return rlc.complete();
145
}
146
147
bool ReferenceToRootClosure::do_jni_handle_roots() {
148
assert(!complete(), "invariant");
149
ReferenceLocateClosure rlc(_callback, OldObjectRoot::_global_jni_handles, OldObjectRoot::_global_jni_handle, NULL);
150
JNIHandles::oops_do(&rlc);
151
return rlc.complete();
152
}
153
154
bool ReferenceToRootClosure::do_jvmti_roots() {
155
assert(!complete(), "invariant");
156
ReferenceLocateClosure rlc(_callback, OldObjectRoot::_jvmti, OldObjectRoot::_global_jni_handle, NULL);
157
JvmtiExport::oops_do(&rlc);
158
return rlc.complete();
159
}
160
161
bool ReferenceToRootClosure::do_system_dictionary_roots() {
162
assert(!complete(), "invariant");
163
ReferenceLocateClosure rlc(_callback, OldObjectRoot::_system_dictionary, OldObjectRoot::_type_undetermined, NULL);
164
SystemDictionary::oops_do(&rlc);
165
return rlc.complete();
166
}
167
168
bool ReferenceToRootClosure::do_management_roots() {
169
assert(!complete(), "invariant");
170
ReferenceLocateClosure rlc(_callback, OldObjectRoot::_management, OldObjectRoot::_type_undetermined, NULL);
171
Management::oops_do(&rlc);
172
return rlc.complete();
173
}
174
175
bool ReferenceToRootClosure::do_string_table_roots() {
176
assert(!complete(), "invariant");
177
ReferenceLocateClosure rlc(_callback, OldObjectRoot::_string_table, OldObjectRoot::_type_undetermined, NULL);
178
StringTable::oops_do(&rlc);
179
return rlc.complete();
180
}
181
182
//bool ReferenceToRootClosure::do_aot_loader_roots() {
183
// assert(!complete(), "invariant");
184
// ReferenceLocateClosure rcl(_callback, OldObjectRoot::_aot, OldObjectRoot::_type_undetermined, NULL);
185
// AOTLoader::oops_do(&rcl);
186
// return rcl.complete();
187
//}
188
189
bool ReferenceToRootClosure::do_roots() {
190
assert(!complete(), "invariant");
191
assert(OldObjectRoot::_system_undetermined == _info._system, "invariant");
192
assert(OldObjectRoot::_type_undetermined == _info._type, "invariant");
193
194
if (do_cldg_roots()) {
195
_complete = true;
196
return true;
197
}
198
199
if (do_object_synchronizer_roots()) {
200
_complete = true;
201
return true;
202
}
203
204
if (do_universe_roots()) {
205
_complete = true;
206
return true;
207
}
208
209
if (do_jni_handle_roots()) {
210
_complete = true;
211
return true;
212
}
213
214
if (do_jvmti_roots()) {
215
_complete = true;
216
return true;
217
}
218
219
if (do_system_dictionary_roots()) {
220
_complete = true;
221
return true;
222
}
223
224
if (do_management_roots()) {
225
_complete = true;
226
return true;
227
}
228
229
if (do_string_table_roots()) {
230
_complete = true;
231
return true;
232
}
233
234
// if (do_aot_loader_roots()) {
235
// _complete = true;
236
// return true;
237
// }
238
239
return false;
240
}
241
242
class ReferenceToThreadRootClosure : public StackObj {
243
private:
244
RootCallback& _callback;
245
bool _complete;
246
247
bool do_java_threads_oops(JavaThread* jt);
248
bool do_thread_roots(JavaThread* jt);
249
bool do_thread_stack_fast(JavaThread* jt);
250
bool do_thread_stack_detailed(JavaThread* jt);
251
bool do_thread_jni_handles(JavaThread* jt);
252
bool do_thread_handle_area(JavaThread* jt);
253
254
public:
255
ReferenceToThreadRootClosure(RootCallback& callback) :_callback(callback), _complete(false) {
256
assert_locked_or_safepoint(Threads_lock);
257
for (JavaThread *thread = Threads::first(); thread != NULL; thread = thread->next()) {
258
if (do_thread_roots(thread)) {
259
return;
260
}
261
}
262
}
263
264
bool complete() const {
265
return _complete;
266
}
267
};
268
269
bool ReferenceToThreadRootClosure::do_thread_handle_area(JavaThread* jt) {
270
assert(jt != NULL, "invariant");
271
assert(!complete(), "invariant");
272
ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_handle_area, jt);
273
jt->handle_area()->oops_do(&rcl);
274
return rcl.complete();
275
}
276
277
bool ReferenceToThreadRootClosure::do_thread_jni_handles(JavaThread* jt) {
278
assert(jt != NULL, "invariant");
279
assert(!complete(), "invariant");
280
281
ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_local_jni_handle, jt);
282
jt->active_handles()->oops_do(&rcl);
283
return rcl.complete();
284
}
285
286
bool ReferenceToThreadRootClosure::do_thread_stack_fast(JavaThread* jt) {
287
assert(jt != NULL, "invariant");
288
assert(!complete(), "invariant");
289
290
if (_callback.entries() == 0) {
291
_complete = true;
292
return true;
293
}
294
295
RootCallbackInfo info;
296
info._high = NULL;
297
info._low = NULL;
298
info._context = jt;
299
info._system = OldObjectRoot::_threads;
300
info._type = OldObjectRoot::_stack_variable;
301
302
for (int i = 0; i < _callback.entries(); ++i) {
303
const address adr = (address)_callback.at(i);
304
if (jt->is_in_usable_stack(adr)) {
305
info._high = adr;
306
_complete = _callback.process(info);
307
if (_complete) {
308
return true;
309
}
310
}
311
}
312
assert(!complete(), "invariant");
313
return false;
314
}
315
316
bool ReferenceToThreadRootClosure::do_thread_stack_detailed(JavaThread* jt) {
317
assert(jt != NULL, "invariant");
318
assert(!complete(), "invariant");
319
320
ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_stack_variable, jt);
321
322
if (jt->has_last_Java_frame()) {
323
PrivilegedElement* const pelem = jt->privileged_stack_top();
324
if (pelem != NULL) {
325
pelem->oops_do(&rcl);
326
if (rcl.complete()) {
327
return true;
328
}
329
}
330
331
// traverse the registered growable array gc_array
332
// can't do this as it is not reachable from outside
333
334
// Traverse the monitor chunks
335
MonitorChunk* chunk = jt->monitor_chunks();
336
for (; chunk != NULL; chunk = chunk->next()) {
337
chunk->oops_do(&rcl);
338
}
339
340
if (rcl.complete()) {
341
return true;
342
}
343
344
// Traverse the execution stack
345
for (StackFrameStream fst(jt); !fst.is_done(); fst.next()) {
346
// XXX set CLDClosure to NULL
347
fst.current()->oops_do(&rcl, NULL, NULL, fst.register_map());
348
}
349
350
} // last java frame
351
352
if (rcl.complete()) {
353
return true;
354
}
355
356
GrowableArray<jvmtiDeferredLocalVariableSet*>* const list = jt->deferred_locals();
357
if (list != NULL) {
358
for (int i = 0; i < list->length(); i++) {
359
list->at(i)->oops_do(&rcl);
360
}
361
}
362
363
if (rcl.complete()) {
364
return true;
365
}
366
367
// Traverse instance variables at the end since the GC may be moving things
368
// around using this function
369
/*
370
* // can't reach these oop* from the outside
371
f->do_oop((oop*) &_threadObj);
372
f->do_oop((oop*) &_vm_result);
373
f->do_oop((oop*) &_exception_oop);
374
f->do_oop((oop*) &_pending_async_exception);
375
*/
376
377
JvmtiThreadState* const jvmti_thread_state = jt->jvmti_thread_state();
378
if (jvmti_thread_state != NULL) {
379
jvmti_thread_state->oops_do(&rcl);
380
}
381
382
return rcl.complete();
383
}
384
385
bool ReferenceToThreadRootClosure::do_java_threads_oops(JavaThread* jt) {
386
assert(jt != NULL, "invariant");
387
assert(!complete(), "invariant");
388
389
ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_global_jni_handle, jt);
390
jt->oops_do(&rcl, NULL, NULL);
391
return rcl.complete();
392
}
393
394
bool ReferenceToThreadRootClosure::do_thread_roots(JavaThread* jt) {
395
assert(jt != NULL, "invariant");
396
397
if (do_thread_stack_fast(jt)) {
398
_complete = true;
399
return true;
400
}
401
402
if (do_thread_jni_handles(jt)) {
403
_complete = true;
404
return true;
405
}
406
407
if (do_thread_handle_area(jt)) {
408
_complete = true;
409
return true;
410
}
411
412
if (do_thread_stack_detailed(jt)) {
413
_complete = true;
414
return true;
415
}
416
417
return false;
418
}
419
420
class RootResolverMarkScope : public MarkingCodeBlobClosure::MarkScope {
421
};
422
423
void RootResolver::resolve(RootCallback& callback) {
424
425
// Need to clear cld claim bit before starting
426
ClassLoaderDataGraph::clear_claimed_marks();
427
RootResolverMarkScope mark_scope;
428
429
// thread local roots
430
ReferenceToThreadRootClosure rtrc(callback);
431
if (rtrc.complete()) {
432
return;
433
}
434
// system global roots
435
ReferenceToRootClosure rrc(callback);
436
}
437
438