8282547: IGV: add control-flow graph view
Co-authored-by: Christian Hagedorn <chagedorn@openjdk.org> Reviewed-by: chagedorn, xliu, thartmann
This commit is contained in:
parent
7418373674
commit
edb42d7b0a
src/utils/IdealGraphVisualizer
ControlFlow/src/main/java/com/sun/hotspot/igv/controlflow
Data/src/main/java/com/sun/hotspot/igv/data
Filter/src/main/java/com/sun/hotspot/igv/filter
ColorFilter.javaCombineFilter.javaConnectionFilter.javaEdgeColorIndexFilter.javaRemoveBlockFilter.javaRemoveInputsFilter.javaRemoveSelfLoopsFilter.javaSplitFilter.java
Graal/src/main/java/com/sun/hotspot/igv/graal/filters
Graph/src/main/java/com/sun/hotspot/igv/graph
AnySelector.javaBlock.javaBlockConnection.javaBlockSelector.javaConnection.javaDiagram.javaFigure.javaFigureConnection.javaSlot.java
HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout
ClusterEdge.javaClusterIngoingConnection.javaClusterInputSlotNode.javaClusterNode.javaClusterOutgoingConnection.javaClusterOutputSlotNode.javaHierarchicalCFGLayoutManager.javaHierarchicalClusterLayoutManager.javaHierarchicalLayoutManager.javaInterClusterConnection.javaLinearLayoutManager.java
Layout/src/main/java/com/sun/hotspot/igv/layout
ServerCompiler/src/main
java/com/sun/hotspot/igv/servercompiler
resources/com/sun/hotspot/igv/servercompiler
Settings/src/main/java/com/sun/hotspot/igv/settings
Util/src/main/java/com/sun/hotspot/igv/util
View/src/main
java/com/sun/hotspot/igv/view
BlockQuickSearch.javaDiagramScene.javaDiagramViewModel.javaEditorTopComponent.javaGraphViewerImplementation.javaNodeQuickSearch.java
actions
widgets
resources/com/sun/hotspot/igv/view
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,6 +26,7 @@ package com.sun.hotspot.igv.controlflow;
|
||||
import com.sun.hotspot.igv.data.InputBlockEdge;
|
||||
import com.sun.hotspot.igv.layout.Link;
|
||||
import com.sun.hotspot.igv.layout.Port;
|
||||
import com.sun.hotspot.igv.layout.Cluster;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Point;
|
||||
import java.awt.Stroke;
|
||||
@ -76,6 +77,14 @@ public class BlockConnectionWidget extends ConnectionWidget implements Link {
|
||||
return outputSlot;
|
||||
}
|
||||
|
||||
public Cluster getFromCluster() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Cluster getToCluster() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setBold(boolean bold) {
|
||||
this.isBold = bold;
|
||||
updateStroke();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -69,6 +69,14 @@ public class HierarchicalGraphLayout<N, E> extends GraphLayout<N, E> {
|
||||
return to.getSlot();
|
||||
}
|
||||
|
||||
public Cluster getFromCluster() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Cluster getToCluster() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<Point> getControlPoints() {
|
||||
return new ArrayList<Point>();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -35,6 +35,7 @@ public class InputBlock {
|
||||
private String name;
|
||||
private InputGraph graph;
|
||||
private Set<InputBlock> successors;
|
||||
private boolean artificial;
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
@ -77,6 +78,7 @@ public class InputBlock {
|
||||
this.name = name;
|
||||
nodes = new ArrayList<>();
|
||||
successors = new LinkedHashSet<>(2);
|
||||
artificial = false;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
@ -101,6 +103,10 @@ public class InputBlock {
|
||||
return Collections.unmodifiableSet(successors);
|
||||
}
|
||||
|
||||
public void setNodes(List<InputNode> nodes) {
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Block " + this.getName();
|
||||
@ -111,4 +117,12 @@ public class InputBlock {
|
||||
successors.add(b);
|
||||
}
|
||||
}
|
||||
|
||||
void setArtificial(boolean artificial) {
|
||||
this.artificial = artificial;
|
||||
}
|
||||
|
||||
public boolean isArtificial() {
|
||||
return artificial;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -38,12 +38,14 @@ public class InputBlockEdge {
|
||||
private InputBlock from;
|
||||
private InputBlock to;
|
||||
private State state = State.SAME;
|
||||
private String label;
|
||||
|
||||
public InputBlockEdge(InputBlock from, InputBlock to) {
|
||||
public InputBlockEdge(InputBlock from, InputBlock to, String label) {
|
||||
assert from != null;
|
||||
assert to != null;
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public InputBlock getFrom() {
|
||||
@ -62,6 +64,10 @@ public class InputBlockEdge {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj != null && obj instanceof InputBlockEdge) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -58,7 +58,11 @@ public class InputGraph extends Properties.Entity implements FolderElement {
|
||||
}
|
||||
|
||||
public InputBlockEdge addBlockEdge(InputBlock left, InputBlock right) {
|
||||
InputBlockEdge edge = new InputBlockEdge(left, right);
|
||||
return addBlockEdge(left, right, null);
|
||||
}
|
||||
|
||||
public InputBlockEdge addBlockEdge(InputBlock left, InputBlock right, String label) {
|
||||
InputBlockEdge edge = new InputBlockEdge(left, right, label);
|
||||
blockEdges.add(edge);
|
||||
left.addSuccessor(right);
|
||||
return edge;
|
||||
@ -140,6 +144,7 @@ public class InputGraph extends Properties.Entity implements FolderElement {
|
||||
|
||||
public void clearBlocks() {
|
||||
blocks.clear();
|
||||
blockEdges.clear();
|
||||
nodeToBlock.clear();
|
||||
}
|
||||
|
||||
@ -168,7 +173,7 @@ public class InputGraph extends Properties.Entity implements FolderElement {
|
||||
assert nodes.get(n.getId()) == n;
|
||||
if (!scheduledNodes.contains(n)) {
|
||||
if (noBlock == null) {
|
||||
noBlock = this.addBlock("(no block)");
|
||||
noBlock = addArtificialBlock();
|
||||
}
|
||||
noBlock.addNode(n.getId());
|
||||
}
|
||||
@ -270,6 +275,12 @@ public class InputGraph extends Properties.Entity implements FolderElement {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public InputBlock addArtificialBlock() {
|
||||
InputBlock b = addBlock("(no block)");
|
||||
b.setArtificial(true);
|
||||
return b;
|
||||
}
|
||||
|
||||
public InputBlock addBlock(String name) {
|
||||
final InputBlock b = new InputBlock(this, name);
|
||||
blocks.put(b.getName(), b);
|
||||
|
4
src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/serialization/Parser.java
4
src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/serialization/Parser.java
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -261,7 +261,7 @@ public class Parser implements GraphParser {
|
||||
for (InputNode n : graph.getNodes()) {
|
||||
if (graph.getBlock(n) == null) {
|
||||
if (noBlock == null) {
|
||||
noBlock = graph.addBlock("(no block)");
|
||||
noBlock = graph.addArtificialBlock();
|
||||
}
|
||||
|
||||
noBlock.addNode(n.getId());
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -78,7 +78,7 @@ public class ColorFilter extends AbstractFilter {
|
||||
ConnectionStyle style = rule.getLineStyle();
|
||||
|
||||
for (OutputSlot s : f.getOutputSlots()) {
|
||||
for (Connection c : s.getConnections()) {
|
||||
for (FigureConnection c : s.getConnections()) {
|
||||
if (color != null) {
|
||||
c.setColor(color);
|
||||
}
|
||||
|
14
src/utils/IdealGraphVisualizer/Filter/src/main/java/com/sun/hotspot/igv/filter/CombineFilter.java
14
src/utils/IdealGraphVisualizer/Filter/src/main/java/com/sun/hotspot/igv/filter/CombineFilter.java
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -67,7 +67,7 @@ public class CombineFilter extends AbstractFilter {
|
||||
InputSlot slot = null;
|
||||
|
||||
for (InputSlot s : succ.getInputSlots()) {
|
||||
for (Connection c : s.getConnections()) {
|
||||
for (FigureConnection c : s.getConnections()) {
|
||||
if (c.getOutputSlot().getFigure() == f) {
|
||||
slot = s;
|
||||
}
|
||||
@ -97,8 +97,8 @@ public class CombineFilter extends AbstractFilter {
|
||||
}
|
||||
|
||||
for (InputSlot s : f.getInputSlots()) {
|
||||
for (Connection c : s.getConnections()) {
|
||||
Connection newConn = diagram.createConnection(slot, c.getOutputSlot(), c.getLabel(), c.getType());
|
||||
for (FigureConnection c : s.getConnections()) {
|
||||
FigureConnection newConn = diagram.createConnection(slot, c.getOutputSlot(), c.getLabel());
|
||||
newConn.setColor(c.getColor());
|
||||
newConn.setStyle(c.getStyle());
|
||||
}
|
||||
@ -115,7 +115,7 @@ public class CombineFilter extends AbstractFilter {
|
||||
|
||||
OutputSlot oldSlot = null;
|
||||
for (OutputSlot s : f.getOutputSlots()) {
|
||||
for (Connection c : s.getConnections()) {
|
||||
for (FigureConnection c : s.getConnections()) {
|
||||
if (c.getInputSlot().getFigure() == succ) {
|
||||
oldSlot = s;
|
||||
}
|
||||
@ -155,8 +155,8 @@ public class CombineFilter extends AbstractFilter {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Connection c : nextSlot.getConnections()) {
|
||||
Connection newConn = diagram.createConnection(c.getInputSlot(), slot, c.getLabel(), c.getType());
|
||||
for (FigureConnection c : nextSlot.getConnections()) {
|
||||
FigureConnection newConn = diagram.createConnection(c.getInputSlot(), slot, c.getLabel());
|
||||
newConn.setColor(c.getColor());
|
||||
newConn.setStyle(c.getStyle());
|
||||
}
|
||||
|
4
src/utils/IdealGraphVisualizer/Filter/src/main/java/com/sun/hotspot/igv/filter/ConnectionFilter.java
4
src/utils/IdealGraphVisualizer/Filter/src/main/java/com/sun/hotspot/igv/filter/ConnectionFilter.java
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -62,7 +62,7 @@ public class ConnectionFilter extends AbstractFilter {
|
||||
|
||||
for (Figure f : figures) {
|
||||
for (OutputSlot os : f.getOutputSlots()) {
|
||||
for (Connection c : os.getConnections()) {
|
||||
for (FigureConnection c : os.getConnections()) {
|
||||
c.setStyle(rule.getLineStyle());
|
||||
c.setColor(rule.getLineColor());
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -64,7 +64,7 @@ public class EdgeColorIndexFilter extends AbstractFilter {
|
||||
for (Slot slot : slots) {
|
||||
if (index < colors.length && colors[index] != null) {
|
||||
slot.setColor(colors[index]);
|
||||
for (Connection c : slot.getConnections()) {
|
||||
for (FigureConnection c : slot.getConnections()) {
|
||||
|
||||
c.setColor(colors[index]);
|
||||
}
|
||||
|
74
src/utils/IdealGraphVisualizer/Filter/src/main/java/com/sun/hotspot/igv/filter/RemoveBlockFilter.java
Normal file
74
src/utils/IdealGraphVisualizer/Filter/src/main/java/com/sun/hotspot/igv/filter/RemoveBlockFilter.java
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
package com.sun.hotspot.igv.filter;
|
||||
|
||||
import com.sun.hotspot.igv.graph.Diagram;
|
||||
import com.sun.hotspot.igv.graph.Block;
|
||||
import com.sun.hotspot.igv.graph.BlockSelector;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class RemoveBlockFilter extends AbstractFilter {
|
||||
|
||||
private final List<RemoveBlockRule> rules;
|
||||
private final String name;
|
||||
|
||||
public RemoveBlockFilter(String name) {
|
||||
this.name = name;
|
||||
rules = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Diagram diagram) {
|
||||
for (RemoveBlockRule r : rules) {
|
||||
List<Block> selected = r.getBlockSelector().selected(diagram);
|
||||
Set<Block> toRemove = new HashSet<>(selected);
|
||||
diagram.removeAllBlocks(toRemove);
|
||||
}
|
||||
}
|
||||
|
||||
public void addRule(RemoveBlockRule rule) {
|
||||
rules.add(rule);
|
||||
}
|
||||
|
||||
public static class RemoveBlockRule {
|
||||
|
||||
private final BlockSelector selector;
|
||||
|
||||
public RemoveBlockRule(BlockSelector selector) {
|
||||
this.selector = selector;
|
||||
}
|
||||
|
||||
public BlockSelector getBlockSelector() {
|
||||
return selector;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -58,9 +58,9 @@ public class RemoveInputsFilter extends AbstractFilter {
|
||||
for (InputSlot is : f.getInputSlots()) {
|
||||
if (z >= r.getStartingIndex() && z <= r.getEndIndex() && is.getConnections().size() > 0) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
List<Connection> conns = is.getConnections();
|
||||
List<FigureConnection> conns = is.getConnections();
|
||||
for (int i = 0; i < conns.size(); i++) {
|
||||
Connection c = conns.get(i);
|
||||
FigureConnection c = conns.get(i);
|
||||
OutputSlot os = c.getOutputSlot();
|
||||
Figure pred = os.getFigure();
|
||||
if (i != 0) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -52,15 +52,15 @@ public class RemoveSelfLoopsFilter extends AbstractFilter {
|
||||
|
||||
for (InputSlot is : f.getInputSlots()) {
|
||||
|
||||
List<Connection> toRemove = new ArrayList<>();
|
||||
for (Connection c : is.getConnections()) {
|
||||
List<FigureConnection> toRemove = new ArrayList<>();
|
||||
for (FigureConnection c : is.getConnections()) {
|
||||
|
||||
if (c.getOutputSlot().getFigure() == f) {
|
||||
toRemove.add(c);
|
||||
}
|
||||
}
|
||||
|
||||
for (Connection c : toRemove) {
|
||||
for (FigureConnection c : toRemove) {
|
||||
|
||||
c.remove();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -54,7 +54,7 @@ public class SplitFilter extends AbstractFilter {
|
||||
for (Figure f : list) {
|
||||
|
||||
for (InputSlot is : f.getInputSlots()) {
|
||||
for (Connection c : is.getConnections()) {
|
||||
for (FigureConnection c : is.getConnections()) {
|
||||
OutputSlot os = c.getOutputSlot();
|
||||
if (f.getSource().getSourceNodes().size() > 0) {
|
||||
os.getSource().addSourceNodes(f.getSource());
|
||||
@ -71,7 +71,7 @@ public class SplitFilter extends AbstractFilter {
|
||||
}
|
||||
}
|
||||
for (OutputSlot os : f.getOutputSlots()) {
|
||||
for (Connection c : os.getConnections()) {
|
||||
for (FigureConnection c : os.getConnections()) {
|
||||
InputSlot is = c.getInputSlot();
|
||||
if (f.getSource().getSourceNodes().size() > 0) {
|
||||
is.getSource().addSourceNodes(f.getSource());
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,7 +25,7 @@ package com.sun.hotspot.igv.graal.filters;
|
||||
|
||||
import com.sun.hotspot.igv.data.Properties;
|
||||
import com.sun.hotspot.igv.filter.AbstractFilter;
|
||||
import com.sun.hotspot.igv.graph.Connection;
|
||||
import com.sun.hotspot.igv.graph.FigureConnection;
|
||||
import com.sun.hotspot.igv.graph.Diagram;
|
||||
import com.sun.hotspot.igv.graph.Figure;
|
||||
import com.sun.hotspot.igv.graph.InputSlot;
|
||||
@ -42,7 +42,7 @@ public class GraalCFGFilter extends AbstractFilter {
|
||||
|
||||
@Override
|
||||
public void apply(Diagram d) {
|
||||
Set<Connection> connectionsToRemove = new HashSet<>();
|
||||
Set<FigureConnection> connectionsToRemove = new HashSet<>();
|
||||
|
||||
for (Figure f : d.getFigures()) {
|
||||
Properties p = f.getProperties();
|
||||
@ -57,7 +57,7 @@ public class GraalCFGFilter extends AbstractFilter {
|
||||
}
|
||||
for (InputSlot is : f.getInputSlots()) {
|
||||
if (is.getPosition() >= predCount && !"EndNode".equals(is.getProperties().get("class"))) {
|
||||
for (Connection c : is.getConnections()) {
|
||||
for (FigureConnection c : is.getConnections()) {
|
||||
if (!"EndNode".equals(c.getOutputSlot().getFigure().getProperties().get("class"))) {
|
||||
connectionsToRemove.add(c);
|
||||
}
|
||||
@ -66,7 +66,7 @@ public class GraalCFGFilter extends AbstractFilter {
|
||||
}
|
||||
}
|
||||
|
||||
for (Connection c : connectionsToRemove) {
|
||||
for (FigureConnection c : connectionsToRemove) {
|
||||
c.remove();
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,16 +23,10 @@
|
||||
*/
|
||||
package com.sun.hotspot.igv.graal.filters;
|
||||
|
||||
import com.sun.hotspot.igv.data.Properties;
|
||||
import com.sun.hotspot.igv.filter.AbstractFilter;
|
||||
import com.sun.hotspot.igv.graph.Connection;
|
||||
import com.sun.hotspot.igv.graph.Connection.ConnectionStyle;
|
||||
import com.sun.hotspot.igv.graph.Diagram;
|
||||
import com.sun.hotspot.igv.graph.Figure;
|
||||
import com.sun.hotspot.igv.graph.InputSlot;
|
||||
import java.awt.Color;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Filter that colors usage and successor edges differently.
|
||||
@ -54,29 +48,6 @@ public class GraalEdgeColorFilter extends AbstractFilter {
|
||||
|
||||
@Override
|
||||
public void apply(Diagram d) {
|
||||
List<Figure> figures = d.getFigures();
|
||||
for (Figure f : figures) {
|
||||
for (InputSlot is : f.getInputSlots()) {
|
||||
for (Connection c : is.getConnections()) {
|
||||
String type = c.getType();
|
||||
if (type == "Association" && "EndNode".equals(c.getOutputSlot().getFigure().getProperties().get("class"))) {
|
||||
type = "Successor";
|
||||
}
|
||||
|
||||
if (type != null) {
|
||||
Color typeColor = usageColor.get(type);
|
||||
if (typeColor == null) {
|
||||
c.setColor(otherUsageColor);
|
||||
} else {
|
||||
c.setColor(typeColor);
|
||||
}
|
||||
if (c.getStyle() != ConnectionStyle.DASHED && type == "Successor") {
|
||||
c.setStyle(ConnectionStyle.BOLD);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Color getUsageColor(String type) {
|
||||
|
46
src/utils/IdealGraphVisualizer/Graph/src/main/java/com/sun/hotspot/igv/graph/AnySelector.java
Normal file
46
src/utils/IdealGraphVisualizer/Graph/src/main/java/com/sun/hotspot/igv/graph/AnySelector.java
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
package com.sun.hotspot.igv.graph;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
// Selects blocks where any node is selected.
|
||||
public class AnySelector implements BlockSelector {
|
||||
|
||||
private final Selector selector;
|
||||
|
||||
public AnySelector(Selector s) {
|
||||
this.selector = s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Block> selected(Diagram d) {
|
||||
List<Block> l = new ArrayList<>();
|
||||
for (Figure f : selector.selected(d)) {
|
||||
l.add(d.getBlock(f.getBlock()));
|
||||
}
|
||||
return l;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,6 +23,7 @@
|
||||
*/
|
||||
package com.sun.hotspot.igv.graph;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import com.sun.hotspot.igv.data.InputBlock;
|
||||
import com.sun.hotspot.igv.layout.Cluster;
|
||||
import java.awt.Rectangle;
|
||||
@ -55,11 +56,17 @@ public class Block implements Cluster {
|
||||
public Set<? extends Cluster> getSuccessors() {
|
||||
Set<Block> succs = new HashSet<Block>();
|
||||
for (InputBlock b : inputBlock.getSuccessors()) {
|
||||
succs.add(diagram.getBlock(b));
|
||||
if (diagram.hasBlock(b)) {
|
||||
succs.add(diagram.getBlock(b));
|
||||
}
|
||||
}
|
||||
return succs;
|
||||
}
|
||||
|
||||
public Dimension getNodeOffset() {
|
||||
return new Dimension(0, -Figure.getVerticalOffset());
|
||||
}
|
||||
|
||||
public void setBounds(Rectangle r) {
|
||||
this.bounds = r;
|
||||
}
|
||||
|
112
src/utils/IdealGraphVisualizer/Graph/src/main/java/com/sun/hotspot/igv/graph/BlockConnection.java
Normal file
112
src/utils/IdealGraphVisualizer/Graph/src/main/java/com/sun/hotspot/igv/graph/BlockConnection.java
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
package com.sun.hotspot.igv.graph;
|
||||
|
||||
import com.sun.hotspot.igv.layout.Port;
|
||||
import java.awt.Color;
|
||||
import java.awt.Point;
|
||||
import java.util.List;
|
||||
|
||||
public class BlockConnection implements Connection {
|
||||
|
||||
private final Block sourceBlock;
|
||||
private final Block destinationBlock;
|
||||
private final String label;
|
||||
private List<Point> controlPoints;
|
||||
|
||||
public BlockConnection(Block src, Block dst, String label) {
|
||||
this.sourceBlock = src;
|
||||
this.destinationBlock = dst;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public Color getColor() {
|
||||
return Color.BLUE;
|
||||
}
|
||||
|
||||
public ConnectionStyle getStyle() {
|
||||
return ConnectionStyle.BOLD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToolTipText() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("B").append(sourceBlock.getInputBlock().getName())
|
||||
.append(" → B").append(destinationBlock.getInputBlock().getName());
|
||||
if (label != null) {
|
||||
builder.append(": ").append(label);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BlockConnection('" + label + "', " + getFromCluster() + " to " + getToCluster() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Port getFrom() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block getFromCluster() {
|
||||
return sourceBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Port getTo() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block getToCluster() {
|
||||
return destinationBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVIP() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Point> getControlPoints() {
|
||||
return controlPoints;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setControlPoints(List<Point> list) {
|
||||
controlPoints = list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlwaysVisible() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSlots() {
|
||||
return false;
|
||||
}
|
||||
}
|
30
src/utils/IdealGraphVisualizer/Graph/src/main/java/com/sun/hotspot/igv/graph/BlockSelector.java
Normal file
30
src/utils/IdealGraphVisualizer/Graph/src/main/java/com/sun/hotspot/igv/graph/BlockSelector.java
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
package com.sun.hotspot.igv.graph;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface BlockSelector {
|
||||
List<Block> selected(Diagram d);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,143 +23,26 @@
|
||||
*/
|
||||
package com.sun.hotspot.igv.graph;
|
||||
|
||||
import com.sun.hotspot.igv.data.Source;
|
||||
import com.sun.hotspot.igv.layout.Link;
|
||||
import com.sun.hotspot.igv.layout.Port;
|
||||
import java.awt.Color;
|
||||
import java.awt.Point;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Thomas Wuerthinger
|
||||
*/
|
||||
public class Connection implements Source.Provider, Link {
|
||||
|
||||
@Override
|
||||
public boolean isVIP() {
|
||||
return style == ConnectionStyle.BOLD;
|
||||
}
|
||||
public interface Connection extends Link {
|
||||
|
||||
public enum ConnectionStyle {
|
||||
|
||||
NORMAL,
|
||||
DASHED,
|
||||
BOLD,
|
||||
INVISIBLE
|
||||
}
|
||||
private InputSlot inputSlot;
|
||||
private OutputSlot outputSlot;
|
||||
private Source source;
|
||||
private Color color;
|
||||
private ConnectionStyle style;
|
||||
private List<Point> controlPoints;
|
||||
private String label;
|
||||
private String type;
|
||||
|
||||
protected Connection(InputSlot inputSlot, OutputSlot outputSlot, String label, String type) {
|
||||
this.inputSlot = inputSlot;
|
||||
this.outputSlot = outputSlot;
|
||||
this.label = label;
|
||||
this.type = type;
|
||||
this.inputSlot.connections.add(this);
|
||||
this.outputSlot.connections.add(this);
|
||||
controlPoints = new ArrayList<>();
|
||||
Figure sourceFigure = this.outputSlot.getFigure();
|
||||
Figure destFigure = this.inputSlot.getFigure();
|
||||
sourceFigure.addSuccessor(destFigure);
|
||||
destFigure.addPredecessor(sourceFigure);
|
||||
source = new Source();
|
||||
public ConnectionStyle getStyle();
|
||||
|
||||
this.color = Color.BLACK;
|
||||
this.style = ConnectionStyle.NORMAL;
|
||||
}
|
||||
public Color getColor();
|
||||
|
||||
public InputSlot getInputSlot() {
|
||||
return inputSlot;
|
||||
}
|
||||
public String getToolTipText();
|
||||
|
||||
public OutputSlot getOutputSlot() {
|
||||
return outputSlot;
|
||||
}
|
||||
public boolean isAlwaysVisible();
|
||||
|
||||
public Color getColor() {
|
||||
return color;
|
||||
}
|
||||
public boolean hasSlots();
|
||||
|
||||
public ConnectionStyle getStyle() {
|
||||
return style;
|
||||
}
|
||||
|
||||
public void setColor(Color c) {
|
||||
color = c;
|
||||
}
|
||||
|
||||
public void setStyle(ConnectionStyle s) {
|
||||
style = s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Source getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
inputSlot.getFigure().removePredecessor(outputSlot.getFigure());
|
||||
inputSlot.connections.remove(this);
|
||||
outputSlot.getFigure().removeSuccessor(inputSlot.getFigure());
|
||||
outputSlot.connections.remove(this);
|
||||
}
|
||||
|
||||
public String getToolTipText() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (label != null) {
|
||||
builder.append(label).append(": ");
|
||||
}
|
||||
if (type != null) {
|
||||
builder.append(type).append(" ");
|
||||
}
|
||||
// Resolve strings lazily every time the tooltip is shown, instead of
|
||||
// eagerly as for node labels, for efficiency.
|
||||
String shortNodeText = getInputSlot().getFigure().getDiagram().getShortNodeText();
|
||||
builder.append(getOutputSlot().getFigure().getProperties().resolveString(shortNodeText));
|
||||
builder.append(" → ");
|
||||
builder.append(getInputSlot().getFigure().getProperties().resolveString(shortNodeText));
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Connection('" + label + "', " + getFrom().getVertex() + " to " + getTo().getVertex() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Port getFrom() {
|
||||
return outputSlot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Port getTo() {
|
||||
return inputSlot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Point> getControlPoints() {
|
||||
return controlPoints;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setControlPoints(List<Point> list) {
|
||||
controlPoints = list;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,12 +24,14 @@
|
||||
package com.sun.hotspot.igv.graph;
|
||||
|
||||
import com.sun.hotspot.igv.data.InputBlock;
|
||||
import com.sun.hotspot.igv.data.InputBlockEdge;
|
||||
import com.sun.hotspot.igv.data.InputEdge;
|
||||
import com.sun.hotspot.igv.data.InputGraph;
|
||||
import com.sun.hotspot.igv.data.InputNode;
|
||||
import com.sun.hotspot.igv.data.Properties;
|
||||
import com.sun.hotspot.igv.data.Properties.StringPropertyMatcher;
|
||||
import java.awt.Font;
|
||||
import java.awt.Color;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@ -44,9 +46,14 @@ public class Diagram {
|
||||
private int curId;
|
||||
private String nodeText;
|
||||
private String shortNodeText;
|
||||
private String tinyNodeText;
|
||||
private final Font font;
|
||||
private final Font slotFont;
|
||||
private final Font boldFont;
|
||||
// Whether widgets derived from this diagram should be adapted for the
|
||||
// control-flow graph view.
|
||||
private boolean cfg;
|
||||
private final Set<BlockConnection> blockConnections;
|
||||
|
||||
public Font getFont() {
|
||||
return font;
|
||||
@ -60,7 +67,16 @@ public class Diagram {
|
||||
return boldFont;
|
||||
}
|
||||
|
||||
private Diagram() {
|
||||
public boolean isCFG() {
|
||||
return cfg;
|
||||
}
|
||||
|
||||
public void setCFG(boolean cfg) {
|
||||
this.cfg = cfg;
|
||||
}
|
||||
|
||||
private Diagram(InputGraph graph, String nodeText, String shortNodeText,
|
||||
String tinyNodeText) {
|
||||
figures = new ArrayList<>();
|
||||
blocks = new LinkedHashMap<>(8);
|
||||
this.nodeText = "";
|
||||
@ -68,6 +84,12 @@ public class Diagram {
|
||||
this.font = new Font("Arial", Font.PLAIN, 12);
|
||||
this.slotFont = new Font("Arial", Font.PLAIN, 10);
|
||||
this.boldFont = this.font.deriveFont(Font.BOLD);
|
||||
this.cfg = false;
|
||||
this.blockConnections = new HashSet<>();
|
||||
this.graph = graph;
|
||||
this.nodeText = nodeText;
|
||||
this.shortNodeText = shortNodeText;
|
||||
this.tinyNodeText = tinyNodeText;
|
||||
}
|
||||
|
||||
public Block getBlock(InputBlock b) {
|
||||
@ -75,6 +97,10 @@ public class Diagram {
|
||||
return blocks.get(b);
|
||||
}
|
||||
|
||||
public boolean hasBlock(InputBlock b) {
|
||||
return blocks.containsKey(b);
|
||||
}
|
||||
|
||||
public String getNodeText() {
|
||||
return nodeText;
|
||||
}
|
||||
@ -83,6 +109,10 @@ public class Diagram {
|
||||
return shortNodeText;
|
||||
}
|
||||
|
||||
public String getTinyNodeText() {
|
||||
return tinyNodeText;
|
||||
}
|
||||
|
||||
public void updateBlocks() {
|
||||
blocks.clear();
|
||||
for (InputBlock b : graph.getBlocks()) {
|
||||
@ -91,18 +121,10 @@ public class Diagram {
|
||||
}
|
||||
}
|
||||
|
||||
public Diagram getNext() {
|
||||
return Diagram.createDiagram(graph.getNext(), nodeText, shortNodeText);
|
||||
}
|
||||
|
||||
public Collection<Block> getBlocks() {
|
||||
return Collections.unmodifiableCollection(blocks.values());
|
||||
}
|
||||
|
||||
public Diagram getPrev() {
|
||||
return Diagram.createDiagram(graph.getPrev(), nodeText, shortNodeText);
|
||||
}
|
||||
|
||||
public List<Figure> getFigures() {
|
||||
return Collections.unmodifiableList(figures);
|
||||
}
|
||||
@ -114,10 +136,10 @@ public class Diagram {
|
||||
return f;
|
||||
}
|
||||
|
||||
public Connection createConnection(InputSlot inputSlot, OutputSlot outputSlot, String label, String type) {
|
||||
public FigureConnection createConnection(InputSlot inputSlot, OutputSlot outputSlot, String label) {
|
||||
assert inputSlot.getFigure().getDiagram() == this;
|
||||
assert outputSlot.getFigure().getDiagram() == this;
|
||||
return new Connection(inputSlot, outputSlot, label, type);
|
||||
return new FigureConnection(inputSlot, outputSlot, label);
|
||||
}
|
||||
|
||||
public Map<InputNode, Set<Figure>> calcSourceToFigureRelation() {
|
||||
@ -137,16 +159,13 @@ public class Diagram {
|
||||
}
|
||||
|
||||
public static Diagram createDiagram(InputGraph graph, String nodeText,
|
||||
String shortNodeText) {
|
||||
String shortNodeText,
|
||||
String tinyNodeText) {
|
||||
if (graph == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Diagram d = new Diagram();
|
||||
d.graph = graph;
|
||||
d.nodeText = nodeText;
|
||||
d.shortNodeText = shortNodeText;
|
||||
|
||||
Diagram d = new Diagram(graph, nodeText, shortNodeText, tinyNodeText);
|
||||
d.updateBlocks();
|
||||
|
||||
Collection<InputNode> nodes = graph.getNodes();
|
||||
@ -156,6 +175,7 @@ public class Diagram {
|
||||
f.getSource().addSourceNode(n);
|
||||
f.getProperties().add(n.getProperties());
|
||||
f.setSubgraphs(n.getSubgraphs());
|
||||
f.setBlock(graph.getBlock(n));
|
||||
figureHash.put(n.getId(), f);
|
||||
}
|
||||
|
||||
@ -181,7 +201,7 @@ public class Diagram {
|
||||
}
|
||||
InputSlot inputSlot = toFigure.getInputSlots().get(toIndex);
|
||||
|
||||
Connection c = d.createConnection(inputSlot, outputSlot, e.getLabel(), e.getType());
|
||||
FigureConnection c = d.createConnection(inputSlot, outputSlot, e.getLabel());
|
||||
|
||||
if (e.getState() == InputEdge.State.NEW) {
|
||||
c.setStyle(Connection.ConnectionStyle.BOLD);
|
||||
@ -190,10 +210,30 @@ public class Diagram {
|
||||
}
|
||||
}
|
||||
|
||||
for (InputBlockEdge e : graph.getBlockEdges()) {
|
||||
Block p = d.getBlock(e.getFrom());
|
||||
Block s = d.getBlock(e.getTo());
|
||||
d.blockConnections.add(new BlockConnection(p, s, e.getLabel()));
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
public void removeAllBlocks(Set<Block> blocksToRemove) {
|
||||
Set<Figure> figuresToRemove = new HashSet<>();
|
||||
for (Block b : blocksToRemove) {
|
||||
for (Figure f : getFigures()) {
|
||||
if (f.getBlock() == b.getInputBlock()) {
|
||||
figuresToRemove.add(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
removeAllFigures(figuresToRemove);
|
||||
for (Block b : blocksToRemove) {
|
||||
blocks.remove(b.getInputBlock());
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllFigures(Set<Figure> figuresToRemove) {
|
||||
for (Figure f : figuresToRemove) {
|
||||
freeFigure(f);
|
||||
@ -228,7 +268,6 @@ public class Diagram {
|
||||
}
|
||||
|
||||
public void removeFigure(Figure succ) {
|
||||
|
||||
assert this.figures.contains(succ);
|
||||
freeFigure(succ);
|
||||
this.figures.remove(succ);
|
||||
@ -242,16 +281,24 @@ public class Diagram {
|
||||
return graph;
|
||||
}
|
||||
|
||||
public Set<Connection> getConnections() {
|
||||
|
||||
Set<Connection> connections = new HashSet<>();
|
||||
public Set<FigureConnection> getConnections() {
|
||||
Set<FigureConnection> connections = new HashSet<>();
|
||||
for (Figure f : figures) {
|
||||
|
||||
for (InputSlot s : f.getInputSlots()) {
|
||||
connections.addAll(s.getConnections());
|
||||
}
|
||||
}
|
||||
return connections;
|
||||
}
|
||||
|
||||
public Set<BlockConnection> getBlockConnections() {
|
||||
Set<BlockConnection> connections = new HashSet<>();
|
||||
for (BlockConnection bc : blockConnections) {
|
||||
if (blocks.containsKey(bc.getFromCluster().getInputBlock()) &&
|
||||
blocks.containsKey(bc.getToCluster().getInputBlock())) {
|
||||
connections.add(bc);
|
||||
}
|
||||
}
|
||||
return connections;
|
||||
}
|
||||
|
||||
@ -278,7 +325,7 @@ public class Diagram {
|
||||
System.out.println("Diagram statistics");
|
||||
|
||||
List<Figure> tmpFigures = getFigures();
|
||||
Set<Connection> connections = getConnections();
|
||||
Set<FigureConnection> connections = getConnections();
|
||||
|
||||
System.out.println("Number of figures: " + tmpFigures.size());
|
||||
System.out.println("Number of connections: " + connections.size());
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -31,18 +31,18 @@ import com.sun.hotspot.igv.data.Source;
|
||||
import com.sun.hotspot.igv.layout.Cluster;
|
||||
import com.sun.hotspot.igv.layout.Vertex;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
public class Figure extends Properties.Entity implements Source.Provider, Vertex {
|
||||
|
||||
public static final int INSET = 8;
|
||||
public static int SLOT_WIDTH = 10;
|
||||
public static final int SLOT_WIDTH = 10;
|
||||
public static final int OVERLAPPING = 6;
|
||||
public static final int SLOT_START = 4;
|
||||
public static final int SLOT_OFFSET = 8;
|
||||
public static final boolean VERTICAL_LAYOUT = true;
|
||||
public static final int TOP_CFG_HEIGHT = 7;
|
||||
public static final int BOTTOM_CFG_HEIGHT = 6;
|
||||
protected List<InputSlot> inputSlots;
|
||||
protected List<OutputSlot> outputSlots;
|
||||
private Source source;
|
||||
@ -57,19 +57,33 @@ public class Figure extends Properties.Entity implements Source.Provider, Vertex
|
||||
private String[] lines;
|
||||
private int heightCash = -1;
|
||||
private int widthCash = -1;
|
||||
private InputBlock block;
|
||||
private final FontMetrics metrics;
|
||||
|
||||
public int getHeight() {
|
||||
if (heightCash == -1) {
|
||||
BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics g = image.getGraphics();
|
||||
g.setFont(diagram.getFont().deriveFont(Font.BOLD));
|
||||
FontMetrics metrics = g.getFontMetrics();
|
||||
String nodeText = diagram.getNodeText();
|
||||
heightCash = nodeText.split("\n").length * metrics.getHeight() + INSET;
|
||||
updateHeight();
|
||||
}
|
||||
return heightCash;
|
||||
}
|
||||
|
||||
private void updateHeight() {
|
||||
String nodeText = diagram.getNodeText();
|
||||
int lines = nodeText.split("\n").length;
|
||||
if (hasInputList() && lines > 1) {
|
||||
lines++;
|
||||
}
|
||||
heightCash = lines * metrics.getHeight() + INSET;
|
||||
if (diagram.isCFG()) {
|
||||
if (hasNamedInputSlot()) {
|
||||
heightCash += TOP_CFG_HEIGHT;
|
||||
}
|
||||
if (hasNamedOutputSlot()) {
|
||||
heightCash += BOTTOM_CFG_HEIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> List<T> getAllBefore(List<T> inputList, T tIn) {
|
||||
List<T> result = new ArrayList<>();
|
||||
for(T t : inputList) {
|
||||
@ -91,11 +105,17 @@ public class Figure extends Properties.Entity implements Source.Provider, Vertex
|
||||
|
||||
public int getWidth() {
|
||||
if (widthCash == -1) {
|
||||
updateWidth();
|
||||
}
|
||||
return widthCash;
|
||||
}
|
||||
|
||||
public void setWidth(int width) {
|
||||
widthCash = width;
|
||||
}
|
||||
|
||||
private void updateWidth() {
|
||||
int max = 0;
|
||||
BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics g = image.getGraphics();
|
||||
g.setFont(diagram.getFont().deriveFont(Font.BOLD));
|
||||
FontMetrics metrics = g.getFontMetrics();
|
||||
for (String s : getLines()) {
|
||||
int cur = metrics.stringWidth(s);
|
||||
if (cur > max) {
|
||||
@ -105,8 +125,6 @@ public class Figure extends Properties.Entity implements Source.Provider, Vertex
|
||||
widthCash = max + INSET;
|
||||
widthCash = Math.max(widthCash, Figure.getSlotsWidth(inputSlots));
|
||||
widthCash = Math.max(widthCash, Figure.getSlotsWidth(outputSlots));
|
||||
}
|
||||
return widthCash;
|
||||
}
|
||||
|
||||
protected Figure(Diagram diagram, int id) {
|
||||
@ -121,6 +139,8 @@ public class Figure extends Properties.Entity implements Source.Provider, Vertex
|
||||
|
||||
this.position = new Point(0, 0);
|
||||
this.color = Color.WHITE;
|
||||
Canvas canvas = new Canvas();
|
||||
metrics = canvas.getFontMetrics(diagram.getFont().deriveFont(Font.BOLD));
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
@ -135,6 +155,18 @@ public class Figure extends Properties.Entity implements Source.Provider, Vertex
|
||||
return color;
|
||||
}
|
||||
|
||||
public boolean hasInputList() {
|
||||
return diagram.isCFG() && !getPredecessors().isEmpty();
|
||||
}
|
||||
|
||||
public void setBlock(InputBlock block) {
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
public InputBlock getBlock() {
|
||||
return block;
|
||||
}
|
||||
|
||||
public List<Figure> getPredecessors() {
|
||||
return Collections.unmodifiableList(predecessors);
|
||||
}
|
||||
@ -221,8 +253,8 @@ public class Figure extends Properties.Entity implements Source.Provider, Vertex
|
||||
|
||||
assert inputSlots.contains(s) || outputSlots.contains(s);
|
||||
|
||||
List<Connection> connections = new ArrayList<>(s.getConnections());
|
||||
for (Connection c : connections) {
|
||||
List<FigureConnection> connections = new ArrayList<>(s.getConnections());
|
||||
for (FigureConnection c : connections) {
|
||||
c.remove();
|
||||
}
|
||||
|
||||
@ -261,6 +293,24 @@ public class Figure extends Properties.Entity implements Source.Provider, Vertex
|
||||
return Collections.unmodifiableList(outputSlots);
|
||||
}
|
||||
|
||||
public boolean hasNamedInputSlot() {
|
||||
for (InputSlot is : getInputSlots()) {
|
||||
if (is.hasSourceNodes() && is.shouldShowName()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasNamedOutputSlot() {
|
||||
for (OutputSlot os : getOutputSlots()) {
|
||||
if (os.hasSourceNodes() && os.shouldShowName()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void removeInputSlot(InputSlot s) {
|
||||
s.removeAllConnections();
|
||||
inputSlots.remove(s);
|
||||
@ -274,41 +324,52 @@ public class Figure extends Properties.Entity implements Source.Provider, Vertex
|
||||
public String[] getLines() {
|
||||
if (lines == null) {
|
||||
updateLines();
|
||||
// Set the "label" property of each input node, so that by default
|
||||
// search is done on the node label (without line breaks). See also
|
||||
// class NodeQuickSearch in the View module.
|
||||
for (InputNode n : getSource().getSourceNodes()) {
|
||||
String label = n.getProperties().resolveString(diagram.getNodeText());
|
||||
n.getProperties().setProperty("label", label.replaceAll("\\R", " "));
|
||||
}
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
public void updateLines() {
|
||||
String[] strings = diagram.getNodeText().split("\n");
|
||||
String[] result = new String[strings.length];
|
||||
List<String> result = new ArrayList<>(strings.length + 1);
|
||||
|
||||
for (int i = 0; i < strings.length; i++) {
|
||||
result[i] = getProperties().resolveString(strings[i]);
|
||||
result.add(getProperties().resolveString(strings[i]));
|
||||
}
|
||||
|
||||
lines = result;
|
||||
if (hasInputList()) {
|
||||
String inputList = " ← ";
|
||||
List<String> inputs = new ArrayList<String>(getPredecessors().size());
|
||||
for (Figure p : getPredecessors()) {
|
||||
inputs.add(p.getProperties().resolveString(diagram.getTinyNodeText()));
|
||||
}
|
||||
inputList += String.join(" ", inputs);
|
||||
if (result.size() == 1) {
|
||||
// Single-line node, append input list to line.
|
||||
result.set(0, result.get(0) + inputList);
|
||||
} else {
|
||||
// Multi-line node, add yet another line for input list.
|
||||
result.add(inputList);
|
||||
}
|
||||
}
|
||||
|
||||
lines = result.toArray(new String[0]);
|
||||
// Set the "label" property of each input node, so that by default
|
||||
// search is done on the node label (without line breaks). See also
|
||||
// class NodeQuickSearch in the View module.
|
||||
for (InputNode n : getSource().getSourceNodes()) {
|
||||
String label = n.getProperties().resolveString(diagram.getNodeText());
|
||||
n.getProperties().setProperty("label", label.replaceAll("\\R", " "));
|
||||
}
|
||||
// Update figure dimensions, as these are affected by the node text.
|
||||
updateWidth();
|
||||
updateHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getSize() {
|
||||
if (VERTICAL_LAYOUT) {
|
||||
int width = Math.max(getWidth(), Figure.SLOT_WIDTH * (Math.max(inputSlots.size(), outputSlots.size()) + 1));
|
||||
int height = getHeight() + 2 * Figure.SLOT_WIDTH - 2 * Figure.OVERLAPPING;
|
||||
|
||||
|
||||
return new Dimension(width, height);
|
||||
} else {
|
||||
int width = getWidth() + 2 * Figure.SLOT_WIDTH - 2*Figure.OVERLAPPING;
|
||||
int height = Figure.SLOT_WIDTH * (Math.max(inputSlots.size(), outputSlots.size()) + 1);
|
||||
return new Dimension(width, height);
|
||||
}
|
||||
int width = Math.max(getWidth(), Figure.SLOT_WIDTH * (Math.max(inputSlots.size(), outputSlots.size()) + 1));
|
||||
int height = getHeight() + (diagram.isCFG() ? 0 : 2 * Figure.SLOT_WIDTH - 2 * Figure.OVERLAPPING);
|
||||
return new Dimension(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -316,12 +377,20 @@ public class Figure extends Properties.Entity implements Source.Provider, Vertex
|
||||
return idString;
|
||||
}
|
||||
|
||||
public InputNode getFirstSourceNode() {
|
||||
return getSource().getSourceNodes().get(0);
|
||||
}
|
||||
|
||||
public static int getVerticalOffset() {
|
||||
return Figure.SLOT_WIDTH - Figure.OVERLAPPING;
|
||||
}
|
||||
|
||||
public Cluster getCluster() {
|
||||
if (getSource().getSourceNodes().size() == 0) {
|
||||
assert false : "Should never reach here, every figure must have at least one source node!";
|
||||
return null;
|
||||
} else {
|
||||
final InputBlock inputBlock = diagram.getGraph().getBlock(getSource().getSourceNodes().get(0));
|
||||
final InputBlock inputBlock = diagram.getGraph().getBlock(getFirstSourceNode());
|
||||
assert inputBlock != null;
|
||||
Cluster result = diagram.getBlock(inputBlock);
|
||||
assert result != null;
|
||||
@ -333,8 +402,8 @@ public class Figure extends Properties.Entity implements Source.Provider, Vertex
|
||||
public boolean isRoot() {
|
||||
|
||||
List<InputNode> sourceNodes = source.getSourceNodes();
|
||||
if (sourceNodes.size() > 0 && sourceNodes.get(0).getProperties().get("name") != null) {
|
||||
return source.getSourceNodes().get(0).getProperties().get("name").equals("Root");
|
||||
if (sourceNodes.size() > 0 && getFirstSourceNode().getProperties().get("name") != null) {
|
||||
return getFirstSourceNode().getProperties().get("name").equals("Root");
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
162
src/utils/IdealGraphVisualizer/Graph/src/main/java/com/sun/hotspot/igv/graph/FigureConnection.java
Normal file
162
src/utils/IdealGraphVisualizer/Graph/src/main/java/com/sun/hotspot/igv/graph/FigureConnection.java
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
package com.sun.hotspot.igv.graph;
|
||||
|
||||
import com.sun.hotspot.igv.layout.Port;
|
||||
import com.sun.hotspot.igv.layout.Cluster;
|
||||
import java.awt.Color;
|
||||
import java.awt.Point;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Thomas Wuerthinger
|
||||
*/
|
||||
public class FigureConnection implements Connection {
|
||||
|
||||
private final InputSlot inputSlot;
|
||||
private final OutputSlot outputSlot;
|
||||
private Color color;
|
||||
private ConnectionStyle style;
|
||||
private List<Point> controlPoints;
|
||||
private String label;
|
||||
|
||||
protected FigureConnection(InputSlot inputSlot, OutputSlot outputSlot, String label) {
|
||||
this.inputSlot = inputSlot;
|
||||
this.outputSlot = outputSlot;
|
||||
this.label = label;
|
||||
this.inputSlot.connections.add(this);
|
||||
this.outputSlot.connections.add(this);
|
||||
controlPoints = new ArrayList<>();
|
||||
Figure sourceFigure = this.outputSlot.getFigure();
|
||||
Figure destFigure = this.inputSlot.getFigure();
|
||||
sourceFigure.addSuccessor(destFigure);
|
||||
destFigure.addPredecessor(sourceFigure);
|
||||
|
||||
this.color = Color.BLACK;
|
||||
this.style = ConnectionStyle.NORMAL;
|
||||
}
|
||||
|
||||
public InputSlot getInputSlot() {
|
||||
return inputSlot;
|
||||
}
|
||||
|
||||
public OutputSlot getOutputSlot() {
|
||||
return outputSlot;
|
||||
}
|
||||
|
||||
public Color getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public ConnectionStyle getStyle() {
|
||||
return style;
|
||||
}
|
||||
|
||||
public void setColor(Color c) {
|
||||
color = c;
|
||||
}
|
||||
|
||||
public void setStyle(ConnectionStyle s) {
|
||||
style = s;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
inputSlot.getFigure().removePredecessor(outputSlot.getFigure());
|
||||
inputSlot.connections.remove(this);
|
||||
outputSlot.getFigure().removeSuccessor(inputSlot.getFigure());
|
||||
outputSlot.connections.remove(this);
|
||||
}
|
||||
|
||||
public String getToolTipText() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (label != null) {
|
||||
builder.append(label).append(": ");
|
||||
}
|
||||
// Resolve strings lazily every time the tooltip is shown, instead of
|
||||
// eagerly as for node labels, for efficiency.
|
||||
String shortNodeText = getInputSlot().getFigure().getDiagram().getShortNodeText();
|
||||
builder.append(getOutputSlot().getFigure().getProperties().resolveString(shortNodeText));
|
||||
builder.append(" → ");
|
||||
builder.append(getInputSlot().getFigure().getProperties().resolveString(shortNodeText));
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FigureConnection('" + label + "', " + getFrom().getVertex() + " to " + getTo().getVertex() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Port getFrom() {
|
||||
return outputSlot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cluster getFromCluster() {
|
||||
return getFrom().getVertex().getCluster();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Port getTo() {
|
||||
return inputSlot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cluster getToCluster() {
|
||||
return getTo().getVertex().getCluster();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVIP() {
|
||||
return style == ConnectionStyle.BOLD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Point> getControlPoints() {
|
||||
return controlPoints;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setControlPoints(List<Point> list) {
|
||||
controlPoints = list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlwaysVisible() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSlots() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -47,7 +47,7 @@ public abstract class Slot implements Port, Source.Provider, Properties.Provider
|
||||
|
||||
private int wantedIndex;
|
||||
private Source source;
|
||||
protected List<Connection> connections;
|
||||
protected List<FigureConnection> connections;
|
||||
private InputNode associatedNode;
|
||||
private Color color;
|
||||
private String text;
|
||||
@ -67,7 +67,7 @@ public abstract class Slot implements Port, Source.Provider, Properties.Provider
|
||||
@Override
|
||||
public Properties getProperties() {
|
||||
Properties p = new Properties();
|
||||
if (source.getSourceNodes().size() > 0) {
|
||||
if (hasSourceNodes()) {
|
||||
for (InputNode n : source.getSourceNodes()) {
|
||||
p.add(n.getProperties());
|
||||
}
|
||||
@ -158,6 +158,10 @@ public abstract class Slot implements Port, Source.Provider, Properties.Provider
|
||||
return getShortName() != null && getShortName().length() > 0;
|
||||
}
|
||||
|
||||
public boolean hasSourceNodes() {
|
||||
return !getSource().getSourceNodes().isEmpty();
|
||||
}
|
||||
|
||||
public void setText(String s) {
|
||||
if (s == null) {
|
||||
s = "";
|
||||
@ -178,13 +182,13 @@ public abstract class Slot implements Port, Source.Provider, Properties.Provider
|
||||
color = c;
|
||||
}
|
||||
|
||||
public List<Connection> getConnections() {
|
||||
public List<FigureConnection> getConnections() {
|
||||
return Collections.unmodifiableList(connections);
|
||||
}
|
||||
|
||||
public void removeAllConnections() {
|
||||
List<Connection> connectionsCopy = new ArrayList<>(this.connections);
|
||||
for (Connection c : connectionsCopy) {
|
||||
List<FigureConnection> connectionsCopy = new ArrayList<>(this.connections);
|
||||
for (FigureConnection c : connectionsCopy) {
|
||||
c.remove();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,6 +25,7 @@ package com.sun.hotspot.igv.hierarchicallayout;
|
||||
|
||||
import com.sun.hotspot.igv.layout.Link;
|
||||
import com.sun.hotspot.igv.layout.Port;
|
||||
import com.sun.hotspot.igv.layout.Cluster;
|
||||
import java.awt.Point;
|
||||
import java.util.List;
|
||||
|
||||
@ -53,6 +54,14 @@ public class ClusterEdge implements Link {
|
||||
return from.getInputSlot();
|
||||
}
|
||||
|
||||
public Cluster getFromCluster() {
|
||||
return from.getCluster();
|
||||
}
|
||||
|
||||
public Cluster getToCluster() {
|
||||
return to.getCluster();
|
||||
}
|
||||
|
||||
public void setControlPoints(List<Point> p) {
|
||||
this.points = p;
|
||||
}
|
||||
@ -64,4 +73,9 @@ public class ClusterEdge implements Link {
|
||||
public boolean isVIP() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return from + "->" + to;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,6 +25,7 @@ package com.sun.hotspot.igv.hierarchicallayout;
|
||||
|
||||
import com.sun.hotspot.igv.layout.Link;
|
||||
import com.sun.hotspot.igv.layout.Port;
|
||||
import com.sun.hotspot.igv.layout.Cluster;
|
||||
import java.awt.Point;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -66,6 +67,14 @@ public class ClusterIngoingConnection implements Link {
|
||||
return outputSlot;
|
||||
}
|
||||
|
||||
public Cluster getFromCluster() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Cluster getToCluster() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setControlPoints(List<Point> p) {
|
||||
this.controlPoints = p;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -87,7 +87,7 @@ public class ClusterInputSlotNode implements Vertex {
|
||||
|
||||
public Point getRelativePosition() {
|
||||
Point p = new Point(thisNode.getPosition());
|
||||
p.x += ClusterNode.BORDER;
|
||||
p.x += blockNode.getBorder();
|
||||
p.y = 0;
|
||||
return p;
|
||||
}
|
||||
@ -142,4 +142,5 @@ public class ClusterInputSlotNode implements Vertex {
|
||||
public int compareTo(Vertex o) {
|
||||
return toString().compareTo(o.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -51,14 +51,34 @@ public class ClusterNode implements Vertex {
|
||||
private boolean dirty;
|
||||
private boolean root;
|
||||
private String name;
|
||||
public static final int BORDER = 20;
|
||||
private final int border;
|
||||
private final Dimension nodeOffset;
|
||||
private final int headerVerticalSpace;
|
||||
private final Dimension emptySize;
|
||||
|
||||
public ClusterNode(Cluster cluster, String name) {
|
||||
public ClusterNode(Cluster cluster, String name, int border,
|
||||
Dimension nodeOffset, int headerVerticalSpace,
|
||||
Dimension emptySize) {
|
||||
this.subNodes = new HashSet<Vertex>();
|
||||
this.subEdges = new HashSet<Link>();
|
||||
this.cluster = cluster;
|
||||
position = new Point(0, 0);
|
||||
this.name = name;
|
||||
this.border = border;
|
||||
this.nodeOffset = nodeOffset;
|
||||
this.headerVerticalSpace = headerVerticalSpace;
|
||||
this.emptySize = emptySize;
|
||||
if (emptySize.width > 0 || emptySize.height > 0) {
|
||||
updateSize();
|
||||
}
|
||||
}
|
||||
|
||||
public ClusterNode(Cluster cluster, String name) {
|
||||
this(cluster, name, 20, new Dimension(0, 0), 0, new Dimension(0, 0));
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void addSubNode(Vertex v) {
|
||||
@ -88,6 +108,11 @@ public class ClusterNode implements Vertex {
|
||||
public Vertex getVertex() {
|
||||
return widget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ClusterInput(" + name + ")";
|
||||
}
|
||||
};
|
||||
|
||||
outputSlot = new Port() {
|
||||
@ -99,13 +124,19 @@ public class ClusterNode implements Vertex {
|
||||
public Vertex getVertex() {
|
||||
return widget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ClusterOutput(" + name + ")";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void calculateSize() {
|
||||
|
||||
if (subNodes.size() == 0) {
|
||||
size = new Dimension(0, 0);
|
||||
if (subNodes.isEmpty()) {
|
||||
size = emptySize;
|
||||
return;
|
||||
}
|
||||
|
||||
int minX = Integer.MAX_VALUE;
|
||||
@ -134,11 +165,12 @@ public class ClusterNode implements Vertex {
|
||||
}
|
||||
}
|
||||
|
||||
size = new Dimension(maxX - minX, maxY - minY);
|
||||
size = new Dimension(maxX - minX, maxY - minY + headerVerticalSpace);
|
||||
|
||||
// Normalize coordinates
|
||||
for (Vertex n : subNodes) {
|
||||
n.setPosition(new Point(n.getPosition().x - minX, n.getPosition().y - minY));
|
||||
n.setPosition(new Point(n.getPosition().x - minX + nodeOffset.width,
|
||||
n.getPosition().y - minY + nodeOffset.height + headerVerticalSpace));
|
||||
}
|
||||
|
||||
for (Link l : subEdges) {
|
||||
@ -151,8 +183,8 @@ public class ClusterNode implements Vertex {
|
||||
|
||||
}
|
||||
|
||||
size.width += 2 * BORDER;
|
||||
size.height += 2 * BORDER;
|
||||
size.width += 2 * border;
|
||||
size.height += 2 * border;
|
||||
}
|
||||
|
||||
public Port getInputSlot() {
|
||||
@ -177,7 +209,7 @@ public class ClusterNode implements Vertex {
|
||||
this.position = pos;
|
||||
for (Vertex n : subNodes) {
|
||||
Point cur = new Point(n.getPosition());
|
||||
cur.translate(pos.x + BORDER, pos.y + BORDER);
|
||||
cur.translate(pos.x + border, pos.y + border);
|
||||
n.setPosition(cur);
|
||||
}
|
||||
|
||||
@ -187,7 +219,7 @@ public class ClusterNode implements Vertex {
|
||||
for (Point p : arr) {
|
||||
if (p != null) {
|
||||
Point p2 = new Point(p);
|
||||
p2.translate(pos.x + BORDER, pos.y + BORDER);
|
||||
p2.translate(pos.x + border, pos.y + border);
|
||||
newArr.add(p2);
|
||||
} else {
|
||||
newArr.add(null);
|
||||
@ -218,6 +250,10 @@ public class ClusterNode implements Vertex {
|
||||
return root;
|
||||
}
|
||||
|
||||
public int getBorder() {
|
||||
return border;
|
||||
}
|
||||
|
||||
public int compareTo(Vertex o) {
|
||||
return toString().compareTo(o.toString());
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,6 +25,7 @@ package com.sun.hotspot.igv.hierarchicallayout;
|
||||
|
||||
import com.sun.hotspot.igv.layout.Link;
|
||||
import com.sun.hotspot.igv.layout.Port;
|
||||
import com.sun.hotspot.igv.layout.Cluster;
|
||||
import java.awt.Point;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -58,6 +59,14 @@ public class ClusterOutgoingConnection implements Link {
|
||||
return outputSlot;
|
||||
}
|
||||
|
||||
public Cluster getFromCluster() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Cluster getToCluster() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setControlPoints(List<Point> p) {
|
||||
this.intermediatePoints = p;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -87,7 +87,7 @@ public class ClusterOutputSlotNode implements Vertex {
|
||||
|
||||
public Point getRelativePosition() {
|
||||
Point p = new Point(thisNode.getPosition());
|
||||
p.x += ClusterNode.BORDER;
|
||||
p.x += blockNode.getBorder();
|
||||
p.y = 0;//thisBlockNode.getSize().height;
|
||||
return p;
|
||||
}
|
||||
@ -142,4 +142,5 @@ public class ClusterOutputSlotNode implements Vertex {
|
||||
public int compareTo(Vertex o) {
|
||||
return toString().compareTo(o.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
155
src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/HierarchicalCFGLayoutManager.java
Normal file
155
src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/HierarchicalCFGLayoutManager.java
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
package com.sun.hotspot.igv.hierarchicallayout;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Canvas;
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
import java.util.*;
|
||||
import com.sun.hotspot.igv.layout.Cluster;
|
||||
import com.sun.hotspot.igv.layout.LayoutGraph;
|
||||
import com.sun.hotspot.igv.layout.LayoutManager;
|
||||
import com.sun.hotspot.igv.layout.Link;
|
||||
import com.sun.hotspot.igv.layout.Vertex;
|
||||
|
||||
public class HierarchicalCFGLayoutManager implements LayoutManager {
|
||||
|
||||
private static final int BLOCK_BORDER = 5;
|
||||
private FontMetrics fontMetrics;
|
||||
// Lays out nodes within a single cluster (basic block).
|
||||
private LayoutManager subManager;
|
||||
// Lays out clusters in the CFG.
|
||||
private LayoutManager manager;
|
||||
private Set<Cluster> clusters;
|
||||
|
||||
public HierarchicalCFGLayoutManager() {
|
||||
// Anticipate block label sizes to dimension blocks appropriately.
|
||||
Canvas canvas = new Canvas();
|
||||
Font font = new Font("Arial", Font.BOLD, 14);
|
||||
fontMetrics = canvas.getFontMetrics(font);
|
||||
}
|
||||
|
||||
public void setSubManager(LayoutManager manager) {
|
||||
this.subManager = manager;
|
||||
}
|
||||
|
||||
public void setManager(LayoutManager manager) {
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
public void setClusters(Set<Cluster> clusters) {
|
||||
this.clusters = clusters;
|
||||
}
|
||||
|
||||
public void doLayout(LayoutGraph graph, Set<? extends Link> importantLinks) {
|
||||
doLayout(graph);
|
||||
}
|
||||
|
||||
public void doLayout(LayoutGraph graph) {
|
||||
|
||||
// Create cluster-level nodes and edges.
|
||||
Map<Cluster, ClusterNode> clusterNode = createClusterNodes(graph);
|
||||
Set<ClusterEdge> clusterEdges = createClusterEdges(clusterNode);
|
||||
markRootClusters(clusterEdges);
|
||||
|
||||
// Compute layout for each cluster.
|
||||
for (Cluster c : clusters) {
|
||||
ClusterNode n = clusterNode.get(c);
|
||||
subManager.doLayout(new LayoutGraph(n.getSubEdges(), n.getSubNodes()), new HashSet<Link>());
|
||||
n.updateSize();
|
||||
}
|
||||
|
||||
// Compute inter-cluster layout.
|
||||
manager.doLayout(new LayoutGraph(clusterEdges, new HashSet<>(clusterNode.values())),
|
||||
new HashSet<Link>());
|
||||
|
||||
// Write back results.
|
||||
writeBackClusterBounds(clusterNode);
|
||||
writeBackClusterEdgePoints(graph, clusterEdges);
|
||||
}
|
||||
|
||||
private Map<Cluster, ClusterNode> createClusterNodes(LayoutGraph graph) {
|
||||
Map<Cluster, ClusterNode> clusterNode = new HashMap<>();
|
||||
for (Cluster c : clusters) {
|
||||
String blockLabel = "B" + c;
|
||||
Dimension emptySize = new Dimension(fontMetrics.stringWidth(blockLabel) + BLOCK_BORDER * 2,
|
||||
fontMetrics.getHeight() + BLOCK_BORDER);
|
||||
ClusterNode cn = new ClusterNode(c, c.toString(), BLOCK_BORDER, c.getNodeOffset(),
|
||||
fontMetrics.getHeight(), emptySize);
|
||||
clusterNode.put(c, cn);
|
||||
}
|
||||
|
||||
for (Vertex v : graph.getVertices()) {
|
||||
Cluster c = v.getCluster();
|
||||
assert c != null : "Cluster of vertex " + v + " is null!";
|
||||
clusterNode.get(c).addSubNode(v);
|
||||
}
|
||||
return clusterNode;
|
||||
}
|
||||
|
||||
private Set<ClusterEdge> createClusterEdges(Map<Cluster, ClusterNode> clusterNode) {
|
||||
Set<ClusterEdge> clusterEdges = new HashSet<>();
|
||||
for (Cluster c : clusters) {
|
||||
ClusterNode start = clusterNode.get(c);
|
||||
for (Cluster succ : c.getSuccessors()) {
|
||||
ClusterNode end = clusterNode.get(succ);
|
||||
if (end != null) {
|
||||
ClusterEdge e = new ClusterEdge(start, end);
|
||||
clusterEdges.add(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return clusterEdges;
|
||||
}
|
||||
|
||||
private void markRootClusters(Set<ClusterEdge> clusterEdges) {
|
||||
Set<Vertex> roots = new LayoutGraph(clusterEdges).findRootVertices();
|
||||
for (Vertex v : roots) {
|
||||
assert v instanceof ClusterNode;
|
||||
((ClusterNode) v).setRoot(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeBackClusterBounds(Map<Cluster, ClusterNode> clusterNode) {
|
||||
for (Cluster c : clusters) {
|
||||
ClusterNode n = clusterNode.get(c);
|
||||
c.setBounds(new Rectangle(n.getPosition(), n.getSize()));
|
||||
}
|
||||
}
|
||||
|
||||
private void writeBackClusterEdgePoints(LayoutGraph graph, Set<ClusterEdge> clusterEdges) {
|
||||
// Map from "primitive" cluster edges to their input links.
|
||||
Map<AbstractMap.SimpleEntry<Cluster, Cluster>, Link> inputLink = new HashMap<>();
|
||||
for (Link l : graph.getLinks()) {
|
||||
inputLink.put(new AbstractMap.SimpleEntry<Cluster, Cluster>(l.getFromCluster(), l.getToCluster()), l);
|
||||
}
|
||||
for (ClusterEdge ce : clusterEdges) {
|
||||
assert (ce.getControlPoints() != null);
|
||||
Link l = inputLink.get(new AbstractMap.SimpleEntry<Cluster, Cluster>(ce.getFromCluster(), ce.getToCluster()));
|
||||
l.setControlPoints(ce.getControlPoints());
|
||||
}
|
||||
}
|
||||
}
|
@ -245,7 +245,4 @@ public class HierarchicalClusterLayoutManager implements LayoutManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void doRouting(LayoutGraph graph) {
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -63,8 +63,10 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
private int layerOffset;
|
||||
private int maxLayerLength;
|
||||
private int minLayerDifference;
|
||||
private boolean layoutSelfEdges;
|
||||
// Algorithm global datastructures
|
||||
private Set<Link> reversedLinks;
|
||||
private Set<LayoutEdge> selfEdges;
|
||||
private List<LayoutNode> nodes;
|
||||
private HashMap<Vertex, LayoutNode> vertexToLayoutNode;
|
||||
private HashMap<Link, List<Point>> reversedLinkStartPoints;
|
||||
@ -108,10 +110,17 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
|
||||
public LayoutNode from;
|
||||
public LayoutNode to;
|
||||
// Horizontal distance relative to start of 'from'.
|
||||
public int relativeFrom;
|
||||
// Horizontal distance relative to start of 'to'.
|
||||
public int relativeTo;
|
||||
public Link link;
|
||||
public boolean vip;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Edge " + from + ", " + to;
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class AlgorithmPart {
|
||||
@ -162,9 +171,18 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
this.layerOffset = LAYER_OFFSET;
|
||||
this.maxLayerLength = MAX_LAYER_LENGTH;
|
||||
this.minLayerDifference = MIN_LAYER_DIFFERENCE;
|
||||
this.layoutSelfEdges = false;
|
||||
this.linksToFollow = new HashSet<>();
|
||||
}
|
||||
|
||||
public void setXOffset(int xOffset) {
|
||||
this.xOffset = xOffset;
|
||||
}
|
||||
|
||||
public void setLayerOffset(int layerOffset) {
|
||||
this.layerOffset = layerOffset;
|
||||
}
|
||||
|
||||
public int getMaxLayerLength() {
|
||||
return maxLayerLength;
|
||||
}
|
||||
@ -177,6 +195,25 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
minLayerDifference = v;
|
||||
}
|
||||
|
||||
public void setLayoutSelfEdges(boolean layoutSelfEdges) {
|
||||
this.layoutSelfEdges = layoutSelfEdges;
|
||||
}
|
||||
|
||||
// Remove self-edges, possibly saving them into the selfEdges set.
|
||||
private void removeSelfEdges(boolean save) {
|
||||
for (LayoutNode node : nodes) {
|
||||
for (LayoutEdge e : new ArrayList<>(node.succs)) {
|
||||
if (e.to == node) {
|
||||
if (save) {
|
||||
selfEdges.add(e);
|
||||
}
|
||||
node.succs.remove(e);
|
||||
node.preds.remove(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doLayout(LayoutGraph graph) {
|
||||
doLayout(graph, new HashSet<Link>());
|
||||
@ -191,6 +228,7 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
|
||||
vertexToLayoutNode = new HashMap<>();
|
||||
reversedLinks = new HashSet<>();
|
||||
selfEdges = new HashSet<>();
|
||||
reversedLinkStartPoints = new HashMap<>();
|
||||
reversedLinkEndPoints = new HashMap<>();
|
||||
bottomEdgeHash = new HashMap<>();
|
||||
@ -202,6 +240,11 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
// Step 1: Build up data structure
|
||||
new BuildDatastructure().start();
|
||||
|
||||
if (!layoutSelfEdges) {
|
||||
// Remove self-edges from the beginning.
|
||||
removeSelfEdges(false);
|
||||
}
|
||||
|
||||
// #############################################################
|
||||
// STEP 2: Reverse edges, handle backedges
|
||||
new ReverseEdges().start();
|
||||
@ -220,6 +263,9 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
}
|
||||
}
|
||||
|
||||
// Hide self-edges from the layout algorithm and save them for later.
|
||||
removeSelfEdges(true);
|
||||
|
||||
// #############################################################
|
||||
// STEP 3: Assign layers
|
||||
new AssignLayers().start();
|
||||
@ -240,6 +286,12 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
// STEP 6: Assign Y coordinates
|
||||
new AssignYCoordinates().start();
|
||||
|
||||
// Put saved self-edges back so that they are assigned points.
|
||||
for (LayoutEdge e : selfEdges) {
|
||||
e.from.succs.add(e);
|
||||
e.to.preds.add(e);
|
||||
}
|
||||
|
||||
// #############################################################
|
||||
// STEP 8: Write back to interface
|
||||
new WriteResult().start();
|
||||
@ -322,6 +374,11 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
} else {
|
||||
if (reversedLinks.contains(e.link)) {
|
||||
Collections.reverse(points);
|
||||
if (selfEdges.contains(e)) {
|
||||
// For self edges, it is enough with the
|
||||
// start and end points computed by ReverseEdges.
|
||||
points.clear();
|
||||
}
|
||||
}
|
||||
if (reversedLinkStartPoints.containsKey(e.link)) {
|
||||
for (Point p1 : reversedLinkStartPoints.get(e.link)) {
|
||||
@ -351,7 +408,11 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
Point p = new Point(e.from.x + e.relativeFrom, e.from.y + e.from.height - e.from.bottomYOffset + e.link.getFrom().getRelativePosition().y);
|
||||
points.add(p);
|
||||
if (e.from.outOffsets.containsKey(e.relativeFrom)) {
|
||||
points.add(new Point(p.x, p.y + e.from.outOffsets.get(e.relativeFrom) + e.link.getFrom().getRelativePosition().y));
|
||||
Point pOffset = new Point(p.x, p.y + e.from.outOffsets.get(e.relativeFrom) +
|
||||
e.link.getFrom().getRelativePosition().y + e.from.yOffset);
|
||||
if (!pOffset.equals(p)) {
|
||||
points.add(pOffset);
|
||||
}
|
||||
}
|
||||
|
||||
LayoutNode cur = e.to;
|
||||
@ -404,12 +465,12 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
|
||||
if (reversedLinkStartPoints.containsKey(e.link)) {
|
||||
for (Point p1 : reversedLinkStartPoints.get(e.link)) {
|
||||
points.add(0, new Point(p1.x + other.x, p1.y + other.y));
|
||||
points.add(0, new Point(p1.x + other.x + other.xOffset, p1.y + other.y));
|
||||
}
|
||||
}
|
||||
if (reversedLinkEndPoints.containsKey(e.link)) {
|
||||
for (Point p1 : reversedLinkEndPoints.get(e.link)) {
|
||||
points.add(new Point(p1.x + cur.x, p1.y + cur.y));
|
||||
points.add(new Point(p1.x + cur.x + cur.xOffset, p1.y + cur.y));
|
||||
}
|
||||
}
|
||||
if (reversedLinks.contains(e.link)) {
|
||||
@ -879,7 +940,7 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
|
||||
for (LayoutNode n : layers[index]) {
|
||||
n.x = x;
|
||||
x += n.width + X_OFFSET;
|
||||
x += n.width + xOffset;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1446,18 +1507,6 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
@Override
|
||||
protected void run() {
|
||||
|
||||
// Remove self-edges
|
||||
for (LayoutNode node : nodes) {
|
||||
ArrayList<LayoutEdge> succs = new ArrayList<>(node.succs);
|
||||
for (LayoutEdge e : succs) {
|
||||
assert e.from == node;
|
||||
if (e.to == node) {
|
||||
node.succs.remove(e);
|
||||
node.preds.remove(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reverse inputs of roots
|
||||
for (LayoutNode node : nodes) {
|
||||
if (node.vertex.isRoot()) {
|
||||
@ -1485,17 +1534,27 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
|
||||
SortedSet<Integer> reversedDown = new TreeSet<>();
|
||||
|
||||
boolean hasSelfEdge = false;
|
||||
for (LayoutEdge e : node.succs) {
|
||||
if (reversedLinks.contains(e.link)) {
|
||||
reversedDown.add(e.relativeFrom);
|
||||
if (e.from == e.to) {
|
||||
hasSelfEdge = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Whether the node has non-self reversed edges going downwards.
|
||||
// If so, reversed edges going upwards are drawn to the left.
|
||||
boolean hasReversedDown =
|
||||
reversedDown.size() > 0 &&
|
||||
!(reversedDown.size() == 1 && hasSelfEdge);
|
||||
|
||||
SortedSet<Integer> reversedUp = null;
|
||||
if (reversedDown.size() == 0) {
|
||||
reversedUp = new TreeSet<>(Collections.reverseOrder());
|
||||
} else {
|
||||
if (hasReversedDown) {
|
||||
reversedUp = new TreeSet<>();
|
||||
} else {
|
||||
reversedUp = new TreeSet<>(Collections.reverseOrder());
|
||||
}
|
||||
|
||||
for (LayoutEdge e : node.preds) {
|
||||
@ -1504,7 +1563,7 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
}
|
||||
}
|
||||
|
||||
final int offset = X_OFFSET + DUMMY_WIDTH;
|
||||
final int offset = xOffset + DUMMY_WIDTH;
|
||||
|
||||
int curX = 0;
|
||||
int curWidth = node.width + reversedDown.size() * offset;
|
||||
@ -1531,17 +1590,22 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
node.yOffset += offset;
|
||||
curWidth -= offset;
|
||||
}
|
||||
node.width += reversedDown.size() * offset;
|
||||
|
||||
if (reversedDown.size() == 0) {
|
||||
curX = offset;
|
||||
} else {
|
||||
int widthFactor = reversedDown.size();
|
||||
if (hasSelfEdge) {
|
||||
widthFactor--;
|
||||
}
|
||||
node.width += widthFactor * offset;
|
||||
|
||||
if (hasReversedDown) {
|
||||
curX = -offset;
|
||||
} else {
|
||||
curX = offset;
|
||||
}
|
||||
|
||||
curX = 0;
|
||||
int minX = 0;
|
||||
if (reversedDown.size() != 0) {
|
||||
if (hasReversedDown) {
|
||||
minX = -offset * reversedUp.size();
|
||||
}
|
||||
|
||||
@ -1550,10 +1614,10 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
ArrayList<LayoutEdge> reversedPreds = new ArrayList<>();
|
||||
for (LayoutEdge e : node.preds) {
|
||||
if (e.relativeTo == pos && reversedLinks.contains(e.link)) {
|
||||
if (reversedDown.size() == 0) {
|
||||
e.relativeTo = node.width + offset;
|
||||
} else {
|
||||
if (hasReversedDown) {
|
||||
e.relativeTo = curX - offset;
|
||||
} else {
|
||||
e.relativeTo = node.width + offset;
|
||||
}
|
||||
|
||||
reversedPreds.add(e);
|
||||
@ -1562,16 +1626,13 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
node.height += offset;
|
||||
ArrayList<Point> endPoints = new ArrayList<>();
|
||||
|
||||
if (reversedDown.size() == 0) {
|
||||
|
||||
curX += offset;
|
||||
node.width += offset;
|
||||
endPoints.add(new Point(node.width, node.height));
|
||||
|
||||
} else {
|
||||
node.width += offset;
|
||||
if (hasReversedDown) {
|
||||
curX -= offset;
|
||||
node.width += offset;
|
||||
endPoints.add(new Point(curX, node.height));
|
||||
} else {
|
||||
curX += offset;
|
||||
endPoints.add(new Point(node.width, node.height));
|
||||
}
|
||||
|
||||
node.outOffsets.put(pos - minX, curX);
|
||||
@ -1735,7 +1796,12 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
protected void run() {
|
||||
// Set up nodes
|
||||
List<Vertex> vertices = new ArrayList<>(graph.getVertices());
|
||||
Collections.sort(vertices);
|
||||
// Order roots first to create more natural layer assignments.
|
||||
Collections.sort(vertices,
|
||||
(Vertex a, Vertex b) ->
|
||||
a.isRoot() == b.isRoot() ?
|
||||
a.compareTo(b) :
|
||||
Boolean.compare(b.isRoot(), a.isRoot()));
|
||||
|
||||
for (Vertex v : vertices) {
|
||||
LayoutNode node = new LayoutNode();
|
||||
@ -1762,7 +1828,6 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
edge.vip = l.isVIP();
|
||||
edge.from.succs.add(edge);
|
||||
edge.to.preds.add(edge);
|
||||
//assert edge.from != edge.to; // No self-loops allowed
|
||||
}
|
||||
|
||||
for (Link l : importantLinks) {
|
||||
@ -1802,9 +1867,4 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRouting(LayoutGraph graph) {
|
||||
// Do nothing for now
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,6 +25,7 @@ package com.sun.hotspot.igv.hierarchicallayout;
|
||||
|
||||
import com.sun.hotspot.igv.layout.Link;
|
||||
import com.sun.hotspot.igv.layout.Port;
|
||||
import com.sun.hotspot.igv.layout.Cluster;
|
||||
import java.awt.Point;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -61,6 +62,14 @@ public class InterClusterConnection implements Link {
|
||||
return outputSlot;
|
||||
}
|
||||
|
||||
public Cluster getFromCluster() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Cluster getToCluster() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setControlPoints(List<Point> p) {
|
||||
this.intermediatePoints = p;
|
||||
}
|
||||
|
67
src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/LinearLayoutManager.java
Normal file
67
src/utils/IdealGraphVisualizer/HierarchicalLayout/src/main/java/com/sun/hotspot/igv/hierarchicallayout/LinearLayoutManager.java
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
package com.sun.hotspot.igv.hierarchicallayout;
|
||||
|
||||
import com.sun.hotspot.igv.layout.LayoutGraph;
|
||||
import com.sun.hotspot.igv.layout.LayoutManager;
|
||||
import com.sun.hotspot.igv.layout.Link;
|
||||
import com.sun.hotspot.igv.layout.Vertex;
|
||||
import java.awt.Point;
|
||||
import java.util.*;
|
||||
|
||||
public class LinearLayoutManager implements LayoutManager {
|
||||
|
||||
// Ranking determining the vertical node ordering.
|
||||
private final Map<? extends Vertex, Integer> vertexRank;
|
||||
|
||||
public LinearLayoutManager(Map<? extends Vertex, Integer> vertexRank) {
|
||||
this.vertexRank = vertexRank;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doLayout(LayoutGraph graph) {
|
||||
doLayout(graph, new HashSet<Link>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doLayout(LayoutGraph graph, Set<? extends Link> importantLinks) {
|
||||
|
||||
assert (graph.getLinks().isEmpty());
|
||||
|
||||
// Sort vertices according to given rank.
|
||||
List<Vertex> vertices = new ArrayList<>(graph.getVertices());
|
||||
vertices.sort(Comparator.comparingInt((Vertex v) -> vertexRank.getOrDefault(v, Integer.MAX_VALUE)));
|
||||
|
||||
// Assign vertical coordinates in rank order.
|
||||
assignVerticalCoordinates(vertices);
|
||||
}
|
||||
|
||||
private void assignVerticalCoordinates(List<Vertex> vertices) {
|
||||
int curY = 0;
|
||||
for (Vertex v : vertices) {
|
||||
v.setPosition(new Point(0, curY));
|
||||
curY += v.getSize().getHeight();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,6 +23,7 @@
|
||||
*/
|
||||
package com.sun.hotspot.igv.layout;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Rectangle;
|
||||
import java.util.Set;
|
||||
|
||||
@ -37,4 +38,6 @@ public interface Cluster extends Comparable<Cluster> {
|
||||
public void setBounds(Rectangle r);
|
||||
|
||||
public Set<? extends Cluster> getSuccessors();
|
||||
|
||||
public Dimension getNodeOffset();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -51,6 +51,9 @@ public class LayoutGraph {
|
||||
outputPorts = new HashMap<>(links.size());
|
||||
|
||||
for (Link l : links) {
|
||||
if (l.getFrom() == null || l.getTo() == null) {
|
||||
continue;
|
||||
}
|
||||
Port p = l.getFrom();
|
||||
Port p2 = l.getTo();
|
||||
Vertex v1 = p.getVertex();
|
||||
@ -195,4 +198,9 @@ public class LayoutGraph {
|
||||
|
||||
return clusters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LayoutGraph(" + vertices + ", " + links + ", " + getClusters() + ")";
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,4 @@ public interface LayoutManager {
|
||||
public void doLayout(LayoutGraph graph);
|
||||
|
||||
public void doLayout(LayoutGraph graph, Set<? extends Link> importantLinks);
|
||||
|
||||
public void doRouting(LayoutGraph graph);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -34,8 +34,12 @@ public interface Link {
|
||||
|
||||
public Port getFrom();
|
||||
|
||||
public Cluster getFromCluster();
|
||||
|
||||
public Port getTo();
|
||||
|
||||
public Cluster getToCluster();
|
||||
|
||||
public boolean isVIP();
|
||||
|
||||
public List<Point> getControlPoints();
|
||||
|
@ -30,6 +30,7 @@ import com.sun.hotspot.igv.data.InputGraph;
|
||||
import com.sun.hotspot.igv.data.InputNode;
|
||||
import com.sun.hotspot.igv.data.services.Scheduler;
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
import org.openide.ErrorManager;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import com.ibm.wala.util.graph.Graph;
|
||||
@ -52,6 +53,38 @@ public class ServerCompilerScheduler implements Scheduler {
|
||||
public boolean isBlockProjection;
|
||||
public boolean isBlockStart;
|
||||
public boolean isCFG;
|
||||
public int rank; // Rank for local scheduling priority.
|
||||
|
||||
public Node(InputNode n) {
|
||||
inputNode = n;
|
||||
String p = n.getProperties().get("is_block_proj");
|
||||
isBlockProjection = (p != null && p.equals("true"));
|
||||
p = n.getProperties().get("is_block_start");
|
||||
isBlockStart = (p != null && p.equals("true"));
|
||||
computeRank();
|
||||
}
|
||||
|
||||
// Rank by local scheduling priority.
|
||||
private void computeRank() {
|
||||
if (isBlockStart || isOtherBlockStart(this)) {
|
||||
rank = 1;
|
||||
} else if (isPhi(this)) {
|
||||
rank = 2;
|
||||
} else if (isParm(this)) {
|
||||
rank = 3;
|
||||
} else if (isProj(this)) {
|
||||
rank = 4;
|
||||
} else if (!isControl(this)) { // Every other node except terminators.
|
||||
rank = 5;
|
||||
} else {
|
||||
rank = 6;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return inputNode.getProperties().get("idx") + " " + inputNode.getProperties().get("name");
|
||||
}
|
||||
}
|
||||
private InputGraph graph;
|
||||
private Collection<Node> nodes;
|
||||
@ -80,15 +113,17 @@ public class ServerCompilerScheduler implements Scheduler {
|
||||
Set<Node> visited = new HashSet<>();
|
||||
Map<InputBlock, Set<Node>> terminators = new HashMap<>();
|
||||
// Pre-compute control successors of each node, excluding self edges.
|
||||
Map<Node, Set<Node>> controlSuccs = new HashMap<>();
|
||||
Map<Node, List<Node>> controlSuccs = new HashMap<>();
|
||||
for (Node n : nodes) {
|
||||
if (n.isCFG) {
|
||||
Set<Node> nControlSuccs = new HashSet<>();
|
||||
List<Node> nControlSuccs = new ArrayList<>();
|
||||
for (Node s : n.succs) {
|
||||
if (s.isCFG && s != n) {
|
||||
nControlSuccs.add(s);
|
||||
}
|
||||
}
|
||||
// Ensure that the block ordering is deterministic.
|
||||
nControlSuccs.sort(Comparator.comparingInt((Node a) -> a.inputNode.getId()));
|
||||
controlSuccs.put(n, nControlSuccs);
|
||||
}
|
||||
}
|
||||
@ -173,7 +208,18 @@ public class ServerCompilerScheduler implements Scheduler {
|
||||
}
|
||||
}
|
||||
for (Node s : uniqueSuccs) {
|
||||
graph.addBlockEdge(terms.getKey(), s.block);
|
||||
// Label the block edge with the short name of the corresponding
|
||||
// control projection, if any.
|
||||
String label = null;
|
||||
if (terms.getValue().size() > 1) {
|
||||
for (Node t : terms.getValue()) {
|
||||
if (s.preds.contains(t)) {
|
||||
label = t.inputNode.getProperties().get("short_name");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
graph.addBlockEdge(terms.getKey(), s.block, label);
|
||||
}
|
||||
}
|
||||
|
||||
@ -237,7 +283,7 @@ public class ServerCompilerScheduler implements Scheduler {
|
||||
for (InputNode n : graph.getNodes()) {
|
||||
if (graph.getBlock(n) == null) {
|
||||
if (noBlock == null) {
|
||||
noBlock = graph.addBlock("(no block)");
|
||||
noBlock = graph.addArtificialBlock();
|
||||
blocks.add(noBlock);
|
||||
}
|
||||
|
||||
@ -246,10 +292,104 @@ public class ServerCompilerScheduler implements Scheduler {
|
||||
assert graph.getBlock(n) != null;
|
||||
}
|
||||
|
||||
scheduleLocal();
|
||||
|
||||
return blocks;
|
||||
}
|
||||
}
|
||||
|
||||
private void scheduleLocal() {
|
||||
// Leave only local predecessors and successors.
|
||||
for (InputBlock b : blocks) {
|
||||
for (InputNode in : b.getNodes()) {
|
||||
Node n = inputNodeToNode.get(in);
|
||||
Predicate<Node> excludePredecessors =
|
||||
node -> isPhi(node) || node.isBlockStart;
|
||||
List<Node> localPreds = new ArrayList<>(n.preds.size());
|
||||
for (Node p : n.preds) {
|
||||
if (p.block == b && p != n && !excludePredecessors.test(n)) {
|
||||
localPreds.add(p);
|
||||
}
|
||||
}
|
||||
n.preds = localPreds;
|
||||
Set<Node> localSuccs = new HashSet<>(n.succs.size());
|
||||
for (Node s : n.succs) {
|
||||
if (s.block == b && s != n && !excludePredecessors.test(s)) {
|
||||
localSuccs.add(s);
|
||||
}
|
||||
}
|
||||
n.succs = localSuccs;
|
||||
}
|
||||
}
|
||||
// Schedule each block independently.
|
||||
for (InputBlock b : blocks) {
|
||||
List<Node> nodes = new ArrayList<>(b.getNodes().size());
|
||||
for (InputNode n : b.getNodes()) {
|
||||
nodes.add(inputNodeToNode.get(n));
|
||||
}
|
||||
List<InputNode> schedule = scheduleBlock(nodes);
|
||||
b.setNodes(schedule);
|
||||
}
|
||||
}
|
||||
|
||||
private static final Comparator<Node> schedulePriority = new Comparator<Node>(){
|
||||
@Override
|
||||
public int compare(Node n1, Node n2) {
|
||||
// Order by rank, then idx.
|
||||
int r1 = n1.rank, r2 = n2.rank;
|
||||
int o1, o2;
|
||||
if (r1 != r2) { // Different rank.
|
||||
o1 = r1;
|
||||
o2 = r2;
|
||||
} else { // Same rank, order by idx.
|
||||
o1 = Integer.parseInt(n1.inputNode.getProperties().get("idx"));
|
||||
o2 = Integer.parseInt(n2.inputNode.getProperties().get("idx"));
|
||||
}
|
||||
return Integer.compare(o1, o2);
|
||||
};
|
||||
};
|
||||
|
||||
private List<InputNode> scheduleBlock(Collection<Node> nodes) {
|
||||
List<InputNode> schedule = new ArrayList<InputNode>();
|
||||
|
||||
// Initialize ready priority queue with nodes without predecessors.
|
||||
Queue<Node> ready = new PriorityQueue<Node>(schedulePriority);
|
||||
// Set of nodes that have been enqueued.
|
||||
Set<Node> visited = new HashSet<Node>(nodes.size());
|
||||
for (Node n : nodes) {
|
||||
if (n.preds.isEmpty()) {
|
||||
ready.add(n);
|
||||
visited.add(n);
|
||||
}
|
||||
}
|
||||
|
||||
// Classic list scheduling algorithm.
|
||||
while (!ready.isEmpty()) {
|
||||
Node n = ready.remove();
|
||||
schedule.add(n.inputNode);
|
||||
|
||||
// Add nodes that are now ready after scheduling n.
|
||||
for (Node s : n.succs) {
|
||||
if (visited.contains(s)) {
|
||||
continue;
|
||||
}
|
||||
boolean allPredsScheduled = true;
|
||||
for (Node p : s.preds) {
|
||||
if (!visited.contains(p)) {
|
||||
allPredsScheduled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allPredsScheduled) {
|
||||
ready.add(s);
|
||||
visited.add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(schedule.size() == nodes.size());
|
||||
return schedule;
|
||||
}
|
||||
|
||||
private void scheduleLatest() {
|
||||
Node root = findRoot();
|
||||
if(root == null) {
|
||||
@ -426,12 +566,32 @@ public class ServerCompilerScheduler implements Scheduler {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isRegion(Node n) {
|
||||
return n.inputNode.getProperties().get("name").equals("Region");
|
||||
private static boolean isOtherBlockStart(Node n) {
|
||||
return hasName(n, "CountedLoopEnd");
|
||||
}
|
||||
|
||||
private boolean isPhi(Node n) {
|
||||
return n.inputNode.getProperties().get("name").equals("Phi");
|
||||
private static boolean isPhi(Node n) {
|
||||
return hasName(n, "Phi");
|
||||
}
|
||||
|
||||
private static boolean isProj(Node n) {
|
||||
return hasName(n, "Proj") || hasName(n, "MachProj");
|
||||
}
|
||||
|
||||
private static boolean isParm(Node n) {
|
||||
return hasName(n, "Parm");
|
||||
}
|
||||
|
||||
private static boolean hasName(Node n, String name) {
|
||||
String nodeName = n.inputNode.getProperties().get("name");
|
||||
if (nodeName == null) {
|
||||
return false;
|
||||
}
|
||||
return nodeName.equals(name);
|
||||
}
|
||||
|
||||
private static boolean isControl(Node n) {
|
||||
return n.inputNode.getProperties().get("category").equals("control");
|
||||
}
|
||||
|
||||
private Node findRoot() {
|
||||
@ -439,9 +599,7 @@ public class ServerCompilerScheduler implements Scheduler {
|
||||
Node alternativeRoot = null;
|
||||
|
||||
for (Node node : nodes) {
|
||||
InputNode inputNode = node.inputNode;
|
||||
String s = inputNode.getProperties().get("name");
|
||||
if (s != null && s.equals("Root")) {
|
||||
if (hasName(node, "Root")) {
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -473,13 +631,8 @@ public class ServerCompilerScheduler implements Scheduler {
|
||||
public void buildUpGraph() {
|
||||
|
||||
for (InputNode n : graph.getNodes()) {
|
||||
Node node = new Node();
|
||||
node.inputNode = n;
|
||||
Node node = new Node(n);
|
||||
nodes.add(node);
|
||||
String p = n.getProperties().get("is_block_proj");
|
||||
node.isBlockProjection = (p != null && p.equals("true"));
|
||||
p = n.getProperties().get("is_block_start");
|
||||
node.isBlockStart = (p != null && p.equals("true"));
|
||||
inputNodeToNode.put(n, node);
|
||||
}
|
||||
|
||||
|
18
src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/filters/hideExceptionBlocks.filter
Normal file
18
src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/filters/hideExceptionBlocks.filter
Normal file
@ -0,0 +1,18 @@
|
||||
// Hide exception blocks.
|
||||
|
||||
var f = new RemoveBlockFilter("Hide exception blocks");
|
||||
f.addRule(
|
||||
new RemoveBlockFilter.RemoveBlockRule(
|
||||
new AnySelector(
|
||||
new OrSelector(
|
||||
new MatcherSelector(
|
||||
new Properties.StringPropertyMatcher("name", "Rethrow")
|
||||
),
|
||||
new MatcherSelector(
|
||||
new Properties.StringPropertyMatcher("name", "RethrowException")
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
f.apply(graph);
|
13
src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/filters/hideRootBlock.filter
Normal file
13
src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/filters/hideRootBlock.filter
Normal file
@ -0,0 +1,13 @@
|
||||
// Remove root block and all nodes in it (hopefully just the Root node).
|
||||
|
||||
var f = new RemoveBlockFilter("Hide root block");
|
||||
f.addRule(
|
||||
new RemoveBlockFilter.RemoveBlockRule(
|
||||
new AnySelector(
|
||||
new MatcherSelector(
|
||||
new Properties.RegexpPropertyMatcher("name", "Root")
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
f.apply(graph);
|
@ -0,0 +1,13 @@
|
||||
// Hide uncommon trap blocks.
|
||||
|
||||
var f = new RemoveBlockFilter("Hide uncommon trap blocks");
|
||||
f.addRule(
|
||||
new RemoveBlockFilter.RemoveBlockRule(
|
||||
new AnySelector(
|
||||
new MatcherSelector(
|
||||
new Properties.RegexpPropertyMatcher("dump_spec", ".*uncommon_trap.*")
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
f.apply(graph);
|
@ -57,5 +57,17 @@
|
||||
<attr name="enabled" boolvalue="false"/>
|
||||
<attr name="after" stringvalue="Hide mixed edges"/>
|
||||
</file>
|
||||
<file name="Hide root block" url="filters/hideRootBlock.filter">
|
||||
<attr name="enabled" boolvalue="false"/>
|
||||
<attr name="after" stringvalue="Hide other edges"/>
|
||||
</file>
|
||||
<file name="Hide uncommon trap blocks" url="filters/hideUncommonTrapBlocks.filter">
|
||||
<attr name="enabled" boolvalue="false"/>
|
||||
<attr name="after" stringvalue="Hide root block"/>
|
||||
</file>
|
||||
<file name="Hide exception blocks" url="filters/hideExceptionBlocks.filter">
|
||||
<attr name="enabled" boolvalue="false"/>
|
||||
<attr name="after" stringvalue="Hide uncommon trap blocks"/>
|
||||
</file>
|
||||
</folder>
|
||||
</filesystem>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -32,12 +32,20 @@ import java.util.prefs.Preferences;
|
||||
*/
|
||||
public class Settings {
|
||||
|
||||
public static class DefaultView {
|
||||
public static final int SEA_OF_NODES = 0;
|
||||
public static final int CLUSTERED_SEA_OF_NODES = 1;
|
||||
public static final int CONTROL_FLOW_GRAPH = 2;
|
||||
}
|
||||
|
||||
public static final String NODE_TEXT = "nodeText";
|
||||
public static final String NODE_TEXT_DEFAULT = "[idx] [name]";
|
||||
public static final String NODE_SHORT_TEXT = "nodeShortText";
|
||||
public static final String NODE_SHORT_TEXT_DEFAULT = "[idx] [name]";
|
||||
public static final String NODE_WIDTH = "nodeWidth";
|
||||
public static final String NODE_WIDTH_DEFAULT = "100";
|
||||
public static final String NODE_TINY_TEXT = "nodeTinyText";
|
||||
public static final String NODE_TINY_TEXT_DEFAULT = "[idx]";
|
||||
public static final String DEFAULT_VIEW = "defaultView";
|
||||
public static final int DEFAULT_VIEW_DEFAULT = DefaultView.SEA_OF_NODES;
|
||||
public static final String PORT = "port";
|
||||
public static final String PORT_BINARY = "portBinary";
|
||||
public static final String PORT_DEFAULT = "4444";
|
||||
|
62
src/utils/IdealGraphVisualizer/Settings/src/main/java/com/sun/hotspot/igv/settings/ViewPanel.form
62
src/utils/IdealGraphVisualizer/Settings/src/main/java/com/sun/hotspot/igv/settings/ViewPanel.form
@ -28,7 +28,7 @@
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jPanel1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="153" max="32767" attributes="0"/>
|
||||
<EmptySpace pref="29" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -46,19 +46,17 @@
|
||||
<Component id="jLabel3" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel4" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel5" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="39" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="103" alignment="0" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="nodeShortTextField" max="32767" attributes="0"/>
|
||||
<Component id="jScrollPane1" pref="365" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
|
||||
<Component id="nodeWidthSpinner" alignment="0" pref="100" max="32767" attributes="0"/>
|
||||
<Component id="portSpinner" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="nodeShortTextField" max="32767" attributes="0"/>
|
||||
<Component id="jScrollPane1" pref="470" max="32767" attributes="0"/>
|
||||
<Component id="portSpinner" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="nodeTinyTextField" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="defaultViewComboBox" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace pref="439" max="32767" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -77,8 +75,13 @@
|
||||
</Group>
|
||||
<EmptySpace pref="27" max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="nodeWidthSpinner" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel5" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="nodeTinyTextField" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="27" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="jLabel2" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="defaultViewComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace pref="27" max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
@ -97,7 +100,7 @@
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel2">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Node Width"/>
|
||||
<Property name="text" type="java.lang.String" value="Default View"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JSpinner" name="portSpinner">
|
||||
@ -118,8 +121,6 @@
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JSpinner" name="nodeWidthSpinner">
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel3">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Network Port"/>
|
||||
@ -141,6 +142,37 @@
|
||||
<AuxValue name="JavaCodeGenerator_SerializeTo" type="java.lang.String" value="ViewPanel_nodeShortTextField"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel5">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Tiny Node Text"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="nodeTinyTextField">
|
||||
<Properties>
|
||||
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="ff" green="ff" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Single-line format string for node input lists. Properties are specified with brackets (example: "[idx]")."/>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_SerializeTo" type="java.lang.String" value="ViewPanel_nodeTinyTextField"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="defaultViewComboBox">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="3">
|
||||
<StringItem index="0" value="Sea of nodes"/>
|
||||
<StringItem index="1" value="Clustered sea of nodes"/>
|
||||
<StringItem index="2" value="Control-flow graph"/>
|
||||
</StringArray>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" value="View shown by default when a graph is opened."/>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
|
54
src/utils/IdealGraphVisualizer/Settings/src/main/java/com/sun/hotspot/igv/settings/ViewPanel.java
54
src/utils/IdealGraphVisualizer/Settings/src/main/java/com/sun/hotspot/igv/settings/ViewPanel.java
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -50,14 +50,16 @@ final class ViewPanel extends javax.swing.JPanel {
|
||||
portSpinner = new javax.swing.JSpinner();
|
||||
jScrollPane1 = new javax.swing.JScrollPane();
|
||||
nodeTextArea = new javax.swing.JTextArea();
|
||||
nodeWidthSpinner = new javax.swing.JSpinner();
|
||||
jLabel3 = new javax.swing.JLabel();
|
||||
jLabel4 = new javax.swing.JLabel();
|
||||
nodeShortTextField = new javax.swing.JTextField();
|
||||
jLabel5 = new javax.swing.JLabel();
|
||||
nodeTinyTextField = new javax.swing.JTextField();
|
||||
defaultViewComboBox = new javax.swing.JComboBox<>();
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, "Node Text");
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(jLabel2, "Node Width");
|
||||
org.openide.awt.Mnemonics.setLocalizedText(jLabel2, "Default View");
|
||||
|
||||
nodeTextArea.setColumns(20);
|
||||
nodeTextArea.setRows(5);
|
||||
@ -71,6 +73,14 @@ final class ViewPanel extends javax.swing.JPanel {
|
||||
nodeShortTextField.setBackground(new java.awt.Color(255, 255, 255));
|
||||
nodeShortTextField.setToolTipText("Single-line format string for nodes in edge tooltips, slot tooltips, and node search bar. Properties are specified with brackets (example: \"[idx]\").");
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(jLabel5, "Tiny Node Text");
|
||||
|
||||
nodeTinyTextField.setBackground(new java.awt.Color(255, 255, 255));
|
||||
nodeTinyTextField.setToolTipText("Single-line format string for node input lists. Properties are specified with brackets (example: \"[idx]\").");
|
||||
|
||||
defaultViewComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Sea of nodes", "Clustered sea of nodes", "Control-flow graph" }));
|
||||
defaultViewComboBox.setToolTipText("View shown by default when a graph is opened.");
|
||||
|
||||
org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1);
|
||||
jPanel1.setLayout(jPanel1Layout);
|
||||
jPanel1Layout.setHorizontalGroup(
|
||||
@ -81,16 +91,16 @@ final class ViewPanel extends javax.swing.JPanel {
|
||||
.add(jLabel1)
|
||||
.add(jLabel3)
|
||||
.add(jLabel2)
|
||||
.add(jLabel4))
|
||||
.add(jLabel4)
|
||||
.add(jLabel5))
|
||||
.add(39, 39, 39)
|
||||
.add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||
.add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
|
||||
.add(nodeShortTextField)
|
||||
.add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 365, Short.MAX_VALUE))
|
||||
.add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
|
||||
.add(org.jdesktop.layout.GroupLayout.LEADING, nodeWidthSpinner, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 100, Short.MAX_VALUE)
|
||||
.add(org.jdesktop.layout.GroupLayout.LEADING, portSpinner)))
|
||||
.addContainerGap(439, Short.MAX_VALUE))
|
||||
.add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
|
||||
.add(nodeShortTextField)
|
||||
.add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 470, Short.MAX_VALUE)
|
||||
.add(portSpinner)
|
||||
.add(nodeTinyTextField)
|
||||
.add(defaultViewComboBox, 0, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
jPanel1Layout.setVerticalGroup(
|
||||
jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||
@ -105,8 +115,12 @@ final class ViewPanel extends javax.swing.JPanel {
|
||||
.add(nodeShortTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 27, Short.MAX_VALUE)
|
||||
.add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
|
||||
.add(nodeWidthSpinner, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||
.add(jLabel2))
|
||||
.add(jLabel5)
|
||||
.add(nodeTinyTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
|
||||
.add(27, 27, 27)
|
||||
.add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
|
||||
.add(jLabel2)
|
||||
.add(defaultViewComboBox, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 27, Short.MAX_VALUE)
|
||||
.add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
|
||||
.add(portSpinner, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||
@ -127,20 +141,22 @@ final class ViewPanel extends javax.swing.JPanel {
|
||||
.add(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(153, Short.MAX_VALUE))
|
||||
.addContainerGap(29, Short.MAX_VALUE))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
void load() {
|
||||
nodeTextArea.setText(Settings.get().get(Settings.NODE_TEXT, Settings.NODE_TEXT_DEFAULT));
|
||||
nodeShortTextField.setText(Settings.get().get(Settings.NODE_SHORT_TEXT, Settings.NODE_SHORT_TEXT_DEFAULT));
|
||||
nodeWidthSpinner.setValue(Integer.parseInt(Settings.get().get(Settings.NODE_WIDTH, Settings.NODE_WIDTH_DEFAULT)));
|
||||
nodeTinyTextField.setText(Settings.get().get(Settings.NODE_TINY_TEXT, Settings.NODE_TINY_TEXT_DEFAULT));
|
||||
defaultViewComboBox.setSelectedIndex(Settings.get().getInt(Settings.DEFAULT_VIEW, Settings.DefaultView.SEA_OF_NODES));
|
||||
portSpinner.setValue(Integer.parseInt(Settings.get().get(Settings.PORT, Settings.PORT_DEFAULT)));
|
||||
}
|
||||
|
||||
void store() {
|
||||
Settings.get().put(Settings.NODE_TEXT, nodeTextArea.getText());
|
||||
Settings.get().put(Settings.NODE_SHORT_TEXT, nodeShortTextField.getText());
|
||||
Settings.get().put(Settings.NODE_WIDTH, nodeWidthSpinner.getValue().toString());
|
||||
Settings.get().put(Settings.NODE_TINY_TEXT, nodeTinyTextField.getText());
|
||||
Settings.get().putInt(Settings.DEFAULT_VIEW, defaultViewComboBox.getSelectedIndex());
|
||||
Settings.get().put(Settings.PORT, portSpinner.getValue().toString());
|
||||
}
|
||||
|
||||
@ -148,15 +164,17 @@ final class ViewPanel extends javax.swing.JPanel {
|
||||
return true;
|
||||
}
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JComboBox<String> defaultViewComboBox;
|
||||
private javax.swing.JLabel jLabel1;
|
||||
private javax.swing.JLabel jLabel2;
|
||||
private javax.swing.JLabel jLabel3;
|
||||
private javax.swing.JLabel jLabel4;
|
||||
private javax.swing.JLabel jLabel5;
|
||||
private javax.swing.JPanel jPanel1;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private javax.swing.JTextField nodeShortTextField;
|
||||
private javax.swing.JTextArea nodeTextArea;
|
||||
private javax.swing.JSpinner nodeWidthSpinner;
|
||||
private javax.swing.JTextField nodeTinyTextField;
|
||||
private javax.swing.JSpinner portSpinner;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -113,4 +113,25 @@ public class StringUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rank a match of a query in a word. Full matches of a word rank highest,
|
||||
* followed by partial matches at the word start, followed by the rest of
|
||||
* matches in increasing size of the partially matched word, for example:
|
||||
*
|
||||
* rank("5", "5") = 1 (full match)
|
||||
* rank("5", "554") = 2 (start match)
|
||||
* rank("5", "25") = 3 (middle match with excess 1)
|
||||
* rank("5", "253") = 4 (middle match with excess 2)
|
||||
*/
|
||||
public static int rankMatch(String query, String word) {
|
||||
if (word.equals(query)) {
|
||||
return 1;
|
||||
} else if (word.startsWith(query)) {
|
||||
return 2;
|
||||
} else if (word.contains(query)) {
|
||||
return word.length() - query.length() + 2;
|
||||
}
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
146
src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/BlockQuickSearch.java
Normal file
146
src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/BlockQuickSearch.java
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
package com.sun.hotspot.igv.view;
|
||||
|
||||
import com.sun.hotspot.igv.data.InputGraph;
|
||||
import com.sun.hotspot.igv.data.InputBlock;
|
||||
import com.sun.hotspot.igv.data.Properties.RegexpPropertyMatcher;
|
||||
import com.sun.hotspot.igv.data.services.InputGraphProvider;
|
||||
import com.sun.hotspot.igv.util.LookupHistory;
|
||||
import com.sun.hotspot.igv.util.StringUtils;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.regex.Pattern;
|
||||
import org.netbeans.spi.quicksearch.SearchProvider;
|
||||
import org.netbeans.spi.quicksearch.SearchRequest;
|
||||
import org.netbeans.spi.quicksearch.SearchResponse;
|
||||
import org.openide.DialogDisplayer;
|
||||
import org.openide.NotifyDescriptor;
|
||||
import org.openide.NotifyDescriptor.Message;
|
||||
|
||||
public class BlockQuickSearch implements SearchProvider {
|
||||
|
||||
@Override
|
||||
public void evaluate(SearchRequest request, SearchResponse response) {
|
||||
String rawValue = request.getText();
|
||||
if (rawValue.trim().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
String value = ".*" + Pattern.quote(rawValue) + ".*";
|
||||
|
||||
final InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);
|
||||
if (p == null || p.getGraph() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
InputGraph matchGraph = p.getGraph();
|
||||
// Search the current graph
|
||||
List<InputBlock> matches = findMatches(value, p.getGraph(), response);
|
||||
if (matches == null) {
|
||||
// See if the it hits in a later graph
|
||||
for (InputGraph graph : p.searchForward()) {
|
||||
matches = findMatches(value, graph, response);
|
||||
if (matches != null) {
|
||||
matchGraph = graph;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (matches == null) {
|
||||
// See if it hits in a earlier graph
|
||||
for (InputGraph graph : p.searchBackward()) {
|
||||
matches = findMatches(value, graph, response);
|
||||
if (matches != null) {
|
||||
matchGraph = graph;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (matches != null) {
|
||||
// Rank the matches.
|
||||
matches.sort((InputBlock a, InputBlock b) ->
|
||||
compareByRankThenNumVal(rawValue,
|
||||
"B" + a.getName(),
|
||||
"B" + b.getName()));
|
||||
|
||||
final InputGraph theGraph = p.getGraph() != matchGraph ? matchGraph : null;
|
||||
for (final InputBlock b : matches) {
|
||||
if (!response.addResult(() -> {
|
||||
final EditorTopComponent comp = EditorTopComponent.getActive();
|
||||
assert(comp != null);
|
||||
if (theGraph != null) {
|
||||
comp.getDiagramModel().selectGraph(theGraph);
|
||||
}
|
||||
comp.setSelectedNodes(b);
|
||||
comp.requestActive();
|
||||
},
|
||||
"B" + b.getName() + (theGraph != null ? " in " + theGraph.getName() : ""))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<InputBlock> findMatches(String blockName, InputGraph inputGraph, SearchResponse response) {
|
||||
try {
|
||||
RegexpPropertyMatcher matcher = new RegexpPropertyMatcher("", blockName, Pattern.CASE_INSENSITIVE);
|
||||
List<InputBlock> matches = new ArrayList<>();
|
||||
for (InputBlock b : inputGraph.getBlocks()) {
|
||||
if (matcher.match("B" + b.getName())) {
|
||||
matches.add(b);
|
||||
}
|
||||
}
|
||||
return matches.size() == 0 ? null : matches;
|
||||
} catch (Exception e) {
|
||||
final String msg = e.getMessage();
|
||||
response.addResult(() -> {
|
||||
Message desc = new NotifyDescriptor.Message("An exception occurred during the search, "
|
||||
+ "perhaps due to a malformed query string:\n" + msg,
|
||||
NotifyDescriptor.WARNING_MESSAGE);
|
||||
DialogDisplayer.getDefault().notify(desc);
|
||||
},
|
||||
"(Error during search)"
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private int compareByRankThenNumVal(String qry, String b1, String b2) {
|
||||
int key1 = StringUtils.rankMatch(qry, b1);
|
||||
int key2 = StringUtils.rankMatch(qry, b2);
|
||||
if (key1 == key2) {
|
||||
// If the matches have the same rank, compare the numeric values of
|
||||
// their first words, if applicable.
|
||||
try {
|
||||
key1 = Integer.parseInt(b1.replace("B", ""));
|
||||
key2 = Integer.parseInt(b2.replace("B", ""));
|
||||
} catch (Exception e) {
|
||||
// Not applicable, return equality value.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return Integer.compare(key1, key2);
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -32,8 +32,11 @@ import com.sun.hotspot.igv.data.Properties;
|
||||
import com.sun.hotspot.igv.data.services.Scheduler;
|
||||
import com.sun.hotspot.igv.graph.*;
|
||||
import com.sun.hotspot.igv.hierarchicallayout.HierarchicalClusterLayoutManager;
|
||||
import com.sun.hotspot.igv.hierarchicallayout.HierarchicalCFGLayoutManager;
|
||||
import com.sun.hotspot.igv.hierarchicallayout.LinearLayoutManager;
|
||||
import com.sun.hotspot.igv.hierarchicallayout.HierarchicalLayoutManager;
|
||||
import com.sun.hotspot.igv.layout.LayoutGraph;
|
||||
import com.sun.hotspot.igv.layout.Link;
|
||||
import com.sun.hotspot.igv.selectioncoordinator.SelectionCoordinator;
|
||||
import com.sun.hotspot.igv.util.ColorIcon;
|
||||
import com.sun.hotspot.igv.util.DoubleClickAction;
|
||||
@ -493,6 +496,19 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
|
||||
return a;
|
||||
}
|
||||
|
||||
public Action createGotoAction(final Block b) {
|
||||
final DiagramScene diagramScene = this;
|
||||
String name = "B" + b.getInputBlock().getName();
|
||||
Action a = new AbstractAction(name) {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
diagramScene.gotoBlock(b);
|
||||
}
|
||||
};
|
||||
a.setEnabled(true);
|
||||
return a;
|
||||
}
|
||||
|
||||
public void setNewModel(DiagramViewModel model) {
|
||||
assert this.model == null : "can set model only once!";
|
||||
this.model = model;
|
||||
@ -518,15 +534,26 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
|
||||
|
||||
Diagram d = getModel().getDiagramToView();
|
||||
|
||||
if (d.getGraph().getBlocks().isEmpty()) {
|
||||
Scheduler s = Lookup.getDefault().lookup(Scheduler.class);
|
||||
d.getGraph().clearBlocks();
|
||||
s.schedule(d.getGraph());
|
||||
d.getGraph().ensureNodesInBlocks();
|
||||
d.updateBlocks();
|
||||
Map<InputBlock, Integer> maxWidth = new HashMap<>();
|
||||
for (InputBlock b : d.getGraph().getBlocks()) {
|
||||
maxWidth.put(b, 10);
|
||||
}
|
||||
for (Figure f : d.getFigures()) {
|
||||
// Update node text, since it might differ across views.
|
||||
f.updateLines();
|
||||
// Compute max node width in each block.
|
||||
if (f.getWidth() > maxWidth.get(f.getBlock())) {
|
||||
maxWidth.put(f.getBlock(), f.getWidth());
|
||||
}
|
||||
}
|
||||
|
||||
for (Figure f : d.getFigures()) {
|
||||
|
||||
// Set all nodes' width to the maximum width in the blocks?
|
||||
if (getModel().getShowCFG()) {
|
||||
f.setWidth(maxWidth.get(f.getBlock()));
|
||||
}
|
||||
|
||||
FigureWidget w = new FigureWidget(f, hoverAction, selectAction, this, mainLayer);
|
||||
w.getActions().addAction(ActionFactory.createPopupMenuAction(w));
|
||||
w.getActions().addAction(selectAction);
|
||||
@ -552,7 +579,7 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
|
||||
}
|
||||
}
|
||||
|
||||
if (getModel().getShowBlocks()) {
|
||||
if (getModel().getShowBlocks() || getModel().getShowCFG()) {
|
||||
for (InputBlock bn : d.getGraph().getBlocks()) {
|
||||
BlockWidget w = new BlockWidget(this, d, bn);
|
||||
w.setVisible(false);
|
||||
@ -578,8 +605,11 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
|
||||
}
|
||||
|
||||
private boolean isVisible(Connection c) {
|
||||
FigureWidget w1 = getWidget(c.getInputSlot().getFigure());
|
||||
FigureWidget w2 = getWidget(c.getOutputSlot().getFigure());
|
||||
if (getModel().getShowCFG()) {
|
||||
return c.isAlwaysVisible();
|
||||
}
|
||||
FigureWidget w1 = getWidget(c.getFrom().getVertex());
|
||||
FigureWidget w2 = getWidget(c.getTo().getVertex());
|
||||
|
||||
if (w1.isVisible() && w2.isVisible()) {
|
||||
return true;
|
||||
@ -608,22 +638,72 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
|
||||
}
|
||||
}
|
||||
|
||||
if (getModel().getShowBlocks()) {
|
||||
HierarchicalClusterLayoutManager m = new HierarchicalClusterLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS);
|
||||
HierarchicalLayoutManager manager = new HierarchicalLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS);
|
||||
manager.setMaxLayerLength(9);
|
||||
manager.setMinLayerDifference(3);
|
||||
m.setManager(manager);
|
||||
m.setSubManager(new HierarchicalLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS));
|
||||
m.doLayout(new LayoutGraph(edges, figures));
|
||||
} else {
|
||||
HierarchicalLayoutManager manager = new HierarchicalLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS);
|
||||
manager.setMaxLayerLength(10);
|
||||
manager.doLayout(new LayoutGraph(edges, figures));
|
||||
if (getModel().getShowSea()) {
|
||||
doSeaLayout(figures, edges);
|
||||
} else if (getModel().getShowBlocks()) {
|
||||
doClusteredLayout(figures, edges);
|
||||
} else if (getModel().getShowCFG()) {
|
||||
doCFGLayout(figures, edges);
|
||||
}
|
||||
|
||||
relayoutWithoutLayout(oldVisibleWidgets);
|
||||
}
|
||||
|
||||
private void doSeaLayout(HashSet<Figure> figures, HashSet<Connection> edges) {
|
||||
HierarchicalLayoutManager manager = new HierarchicalLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS);
|
||||
manager.setMaxLayerLength(10);
|
||||
manager.doLayout(new LayoutGraph(edges, figures));
|
||||
}
|
||||
|
||||
private void doClusteredLayout(HashSet<Figure> figures, HashSet<Connection> edges) {
|
||||
HierarchicalClusterLayoutManager m = new HierarchicalClusterLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS);
|
||||
HierarchicalLayoutManager manager = new HierarchicalLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS);
|
||||
manager.setMaxLayerLength(9);
|
||||
manager.setMinLayerDifference(3);
|
||||
m.setManager(manager);
|
||||
m.setSubManager(new HierarchicalLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS));
|
||||
m.doLayout(new LayoutGraph(edges, figures));
|
||||
}
|
||||
|
||||
private void doCFGLayout(HashSet<Figure> figures, HashSet<Connection> edges) {
|
||||
Diagram diagram = getModel().getDiagramToView();
|
||||
HierarchicalCFGLayoutManager m = new HierarchicalCFGLayoutManager();
|
||||
HierarchicalLayoutManager manager = new HierarchicalLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS);
|
||||
manager.setMaxLayerLength(9);
|
||||
manager.setMinLayerDifference(1);
|
||||
manager.setLayoutSelfEdges(true);
|
||||
manager.setXOffset(25);
|
||||
manager.setLayerOffset(25);
|
||||
m.setManager(manager);
|
||||
Map<InputNode, Figure> nodeFig = new HashMap<InputNode, Figure>();
|
||||
for (Figure f : figures) {
|
||||
InputNode n = f.getFirstSourceNode();
|
||||
if (n != null) {
|
||||
nodeFig.put(n, f);
|
||||
}
|
||||
}
|
||||
// Compute global ranking among figures given by in-block order. If
|
||||
// needed, this could be cached as long as it is computed for all the
|
||||
// figures in the model, not just the visible ones.
|
||||
Map<Figure, Integer> figureRank =
|
||||
new HashMap<Figure, Integer>(figures.size());
|
||||
int r = 0;
|
||||
for (InputBlock b : getModel().getGraphToView().getBlocks()) {
|
||||
for (InputNode n : b.getNodes()) {
|
||||
Figure f = nodeFig.get(n);
|
||||
if (f != null) {
|
||||
figureRank.put(f, r);
|
||||
r++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add connections for CFG edges.
|
||||
edges.addAll(diagram.getBlockConnections());
|
||||
m.setSubManager(new LinearLayoutManager(figureRank));
|
||||
m.setClusters(new HashSet<>(diagram.getBlocks()));
|
||||
m.doLayout(new LayoutGraph(edges, figures));
|
||||
}
|
||||
|
||||
private Set<Pair<Point, Point>> lineCache = new HashSet<>();
|
||||
|
||||
private void relayoutWithoutLayout(Set<Widget> oldVisibleWidgets) {
|
||||
@ -642,7 +722,7 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
|
||||
}
|
||||
}
|
||||
|
||||
for (Connection c : diagram.getConnections()) {
|
||||
for (FigureConnection c : diagram.getConnections()) {
|
||||
List<Point> points = c.getControlPoints();
|
||||
FigureWidget w1 = getWidget((Figure) c.getTo().getVertex());
|
||||
FigureWidget w2 = getWidget((Figure) c.getFrom().getVertex());
|
||||
@ -656,7 +736,7 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
|
||||
}
|
||||
}
|
||||
|
||||
if (getModel().getShowBlocks()) {
|
||||
if (getModel().getShowBlocks() || getModel().getShowCFG()) {
|
||||
for (Block b : diagram.getBlocks()) {
|
||||
BlockWidget w = getWidget(b.getInputBlock());
|
||||
if (w != null && w.isVisible()) {
|
||||
@ -705,7 +785,18 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
|
||||
if (visibleFigureCount > ANIMATION_LIMIT || oldVisibleWidgets == null) {
|
||||
anim = null;
|
||||
}
|
||||
processOutputSlot(lastLineCache, s, s.getConnections(), 0, null, null, offx2, offy2, anim);
|
||||
List<Connection> cl = new ArrayList<>(s.getConnections().size());
|
||||
for (FigureConnection c : s.getConnections()) {
|
||||
cl.add((Connection) c);
|
||||
}
|
||||
processOutputSlot(lastLineCache, s, cl, 0, null, null, offx2, offy2, anim);
|
||||
}
|
||||
}
|
||||
|
||||
if (getModel().getShowCFG()) {
|
||||
for (BlockConnection c : diagram.getBlockConnections()) {
|
||||
SceneAnimator anim = animator;
|
||||
processOutputSlot(lastLineCache, null, Collections.singletonList(c), 0, null, null, offx2, offy2, anim);
|
||||
}
|
||||
}
|
||||
|
||||
@ -723,7 +814,7 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
|
||||
}
|
||||
}
|
||||
|
||||
if (getModel().getShowBlocks()) {
|
||||
if (getModel().getShowBlocks() || getModel().getShowCFG()) {
|
||||
for (Block b : diagram.getBlocks()) {
|
||||
BlockWidget w = getWidget(b.getInputBlock());
|
||||
if (w != null && w.isVisible()) {
|
||||
@ -759,12 +850,15 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
|
||||
}
|
||||
|
||||
Point cur = controlPoints.get(controlPointIndex);
|
||||
if (cur == null) {
|
||||
if (cur == null) { // Long connection, has been cut vertically.
|
||||
cur = specialNullPoint;
|
||||
} else if (controlPointIndex == 0 && !s.shouldShowName()) {
|
||||
cur = new Point(cur.x, cur.y - SLOT_OFFSET);
|
||||
} else if (controlPointIndex == controlPoints.size() - 1 && !c.getInputSlot().shouldShowName()) {
|
||||
cur = new Point(cur.x, cur.y + SLOT_OFFSET);
|
||||
} else if (c.hasSlots()) {
|
||||
if (controlPointIndex == 0 && !s.shouldShowName()) {
|
||||
cur = new Point(cur.x, cur.y - SLOT_OFFSET);
|
||||
} else if (controlPointIndex == controlPoints.size() - 1 &&
|
||||
!((Slot)c.getTo()).shouldShowName()) {
|
||||
cur = new Point(cur.x, cur.y + SLOT_OFFSET);
|
||||
}
|
||||
}
|
||||
|
||||
if (pointMap.containsKey(cur)) {
|
||||
@ -883,6 +977,13 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
|
||||
}
|
||||
}
|
||||
|
||||
public void gotoBlock(final Block block) {
|
||||
BlockWidget bw = getWidget(block.getInputBlock());
|
||||
if (bw != null) {
|
||||
centerRectangle(bw.getBounds());
|
||||
}
|
||||
}
|
||||
|
||||
private Set<Object> idSetToObjectSet(Set<Object> ids) {
|
||||
|
||||
Set<Object> result = new HashSet<>();
|
||||
@ -1042,7 +1143,7 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
|
||||
}
|
||||
}
|
||||
|
||||
if (getModel().getShowBlocks()) {
|
||||
if (getModel().getShowBlocks() || getModel().getShowCFG()) {
|
||||
for (InputBlock b : diagram.getGraph().getBlocks()) {
|
||||
BlockWidget w = getWidget(b);
|
||||
if (w.isVisible()) {
|
||||
@ -1102,7 +1203,23 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
|
||||
}
|
||||
}
|
||||
|
||||
if (getModel().getShowBlocks()) {
|
||||
if (getModel().getShowCFG()) {
|
||||
// Blockless figures and artificial blocks are hidden in this view.
|
||||
for (Figure f : diagram.getFigures()) {
|
||||
if (f.getBlock().isArtificial()) {
|
||||
FigureWidget w = getWidget(f);
|
||||
w.setVisible(false);
|
||||
}
|
||||
}
|
||||
visibleBlocks.clear();
|
||||
for (InputBlock b : diagram.getGraph().getBlocks()) {
|
||||
if (!b.isArtificial()) {
|
||||
visibleBlocks.add(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getModel().getShowBlocks() || getModel().getShowCFG()) {
|
||||
for (InputBlock b : diagram.getGraph().getBlocks()) {
|
||||
|
||||
boolean visibleAfter = visibleBlocks.contains(b);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,6 +25,7 @@
|
||||
package com.sun.hotspot.igv.view;
|
||||
|
||||
import com.sun.hotspot.igv.data.*;
|
||||
import com.sun.hotspot.igv.data.services.Scheduler;
|
||||
import com.sun.hotspot.igv.difference.Difference;
|
||||
import com.sun.hotspot.igv.filter.CustomFilter;
|
||||
import com.sun.hotspot.igv.filter.FilterChain;
|
||||
@ -34,6 +35,7 @@ import com.sun.hotspot.igv.settings.Settings;
|
||||
import com.sun.hotspot.igv.util.RangeSliderModel;
|
||||
import java.awt.Color;
|
||||
import java.util.*;
|
||||
import org.openide.util.Lookup;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -56,7 +58,9 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
|
||||
private ChangedEvent<DiagramViewModel> viewChangedEvent;
|
||||
private ChangedEvent<DiagramViewModel> hiddenNodesChangedEvent;
|
||||
private ChangedEvent<DiagramViewModel> viewPropertiesChangedEvent;
|
||||
private boolean showSea;
|
||||
private boolean showBlocks;
|
||||
private boolean showCFG;
|
||||
private boolean showNodeHull;
|
||||
private boolean hideDuplicates;
|
||||
private ChangedListener<FilterChain> filterChainChangedListener = new ChangedListener<FilterChain>() {
|
||||
@ -102,8 +106,12 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
|
||||
this.onScreenNodes = newModel.onScreenNodes;
|
||||
viewChanged |= (selectedNodes != newModel.selectedNodes);
|
||||
this.selectedNodes = newModel.selectedNodes;
|
||||
viewPropertiesChanged |= (showSea != newModel.showSea);
|
||||
this.showSea = newModel.showSea;
|
||||
viewPropertiesChanged |= (showBlocks != newModel.showBlocks);
|
||||
this.showBlocks = newModel.showBlocks;
|
||||
viewPropertiesChanged |= (showCFG != newModel.showCFG);
|
||||
this.showCFG = newModel.showCFG;
|
||||
viewPropertiesChanged |= (showNodeHull != newModel.showNodeHull);
|
||||
this.showNodeHull = newModel.showNodeHull;
|
||||
|
||||
@ -122,6 +130,15 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getShowSea() {
|
||||
return showSea;
|
||||
}
|
||||
|
||||
public void setShowSea(boolean b) {
|
||||
showSea = b;
|
||||
viewPropertiesChangedEvent.fire();
|
||||
}
|
||||
|
||||
public boolean getShowBlocks() {
|
||||
return showBlocks;
|
||||
}
|
||||
@ -131,6 +148,15 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
|
||||
viewPropertiesChangedEvent.fire();
|
||||
}
|
||||
|
||||
public boolean getShowCFG() {
|
||||
return showCFG;
|
||||
}
|
||||
|
||||
public void setShowCFG(boolean b) {
|
||||
showCFG = b;
|
||||
viewPropertiesChangedEvent.fire();
|
||||
}
|
||||
|
||||
public boolean getShowNodeHull() {
|
||||
return showNodeHull;
|
||||
}
|
||||
@ -164,7 +190,9 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
|
||||
public DiagramViewModel(Group g, FilterChain filterChain, FilterChain sequenceFilterChain) {
|
||||
super(Arrays.asList("default"));
|
||||
|
||||
this.showBlocks = false;
|
||||
this.showSea = Settings.get().getInt(Settings.DEFAULT_VIEW, Settings.DEFAULT_VIEW_DEFAULT) == Settings.DefaultView.SEA_OF_NODES;
|
||||
this.showBlocks = Settings.get().getInt(Settings.DEFAULT_VIEW, Settings.DEFAULT_VIEW_DEFAULT) == Settings.DefaultView.CLUSTERED_SEA_OF_NODES;
|
||||
this.showCFG = Settings.get().getInt(Settings.DEFAULT_VIEW, Settings.DEFAULT_VIEW_DEFAULT) == Settings.DefaultView.CONTROL_FLOW_GRAPH;
|
||||
this.showNodeHull = true;
|
||||
this.group = g;
|
||||
filterGraphs();
|
||||
@ -406,9 +434,17 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
|
||||
public Diagram getDiagramToView() {
|
||||
|
||||
if (diagram == null) {
|
||||
diagram = Diagram.createDiagram(getGraphToView(),
|
||||
InputGraph graph = getGraphToView();
|
||||
if (graph.getBlocks().isEmpty()) {
|
||||
Scheduler s = Lookup.getDefault().lookup(Scheduler.class);
|
||||
graph.clearBlocks();
|
||||
s.schedule(graph);
|
||||
graph.ensureNodesInBlocks();
|
||||
}
|
||||
diagram = Diagram.createDiagram(graph,
|
||||
Settings.get().get(Settings.NODE_TEXT, Settings.NODE_TEXT_DEFAULT),
|
||||
Settings.get().get(Settings.NODE_SHORT_TEXT, Settings.NODE_SHORT_TEXT_DEFAULT));
|
||||
Settings.get().get(Settings.NODE_SHORT_TEXT, Settings.NODE_SHORT_TEXT_DEFAULT),
|
||||
Settings.get().get(Settings.NODE_TINY_TEXT, Settings.NODE_TINY_TEXT_DEFAULT));
|
||||
getFilterChain().apply(diagram, getSequenceFilterChain());
|
||||
if (getFirstPosition() != getSecondPosition()) {
|
||||
CustomFilter f = new CustomFilter(
|
||||
@ -420,6 +456,7 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
|
||||
}
|
||||
}
|
||||
|
||||
diagram.setCFG(getShowCFG());
|
||||
return diagram;
|
||||
}
|
||||
|
||||
|
47
src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/EditorTopComponent.java
47
src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/EditorTopComponent.java
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,6 +28,7 @@ import com.sun.hotspot.igv.data.ChangedListener;
|
||||
import com.sun.hotspot.igv.data.GraphDocument;
|
||||
import com.sun.hotspot.igv.data.Group;
|
||||
import com.sun.hotspot.igv.data.InputNode;
|
||||
import com.sun.hotspot.igv.data.InputBlock;
|
||||
import com.sun.hotspot.igv.data.Properties;
|
||||
import com.sun.hotspot.igv.data.Properties.PropertyMatcher;
|
||||
import com.sun.hotspot.igv.data.services.InputGraphProvider;
|
||||
@ -38,6 +39,7 @@ import com.sun.hotspot.igv.graph.Figure;
|
||||
import com.sun.hotspot.igv.graph.services.DiagramProvider;
|
||||
import com.sun.hotspot.igv.util.LookupHistory;
|
||||
import com.sun.hotspot.igv.util.RangeSlider;
|
||||
import com.sun.hotspot.igv.settings.Settings;
|
||||
import com.sun.hotspot.igv.view.actions.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.HierarchyBoundsListener;
|
||||
@ -91,7 +93,9 @@ public final class EditorTopComponent extends TopComponent implements PropertyCh
|
||||
private DiagramViewer scene;
|
||||
private InstanceContent content;
|
||||
private InstanceContent graphContent;
|
||||
private EnableSeaLayoutAction seaLayoutAction;
|
||||
private EnableBlockLayoutAction blockLayoutAction;
|
||||
private EnableCFGLayoutAction cfgLayoutAction;
|
||||
private OverviewAction overviewAction;
|
||||
private HideDuplicatesAction hideDuplicatesAction;
|
||||
private PredSuccAction predSuccAction;
|
||||
@ -238,12 +242,31 @@ public final class EditorTopComponent extends TopComponent implements PropertyCh
|
||||
toolBar.add(ShowAllAction.get(ZoomInAction.class));
|
||||
toolBar.add(ShowAllAction.get(ZoomOutAction.class));
|
||||
|
||||
toolBar.addSeparator();
|
||||
ButtonGroup layoutButtons = new ButtonGroup();
|
||||
|
||||
seaLayoutAction = new EnableSeaLayoutAction();
|
||||
JToggleButton button = new JToggleButton(seaLayoutAction);
|
||||
button.setSelected(Settings.get().getInt(Settings.DEFAULT_VIEW, Settings.DEFAULT_VIEW_DEFAULT) == Settings.DefaultView.SEA_OF_NODES);
|
||||
layoutButtons.add(button);
|
||||
toolBar.add(button);
|
||||
seaLayoutAction.addPropertyChangeListener(this);
|
||||
|
||||
blockLayoutAction = new EnableBlockLayoutAction();
|
||||
JToggleButton button = new JToggleButton(blockLayoutAction);
|
||||
button.setSelected(false);
|
||||
button = new JToggleButton(blockLayoutAction);
|
||||
button.setSelected(Settings.get().getInt(Settings.DEFAULT_VIEW, Settings.DEFAULT_VIEW_DEFAULT) == Settings.DefaultView.CLUSTERED_SEA_OF_NODES);
|
||||
layoutButtons.add(button);
|
||||
toolBar.add(button);
|
||||
blockLayoutAction.addPropertyChangeListener(this);
|
||||
|
||||
cfgLayoutAction = new EnableCFGLayoutAction();
|
||||
button = new JToggleButton(cfgLayoutAction);
|
||||
button.setSelected(Settings.get().getInt(Settings.DEFAULT_VIEW, Settings.DEFAULT_VIEW_DEFAULT) == Settings.DefaultView.CONTROL_FLOW_GRAPH);
|
||||
layoutButtons.add(button);
|
||||
toolBar.add(button);
|
||||
cfgLayoutAction.addPropertyChangeListener(this);
|
||||
|
||||
toolBar.addSeparator();
|
||||
overviewAction = new OverviewAction();
|
||||
overviewButton = new JToggleButton(overviewAction);
|
||||
overviewButton.setSelected(false);
|
||||
@ -508,6 +531,16 @@ public final class EditorTopComponent extends TopComponent implements PropertyCh
|
||||
setSelectedFigures(list);
|
||||
}
|
||||
|
||||
public void setSelectedNodes(InputBlock b) {
|
||||
List<Figure> list = new ArrayList<>();
|
||||
for (Figure f : getModel().getDiagramToView().getFigures()) {
|
||||
if (f.getBlock() == b) {
|
||||
list.add(f);
|
||||
}
|
||||
}
|
||||
setSelectedFigures(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if (evt.getSource() == this.predSuccAction) {
|
||||
@ -520,9 +553,15 @@ public final class EditorTopComponent extends TopComponent implements PropertyCh
|
||||
} else {
|
||||
showScene();
|
||||
}
|
||||
} else if (evt.getSource() == this.seaLayoutAction) {
|
||||
boolean b = seaLayoutAction.isSelected();
|
||||
this.getModel().setShowSea(b);
|
||||
} else if (evt.getSource() == this.blockLayoutAction) {
|
||||
boolean b = (Boolean) blockLayoutAction.getValue(EnableBlockLayoutAction.STATE);
|
||||
boolean b = blockLayoutAction.isSelected();
|
||||
this.getModel().setShowBlocks(b);
|
||||
} else if (evt.getSource() == this.cfgLayoutAction) {
|
||||
boolean b = cfgLayoutAction.isSelected();
|
||||
this.getModel().setShowCFG(b);
|
||||
} else if (evt.getSource() == this.hideDuplicatesAction) {
|
||||
boolean b = (Boolean) hideDuplicatesAction.getValue(HideDuplicatesAction.STATE);
|
||||
this.getModel().setHideDuplicates(b);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -66,8 +66,10 @@ public class GraphViewerImplementation implements GraphViewer {
|
||||
|
||||
Diagram diagram = Diagram.createDiagram(graph,
|
||||
Settings.get().get(Settings.NODE_TEXT, Settings.NODE_TEXT_DEFAULT),
|
||||
Settings.get().get(Settings.NODE_SHORT_TEXT, Settings.NODE_SHORT_TEXT_DEFAULT));
|
||||
Settings.get().get(Settings.NODE_SHORT_TEXT, Settings.NODE_SHORT_TEXT_DEFAULT),
|
||||
Settings.get().get(Settings.NODE_TINY_TEXT, Settings.NODE_TINY_TEXT_DEFAULT));
|
||||
EditorTopComponent tc = new EditorTopComponent(diagram);
|
||||
diagram.setCFG(tc.getModel().getShowCFG());
|
||||
tc.open();
|
||||
tc.requestActive();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -30,6 +30,7 @@ import com.sun.hotspot.igv.data.Properties.RegexpPropertyMatcher;
|
||||
import com.sun.hotspot.igv.data.services.InputGraphProvider;
|
||||
import com.sun.hotspot.igv.settings.Settings;
|
||||
import com.sun.hotspot.igv.util.LookupHistory;
|
||||
import com.sun.hotspot.igv.util.StringUtils;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@ -214,24 +215,16 @@ public class NodeQuickSearch implements SearchProvider {
|
||||
/**
|
||||
* Rank a match by splitting the property into words. Full matches of a word
|
||||
* rank highest, followed by partial matches at the word start, followed by
|
||||
* the rest of matches in increasing size of the partially matched word, for
|
||||
* example:
|
||||
*
|
||||
* rank("5", "5 AddI") = 1 (full match of first word)
|
||||
* rank("5", "554 MulI") = 2 (start match of first word)
|
||||
* rank("5", "25 AddL") = 3 (middle match of first word with excess 1)
|
||||
* rank("5", "253 AddL") = 4 (middle match of first word with excess 2)
|
||||
* the rest of matches in increasing size of the partially matched word. See
|
||||
* examples in class StringUtils.
|
||||
*/
|
||||
private int rankMatch(String qry, String prop) {
|
||||
String query = qry.toLowerCase();
|
||||
String property = prop.toLowerCase();
|
||||
for (String component : property.split("\\W+")) {
|
||||
if (component.equals(query)) {
|
||||
return 1;
|
||||
} else if (component.startsWith(query)) {
|
||||
return 2;
|
||||
} else if (component.contains(query)) {
|
||||
return component.length() - query.length() + 2;
|
||||
int rank = StringUtils.rankMatch(query, component);
|
||||
if (rank != Integer.MAX_VALUE) {
|
||||
return rank;
|
||||
}
|
||||
}
|
||||
return Integer.MAX_VALUE;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -35,22 +35,22 @@ import org.openide.util.ImageUtilities;
|
||||
*/
|
||||
public class EnableBlockLayoutAction extends AbstractAction {
|
||||
|
||||
private boolean state;
|
||||
public static final String STATE = "state";
|
||||
|
||||
public EnableBlockLayoutAction() {
|
||||
state = false;
|
||||
putValue(AbstractAction.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(iconResource())));
|
||||
putValue(STATE, state);
|
||||
putValue(Action.SHORT_DESCRIPTION, "Cluster nodes into blocks");
|
||||
putValue(SELECTED_KEY, false);
|
||||
putValue(Action.SHORT_DESCRIPTION, "Show clustered sea of nodes");
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent ev) {
|
||||
this.state = !state;
|
||||
this.putValue(STATE, state);
|
||||
public boolean isSelected() {
|
||||
return (Boolean)getValue(SELECTED_KEY);
|
||||
}
|
||||
|
||||
protected String iconResource() {
|
||||
return "com/sun/hotspot/igv/view/images/blocks.gif";
|
||||
return "com/sun/hotspot/igv/view/images/blocks.png";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
}
|
||||
|
||||
}
|
||||
|
51
src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/EnableCFGLayoutAction.java
Normal file
51
src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/EnableCFGLayoutAction.java
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
package com.sun.hotspot.igv.view.actions;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.ImageIcon;
|
||||
import org.openide.util.ImageUtilities;
|
||||
|
||||
public class EnableCFGLayoutAction extends AbstractAction {
|
||||
|
||||
public EnableCFGLayoutAction() {
|
||||
putValue(AbstractAction.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(iconResource())));
|
||||
putValue(SELECTED_KEY, false);
|
||||
putValue(Action.SHORT_DESCRIPTION, "Show control-flow graph");
|
||||
}
|
||||
|
||||
public boolean isSelected() {
|
||||
return (Boolean)getValue(SELECTED_KEY);
|
||||
}
|
||||
|
||||
protected String iconResource() {
|
||||
return "com/sun/hotspot/igv/view/images/cfg.png";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
}
|
||||
}
|
51
src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/EnableSeaLayoutAction.java
Normal file
51
src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/EnableSeaLayoutAction.java
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
package com.sun.hotspot.igv.view.actions;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.ImageIcon;
|
||||
import org.openide.util.ImageUtilities;
|
||||
|
||||
public class EnableSeaLayoutAction extends AbstractAction {
|
||||
|
||||
public EnableSeaLayoutAction() {
|
||||
putValue(AbstractAction.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(iconResource())));
|
||||
putValue(SELECTED_KEY, false);
|
||||
putValue(Action.SHORT_DESCRIPTION, "Show sea of nodes");
|
||||
}
|
||||
|
||||
public boolean isSelected() {
|
||||
return (Boolean)getValue(SELECTED_KEY);
|
||||
}
|
||||
|
||||
protected String iconResource() {
|
||||
return "com/sun/hotspot/igv/view/images/sea.png";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
}
|
||||
}
|
10
src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/widgets/BlockWidget.java
10
src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/widgets/BlockWidget.java
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -43,7 +43,8 @@ public class BlockWidget extends Widget {
|
||||
|
||||
public static final int BORDER = 20;
|
||||
public static final Color BACKGROUND_COLOR = new Color(235, 235, 255);
|
||||
private static final Font titleFont = new Font("Serif", Font.PLAIN, 14).deriveFont(Font.BOLD);
|
||||
private static final Font TITLE_FONT = new Font("Arial", Font.BOLD, 14);
|
||||
public static final Color TITLE_COLOR = new Color(42, 42, 171);
|
||||
private InputBlock blockNode;
|
||||
private Diagram diagram;
|
||||
|
||||
@ -70,9 +71,8 @@ public class BlockWidget extends Widget {
|
||||
g.drawRect(r.x, r.y, r.width, r.height);
|
||||
}
|
||||
|
||||
Color titleColor = Color.BLACK;
|
||||
g.setColor(titleColor);
|
||||
g.setFont(titleFont);
|
||||
g.setColor(TITLE_COLOR);
|
||||
g.setFont(TITLE_FONT);
|
||||
|
||||
String s = "B" + blockNode.getName();
|
||||
Rectangle2D r1 = g.getFontMetrics().getStringBounds(s, g);
|
||||
|
20
src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/widgets/FigureWidget.java
20
src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/widgets/FigureWidget.java
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -46,6 +46,7 @@ import javax.swing.event.MenuListener;
|
||||
import org.netbeans.api.visual.action.PopupMenuProvider;
|
||||
import org.netbeans.api.visual.action.WidgetAction;
|
||||
import org.netbeans.api.visual.layout.LayoutFactory;
|
||||
import org.netbeans.api.visual.layout.LayoutFactory.SerialAlignment;
|
||||
import org.netbeans.api.visual.model.ObjectState;
|
||||
import org.netbeans.api.visual.widget.LabelWidget;
|
||||
import org.netbeans.api.visual.widget.Widget;
|
||||
@ -106,14 +107,20 @@ public class FigureWidget extends Widget implements Properties.Provider, PopupMe
|
||||
outer.setLayout(LayoutFactory.createOverlayLayout());
|
||||
|
||||
middleWidget = new Widget(scene);
|
||||
middleWidget.setLayout(LayoutFactory.createVerticalFlowLayout(LayoutFactory.SerialAlignment.CENTER, 0));
|
||||
SerialAlignment textAlign = scene.getModel().getShowCFG() ?
|
||||
LayoutFactory.SerialAlignment.LEFT_TOP :
|
||||
LayoutFactory.SerialAlignment.CENTER;
|
||||
middleWidget.setLayout(LayoutFactory.createVerticalFlowLayout(textAlign, 0));
|
||||
middleWidget.setBackground(f.getColor());
|
||||
middleWidget.setOpaque(true);
|
||||
middleWidget.getActions().addAction(new DoubleClickAction(this));
|
||||
middleWidget.setCheckClipping(true);
|
||||
|
||||
dummyTop = new Widget(scene);
|
||||
dummyTop.setMinimumSize(new Dimension(Figure.INSET / 2, 1));
|
||||
int extraTopHeight =
|
||||
getFigure().getDiagram().isCFG() && getFigure().hasNamedInputSlot() ?
|
||||
Figure.TOP_CFG_HEIGHT : 0;
|
||||
dummyTop.setMinimumSize(new Dimension(Figure.INSET / 2, 1 + extraTopHeight));
|
||||
middleWidget.addChild(dummyTop);
|
||||
|
||||
String[] strings = figure.getLines();
|
||||
@ -132,10 +139,13 @@ public class FigureWidget extends Widget implements Properties.Provider, PopupMe
|
||||
}
|
||||
|
||||
Widget dummyBottom = new Widget(scene);
|
||||
dummyBottom.setMinimumSize(new Dimension(Figure.INSET / 2, 1));
|
||||
int extraBottomHeight =
|
||||
getFigure().getDiagram().isCFG() && getFigure().hasNamedOutputSlot() ?
|
||||
Figure.BOTTOM_CFG_HEIGHT : 0;
|
||||
dummyBottom.setMinimumSize(new Dimension(Figure.INSET / 2, 1 + extraBottomHeight));
|
||||
middleWidget.addChild(dummyBottom);
|
||||
|
||||
middleWidget.setPreferredBounds(new Rectangle(0, Figure.SLOT_WIDTH - Figure.OVERLAPPING, f.getWidth(), f.getHeight()));
|
||||
middleWidget.setPreferredBounds(new Rectangle(0, Figure.getVerticalOffset(), f.getWidth(), f.getHeight()));
|
||||
this.addChild(middleWidget);
|
||||
|
||||
// Initialize node for property sheet
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,7 +26,6 @@ package com.sun.hotspot.igv.view.widgets;
|
||||
import com.sun.hotspot.igv.graph.Figure;
|
||||
import com.sun.hotspot.igv.graph.InputSlot;
|
||||
import com.sun.hotspot.igv.view.DiagramScene;
|
||||
import java.awt.Point;
|
||||
import java.util.List;
|
||||
import org.netbeans.api.visual.widget.Widget;
|
||||
|
||||
@ -41,12 +40,6 @@ public class InputSlotWidget extends SlotWidget {
|
||||
public InputSlotWidget(InputSlot slot, DiagramScene scene, Widget parent, FigureWidget fw) {
|
||||
super(slot, scene, parent, fw);
|
||||
inputSlot = slot;
|
||||
//init();
|
||||
//getFigureWidget().getLeftWidget().addChild(this);
|
||||
Point p = inputSlot.getRelativePosition();
|
||||
p.x -= this.calculateClientArea().width / 2;
|
||||
p.y += Figure.SLOT_START;
|
||||
this.setPreferredLocation(p);
|
||||
}
|
||||
|
||||
public InputSlot getInputSlot() {
|
||||
@ -59,6 +52,12 @@ public class InputSlotWidget extends SlotWidget {
|
||||
assert slots.contains(getSlot());
|
||||
return calculateWidth(slots.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int yOffset() {
|
||||
return getFigureWidget().getFigure().getDiagram().isCFG() ?
|
||||
calculateClientArea().height - 1 : Figure.SLOT_START;
|
||||
}
|
||||
/*
|
||||
protected Point calculateRelativeLocation() {
|
||||
if (getFigureWidget().getBounds() == null) {
|
||||
|
39
src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/widgets/LineWidget.java
39
src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/widgets/LineWidget.java
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,8 +25,8 @@ package com.sun.hotspot.igv.view.widgets;
|
||||
|
||||
import com.sun.hotspot.igv.graph.Connection;
|
||||
import com.sun.hotspot.igv.graph.Figure;
|
||||
import com.sun.hotspot.igv.graph.InputSlot;
|
||||
import com.sun.hotspot.igv.graph.OutputSlot;
|
||||
import com.sun.hotspot.igv.graph.Block;
|
||||
import com.sun.hotspot.igv.util.StringUtils;
|
||||
import com.sun.hotspot.igv.view.DiagramScene;
|
||||
import java.awt.*;
|
||||
@ -138,8 +138,10 @@ public class LineWidget extends Widget implements PopupMenuProvider {
|
||||
public void select(Widget arg0, Point arg1, boolean arg2) {
|
||||
Set<Figure> set = new HashSet<>();
|
||||
for (Connection c : LineWidget.this.connections) {
|
||||
set.add(c.getInputSlot().getFigure());
|
||||
set.add(c.getOutputSlot().getFigure());
|
||||
if (c.hasSlots()) {
|
||||
set.add(scene.getWidget(c.getTo()));
|
||||
set.add(scene.getWidget(c.getFrom()));
|
||||
}
|
||||
}
|
||||
LineWidget.this.scene.setSelectedObjects(set);
|
||||
}
|
||||
@ -242,10 +244,12 @@ public class LineWidget extends Widget implements PopupMenuProvider {
|
||||
Set<Object> highlightedObjects = new HashSet<>(scene.getHighlightedObjects());
|
||||
Set<Object> highlightedObjectsChange = new HashSet<>();
|
||||
for (Connection c : connections) {
|
||||
highlightedObjectsChange.add(c.getInputSlot().getFigure());
|
||||
highlightedObjectsChange.add(c.getInputSlot());
|
||||
highlightedObjectsChange.add(c.getOutputSlot().getFigure());
|
||||
highlightedObjectsChange.add(c.getOutputSlot());
|
||||
if (c.hasSlots()) {
|
||||
highlightedObjectsChange.add(c.getTo());
|
||||
highlightedObjectsChange.add(c.getTo().getVertex());
|
||||
highlightedObjectsChange.add(c.getFrom());
|
||||
highlightedObjectsChange.add(c.getFrom().getVertex());
|
||||
}
|
||||
}
|
||||
if(b) {
|
||||
highlightedObjects.addAll(highlightedObjectsChange);
|
||||
@ -312,14 +316,19 @@ public class LineWidget extends Widget implements PopupMenuProvider {
|
||||
@Override
|
||||
public JPopupMenu getPopupMenu(Widget widget, Point localLocation) {
|
||||
JPopupMenu menu = new JPopupMenu();
|
||||
menu.add(scene.createGotoAction(outputSlot.getFigure()));
|
||||
menu.addSeparator();
|
||||
|
||||
for (Connection c : connections) {
|
||||
InputSlot s = c.getInputSlot();
|
||||
menu.add(scene.createGotoAction(s.getFigure()));
|
||||
if (outputSlot == null) { // One-to-one block line.
|
||||
assert (connections.size() == 1);
|
||||
Connection c = connections.get(0);
|
||||
menu.add(scene.createGotoAction((Block)c.getFromCluster()));
|
||||
menu.addSeparator();
|
||||
menu.add(scene.createGotoAction((Block)c.getToCluster()));
|
||||
} else { // One-to-many figure line.
|
||||
menu.add(scene.createGotoAction(outputSlot.getFigure()));
|
||||
menu.addSeparator();
|
||||
for (Connection c : connections) {
|
||||
menu.add(scene.createGotoAction((Figure)c.getTo().getVertex()));
|
||||
}
|
||||
}
|
||||
|
||||
final LineWidget w = this;
|
||||
menu.addPopupMenuListener(new PopupMenuListener() {
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,7 +26,6 @@ package com.sun.hotspot.igv.view.widgets;
|
||||
import com.sun.hotspot.igv.graph.Figure;
|
||||
import com.sun.hotspot.igv.graph.OutputSlot;
|
||||
import com.sun.hotspot.igv.view.DiagramScene;
|
||||
import java.awt.Point;
|
||||
import java.util.List;
|
||||
import org.netbeans.api.visual.widget.Widget;
|
||||
|
||||
@ -41,10 +40,6 @@ public class OutputSlotWidget extends SlotWidget {
|
||||
public OutputSlotWidget(OutputSlot slot, DiagramScene scene, Widget parent, FigureWidget fw) {
|
||||
super(slot, scene, parent, fw);
|
||||
outputSlot = slot;
|
||||
Point p = outputSlot.getRelativePosition();
|
||||
p.y += getSlot().getFigure().getHeight() - Figure.SLOT_START;
|
||||
p.x -= this.calculateClientArea().width / 2;
|
||||
this.setPreferredLocation(p);
|
||||
}
|
||||
|
||||
public OutputSlot getOutputSlot() {
|
||||
@ -58,4 +53,11 @@ public class OutputSlotWidget extends SlotWidget {
|
||||
return calculateWidth(slots.size());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int yOffset() {
|
||||
int overlap = getFigureWidget().getFigure().getDiagram().isCFG() ?
|
||||
calculateClientArea().height : Figure.SLOT_START;
|
||||
return getSlot().getFigure().getHeight() - overlap;
|
||||
}
|
||||
}
|
||||
|
21
src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/widgets/SlotWidget.java
21
src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/widgets/SlotWidget.java
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -32,6 +32,7 @@ import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.HashSet;
|
||||
@ -57,13 +58,16 @@ public abstract class SlotWidget extends Widget implements DoubleClickHandler {
|
||||
this.diagramScene = scene;
|
||||
this.slot = slot;
|
||||
figureWidget = fw;
|
||||
if (!slot.getSource().getSourceNodes().isEmpty()) {
|
||||
if (slot.hasSourceNodes()) {
|
||||
this.setToolTipText("<HTML>" + slot.getToolTipText() + "</HTML>");
|
||||
}
|
||||
this.setCheckClipping(true);
|
||||
parent.addChild(this);
|
||||
|
||||
//this.setPreferredBounds(this.calculateClientArea());
|
||||
Point p = slot.getRelativePosition();
|
||||
p.x -= this.calculateClientArea().width / 2;
|
||||
p.y += yOffset();
|
||||
this.setPreferredLocation(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -92,7 +96,7 @@ public abstract class SlotWidget extends Widget implements DoubleClickHandler {
|
||||
int w = this.getBounds().width;
|
||||
int h = this.getBounds().height;
|
||||
|
||||
if (getSlot().getSource().getSourceNodes().size() > 0) {
|
||||
if (getSlot().hasSourceNodes()) {
|
||||
final int SMALLER = 0;
|
||||
g.setColor(getSlot().getColor());
|
||||
|
||||
@ -109,7 +113,7 @@ public abstract class SlotWidget extends Widget implements DoubleClickHandler {
|
||||
g.setStroke(new BasicStroke(1f));
|
||||
}
|
||||
|
||||
if (getSlot().getShortName() != null && getSlot().getShortName().length() > 0) {
|
||||
if (getSlot().shouldShowName()) {
|
||||
g.setFont(font);
|
||||
Rectangle2D r1 = g.getFontMetrics().getStringBounds(getSlot().getShortName(), g);
|
||||
rectW = (int) r1.getWidth() + FONT_OFFSET * 2;
|
||||
@ -123,14 +127,15 @@ public abstract class SlotWidget extends Widget implements DoubleClickHandler {
|
||||
}
|
||||
g.drawRect(w / 2 - rectW / 2, 0, rectW - 1, s - 1);
|
||||
|
||||
if (getSlot().getShortName() != null && getSlot().getShortName().length() > 0 && getScene().getZoomFactor() >= TEXT_ZOOM_FACTOR) {
|
||||
if (getSlot().shouldShowName() && getScene().getZoomFactor() >= TEXT_ZOOM_FACTOR) {
|
||||
Rectangle2D r1 = g.getFontMetrics().getStringBounds(getSlot().getShortName(), g);
|
||||
g.drawString(getSlot().getShortName(), (int) (w - r1.getWidth()) / 2, g.getFontMetrics().getAscent() - 1);//(int) (r1.getHeight()));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (this.getSlot().getConnections().isEmpty()) {
|
||||
if (this.getSlot().getConnections().isEmpty() &&
|
||||
!getFigureWidget().getFigure().getDiagram().isCFG()) {
|
||||
if (this.getState().isHighlighted()) {
|
||||
g.setColor(Color.BLUE);
|
||||
} else {
|
||||
@ -155,6 +160,8 @@ public abstract class SlotWidget extends Widget implements DoubleClickHandler {
|
||||
|
||||
protected abstract int calculateSlotWidth();
|
||||
|
||||
protected abstract int yOffset();
|
||||
|
||||
protected int calculateWidth(int count) {
|
||||
return getFigureWidget().getFigure().getWidth() / count;
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
CTL_EditorAction=Open Editor Window
|
||||
CTL_NextDiagramAction=Show next graph
|
||||
CTL_EnableSeaLayoutAction=Enable sea-of-nodes layout
|
||||
CTL_EnableBlockLayoutAction=Enable block layout
|
||||
CTL_EnableCFGLayoutAction=Enable control-flow graph layout
|
||||
CTL_NodeFindAction=Find
|
||||
CTL_PrevDiagramAction=Show previous graph
|
||||
CTL_ExportAction=Export current graph...
|
||||
|
BIN
src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/images/blocks.gif
BIN
src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/images/blocks.gif
Binary file not shown.
Before ![]() (image error) Size: 143 B |
BIN
src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/images/blocks.png
Normal file
BIN
src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/images/blocks.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 1.7 KiB |
BIN
src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/images/cfg.png
Normal file
BIN
src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/images/cfg.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 1.6 KiB |
BIN
src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/images/sea.png
Normal file
BIN
src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/images/sea.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 1.6 KiB |
@ -17,7 +17,9 @@
|
||||
<file name="com-sun-hotspot-igv-view-actions-ZoomOutAction.instance"><attr name="position" intvalue="2001"/></file>
|
||||
<file name="com-sun-hotspot-igv-view-actions-OverviewAction.instance"><attr name="position" intvalue="2001"/></file>
|
||||
<file name="com-sun-hotspot-igv-view-actions-PredSuccAction.instance"><attr name="position" intvalue="2001"/></file>
|
||||
<file name="com-sun-hotspot-igv-view-actions-EnableSeaLayoutAction.instance"><attr name="position" intvalue="2001"/></file>
|
||||
<file name="com-sun-hotspot-igv-view-actions-EnableBlockLayoutAction.instance"><attr name="position" intvalue="2001"/></file>
|
||||
<file name="com-sun-hotspot-igv-view-actions-EnableCFGLayoutAction.instance"><attr name="position" intvalue="2001"/></file>
|
||||
</folder>
|
||||
</folder>
|
||||
<folder name="Menu">
|
||||
@ -80,6 +82,11 @@
|
||||
<attr name="position" intvalue="0"/>
|
||||
<file name="com-sun-hotspot-igv-view-NodeQuickSearch.instance"/>
|
||||
</folder>
|
||||
<folder name="Blocks">
|
||||
<attr name="command" stringvalue="n"/>
|
||||
<attr name="position" intvalue="1"/>
|
||||
<file name="com-sun-hotspot-igv-view-BlockQuickSearch.instance"/>
|
||||
</folder>
|
||||
<file name="Projects_hidden"/>
|
||||
</folder>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user