Path: blob/master/src/hotspot/share/jfr/leakprofiler/chains/edgeUtils.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 "classfile/javaClasses.inline.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/unifiedOopRef.inline.hpp"30#include "oops/fieldStreams.inline.hpp"31#include "oops/instanceKlass.hpp"32#include "oops/instanceMirrorKlass.hpp"33#include "oops/objArrayOop.inline.hpp"34#include "oops/oopsHierarchy.hpp"35#include "runtime/handles.inline.hpp"3637bool EdgeUtils::is_leak_edge(const Edge& edge) {38return (const Edge*)edge.pointee()->mark().to_pointer() == &edge;39}4041static bool is_static_field(const oop ref_owner, const InstanceKlass* ik, int offset) {42assert(ref_owner != NULL, "invariant");43assert(ik != NULL, "invariant");44assert(ref_owner->klass() == ik, "invariant");45return ik->is_mirror_instance_klass() && offset >= InstanceMirrorKlass::cast(ik)->offset_of_static_fields();46}4748static int field_offset(const Edge& edge, const oop ref_owner) {49assert(ref_owner != NULL, "invariant");50assert(!ref_owner->is_array(), "invariant");51assert(ref_owner->is_instance(), "invariant");52UnifiedOopRef reference = edge.reference();53assert(!reference.is_null(), "invariant");54const int offset = (int)(reference.addr<uintptr_t>() - cast_from_oop<uintptr_t>(ref_owner));55assert(offset < ref_owner->size() * HeapWordSize, "invariant");56return offset;57}5859const Symbol* EdgeUtils::field_name(const Edge& edge, jshort* modifiers) {60assert(!edge.is_root(), "invariant");61assert(!EdgeUtils::is_array_element(edge), "invariant");62assert(modifiers != NULL, "invariant");63const oop ref_owner = edge.reference_owner();64assert(ref_owner != NULL, "invariant");65assert(ref_owner->klass()->is_instance_klass(), "invariant");66const InstanceKlass* ik = InstanceKlass::cast(ref_owner->klass());67const int offset = field_offset(edge, ref_owner);68if (is_static_field(ref_owner, ik, offset)) {69assert(ik->is_mirror_instance_klass(), "invariant");70assert(java_lang_Class::as_Klass(ref_owner)->is_instance_klass(), "invariant");71ik = InstanceKlass::cast(java_lang_Class::as_Klass(ref_owner));72}73while (ik != NULL) {74JavaFieldStream jfs(ik);75while (!jfs.done()) {76if (offset == jfs.offset()) {77*modifiers = jfs.access_flags().as_short();78return jfs.name();79}80jfs.next();81}82ik = (const InstanceKlass*)ik->super();83}84*modifiers = 0;85return NULL;86}8788bool EdgeUtils::is_array_element(const Edge& edge) {89assert(!edge.is_root(), "invariant");90const oop ref_owner = edge.reference_owner();91assert(ref_owner != NULL, "invariant");92return ref_owner->is_objArray();93}9495static int array_offset(const Edge& edge) {96assert(EdgeUtils::is_array_element(edge), "invariant");97const oop ref_owner = edge.reference_owner();98assert(ref_owner != NULL, "invariant");99UnifiedOopRef reference = edge.reference();100assert(!reference.is_null(), "invariant");101assert(ref_owner->is_array(), "invariant");102const objArrayOop ref_owner_array = static_cast<const objArrayOop>(ref_owner);103const int offset = (int)pointer_delta(reference.addr<HeapWord*>(), ref_owner_array->base(), heapOopSize);104assert(offset >= 0 && offset < ref_owner_array->length(), "invariant");105return offset;106}107108int EdgeUtils::array_index(const Edge& edge) {109return array_offset(edge);110}111112int EdgeUtils::array_size(const Edge& edge) {113assert(is_array_element(edge), "invariant");114const oop ref_owner = edge.reference_owner();115assert(ref_owner != NULL, "invariant");116assert(ref_owner->is_objArray(), "invariant");117return ((objArrayOop)ref_owner)->length();118}119120const Edge* EdgeUtils::root(const Edge& edge) {121const Edge* current = &edge;122const Edge* parent = current->parent();123while (parent != NULL) {124current = parent;125parent = current->parent();126}127assert(current != NULL, "invariant");128return current;129}130131const Edge* EdgeUtils::ancestor(const Edge& edge, size_t distance) {132const Edge* current = &edge;133const Edge* parent = current->parent();134size_t seek = 0;135while (parent != NULL && seek != distance) {136seek++;137current = parent;138parent = parent->parent();139}140return current;141}142143144