Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.cpp
41153 views
1
/*
2
* Copyright (c) 2014, 2020, 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 "jfr/leakprofiler/chains/bitset.inline.hpp"
27
#include "jfr/leakprofiler/chains/dfsClosure.hpp"
28
#include "jfr/leakprofiler/chains/edge.hpp"
29
#include "jfr/leakprofiler/chains/edgeStore.hpp"
30
#include "jfr/leakprofiler/chains/rootSetClosure.hpp"
31
#include "jfr/leakprofiler/utilities/granularTimer.hpp"
32
#include "jfr/leakprofiler/utilities/rootType.hpp"
33
#include "jfr/leakprofiler/utilities/unifiedOopRef.inline.hpp"
34
#include "memory/iterator.inline.hpp"
35
#include "memory/resourceArea.hpp"
36
#include "oops/access.inline.hpp"
37
#include "oops/oop.inline.hpp"
38
#include "utilities/align.hpp"
39
40
UnifiedOopRef DFSClosure::_reference_stack[max_dfs_depth];
41
42
void DFSClosure::find_leaks_from_edge(EdgeStore* edge_store,
43
BitSet* mark_bits,
44
const Edge* start_edge) {
45
assert(edge_store != NULL, "invariant");
46
assert(mark_bits != NULL," invariant");
47
assert(start_edge != NULL, "invariant");
48
49
// Depth-first search, starting from a BFS egde
50
DFSClosure dfs(edge_store, mark_bits, start_edge);
51
start_edge->pointee()->oop_iterate(&dfs);
52
}
53
54
void DFSClosure::find_leaks_from_root_set(EdgeStore* edge_store,
55
BitSet* mark_bits) {
56
assert(edge_store != NULL, "invariant");
57
assert(mark_bits != NULL, "invariant");
58
59
// Mark root set, to avoid going sideways
60
DFSClosure dfs(edge_store, mark_bits, NULL);
61
dfs._max_depth = 1;
62
RootSetClosure<DFSClosure> rs(&dfs);
63
rs.process();
64
65
// Depth-first search
66
dfs._max_depth = max_dfs_depth;
67
dfs._ignore_root_set = true;
68
rs.process();
69
}
70
71
DFSClosure::DFSClosure(EdgeStore* edge_store, BitSet* mark_bits, const Edge* start_edge)
72
:_edge_store(edge_store), _mark_bits(mark_bits), _start_edge(start_edge),
73
_max_depth(max_dfs_depth), _depth(0), _ignore_root_set(false) {
74
}
75
76
void DFSClosure::closure_impl(UnifiedOopRef reference, const oop pointee) {
77
assert(pointee != NULL, "invariant");
78
assert(!reference.is_null(), "invariant");
79
80
if (GranularTimer::is_finished()) {
81
return;
82
}
83
if (_depth == 0 && _ignore_root_set) {
84
// Root set is already marked, but we want
85
// to continue, so skip is_marked check.
86
assert(_mark_bits->is_marked(pointee), "invariant");
87
} else {
88
if (_mark_bits->is_marked(pointee)) {
89
return;
90
}
91
}
92
_reference_stack[_depth] = reference;
93
_mark_bits->mark_obj(pointee);
94
assert(_mark_bits->is_marked(pointee), "invariant");
95
96
// is the pointee a sample object?
97
if (pointee->mark().is_marked()) {
98
add_chain();
99
}
100
101
assert(_max_depth >= 1, "invariant");
102
if (_depth < _max_depth - 1) {
103
_depth++;
104
pointee->oop_iterate(this);
105
assert(_depth > 0, "invariant");
106
_depth--;
107
}
108
}
109
110
void DFSClosure::add_chain() {
111
const size_t array_length = _depth + 2;
112
113
ResourceMark rm;
114
Edge* const chain = NEW_RESOURCE_ARRAY(Edge, array_length);
115
size_t idx = 0;
116
117
// aggregate from depth-first search
118
for (size_t i = 0; i <= _depth; i++) {
119
const size_t next = idx + 1;
120
const size_t depth = _depth - i;
121
chain[idx++] = Edge(&chain[next], _reference_stack[depth]);
122
}
123
assert(_depth + 1 == idx, "invariant");
124
assert(array_length == idx + 1, "invariant");
125
126
// aggregate from breadth-first search
127
if (_start_edge != NULL) {
128
chain[idx++] = *_start_edge;
129
} else {
130
chain[idx - 1] = Edge(NULL, chain[idx - 1].reference());
131
}
132
_edge_store->put_chain(chain, idx + (_start_edge != NULL ? _start_edge->distance_to_root() : 0));
133
}
134
135
void DFSClosure::do_oop(oop* ref) {
136
assert(ref != NULL, "invariant");
137
assert(is_aligned(ref, HeapWordSize), "invariant");
138
const oop pointee = HeapAccess<AS_NO_KEEPALIVE>::oop_load(ref);
139
if (pointee != NULL) {
140
closure_impl(UnifiedOopRef::encode_in_heap(ref), pointee);
141
}
142
}
143
144
void DFSClosure::do_oop(narrowOop* ref) {
145
assert(ref != NULL, "invariant");
146
assert(is_aligned(ref, sizeof(narrowOop)), "invariant");
147
const oop pointee = HeapAccess<AS_NO_KEEPALIVE>::oop_load(ref);
148
if (pointee != NULL) {
149
closure_impl(UnifiedOopRef::encode_in_heap(ref), pointee);
150
}
151
}
152
153
void DFSClosure::do_root(UnifiedOopRef ref) {
154
assert(!ref.is_null(), "invariant");
155
const oop pointee = ref.dereference();
156
assert(pointee != NULL, "invariant");
157
closure_impl(ref, pointee);
158
}
159
160