Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/jfr/leakprofiler/chains/dfsClosure.cpp
38922 views
/*1* Copyright (c) 2014, 2019, 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.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/unifiedOop.hpp"33#include "memory/iterator.inline.hpp"34#include "memory/resourceArea.hpp"35#include "oops/oop.inline.hpp"36#include "utilities/align.hpp"3738// max dfs depth should not exceed size of stack39static const size_t max_dfs_depth = 5000;4041EdgeStore* DFSClosure::_edge_store = NULL;42BitSet* DFSClosure::_mark_bits = NULL;43const Edge* DFSClosure::_start_edge = NULL;44size_t DFSClosure::_max_depth = max_dfs_depth;45bool DFSClosure::_ignore_root_set = false;4647DFSClosure::DFSClosure() :48_parent(NULL),49_reference(NULL),50_depth(0) {51}5253DFSClosure::DFSClosure(DFSClosure* parent, size_t depth) :54_parent(parent),55_reference(NULL),56_depth(depth) {57}5859void DFSClosure::find_leaks_from_edge(EdgeStore* edge_store,60BitSet* mark_bits,61const Edge* start_edge) {62assert(edge_store != NULL, "invariant");63assert(mark_bits != NULL," invariant");64assert(start_edge != NULL, "invariant");6566_edge_store = edge_store;67_mark_bits = mark_bits;68_start_edge = start_edge;69_ignore_root_set = false;70assert(_max_depth == max_dfs_depth, "invariant");7172// Depth-first search, starting from a BFS egde73DFSClosure dfs;74start_edge->pointee()->oop_iterate(&dfs);75}7677void DFSClosure::find_leaks_from_root_set(EdgeStore* edge_store,78BitSet* mark_bits) {79assert(edge_store != NULL, "invariant");80assert(mark_bits != NULL, "invariant");8182_edge_store = edge_store;83_mark_bits = mark_bits;84_start_edge = NULL;8586// Mark root set, to avoid going sideways87_max_depth = 1;88_ignore_root_set = false;89DFSClosure dfs;90RootSetClosure<DFSClosure> rs(&dfs);91rs.process();9293// Depth-first search94_max_depth = max_dfs_depth;95_ignore_root_set = true;96assert(_start_edge == NULL, "invariant");97rs.process();98}99100void DFSClosure::closure_impl(const oop* reference, const oop pointee) {101assert(pointee != NULL, "invariant");102assert(reference != NULL, "invariant");103104if (GranularTimer::is_finished()) {105return;106}107if (_depth == 0 && _ignore_root_set) {108// Root set is already marked, but we want109// to continue, so skip is_marked check.110assert(_mark_bits->is_marked(pointee), "invariant");111} else {112if (_mark_bits->is_marked(pointee)) {113return;114}115}116117_reference = reference;118_mark_bits->mark_obj(pointee);119assert(_mark_bits->is_marked(pointee), "invariant");120121// is the pointee a sample object?122if (NULL == pointee->mark()) {123add_chain();124}125126assert(_max_depth >= 1, "invariant");127if (_depth < _max_depth - 1) {128DFSClosure next_level(this, _depth + 1);129pointee->oop_iterate(&next_level);130}131}132133void DFSClosure::add_chain() {134const size_t array_length = _depth + 2;135136ResourceMark rm;137Edge* const chain = NEW_RESOURCE_ARRAY(Edge, array_length);138size_t idx = 0;139140// aggregate from depth-first search141const DFSClosure* c = this;142while (c != NULL) {143const size_t next = idx + 1;144chain[idx++] = Edge(&chain[next], c->reference());145c = c->parent();146}147assert(_depth + 1 == idx, "invariant");148assert(array_length == idx + 1, "invariant");149150// aggregate from breadth-first search151if (_start_edge != NULL) {152chain[idx++] = *_start_edge;153} else {154chain[idx - 1] = Edge(NULL, chain[idx - 1].reference());155}156_edge_store->put_chain(chain, idx + (_start_edge != NULL ? _start_edge->distance_to_root() : 0));157}158159void DFSClosure::do_oop(oop* ref) {160assert(ref != NULL, "invariant");161assert(is_aligned(ref, HeapWordSize), "invariant");162const oop pointee = *ref;163if (pointee != NULL) {164closure_impl(ref, pointee);165}166}167168void DFSClosure::do_oop(narrowOop* ref) {169assert(ref != NULL, "invariant");170assert(is_aligned(ref, sizeof(narrowOop)), "invariant");171const oop pointee = oopDesc::load_decode_heap_oop(ref);172if (pointee != NULL) {173closure_impl(UnifiedOop::encode(ref), pointee);174}175}176177void DFSClosure::do_root(const oop* ref) {178assert(ref != NULL, "invariant");179const oop pointee = UnifiedOop::dereference(ref);180assert(pointee != NULL, "invariant");181closure_impl(ref, pointee);182}183184185