Skip to content

Commit 179d7d5

Browse files
committed
GH-445 collapse repetitive nodes
1 parent aa63258 commit 179d7d5

File tree

2 files changed

+112
-5
lines changed

2 files changed

+112
-5
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright (c) 2022, 2022, 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. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package org.graalvm.visualvm.heapviewer.java.impl;
26+
27+
import org.graalvm.visualvm.lib.jfluid.heap.Field;
28+
import org.graalvm.visualvm.lib.jfluid.heap.FieldValue;
29+
import org.graalvm.visualvm.lib.jfluid.heap.Instance;
30+
import org.graalvm.visualvm.lib.jfluid.heap.JavaClass;
31+
import org.graalvm.visualvm.lib.jfluid.heap.ObjectFieldValue;
32+
import org.openide.util.NbBundle;
33+
34+
/**
35+
*
36+
* @author Tomas Hurka
37+
*/
38+
@NbBundle.Messages({
39+
"HeapPatterns_SkippedInstances={0} ({1} instances of {2})"
40+
})
41+
final class HeapPatterns {
42+
43+
static PathToGCRootPlugin.SkipNode processGCRootReference(ObjectFieldValue reference) {
44+
ObjectFieldValue ref = reference;
45+
int skipped = 0;
46+
for (; ;skipped++) {
47+
Instance i = ref.getDefiningInstance();
48+
Instance path = i.getNearestGCRootPointer();
49+
if (!i.getJavaClass().equals(path.getJavaClass())) {
50+
break;
51+
}
52+
ObjectFieldValue oval = getValueOfField(path, ref.getField());
53+
if (oval == null || !oval.getInstance().equals(i)) {
54+
break;
55+
}
56+
ref = oval;
57+
}
58+
if (skipped>1) {
59+
JavaClass jcls = ref.getDefiningInstance().getJavaClass();
60+
String text = Bundle.HeapPatterns_SkippedInstances(ref.getField().getName(), skipped, jcls.getName());
61+
return new PathToGCRootPlugin.SkipNode(text, ref);
62+
}
63+
return null;
64+
}
65+
66+
static ObjectFieldValue getValueOfField(Instance i, Field f) {
67+
for (FieldValue val : i.getFieldValues()) {
68+
if (val instanceof ObjectFieldValue) {
69+
ObjectFieldValue oval = (ObjectFieldValue) val;
70+
if (oval.getField().equals(f)) {
71+
return oval;
72+
}
73+
}
74+
}
75+
return null;
76+
}
77+
}

visualvm/heapviewer/src/org/graalvm/visualvm/heapviewer/java/impl/PathToGCRootPlugin.java

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ private static Collection<HeapViewerNode> computeInstanceRoots(Instance instance
360360
return Collections.singleton(new TextNode(Bundle.PathToGCRootPlugin_IsRoot()));
361361
} else {
362362
ToRoot node = null;
363-
HeapViewerNode firstNode = null;
363+
ToRoot firstNode = null;
364364
ToRoot previousNode = null;
365365

366366
try {
@@ -371,10 +371,23 @@ private static Collection<HeapViewerNode> computeInstanceRoots(Instance instance
371371
List<Value> references = instance.getReferences();
372372
for (Value reference : references) {
373373
if (nextInstance.equals(reference.getDefiningInstance())) {
374-
if (reference instanceof ObjectFieldValue) node = new FieldToRoot((ObjectFieldValue)reference);
375-
else if (reference instanceof ArrayItemValue) node = new ArrayItemToRoot((ArrayItemValue)reference);
374+
if (reference instanceof ObjectFieldValue) {
375+
ObjectFieldValue ref = (ObjectFieldValue)reference;
376+
SkipNode snode = HeapPatterns.processGCRootReference(ref);
377+
if (snode != null) {
378+
ref = snode.getNextReference();
379+
nextInstance = ref.getDefiningInstance();
380+
node = snode;
381+
if (firstNode == null) firstNode = node;
382+
else previousNode.setChildren(new HeapViewerNode[] { (HeapViewerNode)node });
383+
previousNode = node;
384+
}
385+
node = new FieldToRoot(ref);
386+
} else if (reference instanceof ArrayItemValue) {
387+
node = new ArrayItemToRoot((ArrayItemValue)reference);
388+
}
376389

377-
if (firstNode == null) firstNode = (HeapViewerNode)node;
390+
if (firstNode == null) firstNode = node;
378391
else previousNode.setChildren(new HeapViewerNode[] { (HeapViewerNode)node });
379392

380393
break;
@@ -394,7 +407,7 @@ private static Collection<HeapViewerNode> computeInstanceRoots(Instance instance
394407
progress.finish();
395408
}
396409

397-
return Collections.singleton(firstNode);
410+
return Collections.singleton((HeapViewerNode) firstNode);
398411
}
399412
}
400413

@@ -609,6 +622,23 @@ public void setChildren(HeapViewerNode[] ch) {
609622

610623
}
611624

625+
static class SkipNode extends TextNode implements ToRoot {
626+
627+
private ObjectFieldValue reference;
628+
629+
SkipNode(String text, ObjectFieldValue ref) {
630+
super(text);
631+
reference = ref;
632+
}
633+
634+
public void setChildren(HeapViewerNode[] ch) {
635+
super.setChildren(ch);
636+
}
637+
638+
private ObjectFieldValue getNextReference() {
639+
return reference;
640+
}
641+
}
612642

613643
@ServiceProvider(service=HeapViewPlugin.Provider.class, position = 400)
614644
public static class Provider extends HeapViewPlugin.Provider {

0 commit comments

Comments
 (0)