Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/jfr/leakprofiler/chains/edgeUtils.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 "classfile/javaClasses.hpp"26#include "jfr/leakprofiler/chains/edge.hpp"27#include "jfr/leakprofiler/chains/edgeStore.hpp"28#include "jfr/leakprofiler/chains/edgeUtils.hpp"29#include "jfr/leakprofiler/utilities/unifiedOop.hpp"30#include "oops/fieldStreams.hpp"31#include "oops/instanceKlass.hpp"32#include "oops/objArrayOop.hpp"33#include "oops/oopsHierarchy.hpp"34#include "runtime/handles.inline.hpp"3536bool EdgeUtils::is_leak_edge(const Edge& edge) {37return (const Edge*)edge.pointee()->mark() == &edge;38}3940static int field_offset(const StoredEdge& edge) {41assert(!edge.is_root(), "invariant");42const oop ref_owner = edge.reference_owner();43assert(ref_owner != NULL, "invariant");44const oop* reference = UnifiedOop::decode(edge.reference());45assert(reference != NULL, "invariant");46assert(!UnifiedOop::is_narrow(reference), "invariant");47assert(!ref_owner->is_array(), "invariant");48assert(ref_owner->is_instance(), "invariant");49const int offset = (int)pointer_delta(reference, ref_owner, sizeof(char));50assert(offset < (ref_owner->size() * HeapWordSize), "invariant");51return offset;52}5354static const InstanceKlass* field_type(const StoredEdge& edge) {55assert(!edge.is_root() || !EdgeUtils::is_array_element(edge), "invariant");56return (const InstanceKlass*)edge.reference_owner_klass();57}5859const Symbol* EdgeUtils::field_name_symbol(const Edge& edge) {60assert(!edge.is_root(), "invariant");61assert(!is_array_element(edge), "invariant");62const int offset = field_offset(edge);63const InstanceKlass* ik = field_type(edge);64while (ik != NULL) {65JavaFieldStream jfs(ik);66while (!jfs.done()) {67if (offset == jfs.offset()) {68return jfs.name();69}70jfs.next();71}72ik = (InstanceKlass*)ik->super();73}74return NULL;75}7677jshort EdgeUtils::field_modifiers(const Edge& edge) {78const int offset = field_offset(edge);79const InstanceKlass* ik = field_type(edge);8081while (ik != NULL) {82JavaFieldStream jfs(ik);83while (!jfs.done()) {84if (offset == jfs.offset()) {85return jfs.access_flags().as_short();86}87jfs.next();88}89ik = (InstanceKlass*)ik->super();90}91return 0;92}9394bool EdgeUtils::is_array_element(const Edge& edge) {95assert(!edge.is_root(), "invariant");96const oop ref_owner = edge.reference_owner();97assert(ref_owner != NULL, "invariant");98return ref_owner->is_objArray();99}100101static int array_offset(const Edge& edge) {102assert(!edge.is_root(), "invariant");103const oop ref_owner = edge.reference_owner();104assert(ref_owner != NULL, "invariant");105const oop* reference = UnifiedOop::decode(edge.reference());106assert(reference != NULL, "invariant");107assert(!UnifiedOop::is_narrow(reference), "invariant");108assert(ref_owner->is_array(), "invariant");109const objArrayOop ref_owner_array = static_cast<const objArrayOop>(ref_owner);110const int offset = (int)pointer_delta(reference, ref_owner_array->base(), heapOopSize);111assert(offset >= 0 && offset < ref_owner_array->length(), "invariant");112return offset;113}114115int EdgeUtils::array_index(const Edge& edge) {116return is_array_element(edge) ? array_offset(edge) : 0;117}118119int EdgeUtils::array_size(const Edge& edge) {120if (is_array_element(edge)) {121const oop ref_owner = edge.reference_owner();122assert(ref_owner != NULL, "invariant");123assert(ref_owner->is_objArray(), "invariant");124return ((objArrayOop)(ref_owner))->length();125}126return 0;127}128129const Edge* EdgeUtils::root(const Edge& edge) {130const Edge* current = &edge;131const Edge* parent = current->parent();132while (parent != NULL) {133current = parent;134parent = current->parent();135}136assert(current != NULL, "invariant");137return current;138}139140const Edge* EdgeUtils::ancestor(const Edge& edge, size_t distance) {141const Edge* current = &edge;142const Edge* parent = current->parent();143size_t seek = 0;144while (parent != NULL && seek != distance) {145seek++;146current = parent;147parent = parent->parent();148}149return current;150}151152153