changeset 21146:33ff6b03fad1

add support for control flow window and basic block view on graphs Contributed-by: Michael Haupt <michael.haupt@oracle.com> Contributed-by: Peter Hofer <peter.hofer@jku.at> Contributed-by: Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
author Michael Haupt <michael.haupt@oracle.com>
date Wed, 29 Apr 2015 08:31:28 +0200
parents 0b221b4ad707
children 2b03d4ce9bce
files src/share/tools/IdealGraphVisualizer/ControlFlow/build.xml src/share/tools/IdealGraphVisualizer/ControlFlow/manifest.mf src/share/tools/IdealGraphVisualizer/ControlFlow/nbproject/build-impl.xml src/share/tools/IdealGraphVisualizer/ControlFlow/nbproject/genfiles.properties src/share/tools/IdealGraphVisualizer/ControlFlow/nbproject/platform.properties src/share/tools/IdealGraphVisualizer/ControlFlow/nbproject/project.properties src/share/tools/IdealGraphVisualizer/ControlFlow/nbproject/project.xml src/share/tools/IdealGraphVisualizer/ControlFlow/nbproject/suite.properties src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/BlockConnectionWidget.java src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/BlockWidget.java src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/Bundle.properties src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowAction.java src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowScene.java src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponent.form src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponent.java src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponentSettings.xml src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponentWstcref.xml src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/DoubleClickSelectAction.java src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/HierarchicalGraphLayout.java src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/layer.xml src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Block.java src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Figure.java src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterEdge.java src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterIngoingConnection.java src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterInputSlotNode.java src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterNode.java src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterOutgoingConnection.java src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterOutputSlotNode.java src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalClusterLayoutManager.java src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/InterClusterConnection.java src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Cluster.java src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutGraph.java src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Vertex.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/EnableBlockLayoutAction.java src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/BlockWidget.java src/share/tools/IdealGraphVisualizer/nbproject/project.properties
diffstat 40 files changed, 2796 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/build.xml	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
+<!-- for some information on what you could do (e.g. targets to override). -->
+<!-- If you delete this file and reopen the project it will be recreated. -->
+<project name="com.sun.hotspot.igv.controlflow" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.controlflow.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/manifest.mf	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.controlflow
+OpenIDE-Module-Layer: com/sun/hotspot/igv/controlflow/layer.xml
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/controlflow/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/nbproject/build-impl.xml	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.controlflow-impl" basedir="..">
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
+        <condition>
+            <not>
+                <available file="${harness.dir}" type="dir"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/nbproject/genfiles.properties	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=b524efb3
+build.xml.script.CRC32=79a27be9
+build.xml.stylesheet.CRC32=79c3b980
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=b524efb3
+nbproject/build-impl.xml.script.CRC32=582bdab7
+nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/nbproject/platform.properties	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,29 @@
+# Deprecated since 5.0u1; for compatibility with 5.0:
+disabled.clusters=\
+    apisupport1,\
+    harness,\
+    ide8,\
+    java1,\
+    nb6.0,\
+    profiler2
+disabled.modules=\
+    org.netbeans.core.execution,\
+    org.netbeans.core.multiview,\
+    org.netbeans.core.output2,\
+    org.netbeans.modules.applemenu,\
+    org.netbeans.modules.autoupdate.services,\
+    org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.core.kit,\
+    org.netbeans.modules.favorites,\
+    org.netbeans.modules.javahelp,\
+    org.netbeans.modules.masterfs,\
+    org.netbeans.modules.options.keymap,\
+    org.netbeans.modules.sendopts,\
+    org.netbeans.modules.templates,\
+    org.openide.compat,\
+    org.openide.execution,\
+    org.openide.util.enumerations
+enabled.clusters=\
+    platform7
+nbjdk.active=JDK_1.6
+nbplatform.active=default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/nbproject/project.properties	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,2 @@
+javac.source=1.5
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/nbproject/project.xml	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>com.sun.hotspot.igv.controlflow</code-name-base>
+            <suite-component/>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.data</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.hierarchicallayout</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.layout</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.jdesktop.layout</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.16.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.visual</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>2.9</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.14.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.6.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.windows</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>6.16</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages/>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/nbproject/suite.properties	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/BlockConnectionWidget.java	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2008, 2015, 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.controlflow;
+
+import com.sun.hotspot.igv.data.InputBlockEdge;
+import com.sun.hotspot.igv.layout.Link;
+import com.sun.hotspot.igv.layout.Port;
+import java.awt.BasicStroke;
+import java.awt.Point;
+import java.awt.Stroke;
+import java.util.ArrayList;
+import java.util.List;
+import org.netbeans.api.visual.widget.ConnectionWidget;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class BlockConnectionWidget extends ConnectionWidget implements Link {
+
+    private static final Stroke NORMAL_STROKE = new BasicStroke(1.0f);
+    private static final Stroke BOLD_STROKE = new BasicStroke(2.5f);
+    private static final Stroke DASHED_STROKE = new BasicStroke(1.0f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10.0f, new float[]{5, 5}, 0);
+    private static final Stroke BOLD_DASHED_STROKE = new BasicStroke(2.5f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10.0f, new float[]{5, 5}, 0);
+    
+    private BlockWidget from;
+    private BlockWidget to;
+    private Port inputSlot;
+    private Port outputSlot;
+    private List<Point> points;
+    private InputBlockEdge edge;
+    private boolean isDashed = false;
+    private boolean isBold = false;
+
+    public BlockConnectionWidget(ControlFlowScene scene, InputBlockEdge edge) {
+        super(scene);
+
+        this.edge = edge;
+        this.from = (BlockWidget) scene.findWidget(edge.getFrom());
+        this.to = (BlockWidget) scene.findWidget(edge.getTo());
+        inputSlot = to.getInputSlot();
+        outputSlot = from.getOutputSlot();
+        points = new ArrayList<Point>();
+    }
+
+    public InputBlockEdge getEdge() {
+        return edge;
+    }
+
+    public Port getTo() {
+        return inputSlot;
+    }
+
+    public Port getFrom() {
+        return outputSlot;
+    }
+
+    public void setBold(boolean bold) {
+        this.isBold = bold;
+        updateStroke();
+    }
+
+    public void setDashed(boolean dashed) {
+        this.isDashed = dashed;
+        updateStroke();
+    }
+
+    private void updateStroke() {
+        Stroke stroke = NORMAL_STROKE;
+        if (isBold) {
+            if (isDashed) {
+                stroke = BOLD_DASHED_STROKE;
+            } else {
+                stroke = BOLD_STROKE;
+            }
+        } else if (isDashed) {
+            stroke = DASHED_STROKE;
+        }
+        setStroke(stroke);
+    }
+
+    public void setControlPoints(List<Point> p) {
+        this.points = p;
+    }
+
+    @Override
+    public List<Point> getControlPoints() {
+        return points;
+    }
+
+    @Override
+    public String toString() {
+        return "Connection[ " + from.toString() + " - " + to.toString() + "]";
+    }
+    
+    @Override
+    public boolean isVIP() {
+        return isBold;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/BlockWidget.java	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2008, 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.controlflow;
+
+import com.sun.hotspot.igv.data.InputBlock;
+import com.sun.hotspot.igv.layout.Cluster;
+import com.sun.hotspot.igv.layout.Port;
+import com.sun.hotspot.igv.layout.Vertex;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Point;
+import java.awt.Rectangle;
+import org.netbeans.api.visual.border.BorderFactory;
+import org.netbeans.api.visual.model.ObjectState;
+import org.netbeans.api.visual.widget.LabelWidget;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class BlockWidget extends LabelWidget implements Vertex {
+
+    public static final Dimension MIN_SIZE = new Dimension(20, 20);
+    private InputBlock block;
+    private Port inputSlot;
+    private Port outputSlot;
+    private Cluster cluster;
+    private boolean root;
+    private static final Font font = new Font(Font.SANS_SERIF, Font.PLAIN, 12);
+    private static final Font boldFont = font.deriveFont(Font.BOLD);
+    public static final Color NORMAL_FOREGROUND_COLOR = Color.BLACK;
+    public static final Color HOVER_FOREGROUND_COLOR = Color.BLUE;
+
+    /** Creates a new instance of BlockWidget */
+    public BlockWidget(ControlFlowScene scene, InputBlock block) {
+        super(scene);
+        this.block = block;
+        this.setLabel(block.getName());
+        this.setForeground(NORMAL_FOREGROUND_COLOR);
+        this.setBorder(BorderFactory.createLineBorder(1, NORMAL_FOREGROUND_COLOR));
+        this.setMinimumSize(MIN_SIZE);
+
+        this.setFont(font);
+        this.setAlignment(Alignment.CENTER);
+
+        final BlockWidget widget = this;
+        inputSlot = new Port() {
+            public Point getRelativePosition() {
+                return new Point((int) (getSize().getWidth() / 2), (int) (getSize().getHeight() / 2));
+            }
+            public Vertex getVertex() {
+                return widget;
+            }
+        };
+        outputSlot = new Port() {
+            public Point getRelativePosition() {
+                return new Point((int) (getSize().getWidth() / 2), (int) (getSize().getHeight() / 2));
+            }
+            public Vertex getVertex() {
+                return widget;
+            }
+        };
+    }
+
+    public Port getInputSlot() {
+        return inputSlot;
+    }
+
+    public Port getOutputSlot() {
+        return outputSlot;
+    }
+
+    public InputBlock getBlock() {
+        return block;
+    }
+
+    public Dimension getSize() {
+        Rectangle bounds = getBounds();
+        if (bounds != null) {
+            return bounds.getSize();
+        } else {
+            return MIN_SIZE;
+        }
+    }
+
+    public void setPosition(Point p) {
+        this.setPreferredLocation(p);
+    }
+
+    @Override
+    public String toString() {
+        return block.getName();
+    }
+
+    public Point getPosition() {
+        return this.getPreferredLocation();
+    }
+
+    public Cluster getCluster() {
+        return cluster;
+    }
+
+    public boolean isRoot() {
+        return root;
+    }
+
+    public void setCluster(Cluster c) {
+        cluster = c;
+    }
+
+    public void setRoot(boolean b) {
+        root = b;
+    }
+
+    public int compareTo(Vertex o) {
+        return toString().compareTo(o.toString());
+    }
+
+    @Override
+    protected void notifyStateChanged(ObjectState previousState, ObjectState state) {
+        super.notifyStateChanged(previousState, state);
+
+        if (previousState.isHovered() != state.isHovered()) {
+            if (state.isHovered()) {
+                this.setBorder(BorderFactory.createLineBorder(1, HOVER_FOREGROUND_COLOR));
+            } else {
+                this.setBorder(BorderFactory.createLineBorder(1, NORMAL_FOREGROUND_COLOR));
+            }
+        }
+
+        if (previousState.isSelected() != state.isSelected()) {
+            if (state.isSelected()) {
+                this.setFont(boldFont);
+            } else {
+                this.setFont(font);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/Bundle.properties	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,4 @@
+CTL_ControlFlowAction=Control Flow
+CTL_ControlFlowTopComponent=Control Flow
+HINT_ControlFlowTopComponent=Shows the blocks of the current graph.
+OpenIDE-Module-Name=ControlFlow
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowAction.java	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2008, 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.controlflow;
+
+import java.awt.event.ActionEvent;
+import javax.swing.AbstractAction;
+import org.openide.util.NbBundle;
+import org.openide.windows.TopComponent;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ControlFlowAction extends AbstractAction {
+
+    public ControlFlowAction() {
+        super(NbBundle.getMessage(ControlFlowAction.class, "CTL_ControlFlowAction"));
+    }
+
+    public void actionPerformed(ActionEvent evt) {
+        TopComponent win = ControlFlowTopComponent.findInstance();
+        win.open();
+        win.requestActive();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowScene.java	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2008, 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.controlflow;
+
+import com.sun.hotspot.igv.data.InputBlockEdge;
+import com.sun.hotspot.igv.data.InputBlock;
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.services.InputGraphProvider;
+import com.sun.hotspot.igv.data.InputNode;
+import com.sun.hotspot.igv.util.LookupHistory;
+import java.awt.Color;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+import javax.swing.BorderFactory;
+import org.netbeans.api.visual.action.ActionFactory;
+import org.netbeans.api.visual.action.MoveProvider;
+import org.netbeans.api.visual.action.RectangularSelectDecorator;
+import org.netbeans.api.visual.action.RectangularSelectProvider;
+import org.netbeans.api.visual.action.SelectProvider;
+import org.netbeans.api.visual.action.WidgetAction;
+import org.netbeans.api.visual.anchor.AnchorFactory;
+import org.netbeans.api.visual.anchor.AnchorShape;
+import org.netbeans.api.visual.router.RouterFactory;
+import org.netbeans.api.visual.widget.LayerWidget;
+import org.netbeans.api.visual.widget.Widget;
+import org.netbeans.api.visual.graph.GraphScene;
+import org.netbeans.api.visual.graph.layout.GraphLayout;
+import org.netbeans.api.visual.layout.LayoutFactory;
+import org.netbeans.api.visual.layout.SceneLayout;
+import org.netbeans.api.visual.widget.ConnectionWidget;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ControlFlowScene extends GraphScene<InputBlock, InputBlockEdge> implements SelectProvider, MoveProvider, RectangularSelectDecorator, RectangularSelectProvider {
+
+    private HashSet<BlockWidget> selection;
+    private InputGraph oldGraph;
+    private LayerWidget edgeLayer;
+    private LayerWidget mainLayer;
+    private LayerWidget selectLayer;
+    private WidgetAction hoverAction = this.createWidgetHoverAction();
+    private WidgetAction selectAction = new DoubleClickSelectAction(this);
+    private WidgetAction moveAction = ActionFactory.createMoveAction(null, this);
+
+    public ControlFlowScene() {
+        selection = new HashSet<BlockWidget>();
+
+        this.getInputBindings().setZoomActionModifiers(0);
+        this.setLayout(LayoutFactory.createAbsoluteLayout());
+
+        mainLayer = new LayerWidget(this);
+        this.addChild(mainLayer);
+
+        edgeLayer = new LayerWidget(this);
+        this.addChild(edgeLayer);
+        
+        selectLayer = new LayerWidget(this);
+        this.addChild(selectLayer);
+
+        this.getActions().addAction(hoverAction);
+        this.getActions().addAction(selectAction);
+        this.getActions().addAction(ActionFactory.createRectangularSelectAction(this, selectLayer, this));
+        this.getActions().addAction(ActionFactory.createMouseCenteredZoomAction(1.1));
+    }
+
+    public void setGraph(InputGraph g) {
+        if (g == oldGraph) {
+            return;
+        }
+        oldGraph = g;
+
+        ArrayList<InputBlock> blocks = new ArrayList<InputBlock>(this.getNodes());
+        for (InputBlock b : blocks) {
+            removeNode(b);
+        }
+
+        ArrayList<InputBlockEdge> edges = new ArrayList<InputBlockEdge>(this.getEdges());
+        for (InputBlockEdge e : edges) {
+            removeEdge(e);
+        }
+
+        for (InputBlock b : g.getBlocks()) {
+            addNode(b);
+        }
+
+        for (InputBlockEdge e : g.getBlockEdges()) {
+            addEdge(e);
+            assert g.getBlocks().contains(e.getFrom());
+            assert g.getBlocks().contains(e.getTo());
+            this.setEdgeSource(e, e.getFrom());
+            this.setEdgeTarget(e, e.getTo());
+        }
+
+        GraphLayout<InputBlock, InputBlockEdge> layout = new HierarchicalGraphLayout<InputBlock, InputBlockEdge>();//GridGraphLayout();
+        SceneLayout sceneLayout = LayoutFactory.createSceneGraphLayout(this, layout);
+        sceneLayout.invokeLayout();
+
+        this.validate();
+    }
+
+    public void clearSelection() {
+        for (BlockWidget w : selection) {
+            w.setState(w.getState().deriveSelected(false));
+        }
+        selection.clear();
+        selectionChanged();
+    }
+
+    public void selectionChanged() {
+        InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//)Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
+        if (p != null) {
+            Set<InputNode> inputNodes = new HashSet<InputNode>();
+            for (BlockWidget w : selection) {
+                inputNodes.addAll(w.getBlock().getNodes());
+            }
+            p.setSelectedNodes(inputNodes);
+        }
+    }
+
+    public void addToSelection(BlockWidget widget) {
+        widget.setState(widget.getState().deriveSelected(true));
+        selection.add(widget);
+        selectionChanged();
+    }
+
+    public void removeFromSelection(BlockWidget widget) {
+        widget.setState(widget.getState().deriveSelected(false));
+        selection.remove(widget);
+        selectionChanged();
+    }
+
+    public boolean isAimingAllowed(Widget widget, Point point, boolean b) {
+        return false;
+    }
+
+    public boolean isSelectionAllowed(Widget widget, Point point, boolean b) {
+        return true;
+    }
+
+    public void select(Widget widget, Point point, boolean change) {
+        if (widget == this) {
+            clearSelection();
+        } else {
+
+            assert widget instanceof BlockWidget;
+            BlockWidget bw = (BlockWidget) widget;
+            if (change) {
+                if (selection.contains(bw)) {
+                    removeFromSelection(bw);
+                } else {
+                    addToSelection(bw);
+                }
+            } else {
+                if (!selection.contains(bw)) {
+                    clearSelection();
+                    addToSelection(bw);
+                }
+            }
+        }
+    }
+
+    public void movementStarted(Widget widget) {
+    }
+
+    public void movementFinished(Widget widget) {
+    }
+
+    public Point getOriginalLocation(Widget widget) {
+        return widget.getPreferredLocation();
+    }
+
+    public void setNewLocation(Widget widget, Point location) {
+        if (selection.contains(widget)) {
+            // move entire selection
+            Point originalLocation = getOriginalLocation(widget);
+            int xOffset = location.x - originalLocation.x;
+            int yOffset = location.y - originalLocation.y;
+            for (Widget w : selection) {
+                Point p = new Point(w.getPreferredLocation());
+                p.translate(xOffset, yOffset);
+                w.setPreferredLocation(p);
+            }
+        } else {
+            widget.setPreferredLocation(location);
+        }
+    }
+
+    public Widget createSelectionWidget() {
+        Widget widget = new Widget(this);
+        widget.setOpaque(false);
+        widget.setBorder(BorderFactory.createLineBorder(Color.black, 2));
+        widget.setForeground(Color.red);
+        return widget;
+    }
+
+    public void performSelection(Rectangle rectangle) {
+
+        if (rectangle.width < 0) {
+            rectangle.x += rectangle.width;
+            rectangle.width *= -1;
+        }
+
+        if (rectangle.height < 0) {
+            rectangle.y += rectangle.height;
+            rectangle.height *= -1;
+        }
+
+        boolean changed = false;
+        for (InputBlock b : this.getNodes()) {
+            BlockWidget w = (BlockWidget) findWidget(b);
+            Rectangle r = new Rectangle(w.getBounds());
+            r.setLocation(w.getLocation());
+            if (r.intersects(rectangle)) {
+                if (!selection.contains(w)) {
+                    changed = true;
+                    selection.add(w);
+                    w.setState(w.getState().deriveSelected(true));
+                }
+            } else {
+                if (selection.contains(w)) {
+                    changed = true;
+                    selection.remove(w);
+                    w.setState(w.getState().deriveSelected(false));
+                }
+            }
+        }
+
+        if (changed) {
+            selectionChanged();
+        }
+
+    }
+
+    protected Widget attachNodeWidget(InputBlock node) {
+        BlockWidget w = new BlockWidget(this, node);
+        mainLayer.addChild(w);
+        w.getActions().addAction(hoverAction);
+        w.getActions().addAction(selectAction);
+        w.getActions().addAction(moveAction);
+        return w;
+    }
+
+    protected Widget attachEdgeWidget(InputBlockEdge edge) {
+        BlockConnectionWidget w = new BlockConnectionWidget(this, edge);
+        switch (edge.getState()) {
+            case NEW:
+                w.setBold(true);
+                break;
+            case DELETED:
+                w.setDashed(true);
+                break;
+        }
+        w.setRouter(RouterFactory.createDirectRouter());
+        w.setTargetAnchorShape(AnchorShape.TRIANGLE_FILLED);
+        edgeLayer.addChild(w);
+        return w;
+    }
+
+    protected void attachEdgeSourceAnchor(InputBlockEdge edge, InputBlock oldSourceNode, InputBlock sourceNode) {
+        Widget w = this.findWidget(edge);
+        assert w instanceof ConnectionWidget;
+        ConnectionWidget cw = (ConnectionWidget) w;
+        cw.setSourceAnchor(AnchorFactory.createRectangularAnchor(findWidget(sourceNode)));
+
+    }
+
+    protected void attachEdgeTargetAnchor(InputBlockEdge edge, InputBlock oldTargetNode, InputBlock targetNode) {
+        Widget w = this.findWidget(edge);
+        assert w instanceof ConnectionWidget;
+        ConnectionWidget cw = (ConnectionWidget) w;
+        cw.setTargetAnchor(AnchorFactory.createRectangularAnchor(findWidget(targetNode)));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponent.form	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.3" maxVersion="1.3" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <EmptySpace min="0" pref="400" max="32767" attributes="0"/>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <EmptySpace min="0" pref="300" max="32767" attributes="0"/>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+</Form>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponent.java	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2008, 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.controlflow;
+
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.services.InputGraphProvider;
+import com.sun.hotspot.igv.util.LookupHistory;
+import java.awt.BorderLayout;
+import java.io.Serializable;
+import javax.swing.JScrollPane;
+import javax.swing.SwingUtilities;
+import org.openide.ErrorManager;
+import org.openide.util.Lookup;
+import org.openide.util.LookupEvent;
+import org.openide.util.LookupListener;
+import org.openide.util.NbBundle;
+import org.openide.util.Utilities;
+import org.openide.windows.TopComponent;
+import org.openide.windows.WindowManager;
+
+/**
+ * 
+ * @author Thomas Wuerthinger
+ */
+final class ControlFlowTopComponent extends TopComponent implements LookupListener {
+
+    private static ControlFlowTopComponent instance;
+    private Lookup.Result result = null;
+    private static final String PREFERRED_ID = "ControlFlowTopComponent";
+    private ControlFlowScene scene;
+
+    private ControlFlowTopComponent() {
+        initComponents();
+        setName(NbBundle.getMessage(ControlFlowTopComponent.class, "CTL_ControlFlowTopComponent"));
+        setToolTipText(NbBundle.getMessage(ControlFlowTopComponent.class, "HINT_ControlFlowTopComponent"));
+
+        scene = new ControlFlowScene();
+        this.setLayout(new BorderLayout());
+        this.associateLookup(scene.getLookup());
+
+
+        JScrollPane panel = new JScrollPane(scene.createView());
+        this.add(panel, BorderLayout.CENTER);
+    }
+
+
+
+    /** This method is called from within the constructor to
+     * initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is
+     * always regenerated by the Form Editor.
+     */
+    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+            .add(0, 400, Short.MAX_VALUE)
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+            .add(0, 300, Short.MAX_VALUE)
+        );
+    }// </editor-fold>//GEN-END:initComponents
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    // End of variables declaration//GEN-END:variables
+
+    /**
+     * Gets default instance. Do not use directly: reserved for *.settings files only,
+     * i.e. deserialization routines; otherwise you could get a non-deserialized instance.
+     * To obtain the singleton instance, use {@link findInstance}.
+     */
+    public static synchronized ControlFlowTopComponent getDefault() {
+        if (instance == null) {
+            instance = new ControlFlowTopComponent();
+        }
+        return instance;
+    }
+
+    /**
+     * Obtain the ControlFlowTopComponent instance. Never call {@link #getDefault} directly!
+     */
+    public static synchronized ControlFlowTopComponent findInstance() {
+        TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
+        if (win == null) {
+            ErrorManager.getDefault().log(ErrorManager.WARNING, "Cannot find ControlFlow component. It will not be located properly in the window system.");
+            return getDefault();
+        }
+        if (win instanceof ControlFlowTopComponent) {
+            return (ControlFlowTopComponent) win;
+        }
+        ErrorManager.getDefault().log(ErrorManager.WARNING, "There seem to be multiple components with the '" + PREFERRED_ID + "' ID. That is a potential source of errors and unexpected behavior.");
+        return getDefault();
+    }
+
+    @Override
+    public int getPersistenceType() {
+        return TopComponent.PERSISTENCE_ALWAYS;
+    }
+
+    @Override
+    public void componentOpened() {
+        Lookup.Template<InputGraphProvider> tpl = new Lookup.Template<InputGraphProvider>(InputGraphProvider.class);
+        result = Utilities.actionsGlobalContext().lookup(tpl);
+        result.addLookupListener(this);
+    }
+
+    @Override
+    public void componentClosed() {
+        result.removeLookupListener(this);
+        result = null;
+    }
+
+    public void resultChanged(LookupEvent lookupEvent) {
+        final InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
+        if (p != null) {
+            SwingUtilities.invokeLater(new Runnable() {
+
+                public void run() {
+                    InputGraph g = p.getGraph();
+                    if (g != null) {
+                        scene.setGraph(g);
+                    }
+                }
+            });
+        }
+    }
+
+    @Override
+    public Object writeReplace() {
+        return new ResolvableHelper();
+    }
+
+    @Override
+    protected String preferredID() {
+        return PREFERRED_ID;
+    }
+
+    @Override
+    public void requestActive() {
+        super.requestActive();
+        scene.getView().requestFocus();
+    }
+
+    final static class ResolvableHelper implements Serializable {
+
+        private static final long serialVersionUID = 1L;
+
+        public Object readResolve() {
+            return ControlFlowTopComponent.getDefault();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponentSettings.xml	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE settings PUBLIC "-//NetBeans//DTD Session settings 1.0//EN" "http://www.netbeans.org/dtds/sessionsettings-1_0.dtd">
+<settings version="1.0">
+    <module name="com.sun.hotspot.igv.controlflow" spec="1.0"/>
+    <instanceof class="org.openide.windows.TopComponent"/>
+    <instanceof class="com.sun.hotspot.igv.controlflow.ControlFlowTopComponent"/>
+    <instance class="com.sun.hotspot.igv.controlflow.ControlFlowTopComponent" method="getDefault"/>
+</settings>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponentWstcref.xml	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE tc-ref PUBLIC "-//NetBeans//DTD Top Component in Mode Properties 2.0//EN" "http://www.netbeans.org/dtds/tc-ref2_0.dtd">
+<tc-ref version="2.0" >
+    <module name="com.sun.hotspot.igv.controlflow" spec="1.0"/>
+    <tc-id id="ControlFlowTopComponent"/>
+    <state opened="true"/>
+</tc-ref>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/DoubleClickSelectAction.java	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011, 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.controlflow;
+
+import java.awt.Point;
+import java.awt.event.MouseEvent;
+import org.netbeans.api.visual.action.SelectProvider;
+import org.netbeans.api.visual.action.WidgetAction;
+import org.netbeans.api.visual.widget.Widget;
+
+/**
+ * Selection action that acts on double-click only. Does not support aiming.
+ * 
+ * @author Peter Hofer
+ */
+public class DoubleClickSelectAction extends WidgetAction.LockedAdapter {
+
+    private final SelectProvider provider;
+
+    public DoubleClickSelectAction(SelectProvider provider) {
+        this.provider = provider;
+    }
+
+    protected boolean isLocked() {
+        return false;
+    }
+
+    @Override
+    public State mousePressed(Widget widget, WidgetMouseEvent event) {
+        if (event.getClickCount() >= 2 && (event.getButton() == MouseEvent.BUTTON1 || event.getButton() == MouseEvent.BUTTON2)) {
+            boolean invert = (event.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) != 0;
+            Point point = event.getPoint();
+            if (provider.isSelectionAllowed(widget, point, invert)) {
+                provider.select(widget, point, invert);
+                return State.CHAIN_ONLY;
+            }
+        }
+        return State.REJECTED;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/HierarchicalGraphLayout.java	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2008, 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.controlflow;
+
+import com.sun.hotspot.igv.hierarchicallayout.HierarchicalLayoutManager;
+import com.sun.hotspot.igv.layout.Cluster;
+import com.sun.hotspot.igv.layout.LayoutGraph;
+import com.sun.hotspot.igv.layout.Link;
+import com.sun.hotspot.igv.layout.Port;
+import com.sun.hotspot.igv.layout.Vertex;
+import java.awt.Dimension;
+import java.awt.Point;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.netbeans.api.visual.graph.layout.GraphLayout;
+import org.netbeans.api.visual.graph.layout.UniversalGraph;
+import org.netbeans.api.visual.widget.Widget;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class HierarchicalGraphLayout<N, E> extends GraphLayout<N, E> {
+
+    public HierarchicalGraphLayout() {
+    }
+
+    private class LinkWrapper implements Link {
+
+        private VertexWrapper from;
+        private VertexWrapper to;
+
+        public LinkWrapper(VertexWrapper from, VertexWrapper to) {
+            this.from = from;
+            this.to = to;
+        }
+
+        public Port getFrom() {
+            return from.getSlot();
+        }
+
+        public Port getTo() {
+            return to.getSlot();
+        }
+
+        public List<Point> getControlPoints() {
+            return new ArrayList<Point>();
+        }
+
+        public void setControlPoints(List<Point> list) {
+        // Do nothing for now
+        }
+        
+        public boolean isVIP() {
+            return false;
+        }
+    }
+
+    private class VertexWrapper implements Vertex {
+
+        private N node;
+        private UniversalGraph<N, E> graph;
+        private Port slot;
+        private Point position;
+
+        public VertexWrapper(N node, UniversalGraph<N, E> graph) {
+            this.node = node;
+            this.graph = graph;
+            final VertexWrapper vertex = this;
+            this.slot = new Port() {
+
+                public Vertex getVertex() {
+                    return vertex;
+                }
+
+                public Point getRelativePosition() {
+                    return new Point((int) (vertex.getSize().getWidth() / 2), (int) (vertex.getSize().getHeight() / 2));
+                }
+            };
+
+            Widget w = graph.getScene().findWidget(node);
+            this.position = w.getPreferredLocation();
+        }
+
+        public Cluster getCluster() {
+            return null;
+        }
+
+        public Dimension getSize() {
+            Widget w = graph.getScene().findWidget(node);
+            return w.getBounds().getSize();
+        }
+
+        public Point getPosition() {
+            return position;
+        }
+
+        public void setPosition(Point p) {
+            HierarchicalGraphLayout.this.setResolvedNodeLocation(graph, node, p);
+            position = p;
+        }
+
+        public boolean isRoot() {
+            return false;
+        }
+
+        public int compareTo(Vertex o) {
+            @SuppressWarnings("unchecked")
+            VertexWrapper vw = (VertexWrapper) o;
+            return node.toString().compareTo(vw.node.toString());
+        }
+
+        public Port getSlot() {
+            return slot;
+        }
+    }
+
+    protected void performGraphLayout(UniversalGraph<N, E> graph) {
+        
+        Set<LinkWrapper> links = new LinkedHashSet<LinkWrapper>();
+        Set<VertexWrapper> vertices = new LinkedHashSet<VertexWrapper>();
+        Map<N, VertexWrapper> vertexMap = new HashMap<N, VertexWrapper>();
+
+        for (N node : graph.getNodes()) {
+            VertexWrapper v = new VertexWrapper(node, graph);
+            vertexMap.put(node, v);
+            vertices.add(v);
+        }
+
+        for (E edge : graph.getEdges()) {
+            N source = graph.getEdgeSource(edge);
+            N target = graph.getEdgeTarget(edge);
+            LinkWrapper l = new LinkWrapper(vertexMap.get(source), vertexMap.get(target));
+            links.add(l);
+        }
+
+        HierarchicalLayoutManager m = new HierarchicalLayoutManager(HierarchicalLayoutManager.Combine.NONE);
+
+        LayoutGraph layoutGraph = new LayoutGraph(links, vertices);
+        m.doLayout(layoutGraph);
+    }
+
+    protected void performNodesLayout(UniversalGraph<N, E> graph, Collection<N> nodes) {
+        throw new UnsupportedOperationException();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/layer.xml	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
+<filesystem>
+    <folder name="Actions">
+        <folder name="Window">
+            <file name="com-sun-hotspot-igv-controlflow-ControlFlowAction.instance"/>
+        </folder>
+    </folder>
+    <folder name="Menu">
+        <folder name="Window">
+            <file name="ControlFlowAction.shadow">
+                <attr name="originalFile" stringvalue="Actions/Window/com-sun-hotspot-igv-controlflow-ControlFlowAction.instance"/>
+            </file>
+        </folder>
+    </folder>
+    <folder name="Windows2">
+        <folder name="Components">
+            <file name="ControlFlowTopComponent.settings" url="ControlFlowTopComponentSettings.xml"/>
+        </folder>
+        <folder name="Modes">
+            <folder name="customRightTopMode">
+                <file name="ControlFlowTopComponent.wstcref" url="ControlFlowTopComponentWstcref.xml"/>
+            </folder>
+        </folder>
+    </folder>
+</filesystem>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Block.java	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2008, 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.data.InputBlock;
+import com.sun.hotspot.igv.layout.Cluster;
+import java.awt.Rectangle;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class Block implements Cluster {
+
+    private InputBlock inputBlock;
+    private Rectangle bounds;
+    private Diagram diagram;
+
+    public Block(InputBlock inputBlock, Diagram diagram) {
+        this.inputBlock = inputBlock;
+        this.diagram = diagram;
+    }
+
+    public Cluster getOuter() {
+        return null;
+    }
+
+    public InputBlock getInputBlock() {
+        return inputBlock;
+    }
+
+    public Set<? extends Cluster> getSuccessors() {
+        Set<Block> succs = new HashSet<Block>();
+        for (InputBlock b : inputBlock.getSuccessors()) {
+            succs.add(diagram.getBlock(b));
+        }
+        return succs;
+    }
+
+    public void setBounds(Rectangle r) {
+        this.bounds = r;
+    }
+
+    public Rectangle getBounds() {
+        return bounds;
+    }
+
+    public int compareTo(Cluster o) {
+        return toString().compareTo(o.toString());
+    }
+
+    @Override
+    public String toString() {
+        return inputBlock.getName();
+    }
+}
+    
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java	Tue Apr 28 12:58:40 2015 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java	Wed Apr 29 08:31:28 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, 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 com.sun.hotspot.igv.data.InputBlock;
 import com.sun.hotspot.igv.data.InputEdge;
 import com.sun.hotspot.igv.data.InputGraph;
 import com.sun.hotspot.igv.data.InputNode;
@@ -38,6 +39,7 @@
 public class Diagram {
 
     private List<Figure> figures;
+    private Map<InputBlock, Block> blocks;
     private InputGraph graph;
     private int curId;
     private String nodeText;
@@ -59,19 +61,37 @@
     
     private Diagram() {
         figures = new ArrayList<>();
+        blocks = new LinkedHashMap<>(8);
         this.nodeText = "";
         this.font = new Font("Arial", Font.PLAIN, 12);
         this.slotFont = new Font("Arial", Font.PLAIN, 10);
         this.boldFont = this.font.deriveFont(Font.BOLD);
     }
+    
+    public Block getBlock(InputBlock b) {
+        assert blocks.containsKey(b);
+        return blocks.get(b);
+    }
 
     public String getNodeText() {
         return nodeText;
     }
+    
+    public void updateBlocks() {
+        blocks.clear();
+        for (InputBlock b : graph.getBlocks()) {
+            Block curBlock = new Block(b, this);
+            blocks.put(b, curBlock);
+        }
+    }
 
     public Diagram getNext() {
         return Diagram.createDiagram(graph.getNext(), nodeText);
     }
+    
+    public Collection<Block> getBlocks() {
+        return Collections.unmodifiableCollection(blocks.values());
+    }
 
     public Diagram getPrev() {
         return Diagram.createDiagram(graph.getPrev(), nodeText);
@@ -118,6 +138,8 @@
         Diagram d = new Diagram();
         d.graph = graph;
         d.nodeText = nodeText;
+        
+        d.updateBlocks();
 
         Collection<InputNode> nodes = graph.getNodes();
         Hashtable<Integer, Figure> figureHash = new Hashtable<>();
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Figure.java	Tue Apr 28 12:58:40 2015 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Figure.java	Wed Apr 29 08:31:28 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, 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,10 +23,12 @@
  */
 package com.sun.hotspot.igv.graph;
 
+import com.sun.hotspot.igv.data.InputBlock;
 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.Source;
+import com.sun.hotspot.igv.layout.Cluster;
 import com.sun.hotspot.igv.layout.Vertex;
 import java.awt.*;
 import java.awt.image.BufferedImage;
@@ -338,6 +340,19 @@
     public String toString() {
         return idString;
     }
+    
+    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));
+            assert inputBlock != null;
+            Cluster result = diagram.getBlock(inputBlock);
+            assert result != null;
+            return result;
+        }
+    }
 
     @Override
     public boolean isRoot() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterEdge.java	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2008, 2015, 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.Link;
+import com.sun.hotspot.igv.layout.Port;
+import java.awt.Point;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ClusterEdge implements Link {
+
+    private ClusterNode from;
+    private ClusterNode to;
+    private List<Point> points;
+
+    public ClusterEdge(ClusterNode from, ClusterNode to) {
+        assert from != null;
+        assert to != null;
+        this.from = from;
+        this.to = to;
+    }
+
+    public Port getTo() {
+        return to.getInputSlot();
+    }
+
+    public Port getFrom() {
+        return from.getInputSlot();
+    }
+
+    public void setControlPoints(List<Point> p) {
+        this.points = p;
+    }
+
+    public List<Point> getControlPoints() {
+        return points;
+    }
+    
+    public boolean isVIP() {
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterIngoingConnection.java	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2008, 2015, 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.Link;
+import com.sun.hotspot.igv.layout.Port;
+import java.awt.Point;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ClusterIngoingConnection implements Link {
+
+    private List<Point> controlPoints;
+    private ClusterInputSlotNode inputSlotNode;
+    private Link connection;
+    private Port inputSlot;
+    private Port outputSlot;
+
+    public ClusterIngoingConnection(ClusterInputSlotNode inputSlotNode, Link c) {
+        this.inputSlotNode = inputSlotNode;
+        this.connection = c;
+        this.controlPoints = new ArrayList<Point>();
+
+        inputSlot = c.getTo();
+        outputSlot = inputSlotNode.getOutputSlot();
+    }
+
+    public Link getConnection() {
+        return connection;
+    }
+
+    public ClusterInputSlotNode getInputSlotNode() {
+        return inputSlotNode;
+    }
+
+    public Port getTo() {
+        return inputSlot;
+    }
+
+    public Port getFrom() {
+        return outputSlot;
+    }
+
+    public void setControlPoints(List<Point> p) {
+        this.controlPoints = p;
+    }
+
+    public List<Point> getControlPoints() {
+        return controlPoints;
+    }
+    
+    public boolean isVIP() {
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterInputSlotNode.java	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2008, 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.Cluster;
+import com.sun.hotspot.igv.layout.Port;
+import com.sun.hotspot.igv.layout.Vertex;
+import java.awt.Dimension;
+import java.awt.Point;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ClusterInputSlotNode implements Vertex {
+
+    private final int SIZE = 0;
+    private Point position;
+    private Port inputSlot;
+    private Port outputSlot;
+    private ClusterNode blockNode;
+    private InterClusterConnection interBlockConnection;
+    private Cluster cluster;
+    private ClusterIngoingConnection conn;
+
+    public void setIngoingConnection(ClusterIngoingConnection c) {
+        conn = c;
+    }
+
+    public ClusterIngoingConnection getIngoingConnection() {
+        return conn;
+    }
+    private String id;
+
+    @Override
+    public String toString() {
+        return id;
+    }
+
+    public ClusterInputSlotNode(ClusterNode n, String id) {
+        this.blockNode = n;
+        this.id = id;
+
+        n.addSubNode(this);
+
+        final Vertex thisNode = this;
+        final ClusterNode thisBlockNode = blockNode;
+
+        outputSlot = new Port() {
+
+            public Point getRelativePosition() {
+                return new Point(0, 0);
+            }
+
+            public Vertex getVertex() {
+                return thisNode;
+            }
+
+            @Override
+            public String toString() {
+                return "OutPort of " + thisNode.toString();
+            }
+        };
+
+        inputSlot = new Port() {
+
+            public Point getRelativePosition() {
+                Point p = new Point(thisNode.getPosition());
+                p.x += ClusterNode.BORDER;
+                p.y = 0;
+                return p;
+            }
+
+            public Vertex getVertex() {
+                return thisBlockNode;
+            }
+
+            @Override
+            public String toString() {
+                return "InPort of " + thisNode.toString();
+            }
+        };
+    }
+
+    public Port getInputSlot() {
+        return inputSlot;
+    }
+
+    public InterClusterConnection getInterBlockConnection() {
+        return interBlockConnection;
+    }
+
+    public Port getOutputSlot() {
+        return outputSlot;
+    }
+
+    public Dimension getSize() {
+        return new Dimension(SIZE, SIZE);
+    }
+
+    public void setPosition(Point p) {
+        this.position = p;
+    }
+
+    public Point getPosition() {
+        return position;
+    }
+
+    public void setInterBlockConnection(InterClusterConnection interBlockConnection) {
+        this.interBlockConnection = interBlockConnection;
+    }
+
+    public Cluster getCluster() {
+        return cluster;
+    }
+
+    public boolean isRoot() {
+        return true;
+    }
+
+    public int compareTo(Vertex o) {
+        return toString().compareTo(o.toString());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterNode.java	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2008, 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.Cluster;
+import com.sun.hotspot.igv.layout.Link;
+import com.sun.hotspot.igv.layout.Port;
+import com.sun.hotspot.igv.layout.Vertex;
+import java.awt.Dimension;
+import java.awt.Point;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ClusterNode implements Vertex {
+
+    private Cluster cluster;
+    private Port inputSlot;
+    private Port outputSlot;
+    private Set<Vertex> subNodes;
+    private Dimension size;
+    private Point position;
+    private Set<Link> subEdges;
+    private boolean dirty;
+    private boolean root;
+    private String name;
+    public static final int BORDER = 20;
+
+    public ClusterNode(Cluster cluster, String name) {
+        this.subNodes = new HashSet<Vertex>();
+        this.subEdges = new HashSet<Link>();
+        this.cluster = cluster;
+        position = new Point(0, 0);
+        this.name = name;
+    }
+
+    public void addSubNode(Vertex v) {
+        subNodes.add(v);
+    }
+
+    public void addSubEdge(Link l) {
+        subEdges.add(l);
+    }
+
+    public Set<Link> getSubEdges() {
+        return Collections.unmodifiableSet(subEdges);
+    }
+
+    public void updateSize() {
+
+
+        calculateSize();
+
+        final ClusterNode widget = this;
+        inputSlot = new Port() {
+
+            public Point getRelativePosition() {
+                return new Point(size.width / 2, 0);
+            }
+
+            public Vertex getVertex() {
+                return widget;
+            }
+        };
+
+        outputSlot = new Port() {
+
+            public Point getRelativePosition() {
+                return new Point(size.width / 2, 0);//size.height);
+            }
+
+            public Vertex getVertex() {
+                return widget;
+            }
+        };
+    }
+
+    private void calculateSize() {
+
+        if (subNodes.size() == 0) {
+            size = new Dimension(0, 0);
+        }
+
+        int minX = Integer.MAX_VALUE;
+        int maxX = Integer.MIN_VALUE;
+        int minY = Integer.MAX_VALUE;
+        int maxY = Integer.MIN_VALUE;
+
+
+        for (Vertex n : subNodes) {
+            Point p = n.getPosition();
+            minX = Math.min(minX, p.x);
+            minY = Math.min(minY, p.y);
+            maxX = Math.max(maxX, p.x + n.getSize().width);
+            maxY = Math.max(maxY, p.y + n.getSize().height);
+        }
+
+        for (Link l : subEdges) {
+            List<Point> points = l.getControlPoints();
+            for (Point p : points) {
+                if (p != null) {
+                    minX = Math.min(minX, p.x);
+                    maxX = Math.max(maxX, p.x);
+                    minY = Math.min(minY, p.y);
+                    maxY = Math.max(maxY, p.y);
+                }
+            }
+        }
+
+        size = new Dimension(maxX - minX, maxY - minY);
+
+        // Normalize coordinates
+        for (Vertex n : subNodes) {
+            n.setPosition(new Point(n.getPosition().x - minX, n.getPosition().y - minY));
+        }
+
+        for (Link l : subEdges) {
+            List<Point> points = new ArrayList<Point>(l.getControlPoints());
+            for (Point p : points) {
+                p.x -= minX;
+                p.y -= minY;
+            }
+            l.setControlPoints(points);
+
+        }
+
+        size.width += 2 * BORDER;
+        size.height += 2 * BORDER;
+    }
+
+    public Port getInputSlot() {
+        return inputSlot;
+
+    }
+
+    public Port getOutputSlot() {
+        return outputSlot;
+    }
+
+    public Dimension getSize() {
+        return size;
+    }
+
+    public Point getPosition() {
+        return position;
+    }
+
+    public void setPosition(Point pos) {
+
+        this.position = pos;
+        for (Vertex n : subNodes) {
+            Point cur = new Point(n.getPosition());
+            cur.translate(pos.x + BORDER, pos.y + BORDER);
+            n.setPosition(cur);
+        }
+
+        for (Link e : subEdges) {
+            List<Point> arr = e.getControlPoints();
+            ArrayList<Point> newArr = new ArrayList<Point>(arr.size());
+            for (Point p : arr) {
+                if (p != null) {
+                    Point p2 = new Point(p);
+                    p2.translate(pos.x + BORDER, pos.y + BORDER);
+                    newArr.add(p2);
+                } else {
+                    newArr.add(null);
+                }
+            }
+
+            e.setControlPoints(newArr);
+        }
+    }
+
+    public Cluster getCluster() {
+        return cluster;
+    }
+
+    public void setCluster(Cluster c) {
+        cluster = c;
+    }
+
+    public void setDirty(boolean b) {
+        dirty = b;
+    }
+
+    public void setRoot(boolean b) {
+        root = b;
+    }
+
+    public boolean isRoot() {
+        return root;
+    }
+
+    public int compareTo(Vertex o) {
+        return toString().compareTo(o.toString());
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+
+    public Set<? extends Vertex> getSubNodes() {
+        return subNodes;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterOutgoingConnection.java	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2008, 2015, 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.Link;
+import com.sun.hotspot.igv.layout.Port;
+import java.awt.Point;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ClusterOutgoingConnection implements Link {
+
+    private List<Point> intermediatePoints;
+    private ClusterOutputSlotNode outputSlotNode;
+    private Link connection;
+    private Port inputSlot;
+    private Port outputSlot;
+
+    public ClusterOutgoingConnection(ClusterOutputSlotNode outputSlotNode, Link c) {
+        this.outputSlotNode = outputSlotNode;
+        this.connection = c;
+        this.intermediatePoints = new ArrayList<Point>();
+
+        outputSlot = c.getFrom();
+        inputSlot = outputSlotNode.getInputSlot();
+    }
+
+    public Port getTo() {
+        return inputSlot;
+    }
+
+    public Port getFrom() {
+        return outputSlot;
+    }
+
+    public void setControlPoints(List<Point> p) {
+        this.intermediatePoints = p;
+    }
+
+    public List<Point> getControlPoints() {
+        return intermediatePoints;
+    }
+    
+    public boolean isVIP() {
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterOutputSlotNode.java	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2008, 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.Cluster;
+import com.sun.hotspot.igv.layout.Port;
+import com.sun.hotspot.igv.layout.Vertex;
+import java.awt.Dimension;
+import java.awt.Point;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ClusterOutputSlotNode implements Vertex {
+
+    private final int SIZE = 0;
+    private Point position;
+    private Port inputSlot;
+    private Port outputSlot;
+    private ClusterNode blockNode;
+    private boolean root;
+    private Cluster cluster;
+    private ClusterOutgoingConnection conn;
+    private String id;
+
+    public void setOutgoingConnection(ClusterOutgoingConnection c) {
+        this.conn = c;
+    }
+
+    public ClusterOutgoingConnection getOutgoingConnection() {
+        return conn;
+    }
+
+    @Override
+    public String toString() {
+        return id;
+    }
+
+    public ClusterOutputSlotNode(ClusterNode n, String id) {
+        this.blockNode = n;
+        this.id = id;
+
+        n.addSubNode(this);
+
+        final Vertex thisNode = this;
+        final ClusterNode thisBlockNode = blockNode;
+
+        inputSlot = new Port() {
+
+            public Point getRelativePosition() {
+                return new Point(0, 0);
+            }
+
+            public Vertex getVertex() {
+                return thisNode;
+            }
+
+            @Override
+            public String toString() {
+                return "InPort of " + thisNode.toString();
+            }
+        };
+
+        outputSlot = new Port() {
+
+            public Point getRelativePosition() {
+                Point p = new Point(thisNode.getPosition());
+                p.x += ClusterNode.BORDER;
+                p.y = 0;//thisBlockNode.getSize().height;
+                return p;
+            }
+
+            public Vertex getVertex() {
+                return thisBlockNode;
+            }
+
+            @Override
+            public String toString() {
+                return "OutPort of " + thisNode.toString();
+            }
+        };
+    }
+
+    public Dimension getSize() {
+        return new Dimension(SIZE, SIZE);
+    }
+
+    public void setPosition(Point p) {
+        this.position = p;
+    }
+
+    public Point getPosition() {
+        return position;
+    }
+
+    public Port getInputSlot() {
+        return inputSlot;
+    }
+
+    public Port getOutputSlot() {
+        return outputSlot;
+    }
+
+    public void setCluster(Cluster c) {
+        cluster = c;
+    }
+
+    public void setRoot(boolean b) {
+        root = b;
+    }
+
+    public Cluster getCluster() {
+        return cluster;
+    }
+
+    public boolean isRoot() {
+        return root;
+    }
+
+    public int compareTo(Vertex o) {
+        return toString().compareTo(o.toString());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalClusterLayoutManager.java	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2008, 2015, 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.Point;
+import java.awt.Rectangle;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.TreeSet;
+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.Port;
+import com.sun.hotspot.igv.layout.Vertex;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class HierarchicalClusterLayoutManager implements LayoutManager {
+
+    private HierarchicalLayoutManager.Combine combine;
+    private LayoutManager subManager = new HierarchicalLayoutManager(combine);
+    private LayoutManager manager = new HierarchicalLayoutManager(combine);
+    private static final boolean TRACE = false;
+
+    public HierarchicalClusterLayoutManager(HierarchicalLayoutManager.Combine combine) {
+        this.combine = combine;
+    }
+
+    public void doLayout(LayoutGraph graph) {
+        doLayout(graph, new HashSet<Vertex>(), new HashSet<Vertex>(), new HashSet<Link>());
+    }
+    
+    public void doLayout(LayoutGraph graph, Set<? extends Link> importantLinks) {
+        doLayout(graph);
+    }
+
+    public void setSubManager(LayoutManager manager) {
+        this.subManager = manager;
+    }
+
+    public void setManager(LayoutManager manager) {
+        this.manager = manager;
+    }
+
+    public void doLayout(LayoutGraph graph, Set<? extends Vertex> firstLayerHint, Set<? extends Vertex> lastLayerHint, Set<? extends Link> importantLinks) {
+
+        assert graph.verify();
+
+        HashMap<Cluster, List<Vertex>> lists = new HashMap<Cluster, List<Vertex>>();
+        HashMap<Cluster, List<Link>> listsConnection = new HashMap<Cluster, List<Link>>();
+        HashMap<Cluster, HashMap<Port, ClusterInputSlotNode>> clusterInputSlotHash = new HashMap<Cluster, HashMap<Port, ClusterInputSlotNode>>();
+        HashMap<Cluster, HashMap<Port, ClusterOutputSlotNode>> clusterOutputSlotHash = new HashMap<Cluster, HashMap<Port, ClusterOutputSlotNode>>();
+
+        HashMap<Cluster, ClusterNode> clusterNodes = new HashMap<Cluster, ClusterNode>();
+        HashMap<Cluster, Set<ClusterInputSlotNode>> clusterInputSlotSet = new HashMap<Cluster, Set<ClusterInputSlotNode>>();
+        HashMap<Cluster, Set<ClusterOutputSlotNode>> clusterOutputSlotSet = new HashMap<Cluster, Set<ClusterOutputSlotNode>>();
+        Set<Link> clusterEdges = new HashSet<Link>();
+        Set<Link> interClusterEdges = new HashSet<Link>();
+        HashMap<Link, ClusterOutgoingConnection> linkClusterOutgoingConnection = new HashMap<Link, ClusterOutgoingConnection>();
+        HashMap<Link, InterClusterConnection> linkInterClusterConnection = new HashMap<Link, InterClusterConnection>();
+        HashMap<Link, ClusterIngoingConnection> linkClusterIngoingConnection = new HashMap<Link, ClusterIngoingConnection>();
+        Set<ClusterNode> clusterNodeSet = new HashSet<ClusterNode>();
+
+        Set<Cluster> cluster = graph.getClusters();
+        int z = 0;
+        for (Cluster c : cluster) {
+            lists.put(c, new ArrayList<Vertex>());
+            listsConnection.put(c, new ArrayList<Link>());
+            clusterInputSlotHash.put(c, new HashMap<Port, ClusterInputSlotNode>());
+            clusterOutputSlotHash.put(c, new HashMap<Port, ClusterOutputSlotNode>());
+            clusterOutputSlotSet.put(c, new TreeSet<ClusterOutputSlotNode>());
+            clusterInputSlotSet.put(c, new TreeSet<ClusterInputSlotNode>());
+            ClusterNode cn = new ClusterNode(c, "" + z);
+            clusterNodes.put(c, cn);
+            clusterNodeSet.add(cn);
+            z++;
+        }
+
+        // Add cluster edges
+        for (Cluster c : cluster) {
+
+            ClusterNode start = clusterNodes.get(c);
+
+            for (Cluster succ : c.getSuccessors()) {
+                ClusterNode end = clusterNodes.get(succ);
+                if (end != null && start != end) {
+                    ClusterEdge e = new ClusterEdge(start, end);
+                    clusterEdges.add(e);
+                    interClusterEdges.add(e);
+                }
+            }
+        }
+
+        for (Vertex v : graph.getVertices()) {
+            Cluster c = v.getCluster();
+            assert c != null : "Cluster of vertex " + v + " is null!";
+            clusterNodes.get(c).addSubNode(v);
+        }
+
+        for (Link l : graph.getLinks()) {
+
+            Port fromPort = l.getFrom();
+            Port toPort = l.getTo();
+            Vertex fromVertex = fromPort.getVertex();
+            Vertex toVertex = toPort.getVertex();
+            Cluster fromCluster = fromVertex.getCluster();
+            Cluster toCluster = toVertex.getCluster();
+
+            Port samePort = null;
+            if (combine == HierarchicalLayoutManager.Combine.SAME_INPUTS) {
+                samePort = toPort;
+            } else if (combine == HierarchicalLayoutManager.Combine.SAME_OUTPUTS) {
+                samePort = fromPort;
+            }
+
+            assert listsConnection.containsKey(fromCluster);
+            assert listsConnection.containsKey(toCluster);
+
+            if (fromCluster == toCluster) {
+                listsConnection.get(fromCluster).add(l);
+                clusterNodes.get(fromCluster).addSubEdge(l);
+            } else {
+                ClusterInputSlotNode inputSlotNode = null;
+                ClusterOutputSlotNode outputSlotNode = null;
+
+                if (samePort != null) {
+                    outputSlotNode = clusterOutputSlotHash.get(fromCluster).get(samePort);
+                    inputSlotNode = clusterInputSlotHash.get(toCluster).get(samePort);
+                }
+
+                if (outputSlotNode == null) {
+                    outputSlotNode = new ClusterOutputSlotNode(clusterNodes.get(fromCluster), "Out " + fromCluster.toString() + " " + samePort.toString());
+                    clusterOutputSlotSet.get(fromCluster).add(outputSlotNode);
+                    ClusterOutgoingConnection conn = new ClusterOutgoingConnection(outputSlotNode, l);
+                    outputSlotNode.setOutgoingConnection(conn);
+                    clusterNodes.get(fromCluster).addSubEdge(conn);
+                    if (samePort != null) {
+                        clusterOutputSlotHash.get(fromCluster).put(samePort, outputSlotNode);
+                    }
+
+                    linkClusterOutgoingConnection.put(l, conn);
+                } else {
+                    linkClusterOutgoingConnection.put(l, outputSlotNode.getOutgoingConnection());
+                }
+
+                if (inputSlotNode == null) {
+                    inputSlotNode = new ClusterInputSlotNode(clusterNodes.get(toCluster), "In " + toCluster.toString() + " " + samePort.toString());
+                    clusterInputSlotSet.get(toCluster).add(inputSlotNode);
+                }
+
+                ClusterIngoingConnection conn = new ClusterIngoingConnection(inputSlotNode, l);
+                inputSlotNode.setIngoingConnection(conn);
+                clusterNodes.get(toCluster).addSubEdge(conn);
+                if (samePort != null) {
+                    clusterInputSlotHash.get(toCluster).put(samePort, inputSlotNode);
+                }
+
+                linkClusterIngoingConnection.put(l, conn);
+
+
+                InterClusterConnection interConn = new InterClusterConnection(outputSlotNode, inputSlotNode);
+                linkInterClusterConnection.put(l, interConn);
+                clusterEdges.add(interConn);
+            }
+        }
+
+        Timing t = null;
+
+        if (TRACE) {
+            new Timing("Child timing");
+            t.start();
+        }
+
+        for (Cluster c : cluster) {
+            ClusterNode n = clusterNodes.get(c);
+            subManager.doLayout(new LayoutGraph(n.getSubEdges(), n.getSubNodes()), new HashSet<Link>());
+            n.updateSize();
+        }
+
+        Set<Vertex> roots = new LayoutGraph(interClusterEdges).findRootVertices();
+        for (Vertex v : roots) {
+            assert v instanceof ClusterNode;
+            ((ClusterNode) v).setRoot(true);
+        }
+
+        manager.doLayout(new LayoutGraph(clusterEdges, clusterNodeSet), interClusterEdges);
+
+        for (Cluster c : cluster) {
+            ClusterNode n = clusterNodes.get(c);
+            c.setBounds(new Rectangle(n.getPosition(), n.getSize()));
+        }
+
+        // TODO: handle case where blocks are not fully connected
+
+        if (TRACE) {
+            t.stop();
+            t.print();
+        }
+
+        for (Link l : graph.getLinks()) {
+
+            if (linkInterClusterConnection.containsKey(l)) {
+                ClusterOutgoingConnection conn1 = linkClusterOutgoingConnection.get(l);
+                InterClusterConnection conn2 = linkInterClusterConnection.get(l);
+                ClusterIngoingConnection conn3 = linkClusterIngoingConnection.get(l);
+
+                assert conn1 != null;
+                assert conn2 != null;
+                assert conn3 != null;
+
+                List<Point> points = new ArrayList<Point>();
+
+                points.addAll(conn1.getControlPoints());
+                points.addAll(conn2.getControlPoints());
+                points.addAll(conn3.getControlPoints());
+
+                l.setControlPoints(points);
+            }
+        }
+    }
+
+    public void doRouting(LayoutGraph graph) {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/InterClusterConnection.java	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2008, 2015, 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.Link;
+import com.sun.hotspot.igv.layout.Port;
+import java.awt.Point;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class InterClusterConnection implements Link {
+
+    private Port inputSlot;
+    private Port outputSlot;
+    private List<Point> intermediatePoints;
+    private ClusterInputSlotNode inputSlotNode;
+    private ClusterOutputSlotNode outputSlotNode;
+
+    public InterClusterConnection(ClusterOutputSlotNode outputSlotNode, ClusterInputSlotNode inputSlotNode) {
+        this.outputSlotNode = outputSlotNode;
+        this.inputSlotNode = inputSlotNode;
+        this.inputSlot = inputSlotNode.getInputSlot();
+        this.outputSlot = outputSlotNode.getOutputSlot();
+        intermediatePoints = new ArrayList<Point>();
+    }
+
+    public ClusterOutputSlotNode getOutputSlotNode() {
+        return outputSlotNode;
+    }
+
+    public Port getTo() {
+        return inputSlot;
+    }
+
+    public Port getFrom() {
+        return outputSlot;
+    }
+
+    public void setControlPoints(List<Point> p) {
+        this.intermediatePoints = p;
+    }
+
+    public List<Point> getControlPoints() {
+        return intermediatePoints;
+    }
+
+    @Override
+    public String toString() {
+        return "InterClusterConnection[from=" + getFrom() + ", to=" + getTo() + "]";
+    }
+    
+    public boolean isVIP() {
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Cluster.java	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2008, 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.layout;
+
+import java.awt.Rectangle;
+import java.util.Set;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public interface Cluster extends Comparable<Cluster> {
+
+    public Cluster getOuter();
+
+    public void setBounds(Rectangle r);
+
+    public Set<? extends Cluster> getSuccessors();
+}
--- a/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutGraph.java	Tue Apr 28 12:58:40 2015 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutGraph.java	Wed Apr 29 08:31:28 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, 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
@@ -183,4 +183,16 @@
     public Set<Vertex> findRootVertices() {
         return findRootVertices(new HashSet<Vertex>());
     }
+    
+    public SortedSet<Cluster> getClusters() {
+
+        SortedSet<Cluster> clusters = new TreeSet<Cluster>();
+        for (Vertex v : getVertices()) {
+            if (v.getCluster() != null) {
+                clusters.add(v.getCluster());
+            }
+        }
+
+        return clusters;
+    }
 }
--- a/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Vertex.java	Tue Apr 28 12:58:40 2015 -0700
+++ b/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Vertex.java	Wed Apr 29 08:31:28 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, 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
@@ -39,4 +39,6 @@
     public void setPosition(Point p);
 
     public boolean isRoot();
+    
+    public Cluster getCluster();
 }
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java	Tue Apr 28 12:58:40 2015 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java	Wed Apr 29 08:31:28 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, 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,9 +25,13 @@
 
 import com.sun.hotspot.igv.data.ChangedListener;
 import com.sun.hotspot.igv.data.ControllableChangedListener;
+import com.sun.hotspot.igv.data.InputBlock;
+import com.sun.hotspot.igv.data.InputNode;
 import com.sun.hotspot.igv.data.Pair;
 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.HierarchicalLayoutManager;
 import com.sun.hotspot.igv.layout.LayoutGraph;
 import com.sun.hotspot.igv.selectioncoordinator.SelectionCoordinator;
@@ -111,6 +115,7 @@
             return DiagramScene.this.createPopupMenu();
         }
     };
+
     private RectangularSelectDecorator rectangularSelectDecorator = new RectangularSelectDecorator() {
 
         @Override
@@ -462,8 +467,14 @@
 
         name += " (";
 
+        if (f.getCluster() != null) {
+            name += "B" + f.getCluster().toString();
+        }
         final boolean hidden = !this.getWidget(f, FigureWidget.class).isVisible();
         if (hidden) {
+            if (f.getCluster() != null) {
+                name += ", ";
+            }
             name += "hidden";
         }
         name += ")";
@@ -503,6 +514,14 @@
         }
 
         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();
+        }
 
         for (Figure f : d.getFigures()) {
             FigureWidget w = new FigureWidget(f, hoverAction, selectAction, this, mainLayer);
@@ -530,6 +549,15 @@
             }
         }
         
+        if (getModel().getShowBlocks()) {
+            for (InputBlock bn : d.getGraph().getBlocks()) {
+                BlockWidget w = new BlockWidget(this, d, bn);
+                w.setVisible(false);
+                this.addObject(bn, w);
+                blockLayer.addChild(w);
+            }
+        }
+        
         rebuilding = false;
         this.smallUpdate(true);
     }
@@ -577,9 +605,20 @@
             }
         }
 
-        HierarchicalLayoutManager manager = new HierarchicalLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS);
-        manager.setMaxLayerLength(10);
-        manager.doLayout(new LayoutGraph(edges, figures));
+        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));
+        }
+        
         relayoutWithoutLayout(oldVisibleWidgets);
     }
     private Set<Pair<Point, Point>> lineCache = new HashSet<>();
@@ -613,6 +652,17 @@
                 }
             }
         }
+        
+        if (getModel().getShowBlocks()) {
+            for (Block b : diagram.getBlocks()) {
+                BlockWidget w = getWidget(b.getInputBlock());
+                if (w != null && w.isVisible()) {
+                    Rectangle r = b.getBounds();
+                    maxX = Math.max(maxX, r.x + r.width);
+                    maxY = Math.max(maxY, r.y + r.height);
+                }
+            }
+        }
 
         bottomRight.setPreferredLocation(new Point(maxX + BORDER_SIZE, maxY + BORDER_SIZE));
         int offx = 0;
@@ -669,6 +719,23 @@
                 }
             }
         }
+        
+        if (getModel().getShowBlocks()) {
+            for (Block b : diagram.getBlocks()) {
+                BlockWidget w = getWidget(b.getInputBlock());
+                if (w != null && w.isVisible()) {
+                    Point location = new Point(b.getBounds().x + offx2, b.getBounds().y + offy2);
+                    Rectangle r = new Rectangle(location.x, location.y, b.getBounds().width, b.getBounds().height);
+                    
+                    if ((visibleFigureCount <= ANIMATION_LIMIT && oldVisibleWidgets != null && oldVisibleWidgets.contains(w))) {
+                        animator.animatePreferredBounds(w, r);
+                    } else {
+                        w.setPreferredBounds(r);
+                        animator.animatePreferredBounds(w, r);
+                    }
+                }
+            }
+        }
 
         this.validate();
     }
@@ -956,6 +1023,7 @@
         Diagram diagram = getModel().getDiagramToView();
         assert diagram != null;
 
+        Set<InputBlock> visibleBlocks = new HashSet<InputBlock>();
         Set<Widget> oldVisibleWidgets = new HashSet<>();
 
         for (Figure f : diagram.getFigures()) {
@@ -964,6 +1032,15 @@
                 oldVisibleWidgets.add(w);
             }
         }
+        
+        if (getModel().getShowBlocks()) {
+            for (InputBlock b : diagram.getGraph().getBlocks()) {
+                BlockWidget w = getWidget(b);
+                if (w.isVisible()) {
+                    oldVisibleWidgets.add(w);
+                }
+            }
+        }
 
         for (Figure f : diagram.getFigures()) {
             boolean hiddenAfter = doesIntersect(f.getSource().getSourceNodesAsSet(), newHiddenNodes);
@@ -973,6 +1050,9 @@
             if (!hiddenAfter) {
                 // Figure is shown
                 w.setVisible(true);
+                for (InputNode n : f.getSource().getSourceNodes()) {
+                    visibleBlocks.add(diagram.getGraph().getBlock(n));
+                }
             } else {
                 // Figure is hidden
                 w.setVisible(false);
@@ -998,6 +1078,9 @@
 
                     if (b) {
                         w.setBoundary(true);
+                        for (InputNode n : f.getSource().getSourceNodes()) {
+                            visibleBlocks.add(diagram.getGraph().getBlock(n));
+                        }
                         boundaries.add(w);
                     }
                 }
@@ -1009,6 +1092,22 @@
                 }
             }
         }
+        
+        if (getModel().getShowBlocks()) {
+            for (InputBlock b : diagram.getGraph().getBlocks()) {
+
+                boolean visibleAfter = visibleBlocks.contains(b);
+
+                BlockWidget w = getWidget(b);
+                if (visibleAfter) {
+                    // Block must be shown
+                    w.setVisible(true);
+                } else {
+                    // Block must be hidden
+                    w.setVisible(false);
+                }
+            }
+        }
 
         if (doRelayout) {
             relayout(oldVisibleWidgets);
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java	Tue Apr 28 12:58:40 2015 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java	Wed Apr 29 08:31:28 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, 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
@@ -56,6 +56,7 @@
     private ChangedEvent<DiagramViewModel> viewChangedEvent;
     private ChangedEvent<DiagramViewModel> hiddenNodesChangedEvent;
     private ChangedEvent<DiagramViewModel> viewPropertiesChangedEvent;
+    private boolean showBlocks;
     private boolean showNodeHull;
     private boolean hideDuplicates;
     private ChangedListener<FilterChain> filterChainChangedListener = new ChangedListener<FilterChain>() {
@@ -101,6 +102,8 @@
         this.onScreenNodes = newModel.onScreenNodes;
         viewChanged |= (selectedNodes != newModel.selectedNodes);
         this.selectedNodes = newModel.selectedNodes;
+        viewPropertiesChanged |= (showBlocks != newModel.showBlocks);
+        this.showBlocks = newModel.showBlocks;
         viewPropertiesChanged |= (showNodeHull != newModel.showNodeHull);
         this.showNodeHull = newModel.showNodeHull;
 
@@ -118,6 +121,15 @@
             viewChangedEvent.fire();
         }
     }
+    
+    public boolean getShowBlocks() {
+        return showBlocks;
+    }
+
+    public void setShowBlocks(boolean b) {
+        showBlocks = b;
+        viewPropertiesChangedEvent.fire();
+    }
 
     public boolean getShowNodeHull() {
         return showNodeHull;
@@ -152,6 +164,7 @@
     public DiagramViewModel(Group g, FilterChain filterChain, FilterChain sequenceFilterChain) {
         super(Arrays.asList("default"));
 
+        this.showBlocks = false;
         this.showNodeHull = true;
         this.group = g;
         filterGraphs();
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java	Tue Apr 28 12:58:40 2015 -0700
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java	Wed Apr 29 08:31:28 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, 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
@@ -77,6 +77,7 @@
     private DiagramViewer scene;
     private InstanceContent content;
     private InstanceContent graphContent;
+    private EnableBlockLayoutAction blockLayoutAction;
     private OverviewAction overviewAction;
     private HideDuplicatesAction hideDuplicatesAction;
     private PredSuccAction predSuccAction;
@@ -234,6 +235,12 @@
         toolBar.addSeparator();
         toolBar.add(ShowAllAction.get(ZoomInAction.class));
         toolBar.add(ShowAllAction.get(ZoomOutAction.class));
+        
+        blockLayoutAction = new EnableBlockLayoutAction();
+        JToggleButton button = new JToggleButton(blockLayoutAction);
+        button.setSelected(false);
+        toolBar.add(button);
+        blockLayoutAction.addPropertyChangeListener(this);
 
         overviewAction = new OverviewAction();
         overviewButton = new JToggleButton(overviewAction);
@@ -242,7 +249,7 @@
         overviewAction.addPropertyChangeListener(this);
 
         predSuccAction = new PredSuccAction();
-        JToggleButton button = new JToggleButton(predSuccAction);
+        button = new JToggleButton(predSuccAction);
         button.setSelected(true);
         toolBar.add(button);
         predSuccAction.addPropertyChangeListener(this);
@@ -500,6 +507,9 @@
             } else {
                 showScene();
             }
+        } else if (evt.getSource() == this.blockLayoutAction) {
+            boolean b = (Boolean) blockLayoutAction.getValue(EnableBlockLayoutAction.STATE);
+            this.getModel().setShowBlocks(b);
         } else if (evt.getSource() == this.hideDuplicatesAction) {
             boolean b = (Boolean) hideDuplicatesAction.getValue(HideDuplicatesAction.STATE);
             this.getModel().setHideDuplicates(b);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/EnableBlockLayoutAction.java	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2008, 2015, 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;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+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");
+    }
+
+    public void actionPerformed(ActionEvent ev) {
+        this.state = !state;
+        this.putValue(STATE, state);
+    }
+
+    protected String iconResource() {
+        return "com/sun/hotspot/igv/view/images/blocks.gif";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/BlockWidget.java	Wed Apr 29 08:31:28 2015 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2008, 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.widgets;
+
+import com.sun.hotspot.igv.data.InputBlock;
+import com.sun.hotspot.igv.graph.Diagram;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.Stroke;
+import java.awt.geom.Rectangle2D;
+import org.netbeans.api.visual.widget.Scene;
+import org.netbeans.api.visual.widget.Widget;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+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 InputBlock blockNode;
+    private Diagram diagram;
+
+    public BlockWidget(Scene scene, Diagram d, InputBlock blockNode) {
+        super(scene);
+        this.blockNode = blockNode;
+        this.diagram = d;
+        this.setBackground(BACKGROUND_COLOR);
+        this.setOpaque(true);
+        this.setCheckClipping(true);
+    }
+
+    @Override
+    protected void paintWidget() {
+        super.paintWidget();
+        Graphics2D g = this.getGraphics();
+        Stroke old = g.getStroke();
+        g.setColor(Color.BLUE);
+        Rectangle r = new Rectangle(this.getPreferredBounds());
+        r.width--;
+        r.height--;
+        if (this.getBounds().width > 0 && this.getBounds().height > 0) {
+            g.setStroke(new BasicStroke(2));
+            g.drawRect(r.x, r.y, r.width, r.height);
+        }
+
+        Color titleColor = Color.BLACK;
+        g.setColor(titleColor);
+        g.setFont(titleFont);
+
+        String s = "B" + blockNode.getName();
+        Rectangle2D r1 = g.getFontMetrics().getStringBounds(s, g);
+        g.drawString(s, r.x + 5, r.y + (int) r1.getHeight());
+        g.setStroke(old);
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/nbproject/project.properties	Tue Apr 28 12:58:40 2015 -0700
+++ b/src/share/tools/IdealGraphVisualizer/nbproject/project.properties	Wed Apr 29 08:31:28 2015 +0200
@@ -14,6 +14,7 @@
     ${project.com.sun.hotspot.igv.filter}:\
     ${project.com.sun.hotspot.igv.hierarchicallayout}:\
     ${project.com.sun.hotspot.igv.layout}:\
+    ${project.com.sun.hotspot.igv.controlflow}:\
     ${project.com.sun.hotspot.igv.data}:\
     ${project.com.sun.hotspot.igv.view}:\
     ${project.com.sun.hotspot.igv.bytecodes}:\
@@ -28,6 +29,7 @@
     ${project.com.sun.hotspot.igv.graal}
 project.com.sun.hotspot.connection=NetworkConnection
 project.com.sun.hotspot.igv.bytecodes=Bytecodes
+project.com.sun.hotspot.igv.controlflow=ControlFlow
 project.com.sun.hotspot.igv.coordinator=Coordinator
 project.com.sun.hotspot.igv.data=Data
 project.com.sun.hotspot.igv.difference=Difference