Path: blob/master/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.cpp
41153 views
/*1* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "jfr/leakprofiler/chains/bitset.inline.hpp"26#include "jfr/leakprofiler/chains/dfsClosure.hpp"27#include "jfr/leakprofiler/chains/edge.hpp"28#include "jfr/leakprofiler/chains/edgeStore.hpp"29#include "jfr/leakprofiler/chains/rootSetClosure.hpp"30#include "jfr/leakprofiler/utilities/granularTimer.hpp"31#include "jfr/leakprofiler/utilities/rootType.hpp"32#include "jfr/leakprofiler/utilities/unifiedOopRef.inline.hpp"33#include "memory/iterator.inline.hpp"34#include "memory/resourceArea.hpp"35#include "oops/access.inline.hpp"36#include "oops/oop.inline.hpp"37#include "utilities/align.hpp"3839UnifiedOopRef DFSClosure::_reference_stack[max_dfs_depth];4041void DFSClosure::find_leaks_from_edge(EdgeStore* edge_store,42BitSet* mark_bits,43const Edge* start_edge) {44assert(edge_store != NULL, "invariant");45assert(mark_bits != NULL," invariant");46assert(start_edge != NULL, "invariant");4748// Depth-first search, starting from a BFS egde49DFSClosure dfs(edge_store, mark_bits, start_edge);50start_edge->pointee()->oop_iterate(&dfs);51}5253void DFSClosure::find_leaks_from_root_set(EdgeStore* edge_store,54BitSet* mark_bits) {55assert(edge_store != NULL, "invariant");56assert(mark_bits != NULL, "invariant");5758// Mark root set, to avoid going sideways59DFSClosure dfs(edge_store, mark_bits, NULL);60dfs._max_depth = 1;61RootSetClosure<DFSClosure> rs(&dfs);62rs.process();6364// Depth-first search65dfs._max_depth = max_dfs_depth;66dfs._ignore_root_set = true;67rs.process();68}6970DFSClosure::DFSClosure(EdgeStore* edge_store, BitSet* mark_bits, const Edge* start_edge)71:_edge_store(edge_store), _mark_bits(mark_bits), _start_edge(start_edge),72_max_depth(max_dfs_depth), _depth(0), _ignore_root_set(false) {73}7475void DFSClosure::closure_impl(UnifiedOopRef reference, const oop pointee) {76assert(pointee != NULL, "invariant");77assert(!reference.is_null(), "invariant");7879if (GranularTimer::is_finished()) {80return;81}82if (_depth == 0 && _ignore_root_set) {83// Root set is already marked, but we want84// to continue, so skip is_marked check.85assert(_mark_bits->is_marked(pointee), "invariant");86} else {87if (_mark_bits->is_marked(pointee)) {88return;89}90}91_reference_stack[_depth] = reference;92_mark_bits->mark_obj(pointee);93assert(_mark_bits->is_marked(pointee), "invariant");9495// is the pointee a sample object?96if (pointee->mark().is_marked()) {97add_chain();98}99100assert(_max_depth >= 1, "invariant");101if (_depth < _max_depth - 1) {102_depth++;103pointee->oop_iterate(this);104assert(_depth > 0, "invariant");105_depth--;106}107}108109void DFSClosure::add_chain() {110const size_t array_length = _depth + 2;111112ResourceMark rm;113Edge* const chain = NEW_RESOURCE_ARRAY(Edge, array_length);114size_t idx = 0;115116// aggregate from depth-first search117for (size_t i = 0; i <= _depth; i++) {118const size_t next = idx + 1;119const size_t depth = _depth - i;120chain[idx++] = Edge(&chain[next], _reference_stack[depth]);121}122assert(_depth + 1 == idx, "invariant");123assert(array_length == idx + 1, "invariant");124125// aggregate from breadth-first search126if (_start_edge != NULL) {127chain[idx++] = *_start_edge;128} else {129chain[idx - 1] = Edge(NULL, chain[idx - 1].reference());130}131_edge_store->put_chain(chain, idx + (_start_edge != NULL ? _start_edge->distance_to_root() : 0));132}133134void DFSClosure::do_oop(oop* ref) {135assert(ref != NULL, "invariant");136assert(is_aligned(ref, HeapWordSize), "invariant");137const oop pointee = HeapAccess<AS_NO_KEEPALIVE>::oop_load(ref);138if (pointee != NULL) {139closure_impl(UnifiedOopRef::encode_in_heap(ref), pointee);140}141}142143void DFSClosure::do_oop(narrowOop* ref) {144assert(ref != NULL, "invariant");145assert(is_aligned(ref, sizeof(narrowOop)), "invariant");146const oop pointee = HeapAccess<AS_NO_KEEPALIVE>::oop_load(ref);147if (pointee != NULL) {148closure_impl(UnifiedOopRef::encode_in_heap(ref), pointee);149}150}151152void DFSClosure::do_root(UnifiedOopRef ref) {153assert(!ref.is_null(), "invariant");154const oop pointee = ref.dereference();155assert(pointee != NULL, "invariant");156closure_impl(ref, pointee);157}158159160