Merge
authorhseigel
Fri, 08 May 2015 13:25:11 -0400
changeset 30607 035f5801a92e
parent 30606 9dae6b41c617 (current diff)
parent 30596 0322b394e7fd (diff)
child 30614 e45861098f5a
child 30618 2f98610229a5
Merge
hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMap.java
hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java
hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/bytecode.gif
hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/link.gif
hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/method.gif
hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/META-INF/services/com.sun.hotspot.igv.data.services.GroupOrganizer
hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/GraphCountGroupOrganizer.java
hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/StandardGroupOrganizer.java
hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/StructuredViewAction.java
hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/diff.gif
hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/folder.gif
hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/graph.gif
hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/import.gif
hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/remove.gif
hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/removeall.gif
hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/save.gif
hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/structure.gif
hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/GroupOrganizer.java
hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/GroupReceiver.java
hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/META-INF/services/com.sun.hotspot.igv.filter.ScriptEngineAbstraction
hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/JavaSE6ScriptEngine.java
hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/NullScriptEngine.java
hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/ScriptEngineAbstraction.java
hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/add.gif
hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/delete.gif
hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/down.gif
hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/minus.gif
hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/plus.gif
hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/up.gif
hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Source.java
hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/OldHierarchicalLayoutManager.java
hotspot/src/share/tools/IdealGraphVisualizer/NetworkConnection/src/META-INF/services/com.sun.hotspot.igv.data.services.GroupReceiver
hotspot/src/share/tools/IdealGraphVisualizer/README
hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/build.xml
hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/manifest.mf
hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/build-impl.xml
hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/genfiles.properties
hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/project.properties
hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/project.xml
hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/suite.properties
hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/src/META-INF/services/com.sun.hotspot.igv.filter.ScriptEngineAbstraction
hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/src/com/sun/hotspot/igv/rhino/Bundle.properties
hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/src/com/sun/hotspot/igv/rhino/RhinoScriptEngine.java
hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/src/com/sun/hotspot/igv/rhino/layer.xml
hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/META-INF/services/com.sun.hotspot.igv.data.services.GroupOrganizer
hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/JavaGroupOrganizer.java
hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/combine.filter
hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/extendedColor.filter
hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/linestyle.filter
hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/removeMemory.filter
hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/removeRootInputs.filter
hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/removeSafepointInputs.filter
hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/removeSelfLoops.filter
hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/split.filter
hotspot/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/settings.gif
hotspot/src/share/tools/IdealGraphVisualizer/View/src/META-INF/services/com.sun.hotspot.igv.data.services.InputGraphProvider
hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/ConnectionAnchor.java
hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/ExtendedPanAction.java
hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/FindPanel.java
hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/PreferenceConstants.java
hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/SlotLayout.java
hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/NodeFindAction.java
hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/export.gif
hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/overview.gif
hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/search.gif
hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/zoomin.gif
hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/zoomout.gif
hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/DiagramConnectionWidget.java
hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/MultiConnectionWidget.java
hotspot/src/share/vm/code/codeCache.cpp
hotspot/src/share/vm/runtime/thread.cpp
hotspot/test/TEST.groups
hotspot/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java
hotspot/test/compiler/rtm/cli/RTMGenericCommandLineOptionTest.java
hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java
hotspot/test/gc/TestSoftReferencesBehaviorOnOOME.java
hotspot/test/gc/ergonomics/TestDynamicNumberOfGCThreads.java
hotspot/test/gc/g1/TestShrinkAuxiliaryData.java
hotspot/test/gc/g1/TestShrinkAuxiliaryData05.java
hotspot/test/gc/g1/TestShrinkAuxiliaryData10.java
hotspot/test/gc/g1/TestShrinkAuxiliaryData15.java
hotspot/test/gc/g1/TestShrinkAuxiliaryData20.java
hotspot/test/gc/g1/TestShrinkAuxiliaryData25.java
hotspot/test/gc/g1/TestShrinkAuxiliaryData30.java
--- a/hotspot/.hgignore	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/.hgignore	Fri May 08 13:25:11 2015 -0400
@@ -6,5 +6,7 @@
 ^src/share/tools/IdealGraphVisualizer/[a-zA-Z0-9]*/build/
 ^src/share/tools/IdealGraphVisualizer/build/
 ^src/share/tools/IdealGraphVisualizer/dist/
+^src/share/tools/IdealGraphVisualizer/nbplatform/
+.igv.log
 ^.hgtip
 .DS_Store
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HSDB.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HSDB.java	Fri May 08 13:25:11 2015 -0400
@@ -27,9 +27,7 @@
 import java.io.*;
 import java.awt.*;
 import java.awt.event.*;
-import java.math.*;
 import javax.swing.*;
-import javax.swing.tree.*;
 import java.util.*;
 
 import sun.jvm.hotspot.code.*;
@@ -928,7 +926,7 @@
             boolean shouldSkipOopMaps = false;
             if (curVFrame.isCompiledFrame()) {
               CodeBlob cb = VM.getVM().getCodeCache().findBlob(curFrame.getPC());
-              OopMapSet maps = cb.getOopMaps();
+              ImmutableOopMapSet maps = cb.getOopMaps();
               if ((maps == null) || (maps.getSize() == 0)) {
                 shouldSkipOopMaps = true;
               }
@@ -977,7 +975,7 @@
             } while (nextVFrame != null && nextFrame.equals(curFrame));
 
             if (shouldSkipOopMaps) {
-              anno = anno + "\nNOTE: null or empty OopMapSet found for this CodeBlob";
+              anno = anno + "\nNOTE: null or empty ImmutableOopMapSet found for this CodeBlob";
             }
 
             if (curFrame.getFP() != null) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java	Fri May 08 13:25:11 2015 -0400
@@ -171,17 +171,17 @@
   public boolean isLockedByVM()         { return false; }
 
   /** OopMap for frame; can return null if none available */
-  public OopMapSet getOopMaps() {
+  public ImmutableOopMapSet getOopMaps() {
     Address oopMapsAddr = oopMapsField.getValue(addr);
     if (oopMapsAddr == null) {
       return null;
     }
-    return new OopMapSet(oopMapsAddr);
+    return new ImmutableOopMapSet(oopMapsAddr);
   }
   // FIXME: not yet implementable
-  //  void set_oop_maps(OopMapSet* p);
+  //  void set_oop_maps(ImmutableOopMapSet* p);
 
-  public OopMap getOopMapForReturnAddress(Address returnAddress, boolean debugging) {
+  public ImmutableOopMap getOopMapForReturnAddress(Address returnAddress, boolean debugging) {
     Address pc = returnAddress;
     if (Assert.ASSERTS_ENABLED) {
       Assert.that(getOopMaps() != null, "nope");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/ImmutableOopMap.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2000, 2004, 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 sun.jvm.hotspot.compiler;
+
+import java.util.*;
+
+import sun.jvm.hotspot.code.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.types.*;
+
+public class ImmutableOopMap extends VMObject {
+  private static CIntegerField countField;
+  private static long classSize;
+
+  static {
+    VM.registerVMInitializedObserver(new Observer() {
+        public void update(Observable o, Object data) {
+          initialize(VM.getVM().getTypeDataBase());
+        }
+      });
+  }
+
+  private static void initialize(TypeDataBase db) {
+    Type type = db.lookupType("ImmutableOopMap");
+    countField = type.getCIntegerField("_count");
+    classSize = type.getSize();
+  }
+
+  public ImmutableOopMap(Address addr) {
+    super(addr);
+  }
+
+  //--------------------------------------------------------------------------------
+  // Internals only below this point
+  //
+
+  long getCount() {
+    return countField.getValue(addr);
+  }
+
+  public Address getData() {
+    return addr.addOffsetTo(classSize);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/ImmutableOopMapPair.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 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 sun.jvm.hotspot.compiler;
+
+import sun.jvm.hotspot.debugger.Address;
+import sun.jvm.hotspot.runtime.VM;
+import sun.jvm.hotspot.types.CIntegerField;
+import sun.jvm.hotspot.types.Type;
+import sun.jvm.hotspot.types.TypeDataBase;
+
+import java.util.Observable;
+import java.util.Observer;
+
+public class ImmutableOopMapPair {
+  private static CIntegerField pcField;
+  private static CIntegerField offsetField;
+  private static long classSize;
+
+  static {
+    VM.registerVMInitializedObserver(new Observer() {
+      public void update(Observable o, Object data) {
+        initialize(VM.getVM().getTypeDataBase());
+      }
+    });
+  }
+
+  private final Address address;
+
+  public ImmutableOopMapPair(Address address) {
+    this.address = address;
+  }
+
+  public static long classSize() {
+    return classSize;
+  }
+
+  public int getPC() {
+    return (int) pcField.getValue(address);
+  }
+
+  public int getOffset() {
+    return (int) offsetField.getValue(address);
+  }
+
+  private static void initialize(TypeDataBase db) {
+    Type type = db.lookupType("ImmutableOopMapSet");
+
+    pcField = type.getCIntegerField("_pc_offset");
+    offsetField = type.getCIntegerField("_oopmap_offset");
+    classSize = type.getSize();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/ImmutableOopMapSet.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2000, 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 sun.jvm.hotspot.compiler;
+
+import java.util.*;
+
+import sun.jvm.hotspot.code.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.utilities.*;
+
+public class ImmutableOopMapSet extends VMObject {
+  private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.compiler.ImmutableOopMapSet.DEBUG") != null;
+
+  private static CIntegerField countField;
+  private static CIntegerField sizeField;
+  private static AddressField omDataField;
+  private static int REG_COUNT;
+  private static int SAVED_ON_ENTRY_REG_COUNT;
+  private static int C_SAVED_ON_ENTRY_REG_COUNT;
+  private static long classSize;
+
+  private static class MyVisitor implements OopMapVisitor {
+    private AddressVisitor addressVisitor;
+
+    public MyVisitor(AddressVisitor oopVisitor) {
+      setAddressVisitor(oopVisitor);
+    }
+
+    public void setAddressVisitor(AddressVisitor addressVisitor) {
+      this.addressVisitor = addressVisitor;
+    }
+
+    public void visitOopLocation(Address oopAddr) {
+      addressVisitor.visitAddress(oopAddr);
+    }
+
+    public void visitDerivedOopLocation(Address baseOopAddr, Address derivedOopAddr) {
+      if (VM.getVM().isClientCompiler()) {
+        Assert.that(false, "should not reach here");
+      } else if (VM.getVM().isServerCompiler() &&
+          VM.getVM().useDerivedPointerTable()) {
+        Assert.that(false, "FIXME: add derived pointer table");
+      }
+    }
+
+    public void visitValueLocation(Address valueAddr) {
+    }
+
+    public void visitNarrowOopLocation(Address narrowOopAddr) {
+      addressVisitor.visitCompOopAddress(narrowOopAddr);
+    }
+  }
+
+  static {
+    VM.registerVMInitializedObserver(new Observer() {
+      public void update(Observable o, Object data) {
+        initialize(VM.getVM().getTypeDataBase());
+      }
+    });
+  }
+
+  private static void initialize(TypeDataBase db) {
+    Type type = db.lookupType("ImmutableOopMapSet");
+
+    countField = type.getCIntegerField("_count");
+    sizeField = type.getCIntegerField("_size");
+    classSize = type.getSize();
+
+    if (!VM.getVM().isCore()) {
+      REG_COUNT = db.lookupIntConstant("REG_COUNT").intValue();
+      if (VM.getVM().isServerCompiler()) {
+        SAVED_ON_ENTRY_REG_COUNT = (int) db.lookupIntConstant("SAVED_ON_ENTRY_REG_COUNT").intValue();
+        C_SAVED_ON_ENTRY_REG_COUNT = (int) db.lookupIntConstant("C_SAVED_ON_ENTRY_REG_COUNT").intValue();
+      }
+    }
+  }
+
+  public ImmutableOopMapSet(Address addr) {
+    super(addr);
+  }
+
+  /**
+   * Returns the number of OopMaps in this ImmutableOopMapSet
+   */
+  public long getSize() {
+    return countField.getValue(addr);
+  }
+
+  public int getCount() { return (int) countField.getValue(addr); }
+
+  private Address dataStart() {
+    return (addr.addOffsetTo(ImmutableOopMapSet.classSize * getCount()));
+  }
+
+  public ImmutableOopMapPair pairAt(int index) {
+    Assert.that((index >= 0) && (index < getCount()), "bad index");
+    return new ImmutableOopMapPair(addr.addOffsetTo(index * ImmutableOopMapPair.classSize()));
+  }
+
+  /**
+   * returns the OopMap at a given index
+   */
+  public ImmutableOopMap getMapAt(int index) {
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that((index >= 0) && (index <= getSize()), "bad index");
+    }
+
+    ImmutableOopMapPair immutableOopMapPair = pairAt(index);
+    return getMap(immutableOopMapPair);
+  }
+
+  public ImmutableOopMap findMapAtOffset(long pcOffset, boolean debugging) {
+    int i;
+    int len = (int) getSize();
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(len > 0, "must have pointer maps");
+    }
+
+    // Scan through oopmaps. Stop when current offset is either equal or greater
+    // than the one we are looking for.
+    for (i = 0; i < len; i++) {
+      if (pairAt(i).getPC() >= pcOffset) {
+        break;
+      }
+    }
+
+    if (!debugging) {
+      if (Assert.ASSERTS_ENABLED) {
+        Assert.that(i < len, "oopmap not found for pcOffset = " + pcOffset + "; len = " + len);
+        Assert.that(pairAt(i).getPC() == pcOffset, "oopmap not found");
+      }
+    } else {
+      if (i == len) {
+        if (DEBUG) {
+          System.out.println("can't find oopmap at " + pcOffset);
+          System.out.print("Oopmap offsets are [ ");
+          for (i = 0; i < len; i++) {
+            System.out.print(pairAt(i).getPC());
+          }
+          System.out.println("]");
+        }
+        i = len - 1;
+        return getMapAt(i);
+      }
+    }
+
+    ImmutableOopMap m = getMapAt(i);
+    return m;
+  }
+
+  /**
+   * Visitation -- iterates through the frame for a compiled method.
+   * This is a very generic mechanism that requires the Address to be
+   * dereferenced by the callee. Other, more specialized, visitation
+   * mechanisms are given below.
+   */
+  public static void oopsDo(Frame fr, CodeBlob cb, RegisterMap regMap, AddressVisitor oopVisitor, boolean debugging) {
+    allDo(fr, cb, regMap, new MyVisitor(oopVisitor), debugging);
+  }
+
+  /**
+   * Note that there are 4 required AddressVisitors: one for oops,
+   * one for derived oops, one for values, and one for dead values
+   */
+  public static void allDo(Frame fr, CodeBlob cb, RegisterMap regMap, OopMapVisitor visitor, boolean debugging) {
+    if (Assert.ASSERTS_ENABLED) {
+      CodeBlob tmpCB = VM.getVM().getCodeCache().findBlob(fr.getPC());
+      Assert.that(tmpCB != null && cb.equals(tmpCB), "wrong codeblob passed in");
+    }
+
+    ImmutableOopMapSet maps = cb.getOopMaps();
+    ImmutableOopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging);
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(map != null, "no ptr map found");
+    }
+
+    // handle derived pointers first (otherwise base pointer may be
+    // changed before derived pointer offset has been collected)
+    OopMapValue omv;
+    {
+      for (OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.DERIVED_OOP_VALUE); !oms.isDone(); oms.next()) {
+        if (VM.getVM().isClientCompiler()) {
+          Assert.that(false, "should not reach here");
+        }
+        omv = oms.getCurrent();
+        Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap);
+        if (loc != null) {
+          Address baseLoc = fr.oopMapRegToLocation(omv.getContentReg(), regMap);
+          Address derivedLoc = loc;
+          visitor.visitDerivedOopLocation(baseLoc, derivedLoc);
+        }
+      }
+    }
+
+    // We want narow oop, value and oop oop_types
+    OopMapValue.OopTypes[] values = new OopMapValue.OopTypes[]{
+        OopMapValue.OopTypes.OOP_VALUE, OopMapValue.OopTypes.VALUE_VALUE, OopMapValue.OopTypes.NARROWOOP_VALUE
+    };
+
+    {
+      for (OopMapStream oms = new OopMapStream(map, values); !oms.isDone(); oms.next()) {
+        omv = oms.getCurrent();
+        Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap);
+        if (loc != null) {
+          if (omv.getType() == OopMapValue.OopTypes.OOP_VALUE) {
+            // This assert commented out because this will be useful
+            // to detect in the debugging system
+            // assert(Universe::is_heap_or_null(*loc), "found non oop pointer");
+            visitor.visitOopLocation(loc);
+          } else if (omv.getType() == OopMapValue.OopTypes.VALUE_VALUE) {
+            visitor.visitValueLocation(loc);
+          } else if (omv.getType() == OopMapValue.OopTypes.NARROWOOP_VALUE) {
+            visitor.visitNarrowOopLocation(loc);
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Update callee-saved register info for the following frame.
+   * Should only be called in non-core builds.
+   */
+  public static void updateRegisterMap(Frame fr, CodeBlob cb, RegisterMap regMap, boolean debugging) {
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(!VM.getVM().isCore(), "non-core builds only");
+    }
+
+    if (!VM.getVM().isDebugging()) {
+      if (Assert.ASSERTS_ENABLED) {
+        ImmutableOopMapSet maps = cb.getOopMaps();
+        Assert.that((maps != null) && (maps.getSize() > 0), "found null or empty ImmutableOopMapSet for CodeBlob");
+      }
+    } else {
+      // Hack for some topmost frames that have been found with empty
+      // OopMapSets. (Actually have not seen the null case, but don't
+      // want to take any chances.) See HSDB.showThreadStackMemory().
+      ImmutableOopMapSet maps = cb.getOopMaps();
+      if ((maps == null) || (maps.getSize() == 0)) {
+        return;
+      }
+    }
+
+    // Check if caller must update oop argument
+    regMap.setIncludeArgumentOops(cb.callerMustGCArguments());
+
+    int nofCallee = 0;
+    Address[] locs = new Address[2 * REG_COUNT + 1];
+    VMReg[] regs = new VMReg[2 * REG_COUNT + 1];
+    // ("+1" because REG_COUNT might be zero)
+
+    // Scan through oopmap and find location of all callee-saved registers
+    // (we do not do update in place, since info could be overwritten)
+    ImmutableOopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging);
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(map != null, "no ptr map found");
+    }
+
+    OopMapValue omv = null;
+    for (OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE); !oms.isDone(); oms.next()) {
+      omv = oms.getCurrent();
+      if (Assert.ASSERTS_ENABLED) {
+        Assert.that(nofCallee < 2 * REG_COUNT, "overflow");
+      }
+      regs[nofCallee] = omv.getContentReg();
+      locs[nofCallee] = fr.oopMapRegToLocation(omv.getReg(), regMap);
+      nofCallee++;
+    }
+
+    // Check that runtime stubs save all callee-saved registers
+    // After adapter frames were deleted C2 doesn't use callee save registers at present
+    if (Assert.ASSERTS_ENABLED) {
+      if (VM.getVM().isServerCompiler()) {
+        Assert.that(!cb.isRuntimeStub() ||
+                (nofCallee >= SAVED_ON_ENTRY_REG_COUNT || nofCallee >= C_SAVED_ON_ENTRY_REG_COUNT),
+            "must save all");
+      }
+    }
+
+    // Copy found callee-saved register to reg_map
+    for (int i = 0; i < nofCallee; i++) {
+      regMap.setLocation(regs[i], locs[i]);
+    }
+  }
+
+  public ImmutableOopMapPair getPairAt(int index) {
+    return pairAt(index);
+  }
+
+  public ImmutableOopMap getMap(ImmutableOopMapPair pair) {
+    Assert.that(pair.getOffset() < (int) sizeField.getValue(), "boundary check");
+    return new ImmutableOopMap(dataStart().addOffsetTo(pair.getOffset()));
+  }
+}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMap.java	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2000, 2004, 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 sun.jvm.hotspot.compiler;
-
-import java.util.*;
-
-import sun.jvm.hotspot.code.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.types.*;
-
-public class OopMap extends VMObject {
-  private static CIntegerField pcOffsetField;
-  private static CIntegerField omvCountField;
-  private static CIntegerField omvDataSizeField;
-  private static AddressField  omvDataField;
-  private static AddressField  compressedWriteStreamField;
-
-  // This is actually a field inside class CompressedStream
-  private static AddressField  compressedStreamBufferField;
-
-  static {
-    VM.registerVMInitializedObserver(new Observer() {
-        public void update(Observable o, Object data) {
-          initialize(VM.getVM().getTypeDataBase());
-        }
-      });
-  }
-
-  private static void initialize(TypeDataBase db) {
-    Type type = db.lookupType("OopMap");
-
-    pcOffsetField              = type.getCIntegerField("_pc_offset");
-    omvCountField              = type.getCIntegerField("_omv_count");
-    omvDataSizeField           = type.getCIntegerField("_omv_data_size");
-    omvDataField               = type.getAddressField("_omv_data");
-    compressedWriteStreamField = type.getAddressField("_write_stream");
-
-    type = db.lookupType("CompressedStream");
-    compressedStreamBufferField = type.getAddressField("_buffer");
-  }
-
-  public OopMap(Address addr) {
-    super(addr);
-  }
-
-  public long getOffset() {
-    return pcOffsetField.getValue(addr);
-  }
-
-  //--------------------------------------------------------------------------------
-  // Internals only below this point
-  //
-
-  // Accessors -- package private for now
-  Address getOMVData() {
-    return omvDataField.getValue(addr);
-  }
-
-  long getOMVDataSize() {
-    return omvDataSizeField.getValue(addr);
-  }
-
-  long getOMVCount() {
-    return omvCountField.getValue(addr);
-  }
-
-  CompressedWriteStream getWriteStream() {
-    Address wsAddr = compressedWriteStreamField.getValue(addr);
-    if (wsAddr == null) {
-      return null;
-    }
-    Address bufferAddr = compressedStreamBufferField.getValue(wsAddr);
-    if (bufferAddr == null) {
-      return null;
-    }
-    return new CompressedWriteStream(bufferAddr);
-  }
-}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,289 +0,0 @@
-/*
- * Copyright (c) 2000, 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 sun.jvm.hotspot.compiler;
-
-import java.util.*;
-
-import sun.jvm.hotspot.code.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.types.*;
-import sun.jvm.hotspot.utilities.*;
-
-public class OopMapSet extends VMObject {
-  private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.compiler.OopMapSet.DEBUG") != null;
-
-  private static CIntegerField omCountField;
-  private static CIntegerField omSizeField;
-  private static AddressField  omDataField;
-  private static int REG_COUNT;
-  private static int SAVED_ON_ENTRY_REG_COUNT;
-  private static int C_SAVED_ON_ENTRY_REG_COUNT;
-  private static class MyVisitor implements OopMapVisitor {
-    private AddressVisitor addressVisitor;
-
-    public MyVisitor(AddressVisitor oopVisitor) {
-      setAddressVisitor(oopVisitor);
-    }
-
-    public void setAddressVisitor(AddressVisitor addressVisitor) {
-      this.addressVisitor = addressVisitor;
-    }
-
-    public void visitOopLocation(Address oopAddr) {
-      addressVisitor.visitAddress(oopAddr);
-    }
-
-    public void visitDerivedOopLocation(Address baseOopAddr, Address derivedOopAddr) {
-      if (VM.getVM().isClientCompiler()) {
-        Assert.that(false, "should not reach here");
-      } else if (VM.getVM().isServerCompiler() &&
-                 VM.getVM().useDerivedPointerTable()) {
-        Assert.that(false, "FIXME: add derived pointer table");
-      }
-    }
-
-    public void visitValueLocation(Address valueAddr) {
-    }
-
-    public void visitNarrowOopLocation(Address narrowOopAddr) {
-      addressVisitor.visitCompOopAddress(narrowOopAddr);
-    }
-  }
-
-  static {
-    VM.registerVMInitializedObserver(new Observer() {
-        public void update(Observable o, Object data) {
-          initialize(VM.getVM().getTypeDataBase());
-        }
-      });
-  }
-
-  private static void initialize(TypeDataBase db) {
-    Type type = db.lookupType("OopMapSet");
-
-    omCountField  = type.getCIntegerField("_om_count");
-    omSizeField   = type.getCIntegerField("_om_size");
-    omDataField   = type.getAddressField("_om_data");
-
-    if (!VM.getVM().isCore()) {
-      REG_COUNT = db.lookupIntConstant("REG_COUNT").intValue();
-      if (VM.getVM().isServerCompiler()) {
-        SAVED_ON_ENTRY_REG_COUNT = (int) db.lookupIntConstant("SAVED_ON_ENTRY_REG_COUNT").intValue();
-        C_SAVED_ON_ENTRY_REG_COUNT = (int) db.lookupIntConstant("C_SAVED_ON_ENTRY_REG_COUNT").intValue();
-      }
-    }
-  }
-
-  public OopMapSet(Address addr) {
-    super(addr);
-  }
-
-  /** Returns the number of OopMaps in this OopMapSet */
-  public long getSize() {
-    return omCountField.getValue(addr);
-  }
-
-  /** returns the OopMap at a given index */
-  public OopMap getMapAt(int index) {
-    if (Assert.ASSERTS_ENABLED) {
-      Assert.that((index >= 0) && (index <= getSize()),"bad index");
-    }
-    Address omDataAddr = omDataField.getValue(addr);
-    Address oopMapAddr = omDataAddr.getAddressAt(index * VM.getVM().getAddressSize());
-    if (oopMapAddr == null) {
-      return null;
-    }
-    return new OopMap(oopMapAddr);
-  }
-
-  public OopMap findMapAtOffset(long pcOffset, boolean debugging) {
-    int i;
-    int len = (int) getSize();
-    if (Assert.ASSERTS_ENABLED) {
-      Assert.that(len > 0, "must have pointer maps");
-    }
-
-    // Scan through oopmaps. Stop when current offset is either equal or greater
-    // than the one we are looking for.
-    for (i = 0; i < len; i++) {
-      if (getMapAt(i).getOffset() >= pcOffset) {
-        break;
-      }
-    }
-
-    if (!debugging) {
-      if (Assert.ASSERTS_ENABLED) {
-        Assert.that(i < len, "oopmap not found for pcOffset = " + pcOffset + "; len = " + len);
-        Assert.that(getMapAt(i).getOffset() == pcOffset, "oopmap not found");
-      }
-    } else {
-      if (i == len) {
-        if (DEBUG) {
-          System.out.println("can't find oopmap at " + pcOffset);
-          System.out.print("Oopmap offsets are [ ");
-          for (i = 0; i < len; i++) {
-            System.out.print(getMapAt(i).getOffset());
-          }
-          System.out.println("]");
-        }
-        i = len - 1;
-        return getMapAt(i);
-      }
-    }
-
-    OopMap m = getMapAt(i);
-    return m;
-  }
-
-  /** Visitation -- iterates through the frame for a compiled method.
-      This is a very generic mechanism that requires the Address to be
-      dereferenced by the callee. Other, more specialized, visitation
-      mechanisms are given below. */
-  public static void oopsDo(Frame fr, CodeBlob cb, RegisterMap regMap, AddressVisitor oopVisitor, boolean debugging) {
-    allDo(fr, cb, regMap, new MyVisitor(oopVisitor), debugging);
-  }
-
-  /** Note that there are 4 required AddressVisitors: one for oops,
-      one for derived oops, one for values, and one for dead values */
-  public static void allDo(Frame fr, CodeBlob cb, RegisterMap regMap, OopMapVisitor visitor, boolean debugging) {
-    if (Assert.ASSERTS_ENABLED) {
-      CodeBlob tmpCB = VM.getVM().getCodeCache().findBlob(fr.getPC());
-      Assert.that(tmpCB != null && cb.equals(tmpCB), "wrong codeblob passed in");
-    }
-
-    OopMapSet maps = cb.getOopMaps();
-    OopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging);
-    if (Assert.ASSERTS_ENABLED) {
-      Assert.that(map != null, "no ptr map found");
-    }
-
-    // handle derived pointers first (otherwise base pointer may be
-    // changed before derived pointer offset has been collected)
-    OopMapValue omv;
-    {
-      for (OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.DERIVED_OOP_VALUE); !oms.isDone(); oms.next()) {
-        if (VM.getVM().isClientCompiler()) {
-          Assert.that(false, "should not reach here");
-        }
-        omv = oms.getCurrent();
-        Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap);
-        if (loc != null) {
-          Address baseLoc    = fr.oopMapRegToLocation(omv.getContentReg(), regMap);
-          Address derivedLoc = loc;
-          visitor.visitDerivedOopLocation(baseLoc, derivedLoc);
-        }
-      }
-    }
-
-    // We want narow oop, value and oop oop_types
-    OopMapValue.OopTypes[] values = new OopMapValue.OopTypes[] {
-      OopMapValue.OopTypes.OOP_VALUE, OopMapValue.OopTypes.VALUE_VALUE, OopMapValue.OopTypes.NARROWOOP_VALUE
-    };
-
-    {
-      for (OopMapStream oms = new OopMapStream(map, values); !oms.isDone(); oms.next()) {
-        omv = oms.getCurrent();
-        Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap);
-        if (loc != null) {
-          if (omv.getType() == OopMapValue.OopTypes.OOP_VALUE) {
-            // This assert commented out because this will be useful
-            // to detect in the debugging system
-            // assert(Universe::is_heap_or_null(*loc), "found non oop pointer");
-            visitor.visitOopLocation(loc);
-          } else if (omv.getType() == OopMapValue.OopTypes.VALUE_VALUE) {
-            visitor.visitValueLocation(loc);
-          } else if (omv.getType() == OopMapValue.OopTypes.NARROWOOP_VALUE) {
-            visitor.visitNarrowOopLocation(loc);
-          }
-        }
-      }
-    }
-  }
-
-  /** Update callee-saved register info for the following frame.
-      Should only be called in non-core builds. */
-  public static void updateRegisterMap(Frame fr, CodeBlob cb, RegisterMap regMap, boolean debugging) {
-    if (Assert.ASSERTS_ENABLED) {
-      Assert.that(!VM.getVM().isCore(), "non-core builds only");
-    }
-
-    if (!VM.getVM().isDebugging()) {
-      if (Assert.ASSERTS_ENABLED) {
-        OopMapSet maps = cb.getOopMaps();
-        Assert.that((maps != null) && (maps.getSize() > 0), "found null or empty OopMapSet for CodeBlob");
-      }
-    } else {
-      // Hack for some topmost frames that have been found with empty
-      // OopMapSets. (Actually have not seen the null case, but don't
-      // want to take any chances.) See HSDB.showThreadStackMemory().
-      OopMapSet maps = cb.getOopMaps();
-      if ((maps == null) || (maps.getSize() == 0)) {
-        return;
-      }
-    }
-
-    // Check if caller must update oop argument
-    regMap.setIncludeArgumentOops(cb.callerMustGCArguments());
-
-    int nofCallee = 0;
-    Address[] locs = new Address[2 * REG_COUNT + 1];
-    VMReg  [] regs = new VMReg  [2 * REG_COUNT + 1];
-    // ("+1" because REG_COUNT might be zero)
-
-    // Scan through oopmap and find location of all callee-saved registers
-    // (we do not do update in place, since info could be overwritten)
-    OopMap map  = cb.getOopMapForReturnAddress(fr.getPC(), debugging);
-    if (Assert.ASSERTS_ENABLED) {
-      Assert.that(map != null, "no ptr map found");
-    }
-
-    OopMapValue omv = null;
-    for(OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE); !oms.isDone(); oms.next()) {
-      omv = oms.getCurrent();
-      if (Assert.ASSERTS_ENABLED) {
-        Assert.that(nofCallee < 2 * REG_COUNT, "overflow");
-      }
-      regs[nofCallee] = omv.getContentReg();
-      locs[nofCallee] = fr.oopMapRegToLocation(omv.getReg(), regMap);
-      nofCallee++;
-    }
-
-    // Check that runtime stubs save all callee-saved registers
-    // After adapter frames were deleted C2 doesn't use callee save registers at present
-    if (Assert.ASSERTS_ENABLED) {
-      if (VM.getVM().isServerCompiler()) {
-        Assert.that(!cb.isRuntimeStub() ||
-                    (nofCallee >= SAVED_ON_ENTRY_REG_COUNT || nofCallee >= C_SAVED_ON_ENTRY_REG_COUNT),
-                    "must save all");
-      }
-    }
-
-    // Copy found callee-saved register to reg_map
-    for (int i = 0; i < nofCallee; i++) {
-      regMap.setLocation(regs[i], locs[i]);
-    }
-  }
-}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapStream.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapStream.java	Fri May 08 13:25:11 2015 -0400
@@ -28,30 +28,26 @@
 
 public class OopMapStream {
   private CompressedReadStream stream;
-  private OopMap oopMap;
+  private ImmutableOopMap oopMap;
   private int mask;
   private int size;
   private int position;
   private OopMapValue omv;
   private boolean omvValid;
 
-  public OopMapStream(OopMap oopMap) {
+  public OopMapStream(ImmutableOopMap oopMap) {
     this(oopMap, (OopMapValue.OopTypes[]) null);
   }
 
-  public OopMapStream(OopMap oopMap, OopMapValue.OopTypes type) {
+  public OopMapStream(ImmutableOopMap oopMap, OopMapValue.OopTypes type) {
     this(oopMap, (OopMapValue.OopTypes[]) null);
     mask = type.getValue();
   }
 
-  public OopMapStream(OopMap oopMap, OopMapValue.OopTypes[] types) {
-    if (oopMap.getOMVData() == null) {
-      stream = new CompressedReadStream(oopMap.getWriteStream().getBuffer());
-    } else {
-      stream = new CompressedReadStream(oopMap.getOMVData());
-    }
+  public OopMapStream(ImmutableOopMap oopMap, OopMapValue.OopTypes[] types) {
+    stream = new CompressedReadStream(oopMap.getData());
     mask = computeMask(types);
-    size = (int) oopMap.getOMVCount();
+    size = (int) oopMap.getCount();
     position = 0;
     omv = new OopMapValue();
     omvValid = false;
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java	Fri May 08 13:25:11 2015 -0400
@@ -26,14 +26,12 @@
 
 import java.io.*;
 import java.util.*;
-import sun.jvm.hotspot.*;
+
 import sun.jvm.hotspot.code.*;
 import sun.jvm.hotspot.compiler.*;
-import sun.jvm.hotspot.c1.*;
 import sun.jvm.hotspot.debugger.*;
 import sun.jvm.hotspot.interpreter.*;
 import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.runtime.sparc.SPARCFrame;
 import sun.jvm.hotspot.types.*;
 import sun.jvm.hotspot.utilities.*;
 
@@ -626,7 +624,7 @@
       Assert.that(cb != null, "sanity check");
     }
     if (cb.getOopMaps() != null) {
-      OopMapSet.oopsDo(this, cb, regMap, oopVisitor, VM.getVM().isDebugging());
+      ImmutableOopMapSet.oopsDo(this, cb, regMap, oopVisitor, VM.getVM().isDebugging());
 
       // FIXME: add in traversal of argument oops (skipping this for
       // now until we have the other stuff tested)
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java	Fri May 08 13:25:11 2015 -0400
@@ -358,7 +358,7 @@
       map.setIncludeArgumentOops(cb.callerMustGCArguments());
 
       if (cb.getOopMaps() != null) {
-        OopMapSet.updateRegisterMap(this, cb, map, true);
+        ImmutableOopMapSet.updateRegisterMap(this, cb, map, true);
       }
     }
 
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java	Fri May 08 13:25:11 2015 -0400
@@ -24,8 +24,6 @@
 
 package sun.jvm.hotspot.runtime.sparc;
 
-import java.util.*;
-
 import sun.jvm.hotspot.asm.sparc.*;
 import sun.jvm.hotspot.code.*;
 import sun.jvm.hotspot.compiler.*;
@@ -34,7 +32,6 @@
 import sun.jvm.hotspot.oops.*;
 import sun.jvm.hotspot.runtime.*;
 import sun.jvm.hotspot.runtime.posix.*;
-import sun.jvm.hotspot.types.*;
 import sun.jvm.hotspot.utilities.*;
 
 /** Specialization of and implementation of abstract methods of the
@@ -592,7 +589,7 @@
             map.setIncludeArgumentOops(true);
           }
           if (cb.getOopMaps() != null) {
-            OopMapSet.updateRegisterMap(this, cb, map, VM.getVM().isDebugging());
+            ImmutableOopMapSet.updateRegisterMap(this, cb, map, VM.getVM().isDebugging());
           }
         }
       }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java	Fri May 08 13:25:11 2015 -0400
@@ -385,7 +385,7 @@
       map.setIncludeArgumentOops(cb.callerMustGCArguments());
 
       if (cb.getOopMaps() != null) {
-        OopMapSet.updateRegisterMap(this, cb, map, true);
+        ImmutableOopMapSet.updateRegisterMap(this, cb, map, true);
       }
 
       // Since the prolog does the save and restore of EBP there is no oopmap
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java	Fri May 08 13:25:11 2015 -0400
@@ -31,11 +31,9 @@
 import sun.jvm.hotspot.compiler.*;
 import sun.jvm.hotspot.debugger.*;
 import sun.jvm.hotspot.interpreter.*;
-import sun.jvm.hotspot.memory.*;
 import sun.jvm.hotspot.oops.*;
 import sun.jvm.hotspot.runtime.*;
 import sun.jvm.hotspot.tools.jcore.*;
-import sun.jvm.hotspot.types.*;
 import sun.jvm.hotspot.utilities.*;
 
 public class HTMLGenerator implements /* imports */ ClassConstants {
@@ -887,7 +885,7 @@
       private Formatter buf;
       private SymbolFinder symFinder = createSymbolFinder();
       private long pc;
-      private OopMapSet oms;
+      private ImmutableOopMapSet oms;
       private CodeBlob blob;
       private NMethod nmethod;
 
@@ -954,13 +952,13 @@
 
          if (oms != null) {
             long base = addressToLong(blob.codeBegin());
-            for (int i = 0, imax = (int)oms.getSize(); i < imax; i++) {
-               OopMap om = oms.getMapAt(i);
-               long omspc = base + om.getOffset();
+            for (int i = 0, imax = oms.getCount(); i < imax; i++) {
+               ImmutableOopMapPair pair = oms.getPairAt(i);
+               long omspc = base + pair.getPC();
                if (omspc > pc) {
                   if (omspc <= endPc) {
                      buf.br();
-                     buf.append(genOopMapInfo(om));
+                     buf.append(genOopMapInfo(oms.getMap(pair)));
                      // st.move_to(column);
                      // visitor.print("; ");
                         // om.print_on(st);
@@ -1167,7 +1165,7 @@
         }
     }
 
-   protected String genHTMLForOopMap(OopMap map) {
+   protected String genHTMLForOopMap(ImmutableOopMap map) {
       final int stack0 = VMRegImpl.getStack0().getValue();
       Formatter buf = new Formatter(genHTML);
 
@@ -1237,11 +1235,11 @@
 
 
    protected String genOopMapInfo(NMethod nmethod, PCDesc pcDesc) {
-      OopMapSet mapSet = nmethod.getOopMaps();
+      ImmutableOopMapSet mapSet = nmethod.getOopMaps();
       if (mapSet == null || (mapSet.getSize() <= 0))
         return "";
       int pcOffset = pcDesc.getPCOffset();
-      OopMap map = mapSet.findMapAtOffset(pcOffset, VM.getVM().isDebugging());
+      ImmutableOopMap map = mapSet.findMapAtOffset(pcOffset, VM.getVM().isDebugging());
       if (map == null) {
          throw new IllegalArgumentException("no oopmap at safepoint!");
       }
@@ -1249,7 +1247,7 @@
       return genOopMapInfo(map);
    }
 
-   protected String genOopMapInfo(OopMap map) {
+   protected String genOopMapInfo(ImmutableOopMap map) {
      Formatter buf = new Formatter(genHTML);
      buf.beginTag("pre");
      buf.append("OopMap: ");
--- a/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp	Fri May 08 13:25:11 2015 -0400
@@ -502,10 +502,17 @@
   __ neg(reg, reg);
 }
 
-void TemplateTable::iload()
-{
+void TemplateTable::iload() {
+  iload_internal();
+}
+
+void TemplateTable::nofast_iload() {
+  iload_internal(may_not_rewrite);
+}
+
+void TemplateTable::iload_internal(RewriteControl rc) {
   transition(vtos, itos);
-  if (RewriteFrequentPairs) {
+  if (RewriteFrequentPairs && rc == may_rewrite) {
     // TODO : check x86 code for what to do here
     __ call_Unimplemented();
   } else {
@@ -759,8 +766,15 @@
   __ ldr(r0, iaddress(n));
 }
 
-void TemplateTable::aload_0()
-{
+void TemplateTable::aload_0() {
+  aload_0_internal();
+}
+
+void TemplateTable::nofast_aload_0() {
+  aload_0_internal(may_not_rewrite);
+}
+
+void TemplateTable::aload_0_internal(RewriteControl rc) {
   // According to bytecode histograms, the pairs:
   //
   // _aload_0, _fast_igetfield
@@ -782,7 +796,7 @@
   //   aload_0, iload_1
   // These bytecodes with a small amount of code are most profitable
   // to rewrite
-  if (RewriteFrequentPairs) {
+  if (RewriteFrequentPairs && rc == may_rewrite) {
     __ call_Unimplemented();
   } else {
     aload(0);
@@ -2132,14 +2146,21 @@
   assert_different_registers(Rcache, index, temp);
 
   Label resolved;
+
+  Bytecodes::Code code = bytecode();
+  switch (code) {
+  case Bytecodes::_nofast_getfield: code = Bytecodes::_getfield; break;
+  case Bytecodes::_nofast_putfield: code = Bytecodes::_putfield; break;
+  }
+
   assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
   __ get_cache_and_index_and_bytecode_at_bcp(Rcache, index, temp, byte_no, 1, index_size);
-  __ cmp(temp, (int) bytecode());  // have we resolved this bytecode?
+  __ cmp(temp, (int) code);  // have we resolved this bytecode?
   __ br(Assembler::EQ, resolved);
 
   // resolve first time through
   address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
-  __ mov(temp, (int) bytecode());
+  __ mov(temp, (int) code);
   __ call_VM(noreg, entry, temp);
 
   // Update registers with resolved info
@@ -2257,7 +2278,7 @@
   __ verify_oop(r);
 }
 
-void TemplateTable::getfield_or_static(int byte_no, bool is_static)
+void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteControl rc)
 {
   const Register cache = r2;
   const Register index = r3;
@@ -2287,11 +2308,14 @@
   assert(btos == 0, "change code, btos != 0");
   __ cbnz(flags, notByte);
 
+  // Don't rewrite getstatic, only getfield
+  if (is_static) rc = may_not_rewrite;
+
   // btos
   __ load_signed_byte(r0, field);
   __ push(btos);
   // Rewrite bytecode to be faster
-  if (!is_static) {
+  if (rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_bgetfield, bc, r1);
   }
   __ b(Done);
@@ -2302,7 +2326,7 @@
   // atos
   __ load_heap_oop(r0, field);
   __ push(atos);
-  if (!is_static) {
+  if (rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_agetfield, bc, r1);
   }
   __ b(Done);
@@ -2314,7 +2338,7 @@
   __ ldrw(r0, field);
   __ push(itos);
   // Rewrite bytecode to be faster
-  if (!is_static) {
+  if (rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_igetfield, bc, r1);
   }
   __ b(Done);
@@ -2326,7 +2350,7 @@
   __ load_unsigned_short(r0, field);
   __ push(ctos);
   // Rewrite bytecode to be faster
-  if (!is_static) {
+  if (rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_cgetfield, bc, r1);
   }
   __ b(Done);
@@ -2338,7 +2362,7 @@
   __ load_signed_short(r0, field);
   __ push(stos);
   // Rewrite bytecode to be faster
-  if (!is_static) {
+  if (rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_sgetfield, bc, r1);
   }
   __ b(Done);
@@ -2350,7 +2374,7 @@
   __ ldr(r0, field);
   __ push(ltos);
   // Rewrite bytecode to be faster
-  if (!is_static) {
+  if (rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_lgetfield, bc, r1);
   }
   __ b(Done);
@@ -2362,7 +2386,7 @@
   __ ldrs(v0, field);
   __ push(ftos);
   // Rewrite bytecode to be faster
-  if (!is_static) {
+  if (rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_fgetfield, bc, r1);
   }
   __ b(Done);
@@ -2376,7 +2400,7 @@
   __ ldrd(v0, field);
   __ push(dtos);
   // Rewrite bytecode to be faster
-  if (!is_static) {
+  if (rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_dgetfield, bc, r1);
   }
 #ifdef ASSERT
@@ -2398,6 +2422,10 @@
   getfield_or_static(byte_no, false);
 }
 
+void TemplateTable::nofast_getfield(int byte_no) {
+  getfield_or_static(byte_no, false, may_not_rewrite);
+}
+
 void TemplateTable::getstatic(int byte_no)
 {
   getfield_or_static(byte_no, true);
@@ -2461,7 +2489,7 @@
   }
 }
 
-void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
+void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteControl rc) {
   transition(vtos, vtos);
 
   const Register cache = r2;
@@ -2498,12 +2526,15 @@
   assert(btos == 0, "change code, btos != 0");
   __ cbnz(flags, notByte);
 
+  // Don't rewrite putstatic, only putfield
+  if (is_static) rc = may_not_rewrite;
+
   // btos
   {
     __ pop(btos);
     if (!is_static) pop_and_check_object(obj);
     __ strb(r0, field);
-    if (!is_static) {
+    if (rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_bputfield, bc, r1, true, byte_no);
     }
     __ b(Done);
@@ -2519,7 +2550,7 @@
     if (!is_static) pop_and_check_object(obj);
     // Store into the field
     do_oop_store(_masm, field, r0, _bs->kind(), false);
-    if (!is_static) {
+    if (rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_aputfield, bc, r1, true, byte_no);
     }
     __ b(Done);
@@ -2534,7 +2565,7 @@
     __ pop(itos);
     if (!is_static) pop_and_check_object(obj);
     __ strw(r0, field);
-    if (!is_static) {
+    if (rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_iputfield, bc, r1, true, byte_no);
     }
     __ b(Done);
@@ -2549,7 +2580,7 @@
     __ pop(ctos);
     if (!is_static) pop_and_check_object(obj);
     __ strh(r0, field);
-    if (!is_static) {
+    if (rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_cputfield, bc, r1, true, byte_no);
     }
     __ b(Done);
@@ -2564,7 +2595,7 @@
     __ pop(stos);
     if (!is_static) pop_and_check_object(obj);
     __ strh(r0, field);
-    if (!is_static) {
+    if (rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_sputfield, bc, r1, true, byte_no);
     }
     __ b(Done);
@@ -2579,7 +2610,7 @@
     __ pop(ltos);
     if (!is_static) pop_and_check_object(obj);
     __ str(r0, field);
-    if (!is_static) {
+    if (rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_lputfield, bc, r1, true, byte_no);
     }
     __ b(Done);
@@ -2594,7 +2625,7 @@
     __ pop(ftos);
     if (!is_static) pop_and_check_object(obj);
     __ strs(v0, field);
-    if (!is_static) {
+    if (rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_fputfield, bc, r1, true, byte_no);
     }
     __ b(Done);
@@ -2611,7 +2642,7 @@
     __ pop(dtos);
     if (!is_static) pop_and_check_object(obj);
     __ strd(v0, field);
-    if (!is_static) {
+    if (rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_dputfield, bc, r1, true, byte_no);
     }
   }
@@ -2638,6 +2669,10 @@
   putfield_or_static(byte_no, false);
 }
 
+void TemplateTable::nofast_putfield(int byte_no) {
+  putfield_or_static(byte_no, false, may_not_rewrite);
+}
+
 void TemplateTable::putstatic(int byte_no) {
   putfield_or_static(byte_no, true);
 }
--- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp	Fri May 08 13:25:11 2015 -0400
@@ -629,7 +629,7 @@
   // Print the detection code.
   if (PrintAssembly) {
     ttyLocker ttyl;
-    tty->print_cr("Decoding dscr configuration stub at " INTPTR_FORMAT " before execution:", code);
+    tty->print_cr("Decoding dscr configuration stub at " INTPTR_FORMAT " before execution:", p2i(code));
     Disassembler::decode((u_char*)code, (u_char*)code_end, tty);
   }
 
--- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Fri May 08 13:25:11 2015 -0400
@@ -1631,36 +1631,22 @@
 
         NOT_LP64(__ get_thread(thread);)
 
-        Address in_progress(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
-                                             PtrQueue::byte_offset_of_active()));
-
         Address queue_index(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
                                              PtrQueue::byte_offset_of_index()));
         Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
                                         PtrQueue::byte_offset_of_buf()));
 
-
         Label done;
         Label runtime;
 
         // Can we store original value in the thread's buffer?
 
-#ifdef _LP64
-        __ movslq(tmp, queue_index);
-        __ cmpq(tmp, 0);
-#else
-        __ cmpl(queue_index, 0);
-#endif
-        __ jcc(Assembler::equal, runtime);
-#ifdef _LP64
-        __ subq(tmp, wordSize);
-        __ movl(queue_index, tmp);
-        __ addq(tmp, buffer);
-#else
-        __ subl(queue_index, wordSize);
-        __ movl(tmp, buffer);
-        __ addl(tmp, queue_index);
-#endif
+        __ movptr(tmp, queue_index);
+        __ testptr(tmp, tmp);
+        __ jcc(Assembler::zero, runtime);
+        __ subptr(tmp, wordSize);
+        __ movptr(queue_index, tmp);
+        __ addptr(tmp, buffer);
 
         // prev_val (rax)
         f.load_argument(0, pre_val);
@@ -1713,6 +1699,7 @@
         assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
 
         Label done;
+        Label enqueued;
         Label runtime;
 
         // At this point we know new_value is non-NULL and the new_value crosses regions.
@@ -1752,28 +1739,19 @@
 
         __ movb(Address(card_addr, 0), (int)CardTableModRefBS::dirty_card_val());
 
-        __ cmpl(queue_index, 0);
-        __ jcc(Assembler::equal, runtime);
-        __ subl(queue_index, wordSize);
-
-        const Register buffer_addr = rbx;
-        __ push(rbx);
-
-        __ movptr(buffer_addr, buffer);
+        const Register tmp = rdx;
+        __ push(rdx);
 
-#ifdef _LP64
-        __ movslq(rscratch1, queue_index);
-        __ addptr(buffer_addr, rscratch1);
-#else
-        __ addptr(buffer_addr, queue_index);
-#endif
-        __ movptr(Address(buffer_addr, 0), card_addr);
-
-        __ pop(rbx);
-        __ jmp(done);
+        __ movptr(tmp, queue_index);
+        __ testptr(tmp, tmp);
+        __ jcc(Assembler::zero, runtime);
+        __ subptr(tmp, wordSize);
+        __ movptr(queue_index, tmp);
+        __ addptr(tmp, buffer);
+        __ movptr(Address(tmp, 0), card_addr);
+        __ jmp(enqueued);
 
         __ bind(runtime);
-        __ push(rdx);
 #ifdef _LP64
         __ push(r8);
         __ push(r9);
@@ -1795,12 +1773,12 @@
         __ pop(r9);
         __ pop(r8);
 #endif
+        __ bind(enqueued);
         __ pop(rdx);
+
         __ bind(done);
-
         __ pop(rcx);
         __ pop(rax);
-
       }
       break;
 #endif // INCLUDE_ALL_GCS
--- a/hotspot/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/nbproject/build-impl.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/nbproject/build-impl.xml	Fri May 08 13:25:11 2015 -0400
@@ -4,6 +4,13 @@
 ***         EDIT ../build.xml INSTEAD         ***
 -->
 <project name="com.sun.hotspot.igv.svg-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
     <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>
@@ -16,13 +23,21 @@
             <property name="@{name}" value="${@{value}}"/>
         </sequential>
     </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" 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'">
+    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
         <condition>
             <not>
-                <available file="${harness.dir}" type="dir"/>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
             </not>
         </condition>
     </fail>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/nbproject/genfiles.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/nbproject/genfiles.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,8 +1,5 @@
-build.xml.data.CRC32=ebcf0422
-build.xml.script.CRC32=d7a2678d
-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=ebcf0422
-nbproject/build-impl.xml.script.CRC32=57997f94
-nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
+nbproject/build-impl.xml.script.CRC32=42ef3ff6
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1
--- a/hotspot/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/nbproject/project.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/nbproject/project.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/hotspot/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/BatikSVG.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/BatikSVG.java	Fri May 08 13:25:11 2015 -0400
@@ -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,40 +25,58 @@
 
 import java.awt.Graphics2D;
 import java.io.Writer;
+import java.io.File;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
 import org.w3c.dom.DOMImplementation;
 
 /**
- *
+ * Utility class
  * @author Thomas Wuerthinger
  */
 public class BatikSVG {
 
+    private BatikSVG() {
+    }
+
     private static Constructor SVGGraphics2DConstructor;
-    private static Method Method_stream;
-    private static Method Method_createDefault;
-    private static Method Method_getDOMImplementation;
-    private static Method Method_setEmbeddedFontsOn;
+    private static Method streamMethod;
+    private static Method createDefaultMethod;
+    private static Method getDOMImplementationMethod;
+    private static Method setEmbeddedFontsOnMethod;
+    private static Class<?> classSVGGraphics2D;
 
+    /**
+     * Creates a graphics object that allows to be exported to SVG data using the {@link #printToStream(Graphics2D, Writer, boolean) printToStream} method.
+     * @return the newly created Graphics2D object or null if the library does not exist
+     */
     public static Graphics2D createGraphicsObject() {
         try {
             if (SVGGraphics2DConstructor == null) {
-                ClassLoader cl = BatikSVG.class.getClassLoader();
-                Class Class_GenericDOMImplementation = cl.loadClass("org.apache.batik.dom.GenericDOMImplementation");
-                Class Class_SVGGeneratorContext = cl.loadClass("org.apache.batik.svggen.SVGGeneratorContext");
-                Class Class_SVGGraphics2D = cl.loadClass("org.apache.batik.svggen.SVGGraphics2D");
-                Method_getDOMImplementation = Class_GenericDOMImplementation.getDeclaredMethod("getDOMImplementation", new Class[0]);
-                Method_createDefault = Class_SVGGeneratorContext.getDeclaredMethod("createDefault", new Class[]{org.w3c.dom.Document.class});
-                Method_setEmbeddedFontsOn = Class_SVGGeneratorContext.getDeclaredMethod("setEmbeddedFontsOn", new Class[]{boolean.class});
-                Method_stream = Class_SVGGraphics2D.getDeclaredMethod("stream", Writer.class, boolean.class);
-                SVGGraphics2DConstructor = Class_SVGGraphics2D.getConstructor(Class_SVGGeneratorContext, boolean.class);
+                String batikJar = System.getenv().get("IGV_BATIK_JAR");
+                if (batikJar == null) {
+                    return null;
+                }
+                // Load batik in it's own class loader since some it's support jars interfere with the JDK
+                URL url = new File(batikJar).toURI().toURL();
+                ClassLoader cl = new URLClassLoader(new URL[] { url });
+                Class<?> classGenericDOMImplementation = cl.loadClass("org.apache.batik.dom.GenericDOMImplementation");
+                Class<?> classSVGGeneratorContext = cl.loadClass("org.apache.batik.svggen.SVGGeneratorContext");
+                classSVGGraphics2D = cl.loadClass("org.apache.batik.svggen.SVGGraphics2D");
+                getDOMImplementationMethod = classGenericDOMImplementation.getDeclaredMethod("getDOMImplementation", new Class[0]);
+                createDefaultMethod = classSVGGeneratorContext.getDeclaredMethod("createDefault", new Class[]{org.w3c.dom.Document.class});
+                setEmbeddedFontsOnMethod = classSVGGeneratorContext.getDeclaredMethod("setEmbeddedFontsOn", new Class[]{boolean.class});
+                streamMethod = classSVGGraphics2D.getDeclaredMethod("stream", Writer.class, boolean.class);
+                SVGGraphics2DConstructor = classSVGGraphics2D.getConstructor(classSVGGeneratorContext, boolean.class);
             }
-            DOMImplementation dom = (DOMImplementation) Method_getDOMImplementation.invoke(null);
+            DOMImplementation dom = (DOMImplementation) getDOMImplementationMethod.invoke(null);
             org.w3c.dom.Document document = dom.createDocument("http://www.w3.org/2000/svg", "svg", null);
-            Object ctx = Method_createDefault.invoke(null, document);
-            Method_setEmbeddedFontsOn.invoke(ctx, true);
+            Object ctx = createDefaultMethod.invoke(null, document);
+            setEmbeddedFontsOnMethod.invoke(ctx, true);
             Graphics2D svgGenerator = (Graphics2D) SVGGraphics2DConstructor.newInstance(ctx, true);
             return svgGenerator;
         } catch (ClassNotFoundException e) {
@@ -71,12 +89,22 @@
             return null;
         } catch (InstantiationException e) {
             return null;
+        } catch (MalformedURLException e) {
+            return null;
         }
     }
 
+    /**
+     * Serializes a graphics object to a stream in SVG format.
+     * @param svgGenerator the graphics object. Only graphics objects created by the {@link #createGraphicsObject() createGraphicsObject} method are valid.
+     * @param stream the stream to which the data is written
+     * @param useCSS whether to use CSS styles in the SVG output
+     */
     public static void printToStream(Graphics2D svgGenerator, Writer stream, boolean useCSS) {
+        assert classSVGGraphics2D != null;
+        assert classSVGGraphics2D.isInstance(svgGenerator);
         try {
-            Method_stream.invoke(svgGenerator, stream, useCSS);
+            streamMethod.invoke(svgGenerator, stream, useCSS);
         } catch (IllegalAccessException e) {
             assert false;
         } catch (InvocationTargetException e) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/package-info.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ *
+ */
+/**
+ * This package is used to proxy the SVG export functionality of the BatikSVG library. Reflection is used such that the
+ * library is optional and need not be present at build time.
+ */
+package com.sun.hotspot.igv.svg;
+
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/manifest.mf	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/manifest.mf	Fri May 08 13:25:11 2015 -0400
@@ -1,6 +1,6 @@
-Manifest-Version: 1.0
-OpenIDE-Module: com.sun.hotspot.igv.bytecodes
-OpenIDE-Module-Layer: com/sun/hotspot/igv/bytecodes/layer.xml
-OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/bytecodes/Bundle.properties
-OpenIDE-Module-Specification-Version: 1.0
-
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.bytecodes
+OpenIDE-Module-Layer: com/sun/hotspot/igv/bytecodes/layer.xml
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/bytecodes/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/nbproject/project.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/nbproject/project.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/nbproject/project.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/nbproject/project.xml	Fri May 08 13:25:11 2015 -0400
@@ -15,12 +15,36 @@
                     </run-dependency>
                 </dependency>
                 <dependency>
+                    <code-name-base>com.sun.hotspot.igv.graph</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.4</specification-version>
+                        <specification-version>1.16.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.awt</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.39.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -28,7 +52,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.11</specification-version>
+                        <specification-version>6.34.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -36,7 +60,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.2.0.1</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -44,7 +68,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.9.0.1</specification-version>
+                        <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>
@@ -52,7 +84,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.16</specification-version>
+                        <specification-version>6.39.1</specification-version>
                     </run-dependency>
                 </dependency>
             </module-dependencies>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/Bundle.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/Bundle.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
-CTL_BytecodeViewAction=Open BytecodeView Window
-CTL_BytecodeViewTopComponent=BytecodeView Window
+CTL_BytecodeViewAction=Bytecode
+CTL_BytecodeViewTopComponent=Bytecode
 CTL_SelectBytecodesAction=Select nodes
-HINT_BytecodeViewTopComponent=This is a BytecodeView window
+HINT_BytecodeViewTopComponent=Shows the bytecode associated with the displayed graph.
 OpenIDE-Module-Name=Bytecodes
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeNode.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeNode.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -29,14 +29,14 @@
 import com.sun.hotspot.igv.data.Properties;
 import com.sun.hotspot.igv.data.Properties.StringPropertyMatcher;
 import java.awt.Image;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
 import javax.swing.Action;
 import org.openide.nodes.AbstractNode;
 import org.openide.nodes.Children;
 import org.openide.nodes.Node;
-import org.openide.util.Utilities;
+import org.openide.util.ImageUtilities;
 
 /**
  *
@@ -49,29 +49,35 @@
     public BytecodeNode(InputBytecode bytecode, InputGraph graph, String bciValue) {
 
         super(Children.LEAF);
-        this.setDisplayName(bytecode.getBci() + " " + bytecode.getName());
+        String displayName = bytecode.getBci() + " " + bytecode.getName() + " " + bytecode.getOperands();
 
         bciValue = bytecode.getBci() + " " + bciValue;
         bciValue = bciValue.trim();
 
-        Properties.PropertySelector<InputNode> selector = new Properties.PropertySelector<InputNode>(graph.getNodes());
+        Properties.PropertySelector<InputNode> selector = new Properties.PropertySelector<>(graph.getNodes());
         StringPropertyMatcher matcher = new StringPropertyMatcher("bci", bciValue);
         List<InputNode> nodeList = selector.selectMultiple(matcher);
         if (nodeList.size() > 0) {
-            nodes = new HashSet<InputNode>();
+            nodes = new LinkedHashSet<>();
             for (InputNode n : nodeList) {
                 nodes.add(n);
             }
-            this.setDisplayName(this.getDisplayName() + " (" + nodes.size() + " nodes)");
+            displayName += " (" + nodes.size() + " nodes)";
         }
+
+        if (bytecode.getComment() != null) {
+            displayName += " // " + bytecode.getComment();
+        }
+
+        this.setDisplayName(displayName);
     }
 
     @Override
     public Image getIcon(int i) {
         if (nodes != null) {
-            return Utilities.loadImage("com/sun/hotspot/igv/bytecodes/images/link.gif");
+            return ImageUtilities.loadImage("com/sun/hotspot/igv/bytecodes/images/link.png");
         } else {
-            return Utilities.loadImage("com/sun/hotspot/igv/bytecodes/images/bytecode.gif");
+            return ImageUtilities.loadImage("com/sun/hotspot/igv/bytecodes/images/bytecode.png");
         }
     }
 
@@ -91,6 +97,7 @@
     }
 
     @Override
+    @SuppressWarnings("unchecked")
     public <T extends Node.Cookie> T getCookie(Class<T> aClass) {
         if (aClass == SelectBytecodesCookie.class && nodes != null) {
             return (T) (new SelectBytecodesCookie(nodes));
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -37,6 +37,7 @@
         super(NbBundle.getMessage(BytecodeViewAction.class, "CTL_BytecodeViewAction"));
     }
 
+    @Override
     public void actionPerformed(ActionEvent evt) {
         TopComponent win = BytecodeViewTopComponent.findInstance();
         win.open();
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.form	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.form	Fri May 08 13:25:11 2015 -0400
@@ -3,6 +3,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"/>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -26,6 +26,7 @@
 import com.sun.hotspot.igv.data.Group;
 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.SwingUtilities;
@@ -33,11 +34,7 @@
 import org.openide.explorer.ExplorerManager;
 import org.openide.explorer.ExplorerUtils;
 import org.openide.explorer.view.BeanTreeView;
-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.util.*;
 import org.openide.windows.TopComponent;
 import org.openide.windows.WindowManager;
 
@@ -91,6 +88,7 @@
     }// </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.
@@ -126,7 +124,7 @@
 
     @Override
     public void componentOpened() {
-        Lookup.Template tpl = new Lookup.Template(Object.class);
+        Lookup.Template<InputGraphProvider> tpl = new Lookup.Template<>(InputGraphProvider.class);
         result = Utilities.actionsGlobalContext().lookup(tpl);
         result.addLookupListener(this);
     }
@@ -147,23 +145,47 @@
         return PREFERRED_ID;
     }
 
+    @Override
     public ExplorerManager getExplorerManager() {
         return manager;
     }
 
+    @Override
+    public void requestActive() {
+        super.requestActive();
+        this.treeView.requestFocus();
+    }
+
+    @Override
+    public boolean requestFocus(boolean temporary) {
+        this.treeView.requestFocus();
+        return super.requestFocus(temporary);
+    }
+
+    @Override
+    protected boolean requestFocusInWindow(boolean temporary) {
+        this.treeView.requestFocus();
+        return super.requestFocusInWindow(temporary);
+    }
+
+    @Override
     public void resultChanged(LookupEvent lookupEvent) {
-        final InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class);
-        if (p != null) {
+        final InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//)Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
             SwingUtilities.invokeLater(new Runnable() {
+                @Override
                 public void run() {
-            InputGraph graph = p.getGraph();
-            if (graph != null) {
-                Group g = graph.getGroup();
-                rootNode.update(graph, g.getMethod());
-            }
-        }
+                if (p != null) {
+                    InputGraph graph = p.getGraph();
+                    if (graph != null) {
+                        Group g = graph.getGroup();
+                        rootNode.update(graph, g.getMethod());
+                        return;
+                    }
+                }
+                        rootNode.update(null, null);
+                    }
             });
-        }
+
     }
 
     final static class ResolvableHelper implements Serializable {
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/MethodNode.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/MethodNode.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -30,7 +30,7 @@
 import org.openide.nodes.AbstractNode;
 import org.openide.nodes.Children;
 import org.openide.nodes.Node;
-import org.openide.util.Utilities;
+import org.openide.util.ImageUtilities;
 
 /**
  *
@@ -38,7 +38,7 @@
  */
 public class MethodNode extends AbstractNode {
 
-    private static class MethodNodeChildren extends Children.Keys {
+    private static class MethodNodeChildren extends Children.Keys<InputBytecode> {
 
         private InputMethod method;
         private InputGraph graph;
@@ -50,9 +50,8 @@
             this.graph = graph;
         }
 
-        protected Node[] createNodes(Object object) {
-            assert object instanceof InputBytecode;
-            InputBytecode bc = (InputBytecode) object;
+        @Override
+        protected Node[] createNodes(InputBytecode bc) {
             if (bc.getInlined() == null) {
                 return new Node[]{new BytecodeNode(bc, graph, bciString)};
             } else {
@@ -84,7 +83,7 @@
 
     @Override
     public Image getIcon(int i) {
-        return Utilities.loadImage("com/sun/hotspot/igv/bytecodes/images/method.gif");
+        return ImageUtilities.loadImage("com/sun/hotspot/igv/bytecodes/images/method.png");
     }
 
     @Override
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/SelectBytecodesAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/SelectBytecodesAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -24,9 +24,9 @@
 package com.sun.hotspot.igv.bytecodes;
 
 import com.sun.hotspot.igv.data.services.InputGraphProvider;
+import com.sun.hotspot.igv.util.LookupHistory;
 import org.openide.nodes.Node;
 import org.openide.util.HelpCtx;
-import org.openide.util.Lookup;
 import org.openide.util.NbBundle;
 import org.openide.util.actions.CookieAction;
 
@@ -36,22 +36,26 @@
  */
 public final class SelectBytecodesAction extends CookieAction {
 
+    @Override
     protected void performAction(Node[] activatedNodes) {
         SelectBytecodesCookie c = activatedNodes[0].getCookie(SelectBytecodesCookie.class);
-        InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class);
+        InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
         if (p != null) {
             p.setSelectedNodes(c.getNodes());
         }
     }
 
+    @Override
     protected int mode() {
         return CookieAction.MODE_EXACTLY_ONE;
     }
 
+    @Override
     public String getName() {
         return NbBundle.getMessage(SelectBytecodesAction.class, "CTL_SelectBytecodesAction");
     }
 
+    @Override
     protected Class[] cookieClasses() {
         return new Class[]{
             SelectBytecodesCookie.class
@@ -64,6 +68,7 @@
         putValue("noIconInMenu", Boolean.TRUE);
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
@@ -73,3 +78,4 @@
         return false;
     }
 }
+
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/SelectBytecodesCookie.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/SelectBytecodesCookie.java	Fri May 08 13:25:11 2015 -0400
@@ -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
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/bytecode.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/bytecode.png has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/link.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/link.png has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/method.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/method.png has changed
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/manifest.mf	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/manifest.mf	Fri May 08 13:25:11 2015 -0400
@@ -1,6 +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
-
+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
+
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/nbproject/project.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/nbproject/project.xml	Fri May 08 13:25:11 2015 -0400
@@ -31,12 +31,20 @@
                     </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.4</specification-version>
+                        <specification-version>1.16.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -52,7 +60,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.9.0.1</specification-version>
+                        <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>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/BlockConnectionWidget.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/BlockConnectionWidget.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -26,7 +26,9 @@
 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;
@@ -37,12 +39,19 @@
  */
 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);
@@ -67,6 +76,30 @@
         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;
     }
@@ -80,4 +113,9 @@
     public String toString() {
         return "Connection[ " + from.toString() + " - " + to.toString() + "]";
     }
+
+    @Override
+    public boolean isVIP() {
+        return isBold;
+    }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/BlockWidget.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/BlockWidget.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -31,6 +31,7 @@
 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;
@@ -41,13 +42,13 @@
  */
 public class BlockWidget extends LabelWidget implements Vertex {
 
-    public static final Dimension SIZE = new Dimension(20, 20);
+    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.SERIF, Font.PLAIN, 12);
+    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;
@@ -59,29 +60,24 @@
         this.setLabel(block.getName());
         this.setForeground(NORMAL_FOREGROUND_COLOR);
         this.setBorder(BorderFactory.createLineBorder(1, NORMAL_FOREGROUND_COLOR));
-        this.setMinimumSize(SIZE);
-        this.setMaximumSize(SIZE);
+        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) (SIZE.getWidth() / 2), (int) (SIZE.getHeight() / 2));
+                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) (SIZE.getWidth() / 2), (int) (SIZE.getHeight() / 2));
+                return new Point((int) (getSize().getWidth() / 2), (int) (getSize().getHeight() / 2));
             }
-
             public Vertex getVertex() {
                 return widget;
             }
@@ -101,7 +97,12 @@
     }
 
     public Dimension getSize() {
-        return SIZE;
+        Rectangle bounds = getBounds();
+        if (bounds != null) {
+            return bounds.getSize();
+        } else {
+            return MIN_SIZE;
+        }
     }
 
     public void setPosition(Point p) {
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/Bundle.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/Bundle.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,4 +1,4 @@
-CTL_ControlFlowAction=Open ControlFlow Window
-CTL_ControlFlowTopComponent=ControlFlow Window
-HINT_ControlFlowTopComponent=This is a ControlFlow window
+CTL_ControlFlowAction=Control Flow
+CTL_ControlFlowTopComponent=Control Flow
+HINT_ControlFlowTopComponent=Shows the blocks of the current graph.
 OpenIDE-Module-Name=ControlFlow
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowScene.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowScene.java	Fri May 08 13:25:11 2015 -0400
@@ -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,17 +23,17 @@
  */
 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.InputBlockEdge;
 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.HashMap;
 import java.util.Set;
 import javax.swing.BorderFactory;
 import org.netbeans.api.visual.action.ActionFactory;
@@ -44,15 +44,14 @@
 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.layout.LayoutFactory;
 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;
-import org.openide.util.Lookup;
 
 /**
  *
@@ -61,13 +60,12 @@
 public class ControlFlowScene extends GraphScene<InputBlock, InputBlockEdge> implements SelectProvider, MoveProvider, RectangularSelectDecorator, RectangularSelectProvider {
 
     private HashSet<BlockWidget> selection;
-    private HashMap<InputBlock, BlockWidget> blockMap;
     private InputGraph oldGraph;
     private LayerWidget edgeLayer;
     private LayerWidget mainLayer;
     private LayerWidget selectLayer;
     private WidgetAction hoverAction = this.createWidgetHoverAction();
-    private WidgetAction selectAction = ActionFactory.createSelectAction(this);
+    private WidgetAction selectAction = new DoubleClickSelectAction(this);
     private WidgetAction moveAction = ActionFactory.createMoveAction(null, this);
 
     public ControlFlowScene() {
@@ -111,27 +109,21 @@
             addNode(b);
         }
 
-        for (InputBlock b : g.getBlocks()) {
-            for (InputBlockEdge e : b.getOutputs()) {
-                addEdge(e);
-                assert g.getBlocks().contains(e.getFrom());
-                assert g.getBlocks().contains(e.getTo());
-                this.setEdgeSource(e, e.getFrom());
-                this.setEdgeTarget(e, e.getTo());
-            }
+        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 layout = new HierarchicalGraphLayout();//GridGraphLayout();
+        GraphLayout<InputBlock, InputBlockEdge> layout = new HierarchicalGraphLayout<InputBlock, InputBlockEdge>();//GridGraphLayout();
         SceneLayout sceneLayout = LayoutFactory.createSceneGraphLayout(this, layout);
         sceneLayout.invokeLayout();
 
         this.validate();
     }
 
-    public BlockWidget getBlockWidget(InputBlock b) {
-        return blockMap.get(b);
-    }
-
     public void clearSelection() {
         for (BlockWidget w : selection) {
             w.setState(w.getState().deriveSelected(false));
@@ -141,7 +133,7 @@
     }
 
     public void selectionChanged() {
-        InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class);
+        InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//)Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
         if (p != null) {
             Set<InputNode> inputNodes = new HashSet<InputNode>();
             for (BlockWidget w : selection) {
@@ -204,15 +196,19 @@
     }
 
     public void setNewLocation(Widget widget, Point location) {
-        Point originalLocation = getOriginalLocation(widget);
-        int xOffset = location.x - originalLocation.x;
-        int yOffset = location.y - originalLocation.y;
-        for (Widget w : this.selection) {
-            Point p = new Point(w.getPreferredLocation());
-            p.translate(xOffset, yOffset);
-            w.setPreferredLocation(p);
+        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() {
@@ -271,7 +267,15 @@
     }
 
     protected Widget attachEdgeWidget(InputBlockEdge edge) {
-        ConnectionWidget w = new BlockConnectionWidget(this, 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);
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponent.form	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponent.form	Fri May 08 13:25:11 2015 -0400
@@ -3,6 +3,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"/>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponent.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowTopComponent.java	Fri May 08 13:25:11 2015 -0400
@@ -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,6 +25,7 @@
 
 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;
@@ -63,17 +64,7 @@
         this.add(panel, BorderLayout.CENTER);
     }
 
-    @Override
-    public void requestFocus() {
-        super.requestFocus();
-        scene.getView().requestFocus();
-    }
 
-    @Override
-    public boolean requestFocusInWindow() {
-        super.requestFocusInWindow();
-        return scene.getView().requestFocusInWindow();
-    }
 
     /** This method is called from within the constructor to
      * initialize the form.
@@ -96,6 +87,7 @@
     }// </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.
@@ -131,7 +123,7 @@
 
     @Override
     public void componentOpened() {
-        Lookup.Template tpl = new Lookup.Template(Object.class);
+        Lookup.Template<InputGraphProvider> tpl = new Lookup.Template<InputGraphProvider>(InputGraphProvider.class);
         result = Utilities.actionsGlobalContext().lookup(tpl);
         result.addLookupListener(this);
     }
@@ -143,16 +135,16 @@
     }
 
     public void resultChanged(LookupEvent lookupEvent) {
-
-        final InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class);
+        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);
-            }
-        }
+                    InputGraph g = p.getGraph();
+                    if (g != null) {
+                        scene.setGraph(g);
+                    }
+                }
             });
         }
     }
@@ -169,8 +161,8 @@
 
     @Override
     public void requestActive() {
-        scene.getView().requestFocusInWindow();
         super.requestActive();
+        scene.getView().requestFocus();
     }
 
     final static class ResolvableHelper implements Serializable {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/DoubleClickSelectAction.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011, 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 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;
+    }
+}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/HierarchicalGraphLayout.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/HierarchicalGraphLayout.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -34,7 +34,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -76,6 +76,10 @@
         public void setControlPoints(List<Point> list) {
         // Do nothing for now
         }
+
+        public boolean isVIP() {
+            return false;
+        }
     }
 
     private class VertexWrapper implements Vertex {
@@ -127,6 +131,7 @@
         }
 
         public int compareTo(Vertex o) {
+            @SuppressWarnings("unchecked")
             VertexWrapper vw = (VertexWrapper) o;
             return node.toString().compareTo(vw.node.toString());
         }
@@ -138,8 +143,8 @@
 
     protected void performGraphLayout(UniversalGraph<N, E> graph) {
 
-        Set<LinkWrapper> links = new HashSet<LinkWrapper>();
-        Set<VertexWrapper> vertices = new HashSet<VertexWrapper>();
+        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()) {
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/nbproject/project.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/nbproject/project.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/nbproject/project.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/nbproject/project.xml	Fri May 08 13:25:11 2015 -0400
@@ -1,126 +1,142 @@
-<?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.coordinator</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.difference</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.settings</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.netbeans.api.progress</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <release-version>1</release-version>
-                        <specification-version>1.10.0.1</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>org.openide.actions</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>6.6.1.1</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>org.openide.awt</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>6.11.0.1</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>org.openide.dialogs</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>7.5.1</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>org.openide.explorer</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>6.11</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>org.openide.filesystems</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>7.3</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>org.openide.loaders</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>6.7</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>org.openide.nodes</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>7.2.0.1</specification-version>
-                    </run-dependency>
-                </dependency>
-                <dependency>
-                    <code-name-base>org.openide.util</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>7.9.0.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>
+<?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.coordinator</code-name-base>
+            <suite-component/>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>com.sun.hotspot.igv.connection</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.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.difference</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.settings</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.netbeans.api.progress</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.23.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.actions</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>6.21.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.awt</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.30.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.dialogs</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.18.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.explorer</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>6.34.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.filesystems</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.46.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.loaders</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.20.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.nodes</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.20.1</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.39.1</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages/>
+        </data>
+    </configuration>
+</project>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/META-INF/services/com.sun.hotspot.igv.data.services.GroupOrganizer	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-com.sun.hotspot.igv.coordinator.StandardGroupOrganizer
-com.sun.hotspot.igv.coordinator.GraphCountGroupOrganizer
\ No newline at end of file
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/Bundle.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/Bundle.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,7 +1,6 @@
-
-AdvancedOption_DisplayName_Coordinator=Settings
-AdvancedOption_Tooltip_Coordinator=Visualization Tool Settings
-CTL_OutlineTopComponent=Outline Window
-CTL_SomeAction=test
-HINT_OutlineTopComponent=This is a Outline window
-OpenIDE-Module-Name=Coordinator
+AdvancedOption_DisplayName_Coordinator=Settings
+AdvancedOption_Tooltip_Coordinator=Visualization Tool Settings
+CTL_OutlineTopComponent=Outline
+CTL_SomeAction=test
+HINT_OutlineTopComponent=Displays loaded groups of graphs.
+OpenIDE-Module-Name=Coordinator
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/FolderNode.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/FolderNode.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -24,18 +24,13 @@
 package com.sun.hotspot.igv.coordinator;
 
 import com.sun.hotspot.igv.coordinator.actions.RemoveCookie;
-import com.sun.hotspot.igv.data.ChangedListener;
-import com.sun.hotspot.igv.data.Group;
-import com.sun.hotspot.igv.data.services.GroupOrganizer;
-import com.sun.hotspot.igv.data.InputGraph;
-import com.sun.hotspot.igv.data.Pair;
+import com.sun.hotspot.igv.data.*;
 import java.awt.Image;
-import java.util.ArrayList;
 import java.util.List;
 import org.openide.nodes.AbstractNode;
 import org.openide.nodes.Children;
 import org.openide.nodes.Node;
-import org.openide.util.Utilities;
+import org.openide.util.ImageUtilities;
 import org.openide.util.lookup.AbstractLookup;
 import org.openide.util.lookup.InstanceContent;
 
@@ -45,107 +40,72 @@
  */
 public class FolderNode extends AbstractNode {
 
-    private GroupOrganizer organizer;
     private InstanceContent content;
-    private List<Pair<String, List<Group>>> structure;
-    private List<String> subFolders;
     private FolderChildren children;
 
-    private static class FolderChildren extends Children.Keys implements ChangedListener<Group> {
+    private static class FolderChildren extends Children.Keys<FolderElement> implements ChangedListener {
+
+        private final Folder folder;
 
-        private FolderNode parent;
-        private List<Group> registeredGroups;
-
-        public void setParent(FolderNode parent) {
-            this.parent = parent;
-            this.registeredGroups = new ArrayList<Group>();
+        public FolderChildren(Folder folder) {
+            this.folder = folder;
+            folder.getChangedEvent().addListener(this);
         }
 
         @Override
-        protected Node[] createNodes(Object arg0) {
-
-            for(Group g : registeredGroups) {
-                g.getChangedEvent().removeListener(this);
-            }
-            registeredGroups.clear();
-
-            Pair<String, List<Group>> p = (Pair<String, List<Group>>) arg0;
-            if (p.getLeft().length() == 0) {
-
-                List<Node> curNodes = new ArrayList<Node>();
-                for (Group g : p.getRight()) {
-                    for (InputGraph graph : g.getGraphs()) {
-                        curNodes.add(new GraphNode(graph));
-                    }
-                    g.getChangedEvent().addListener(this);
-                    registeredGroups.add(g);
-                }
-
-                Node[] result = new Node[curNodes.size()];
-                for (int i = 0; i < curNodes.size(); i++) {
-                    result[i] = curNodes.get(i);
-                }
-                return result;
-
-            } else {
-                return new Node[]{new FolderNode(p.getLeft(), parent.organizer, parent.subFolders, p.getRight())};
+        protected Node[] createNodes(FolderElement e) {
+             if (e instanceof InputGraph) {
+                return new Node[]{new GraphNode((InputGraph) e)};
+            } else if (e instanceof Folder) {
+                 return new Node[]{new FolderNode((Folder) e)};
+             } else {
+                return null;
             }
         }
 
         @Override
         public void addNotify() {
-            this.setKeys(parent.structure);
+            this.setKeys(folder.getElements());
         }
 
-        public void changed(Group source) {
-            List<Pair<String, List<Group>>> newStructure = new ArrayList<Pair<String, List<Group>>>();
-            for(Pair<String, List<Group>> p : parent.structure) {
-                refreshKey(p);
-            }
-        }
-    }
-
-    protected InstanceContent getContent() {
-        return content;
+        @Override
+        public void changed(Object source) {
+            addNotify();
+         }
     }
 
     @Override
     public Image getIcon(int i) {
-        return Utilities.loadImage("com/sun/hotspot/igv/coordinator/images/folder.gif");
+        return ImageUtilities.loadImage("com/sun/hotspot/igv/coordinator/images/folder.png");
     }
 
-    protected FolderNode(String name, GroupOrganizer organizer, List<String> subFolders, List<Group> groups) {
-        this(name, organizer, subFolders, groups, new FolderChildren(), new InstanceContent());
+    protected FolderNode(Folder folder) {
+        this(folder, new FolderChildren(folder), new InstanceContent());
     }
 
-    private FolderNode(String name, GroupOrganizer organizer, List<String> oldSubFolders, final List<Group> groups, FolderChildren children, InstanceContent content) {
+    private FolderNode(final Folder folder, FolderChildren children, InstanceContent content) {
         super(children, new AbstractLookup(content));
-        children.setParent(this);
         this.content = content;
         this.children = children;
-        content.add(new RemoveCookie() {
-
-            public void remove() {
-                for (Group g : groups) {
-                    if (g.getDocument() != null) {
-                        g.getDocument().removeGroup(g);
-                    }
+        if (folder instanceof FolderElement) {
+            final FolderElement folderElement = (FolderElement) folder;
+            this.setDisplayName(folderElement.getName());
+            content.add(new RemoveCookie() {
+                @Override
+                public void remove() {
+                    folderElement.getParent().removeElement(folderElement);
                 }
-            }
-        });
-        init(name, organizer, oldSubFolders, groups);
+            });
+        }
     }
 
-    public void init(String name, GroupOrganizer organizer, List<String> oldSubFolders, List<Group> groups) {
+    public void init(String name, List<Group> groups) {
         this.setDisplayName(name);
-        this.organizer = organizer;
-        this.subFolders = new ArrayList<String>(oldSubFolders);
-        if (name.length() > 0) {
-            this.subFolders.add(name);
+        children.addNotify();
+
+        for (Group g : groups) {
+            content.add(g);
         }
-        structure = organizer.organize(subFolders, groups);
-        assert structure != null;
-        children.addNotify();
     }
 
     @Override
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/GraphCountGroupOrganizer.java	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 1998, 2007, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.coordinator;
-
-import com.sun.hotspot.igv.data.Group;
-import com.sun.hotspot.igv.data.Pair;
-import com.sun.hotspot.igv.data.services.GroupOrganizer;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class GraphCountGroupOrganizer implements GroupOrganizer {
-
-    public String getName() {
-        return "Graph count structure";
-    }
-
-    public List<Pair<String, List<Group>>> organize(List<String> subFolders, List<Group> groups) {
-
-        List<Pair<String, List<Group>>> result = new ArrayList<Pair<String, List<Group>>>();
-
-        if (subFolders.size() == 0) {
-            Map<Integer, List<Group>> map = new HashMap<Integer, List<Group>>();
-            for (Group g : groups) {
-                Integer cur = g.getGraphs().size();
-                if (!map.containsKey(cur)) {
-                    map.put(cur, new ArrayList<Group>());
-                }
-                map.get(cur).add(g);
-            }
-
-            SortedSet<Integer> keys = new TreeSet<Integer>(map.keySet());
-            for (Integer i : keys) {
-                result.add(new Pair<String, List<Group>>("Graph count " + i, map.get(i)));
-            }
-
-        } else if (subFolders.size() == 1) {
-            for (Group g : groups) {
-                List<Group> children = new ArrayList<Group>();
-                children.add(g);
-                Pair<String, List<Group>> p = new Pair<String, List<Group>>();
-                p.setLeft(g.getName());
-                p.setRight(children);
-                result.add(p);
-            }
-        } else if (subFolders.size() == 2) {
-            result.add(new Pair<String, List<Group>>("", groups));
-        }
-
-        return result;
-    }
-}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/GraphNode.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/GraphNode.java	Fri May 08 13:25:11 2015 -0400
@@ -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,23 +23,27 @@
  */
 package com.sun.hotspot.igv.coordinator;
 
+import com.sun.hotspot.igv.coordinator.actions.CloneGraphAction;
 import com.sun.hotspot.igv.coordinator.actions.DiffGraphAction;
 import com.sun.hotspot.igv.coordinator.actions.DiffGraphCookie;
-import com.sun.hotspot.igv.coordinator.actions.RemoveCookie;
+import com.sun.hotspot.igv.coordinator.actions.GraphCloneCookie;
+import com.sun.hotspot.igv.coordinator.actions.GraphOpenCookie;
+import com.sun.hotspot.igv.coordinator.actions.GraphRemoveCookie;
 import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.Properties;
 import com.sun.hotspot.igv.data.services.GraphViewer;
-import com.sun.hotspot.igv.data.services.InputGraphProvider;
 import com.sun.hotspot.igv.util.PropertiesSheet;
 import java.awt.Image;
 import javax.swing.Action;
 import org.openide.actions.OpenAction;
-import org.openide.cookies.OpenCookie;
 import org.openide.nodes.AbstractNode;
 import org.openide.nodes.Children;
-import org.openide.nodes.Node;
+import org.openide.nodes.NodeAdapter;
+import org.openide.nodes.NodeEvent;
+import org.openide.nodes.NodeMemberEvent;
 import org.openide.nodes.Sheet;
+import org.openide.util.ImageUtilities;
 import org.openide.util.Lookup;
-import org.openide.util.Utilities;
 import org.openide.util.lookup.AbstractLookup;
 import org.openide.util.lookup.InstanceContent;
 
@@ -48,7 +52,6 @@
  * @author Thomas Wuerthinger
  */
 public class GraphNode extends AbstractNode {
-
     private InputGraph graph;
 
     /** Creates a new instance of GraphNode */
@@ -56,7 +59,7 @@
         this(graph, new InstanceContent());
     }
 
-    private GraphNode(final InputGraph graph, InstanceContent content) {
+    private GraphNode(InputGraph graph, InstanceContent content) {
         super(Children.LEAF, new AbstractLookup(content));
         this.graph = graph;
         this.setDisplayName(graph.getName());
@@ -66,19 +69,22 @@
 
         if (viewer != null) {
             // Action for opening the graph
-            content.add(new OpenCookie() {
-
-                public void open() {
-                    viewer.view(graph);
-                }
-            });
+            content.add(new GraphOpenCookie(viewer, graph));
         }
 
         // Action for removing a graph
-        content.add(new RemoveCookie() {
+        content.add(new GraphRemoveCookie(graph));
+
+        // Action for diffing to the current graph
+        content.add(new DiffGraphCookie(graph));
 
-            public void remove() {
-                graph.getGroup().removeGraph(graph);
+        // Action for cloning to the current graph
+        content.add(new GraphCloneCookie(viewer, graph));
+
+        this.addNodeListener(new NodeAdapter() {
+            @Override
+            public void childrenRemoved(NodeMemberEvent ev) {
+                GraphNode.this.graph = null;
             }
         });
     }
@@ -86,13 +92,17 @@
     @Override
     protected Sheet createSheet() {
         Sheet s = super.createSheet();
-        PropertiesSheet.initializeSheet(graph.getProperties(), s);
+        Properties p = new Properties();
+        p.add(graph.getProperties());
+        p.setProperty("nodeCount", Integer.toString(graph.getNodes().size()));
+        p.setProperty("edgeCount", Integer.toString(graph.getEdges().size()));
+        PropertiesSheet.initializeSheet(p, s);
         return s;
     }
 
     @Override
     public Image getIcon(int i) {
-        return Utilities.loadImage("com/sun/hotspot/igv/coordinator/images/graph.gif");
+        return ImageUtilities.loadImage("com/sun/hotspot/igv/coordinator/images/graph.png");
     }
 
     @Override
@@ -101,30 +111,28 @@
     }
 
     @Override
-    public <T extends Node.Cookie> T getCookie(Class<T> aClass) {
-        if (aClass == DiffGraphCookie.class) {
-            InputGraphProvider graphProvider = Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
-
-            InputGraph graphA = null;
-            if (graphProvider != null) {
-                graphA = graphProvider.getGraph();
-            }
-
-            if (graphA != null && !graphA.isDifferenceGraph()) {
-                return (T) new DiffGraphCookie(graphA, graph);
-            }
-        }
-
-        return super.getCookie(aClass);
-    }
-
-    @Override
     public Action[] getActions(boolean b) {
-        return new Action[]{(Action) DiffGraphAction.findObject(DiffGraphAction.class, true), (Action) OpenAction.findObject(OpenAction.class, true)};
+        return new Action[]{(Action) DiffGraphAction.findObject(DiffGraphAction.class, true), (Action) CloneGraphAction.findObject(CloneGraphAction.class, true), (Action) OpenAction.findObject(OpenAction.class, true)};
     }
 
     @Override
     public Action getPreferredAction() {
         return (Action) OpenAction.findObject(OpenAction.class, true);
     }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof GraphNode) {
+            return (graph == ((GraphNode) obj).graph);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return graph.hashCode();
+    }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.form	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.form	Fri May 08 13:25:11 2015 -0400
@@ -3,6 +3,8 @@
 <Form version="1.2" maxVersion="1.2" 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"/>
@@ -14,28 +16,17 @@
 
   <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
   <SubComponents>
-    <Container class="javax.swing.JPanel" name="jPanel2">
+    <Container class="javax.swing.JScrollPane" name="treeView">
+      <AuxValues>
+        <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new BeanTreeView();"/>
+      </AuxValues>
       <Constraints>
         <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
           <BorderConstraints direction="Center"/>
         </Constraint>
       </Constraints>
 
-      <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
-      <SubComponents>
-        <Container class="javax.swing.JScrollPane" name="jScrollPane1">
-          <AuxValues>
-            <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new BeanTreeView();"/>
-          </AuxValues>
-          <Constraints>
-            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
-              <BorderConstraints direction="Center"/>
-            </Constraint>
-          </Constraints>
-
-          <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
-        </Container>
-      </SubComponents>
+      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
     </Container>
   </SubComponents>
 </Form>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java	Fri May 08 13:25:11 2015 -0400
@@ -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,37 +23,25 @@
  */
 package com.sun.hotspot.igv.coordinator;
 
-import com.sun.hotspot.igv.coordinator.actions.ImportAction;
-import com.sun.hotspot.igv.coordinator.actions.RemoveAction;
-import com.sun.hotspot.igv.coordinator.actions.RemoveAllAction;
-import com.sun.hotspot.igv.coordinator.actions.SaveAllAction;
-import com.sun.hotspot.igv.coordinator.actions.SaveAsAction;
-import com.sun.hotspot.igv.coordinator.actions.StructuredViewAction;
+import com.sun.hotspot.igv.connection.Server;
+import com.sun.hotspot.igv.coordinator.actions.*;
 import com.sun.hotspot.igv.data.GraphDocument;
-import com.sun.hotspot.igv.data.ChangedListener;
 import com.sun.hotspot.igv.data.Group;
 import com.sun.hotspot.igv.data.services.GroupCallback;
-import com.sun.hotspot.igv.data.services.GroupOrganizer;
-import com.sun.hotspot.igv.data.services.GroupReceiver;
 import java.awt.BorderLayout;
-import java.awt.Component;
 import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
 import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collection;
-import javax.swing.BoxLayout;
-import javax.swing.JPanel;
 import javax.swing.UIManager;
 import javax.swing.border.Border;
 import org.openide.ErrorManager;
+import org.openide.actions.GarbageCollectAction;
 import org.openide.awt.Toolbar;
 import org.openide.awt.ToolbarPool;
 import org.openide.explorer.ExplorerManager;
 import org.openide.explorer.ExplorerUtils;
 import org.openide.explorer.view.BeanTreeView;
-import org.openide.util.Lookup;
 import org.openide.util.LookupEvent;
 import org.openide.util.LookupListener;
 import org.openide.util.NbBundle;
@@ -72,7 +60,8 @@
     private ExplorerManager manager;
     private GraphDocument document;
     private FolderNode root;
-    private GroupOrganizer organizer;
+    private Server server;
+    private Server binaryServer;
 
     private OutlineTopComponent() {
         initComponents();
@@ -88,17 +77,9 @@
 
     private void initListView() {
         manager = new ExplorerManager();
-        organizer = new StandardGroupOrganizer();
-        root = new FolderNode("", organizer, new ArrayList<String>(), document.getGroups());
+        root = new FolderNode(document);
         manager.setRootContext(root);
-        ((BeanTreeView) this.jScrollPane1).setRootVisible(false);
-
-        document.getChangedEvent().addListener(new ChangedListener<GraphDocument>() {
-
-            public void changed(GraphDocument document) {
-                updateStructure();
-            }
-        });
+        ((BeanTreeView) this.treeView).setRootVisible(false);
 
         associateLookup(ExplorerUtils.createLookup(manager, getActionMap()));
     }
@@ -111,61 +92,41 @@
         this.add(toolbar, BorderLayout.NORTH);
 
         toolbar.add(ImportAction.get(ImportAction.class));
-        toolbar.add(((NodeAction) RemoveAction.get(RemoveAction.class)).createContextAwareInstance(this.getLookup()));
-        toolbar.add(RemoveAllAction.get(RemoveAllAction.class));
 
         toolbar.add(((NodeAction) SaveAsAction.get(SaveAsAction.class)).createContextAwareInstance(this.getLookup()));
         toolbar.add(SaveAllAction.get(SaveAllAction.class));
 
-        toolbar.add(StructuredViewAction.get(StructuredViewAction.class).getToolbarPresenter());
+        toolbar.add(((NodeAction) RemoveAction.get(RemoveAction.class)).createContextAwareInstance(this.getLookup()));
+        toolbar.add(RemoveAllAction.get(RemoveAllAction.class));
+
+        toolbar.add(GarbageCollectAction.get(GarbageCollectAction.class).getToolbarPresenter());
 
         for (Toolbar tb : ToolbarPool.getDefault().getToolbars()) {
             tb.setVisible(false);
         }
-
-        initOrganizers();
-    }
-
-    public void setOrganizer(GroupOrganizer organizer) {
-        this.organizer = organizer;
-        updateStructure();
-    }
-
-    private void initOrganizers() {
-
     }
 
     private void initReceivers() {
 
         final GroupCallback callback = new GroupCallback() {
 
+            @Override
             public void started(Group g) {
-                getDocument().addGroup(g);
+                synchronized(OutlineTopComponent.this) {
+                    getDocument().addElement(g);
+                }
             }
         };
 
-        Collection<? extends GroupReceiver> receivers = Lookup.getDefault().lookupAll(GroupReceiver.class);
-        if (receivers.size() > 0) {
-            JPanel panel = new JPanel();
-            panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
-
-            for (GroupReceiver r : receivers) {
-                Component c = r.init(callback);
-                panel.add(c);
-            }
-
-            jPanel2.add(panel, BorderLayout.PAGE_START);
-        }
-    }
-
-    private void updateStructure() {
-        root.init("", organizer, new ArrayList<String>(), document.getGroups());
+        server = new Server(getDocument(), callback, false);
+        binaryServer = new Server(getDocument(), callback, true);
     }
 
     public void clear() {
         document.clear();
     }
 
+    @Override
     public ExplorerManager getExplorerManager() {
         return manager;
     }
@@ -221,6 +182,25 @@
         return PREFERRED_ID;
     }
 
+    @Override
+    public void requestActive() {
+        super.requestActive();
+        treeView.requestFocus();
+    }
+
+    @Override
+    public boolean requestFocus(boolean temporary) {
+        treeView.requestFocus();
+        return super.requestFocus(temporary);
+    }
+
+    @Override
+    protected boolean requestFocusInWindow(boolean temporary) {
+        treeView.requestFocus();
+        return super.requestFocusInWindow(temporary);
+    }
+
+    @Override
     public void resultChanged(LookupEvent lookupEvent) {
     }
 
@@ -228,7 +208,7 @@
     public void readExternal(ObjectInput objectInput) throws IOException, ClassNotFoundException {
         // Not called when user starts application for the first time
         super.readExternal(objectInput);
-        ((BeanTreeView) this.jScrollPane1).setRootVisible(false);
+        ((BeanTreeView) this.treeView).setRootVisible(false);
     }
 
     @Override
@@ -253,19 +233,13 @@
     // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
     private void initComponents() {
 
-        jPanel2 = new javax.swing.JPanel();
-        jScrollPane1 = new BeanTreeView();
+        treeView = new BeanTreeView();
 
         setLayout(new java.awt.BorderLayout());
-
-        jPanel2.setLayout(new java.awt.BorderLayout());
-        jPanel2.add(jScrollPane1, java.awt.BorderLayout.CENTER);
-
-        add(jPanel2, java.awt.BorderLayout.CENTER);
+        add(treeView, java.awt.BorderLayout.CENTER);
     }// </editor-fold>//GEN-END:initComponents
 
     // Variables declaration - do not modify//GEN-BEGIN:variables
-    private javax.swing.JPanel jPanel2;
-    private javax.swing.JScrollPane jScrollPane1;
+    private javax.swing.JScrollPane treeView;
     // End of variables declaration//GEN-END:variables
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/StandardConfiguration.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/StandardConfiguration.xml	Fri May 08 13:25:11 2015 -0400
@@ -4,7 +4,7 @@
     <Row>
         <Toolbar name="Edit" position="1" visible="false"/>
         <Toolbar name="File" position="1" visible="false" />
-        <Toolbar name="Memory" position="1" visible="false" />
+        <Toolbar name="Memory" position="1" visible="true" />
     </Row>
     <Row>
         <Toolbar name="WorkspaceSwitcher" />
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/StandardGroupOrganizer.java	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 1998, 2007, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.coordinator;
-
-import com.sun.hotspot.igv.data.Group;
-import com.sun.hotspot.igv.data.services.GroupOrganizer;
-import com.sun.hotspot.igv.data.Pair;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class StandardGroupOrganizer implements GroupOrganizer {
-
-    public String getName() {
-        return "-- None --";
-    }
-
-    public List<Pair<String, List<Group>>> organize(List<String> subFolders, List<Group> groups) {
-
-        List<Pair<String, List<Group>>> result = new ArrayList<Pair<String, List<Group>>>();
-
-        if (groups.size() == 1 && subFolders.size() > 0) {
-            result.add(new Pair<String, List<Group>>("", groups));
-        } else {
-            for (Group g : groups) {
-                List<Group> children = new ArrayList<Group>();
-                children.add(g);
-                Pair<String, List<Group>> p = new Pair<String, List<Group>>();
-                p.setLeft(g.getName());
-                p.setRight(children);
-                result.add(p);
-            }
-        }
-
-        return result;
-    }
-}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/Bundle.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/Bundle.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,18 +1,10 @@
-CTL_EditFilterAction=Edit...
 CTL_ImportAction=Open...
 CTL_OpenGraphAction=View graph
 CTL_DiffGraphAction=Difference to current graph
-CTL_RemoveAction=Remove methods
-CTL_ApplyFilterAction=Apply
-CTL_FilterAction=Open Filter Window
-CTL_AppliedFilterAction=Open AppliedFilter Window
-CTL_OutlineAction=Open Outline Window
-CTL_MoveFilterUpAction=Move upwards
-CTL_MoveFilterDownAction=Move downwards
-CTL_RemoveFilterAction=Remove
-CTL_RemoveFilterSettingsAction=Remove filter setting
-CTL_SaveAsAction=Save selected methods...
-CTL_SaveAllAction=Save all...
-CTL_SaveFilterSettingsAction=Save filter settings...
-CTL_PropertiesAction=Open Properties Window
+CTL_RemoveAction=Remove selected graphs and groups
+CTL_RemoveAllAction=Remove all graphs and groups
+CTL_OutlineAction=Outline
+CTL_SaveAsAction=Save selected groups...
+CTL_SaveAllAction=Save all groups...
+CTL_PropertiesAction=Open Properties Window 
 CTL_NewFilterAction=New filter...
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/CloneGraphAction.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013, 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.coordinator.actions;
+
+import org.openide.nodes.Node;
+import org.openide.util.HelpCtx;
+import org.openide.util.actions.CookieAction;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public final class CloneGraphAction extends CookieAction {
+
+    @Override
+    protected void performAction(Node[] activatedNodes) {
+        GraphCloneCookie c = activatedNodes[0].getCookie(GraphCloneCookie.class);
+        assert c != null;
+        c.openClone();
+    }
+
+    @Override
+    protected int mode() {
+        return CookieAction.MODE_EXACTLY_ONE;
+    }
+
+    @Override
+    protected boolean enable(Node[] activatedNodes) {
+        boolean b = super.enable(activatedNodes);
+        if (b) {
+            assert activatedNodes.length == 1;
+            GraphCloneCookie c = activatedNodes[0].getCookie(GraphCloneCookie.class);
+            assert c != null;
+            return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    public String getName() {
+        return "Open clone";
+    }
+
+    @Override
+    protected Class<?>[] cookieClasses() {
+        return new Class<?>[]{
+            GraphCloneCookie.class
+        };
+    }
+
+    @Override
+    protected String iconResource() {
+        return "com/sun/hotspot/igv/coordinator/images/graph.png";
+    }
+
+    @Override
+    public HelpCtx getHelpCtx() {
+        return HelpCtx.DEFAULT_HELP;
+    }
+
+    @Override
+    protected boolean asynchronous() {
+        return false;
+    }
+}
+
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/DiffGraphAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/DiffGraphAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -35,30 +35,49 @@
  */
 public final class DiffGraphAction extends CookieAction {
 
+    @Override
     protected void performAction(Node[] activatedNodes) {
         DiffGraphCookie c = activatedNodes[0].getCookie(DiffGraphCookie.class);
+        assert c != null;
         c.openDiff();
     }
 
+    @Override
     protected int mode() {
         return CookieAction.MODE_EXACTLY_ONE;
     }
 
+    @Override
+    protected boolean enable(Node[] activatedNodes) {
+        boolean b = super.enable(activatedNodes);
+        if (b) {
+            assert activatedNodes.length == 1;
+            DiffGraphCookie c = activatedNodes[0].getCookie(DiffGraphCookie.class);
+            assert c != null;
+            return c.isPossible();
+        }
+
+        return false;
+    }
+
+    @Override
     public String getName() {
         return NbBundle.getMessage(DiffGraphAction.class, "CTL_DiffGraphAction");
     }
 
-    protected Class[] cookieClasses() {
-        return new Class[]{
+    @Override
+    protected Class<?>[] cookieClasses() {
+        return new Class<?>[]{
             DiffGraphCookie.class
         };
     }
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/coordinator/images/diff.gif";
+        return "com/sun/hotspot/igv/coordinator/images/diff.png";
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
@@ -68,3 +87,4 @@
         return false;
     }
 }
+
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/DiffGraphCookie.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/DiffGraphCookie.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -21,12 +21,13 @@
  * questions.
  *
  */
-
 package com.sun.hotspot.igv.coordinator.actions;
 
 import com.sun.hotspot.igv.data.InputGraph;
 import com.sun.hotspot.igv.data.services.GraphViewer;
+import com.sun.hotspot.igv.data.services.InputGraphProvider;
 import com.sun.hotspot.igv.difference.Difference;
+import com.sun.hotspot.igv.util.LookupHistory;
 import org.openide.nodes.Node;
 import org.openide.util.Lookup;
 
@@ -36,21 +37,30 @@
  */
 public class DiffGraphCookie implements Node.Cookie {
 
-    private InputGraph a;
-    private InputGraph b;
+    private InputGraph graph;
+
+    public DiffGraphCookie(InputGraph graph) {
+        this.graph = graph;
+    }
 
-    public DiffGraphCookie(InputGraph a, InputGraph b) {
-        this.a = a;
-        this.b = b;
+    private InputGraph getCurrentGraph() {
+        InputGraphProvider graphProvider = LookupHistory.getLast(InputGraphProvider.class);
+        if (graphProvider != null) {
+            return graphProvider.getGraph();
+        }
+        return null;
+    }
+
+    public boolean isPossible() {
+        return getCurrentGraph() != null;
     }
 
     public void openDiff() {
-
+        InputGraph other = getCurrentGraph();
         final GraphViewer viewer = Lookup.getDefault().lookup(GraphViewer.class);
-
-        if(viewer != null) {
-            InputGraph diffGraph = Difference.createDiffGraph(a, b);
-            viewer.view(diffGraph);
+        if (viewer != null) {
+            InputGraph diffGraph = Difference.createDiffGraph(other, graph);
+            viewer.view(diffGraph, true);
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/GraphCloneCookie.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013, 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.coordinator.actions;
+
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.services.GraphViewer;
+import org.openide.nodes.Node;
+
+public class GraphCloneCookie implements Node.Cookie {
+
+    private final GraphViewer viewer;
+    private final InputGraph graph;
+
+    public GraphCloneCookie(GraphViewer viewer, InputGraph graph) {
+        this.viewer = viewer;
+        this.graph = graph;
+    }
+
+    public void openClone() {
+        viewer.view(graph, true);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/GraphOpenCookie.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2011, 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.coordinator.actions;
+
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.services.GraphViewer;
+import org.openide.cookies.OpenCookie;
+
+public class GraphOpenCookie implements OpenCookie {
+
+    private final GraphViewer viewer;
+    private final InputGraph graph;
+
+    public GraphOpenCookie(GraphViewer viewer, InputGraph graph) {
+        this.viewer = viewer;
+        this.graph = graph;
+    }
+
+    @Override
+    public void open() {
+        viewer.view(graph, false);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/GraphRemoveCookie.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2011, 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.coordinator.actions;
+
+import com.sun.hotspot.igv.data.InputGraph;
+
+public class GraphRemoveCookie implements RemoveCookie {
+    private final InputGraph graph;
+
+    public GraphRemoveCookie(InputGraph graph) {
+        this.graph = graph;
+    }
+
+    @Override
+    public void remove() {
+        graph.getGroup().removeElement(graph);
+    }
+}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/ImportAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/ImportAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -26,51 +26,54 @@
 
 import com.sun.hotspot.igv.coordinator.OutlineTopComponent;
 import com.sun.hotspot.igv.data.GraphDocument;
+import com.sun.hotspot.igv.data.serialization.BinaryParser;
+import com.sun.hotspot.igv.data.serialization.GraphParser;
+import com.sun.hotspot.igv.data.serialization.ParseMonitor;
 import com.sun.hotspot.igv.data.serialization.Parser;
 import com.sun.hotspot.igv.settings.Settings;
-import com.sun.hotspot.igv.data.serialization.XMLParser;
 import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.nio.channels.FileChannel;
+import java.nio.file.StandardOpenOption;
 import javax.swing.Action;
 import javax.swing.JFileChooser;
 import javax.swing.KeyStroke;
+import javax.swing.SwingUtilities;
 import javax.swing.filechooser.FileFilter;
 import org.netbeans.api.progress.ProgressHandle;
 import org.netbeans.api.progress.ProgressHandleFactory;
-import org.openide.DialogDisplayer;
-import org.openide.NotifyDescriptor;
+import org.openide.util.Exceptions;
 import org.openide.util.HelpCtx;
 import org.openide.util.NbBundle;
 import org.openide.util.RequestProcessor;
 import org.openide.util.actions.CallableSystemAction;
-import org.openide.xml.XMLUtil;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
 public final class ImportAction extends CallableSystemAction {
+    private static final int WORKUNITS = 10000;
 
     public static FileFilter getFileFilter() {
         return new FileFilter() {
 
+            @Override
             public boolean accept(File f) {
-                return f.getName().toLowerCase().endsWith(".xml") || f.isDirectory();
+                return f.getName().toLowerCase().endsWith(".xml") || f.getName().toLowerCase().endsWith(".bgv") || f.isDirectory();
             }
 
+            @Override
             public String getDescription() {
-                return "XML files (*.xml)";
+                return "Graph files (*.xml, *.bgv)";
             }
         };
     }
 
+    @Override
     public void performAction() {
 
         JFileChooser fc = new JFileChooser();
@@ -86,84 +89,79 @@
             }
 
             Settings.get().put(Settings.DIRECTORY, dir.getAbsolutePath());
-
             try {
-                final XMLReader reader = XMLUtil.createXMLReader();
-                final FileInputStream inputStream = new FileInputStream(file);
-                final InputSource is = new InputSource(inputStream);
-
+                final FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.READ);
                 final ProgressHandle handle = ProgressHandleFactory.createHandle("Opening file " + file.getName());
-                final int basis = 1000;
-                handle.start(basis);
-                final int start = inputStream.available();
-
-                final XMLParser.ParseMonitor parseMonitor = new XMLParser.ParseMonitor() {
-
-                    public void setProgress(double d) {
+                handle.start(WORKUNITS);
+                final long start = channel.size();
+                ParseMonitor monitor = new ParseMonitor() {
+                    @Override
+                    public void updateProgress() {
                         try {
-                            int curAvailable = inputStream.available();
-                            int prog = (int) (basis * (double) (start - curAvailable) / (double) start);
+                            int prog = (int) (WORKUNITS * (double) channel.position() / (double) start);
                             handle.progress(prog);
                         } catch (IOException ex) {
                         }
                     }
-
+                    @Override
                     public void setState(String state) {
-                        setProgress(0.0);
+                        updateProgress();
                         handle.progress(state);
                     }
                 };
-                final Parser parser = new Parser();
+                final GraphParser parser;
                 final OutlineTopComponent component = OutlineTopComponent.findInstance();
-
-                component.requestActive();
-
+                if (file.getName().endsWith(".xml")) {
+                    parser = new Parser(channel, monitor, null);
+                } else if (file.getName().endsWith(".bgv")) {
+                    parser = new BinaryParser(channel, monitor, component.getDocument(), null);
+                } else {
+                    parser = null;
+                }
                 RequestProcessor.getDefault().post(new Runnable() {
-
+                    @Override
                     public void run() {
-                        GraphDocument document = null;
                         try {
-                            document = parser.parse(reader, is, parseMonitor);
-                            parseMonitor.setState("Finishing");
-                            component.getDocument().addGraphDocument(document);
-                        } catch (SAXException ex) {
-                            String s = "Exception during parsing the XML file, could not load document!";
-                            if (ex instanceof XMLParser.MissingAttributeException) {
-                                XMLParser.MissingAttributeException e = (XMLParser.MissingAttributeException) ex;
-                                s += "\nMissing attribute \"" + e.getAttributeName() + "\"";
+                            final GraphDocument document = parser.parse();
+                            if (document != null) {
+                                SwingUtilities.invokeLater(new Runnable(){
+                                    @Override
+                                    public void run() {
+                                        component.requestActive();
+                                        component.getDocument().addGraphDocument(document);
+                                    }
+                                });
                             }
-                            ex.printStackTrace();
-                            NotifyDescriptor d = new NotifyDescriptor.Message(s, NotifyDescriptor.ERROR_MESSAGE);
-                            DialogDisplayer.getDefault().notify(d);
+                        } catch (IOException ex) {
+                            Exceptions.printStackTrace(ex);
                         }
                         handle.finish();
                     }
                 });
-
-            } catch (SAXException ex) {
-                ex.printStackTrace();
             } catch (FileNotFoundException ex) {
-                ex.printStackTrace();
+                Exceptions.printStackTrace(ex);
             } catch (IOException ex) {
-                ex.printStackTrace();
+                Exceptions.printStackTrace(ex);
             }
         }
     }
 
+    @Override
     public String getName() {
         return NbBundle.getMessage(ImportAction.class, "CTL_ImportAction");
     }
 
     public ImportAction() {
-        putValue(Action.SHORT_DESCRIPTION, "Open an XML graph document");
+        putValue(Action.SHORT_DESCRIPTION, "Open XML graph document...");
         putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK));
     }
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/coordinator/images/import.gif";
+        return "com/sun/hotspot/igv/coordinator/images/import.png";
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/OutlineAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/OutlineAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -24,7 +24,7 @@
 
 package com.sun.hotspot.igv.coordinator.actions;
 
-import com.sun.hotspot.igv.coordinator.*;
+import com.sun.hotspot.igv.coordinator.OutlineTopComponent;
 import java.awt.event.ActionEvent;
 import javax.swing.AbstractAction;
 import org.openide.util.NbBundle;
@@ -40,6 +40,7 @@
         super(NbBundle.getMessage(OutlineAction.class, "CTL_OutlineAction"));
     }
 
+    @Override
     public void actionPerformed(ActionEvent evt) {
         TopComponent win = OutlineTopComponent.findInstance();
         win.open();
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/RemoveAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/RemoveAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -36,6 +36,7 @@
  */
 public final class RemoveAction extends NodeAction {
 
+    @Override
     protected void performAction(Node[] activatedNodes) {
         for (Node n : activatedNodes) {
             RemoveCookie removeCookie = n.getCookie(RemoveCookie.class);
@@ -46,18 +47,20 @@
     }
 
     public RemoveAction() {
-        putValue(Action.SHORT_DESCRIPTION, "Remove");
+        putValue(Action.SHORT_DESCRIPTION, "Remove selected graphs and groups");
     }
 
+    @Override
     public String getName() {
         return NbBundle.getMessage(RemoveAction.class, "CTL_RemoveAction");
     }
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/coordinator/images/remove.gif";
+        return "com/sun/hotspot/igv/coordinator/images/remove.png";
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
@@ -67,6 +70,7 @@
         return false;
     }
 
+    @Override
     protected boolean enable(Node[] nodes) {
         return nodes.length > 0;
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/RemoveAllAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/RemoveAllAction.java	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, 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
@@ -40,20 +40,22 @@
 public final class RemoveAllAction extends CallableSystemAction {
 
 
+    @Override
     public String getName() {
-        return NbBundle.getMessage(RemoveAllAction.class, "CTL_ImportAction");
+        return NbBundle.getMessage(RemoveAllAction.class, "CTL_RemoveAllAction");
     }
 
     public RemoveAllAction() {
-        putValue(Action.SHORT_DESCRIPTION, "Remove all methods");
+        putValue(Action.SHORT_DESCRIPTION, "Remove all graphs and groups");
         putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_SHIFT, InputEvent.CTRL_MASK));
     }
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/coordinator/images/removeall.gif";
+        return "com/sun/hotspot/igv/coordinator/images/removeall.png";
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/RemoveCookie.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/RemoveCookie.java	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, 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
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/SaveAllAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/SaveAllAction.java	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, 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
@@ -39,17 +39,19 @@
  */
 public final class SaveAllAction extends CallableSystemAction {
 
+    @Override
     public void performAction() {
         final OutlineTopComponent component = OutlineTopComponent.findInstance();
         SaveAsAction.save(component.getDocument());
     }
 
+    @Override
     public String getName() {
         return NbBundle.getMessage(SaveAllAction.class, "CTL_SaveAllAction");
     }
 
     public SaveAllAction() {
-        putValue(Action.SHORT_DESCRIPTION, "Save all methods to XML file");
+        putValue(Action.SHORT_DESCRIPTION, "Save all groups to XML file...");
         putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_MASK));
     }
 
@@ -58,6 +60,7 @@
         return "com/sun/hotspot/igv/coordinator/images/saveall.gif";
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/SaveAsAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/SaveAsAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -28,12 +28,8 @@
 import com.sun.hotspot.igv.data.Group;
 import com.sun.hotspot.igv.data.serialization.Printer;
 import com.sun.hotspot.igv.settings.Settings;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
+import java.io.*;
+import javax.swing.Action;
 import javax.swing.JFileChooser;
 import org.openide.nodes.Node;
 import org.openide.util.HelpCtx;
@@ -47,12 +43,17 @@
  */
 public final class SaveAsAction extends NodeAction {
 
+    public SaveAsAction() {
+        putValue(Action.SHORT_DESCRIPTION, "Save selected groups to XML file...");
+    }
+
+    @Override
     protected void performAction(Node[] activatedNodes) {
 
         GraphDocument doc = new GraphDocument();
         for (Node n : activatedNodes) {
             Group group = n.getLookup().lookup(Group.class);
-            doc.addGroup(group);
+            doc.addElement(group);
         }
 
         save(doc);
@@ -75,10 +76,10 @@
             }
             Settings.get().put(Settings.DIRECTORY, dir.getAbsolutePath());
             try {
-                Writer writer = new OutputStreamWriter(new FileOutputStream(file));
-                Printer p = new Printer();
-                p.export(writer, doc);
-                writer.close();
+                try (Writer writer = new OutputStreamWriter(new FileOutputStream(file))) {
+                    Printer p = new Printer();
+                    p.export(writer, doc);
+                }
             } catch (FileNotFoundException e) {
                 e.printStackTrace();
             } catch (IOException e) {
@@ -92,15 +93,17 @@
         return CookieAction.MODE_SOME;
     }
 
+    @Override
     public String getName() {
         return NbBundle.getMessage(SaveAsAction.class, "CTL_SaveAsAction");
     }
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/coordinator/images/save.gif";
+        return "com/sun/hotspot/igv/coordinator/images/save.png";
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
@@ -110,6 +113,7 @@
         return false;
     }
 
+    @Override
     protected boolean enable(Node[] nodes) {
 
         int cnt = 0;
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/StructuredViewAction.java	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,180 +0,0 @@
-/*
- * Copyright (c) 1998, 2007, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.coordinator.actions;
-
-import com.sun.hotspot.igv.coordinator.OutlineTopComponent;
-import com.sun.hotspot.igv.data.services.GroupOrganizer;
-import java.awt.Component;
-import java.awt.Image;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
-import java.awt.image.BufferedImage;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import javax.swing.Action;
-import javax.swing.ButtonGroup;
-import javax.swing.ImageIcon;
-import javax.swing.JButton;
-import javax.swing.JCheckBoxMenuItem;
-import javax.swing.JMenuItem;
-import javax.swing.JPopupMenu;
-import javax.swing.event.PopupMenuEvent;
-import javax.swing.event.PopupMenuListener;
-import org.openide.awt.DropDownButtonFactory;
-import org.openide.util.HelpCtx;
-import org.openide.util.Lookup;
-import org.openide.util.Utilities;
-import org.openide.util.actions.CallableSystemAction;
-
-public class StructuredViewAction extends CallableSystemAction {
-
-    private static JButton dropDownButton;
-    private static ButtonGroup buttonGroup;
-    private static JPopupMenu popup;
-    private MyMenuItemListener menuItemListener;
-    private Map<JMenuItem, GroupOrganizer> map;
-
-    public StructuredViewAction() {
-
-        putValue(Action.SHORT_DESCRIPTION, "Cluster nodes into blocks");
-    }
-
-    @Override
-    public Component getToolbarPresenter() {
-
-        Image iconImage = Utilities.loadImage("com/sun/hotspot/igv/coordinator/images/structure.gif");
-        ImageIcon icon = new ImageIcon(iconImage);
-
-        popup = new JPopupMenu();
-
-        menuItemListener = new MyMenuItemListener();
-
-        buttonGroup = new ButtonGroup();
-
-        Collection<? extends GroupOrganizer> organizersCollection = Lookup.getDefault().lookupAll(GroupOrganizer.class);
-
-        List<GroupOrganizer> organizers = new ArrayList<GroupOrganizer>(organizersCollection);
-        Collections.sort(organizers, new Comparator<GroupOrganizer>() {
-            public int compare(GroupOrganizer a, GroupOrganizer b) {
-                return a.getName().compareTo(b.getName());
-            }
-        });
-
-        map = new HashMap<JMenuItem, GroupOrganizer>();
-
-        boolean first = true;
-        for(GroupOrganizer organizer : organizers) {
-            JCheckBoxMenuItem item = new JCheckBoxMenuItem(organizer.getName());
-            map.put(item, organizer);
-            item.addActionListener(menuItemListener);
-            buttonGroup.add(item);
-            popup.add(item);
-            if(first) {
-                item.setSelected(true);
-                first = false;
-            }
-        }
-
-        dropDownButton = DropDownButtonFactory.createDropDownButton(
-                new ImageIcon(
-                new BufferedImage(32, 32, BufferedImage.TYPE_BYTE_GRAY)),
-                popup);
-
-        dropDownButton.setIcon(icon);
-
-        dropDownButton.setToolTipText("Insert Layer Registration");
-
-        dropDownButton.addItemListener(new ItemListener() {
-
-            public void itemStateChanged(ItemEvent e) {
-                int state = e.getStateChange();
-                if (state == ItemEvent.SELECTED) {
-                    performAction();
-                }
-            }
-        });
-
-        dropDownButton.addActionListener(new ActionListener() {
-            public void actionPerformed(ActionEvent e) {
-                performAction();
-            }
-        });
-
-        popup.addPopupMenuListener(new PopupMenuListener() {
-
-            public void popupMenuCanceled(PopupMenuEvent e) {
-                dropDownButton.setSelected(false);
-            }
-
-            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
-                dropDownButton.setSelected(false);
-            }
-
-            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
-                dropDownButton.setSelected(true);
-            }
-        });
-
-        return dropDownButton;
-
-    }
-
-    private class MyMenuItemListener implements ActionListener {
-
-        public void actionPerformed(ActionEvent ev) {
-            JMenuItem item = (JMenuItem) ev.getSource();
-            GroupOrganizer organizer = map.get(item);
-            assert organizer != null : "Organizer must exist!";
-            OutlineTopComponent.findInstance().setOrganizer(organizer);
-        }
-    }
-
-
-    @Override
-    public void performAction() {
-        popup.show(dropDownButton, 0, dropDownButton.getHeight());
-    }
-
-    public String getName() {
-        return "Structured View";
-    }
-
-    public HelpCtx getHelpCtx() {
-        return HelpCtx.DEFAULT_HELP;
-    }
-
-    @Override
-    protected boolean asynchronous() {
-        return false;
-    }
-
-}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/customLeftWsmode.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/customLeftWsmode.xml	Fri May 08 13:25:11 2015 -0400
@@ -4,12 +4,8 @@
     <kind type="view" />
     <state type="joined" />
     <constraints>
-        <path orientation="horizontal" number="0" weight="0.779245283018868"/>
-        <path orientation="vertical" number="0" weight="0.7511825922421949"/>
-        <path orientation="horizontal" number="0" weight="0.5"/>
-        <path orientation="vertical" number="20" weight="0.7"/>
-        <path orientation="horizontal" number="40" weight="0.55"/>
-        <path orientation="horizontal" number="0" weight="0.2711864406779661"/>
+        <path orientation="horizontal" number="0" weight="0.2"/>
+        <path orientation="vertical" number="0" weight="0.75"/>
     </constraints>
     <bounds x="0" y="0" width="0" height="0" />
     <frame state="0"/>
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/diff.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/diff.png has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/folder.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/folder.png has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/graph.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/graph.png has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/import.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/import.png has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/remove.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/remove.png has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/removeall.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/removeall.png has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/save.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/save.png has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/saveall.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/structure.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/images/structure.png has changed
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/layer.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/layer.xml	Fri May 08 13:25:11 2015 -0400
@@ -1,110 +1,194 @@
 <?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">
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
 <filesystem>
-    <attr name="Actions\Edit\com-sun-hotspot-igv-bytecodes-SelectBytecodesAction.instance\position" intvalue="200"/>
-    <attr name="Actions\Edit\org-netbeans-core-ui-sysopen-SystemOpenAction.instance\position" intvalue="100"/>
-    <attr name="Actions\Edit\org-openide-actions-CopyAction.instance\position" intvalue="1300"/>
-    <attr name="Actions\Edit\org-openide-actions-CutAction.instance\position" intvalue="1400"/>
-    <attr name="Actions\Edit\org-openide-actions-DeleteAction.instance\position" intvalue="1500"/>
-    <attr name="Actions\Edit\org-openide-actions-FindAction.instance\position" intvalue="1600"/>
-    <attr name="Actions\Edit\org-openide-actions-GotoAction.instance\position" intvalue="1700"/>
-    <attr name="Actions\Edit\org-openide-actions-PasteAction.instance\position" intvalue="1800"/>
-    <attr name="Actions\Edit\org-openide-actions-RedoAction.instance\position" intvalue="1900"/>
-    <attr name="Actions\Edit\org-openide-actions-ReplaceAction.instance\position" intvalue="2000"/>
-    <attr name="Actions\Edit\org-openide-actions-UndoAction.instance\position" intvalue="2100"/>
-
     <folder name="Actions">
         <folder name="File">
-            <file name="com-sun-hotspot-igv-coordinator-actions-SaveAsAction.instance">
-                <attr name="position" intvalue="700"/>
-            </file>
-            <file name="com-sun-hotspot-igv-coordinator-actions-SaveAllAction.instance">
-                <attr name="position" intvalue="800"/>
-            </file>
-            <file name="com-sun-hotspot-igv-coordinator-actions-ImportAction.instance">
-                <attr name="position" intvalue="1000"/>
-            </file>
+            <file name="com-sun-hotspot-igv-coordinator-actions-SaveAsAction.instance"/>
+            <file name="com-sun-hotspot-igv-coordinator-actions-SaveAllAction.instance"/>
+            <file name="com-sun-hotspot-igv-coordinator-actions-ImportAction.instance"/>
         </folder>
         <folder name="Edit">
-
-            <file name="com-sun-hotspot-igv-coordinator-actions-RemoveAction.instance">
-                <attr name="position" intvalue="1200"/>
-            </file>
+            <file name="com-sun-hotspot-igv-coordinator-actions-RemoveAction.instance"/>
+            <file name="com-sun-hotspot-igv-coordinator-actions-RemoveAllAction.instance"/>
         </folder>
         <folder name="Window">
             <file name="com-sun-hotspot-igv-coordinator-actions-OutlineAction.instance"/>
         </folder>
     </folder>
+    
     <folder name="Menu">
         <folder name="File">
+            <file name="Separator2.instance_hidden"/>
+            <file name="Separator3.instance_hidden"/>
+            <file name="SeparatorOpen.instance_hidden"/>
             <file name="com-sun-hotspot-igv-coordinator-actions-ImportAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/File/com-sun-hotspot-igv-coordinator-actions-ImportAction.instance"/>
                 <attr name="position" intvalue="100"/>
             </file>
-            <file name="MySeparator2.instance">
+            <file name="SeparatorSave.instance">
                 <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
-                <attr name="position" intvalue="300"/>
+                <attr name="position" intvalue="150"/>
             </file>
             <file name="com-sun-hotspot-igv-coordinator-actions-SaveAsAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/File/com-sun-hotspot-igv-coordinator-actions-SaveAsAction.instance"/>
-                <attr name="position" intvalue="300"/>
+                <attr name="position" intvalue="200"/>
             </file>
             <file name="com-sun-hotspot-igv-coordinator-actions-SaveAllAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/File/com-sun-hotspot-igv-coordinator-actions-SaveAllAction.instance"/>
-                <attr name="position" intvalue="400"/>
-            </file>
-            <file name="MySeparator3.instance">
-                <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
-                <attr name="position" intvalue="500"/>
+                <attr name="position" intvalue="300"/>
             </file>
-
-            <file name="org-netbeans-modules-openfile-OpenFileAction.instance_hidden"/>
-            <file name="org-openide-actions-PageSetupAction.instance_hidden"/>
-            <file name="org-openide-actions-PrintAction.instance_hidden"/>
-            <file name="org-openide-actions-SaveAction.instance_hidden"/>
-            <file name="org-openide-actions-SaveAllAction.instance_hidden"/>
-            <file name="org-openide-actions-SaveAsAction.shadow_hidden"/>
-        </folder>
-        <folder name="Edit">
-            <file name="com-sun-hotspot-igv-coordinator-actions-SaveFilterSettingsAction.shadow">
-                <attr name="originalFile" stringvalue="Actions/Edit/com-sun-hotspot-igv-coordinator-actions-SaveFilterSettingsAction.instance"/>
+            <file name="SeparatorRemove.instance">
+                <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
+                <attr name="position" intvalue="350"/>
             </file>
             <file name="com-sun-hotspot-igv-coordinator-actions-RemoveAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/Edit/com-sun-hotspot-igv-coordinator-actions-RemoveAction.instance"/>
+                <attr name="position" intvalue="400" />
             </file>
-            <file name="org-netbeans-core-actions-JumpNextAction.shadow_hidden"/>
-            <file name="org-netbeans-core-actions-JumpPrevAction.shadow_hidden"/>
-            <file name="org-openide-actions-CutAction.instance_hidden"/>
-            <file name="org-openide-actions-CopyAction.instance_hidden"/>
-            <file name="org-openide-actions-PasteAction.instance_hidden"/>
-            <file name="org-openide-actions-DeleteAction.instance_hidden"/>
-            <file name="org-openide-actions-FindAction.instance_hidden"/>
-            <file name="org-openide-actions-ReplaceAction.instance_hidden"/>
-            <file name="org-openide-actions-JumpNextAction.shadow_hidden"/>
-            <file name="org-openide-actions-JumpPrevAction.shadow_hidden"/>
+            <file name="com-sun-hotspot-igv-coordinator-actions-RemoveAllAction.shadow">
+                <attr name="originalFile" stringvalue="Actions/Edit/com-sun-hotspot-igv-coordinator-actions-RemoveAllAction.instance"/>
+                <attr name="position" intvalue="500" />
+            </file>
+            
+            <!-- Hidden menu entries from other modules -->
+            <file name="org-netbeans-modules-editor-ExportHtmlAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-openfile-OpenFileAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-openfile-RecentFileAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-print-action-PageSetupAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-print-action-PrintAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-project-ui-CloseProject.shadow_hidden"/>
+            <file name="org-netbeans-modules-project-ui-CustomizeProject.shadow_hidden"/>
+            <file name="org-netbeans-modules-project-ui-NewFile.shadow_hidden"/>
+            <file name="org-netbeans-modules-project-ui-NewProject.shadow_hidden"/>
+            <file name="org-netbeans-modules-project-ui-OpenProject.shadow_hidden"/>
+            <file name="org-netbeans-modules-project-ui-RecentProjects.shadow_hidden"/>
+            <file name="org-netbeans-modules-project-ui-groups-GroupsMenu.shadow_hidden"/>
+            <file name="org-openide-actions-SaveAction.shadow_hidden"/>
+            <file name="org-openide-actions-SaveAllAction.shadow_hidden"/>
+            <file name="org-openide-actions-SaveAsAction.shadow_hidden"/>
         </folder>
-        <file name="GoTo_hidden"/>
-        <folder name="View">
+        
+        <folder name="Edit">
+            <!-- Hidden menu entries from other modules -->
             <file name="Separator1.instance_hidden"/>
             <file name="Separator2.instance_hidden"/>
-            <file name="org-netbeans-core-actions-HTMLViewAction.instance_hidden"/>
-            <file name="org-netbeans-core-actions-LogAction.instance_hidden"/>
+            <file name="SeparatorAfterFindPrevious.instance_hidden"/>
+            <file name="SeparatorAfterProjectsSearch.instance_hidden"/>
+            <file name="WhereUsedAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-editor-MainMenuAction$FindNextAction.instance_hidden"/>
+            <file name="org-netbeans-modules-editor-MainMenuAction$FindPreviousAction.instance_hidden"/>
+            <file name="org-netbeans-modules-editor-MainMenuAction$FindSelectionAction.instance_hidden"/>
+            <file name="org-netbeans-modules-editor-MainMenuAction$PasteFormattedAction.instance_hidden"/>
+            <file name="org-netbeans-modules-editor-MainMenuAction$SelectAllAction.instance_hidden"/>
+            <file name="org-netbeans-modules-editor-MainMenuAction$SelectIdentifierAction.instance_hidden"/>
+            <file name="org-netbeans-modules-editor-MainMenuAction$StartMacroRecordingAction.instance_hidden"/>
+            <file name="org-netbeans-modules-editor-MainMenuAction$StopMacroRecordingAction.instance_hidden"/>
+            <file name="org-netbeans-modules-search-FindInFilesAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-search-ReplaceInFilesAction.shadow_hidden"/>
+            <file name="org-openide-actions-CopyAction.shadow_hidden"/>
+            <file name="org-openide-actions-CutAction.shadow_hidden"/>
+            <file name="org-openide-actions-DeleteAction.shadow_hidden"/>
+            <file name="org-openide-actions-FindAction.shadow_hidden"/>
+            <file name="org-openide-actions-PasteAction.shadow_hidden"/>
+            <file name="org-openide-actions-ReplaceAction.shadow_hidden"/>
+            <file name="sep-before-reposearch.instance_hidden"/>
+        </folder>
+        
+        <folder name="View">
+            <!-- Hidden menu entries from other modules -->
+            <file name="Separator1.instance_hidden"/>
+            <file name="Separator2.instance_hidden"/>
+            <file name="org-netbeans-core-actions-HTMLViewAction.shadow_hidden"/>
+            <file name="org-netbeans-core-actions-LogAction.shadow_hidden"/>
+            <file name="org-netbeans-core-multiview-EditorsAction.instance_hidden"/>
             <file name="org-netbeans-core-windows-actions-ToolbarsListAction.instance_hidden"/>
+            <file name="org-netbeans-modules-editor-NbCodeFoldingAction.instance_hidden"/>
+            <file name="org-netbeans-modules-project-ui-SyncEditorWithViewsAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-versioning-ShowTextAnnotationsAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-versioning-diff-ShowDiffSidebarAction.shadow_hidden"/>
+            <file name="toggle-line-numbers.shadow_hidden"/>
+            <file name="toggle-non-printable-characters.shadow_hidden"/>
+            <file name="toggle-toolbar.shadow_hidden"/>
         </folder>
+        
+        <!-- Hidden menus -->
+        <folder name="GoTo_hidden"/>
+        <folder name="Source_hidden"/>
+        <folder name="Refactoring_hidden"/>
+        <folder name="BuildProject_hidden"/>
+        <folder name="RunProject_hidden"/>
+        <folder name="Versioning_hidden"/>
+        
+        <folder name="Tools">
+            <!-- Hidden menu entries from other modules -->
+            <file name="LibrariesCustomizerAction.shadow_hidden"/>
+            <file name="PaletteManager_hidden"/>
+            <file name="Separator1.instance_hidden"/>
+            <file name="Separator2.instance_hidden"/>
+            <file name="ServerManagerAction3.shadow_hidden"/>
+            <file name="VariablesCustomizerAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-autoupdate-ui-actions-PluginManagerAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-favorites-templates-TemplatesAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-options-OptionsWindowAction-separatorBefore.instance_hidden"/>
+            <file name="org-netbeans-modules-xml-catalog-CatalogAction.shadow_hidden"/>
+            <file name="org-openide-actions-ToolsAction.shadow_hidden"/>
+        </folder>
+        
         <folder name="Window">
             <file name="OutlineAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/Window/com-sun-hotspot-igv-coordinator-actions-OutlineAction.instance"/>
             </file>
+            
+            <!-- Hidden menu entries from other modules -->
+            <file name="Debug_hidden"/>
+            <file name="Navigator_hidden"/>
+            <file name="Other_hidden"/>
+            <file name="Output_hidden"/>
+            <file name="ProgressListAction.shadow_hidden"/>
+            <file name="ShowPaletteAction.shadow_hidden"/>
+            <file name="SwitchToRecentDocumentAction.shadow_hidden"/>
+            <file name="Versioning_hidden"/>
+            <file name="org-netbeans-core-ide-ServicesTabAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-favorites-View.shadow_hidden"/>
+            <file name="org-netbeans-modules-project-ui-logical-tab-action.shadow_hidden"/>
+            <file name="org-netbeans-modules-project-ui-physical-tab-action.shadow_hidden"/>
+            <file name="org-netbeans-modules-tasklist-ui-TaskListAction.shadow_hidden"/>
+            <file name="CloneDocumentAction.shadow_hidden"/>
+        </folder>
+
+        <folder name="Help">
+            <!-- Hidden menu entries from other modules -->
+            <file name="Separator1.instance_hidden"/>
+            <file name="netbeans-kb.url_hidden"/>
+            <file name="org-netbeans-modules-autoupdate-ui-actions-CheckForUpdatesAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-bugzilla-ReportNBIssueAction.shadow_hidden"/>
+            <file name="org-netbeans-modules-usersguide-master.xml_hidden"/>
+            <file name="shortcuts.xml_hidden"/>
         </folder>
     </folder>
-    <folder name="Toolbars">
-        <file name="Standard.xml" url="StandardConfiguration.xml"/>
+
+    <folder name="OptionsDialog">
+        <!-- Hidden option tabs from other modules -->
+        <file name="Editor.instance_hidden"/>
+        <file name="FontsAndColors.instance_hidden"/>
+        <file name="General.instance_hidden"/>
+        <file name="Keymaps.instance_hidden"/>
+        <folder name="Advanced">
+            <file name="Files.instance_hidden"/>
+            <file name="IssueTracking.instance_hidden"/>
+            <file name="JavaScript.instance_hidden"/>
+            <file name="Spellchecker.instance_hidden"/>
+            <file name="TermAdvancedOption.instance_hidden"/>
+            <file name="ToDo.instance_hidden"/>
+            <file name="Versioning.instance_hidden"/>
+        </folder>
     </folder>
+    
     <folder name="Windows2">
         <folder name="Components">
             <file name="OutlineTopComponent.settings" url="OutlineTopComponentSettings.xml"/>
         </folder>
-        <folder name="Modes">
+        <folder name="Modes">  
             <file name="customLeft.wsmode" url="customLeftWsmode.xml"/>
             <folder name="customLeft">
                 <file name="OutlineTopComponent.wstcref" url="OutlineTopComponentWstcref.xml"/>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/manifest.mf	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/manifest.mf	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
-Manifest-Version: 1.0
-OpenIDE-Module: com.sun.hotspot.igv.data
-OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/data/Bundle.properties
-OpenIDE-Module-Specification-Version: 1.0
-
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.data
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/data/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/nbproject/project.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/nbproject/project.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,2 +1,8 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
+src.dir=src
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+test.src.dir=test
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/nbproject/project.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/nbproject/project.xml	Fri May 08 13:25:11 2015 -0400
@@ -6,6 +6,19 @@
             <code-name-base>com.sun.hotspot.igv.data</code-name-base>
             <suite-component/>
             <module-dependencies/>
+            <test-dependencies>
+                <test-type>
+                    <name>unit</name>
+                    <test-dependency>
+                        <code-name-base>org.netbeans.libs.junit4</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.openide.util</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                </test-type>
+            </test-dependencies>
             <public-packages>
                 <package>com.sun.hotspot.igv.data</package>
                 <package>com.sun.hotspot.igv.data.serialization</package>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/ChangedEvent.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/ChangedEvent.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -24,20 +24,22 @@
 package com.sun.hotspot.igv.data;
 
 /**
- *
+ * Class representing a generic changed event.
  * @author Thomas Wuerthinger
+ * @param <T>
  */
 public class ChangedEvent<T> extends Event<ChangedListener<T>> {
 
     private T object;
 
-    public ChangedEvent() {
-    }
-
+    /**
+     * Creates a new event with the specific object as the one for which the event gets fired.
+     */
     public ChangedEvent(T object) {
         this.object = object;
     }
 
+    @Override
     protected void fire(ChangedListener<T> l) {
         l.changed(object);
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/ChangedEventProvider.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/ChangedEventProvider.java	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, 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
@@ -25,10 +25,14 @@
 package com.sun.hotspot.igv.data;
 
 /**
- *
+ * Provides a changed event object.
  * @author Thomas Wuerthinger
+ * @param <T> Class for which the changed event fires.
  */
 public interface ChangedEventProvider<T> {
 
-    public ChangedEvent<T> getChangedEvent();
+    /**
+     * Returns the changed event object. Should always return the same instance.
+     */
+    ChangedEvent<T> getChangedEvent();
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/ChangedListener.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/ChangedListener.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -24,10 +24,15 @@
 package com.sun.hotspot.igv.data;
 
 /**
- *
+ * Listens to changed events.
  * @author Thomas Wuerthinger
+ * @param <T> Class for which the changed event fires.
  */
 public interface ChangedListener<T> {
 
-    public void changed(T source);
+    /**
+     * This method is called everytime a changed event is fired.
+     * @param source Object that has changed.
+     */
+    void changed(T source);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/ControllableChangedListener.java	Fri May 08 13:25:11 2015 -0400
@@ -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.data;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public abstract class ControllableChangedListener<T> implements ChangedListener<T>{
+
+    private boolean enabled;
+
+
+    public ControllableChangedListener() {
+        enabled = true;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(boolean b) {
+        enabled = b;
+    }
+
+    @Override
+    public void changed(T source) {
+        if(enabled) {
+            filteredChanged(source);
+        }
+    }
+
+    public abstract void filteredChanged(T source);
+}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Event.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Event.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -33,23 +33,48 @@
 public abstract class Event<L> {
 
     private List<L> listener;
+    private boolean fireEvents;
+    private boolean eventWasFired;
 
     public Event() {
-        listener = new ArrayList<L>();
+        listener = new ArrayList<>();
+        fireEvents = true;
     }
 
     public void addListener(L l) {
         listener.add(l);
     }
 
-    public void removeListener(L l) {
+    /**
+     * Remove listener
+     * @param l
+     */
+    public void removeListener(final L l) {
         listener.remove(l);
     }
 
     public void fire() {
-        List<L> tmpList = new ArrayList<L>(listener);
-        for (L l : tmpList) {
-            fire(l);
+        if(fireEvents) {
+            List<L> tmpList = new ArrayList<>(listener);
+            for (L l : tmpList) {
+                fire(l);
+            }
+        } else {
+            eventWasFired = true;
+        }
+    }
+
+    public void beginAtomic() {
+        assert fireEvents : "endAtomic has to be called before another beginAtomic may be called";
+        this.fireEvents = false;
+        this.eventWasFired = false;
+    }
+
+    public void endAtomic() {
+        assert !fireEvents : "beginAtomic has to be called first";
+        this.fireEvents = true;
+        if(eventWasFired) {
+            fire();
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Folder.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 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.data;
+
+import java.util.List;
+
+public interface Folder {
+    List<? extends FolderElement> getElements();
+    void removeElement(FolderElement element);
+    void addElement(FolderElement group);
+    ChangedEvent<? extends Folder> getChangedEvent();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/FolderElement.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 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.data;
+
+public interface FolderElement {
+
+    Folder getParent();
+    String getName();
+    void setParent(Folder parent);
+}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/GraphDocument.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/GraphDocument.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -24,53 +24,36 @@
 package com.sun.hotspot.igv.data;
 
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
-public class GraphDocument extends Properties.Entity implements ChangedEventProvider<GraphDocument> {
+public class GraphDocument extends Properties.Entity implements ChangedEventProvider<GraphDocument>, Folder {
 
-    private List<Group> groups;
+    private List<FolderElement> elements;
     private ChangedEvent<GraphDocument> changedEvent;
 
     public GraphDocument() {
-        groups = new ArrayList<Group>();
-        changedEvent = new ChangedEvent<GraphDocument>(this);
+        elements = new ArrayList<>();
+        changedEvent = new ChangedEvent<>(this);
     }
 
     public void clear() {
-        groups.clear();
+        elements.clear();
         getChangedEvent().fire();
     }
 
+    @Override
     public ChangedEvent<GraphDocument> getChangedEvent() {
         return changedEvent;
     }
 
-    public List<Group> getGroups() {
-        return Collections.unmodifiableList(groups);
-    }
-
-    public void addGroup(Group group) {
-        group.setDocument(this);
-        groups.add(group);
-        getChangedEvent().fire();
-    }
-
-    public void removeGroup(Group group) {
-        if (groups.contains(group)) {
-            group.setDocument(null);
-            groups.remove(group);
-            getChangedEvent().fire();
-        }
-    }
-
     public void addGraphDocument(GraphDocument document) {
-        for (Group g : document.groups) {
-            this.addGroup(g);
+        for (FolderElement e : document.elements) {
+            e.setParent(this);
+            this.addElement(e);
         }
         document.clear();
         getChangedEvent().fire();
@@ -80,12 +63,30 @@
     public String toString() {
         StringBuilder sb = new StringBuilder();
 
-        sb.append("GraphDocument: " + getProperties().toString() + " \n\n");
-        for (Group g : getGroups()) {
+        sb.append("GraphDocument: ").append(getProperties().toString()).append(" \n\n");
+        for (FolderElement g : getElements()) {
             sb.append(g.toString());
             sb.append("\n\n");
         }
 
         return sb.toString();
     }
+
+    @Override
+    public List<? extends FolderElement> getElements() {
+        return elements;
+    }
+
+    @Override
+    public void removeElement(FolderElement element) {
+        if (elements.remove(element)) {
+            getChangedEvent().fire();
+        }
+    }
+
+    @Override
+    public void addElement(FolderElement element) {
+        elements.add(element);
+        getChangedEvent().fire();
+    }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Group.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Group.java	Fri May 08 13:25:11 2015 -0400
@@ -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,49 +23,36 @@
  */
 package com.sun.hotspot.igv.data;
 
-import com.sun.hotspot.igv.data.ChangedEvent;
-import com.sun.hotspot.igv.data.ChangedEventProvider;
-import com.sun.hotspot.igv.data.Properties;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
-public class Group extends Properties.Entity implements ChangedEventProvider<Group> {
+public class Group extends Properties.Entity implements ChangedEventProvider<Group>, Folder, FolderElement {
 
-    private List<InputGraph> graphs;
+    private final List<FolderElement> elements;
+    private final List<InputGraph> graphs;
+
+    private InputMethod method;
     private transient ChangedEvent<Group> changedEvent;
-    private GraphDocument document;
-    private InputMethod method;
-    private String assembly;
+    private Folder parent;
 
-    public Group() {
-        graphs = new ArrayList<InputGraph>();
-        init();
-    }
+    public Group(Folder parent) {
+        elements = new ArrayList<>();
+        graphs = new ArrayList<>();
+        changedEvent = new ChangedEvent<>(this);
+        this.parent = parent;
 
-    private void init() {
-        changedEvent = new ChangedEvent<Group>(this);
+        // Ensure that name and type are never null
+        getProperties().setProperty("name", "");
+        getProperties().setProperty("type", "");
     }
 
     public void fireChangedEvent() {
         changedEvent.fire();
     }
 
-    public void setAssembly(String s) {
-        this.assembly = s;
-    }
-
-    public String getAssembly() {
-        return assembly;
-    }
-
     public void setMethod(InputMethod method) {
         this.method = method;
     }
@@ -74,68 +61,120 @@
         return method;
     }
 
-    void setDocument(GraphDocument document) {
-        this.document = document;
-    }
-
-    public GraphDocument getDocument() {
-        return document;
-    }
-
+    @Override
     public ChangedEvent<Group> getChangedEvent() {
         return changedEvent;
     }
 
-    public List<InputGraph> getGraphs() {
-        return Collections.unmodifiableList(graphs);
+    @Override
+    public List<FolderElement> getElements() {
+        return Collections.unmodifiableList(elements);
+    }
+
+    public int getGraphsCount() {
+        return elements.size();
     }
 
-    public void addGraph(InputGraph g) {
-        assert g != null;
-        assert !graphs.contains(g);
-        graphs.add(g);
+    @Override
+    public void addElement(FolderElement element) {
+        elements.add(element);
+        if (element instanceof InputGraph) {
+            graphs.add((InputGraph) element);
+        } else {
+
+        }
+        element.setParent(this);
         changedEvent.fire();
     }
 
-    public void removeGraph(InputGraph g) {
-        int index = graphs.indexOf(g);
-        if (index != -1) {
-            graphs.remove(g);
-            changedEvent.fire();
-        }
-    }
-
     public Set<Integer> getAllNodes() {
-        Set<Integer> result = new HashSet<Integer>();
-        for (InputGraph g : graphs) {
-            Set<Integer> ids = g.getNodesAsSet();
-            result.addAll(g.getNodesAsSet());
-            for (Integer i : ids) {
-                result.add(-i);
+        Set<Integer> result = new HashSet<>();
+        for (FolderElement e : elements) {
+            if (e instanceof InputGraph) {
+                InputGraph g = (InputGraph) e;
+                result.addAll(g.getNodesAsSet());
             }
         }
         return result;
     }
 
-    public InputGraph getLastAdded() {
-        if (graphs.size() == 0) {
-            return null;
-        }
-        return graphs.get(graphs.size() - 1);
-    }
-
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
-        sb.append("Group " + getProperties().toString() + "\n");
-        for (InputGraph g : graphs) {
+        sb.append("Group ").append(getProperties()).append("\n");
+        for (FolderElement g : elements) {
             sb.append(g.toString());
-            sb.append("\n");
+            sb.append('\n');
         }
         return sb.toString();
     }
 
+    @Override
     public String getName() {
         return getProperties().get("name");
     }
+
+    public String getType() {
+        return getProperties().get("type");
+
+    }
+
+    InputGraph getPrev(InputGraph graph) {
+        InputGraph lastGraph = null;
+        for (FolderElement e : elements) {
+            if (e == graph) {
+                return lastGraph;
+            }
+            if (e instanceof InputGraph) {
+                lastGraph = (InputGraph) e;
+            }
+        }
+        return null;
+    }
+
+    InputGraph getNext(InputGraph graph) {
+        boolean found = false;
+        for (FolderElement e : elements) {
+            if (e == graph) {
+                found = true;
+            } else if (found && e instanceof InputGraph) {
+                return (InputGraph) e;
+            }
+        }
+        return null;
+    }
+
+    public InputGraph getLastGraph() {
+        InputGraph lastGraph = null;
+        for (FolderElement e : elements) {
+            if (e instanceof InputGraph) {
+                lastGraph = (InputGraph) e;
+            }
+        }
+        return lastGraph;
+    }
+
+    @Override
+    public Folder getParent() {
+         return parent;
+    }
+
+    @Override
+    public void removeElement(FolderElement element) {
+        if (elements.remove(element)) {
+            if (element instanceof InputGraph) {
+                graphs.remove((InputGraph) element);
+            }
+            changedEvent.fire();
+        }
+    }
+
+    public List<InputGraph> getGraphs() {
+        return graphs;
+    }
+
+    @Override
+    public void setParent(Folder parent) {
+        this.parent = parent;
+    }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java	Fri May 08 13:25:11 2015 -0400
@@ -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,12 +23,7 @@
  */
 package com.sun.hotspot.igv.data;
 
-import java.awt.Rectangle;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 
 /**
  *
@@ -37,104 +32,81 @@
 public class InputBlock {
 
     private List<InputNode> nodes;
-    private List<String> successorNames;
     private String name;
     private InputGraph graph;
-    private Rectangle bounds;
     private Set<InputBlock> successors;
-    private Set<InputBlock> predecessors;
-    private Set<InputBlockEdge> inputs;
-    private Set<InputBlockEdge> outputs;
+
+    @Override
+    public int hashCode() {
+        return name.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+
+        if (o == this) {
+            return true;
+        }
+
+        if (o == null || (!(o instanceof InputBlock))) {
+            return false;
+        }
 
-    public InputBlock(InputGraph graph, String name) {
+        final InputBlock b = (InputBlock)o;
+        final boolean result = b.nodes.equals(nodes) && b.name.equals(name) && b.successors.size() == successors.size();
+        if (!result) {
+            return false;
+        }
+
+        final HashSet<String> s = new HashSet<>();
+        for (InputBlock succ : successors) {
+            s.add(succ.name);
+        }
+
+        for (InputBlock succ : b.successors) {
+            if (!s.contains(succ.name)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    InputBlock(InputGraph graph, String name) {
         this.graph = graph;
         this.name = name;
-        nodes = new ArrayList<InputNode>();
-        successorNames = new ArrayList<String>();
-        successors = new HashSet<InputBlock>();
-        predecessors = new HashSet<InputBlock>();
-        inputs = new HashSet<InputBlockEdge>();
-        outputs = new HashSet<InputBlockEdge>();
-    }
-
-    public void removeSuccessor(InputBlock b) {
-        if (successors.contains(b)) {
-            successors.remove(b);
-            b.predecessors.remove(this);
-            InputBlockEdge e = new InputBlockEdge(this, b);
-            assert outputs.contains(e);
-            outputs.remove(e);
-            assert b.inputs.contains(e);
-            b.inputs.remove(e);
-        }
+        nodes = new ArrayList<>();
+        successors = new LinkedHashSet<>(2);
     }
 
     public String getName() {
         return name;
     }
 
-    public void setName(String s) {
-        name = s;
-    }
-
     public List<InputNode> getNodes() {
         return Collections.unmodifiableList(nodes);
     }
 
     public void addNode(int id) {
-        InputNode n = graph.getNode(id);
-        assert n != null;
-        graph.setBlock(n, this);
-        addNode(graph.getNode(id));
-    }
-
-    public void addNode(InputNode node) {
-        assert !nodes.contains(node);
+        InputNode node = graph.getNode(id);
+        assert node != null;
+        assert !nodes.contains(node) : "duplicate : " + node;
+        graph.setBlock(node, this);
         nodes.add(node);
     }
 
-    public Set<InputBlock> getPredecessors() {
-        return Collections.unmodifiableSet(predecessors);
-    }
-
     public Set<InputBlock> getSuccessors() {
         return Collections.unmodifiableSet(successors);
     }
 
-    public Set<InputBlockEdge> getInputs() {
-        return Collections.unmodifiableSet(inputs);
-    }
-
-    public Set<InputBlockEdge> getOutputs() {
-        return Collections.unmodifiableSet(outputs);
-    }
-
-    // resolveBlockLinks must be called afterwards
-    public void addSuccessor(String name) {
-        successorNames.add(name);
+    @Override
+    public String toString() {
+        return "Block " + this.getName();
     }
 
-    public void resolveBlockLinks() {
-        for (String s : successorNames) {
-            InputBlock b = graph.getBlock(s);
-            addSuccessor(b);
-        }
-
-        successorNames.clear();
-    }
-
-    public void addSuccessor(InputBlock b) {
+    void addSuccessor(InputBlock b) {
         if (!successors.contains(b)) {
             successors.add(b);
-            b.predecessors.add(this);
-            InputBlockEdge e = new InputBlockEdge(this, b);
-            outputs.add(e);
-            b.inputs.add(e);
         }
     }
-
-    @Override
-    public String toString() {
-        return this.getName();
-    }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlockEdge.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlockEdge.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -29,8 +29,15 @@
  */
 public class InputBlockEdge {
 
+    public enum State {
+        SAME,
+        NEW,
+        DELETED
+    }
+
     private InputBlock from;
     private InputBlock to;
+    private State state = State.SAME;
 
     public InputBlockEdge(InputBlock from, InputBlock to) {
         assert from != null;
@@ -47,13 +54,21 @@
         return to;
     }
 
+    public State getState() {
+        return state;
+    }
+
+    public void setState(State state) {
+        this.state = state;
+    }
+
     @Override
     public boolean equals(Object obj) {
-        if (obj instanceof InputBlockEdge && obj != null) {
+        if (obj != null && obj instanceof InputBlockEdge) {
             InputBlockEdge e = (InputBlockEdge) obj;
             return e.from.equals(from) && e.to.equals(to);
         }
-        return super.equals(obj);
+        return false;
     }
 
     @Override
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBytecode.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBytecode.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -31,11 +31,15 @@
 
     private int bci;
     private String name;
+    private String operands;
+    private String comment;
     private InputMethod inlined;
 
-    public InputBytecode(int bci, String name) {
+    public InputBytecode(int bci, String name, String operands, String comment) {
         this.bci = bci;
         this.name = name;
+        this.operands = operands;
+        this.comment = comment;
     }
 
     public InputMethod getInlined() {
@@ -53,4 +57,12 @@
     public String getName() {
         return name;
     }
+
+    public String getOperands() {
+        return operands;
+    }
+
+    public String getComment() {
+        return comment;
+    }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputEdge.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputEdge.java	Fri May 08 13:25:11 2015 -0400
@@ -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,10 @@
  */
 package com.sun.hotspot.igv.data;
 
+import java.util.Comparator;
+import java.util.WeakHashMap;
+import java.lang.ref.WeakReference;
+
 /**
  *
  * @author Thomas Wuerthinger
@@ -30,21 +34,83 @@
 public class InputEdge {
 
     public enum State {
-
+        IMMUTABLE,
         SAME,
         NEW,
         DELETED
     }
-    private char toIndex;
-    private int from;
-    private int to;
+
+    public static final Comparator<InputEdge> OUTGOING_COMPARATOR = new Comparator<InputEdge>(){
+
+        @Override
+            public int compare(InputEdge o1, InputEdge o2) {
+                if(o1.getFromIndex() == o2.getFromIndex()) {
+                    return o1.getTo() - o2.getTo();
+                }
+                return o1.getFromIndex() - o2.getFromIndex();
+            }
+    };
+
+    public static final Comparator<InputEdge> INGOING_COMPARATOR = new Comparator<InputEdge>(){
+
+        @Override
+            public int compare(InputEdge o1, InputEdge o2) {
+                if(o1.getToIndex() == o2.getToIndex()) {
+                    return o1.getFrom() - o2.getFrom();
+                }
+                return o1.getToIndex() - o2.getToIndex();
+            }
+    };
+
+    private final char toIndex;
+    private final char fromIndex;
+    private final int from;
+    private final int to;
+    private final String label;
+    private final String type;
     private State state;
 
     public InputEdge(char toIndex, int from, int to) {
+        this((char) 0, toIndex, from, to, null, null);
+    }
+
+    public InputEdge(char fromIndex, char toIndex, int from, int to) {
+        this(fromIndex, toIndex, from, to, null, null);
+    }
+
+    public InputEdge(char fromIndex, char toIndex, int from, int to, String label, String type) {
         this.toIndex = toIndex;
+        this.fromIndex = fromIndex;
         this.from = from;
         this.to = to;
         this.state = State.SAME;
+        this.label = label;
+        this.type = type.intern();
+    }
+
+    static WeakHashMap<InputEdge, WeakReference<InputEdge>> immutableCache = new WeakHashMap<>();
+
+    public static synchronized InputEdge createImmutable(char fromIndex, char toIndex, int from, int to, String label, String type) {
+        InputEdge edge = new InputEdge(fromIndex, toIndex, from, to, label, type, State.IMMUTABLE);
+        WeakReference<InputEdge> result = immutableCache.get(edge);
+        if (result != null) {
+            InputEdge edge2 = result.get();
+            if (edge2 != null) {
+                return edge2;
+            }
+        }
+        immutableCache.put(edge, new WeakReference<>(edge));
+        return edge;
+    }
+
+    public InputEdge(char fromIndex, char toIndex, int from, int to, String label, String type, State state) {
+        this.toIndex = toIndex;
+        this.fromIndex = fromIndex;
+        this.from = from;
+        this.to = to;
+        this.state = state;
+        this.label = label;
+        this.type = type;
     }
 
     public State getState() {
@@ -52,6 +118,9 @@
     }
 
     public void setState(State x) {
+        if (state == State.IMMUTABLE) {
+            throw new InternalError("Can't change immutable instances");
+        }
         this.state = x;
     }
 
@@ -59,6 +128,10 @@
         return toIndex;
     }
 
+    public char getFromIndex() {
+        return fromIndex;
+    }
+
     public String getName() {
         return "in" + toIndex;
     }
@@ -71,22 +144,35 @@
         return to;
     }
 
+    public String getLabel() {
+        return label;
+    }
+
+    public String getType() {
+        return type;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (o == null || !(o instanceof InputEdge)) {
             return false;
         }
         InputEdge conn2 = (InputEdge) o;
-        return conn2.toIndex == toIndex && conn2.from == from && conn2.to == to;
+        boolean result = conn2.fromIndex == fromIndex && conn2.toIndex == toIndex && conn2.from == from && conn2.to == to;
+        if (result && (state == State.IMMUTABLE || conn2.state == State.IMMUTABLE)) {
+            // Immutable instances must be exactly the same
+            return conn2.label == label && conn2.state == state;
+        }
+        return result;
     }
 
     @Override
     public String toString() {
-        return "Edge from " + from + " to " + to + "(" + (int) toIndex + ") ";
+        return "Edge from " + from + " to " + to + "(" + (int) fromIndex + ", " + (int) toIndex + ") ";
     }
 
     @Override
     public int hashCode() {
-        return (from << 20 | to << 8 | toIndex);
+        return (from << 20 | to << 8 | toIndex << 4 | fromIndex);
     }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java	Fri May 08 13:25:11 2015 -0400
@@ -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,65 +23,141 @@
  */
 package com.sun.hotspot.igv.data;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
-public class InputGraph extends Properties.Entity {
+public class InputGraph extends Properties.Entity implements FolderElement {
+
+    private Map<Integer, InputNode> nodes;
+    private List<InputEdge> edges;
+    private Folder parent;
+    private Group parentGroup;
+    private Map<String, InputBlock> blocks;
+    private List<InputBlockEdge> blockEdges;
+    private Map<Integer, InputBlock> nodeToBlock;
+
+    public InputGraph(String name) {
+        setName(name);
+        nodes = new LinkedHashMap<>();
+        edges = new ArrayList<>();
+        blocks = new LinkedHashMap<>();
+        blockEdges = new ArrayList<>();
+        nodeToBlock = new LinkedHashMap<>();
+    }
 
-    private HashMap<Integer, InputNode> nodes;
-    private ArrayList<InputEdge> edges;
-    private Group parent;
-    private HashMap<String, InputBlock> blocks;
-    private HashMap<Integer, InputBlock> nodeToBlock;
-    private boolean isDifferenceGraph;
+    @Override
+    public void setParent(Folder parent) {
+        this.parent = parent;
+        if (parent instanceof Group) {
+            assert this.parentGroup == null;
+            this.parentGroup = (Group) parent;
+        }
+    }
 
-    public InputGraph(Group parent) {
-        this(parent, null);
+    public InputBlockEdge addBlockEdge(InputBlock left, InputBlock right) {
+        InputBlockEdge edge = new InputBlockEdge(left, right);
+        blockEdges.add(edge);
+        left.addSuccessor(right);
+        return edge;
+    }
+
+    public List<InputNode> findRootNodes() {
+        List<InputNode> result = new ArrayList<>();
+        Set<Integer> nonRoot = new HashSet<>();
+        for(InputEdge curEdges : getEdges()) {
+            nonRoot.add(curEdges.getTo());
+        }
+
+        for(InputNode node : getNodes()) {
+            if(!nonRoot.contains(node.getId())) {
+                result.add(node);
+            }
+        }
+
+        return result;
     }
 
-    public InputGraph(Group parent, InputGraph last) {
-        this(parent, last, "");
+    public Map<InputNode, List<InputEdge>> findAllOutgoingEdges() {
+        Map<InputNode, List<InputEdge>> result = new HashMap<>(getNodes().size());
+        for(InputNode n : this.getNodes()) {
+            result.put(n, new ArrayList<InputEdge>());
+        }
+
+        for(InputEdge e : this.edges) {
+            int from = e.getFrom();
+            InputNode fromNode = this.getNode(from);
+            List<InputEdge> fromList = result.get(fromNode);
+            assert fromList != null;
+            fromList.add(e);
+        }
+
+        for(InputNode n : this.getNodes()) {
+            List<InputEdge> list = result.get(n);
+            Collections.sort(list, InputEdge.OUTGOING_COMPARATOR);
+        }
+
+        return result;
     }
 
-    private void clearBlocks() {
+    public Map<InputNode, List<InputEdge>> findAllIngoingEdges() {
+        Map<InputNode, List<InputEdge>> result = new HashMap<>(getNodes().size());
+        for(InputNode n : this.getNodes()) {
+            result.put(n, new ArrayList<InputEdge>());
+        }
+
+        for(InputEdge e : this.edges) {
+            int to = e.getTo();
+            InputNode toNode = this.getNode(to);
+            List<InputEdge> toList = result.get(toNode);
+            assert toList != null;
+            toList.add(e);
+        }
+
+        for(InputNode n : this.getNodes()) {
+            List<InputEdge> list = result.get(n);
+            Collections.sort(list, InputEdge.INGOING_COMPARATOR);
+        }
+
+        return result;
+    }
+
+    public List<InputEdge> findOutgoingEdges(InputNode n) {
+        List<InputEdge> result = new ArrayList<>();
+
+        for(InputEdge e : this.edges) {
+            if(e.getFrom() == n.getId()) {
+                result.add(e);
+            }
+        }
+
+        Collections.sort(result, InputEdge.OUTGOING_COMPARATOR);
+
+        return result;
+    }
+
+    public void clearBlocks() {
         blocks.clear();
         nodeToBlock.clear();
     }
 
-    public InputGraph(Group parent, InputGraph last, String name) {
-        this.parent = parent;
-        setName(name);
-        nodes = new HashMap<Integer, InputNode>();
-        edges = new ArrayList<InputEdge>();
-        blocks = new HashMap<String, InputBlock>();
-        nodeToBlock = new HashMap<Integer, InputBlock>();
-        if (last != null) {
+    public void setEdge(int fromIndex, int toIndex, int from, int to) {
+        assert fromIndex == ((char)fromIndex) : "Downcast must be safe";
+        assert toIndex == ((char)toIndex) : "Downcast must be safe";
 
-            for (InputNode n : last.getNodes()) {
-                addNode(n);
-            }
-
-            for (InputEdge c : last.getEdges()) {
-                addEdge(c);
-            }
+        InputEdge edge = new InputEdge((char)fromIndex, (char)toIndex, from, to);
+        if(!this.getEdges().contains(edge)) {
+            this.addEdge(edge);
         }
     }
 
-    public void schedule(Collection<InputBlock> newBlocks) {
-        clearBlocks();
-        InputBlock noBlock = new InputBlock(this, "no block");
-        Set<InputNode> scheduledNodes = new HashSet<InputNode>();
+    public void ensureNodesInBlocks() {
+        InputBlock noBlock = null;
+        Set<InputNode> scheduledNodes = new HashSet<>();
 
-        for (InputBlock b : newBlocks) {
+        for (InputBlock b : getBlocks()) {
             for (InputNode n : b.getNodes()) {
                 assert !scheduledNodes.contains(n);
                 scheduledNodes.add(n);
@@ -91,18 +167,11 @@
         for (InputNode n : this.getNodes()) {
             assert nodes.get(n.getId()) == n;
             if (!scheduledNodes.contains(n)) {
+                if (noBlock == null) {
+                    noBlock = this.addBlock("(no block)");
+                }
                 noBlock.addNode(n.getId());
             }
-        }
-
-        if (noBlock.getNodes().size() != 0) {
-            newBlocks.add(noBlock);
-        }
-        for (InputBlock b : newBlocks) {
-            addBlock(b);
-        }
-
-        for (InputNode n : this.getNodes()) {
             assert this.getBlock(n) != null;
         }
     }
@@ -116,45 +185,26 @@
     }
 
     public InputBlock getBlock(InputNode node) {
+        assert nodes.containsKey(node.getId());
+        assert nodes.get(node.getId()).equals(node);
         return getBlock(node.getId());
     }
 
     public InputGraph getNext() {
-        List<InputGraph> list = parent.getGraphs();
-        if (!list.contains(this)) {
-            return null;
-        }
-        int index = list.indexOf(this);
-        if (index == list.size() - 1) {
-            return null;
-        } else {
-            return list.get(index + 1);
-        }
+        return parentGroup.getNext(this);
     }
 
     public InputGraph getPrev() {
-        List<InputGraph> list = parent.getGraphs();
-        if (!list.contains(this)) {
-            return null;
-        }
-        int index = list.indexOf(this);
-        if (index == 0) {
-            return null;
-        } else {
-            return list.get(index - 1);
-        }
+        return parentGroup.getPrev(this);
     }
 
-    public String getName() {
-        return getProperties().get("name");
+    private void setName(String name) {
+        this.getProperties().setProperty("name", name);
     }
 
-    public String getAbsoluteName() {
-        String result = getName();
-        if (this.parent != null) {
-            result = parent.getName() + ": " + result;
-        }
-        return result;
+    @Override
+    public String getName() {
+        return getProperties().get("name");
     }
 
     public Collection<InputNode> getNodes() {
@@ -186,25 +236,22 @@
     }
 
     public void removeEdge(InputEdge c) {
-        assert edges.contains(c);
-        edges.remove(c);
-        assert !edges.contains(c);
+        boolean removed = edges.remove(c);
+        assert removed;
     }
 
     public void addEdge(InputEdge c) {
-        assert !edges.contains(c);
         edges.add(c);
-        assert edges.contains(c);
     }
 
     public Group getGroup() {
-        return parent;
+        return parentGroup;
     }
 
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
-        sb.append("Graph " + getName() + " " + getProperties().toString() + "\n");
+        sb.append("Graph ").append(getName()).append(" ").append(getProperties().toString()).append("\n");
         for (InputNode n : nodes.values()) {
             sb.append(n.toString());
             sb.append("\n");
@@ -214,35 +261,31 @@
             sb.append(c.toString());
             sb.append("\n");
         }
+
+        for (InputBlock b : getBlocks()) {
+            sb.append(b.toString());
+            sb.append("\n");
+        }
+
         return sb.toString();
     }
 
-    public void addBlock(InputBlock b) {
+    public InputBlock addBlock(String name) {
+        final InputBlock b = new InputBlock(this, name);
         blocks.put(b.getName(), b);
-        for (InputNode n : b.getNodes()) {
-            this.nodeToBlock.put(n.getId(), b);
-        }
-    }
-
-    public void resolveBlockLinks() {
-        for (InputBlock b : blocks.values()) {
-            b.resolveBlockLinks();
-        }
-    }
-
-    public void setName(String s) {
-        getProperties().setProperty("name", s);
+        return b;
     }
 
     public InputBlock getBlock(String s) {
         return blocks.get(s);
     }
 
-    public boolean isDifferenceGraph() {
-        return this.isDifferenceGraph;
+    public Collection<InputBlockEdge> getBlockEdges() {
+        return Collections.unmodifiableList(blockEdges);
     }
 
-    public void setIsDifferenceGraph(boolean b) {
-        isDifferenceGraph = b;
+    @Override
+    public Folder getParent() {
+        return parent;
     }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java	Fri May 08 13:25:11 2015 -0400
@@ -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,11 @@
  */
 package com.sun.hotspot.igv.data;
 
-import com.sun.hotspot.igv.data.Properties;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  *
@@ -42,14 +43,37 @@
     private Group group;
     private List<InputBytecode> bytecodes;
 
+    @Override
+    public int hashCode() {
+        int result = name.hashCode();
+        result = result * 31 + bci;
+        result = result * 31 + shortName.hashCode();
+        result = result * 31 + inlined.hashCode();
+        result = result * 31 + bytecodes.hashCode();
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == null || (!(o instanceof InputMethod))) {
+            return false;
+        }
+
+        final InputMethod im = (InputMethod)o;
+        return name.equals(im.name) && bci == im.bci && shortName.equals(im.shortName) &&
+               inlined.equals(im.inlined) && bytecodes.equals(im.bytecodes);
+    }
+
+
+
     /** Creates a new instance of InputMethod */
     public InputMethod(Group parent, String name, String shortName, int bci) {
         this.group = parent;
         this.name = name;
         this.bci = bci;
         this.shortName = shortName;
-        inlined = new ArrayList<InputMethod>();
-        bytecodes = new ArrayList<InputBytecode>();
+        inlined = new ArrayList<>();
+        bytecodes = new ArrayList<>();
     }
 
     public List<InputBytecode> getBytecodes() {
@@ -87,31 +111,42 @@
     }
 
     public void setBytecodes(String text) {
-
+        Pattern instruction = Pattern.compile("\\s*(\\d+)\\s*:?\\s*(\\w+)\\s*(.*)(?://(.*))?");
         String[] strings = text.split("\n");
-        int oldNumber = -1;
+        int oldBci = -1;
         for (String s : strings) {
-
-            if (s.length() > 0 && Character.isDigit(s.charAt(0))) {
-                s = s.trim();
-                int spaceIndex = s.indexOf(' ');
-                String numberString = s.substring(0, spaceIndex);
-                String tmpName = s.substring(spaceIndex + 1, s.length());
+            if (s.startsWith(" ")) {
+                // indented lines are extra textual information
+                continue;
+            }
+            s = s.trim();
+            if (s.length() != 0) {
+                final Matcher matcher = instruction.matcher(s);
+                if (matcher.matches()) {
+                    String bciString = matcher.group(1);
+                    String opcode = matcher.group(2);
+                    String operands = matcher.group(3).trim();
+                    String comment = matcher.group(4);
+                    if (comment != null) {
+                        comment = comment.trim();
+                    }
 
-                int number = -1;
-                number = Integer.parseInt(numberString);
+                    int bci = Integer.parseInt(bciString);
 
-                // assert correct order of bytecodes
-                assert number > oldNumber;
+                    // assert correct order of bytecodes
+                    assert bci > oldBci;
+
+                    InputBytecode bc = new InputBytecode(bci, opcode, operands, comment);
+                    bytecodes.add(bc);
 
-                InputBytecode bc = new InputBytecode(number, tmpName);
-                bytecodes.add(bc);
-
-                for (InputMethod m : inlined) {
-                    if (m.getBci() == number) {
-                        bc.setInlined(m);
-                        break;
+                    for (InputMethod m : inlined) {
+                        if (m.getBci() == bci) {
+                            bc.setInlined(m);
+                            break;
+                        }
                     }
+                } else {
+                    System.out.println("no match: " + s);
                 }
             }
         }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputNode.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputNode.java	Fri May 08 13:25:11 2015 -0400
@@ -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,10 @@
  */
 package com.sun.hotspot.igv.data;
 
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
 /**
  *
  * @author Thomas Wuerthinger
@@ -30,6 +34,37 @@
 public class InputNode extends Properties.Entity {
 
     private int id;
+    private List<InputGraph> subgraphs;
+
+    public static final Comparator<InputNode> COMPARATOR = new Comparator<InputNode>() {
+        @Override
+        public int compare(InputNode o1, InputNode o2) {
+            return o1.getId() - o2.getId();
+        }
+    };
+
+    public static Comparator<InputNode> getPropertyComparator(final String propertyName) {
+        return new Comparator<InputNode>() {
+
+            @Override
+            public int compare(InputNode o1, InputNode o2) {
+
+                int i1 = 0;
+                try {
+                    i1 = Integer.parseInt(o1.getProperties().get(propertyName));
+                } catch(NumberFormatException e) {
+                }
+
+                int i2 = 0;
+                try {
+                    i2 = Integer.parseInt(o2.getProperties().get(propertyName));
+                } catch(NumberFormatException e) {
+                }
+
+                return i1 - i2;
+            }
+        };
+    }
 
     public InputNode(InputNode n) {
         super(n);
@@ -49,21 +84,29 @@
         return id;
     }
 
+    public void addSubgraph(InputGraph graph) {
+        if (subgraphs == null) {
+            subgraphs = new ArrayList<>();
+        }
+        subgraphs.add(graph);
+    }
+
+    public List<InputGraph> getSubgraphs() {
+        return subgraphs;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (!(o instanceof InputNode)) {
             return false;
         }
         InputNode n = (InputNode) o;
-        if (n.id != id) {
-            return false;
-        }
-        return getProperties().equals(n.getProperties());
+        return n.id == id;
     }
 
     @Override
     public int hashCode() {
-        return id;
+        return id * 13;
     }
 
     @Override
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Pair.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Pair.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -58,15 +58,30 @@
 
     @Override
     public boolean equals(Object o) {
-        if (!(o instanceof Pair)) {
+        if (o == null || !(o instanceof Pair)) {
             return false;
         }
-        Pair obj = (Pair) o;
-        return l.equals(obj.l) && r.equals(obj.r);
+        Pair<?,?> obj = (Pair<?,?>) o;
+        boolean b1 = (l == obj.l);
+        if (l != null) {
+            b1 = l.equals(obj.l);
+        }
+
+        boolean b2 = (r == obj.r);
+        if (r != null) {
+            b2 = r.equals(obj.r);
+        }
+
+        return b1 && b2;
     }
 
     @Override
     public int hashCode() {
-        return l.hashCode() * 71 + r.hashCode();
+        return ((l == null) ? 0 : l.hashCode()) * 71 + ((r == null) ? 0 : r.hashCode());
+    }
+
+    @Override
+    public String toString() {
+        return "[" + l + "/" + r + "]";
     }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Properties.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Properties.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -24,13 +24,10 @@
 package com.sun.hotspot.igv.data;
 
 import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
+import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-
+import java.util.regex.PatternSyntaxException;
 
 /**
  *
@@ -58,13 +55,30 @@
                 return false;
             }
         }
+
+        for (Property prop : p) {
+            String value = this.get(prop.getName());
+            if (value == null || !value.equals(prop.getValue())) {
+                return false;
+            }
+        }
+
         return true;
     }
 
     @Override
     public int hashCode() {
         int hash = 5;
-        hash = 83 * hash + (this.map != null ? this.map.hashCode() : 0);
+
+        if (map != null) {
+            for (int i = 0; i < this.map.length; i++) {
+                if (map[i] == null) {
+                    i++;
+                } else {
+                    hash = hash * 83 + map[i].hashCode();
+                }
+            }
+        }
         return hash;
     }
 
@@ -85,7 +99,7 @@
 
     public Properties(Properties p) {
         map = new String[p.map.length];
-        System.arraycopy(map, 0, p.map, 0, p.map.length);
+        System.arraycopy(p.map, 0, map, 0, p.map.length);
     }
 
     public static class Entity implements Provider {
@@ -100,19 +114,12 @@
             properties = new Properties(object.getProperties());
         }
 
+        @Override
         public Properties getProperties() {
             return properties;
         }
     }
 
-    private String getProperty(String key) {
-        for (int i = 0; i < map.length; i += 2)
-            if (map[i] != null && map[i].equals(key)) {
-                return map[i + 1];
-            }
-        return null;
-    }
-
     public interface PropertyMatcher {
 
         String getName();
@@ -128,11 +135,16 @@
             this.matcher = matcher;
         }
 
+        @Override
         public String getName() {
             return matcher.getName();
         }
 
+        @Override
         public boolean match(String p) {
+            if (p == null) {
+                return false;
+            }
             return !matcher.match(p);
         }
     }
@@ -143,15 +155,26 @@
         private String value;
 
         public StringPropertyMatcher(String name, String value) {
+            if (name == null) {
+                throw new IllegalArgumentException("Property name must not be null!");
+            }
+            if (value == null) {
+                throw new IllegalArgumentException("Property value must not be null!");
+            }
             this.name = name;
             this.value = value;
         }
 
+        @Override
         public String getName() {
             return name;
         }
 
+        @Override
         public boolean match(String p) {
+            if (p == null) {
+                throw new IllegalArgumentException("Property value must not be null!");
+            }
             return p.equals(value);
         }
     }
@@ -162,30 +185,55 @@
         private Pattern valuePattern;
 
         public RegexpPropertyMatcher(String name, String value) {
-            this.name = name;
-            valuePattern = Pattern.compile(value);
+            this(name, value, 0);
         }
 
+        public RegexpPropertyMatcher(String name, String value, int flags) {
+
+            if (name == null) {
+                throw new IllegalArgumentException("Property name must not be null!");
+            }
+
+            if (value == null) {
+                throw new IllegalArgumentException("Property value pattern must not be null!");
+            }
+
+            this.name = name;
+
+            try {
+                valuePattern = Pattern.compile(value, flags);
+            } catch (PatternSyntaxException e) {
+                throw new IllegalArgumentException("Bad pattern: " + value);
+            }
+        }
+
+        @Override
         public String getName() {
             return name;
         }
 
+        @Override
         public boolean match(String p) {
+            if (p == null) {
+                throw new IllegalArgumentException("Property value must not be null!");
+            }
             Matcher m = valuePattern.matcher(p);
             return m.matches();
         }
     }
 
     public Property selectSingle(PropertyMatcher matcher) {
+
+        final String name = matcher.getName();
         String value = null;
         for (int i = 0; i < map.length; i += 2) {
-            if (map[i] != null && matcher.getName().equals(map[i]))  {
+            if (map[i] != null && name.equals(map[i])) {
                 value = map[i + 1];
                 break;
             }
         }
         if (value != null && matcher.match(value)) {
-            return new Property(matcher.getName(), value);
+            return new Property(name, value);
         } else {
             return null;
         }
@@ -198,13 +246,32 @@
 
     @Override
     public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("[");
+        List<String[]> pairs = new ArrayList<>();
         for (int i = 0; i < map.length; i += 2) {
             if (map[i + 1] != null) {
-                String p = map[i + 1];
-                sb.append(map[i] + " = " + map[i + 1] + "; ");
+                pairs.add(new String[]{map[i], map[i + 1]});
+            }
+        }
+
+        Collections.sort(pairs, new Comparator<String[]>() {
+            @Override
+            public int compare(String[] o1, String[] o2) {
+                assert o1.length == 2;
+                assert o2.length == 2;
+                return o1[0].compareTo(o2[0]);
             }
+        });
+
+        StringBuilder sb = new StringBuilder();
+        sb.append("[");
+        boolean first = true;
+        for (String[] p : pairs) {
+            if (first) {
+                first = false;
+            } else {
+                sb.append(", ");
+            }
+            sb.append(p[0]).append("=").append(p[1]);
         }
         return sb.append("]").toString();
     }
@@ -217,10 +284,6 @@
             this.objects = objects;
         }
 
-        public T selectSingle(final String name, final String value) {
-            return selectSingle(new StringPropertyMatcher(name, value));
-        }
-
         public T selectSingle(PropertyMatcher matcher) {
 
             for (T t : objects) {
@@ -233,18 +296,16 @@
             return null;
         }
 
-        public List<T> selectMultiple(final String name, final String value) {
-            return selectMultiple(new StringPropertyMatcher(name, value));
-        }
+        public List<T> selectMultiple(PropertyMatcher matcher) {
+            List<T> result = new ArrayList<>();
 
-        public List<T> selectMultiple(PropertyMatcher matcher) {
-            List<T> result = new ArrayList<T>();
             for (T t : objects) {
                 Property p = t.getProperties().selectSingle(matcher);
                 if (p != null) {
                     result.add(t);
                 }
             }
+
             return result;
         }
     }
@@ -259,6 +320,10 @@
     }
 
     public void setProperty(String name, String value) {
+        setPropertyInternal(name.intern(), value != null ? value.intern() : null);
+    }
+    private void setPropertyInternal(String name, String value) {
+
         for (int i = 0; i < map.length; i += 2) {
             if (map[i] != null && map[i].equals(name)) {
                 String p = map[i + 1];
@@ -289,34 +354,26 @@
         map = newMap;
     }
 
-    public  Iterator<Property> getProperties() {
-        return iterator();
-    }
-
     public void add(Properties properties) {
         for (Property p : properties) {
-            add(p);
+            // Already interned
+            setPropertyInternal(p.getName(), p.getValue());
         }
     }
 
-    public void add(Property property) {
-        assert property.getName() != null;
-        assert property.getValue() != null;
-        setProperty(property.getName(), property.getValue());
-    }
-    class PropertiesIterator implements Iterator<Property>, Iterable<Property> {
-        public Iterator<Property> iterator() {
-                return this;
-        }
+    private class PropertiesIterator implements Iterator<Property> {
 
         int index;
 
+        @Override
         public boolean hasNext() {
-            while (index < map.length && map[index + 1] == null)
+            while (index < map.length && map[index + 1] == null) {
                 index += 2;
+            }
             return index < map.length;
         }
 
+        @Override
         public Property next() {
             if (index < map.length) {
                 index += 2;
@@ -325,11 +382,13 @@
             return null;
         }
 
+        @Override
         public void remove() {
             throw new UnsupportedOperationException("Not supported yet.");
         }
+    }
 
-    }
+    @Override
     public Iterator<Property> iterator() {
         return new PropertiesIterator();
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Property.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Property.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -32,25 +32,20 @@
 public class Property implements Serializable {
 
     public static final long serialVersionUID = 1L;
-
     private String name;
     private String value;
 
-    private Property() {
-        this(null, null);
-    }
-
-    private Property(Property p) {
-        this(p.getName(), p.getValue());
-    }
-
-    private Property(String name) {
-        this(name, null);
-    }
-
-    public Property(String name, String value) {
+    Property(String name, String value) {
         this.name = name;
         this.value = value;
+
+        if (value == null) {
+            throw new IllegalArgumentException("Property value must not be null!");
+        }
+
+        if (name == null) {
+            throw new IllegalArgumentException("Property name must not be null!");
+        }
     }
 
     public String getName() {
@@ -63,17 +58,20 @@
 
     @Override
     public String toString() {
-        return name + " = " + value + "; ";
+        return name + "=" + value;
     }
 
     @Override
     public boolean equals(Object o) {
-        if (!(o instanceof Property)) return false;
-        Property p2 = (Property)o;
+        if (!(o instanceof Property)) {
+            return false;
+        }
+        Property p2 = (Property) o;
         return name.equals(p2.name) && value.equals(p2.value);
     }
+
     @Override
     public int hashCode() {
-        return name.hashCode() + value == null ? 0 : value.hashCode();
+        return name.hashCode() * 13 + value.hashCode();
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Source.java	Fri May 08 13:25:11 2015 -0400
@@ -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.data;
+
+import java.util.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class Source {
+
+    private List<InputNode> sourceNodes;
+    private Set<Integer> set;
+
+    public Source() {
+        sourceNodes = new ArrayList<>(1);
+        set = new LinkedHashSet<>(1);
+    }
+
+    public List<InputNode> getSourceNodes() {
+        return Collections.unmodifiableList(sourceNodes);
+    }
+
+    public Set<Integer> getSourceNodesAsSet() {
+        return Collections.unmodifiableSet(set);
+    }
+
+    public void addSourceNode(InputNode n) {
+        if (!set.contains(n.getId())) {
+            sourceNodes.add(n);
+            set.add(n.getId());
+        }
+    }
+
+    public interface Provider {
+
+        public Source getSource();
+    }
+
+    public void addSourceNodes(Source s) {
+        for (InputNode n : s.getSourceNodes()) {
+            addSourceNode(n);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,900 @@
+/*
+ * Copyright (c) 2012, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.data.serialization;
+
+import com.sun.hotspot.igv.data.*;
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.data.services.GroupCallback;
+import java.io.EOFException;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.swing.SwingUtilities;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class BinaryParser implements GraphParser {
+    private static final int BEGIN_GROUP = 0x00;
+    private static final int BEGIN_GRAPH = 0x01;
+    private static final int CLOSE_GROUP = 0x02;
+
+    private static final int POOL_NEW = 0x00;
+    private static final int POOL_STRING = 0x01;
+    private static final int POOL_ENUM = 0x02;
+    private static final int POOL_CLASS = 0x03;
+    private static final int POOL_METHOD = 0x04;
+    private static final int POOL_NULL = 0x05;
+    private static final int POOL_NODE_CLASS = 0x06;
+    private static final int POOL_FIELD = 0x07;
+    private static final int POOL_SIGNATURE = 0x08;
+
+    private static final int KLASS = 0x00;
+    private static final int ENUM_KLASS = 0x01;
+
+    private static final int PROPERTY_POOL = 0x00;
+    private static final int PROPERTY_INT = 0x01;
+    private static final int PROPERTY_LONG = 0x02;
+    private static final int PROPERTY_DOUBLE = 0x03;
+    private static final int PROPERTY_FLOAT = 0x04;
+    private static final int PROPERTY_TRUE = 0x05;
+    private static final int PROPERTY_FALSE = 0x06;
+    private static final int PROPERTY_ARRAY = 0x07;
+    private static final int PROPERTY_SUBGRAPH = 0x08;
+
+    private static final String NO_BLOCK = "noBlock";
+
+    private final GroupCallback callback;
+    private final List<Object> constantPool;
+    private final ByteBuffer buffer;
+    private final ReadableByteChannel channel;
+    private final GraphDocument rootDocument;
+    private final Deque<Folder> folderStack;
+    private final Deque<byte[]> hashStack;
+    private final ParseMonitor monitor;
+
+    private MessageDigest digest;
+
+    private enum Length {
+        S,
+        M,
+        L
+    }
+
+    private interface LengthToString {
+        String toString(Length l);
+    }
+
+    private static abstract class Member implements LengthToString {
+        public final Klass holder;
+        public final int accessFlags;
+        public final String name;
+        public Member(Klass holder, String name, int accessFlags) {
+            this.holder = holder;
+            this.accessFlags = accessFlags;
+            this.name = name;
+        }
+    }
+
+    private static class Method extends Member {
+        public final Signature signature;
+        public final byte[] code;
+        public Method(String name, Signature signature, byte[] code, Klass holder, int accessFlags) {
+            super(holder, name, accessFlags);
+            this.signature = signature;
+            this.code = code;
+        }
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append(holder).append('.').append(name).append('(');
+            for (int i = 0; i < signature.argTypes.length; i++) {
+                if (i > 0) {
+                    sb.append(", ");
+                }
+                sb.append(signature.argTypes[i]);
+            }
+            sb.append(')');
+            return sb.toString();
+        }
+        @Override
+        public String toString(Length l) {
+            switch(l) {
+                case M:
+                    return holder.toString(Length.L) + "." + name;
+                case S:
+                    return holder.toString(Length.S) + "." + name;
+                default:
+                case L:
+                    return toString();
+            }
+        }
+    }
+
+    private static class Signature {
+        public final String returnType;
+        public final String[] argTypes;
+        public Signature(String returnType, String[] argTypes) {
+            this.returnType = returnType;
+            this.argTypes = argTypes;
+        }
+    }
+
+    private static class Field extends Member {
+        public final String type;
+        public Field(String type, Klass holder, String name, int accessFlags) {
+            super(holder, name, accessFlags);
+            this.type = type;
+        }
+        @Override
+        public String toString() {
+            return holder + "." + name;
+        }
+        @Override
+        public String toString(Length l) {
+            switch(l) {
+                case M:
+                    return holder.toString(Length.L) + "." + name;
+                case S:
+                    return holder.toString(Length.S) + "." + name;
+                default:
+                case L:
+                    return toString();
+            }
+        }
+    }
+
+    private static class Klass implements LengthToString {
+        public final String name;
+        public final String simpleName;
+        public Klass(String name) {
+            this.name = name;
+            String simple;
+            try {
+                simple = name.substring(name.lastIndexOf('.') + 1);
+            } catch (IndexOutOfBoundsException ioobe) {
+                simple = name;
+            }
+            this.simpleName = simple;
+        }
+        @Override
+        public String toString() {
+            return name;
+        }
+        @Override
+        public String toString(Length l) {
+            switch(l) {
+                case S:
+                    return simpleName;
+                default:
+                case L:
+                case M:
+                    return toString();
+            }
+        }
+    }
+
+    private static class EnumKlass extends Klass {
+        public final String[] values;
+        public EnumKlass(String name, String[] values) {
+            super(name);
+            this.values = values;
+        }
+    }
+
+    private static class Port {
+        public final boolean isList;
+        public final String name;
+        private Port(boolean isList, String name) {
+            this.isList = isList;
+            this.name = name;
+        }
+    }
+
+    private static class TypedPort extends Port {
+        public final EnumValue type;
+        private TypedPort(boolean isList, String name, EnumValue type) {
+            super(isList, name);
+            this.type = type;
+        }
+    }
+
+    private static class NodeClass {
+        public final String className;
+        public final String nameTemplate;
+        public final List<TypedPort> inputs;
+        public final List<Port> sux;
+        private NodeClass(String className, String nameTemplate, List<TypedPort> inputs, List<Port> sux) {
+            this.className = className;
+            this.nameTemplate = nameTemplate;
+            this.inputs = inputs;
+            this.sux = sux;
+        }
+        @Override
+        public String toString() {
+            return className;
+        }
+    }
+
+    private static class EnumValue implements LengthToString {
+        public EnumKlass enumKlass;
+        public int ordinal;
+        public EnumValue(EnumKlass enumKlass, int ordinal) {
+            this.enumKlass = enumKlass;
+            this.ordinal = ordinal;
+        }
+        @Override
+        public String toString() {
+            return enumKlass.simpleName + "." + enumKlass.values[ordinal];
+        }
+        @Override
+        public String toString(Length l) {
+            switch(l) {
+                case S:
+                    return enumKlass.values[ordinal];
+                default:
+                case M:
+                case L:
+                    return toString();
+            }
+        }
+    }
+
+    public BinaryParser(ReadableByteChannel channel, ParseMonitor monitor, GraphDocument rootDocument, GroupCallback callback) {
+        this.callback = callback;
+        constantPool = new ArrayList<>();
+        buffer = ByteBuffer.allocateDirect(256 * 1024);
+        buffer.flip();
+        this.channel = channel;
+        this.rootDocument = rootDocument;
+        folderStack = new LinkedList<>();
+        hashStack = new LinkedList<>();
+        this.monitor = monitor;
+        try {
+            this.digest = MessageDigest.getInstance("SHA-256");
+        } catch (NoSuchAlgorithmException e) {
+        }
+    }
+
+    private void fill() throws IOException {
+        buffer.compact();
+        if (channel.read(buffer) < 0) {
+            throw new EOFException();
+        }
+        buffer.flip();
+    }
+
+    private void ensureAvailable(int i) throws IOException {
+        while (buffer.remaining() < i) {
+            fill();
+        }
+        buffer.mark();
+        byte[] result = new byte[i];
+        buffer.get(result);
+        digest.update(result);
+        buffer.reset();
+    }
+
+    private int readByte() throws IOException {
+        ensureAvailable(1);
+        return ((int)buffer.get()) & 0xff;
+    }
+
+    private int readInt() throws IOException {
+        ensureAvailable(4);
+        return buffer.getInt();
+    }
+
+    private char readShort() throws IOException {
+        ensureAvailable(2);
+        return buffer.getChar();
+    }
+
+    private long readLong() throws IOException {
+        ensureAvailable(8);
+        return buffer.getLong();
+    }
+
+    private double readDouble() throws IOException {
+        ensureAvailable(8);
+        return buffer.getDouble();
+    }
+
+    private float readFloat() throws IOException {
+        ensureAvailable(4);
+        return buffer.getFloat();
+    }
+
+    private String readString() throws IOException {
+        int len = readInt();
+        ensureAvailable(len * 2);
+        char[] chars = new char[len];
+        buffer.asCharBuffer().get(chars);
+        buffer.position(buffer.position() + len * 2);
+        return new String(chars).intern();
+    }
+
+    private byte[] readBytes() throws IOException {
+        int len = readInt();
+        if (len < 0) {
+            return null;
+        }
+        ensureAvailable(len);
+        byte[] data = new byte[len];
+        buffer.get(data);
+        return data;
+    }
+
+    private String readIntsToString() throws IOException {
+        int len = readInt();
+        if (len < 0) {
+            return "null";
+        }
+        ensureAvailable(len * 4);
+        StringBuilder sb = new StringBuilder().append('[');
+        for (int i = 0; i < len; i++) {
+            sb.append(buffer.getInt());
+            if (i < len - 1) {
+                sb.append(", ");
+            }
+        }
+        sb.append(']');
+        return sb.toString().intern();
+    }
+
+    private String readDoublesToString() throws IOException {
+        int len = readInt();
+        if (len < 0) {
+            return "null";
+        }
+        ensureAvailable(len * 8);
+        StringBuilder sb = new StringBuilder().append('[');
+        for (int i = 0; i < len; i++) {
+            sb.append(buffer.getDouble());
+            if (i < len - 1) {
+                sb.append(", ");
+            }
+        }
+        sb.append(']');
+        return sb.toString().intern();
+    }
+
+    private String readPoolObjectsToString() throws IOException {
+        int len = readInt();
+        if (len < 0) {
+            return "null";
+        }
+        StringBuilder sb = new StringBuilder().append('[');
+        for (int i = 0; i < len; i++) {
+            sb.append(readPoolObject(Object.class));
+            if (i < len - 1) {
+                sb.append(", ");
+            }
+        }
+        sb.append(']');
+        return sb.toString().intern();
+    }
+
+    private <T> T readPoolObject(Class<T> klass) throws IOException {
+        int type = readByte();
+        if (type == POOL_NULL) {
+            return null;
+        }
+        if (type == POOL_NEW) {
+            return (T) addPoolEntry(klass);
+        }
+        assert assertObjectType(klass, type);
+        char index = readShort();
+        if (index < 0 || index >= constantPool.size()) {
+            throw new IOException("Invalid constant pool index : " + index);
+        }
+        Object obj = constantPool.get(index);
+        return (T) obj;
+    }
+
+    private boolean assertObjectType(Class<?> klass, int type) {
+        switch(type) {
+            case POOL_CLASS:
+                return klass.isAssignableFrom(EnumKlass.class);
+            case POOL_ENUM:
+                return klass.isAssignableFrom(EnumValue.class);
+            case POOL_METHOD:
+                return klass.isAssignableFrom(Method.class);
+            case POOL_STRING:
+                return klass.isAssignableFrom(String.class);
+            case POOL_NODE_CLASS:
+                return klass.isAssignableFrom(NodeClass.class);
+            case POOL_FIELD:
+                return klass.isAssignableFrom(Field.class);
+            case POOL_SIGNATURE:
+                return klass.isAssignableFrom(Signature.class);
+            case POOL_NULL:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    private Object addPoolEntry(Class<?> klass) throws IOException {
+        char index = readShort();
+        int type = readByte();
+        assert assertObjectType(klass, type) : "Wrong object type : " + klass + " != " + type;
+        Object obj;
+        switch(type) {
+            case POOL_CLASS: {
+                String name = readString();
+                int klasstype = readByte();
+                if (klasstype == ENUM_KLASS) {
+                    int len = readInt();
+                    String[] values = new String[len];
+                    for (int i = 0; i < len; i++) {
+                        values[i] = readPoolObject(String.class);
+                    }
+                    obj = new EnumKlass(name, values);
+                } else if (klasstype == KLASS) {
+                    obj = new Klass(name);
+                } else {
+                    throw new IOException("unknown klass type : " + klasstype);
+                }
+                break;
+            }
+            case POOL_ENUM: {
+                EnumKlass enumClass = readPoolObject(EnumKlass.class);
+                int ordinal = readInt();
+                obj = new EnumValue(enumClass, ordinal);
+                break;
+            }
+            case POOL_NODE_CLASS: {
+                String className = readString();
+                String nameTemplate = readString();
+                int inputCount = readShort();
+                List<TypedPort> inputs = new ArrayList<>(inputCount);
+                for (int i = 0; i < inputCount; i++) {
+                    boolean isList = readByte() != 0;
+                    String name = readPoolObject(String.class);
+                    EnumValue inputType = readPoolObject(EnumValue.class);
+                    inputs.add(new TypedPort(isList, name, inputType));
+                }
+                int suxCount = readShort();
+                List<Port> sux = new ArrayList<>(suxCount);
+                for (int i = 0; i < suxCount; i++) {
+                    boolean isList = readByte() != 0;
+                    String name = readPoolObject(String.class);
+                    sux.add(new Port(isList, name));
+                }
+                obj = new NodeClass(className, nameTemplate, inputs, sux);
+                break;
+            }
+            case POOL_METHOD: {
+                Klass holder = readPoolObject(Klass.class);
+                String name = readPoolObject(String.class);
+                Signature sign = readPoolObject(Signature.class);
+                int flags = readInt();
+                byte[] code = readBytes();
+                obj = new Method(name, sign, code, holder, flags);
+                break;
+            }
+            case POOL_FIELD: {
+                Klass holder = readPoolObject(Klass.class);
+                String name = readPoolObject(String.class);
+                String fType = readPoolObject(String.class);
+                int flags = readInt();
+                obj = new Field(fType, holder, name, flags);
+                break;
+            }
+            case POOL_SIGNATURE: {
+                int argc = readShort();
+                String[] args = new String[argc];
+                for (int i = 0; i < argc; i++) {
+                    args[i] = readPoolObject(String.class);
+                }
+                String returnType = readPoolObject(String.class);
+                obj = new Signature(returnType, args);
+                break;
+            }
+            case POOL_STRING: {
+                obj = readString();
+                break;
+            }
+            default:
+                throw new IOException("unknown pool type");
+        }
+        while (constantPool.size() <= index) {
+            constantPool.add(null);
+        }
+        constantPool.set(index, obj);
+        return obj;
+    }
+
+    private Object readPropertyObject() throws IOException {
+        int type = readByte();
+        switch (type) {
+            case PROPERTY_INT:
+                return readInt();
+            case PROPERTY_LONG:
+                return readLong();
+            case PROPERTY_FLOAT:
+                return readFloat();
+            case PROPERTY_DOUBLE:
+                return readDouble();
+            case PROPERTY_TRUE:
+                return Boolean.TRUE;
+            case PROPERTY_FALSE:
+                return Boolean.FALSE;
+            case PROPERTY_POOL:
+                return readPoolObject(Object.class);
+            case PROPERTY_ARRAY:
+                int subType = readByte();
+                switch(subType) {
+                    case PROPERTY_INT:
+                        return readIntsToString();
+                    case PROPERTY_DOUBLE:
+                        return readDoublesToString();
+                    case PROPERTY_POOL:
+                        return readPoolObjectsToString();
+                    default:
+                        throw new IOException("Unknown type");
+                }
+            case PROPERTY_SUBGRAPH:
+                InputGraph graph = parseGraph("");
+                new Group(null).addElement(graph);
+                return graph;
+            default:
+                throw new IOException("Unknown type");
+        }
+    }
+
+    @Override
+    public GraphDocument parse() throws IOException {
+        folderStack.push(rootDocument);
+        hashStack.push(null);
+        if (monitor != null) {
+            monitor.setState("Starting parsing");
+        }
+        try {
+            while(true) {
+                parseRoot();
+            }
+        } catch (EOFException e) {
+
+        }
+        if (monitor != null) {
+            monitor.setState("Finished parsing");
+        }
+        return rootDocument;
+    }
+
+    private void parseRoot() throws IOException {
+        int type = readByte();
+        switch(type) {
+            case BEGIN_GRAPH: {
+                final Folder parent = folderStack.peek();
+                final InputGraph graph = parseGraph();
+                SwingUtilities.invokeLater(new Runnable(){
+                    @Override
+                    public void run() {
+                        parent.addElement(graph);
+                    }
+                });
+                break;
+            }
+            case BEGIN_GROUP: {
+                final Folder parent = folderStack.peek();
+                final Group group = parseGroup(parent);
+                if (callback == null || parent instanceof Group) {
+                    SwingUtilities.invokeLater(new Runnable(){
+                        @Override
+                        public void run() {
+                            parent.addElement(group);
+                        }
+                    });
+                }
+                folderStack.push(group);
+                hashStack.push(null);
+                if (callback != null && parent instanceof GraphDocument) {
+                    callback.started(group);
+                }
+                break;
+            }
+            case CLOSE_GROUP: {
+                if (folderStack.isEmpty()) {
+                    throw new IOException("Unbalanced groups");
+                }
+                folderStack.pop();
+                hashStack.pop();
+                break;
+            }
+            default:
+                throw new IOException("unknown root : " + type);
+        }
+    }
+
+    private Group parseGroup(Folder parent) throws IOException {
+        String name = readPoolObject(String.class);
+        String shortName = readPoolObject(String.class);
+        if (monitor != null) {
+            monitor.setState(shortName);
+        }
+        Method method = readPoolObject(Method.class);
+        int bci = readInt();
+        Group group = new Group(parent);
+        group.getProperties().setProperty("name", name);
+        if (method != null) {
+            InputMethod inMethod = new InputMethod(group, method.name, shortName, bci);
+            inMethod.setBytecodes("TODO");
+            group.setMethod(inMethod);
+        }
+        return group;
+    }
+
+    private InputGraph parseGraph() throws IOException {
+        if (monitor != null) {
+            monitor.updateProgress();
+        }
+        String title = readPoolObject(String.class);
+        digest.reset();
+        InputGraph graph = parseGraph(title);
+        byte[] d = digest.digest();
+        byte[] hash = hashStack.peek();
+        if (hash != null && Arrays.equals(hash, d)) {
+            graph.getProperties().setProperty("_isDuplicate", "true");
+        } else {
+            hashStack.pop();
+            hashStack.push(d);
+        }
+        return graph;
+    }
+
+    private InputGraph parseGraph(String title) throws IOException {
+        InputGraph graph = new InputGraph(title);
+        parseNodes(graph);
+        parseBlocks(graph);
+        graph.ensureNodesInBlocks();
+        return graph;
+    }
+
+    private void parseBlocks(InputGraph graph) throws IOException {
+        int blockCount = readInt();
+        List<Edge> edges = new LinkedList<>();
+        for (int i = 0; i < blockCount; i++) {
+            int id = readInt();
+            String name = id >= 0 ? Integer.toString(id) : NO_BLOCK;
+            InputBlock block = graph.addBlock(name);
+            int nodeCount = readInt();
+            for (int j = 0; j < nodeCount; j++) {
+                int nodeId = readInt();
+                if (nodeId < 0) {
+                    continue;
+                }
+                final Properties properties = graph.getNode(nodeId).getProperties();
+                final String oldBlock = properties.get("block");
+                if(oldBlock != null) {
+                    properties.setProperty("block", oldBlock + ", " + name);
+                } else {
+                    block.addNode(nodeId);
+                    properties.setProperty("block", name);
+                }
+            }
+            int edgeCount = readInt();
+            for (int j = 0; j < edgeCount; j++) {
+                int to = readInt();
+                edges.add(new Edge(id, to));
+            }
+        }
+        for (Edge e : edges) {
+            String fromName = e.from >= 0 ? Integer.toString(e.from) : NO_BLOCK;
+            String toName = e.to >= 0 ? Integer.toString(e.to) : NO_BLOCK;
+            graph.addBlockEdge(graph.getBlock(fromName), graph.getBlock(toName));
+        }
+    }
+
+    private void parseNodes(InputGraph graph) throws IOException {
+        int count = readInt();
+        Map<String, Object> props = new HashMap<>();
+        List<Edge> inputEdges = new ArrayList<>(count);
+        List<Edge> succEdges = new ArrayList<>(count);
+        for (int i = 0; i < count; i++) {
+            int id = readInt();
+            InputNode node = new InputNode(id);
+            final Properties properties = node.getProperties();
+            NodeClass nodeClass = readPoolObject(NodeClass.class);
+            int preds = readByte();
+            if (preds > 0) {
+                properties.setProperty("hasPredecessor", "true");
+            }
+            properties.setProperty("idx", Integer.toString(id));
+            int propCount = readShort();
+            for (int j = 0; j < propCount; j++) {
+                String key = readPoolObject(String.class);
+                if (key.equals("hasPredecessor") || key.equals("name") || key.equals("class") || key.equals("id") || key.equals("idx")) {
+                    key = "!data." + key;
+                }
+                Object value = readPropertyObject();
+                if (value instanceof InputGraph) {
+                    InputGraph subgraph = (InputGraph) value;
+                    subgraph.getProperties().setProperty("name", node.getId() + ":" + key);
+                    node.addSubgraph((InputGraph) value);
+                } else {
+                    properties.setProperty(key, value != null ? value.toString() : "null");
+                    props.put(key, value);
+                }
+            }
+            ArrayList<Edge> currentEdges = new ArrayList<>();
+            int portNum = 0;
+            for (TypedPort p : nodeClass.inputs) {
+                if (p.isList) {
+                    int size = readShort();
+                    for (int j = 0; j < size; j++) {
+                        int in = readInt();
+                        if (in >= 0) {
+                            Edge e = new Edge(in, id, (char) (preds + portNum), p.name + "[" + j + "]", p.type.toString(Length.S), true);
+                            currentEdges.add(e);
+                            inputEdges.add(e);
+                            portNum++;
+                        }
+                    }
+                } else {
+                    int in = readInt();
+                    if (in >= 0) {
+                        Edge e = new Edge(in, id, (char) (preds + portNum), p.name, p.type.toString(Length.S), true);
+                        currentEdges.add(e);
+                        inputEdges.add(e);
+                        portNum++;
+                    }
+                }
+
+            }
+            portNum = 0;
+            for (Port p : nodeClass.sux) {
+                if (p.isList) {
+                    int size = readShort();
+                    for (int j = 0; j < size; j++) {
+                        int sux = readInt();
+                        if (sux >= 0) {
+                            Edge e = new Edge(id, sux, (char) portNum, p.name + "[" + j + "]", "Successor", false);
+                            currentEdges.add(e);
+                            succEdges.add(e);
+                            portNum++;
+                        }
+                    }
+                } else {
+                    int sux = readInt();
+                    if (sux >= 0) {
+                        Edge e = new Edge(id, sux, (char) portNum, p.name, "Successor", false);
+                        currentEdges.add(e);
+                        succEdges.add(e);
+                        portNum++;
+                    }
+                }
+            }
+            properties.setProperty("name", createName(currentEdges, props, nodeClass.nameTemplate));
+            properties.setProperty("class", nodeClass.className);
+            switch (nodeClass.className) {
+                case "BeginNode":
+                    properties.setProperty("shortName", "B");
+                    break;
+                case "EndNode":
+                    properties.setProperty("shortName", "E");
+                    break;
+            }
+            graph.addNode(node);
+            props.clear();
+        }
+
+        Set<InputNode> nodesWithSuccessor = new HashSet<>();
+
+        for (Edge e : succEdges) {
+            assert !e.input;
+            char fromIndex = e.num;
+            nodesWithSuccessor.add(graph.getNode(e.from));
+            char toIndex = 0;
+            graph.addEdge(InputEdge.createImmutable(fromIndex, toIndex, e.from, e.to, e.label, e.type));
+        }
+        for (Edge e : inputEdges) {
+            assert e.input;
+            char fromIndex = (char) (nodesWithSuccessor.contains(graph.getNode(e.from)) ? 1 : 0);
+            char toIndex = e.num;
+            graph.addEdge(InputEdge.createImmutable(fromIndex, toIndex, e.from, e.to, e.label, e.type));
+        }
+    }
+
+    private String createName(List<Edge> edges, Map<String, Object> properties, String template) {
+        Pattern p = Pattern.compile("\\{(p|i)#([a-zA-Z0-9$_]+)(/(l|m|s))?\\}");
+        Matcher m = p.matcher(template);
+        StringBuffer sb = new StringBuffer();
+        while (m.find()) {
+            String name = m.group(2);
+            String type = m.group(1);
+            String result;
+            switch (type) {
+                case "i":
+                    StringBuilder inputString = new StringBuilder();
+                    for(Edge edge : edges) {
+                        if (edge.label.startsWith(name) && (name.length() == edge.label.length() || edge.label.charAt(name.length()) == '[')) {
+                            if (inputString.length() > 0) {
+                                inputString.append(", ");
+                            }
+                            inputString.append(edge.from);
+                        }
+                    }
+                    result = inputString.toString();
+                    break;
+                case "p":
+                    Object prop = properties.get(name);
+                    String length = m.group(4);
+                    if (prop == null) {
+                        result = "?";
+                    } else if (length != null && prop instanceof LengthToString) {
+                        LengthToString lengthProp = (LengthToString) prop;
+                        switch(length) {
+                            default:
+                            case "l":
+                                result = lengthProp.toString(Length.L);
+                                break;
+                            case "m":
+                                result = lengthProp.toString(Length.M);
+                                break;
+                            case "s":
+                                result = lengthProp.toString(Length.S);
+                                break;
+                        }
+                    } else {
+                        result = prop.toString();
+                    }
+                    break;
+                default:
+                    result = "#?#";
+                    break;
+            }
+            result = result.replace("\\", "\\\\");
+            result = result.replace("$", "\\$");
+            m.appendReplacement(sb, result);
+        }
+        m.appendTail(sb);
+        return sb.toString().intern();
+    }
+
+    private static class Edge {
+        final int from;
+        final int to;
+        final char num;
+        final String label;
+        final String type;
+        final boolean input;
+        public Edge(int from, int to) {
+            this(from, to, (char) 0, null, null, false);
+        }
+        public Edge(int from, int to, char num, String label, String type, boolean input) {
+            this.from = from;
+            this.to = to;
+            this.label = label != null ? label.intern() : label;
+            this.type = type != null ? type.intern() : type;
+            this.num = num;
+            this.input = input;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/GraphParser.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.data.serialization;
+
+import com.sun.hotspot.igv.data.GraphDocument;
+import java.io.IOException;
+
+public interface GraphParser {
+    public GraphDocument parse() throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/ParseMonitor.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.data.serialization;
+
+public interface ParseMonitor {
+
+    public void updateProgress();
+
+    public void setState(String state);
+
+}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java	Fri May 08 13:25:11 2015 -0400
@@ -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,31 +23,34 @@
  */
 package com.sun.hotspot.igv.data.serialization;
 
-import com.sun.hotspot.igv.data.GraphDocument;
-import com.sun.hotspot.igv.data.Group;
-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.InputMethod;
-import com.sun.hotspot.igv.data.InputNode;
-import com.sun.hotspot.igv.data.Properties;
-import com.sun.hotspot.igv.data.Property;
-import com.sun.hotspot.igv.data.services.GroupCallback;
+import com.sun.hotspot.igv.data.*;
 import com.sun.hotspot.igv.data.serialization.XMLParser.ElementHandler;
 import com.sun.hotspot.igv.data.serialization.XMLParser.HandoverElementHandler;
-import com.sun.hotspot.igv.data.serialization.XMLParser.ParseMonitor;
 import com.sun.hotspot.igv.data.serialization.XMLParser.TopElementHandler;
+import com.sun.hotspot.igv.data.services.GroupCallback;
 import java.io.IOException;
+import java.io.InputStream;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Map;
+import javax.swing.SwingUtilities;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.SchemaFactory;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
 import org.xml.sax.XMLReader;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
-public class Parser {
+public class Parser implements GraphParser {
 
     public static final String INDENT = "  ";
     public static final String TOP_ELEMENT = "graphDocument";
@@ -63,6 +66,7 @@
     public static final String REMOVE_EDGE_ELEMENT = "removeEdge";
     public static final String REMOVE_NODE_ELEMENT = "removeNode";
     public static final String METHOD_NAME_PROPERTY = "name";
+    public static final String GROUP_NAME_PROPERTY = "name";
     public static final String METHOD_IS_PUBLIC_PROPERTY = "public";
     public static final String METHOD_IS_STATIC_PROPERTY = "static";
     public static final String TRUE_VALUE = "true";
@@ -71,9 +75,13 @@
     public static final String NODE_ID_PROPERTY = "id";
     public static final String FROM_PROPERTY = "from";
     public static final String TO_PROPERTY = "to";
+    public static final String TYPE_PROPERTY = "type";
     public static final String PROPERTY_NAME_PROPERTY = "name";
     public static final String GRAPH_NAME_PROPERTY = "name";
-    public static final String TO_INDEX_PROPERTY = "index";
+    public static final String FROM_INDEX_PROPERTY = "fromIndex";
+    public static final String TO_INDEX_PROPERTY = "toIndex";
+    public static final String TO_INDEX_ALT_PROPERTY = "index";
+    public static final String LABEL_PROPERTY = "label";
     public static final String METHOD_ELEMENT = "method";
     public static final String INLINE_ELEMENT = "inline";
     public static final String BYTECODES_ELEMENT = "bytecodes";
@@ -86,13 +94,23 @@
     public static final String SUCCESSOR_ELEMENT = "successor";
     public static final String ASSEMBLY_ELEMENT = "assembly";
     public static final String DIFFERENCE_PROPERTY = "difference";
-    private TopElementHandler xmlDocument = new TopElementHandler();
-    private boolean difference;
+    private TopElementHandler<GraphDocument> xmlDocument = new TopElementHandler<>();
+    private Map<Group, Boolean> differenceEncoding = new HashMap<>();
+    private Map<Group, InputGraph> lastParsedGraph = new HashMap<>();
     private GroupCallback groupCallback;
-    private HashMap<String, Integer> idCache = new HashMap<String, Integer>();
+    private HashMap<String, Integer> idCache = new HashMap<>();
+    private ArrayList<Pair<String, String>> blockConnections = new ArrayList<>();
     private int maxId = 0;
+    private GraphDocument graphDocument;
+    private final ParseMonitor monitor;
+    private final ReadableByteChannel channel;
 
     private int lookupID(String i) {
+        try {
+            return Integer.parseInt(i);
+        } catch (NumberFormatException nfe) {
+            // ignore
+        }
         Integer id = idCache.get(i);
         if (id == null) {
             id = maxId++;
@@ -106,41 +124,40 @@
 
         @Override
         protected GraphDocument start() throws SAXException {
-            return new GraphDocument();
+            graphDocument = new GraphDocument();
+            return graphDocument;
         }
     };
     // <group>
-    private ElementHandler<Group, GraphDocument> groupHandler = new XMLParser.ElementHandler<Group, GraphDocument>(GROUP_ELEMENT) {
+    private ElementHandler<Group, Folder> groupHandler = new XMLParser.ElementHandler<Group, Folder>(GROUP_ELEMENT) {
 
         @Override
         protected Group start() throws SAXException {
-            Group group = new Group();
-            Parser.this.difference = false;
+            final Group group = new Group(this.getParentObject());
+
             String differenceProperty = this.readAttribute(DIFFERENCE_PROPERTY);
-            if (differenceProperty != null && (differenceProperty.equals("1") || differenceProperty.equals("true"))) {
-                Parser.this.difference = true;
-            }
+            Parser.this.differenceEncoding.put(group, (differenceProperty != null && (differenceProperty.equals("1") || differenceProperty.equals("true"))));
 
             ParseMonitor monitor = getMonitor();
             if (monitor != null) {
                 monitor.setState(group.getName());
             }
 
+            final Folder parent = getParentObject();
+            if (groupCallback == null || parent instanceof Group) {
+                SwingUtilities.invokeLater(new Runnable(){
+                    @Override
+                    public void run() {
+                        parent.addElement(group);
+                    }
+                });
+            }
+
             return group;
         }
 
         @Override
         protected void end(String text) throws SAXException {
-            if (groupCallback == null) {
-                getParentObject().addGroup(getObject());
-            }
-        }
-    };
-    private HandoverElementHandler<Group> assemblyHandler = new XMLParser.HandoverElementHandler<Group>(ASSEMBLY_ELEMENT, true) {
-
-        @Override
-        protected void end(String text) throws SAXException {
-            getParentObject().setAssembly(text);
         }
     };
     // <method>
@@ -155,7 +172,7 @@
         }
     };
 
-    private InputMethod parseMethod(XMLParser.ElementHandler handler, Group group) throws SAXException {
+    private InputMethod parseMethod(XMLParser.ElementHandler<?,?> handler, Group group) throws SAXException {
         String s = handler.readRequiredAttribute(METHOD_BCI_PROPERTY);
         int bci = 0;
         try {
@@ -175,7 +192,7 @@
         }
     };
     // <inlined>
-    private HandoverElementHandler<InputMethod> inlinedHandler = new XMLParser.HandoverElementHandler<InputMethod>(INLINE_ELEMENT);
+    private HandoverElementHandler<InputMethod> inlinedHandler = new XMLParser.HandoverElementHandler<>(INLINE_ELEMENT);
     // <inlined><method>
     private ElementHandler<InputMethod, InputMethod> inlinedMethodHandler = new XMLParser.ElementHandler<InputMethod, InputMethod>(METHOD_ELEMENT) {
 
@@ -189,45 +206,110 @@
     // <graph>
     private ElementHandler<InputGraph, Group> graphHandler = new XMLParser.ElementHandler<InputGraph, Group>(GRAPH_ELEMENT) {
 
-        private InputGraph graph;
-
         @Override
         protected InputGraph start() throws SAXException {
-
             String name = readAttribute(GRAPH_NAME_PROPERTY);
-            InputGraph previous = getParentObject().getLastAdded();
-            if (!difference) {
-                previous = null;
+            InputGraph curGraph = new InputGraph(name);
+            if (differenceEncoding.get(getParentObject())) {
+                InputGraph previous = lastParsedGraph.get(getParentObject());
+                lastParsedGraph.put(getParentObject(), curGraph);
+                if (previous != null) {
+                    for (InputNode n : previous.getNodes()) {
+                        curGraph.addNode(n);
+                    }
+                    for (InputEdge e : previous.getEdges()) {
+                        curGraph.addEdge(e);
+                    }
+                }
             }
-            InputGraph curGraph = new InputGraph(getParentObject(), previous, name);
-            this.graph = curGraph;
+            ParseMonitor monitor = getMonitor();
+            if (monitor != null) {
+                monitor.updateProgress();
+            }
             return curGraph;
         }
 
         @Override
         protected void end(String text) throws SAXException {
-            getParentObject().addGraph(graph);
-            graph.resolveBlockLinks();
+            // NOTE: Some graphs intentionally don't provide blocks. Instead
+            //       they later generate the blocks from other information such
+            //       as node properties (example: ServerCompilerScheduler).
+            //       Thus, we shouldn't assign nodes that don't belong to any
+            //       block to some artificial block below unless blocks are
+            //       defined and nodes are assigned to them.
+
+            final InputGraph graph = getObject();
+            final Group parent = getParentObject();
+            if (graph.getBlocks().size() > 0) {
+                boolean blocksContainNodes = false;
+                for (InputBlock b : graph.getBlocks()) {
+                    if (b.getNodes().size() > 0) {
+                        blocksContainNodes = true;
+                        break;
+                    }
+                }
+
+                if (!blocksContainNodes) {
+                    graph.clearBlocks();
+                    blockConnections.clear();
+                } else {
+                    // Blocks and their nodes defined: add other nodes to an
+                    //  artificial "no block" block
+                    InputBlock noBlock = null;
+                    for (InputNode n : graph.getNodes()) {
+                        if (graph.getBlock(n) == null) {
+                            if (noBlock == null) {
+                                noBlock = graph.addBlock("(no block)");
+                            }
+
+                            noBlock.addNode(n.getId());
+                        }
+
+                        assert graph.getBlock(n) != null;
+                    }
+                }
+            }
+
+            // Resolve block successors
+            for (Pair<String, String> p : blockConnections) {
+                final InputBlock left = graph.getBlock(p.getLeft());
+                assert left != null;
+                final InputBlock right = graph.getBlock(p.getRight());
+                assert right != null;
+                graph.addBlockEdge(left, right);
+            }
+            blockConnections.clear();
+
+            SwingUtilities.invokeLater(new Runnable(){
+
+                @Override
+                public void run() {
+                    // Add to group
+                    parent.addElement(graph);
+                }
+            });
         }
     };
     // <nodes>
-    private HandoverElementHandler<InputGraph> nodesHandler = new HandoverElementHandler<InputGraph>(NODES_ELEMENT);
+    private HandoverElementHandler<InputGraph> nodesHandler = new HandoverElementHandler<>(NODES_ELEMENT);
     // <controlFlow>
-    private HandoverElementHandler<InputGraph> controlFlowHandler = new HandoverElementHandler<InputGraph>(CONTROL_FLOW_ELEMENT);
+    private HandoverElementHandler<InputGraph> controlFlowHandler = new HandoverElementHandler<>(CONTROL_FLOW_ELEMENT);
     // <block>
     private ElementHandler<InputBlock, InputGraph> blockHandler = new ElementHandler<InputBlock, InputGraph>(BLOCK_ELEMENT) {
 
         @Override
         protected InputBlock start() throws SAXException {
             InputGraph graph = getParentObject();
-            String name = readRequiredAttribute(BLOCK_NAME_PROPERTY).intern();
-            InputBlock b = new InputBlock(getParentObject(), name);
-            graph.addBlock(b);
+            String name = readRequiredAttribute(BLOCK_NAME_PROPERTY);
+            InputBlock b = graph.addBlock(name);
+            for (InputNode n : b.getNodes()) {
+                assert graph.getBlock(n).equals(b);
+            }
             return b;
         }
     };
     // <nodes>
-    private HandoverElementHandler<InputBlock> blockNodesHandler = new HandoverElementHandler<InputBlock>(NODES_ELEMENT);
+    private HandoverElementHandler<InputBlock> blockNodesHandler = new HandoverElementHandler<>(NODES_ELEMENT);
     // <node>
     private ElementHandler<InputBlock, InputBlock> blockNodeHandler = new ElementHandler<InputBlock, InputBlock>(NODE_ELEMENT) {
 
@@ -246,14 +328,14 @@
         }
     };
     // <successors>
-    private HandoverElementHandler<InputBlock> successorsHandler = new HandoverElementHandler<InputBlock>(SUCCESSORS_ELEMENT);
+    private HandoverElementHandler<InputBlock> successorsHandler = new HandoverElementHandler<>(SUCCESSORS_ELEMENT);
     // <successor>
     private ElementHandler<InputBlock, InputBlock> successorHandler = new ElementHandler<InputBlock, InputBlock>(SUCCESSOR_ELEMENT) {
 
         @Override
         protected InputBlock start() throws SAXException {
             String name = readRequiredAttribute(BLOCK_NAME_PROPERTY);
-            getParentObject().addSuccessor(name);
+            blockConnections.add(new Pair<>(getParentObject().getName(), name));
             return getParentObject();
         }
     };
@@ -290,7 +372,7 @@
         }
     };
     // <graph>
-    private HandoverElementHandler<InputGraph> edgesHandler = new HandoverElementHandler<InputGraph>(EDGES_ELEMENT);
+    private HandoverElementHandler<InputGraph> edgesHandler = new HandoverElementHandler<>(EDGES_ELEMENT);
 
     // Local class for edge elements
     private class EdgeElementHandler extends ElementHandler<InputEdge, InputGraph> {
@@ -301,24 +383,37 @@
 
         @Override
         protected InputEdge start() throws SAXException {
+            int fromIndex = 0;
             int toIndex = 0;
             int from = -1;
             int to = -1;
+            String label = null;
+            String type = null;
 
             try {
+                String fromIndexString = readAttribute(FROM_INDEX_PROPERTY);
+                if (fromIndexString != null) {
+                    fromIndex = Integer.parseInt(fromIndexString);
+                }
+
                 String toIndexString = readAttribute(TO_INDEX_PROPERTY);
+                if (toIndexString == null) {
+                    toIndexString = readAttribute(TO_INDEX_ALT_PROPERTY);
+                }
                 if (toIndexString != null) {
                     toIndex = Integer.parseInt(toIndexString);
                 }
 
+                label = readAttribute(LABEL_PROPERTY);
+                type = readAttribute(TYPE_PROPERTY);
+
                 from = lookupID(readRequiredAttribute(FROM_PROPERTY));
                 to = lookupID(readRequiredAttribute(TO_PROPERTY));
             } catch (NumberFormatException e) {
                 throw new SAXException(e);
             }
 
-
-            InputEdge conn = new InputEdge((char) toIndex, from, to);
+            InputEdge conn = new InputEdge((char) fromIndex, (char) toIndex, from, to, label, type == null ? "" : type);
             return start(conn);
         }
 
@@ -345,14 +440,20 @@
         }
     };
     // <properties>
-    private HandoverElementHandler<Properties.Provider> propertiesHandler = new HandoverElementHandler<Properties.Provider>(PROPERTIES_ELEMENT);
+    private HandoverElementHandler<Properties.Provider> propertiesHandler = new HandoverElementHandler<>(PROPERTIES_ELEMENT);
     // <properties>
     private HandoverElementHandler<Group> groupPropertiesHandler = new HandoverElementHandler<Group>(PROPERTIES_ELEMENT) {
 
         @Override
         public void end(String text) throws SAXException {
-            if (groupCallback != null) {
-                groupCallback.started(getParentObject());
+            if (groupCallback != null && getParentObject().getParent() instanceof GraphDocument) {
+                final Group group = getParentObject();
+                SwingUtilities.invokeLater(new Runnable() {
+                    @Override
+                    public void run() {
+                        groupCallback.started(group);
+                    }
+                });
             }
         }
     };
@@ -361,30 +462,32 @@
 
         @Override
         public String start() throws SAXException {
-            return readRequiredAttribute(PROPERTY_NAME_PROPERTY).intern();
-        }
+            return readRequiredAttribute(PROPERTY_NAME_PROPERTY);
+         }
 
         @Override
         public void end(String text) {
-            getParentObject().getProperties().setProperty(getObject(), text.trim().intern());
+            getParentObject().getProperties().setProperty(getObject(), text.trim());
         }
     };
 
-    public Parser() {
-        this(null);
+    public Parser(ReadableByteChannel channel) {
+        this(channel, null, null);
     }
 
-    public Parser(GroupCallback groupCallback) {
+    public Parser(ReadableByteChannel channel, ParseMonitor monitor, GroupCallback groupCallback) {
 
         this.groupCallback = groupCallback;
+        this.monitor = monitor;
+        this.channel = channel;
 
         // Initialize dependencies
         xmlDocument.addChild(topHandler);
         topHandler.addChild(groupHandler);
 
         groupHandler.addChild(methodHandler);
-        groupHandler.addChild(assemblyHandler);
         groupHandler.addChild(graphHandler);
+        groupHandler.addChild(groupHandler);
 
         methodHandler.addChild(inlinedHandler);
         methodHandler.addChild(bytecodesHandler);
@@ -420,14 +523,40 @@
     }
 
     // Returns a new GraphDocument object deserialized from an XML input source.
-    public GraphDocument parse(XMLReader reader, InputSource source, XMLParser.ParseMonitor monitor) throws SAXException {
-        reader.setContentHandler(new XMLParser(xmlDocument, monitor));
+    @Override
+    public GraphDocument parse() throws IOException {
+        if (monitor != null) {
+            monitor.setState("Starting parsing");
+        }
         try {
-            reader.parse(source);
-        } catch (IOException ex) {
+            XMLReader reader = createReader();
+            reader.setContentHandler(new XMLParser(xmlDocument, monitor));
+            reader.parse(new InputSource(Channels.newInputStream(channel)));
+        } catch (SAXException ex) {
+            if (!(ex instanceof SAXParseException) || !"XML document structures must start and end within the same entity.".equals(ex.getMessage())) {
+                throw new IOException(ex);
+            }
+        }
+        if (monitor != null) {
+            monitor.setState("Finished parsing");
+        }
+        return graphDocument;
+    }
+
+    private XMLReader createReader() throws SAXException {
+        try {
+            SAXParserFactory pfactory = SAXParserFactory.newInstance();
+            pfactory.setValidating(true);
+            pfactory.setNamespaceAware(true);
+
+            // Enable schema validation
+            SchemaFactory sfactory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
+            InputStream stream = Parser.class.getResourceAsStream("graphdocument.xsd");
+            pfactory.setSchema(sfactory.newSchema(new Source[]{new StreamSource(stream)}));
+
+            return pfactory.newSAXParser().getXMLReader();
+        } catch (ParserConfigurationException ex) {
             throw new SAXException(ex);
         }
-
-        return topHandler.getObject();
     }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Printer.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Printer.java	Fri May 08 13:25:11 2015 -0400
@@ -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,17 +23,9 @@
  */
 package com.sun.hotspot.igv.data.serialization;
 
-import com.sun.hotspot.igv.data.GraphDocument;
-import com.sun.hotspot.igv.data.Group;
-import com.sun.hotspot.igv.data.InputBlock;
-import com.sun.hotspot.igv.data.InputBytecode;
-import com.sun.hotspot.igv.data.InputEdge;
-import com.sun.hotspot.igv.data.InputGraph;
-import com.sun.hotspot.igv.data.InputMethod;
-import com.sun.hotspot.igv.data.InputNode;
-import com.sun.hotspot.igv.data.Properties;
-import com.sun.hotspot.igv.data.Property;
+import com.sun.hotspot.igv.data.*;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.Writer;
 import java.util.HashSet;
 import java.util.Set;
@@ -44,6 +36,16 @@
  */
 public class Printer {
 
+    private InputStream in;
+
+    public Printer() {
+        this(null);
+    }
+
+    public Printer(InputStream inputStream) {
+        this.in = inputStream;
+    }
+
     public void export(Writer writer, GraphDocument document) {
 
         XMLWriter xmlWriter = new XMLWriter(writer);
@@ -57,8 +59,12 @@
     private void export(XMLWriter xmlWriter, GraphDocument document) throws IOException {
         xmlWriter.startTag(Parser.ROOT_ELEMENT);
         xmlWriter.writeProperties(document.getProperties());
-        for (Group g : document.getGroups()) {
-            export(xmlWriter, g);
+        for (FolderElement e : document.getElements()) {
+            if (e instanceof Group) {
+                export(xmlWriter, (Group) e);
+            } else if (e instanceof InputGraph) {
+                export(xmlWriter, (InputGraph)e, null, false);
+            }
         }
 
         xmlWriter.endTag();
@@ -71,14 +77,29 @@
         writer.startTag(Parser.GROUP_ELEMENT, attributes);
         writer.writeProperties(g.getProperties());
 
-        if (g.getMethod() != null) {
-            export(writer, g.getMethod());
+        boolean shouldExport = true;
+        if (in != null) {
+            char c = (char) in.read();
+            if (c != 'y') {
+                shouldExport = false;
+            }
         }
 
-        InputGraph previous = null;
-        for (InputGraph graph : g.getGraphs()) {
-            export(writer, graph, previous, true);
-            previous = graph;
+        if (shouldExport) {
+            if (g.getMethod() != null) {
+                export(writer, g.getMethod());
+            }
+
+            InputGraph previous = null;
+            for (FolderElement e : g.getElements()) {
+                if (e instanceof InputGraph) {
+                    InputGraph graph = (InputGraph) e;
+                    export(writer, graph, previous, true);
+                    previous = graph;
+                } else if (e instanceof Group) {
+                    export(writer, (Group) e);
+                }
+            }
         }
 
         writer.endTag();
@@ -90,8 +111,8 @@
         writer.writeProperties(graph.getProperties());
         writer.startTag(Parser.NODES_ELEMENT);
 
-        Set<InputNode> removed = new HashSet<InputNode>();
-        Set<InputNode> equal = new HashSet<InputNode>();
+        Set<InputNode> removed = new HashSet<>();
+        Set<InputNode> equal = new HashSet<>();
 
         if (previous != null) {
             for (InputNode n : previous.getNodes()) {
@@ -122,8 +143,8 @@
         writer.endTag();
 
         writer.startTag(Parser.EDGES_ELEMENT);
-        Set<InputEdge> removedEdges = new HashSet<InputEdge>();
-        Set<InputEdge> equalEdges = new HashSet<InputEdge>();
+        Set<InputEdge> removedEdges = new HashSet<>();
+        Set<InputEdge> equalEdges = new HashSet<>();
 
         if (previous != null) {
             for (InputEdge e : previous.getEdges()) {
@@ -153,23 +174,25 @@
 
         writer.startTag(Parser.CONTROL_FLOW_ELEMENT);
         for (InputBlock b : graph.getBlocks()) {
-
             writer.startTag(Parser.BLOCK_ELEMENT, new Properties(Parser.BLOCK_NAME_PROPERTY, b.getName()));
 
-            writer.startTag(Parser.SUCCESSORS_ELEMENT);
-            for (InputBlock s : b.getSuccessors()) {
-                writer.simpleTag(Parser.SUCCESSOR_ELEMENT, new Properties(Parser.BLOCK_NAME_PROPERTY, s.getName()));
+            if (b.getSuccessors().size() > 0) {
+                writer.startTag(Parser.SUCCESSORS_ELEMENT);
+                for (InputBlock s : b.getSuccessors()) {
+                    writer.simpleTag(Parser.SUCCESSOR_ELEMENT, new Properties(Parser.BLOCK_NAME_PROPERTY, s.getName()));
+                }
+                writer.endTag();
             }
-            writer.endTag();
 
+            if (b.getNodes().size() > 0) {
             writer.startTag(Parser.NODES_ELEMENT);
-            for (InputNode n : b.getNodes()) {
-                writer.simpleTag(Parser.NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, n.getId() + ""));
+                for (InputNode n : b.getNodes()) {
+                    writer.simpleTag(Parser.NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, n.getId() + ""));
+                }
+                writer.endTag();
             }
-            writer.endTag();
 
             writer.endTag();
-
         }
 
         writer.endTag();
@@ -199,8 +222,8 @@
             b.append(" ");
             b.append(code.getName());
             b.append("\n");
+        }
 
-        }
         b.append("]]>");
         w.write(b.toString());
         w.endTag();
@@ -209,9 +232,15 @@
 
     private Properties createProperties(InputEdge edge) {
         Properties p = new Properties();
-        p.setProperty(Parser.TO_INDEX_PROPERTY, Integer.toString(edge.getToIndex()));
+        if (edge.getToIndex() != 0) {
+            p.setProperty(Parser.TO_INDEX_PROPERTY, Integer.toString(edge.getToIndex()));
+        }
+        if (edge.getFromIndex() != 0) {
+            p.setProperty(Parser.FROM_INDEX_PROPERTY, Integer.toString(edge.getFromIndex()));
+        }
         p.setProperty(Parser.TO_PROPERTY, Integer.toString(edge.getTo()));
         p.setProperty(Parser.FROM_PROPERTY, Integer.toString(edge.getFrom()));
+        p.setProperty(Parser.TYPE_PROPERTY, edge.getType());
         return p;
     }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLParser.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLParser.java	Fri May 08 13:25:11 2015 -0400
@@ -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,7 +23,6 @@
  */
 package com.sun.hotspot.igv.data.serialization;
 
-import com.sun.hotspot.igv.data.Property;
 import com.sun.hotspot.igv.data.Properties;
 import java.util.HashMap;
 import java.util.Stack;
@@ -38,13 +37,6 @@
  */
 public class XMLParser implements ContentHandler {
 
-    public static interface ParseMonitor {
-
-        public void setProgress(double d);
-
-        public void setState(String state);
-    }
-
     public static class MissingAttributeException extends SAXException {
 
         private String name;
@@ -85,24 +77,25 @@
     public static class ElementHandler<T, P> {
 
         private String name;
-        private T object;
+        private Stack<T> object = new Stack<>();
         private Attributes attr;
         private StringBuilder currentText;
         private ParseMonitor monitor;
         private HashMap<String, ElementHandler<?, ? super T>> hashtable;
         private boolean needsText;
-        private ElementHandler<P, ?> parentElement;
+        private Stack<ElementHandler<P, ?>> parentElement = new Stack<>();
+        private Stack<P> parentObject = new Stack<>();
 
         public ElementHandler(String name) {
             this(name, false);
         }
 
         public ElementHandler<P, ?> getParentElement() {
-            return parentElement;
+            return parentElement.peek();
         }
 
         public P getParentObject() {
-            return getParentElement().getObject();
+            return parentObject.peek();
         }
 
         protected boolean needsText() {
@@ -110,7 +103,7 @@
         }
 
         public ElementHandler(String name, boolean needsText) {
-            this.hashtable = new HashMap<String, ElementHandler<?, ? super T>>();
+            this.hashtable = new HashMap<>();
             this.name = name;
             this.needsText = needsText;
         }
@@ -133,7 +126,7 @@
         }
 
         public T getObject() {
-            return object;
+            return object.size() == 0 ? null : object.peek();
         }
 
         public String readAttribute(String name) {
@@ -151,8 +144,8 @@
         public void processAttributesAsProperties(Properties p) {
             int length = attr.getLength();
             for (int i = 0; i < length; i++) {
-                String val = attr.getValue(i).intern();
-                String localName = attr.getLocalName(i).intern();
+                String val = attr.getValue(i);
+                String localName = attr.getLocalName(i);
                 p.setProperty(val, localName);
             }
         }
@@ -161,8 +154,9 @@
             this.currentText = new StringBuilder();
             this.attr = attr;
             this.monitor = monitor;
-            this.parentElement = parentElement;
-            object = start();
+            this.parentElement.push(parentElement);
+            parentObject.push(parentElement.getObject());
+            object.push(start());
         }
 
         protected T start() throws SAXException {
@@ -175,6 +169,9 @@
 
         public void endElement() throws SAXException {
             end(currentText.toString());
+            object.pop();
+            parentElement.pop();
+            parentObject.pop();
         }
 
         protected void text(char[] c, int start, int length) {
@@ -186,32 +183,37 @@
     private ParseMonitor monitor;
 
     public XMLParser(TopElementHandler rootHandler, ParseMonitor monitor) {
-        this.stack = new Stack<ElementHandler>();
+        this.stack = new Stack<>();
         this.monitor = monitor;
         this.stack.push(rootHandler);
     }
 
+    @Override
     public void setDocumentLocator(Locator locator) {
-        if (monitor != null) {
-            monitor.setState("Starting parsing");
-        }
+
     }
 
+    @Override
     public void startDocument() throws SAXException {
     }
 
+    @Override
     public void endDocument() throws SAXException {
     }
 
+    @Override
     public void startPrefixMapping(String prefix, String uri) throws SAXException {
     }
 
+    @Override
     public void endPrefixMapping(String prefix) throws SAXException {
     }
 
+    @SuppressWarnings("unchecked")
+    @Override
     public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
+        assert !stack.isEmpty();
 
-        assert !stack.isEmpty();
         ElementHandler parent = stack.peek();
         if (parent != null) {
             ElementHandler child = parent.getChild(qName);
@@ -225,6 +227,7 @@
         stack.push(null);
     }
 
+    @Override
     public void endElement(String uri, String localName, String qName) throws SAXException {
         ElementHandler handler = stack.pop();
         if (handler != null) {
@@ -232,6 +235,7 @@
         }
     }
 
+    @Override
     public void characters(char[] ch, int start, int length) throws SAXException {
 
         assert !stack.isEmpty();
@@ -243,12 +247,15 @@
         }
     }
 
+    @Override
     public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
     }
 
+    @Override
     public void processingInstruction(String target, String data) throws SAXException {
     }
 
+    @Override
     public void skippedEntity(String name) throws SAXException {
     }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLWriter.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLWriter.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -41,7 +41,7 @@
 
     public XMLWriter(Writer inner) {
         this.inner = inner;
-        elementStack = new Stack<String>();
+        elementStack = new Stack<>();
     }
 
     @Override
@@ -49,6 +49,7 @@
         write(arr, 0, arr.length);
     }
 
+    @Override
     public void write(char[] cbuf, int off, int len) throws IOException {
         for (int i = off; i < off + len; i++) {
             char c = cbuf[i];
@@ -64,10 +65,12 @@
         }
     }
 
+    @Override
     public void flush() throws IOException {
         inner.flush();
     }
 
+    @Override
     public void close() throws IOException {
         inner.close();
     }
@@ -111,7 +114,7 @@
     }
 
     public void writeProperties(Properties props) throws IOException {
-        if (props.getProperties().hasNext() == false) {
+        if (props.iterator().hasNext() == false) {
             return;
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/graphdocument.xsd	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
+    
+    <xsd:element name="graphDocument">
+        <xsd:complexType>
+            <xsd:sequence>
+                <xsd:element name="properties" type="propertiesType" minOccurs="0" maxOccurs="1" />
+                <xsd:element name="group" type="groupType" minOccurs="0" maxOccurs="unbounded" />
+            </xsd:sequence>
+        </xsd:complexType>
+    </xsd:element>
+
+    <xsd:complexType name="groupType">
+        <xsd:sequence>
+            <xsd:element name="properties" type="propertiesType" minOccurs="0" maxOccurs="1" />
+            <xsd:element name="assembly" type="assemblyType" minOccurs="0" maxOccurs="1" />
+            <xsd:element name="method" type="methodType" minOccurs="0" maxOccurs="1" />
+            <xsd:choice minOccurs="0" maxOccurs="unbounded" >
+                <xsd:element name="graph" type="graphType" />
+                <xsd:element name="group" type="groupType" />
+            </xsd:choice>
+        </xsd:sequence>
+        <xsd:attribute name="difference" use="optional" />
+    </xsd:complexType>
+    
+    <xsd:complexType name="propertiesType">
+        <xsd:sequence>
+            <xsd:element name="p" minOccurs="0" maxOccurs="unbounded">
+                <xsd:complexType>
+                    <xsd:simpleContent>
+                        <xsd:extension base="xsd:string">
+                            <xsd:attribute name="name" use="required" />
+                        </xsd:extension>
+                    </xsd:simpleContent>
+                </xsd:complexType>
+            </xsd:element>
+        </xsd:sequence>
+    </xsd:complexType>
+    
+    <xsd:simpleType name="assemblyType">
+        <xsd:restriction base="xsd:string" />
+    </xsd:simpleType>
+    
+    <xsd:complexType name="methodType">
+        <xsd:all>
+            <xsd:element name="properties" type="propertiesType" minOccurs="0" maxOccurs="1" />
+            <xsd:element name="bytecodes" minOccurs="0" maxOccurs="1">
+                <xsd:simpleType>
+                    <xsd:restriction base="xsd:string" />
+                </xsd:simpleType>
+            </xsd:element>
+            <xsd:element name="inlined" minOccurs="0" maxOccurs="1">
+                <xsd:complexType>
+                    <xsd:sequence>
+                        <xsd:element name="method" type="methodType" minOccurs="0" maxOccurs="unbounded" />
+                    </xsd:sequence>
+                </xsd:complexType>
+            </xsd:element>
+        </xsd:all>
+        <xsd:attribute name="bci" type="xsd:int" use="required" />
+        <xsd:attribute name="shortName" type="xsd:string" use="required" />
+        <xsd:attribute name="name" type="xsd:string" use="required" />
+    </xsd:complexType>
+    
+    <xsd:complexType name="graphType">
+        <xsd:sequence>
+            <xsd:element name="properties" type="propertiesType" minOccurs="0" maxOccurs="1" />
+            
+            <xsd:element name="nodes" minOccurs="0" maxOccurs="1">
+                <xsd:complexType>
+                    <xsd:sequence>
+                        <xsd:choice minOccurs="0" maxOccurs="unbounded">
+                            <xsd:element name="node" type="nodeType" />
+                            <xsd:element name="removeNode" type="nodeRefType" />
+                        </xsd:choice>
+                    </xsd:sequence>
+                </xsd:complexType>
+            </xsd:element>
+            
+            <xsd:element name="edges" minOccurs="0" maxOccurs="1">
+                <xsd:complexType>
+                    <xsd:sequence>
+                        <xsd:choice minOccurs="0" maxOccurs="unbounded">
+                            <xsd:element name="edge" type="edgeType" />
+                            <xsd:element name="removeEdge" type="edgeType" />
+                        </xsd:choice>
+                    </xsd:sequence>
+                </xsd:complexType>
+            </xsd:element>
+            
+            <xsd:element name="controlFlow" type="controlFlowType" minOccurs="0" maxOccurs="1" />
+        </xsd:sequence>
+        
+        <xsd:attribute name="name" use="optional" />
+    </xsd:complexType>
+    
+    <xsd:complexType name="nodeType">
+        <xsd:sequence>
+            <xsd:element name="properties" type="propertiesType" minOccurs="0" maxOccurs="1" />
+        </xsd:sequence>
+        <xsd:attribute name="id" type="xsd:int" use="required" />
+    </xsd:complexType>
+    
+    <xsd:complexType name="nodeRefType">
+        <xsd:attribute name="id" type="xsd:int" use="required" />
+    </xsd:complexType>
+    
+    <xsd:complexType name="edgeType">
+        <xsd:attribute name="from" type="xsd:int" use="required" />
+        <xsd:attribute name="to" type="xsd:int" use="required" />
+        <xsd:attribute name="label" type="xsd:string" use="optional" />
+        <xsd:attribute name="type" type="xsd:string" use="optional" />
+        <xsd:attribute name="fromIndex" type="xsd:int" use="optional" />
+        
+        <!-- These are aliases and should be mutually exclusive -->
+        <xsd:attribute name="toIndex" type="xsd:int" use="optional" />
+        <xsd:attribute name="index" type="xsd:int" use="optional" />
+    </xsd:complexType>
+    
+    <xsd:complexType name="controlFlowType">
+        <xsd:sequence>
+            <xsd:element name="block" type="blockType" minOccurs="0" maxOccurs="unbounded" />
+        </xsd:sequence>
+    </xsd:complexType>
+    
+    <xsd:complexType name="blockType">
+        <xsd:all>
+            <xsd:element name="successors" minOccurs="0" maxOccurs="1">
+                <xsd:complexType>
+                    <xsd:sequence>
+                        <xsd:element name="successor" minOccurs="0" maxOccurs="unbounded">
+                            <xsd:complexType>
+                                <xsd:attribute name="name" type="xsd:string" use="required" />
+                            </xsd:complexType>
+                        </xsd:element>
+                    </xsd:sequence>
+                </xsd:complexType>
+            </xsd:element>
+            <xsd:element name="nodes" minOccurs="0" maxOccurs="1">
+                <xsd:complexType>
+                    <xsd:sequence>
+                        <xsd:element name="node" type="nodeRefType" minOccurs="0" maxOccurs="unbounded" />
+                    </xsd:sequence>
+                </xsd:complexType>
+            </xsd:element>    
+        </xsd:all>
+        
+        <xsd:attribute name="name" type="xsd:string" use="required" />
+    </xsd:complexType>
+</xsd:schema>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/GraphViewer.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/GraphViewer.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -31,5 +31,5 @@
  */
 public interface GraphViewer {
 
-    public void view(InputGraph graph);
+    public void view(InputGraph graph, boolean clone);
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/GroupCallback.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/GroupCallback.java	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, 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
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/GroupOrganizer.java	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * 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.data.services;
-
-import com.sun.hotspot.igv.data.Group;
-import com.sun.hotspot.igv.data.Pair;
-import java.util.List;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public interface GroupOrganizer {
-
-    public String getName();
-
-    public List<Pair<String, List<Group>>> organize(List<String> subFolders, List<Group> groups);
-}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/GroupReceiver.java	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * 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.data.services;
-
-import java.awt.Component;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public interface GroupReceiver {
-
-    public Component init(GroupCallback callback);
-}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/InputGraphProvider.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/InputGraphProvider.java	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, 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
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/Scheduler.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/Scheduler.java	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/ChangedEventTest.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,95 @@
+/*
+ * 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.data;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ChangedEventTest {
+
+    public ChangedEventTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    /**
+     * Test of addListener method, of class Event.
+     */
+    @Test
+    public void testBase() {
+
+        ChangedEvent<Integer> e = new ChangedEvent<>(5);
+        final int[] fireCount = new int[1];
+
+        e.addListener(new ChangedListener<Integer>() {
+            @Override
+            public void changed(Integer s) {
+                assertEquals(s.intValue(), 5);
+                fireCount[0]++;
+            }
+        });
+
+        e.fire();
+        assertEquals(1, fireCount[0]);
+
+        e.fire();
+        assertEquals(2, fireCount[0]);
+
+        e.beginAtomic();
+
+        e.fire();
+        assertEquals(2, fireCount[0]);
+
+        e.fire();
+        assertEquals(2, fireCount[0]);
+
+        e.fire();
+        assertEquals(2, fireCount[0]);
+
+        e.endAtomic();
+        assertEquals(3, fireCount[0]);
+
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/ControllableChangedListenerTest.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,93 @@
+/*
+ * 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.data;
+
+import static org.junit.Assert.*;
+import org.junit.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ControllableChangedListenerTest {
+
+    public ControllableChangedListenerTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    /**
+     * Test of isEnabled method, of class ControllableChangedListener.
+     */
+    @Test
+    public void testBase() {
+
+        final boolean[] hasFired = new boolean[1];
+        final boolean[] shouldFire = new boolean[1];
+        final Integer[] valueToFire = new Integer[1];
+        ControllableChangedListener<Integer> l = new ControllableChangedListener<Integer>() {
+
+            @Override
+            public void filteredChanged(Integer value) {
+                assertTrue(shouldFire[0]);
+                assertEquals(valueToFire[0], value);
+                hasFired[0] = true;
+            }
+        };
+
+        shouldFire[0] = true;
+        valueToFire[0] = 1;
+        hasFired[0] = false;
+        l.changed(1);
+        assertTrue(hasFired[0]);
+
+        shouldFire[0] = false;
+        hasFired[0] = false;
+        l.setEnabled(false);
+        l.changed(1);
+        assertFalse(hasFired[0]);
+
+        shouldFire[0] = true;
+        valueToFire[0] = 1;
+        hasFired[0] = false;
+        l.setEnabled(true);
+        l.changed(1);
+        assertTrue(hasFired[0]);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/GroupTest.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,74 @@
+/*
+ * 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.data;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import static org.junit.Assert.assertEquals;
+import org.junit.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class GroupTest {
+
+    public GroupTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    /**
+     * Test of getAllNodes method, of class Group.
+     */
+    @Test
+    public void testGetAllNodes() {
+        final Group g = new Group(null);
+        final InputGraph graph1 = new InputGraph("1");
+        final InputGraph graph2 = new InputGraph("2");
+        g.addElement(graph1);
+        g.addElement(graph2);
+        graph1.addNode(new InputNode(1));
+        graph1.addNode(new InputNode(2));
+        graph2.addNode(new InputNode(2));
+        graph2.addNode(new InputNode(3));
+        assertEquals(g.getAllNodes(), new HashSet(Arrays.asList(1, 2, 3)));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/InputGraphTest.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,211 @@
+/*
+ * 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.data;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import org.junit.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class InputGraphTest {
+
+    /**
+     *    1
+     *   / \
+     *  2   3
+     *   \  |  5
+     *    \ | /
+     *      4
+     */
+    private static InputGraph referenceGraph;
+
+    private static InputGraph emptyGraph;
+
+    private static final InputNode N1 = new InputNode(1);
+    private static final InputNode N2 = new InputNode(2);
+    private static final InputNode N3 = new InputNode(3);
+    private static final InputNode N4 = new InputNode(4);
+    private static final InputNode N5 = new InputNode(5);
+    private static final InputEdge E12 = new InputEdge((char)0, 1, 2);
+    private static final InputEdge E13 = new InputEdge((char)0, 1, 3);
+    private static final InputEdge E24 = new InputEdge((char)0, 2, 4);
+    private static final InputEdge E34 = new InputEdge((char)0, 3, 4);
+    private static final InputEdge E54 = new InputEdge((char)0, 5, 4);
+
+    public InputGraphTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+        Group group = new Group(null);
+
+        emptyGraph = new InputGraph("emptyGraph");
+        group.addElement(emptyGraph);
+
+        referenceGraph = new InputGraph("referenceGraph");
+        group.addElement(referenceGraph);
+        referenceGraph.addNode(N1);
+        referenceGraph.addNode(N2);
+        referenceGraph.addNode(N3);
+        referenceGraph.addNode(N4);
+        referenceGraph.addNode(N5);
+
+        referenceGraph.addEdge(E12);
+        referenceGraph.addEdge(E13);
+        referenceGraph.addEdge(E24);
+        referenceGraph.addEdge(E34);
+        referenceGraph.addEdge(E54);
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    /**
+     * Test of equals method, of class InputGraph.
+     */
+    @Test
+    public void testEquals() {
+
+        Group parentA = new Group(null);
+        InputGraph a = new InputGraph("graph");
+        parentA.addElement(a);
+
+        Group parentB = new Group(null);
+        InputGraph b = new InputGraph("graph");
+        parentB.addElement(b);
+
+        InputGraph c = new InputGraph("graph");
+        parentB.addElement(b);
+
+        Util.assertGraphEquals(a, b);
+        Util.assertGraphEquals(b, c);
+
+        a.addNode(new InputNode(1));
+        Util.assertGraphNotEquals(a, b);
+
+        b.addNode(new InputNode(1));
+        Util.assertGraphEquals(a, b);
+    }
+
+    /**
+     * Test of findRootNodes method, of class InputGraph.
+     */
+    @Test
+    public void testFindRootNodes() {
+        assertTrue(emptyGraph.findRootNodes().isEmpty());
+
+        List<InputNode> result = referenceGraph.findRootNodes();
+        assertTrue(result.size() == 2);
+        assertTrue(result.contains(N1));
+        assertTrue(result.contains(N5));
+    }
+
+    /**
+     * Test of findAllOutgoingEdges method, of class InputGraph.
+     */
+    @Test
+    public void testFindAllOutgoingEdges() {
+        assertTrue(emptyGraph.findAllOutgoingEdges().isEmpty());
+
+        Map<InputNode, List<InputEdge>> result = referenceGraph.findAllOutgoingEdges();
+        assertTrue(result.size() == 5);
+        assertEquals(result.get(N1), Arrays.asList(E12, E13));
+        assertEquals(result.get(N2), Arrays.asList(E24));
+        assertEquals(result.get(N3), Arrays.asList(E34));
+        assertEquals(result.get(N4), Arrays.asList());
+        assertEquals(result.get(N5), Arrays.asList(E54));
+    }
+
+    /**
+     * Test of findAllIngoingEdges method, of class InputGraph.
+     */
+    @Test
+    public void testFindAllIngoingEdges() {
+        assertTrue(emptyGraph.findAllIngoingEdges().isEmpty());
+
+        Map<InputNode, List<InputEdge>> result = referenceGraph.findAllIngoingEdges();
+        assertTrue(result.size() == 5);
+        assertEquals(result.get(N1), Arrays.asList());
+        assertEquals(result.get(N2), Arrays.asList(E12));
+        assertEquals(result.get(N3), Arrays.asList(E13));
+        assertEquals(result.get(N4), Arrays.asList(E24, E34, E54));
+        assertEquals(result.get(N5), Arrays.asList());
+    }
+
+    /**
+     * Test of findOutgoingEdges method, of class InputGraph.
+     */
+    @Test
+    public void testFindOutgoingEdges() {
+        assertTrue(emptyGraph.findOutgoingEdges(new InputNode(1)).isEmpty());
+
+        assertEquals(referenceGraph.findOutgoingEdges(N1), Arrays.asList(E12, E13));
+        assertEquals(referenceGraph.findOutgoingEdges(N2), Arrays.asList(E24));
+        assertEquals(referenceGraph.findOutgoingEdges(N3), Arrays.asList(E34));
+        assertEquals(referenceGraph.findOutgoingEdges(N4), Arrays.asList());
+        assertEquals(referenceGraph.findOutgoingEdges(N5), Arrays.asList(E54));
+    }
+
+    /**
+     * Test of getNext method, of class InputGraph.
+     */
+    @Test
+    public void testGetNextPrev() {
+        final Group group = new Group(null);
+
+        final InputGraph a = new InputGraph("a");
+
+        final InputGraph b = new InputGraph("b");
+
+        final InputGraph c = new InputGraph("c");
+        group.addElement(a);
+        group.addElement(b);
+        group.addElement(c);
+
+        assertEquals(null, a.getPrev());
+        assertEquals(b, a.getNext());
+
+        assertEquals(a, b.getPrev());
+        assertEquals(c, b.getNext());
+
+        assertEquals(b, c.getPrev());
+        assertEquals(null, c.getNext());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/InputMethodTest.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2011, 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.data;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+import org.junit.*;
+
+/**
+ *
+ * @author Thomas
+ */
+public class InputMethodTest {
+
+    public InputMethodTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+
+    /**
+     * Test of getBytecodes method, of class InputMethod.
+     */
+    @Test
+    public void testGetSetBytecodes() {
+
+        final String input = "0 iload_0\n" +
+                             "1 iconst_1\n" +
+                             "2 if_icmpne 7\n" +
+                             "5 iconst_1\n" +
+                             "6 ireturn\n" +
+                             "7 iconst_0\n" +
+                             "8 ireturn";
+
+        final Group g = new Group(null);
+        InputMethod m = new InputMethod(g, "name", "shortName", -1);
+        m.setBytecodes(input);
+
+        assertThat(m.getBytecodes().size(), is(7));
+
+        assertThat(m.getBytecodes().get(0).getBci(), is(0));
+        assertThat(m.getBytecodes().get(1).getBci(), is(1));
+        assertThat(m.getBytecodes().get(2).getBci(), is(2));
+        assertThat(m.getBytecodes().get(3).getBci(), is(5));
+
+        assertThat(m.getBytecodes().get(0).getName(), is("iload_0"));
+        assertThat(m.getBytecodes().get(1).getName(), is("iconst_1"));
+        assertThat(m.getBytecodes().get(2).getName(), is("if_icmpne 7"));
+        assertThat(m.getBytecodes().get(6).getName(), is("ireturn"));
+
+        assertThat(m.getBytecodes().get(2).getInlined(), nullValue());
+        assertThat(m.getBytecodes().get(6).getInlined(), nullValue());
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/PairTest.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,98 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.data;
+
+import static org.junit.Assert.*;
+import org.junit.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class PairTest {
+
+    public PairTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    /**
+     * Test of getLeft method, of class Pair.
+     */
+    @Test
+    public void testBase() {
+        Pair p = new Pair();
+        assertTrue(p.getLeft() == null);
+        assertTrue(p.getRight() == null);
+        assertEquals("[null/null]", p.toString());
+        assertFalse(p.equals(null));
+
+        Pair<Integer, Integer> p2 = new Pair(1, 2);
+        assertTrue(p2.getLeft().intValue() == 1);
+        assertTrue(p2.getRight().intValue() == 2);
+        assertFalse(p.equals(p2));
+        assertFalse(p2.equals(p));
+        assertFalse(p.hashCode() == p2.hashCode());
+        assertEquals("[1/2]", p2.toString());
+
+        Pair p3 = new Pair(1, 2);
+        assertTrue(p2.equals(p3));
+        assertTrue(p2.hashCode() == p3.hashCode());
+
+        p2.setLeft(2);
+        assertFalse(p2.equals(p3));
+        assertTrue(p2.getLeft().intValue() == 2);
+        assertTrue(p2.getRight().intValue() == 2);
+        assertFalse(p2.hashCode() == p3.hashCode());
+        assertEquals("[2/2]", p2.toString());
+
+        p2.setRight(1);
+        assertFalse(p2.equals(p3));
+        assertTrue(p2.getLeft().intValue() == 2);
+        assertTrue(p2.getRight().intValue() == 1);
+        assertFalse(p2.hashCode() == p3.hashCode());
+        assertEquals("[2/1]", p2.toString());
+
+        p3.setLeft(2);
+        p3.setRight(1);
+        assertTrue(p2.hashCode() == p3.hashCode());
+        assertTrue(p2.equals(p3));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/PropertiesTest.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,401 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.data;
+
+import com.sun.hotspot.igv.data.Properties.InvertPropertyMatcher;
+import com.sun.hotspot.igv.data.Properties.PropertyMatcher;
+import com.sun.hotspot.igv.data.Properties.PropertySelector;
+import com.sun.hotspot.igv.data.Properties.RegexpPropertyMatcher;
+import com.sun.hotspot.igv.data.Properties.StringPropertyMatcher;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import junit.framework.TestCase;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class PropertiesTest extends TestCase {
+
+
+
+    public PropertiesTest(String testName) {
+        super(testName);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * Test of equals method, of class Properties.
+     */
+    public void testEquals() {
+        Properties a = new Properties();
+        assertFalse(a.equals(null));
+        assertTrue(a.equals(a));
+
+        Properties b = new Properties();
+        assertTrue(a.equals(b));
+        assertTrue(a.hashCode() == b.hashCode());
+
+        a.setProperty("p1", "1");
+        assertFalse(a.equals(b));
+        assertFalse(b.equals(a));
+        assertFalse(a.hashCode() == b.hashCode());
+
+        b.setProperty("p1", "1");
+        assertTrue(a.equals(b));
+        assertTrue(a.hashCode() == b.hashCode());
+
+        Properties c = new Properties(a);
+        assertTrue(c.equals(a));
+        assertTrue(c.equals(b));
+
+        c.setProperty("p1", "2");
+        assertFalse(c.equals(b));
+        assertFalse(c.hashCode() == b.hashCode());
+        assertFalse(c.equals(a));
+        assertFalse(c.hashCode() == a.hashCode());
+
+        a.setProperty("p2", "2");
+        Properties d = new Properties();
+        d.setProperty("p2", "2");
+        d.setProperty("p1", "1");
+        assertTrue(d.equals(a));
+    }
+
+    /**
+     * Test of selectSingle method, of class Properties.
+     */
+    public void testSelectSingle() {
+
+        final boolean[] called = new boolean[1];
+        final String v = "2";
+        final String n = "p2";
+
+        PropertyMatcher matcher = new PropertyMatcher() {
+
+            @Override
+            public String getName() {
+                assertFalse(called[0]);
+                called[0] = true;
+                return n;
+            }
+
+            @Override
+            public boolean match(String value) {
+                assertTrue(v.equals(value));
+                return true;
+            }
+        };
+
+        Properties instance = new Properties();
+        instance.setProperty("p1", "1");
+        instance.setProperty(n, v);
+        instance.setProperty("p3", "3");
+        Property result = instance.selectSingle(matcher);
+        assertEquals(result, new Property(n, v));
+
+
+        called[0] = false;
+        PropertyMatcher matcher2 = new PropertyMatcher() {
+
+            @Override
+            public String getName() {
+                assertFalse(called[0]);
+                called[0] = true;
+                return n;
+            }
+
+            @Override
+            public boolean match(String value) {
+                return false;
+            }
+        };
+
+
+        Property result2 = instance.selectSingle(matcher2);
+        assertTrue(result2 == null);
+    }
+
+    /**
+     * Test of get method, of class Properties.
+     */
+    public void testGet() {
+        Properties instance = new Properties();
+        instance.setProperty("p1", "1");
+        assertEquals("1", instance.get("p1"));
+        assertEquals(null, instance.get("p2"));
+    }
+
+    /**
+     * Test of getProperties method, of class Properties.
+     */
+    public void testIterator() {
+        Properties instance = new Properties();
+        instance.setProperty("p1", "1");
+        instance.setProperty("p2", "2");
+        Iterator<Property> result = instance.iterator();
+        assertTrue(result.hasNext());
+        assertEquals(new Property("p1", "1"), result.next());
+        assertTrue(result.hasNext());
+        assertEquals(new Property("p2", "2"), result.next());
+        assertFalse(result.hasNext());
+        assertTrue(result.next() == null);
+
+        try {
+            result.remove();
+            fail();
+        } catch(UnsupportedOperationException e) {}
+    }
+
+    /**
+     * Test of add method, of class Properties.
+     */
+    public void testAdd() {
+        Properties a = new Properties();
+        a.setProperty("p1", "1");
+        a.setProperty("p2", "2");
+
+        Properties b = new Properties();
+        b.setProperty("p1", "1");
+
+        Properties c = new Properties();
+        c.setProperty("p2", "2");
+
+        assertFalse(a.equals(b));
+        b.add(c);
+
+        assertTrue(a.equals(b));
+
+        b.setProperty("p3", null);
+        assertTrue(a.equals(b));
+
+        Properties empty = new Properties();
+        b.add(empty);
+        assertTrue(a.equals(b));
+
+        empty.add(b);
+        assertTrue(a.equals(empty));
+    }
+
+
+    /**
+     * Test the multiple argument constructors.
+     */
+    public void testConstructors() {
+        Properties a = new Properties("p1", "1", "p2", "2", "p3", "3");
+        Properties b = new Properties("p1", "1", "p2", "2");
+        Properties c = new Properties("p1", "1");
+
+        assertTrue(a.get("p3").equals("3"));
+        assertTrue(b.get("p2").equals("2"));
+        assertTrue(b.get("p1").equals("1"));
+
+        b.setProperty("p3", "3");
+        c.setProperty("p2", "2");
+        c.setProperty("p3", "3");
+
+        assertTrue(a.equals(b));
+        assertTrue(a.equals(c));
+    }
+
+    /**
+     * Test Entity class
+     */
+    public void testEntity() {
+
+        Properties p = new Properties();
+
+        Properties.Entity entity = new Properties.Entity();
+        assertEquals(entity.getProperties(), p);
+
+        entity.getProperties().setProperty("p1", "1");
+        Properties.Entity entity2 = new Properties.Entity(entity);
+        assertEquals(entity.getProperties(), entity2.getProperties());
+    }
+
+    /**
+     * Test property selector
+     */
+    public void testPropertySelector() {
+        final Collection<Properties.Entity> c = new ArrayList<>();
+
+        final Properties.Entity e1 = new Properties.Entity();
+        e1.getProperties().setProperty("p1", "1");
+        e1.getProperties().setProperty("p2", "2");
+        c.add(e1);
+
+        final Properties.Entity e2 = new Properties.Entity();
+        e2.getProperties().setProperty("p2", "2");
+        e2.getProperties().setProperty("p1", "1");
+        e2.getProperties().setProperty("p3", "3");
+        c.add(e2);
+
+        final Properties.Entity e3 = new Properties.Entity();
+        e3.getProperties().setProperty("p3", "3");
+        e3.getProperties().setProperty("p4", "4");
+        c.add(e3);
+
+        final PropertySelector<Properties.Entity> sel = new PropertySelector<>(c);
+
+        final StringPropertyMatcher matcher1 = new StringPropertyMatcher("p2", "2");
+        assertTrue(sel.selectMultiple(matcher1).size() == 2);
+        assertTrue(sel.selectMultiple(matcher1).contains(e1));
+        assertTrue(sel.selectMultiple(matcher1).contains(e2));
+        assertTrue(sel.selectSingle(matcher1).equals(e1) || sel.selectSingle(matcher1).equals(e2));
+
+        final StringPropertyMatcher matcher2 = new StringPropertyMatcher("p3", "3");
+        assertTrue(sel.selectMultiple(matcher2).size() == 2);
+        assertTrue(sel.selectMultiple(matcher2).contains(e2));
+        assertTrue(sel.selectMultiple(matcher2).contains(e3));
+        assertTrue(sel.selectSingle(matcher2).equals(e2) || sel.selectSingle(matcher2).equals(e3));
+
+        final StringPropertyMatcher matcher3 = new StringPropertyMatcher("p4", "4");
+        assertTrue(sel.selectMultiple(matcher3).size() == 1);
+        assertTrue(sel.selectMultiple(matcher3).contains(e3));
+        assertTrue(sel.selectSingle(matcher3).equals(e3));
+
+        final StringPropertyMatcher matcher4 = new StringPropertyMatcher("p5", "5");
+        assertTrue(sel.selectMultiple(matcher4).size() == 0);
+        assertTrue(sel.selectSingle(matcher4) == null);
+    }
+
+    public void testRemoveProperty() {
+        final Properties p = new Properties();
+        p.setProperty("p1", "1");
+        p.setProperty("p2", "2");
+
+        assertTrue(p.get("p1").equals("1"));
+        assertTrue(p.get("p2").equals("2"));
+
+        p.setProperty("p1", null);
+        assertTrue(p.get("p1") == null);
+        assertTrue(p.get("p2").equals("2"));
+
+        p.setProperty("p2", null);
+        assertTrue(p.get("p1") == null);
+        assertTrue(p.get("p2") == null);
+
+        p.setProperty("p3", "3");
+        assertTrue(p.get("p1") == null);
+        assertTrue(p.get("p2") == null);
+        assertTrue(p.get("p3").equals("3"));
+    }
+
+    /**
+     * Test property matchers
+     */
+    public void testPropertyMatchers() {
+        final StringPropertyMatcher matcher = new StringPropertyMatcher("p1", "1");
+        assertTrue(matcher.getName().equals("p1"));
+        assertTrue(matcher.match("1"));
+        assertFalse(matcher.match("2"));
+        try {
+            matcher.match(null);
+            fail();
+        } catch(IllegalArgumentException e) {}
+
+        try {
+            new StringPropertyMatcher(null, "**");
+            fail();
+        } catch(IllegalArgumentException e) {}
+
+        try {
+            new StringPropertyMatcher("p1", null);
+            fail();
+        } catch(IllegalArgumentException e) {}
+
+        final RegexpPropertyMatcher matcher2 = new RegexpPropertyMatcher("p1", "C.*");
+        assertTrue(matcher2.getName().equals("p1"));
+        assertTrue(matcher2.match("C"));
+        assertTrue(matcher2.match("Casdf"));
+        assertFalse(matcher2.match(" C"));
+        assertFalse(matcher2.match("c"));
+        assertFalse(matcher2.match("asdfC"));
+
+        try {
+            matcher2.match(null);
+            fail();
+        } catch(IllegalArgumentException e) {}
+
+        try {
+            new RegexpPropertyMatcher("p1", "**");
+            fail();
+        } catch(IllegalArgumentException e) {}
+
+        try {
+            new RegexpPropertyMatcher(null, "1");
+            fail();
+        } catch(IllegalArgumentException e) {}
+
+        try {
+            new RegexpPropertyMatcher("p1", null);
+            fail();
+        } catch(IllegalArgumentException e) {}
+
+        final InvertPropertyMatcher matcher3 = new InvertPropertyMatcher(matcher);
+        assertTrue(matcher3.getName().equals("p1"));
+        assertFalse(matcher3.match("1"));
+        assertTrue(matcher3.match("2"));
+        assertFalse(matcher3.match(null));
+    }
+
+    public void testToString() {
+        Properties p = new Properties();
+        assertEquals(p.toString(), "[]");
+
+        p.setProperty("p1", "1");
+        assertEquals(p.toString(), "[p1=1]");
+
+        Properties p2 = new Properties();
+        p2.setProperty("p1", "1");
+        p2.setProperty("p2", "2");
+        assertEquals(p2.toString(), "[p1=1, p2=2]");
+
+        Properties p3 = new Properties();
+        p3.setProperty("p2", "2");
+        p3.setProperty("p1", "1");
+        assertEquals(p3.toString(), "[p1=1, p2=2]");
+
+        p3.setProperty("p0", "0");
+        assertEquals(p3.toString(), "[p0=0, p1=1, p2=2]");
+
+        p2.setProperty("p1", null);
+        assertEquals(p2.toString(), "[p2=2]");
+
+        p2.setProperty("p2", null);
+        assertEquals(p2.toString(), "[]");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/PropertyTest.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,116 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.data;
+
+import static org.junit.Assert.*;
+import org.junit.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class PropertyTest {
+
+    public PropertyTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    /**
+     * Test of getName method, of class Property.
+     */
+    @Test
+    public void testGetNameAndValue() {
+        final Property p = new Property("name", "value");
+        assertEquals(p.getName(), "name");
+        assertEquals(p.getValue(), "value");
+
+        try {
+            new Property(null, "value");
+            fail();
+        } catch(IllegalArgumentException e) {
+        }
+
+
+        try {
+            new Property("name", null);
+            fail();
+        } catch(IllegalArgumentException e) {
+        }
+    }
+
+    /**
+     * Test of toString method, of class Property.
+     */
+    @Test
+    public void testToString() {
+        final Property p = new Property("name", "value");
+        assertEquals(p.toString(), "name=value");
+    }
+
+    /**
+     * Test of equals method, of class Property.
+     */
+    @Test
+    public void testEquals() {
+        final Property p = new Property("name", "value");
+        final Object o = new Object();
+        assertFalse(p.equals(o));
+        assertFalse(p.equals(null));
+        assertTrue(p.equals(p));
+
+        final Property p2 = new Property("name", "value1");
+        assertFalse(p.equals(p2));
+        assertTrue(p.hashCode() != p2.hashCode());
+
+        final Property p3 = new Property("name2", "value");
+        assertFalse(p.equals(p3));
+        assertTrue(p.hashCode() != p3.hashCode());
+        assertTrue(p2.hashCode() != p3.hashCode());
+
+        final Property p4 = new Property("name", "value");
+        assertEquals(p, p4);
+        assertEquals(p.hashCode(), p4.hashCode());
+
+        final Property p5 = new Property("value", "name");
+        assertFalse(p.equals(p5));
+        assertTrue(p.hashCode() != p5.hashCode());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/SourceTest.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2011, 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.data;
+
+import java.util.Arrays;
+import java.util.LinkedHashSet;
+import static org.junit.Assert.assertEquals;
+import org.junit.*;
+
+/**
+ *
+ * @author Thomas
+ */
+public class SourceTest {
+
+    public SourceTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    /**
+     * Test of getSourceNodes method, of class Source.
+     */
+    @Test
+    public void testBase() {
+        final Source s = new Source();
+
+        final InputNode N1 = new InputNode(1);
+        final InputNode N2 = new InputNode(2);
+
+        s.addSourceNode(N1);
+        assertEquals(s.getSourceNodes(), Arrays.asList(N1));
+        assertEquals(s.getSourceNodesAsSet(), new LinkedHashSet<>(Arrays.asList(1)));
+
+        s.addSourceNode(N2);
+        assertEquals(s.getSourceNodes(), Arrays.asList(N1, N2));
+        assertEquals(s.getSourceNodesAsSet(), new LinkedHashSet<>(Arrays.asList(1, 2)));
+
+        s.addSourceNode(N1);
+        assertEquals(s.getSourceNodes(), Arrays.asList(N1, N2));
+        assertEquals(s.getSourceNodesAsSet(), new LinkedHashSet<>(Arrays.asList(1, 2)));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/Util.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,126 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.data;
+
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class Util {
+
+    public static void assertGraphDocumentNotEquals(GraphDocument a, GraphDocument b) {
+        try {
+            assertGraphDocumentEquals(a, b);
+        } catch(AssertionError e) {
+            return;
+        }
+
+        fail("Graphs documents are equal!");
+    }
+
+    public static void assertGraphDocumentEquals(GraphDocument a, GraphDocument b) {
+
+        if (a.getElements().size() != b.getElements().size()) {
+            fail();
+        }
+
+        int z = 0;
+        for (FolderElement e : b.getElements()) {
+
+            if (e instanceof Group) {
+                Group g = (Group) e;
+                Group thisG = (Group) a.getElements().get(z);
+                assertGroupEquals(thisG, g);
+            z++;
+            }
+        }
+    }
+
+    public static void assertGroupNotEquals(Group a, Group b) {
+        try {
+            assertGroupEquals(a, b);
+        } catch(AssertionError e) {
+            return;
+        }
+
+        fail("Groups are equal!");
+    }
+
+    public static void assertGroupEquals(Group a, Group b) {
+
+        if (a.getGraphsCount() != b.getGraphsCount()) {
+            fail();
+        }
+
+        int z = 0;
+        for (InputGraph graph : a.getGraphs()) {
+            InputGraph otherGraph = b.getGraphs().get(z);
+            assertGraphEquals(graph, otherGraph);
+            z++;
+        }
+
+        if (a.getMethod() == null || b.getMethod() == null) {
+            if (a.getMethod() != b.getMethod()) {
+                fail();
+            }
+        } else {
+            if (!a.getMethod().equals(b.getMethod())) {
+                fail();
+            }
+        }
+    }
+
+    public static void assertGraphNotEquals(InputGraph a, InputGraph b) {
+        try {
+            assertGraphEquals(a, b);
+        } catch(AssertionError e) {
+            return;
+        }
+
+        fail("Graphs are equal!");
+    }
+
+    public static void assertGraphEquals(InputGraph a, InputGraph b) {
+
+        if(!a.getNodesAsSet().equals(b.getNodesAsSet())) {
+            fail();
+        }
+
+        if (!a.getEdges().equals(b.getEdges())) {
+            fail();
+        }
+
+        if (a.getBlocks().equals(b.getBlocks())) {
+            fail();
+        }
+
+        for (InputNode n : a.getNodes()) {
+            assertEquals(a.getBlock(n), b.getBlock(n));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/serialization/ParserTest.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,225 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.data.serialization;
+
+import com.sun.hotspot.igv.data.*;
+import java.io.*;
+import java.nio.channels.Channels;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import org.junit.*;
+import org.openide.util.Exceptions;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ParserTest {
+
+    public ParserTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    private void test(GraphDocument document) {
+        final Printer printer = new Printer();
+        final CharArrayWriter writer = new CharArrayWriter();
+        printer.export(writer, document);
+        test(document, writer.toString());
+    }
+
+    private void test(GraphDocument document, String xmlString) {
+        try {
+            InputStream in = new ByteArrayInputStream(xmlString.getBytes("UTF-8"));
+            try {
+                Parser parser = new Parser(Channels.newChannel(in));
+                final GraphDocument parsedDocument = parser.parse();
+                Util.assertGraphDocumentEquals(document, parsedDocument);
+            } catch (SAXException ex) {
+                fail(ex.toString());
+            }
+        } catch (UnsupportedEncodingException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+    }
+
+    private void testBoth(GraphDocument document, String xmlString) {
+        test(document);
+        test(document, xmlString);
+    }
+
+    /**
+     * Test of graph document serialization
+     */
+    @Test
+    public void testSerialization() {
+        final GraphDocument doc = new GraphDocument();
+
+        test(doc);
+
+        final Group group1 = new Group(doc);
+        doc.addElement(group1);
+        test(doc);
+
+        final Group group2 = new Group(doc);
+        doc.addElement(group2);
+        test(doc);
+
+        final InputGraph graph = new InputGraph("");
+        group1.addElement(graph);
+        test(doc);
+
+        graph.addNode(new InputNode(0));
+        test(doc);
+
+        graph.addNode(new InputNode(1));
+        test(doc);
+
+        graph.addNode(new InputNode(2));
+        test(doc);
+
+        graph.addNode(new InputNode(3));
+        test(doc);
+
+        graph.addEdge(new InputEdge((char)0, (char)0, 0, 1));
+        test(doc);
+
+        graph.addEdge(new InputEdge((char)1, (char)1, 0, 1));
+        test(doc);
+
+        graph.addEdge(new InputEdge((char)0, (char)0, 1, 2));
+        test(doc);
+
+        graph.addEdge(new InputEdge((char)0, (char)0, 2, 3));
+        test(doc);
+
+        group1.setMethod(new InputMethod(group1, "testMethod", "tM", 1));
+        test(doc);
+
+        final InputBlock b1 = graph.addBlock("1");
+        b1.addNode(0);
+        b1.addNode(1);
+
+        final InputBlock b2 = graph.addBlock("2");
+        b2.addNode(2);
+        b2.addNode(3);
+        test(doc);
+
+        final GraphDocument document2 = new GraphDocument();
+        doc.addGraphDocument(document2);
+        test(doc);
+        assertTrue(doc.getElements().size() == 2);
+
+        final Group group3 = new Group(document2);
+        document2.addElement(group3);
+        doc.addGraphDocument(document2);
+        assertTrue(doc.getElements().size() == 3);
+        assertTrue(document2.getElements().size() == 0);
+
+        doc.clear();
+        test(doc);
+        Util.assertGraphDocumentEquals(doc, new GraphDocument());
+    }
+
+    @Test
+    public void testSimpleExport() {
+        GraphDocument document = new GraphDocument();
+        Group g = new Group(document);
+        document.addElement(g);
+
+        InputGraph graph = new InputGraph("TestGraph");
+                g.addElement(graph);
+        graph.getProperties().setProperty("testName", "testValue");
+
+        InputNode n1 = new InputNode(0);
+        InputNode n2 = new InputNode(1);
+        InputEdge e1 = new InputEdge((char)0, 0, 1);
+        InputEdge e2 = new InputEdge((char)1, 0, 1);
+        graph.addNode(n1);
+        graph.addNode(n2);
+        graph.addEdge(e1);
+        graph.addEdge(e2);
+
+        test(document);
+    }
+
+    @Test
+    public void testComplexExport() {
+
+        GraphDocument document = new GraphDocument();
+        Group g = new Group(document);
+        document.addElement(g);
+
+        InputGraph graph = new InputGraph("TestGraph");
+                g.addElement(graph);
+        graph.getProperties().setProperty("testName", "testValue");
+
+        InputNode n1 = new InputNode(0);
+        InputNode n2 = new InputNode(1);
+        InputEdge e1 = new InputEdge((char)0, 0, 0);
+        InputEdge e2 = new InputEdge((char)1, 1, 1);
+        graph.addNode(n1);
+        graph.addNode(n2);
+        graph.addEdge(e1);
+        graph.addEdge(e2);
+
+        InputGraph graph2 = new InputGraph("TestGraph2");
+                g.addElement(graph2);
+        graph2.addNode(n1);
+        InputNode n3 = new InputNode(2);
+        graph2.addNode(n3);
+        InputEdge e3 = new InputEdge((char)0, 0, 2);
+        graph2.addEdge(e3);
+
+        test(document);
+    }
+
+
+    /**
+     * Test of parse method, of class Parser.
+     */
+    @Test
+    public void testParse() {
+        testBoth(new GraphDocument(), "<graphDocument></graphDocument>");
+    }
+
+}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Difference/nbproject/project.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Difference/nbproject/project.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Difference/nbproject/project.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Difference/nbproject/project.xml	Fri May 08 13:25:11 2015 -0400
@@ -14,6 +14,14 @@
                         <specification-version>1.0</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>
             </module-dependencies>
             <public-packages>
                 <package>com.sun.hotspot.igv.difference</package>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -24,16 +24,11 @@
  */
 package com.sun.hotspot.igv.difference;
 
-import com.sun.hotspot.igv.data.Group;
-import com.sun.hotspot.igv.data.InputEdge;
-import com.sun.hotspot.igv.data.InputGraph;
-import com.sun.hotspot.igv.data.InputNode;
-import com.sun.hotspot.igv.data.Property;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.data.*;
+import com.sun.hotspot.igv.data.services.Scheduler;
+import java.util.*;
+import org.openide.util.Lookup;
 
 /**
  *
@@ -46,7 +41,7 @@
     public static final String VALUE_CHANGED = "changed";
     public static final String VALUE_SAME = "same";
     public static final String VALUE_DELETED = "deleted";
-    public static final String OLD_PREFIX = "OLD_";
+    public static final String NEW_PREFIX = "NEW_";
     public static final String MAIN_PROPERTY = "name";
     public static final double LIMIT = 100.0;
     public static final String[] IGNORE_PROPERTIES = new String[]{"idx", "debug_idx"};
@@ -60,14 +55,14 @@
     }
 
     private static InputGraph createDiffSameGroup(InputGraph a, InputGraph b) {
-        Map<Integer, InputNode> keyMapB = new HashMap<Integer, InputNode>();
+        Map<Integer, InputNode> keyMapB = new HashMap<>(b.getNodes().size());
         for (InputNode n : b.getNodes()) {
             Integer key = n.getId();
             assert !keyMapB.containsKey(key);
             keyMapB.put(key, n);
         }
 
-        Set<Pair> pairs = new HashSet<Pair>();
+        Set<NodePair> pairs = new HashSet<>();
 
         for (InputNode n : a.getNodes()) {
             Integer key = n.getId();
@@ -75,30 +70,92 @@
 
             if (keyMapB.containsKey(key)) {
                 InputNode nB = keyMapB.get(key);
-                pairs.add(new Pair(n, nB));
+                pairs.add(new NodePair(n, nB));
             }
         }
 
         return createDiff(a, b, pairs);
     }
 
-    private static InputGraph createDiff(InputGraph a, InputGraph b, Set<Pair> pairs) {
-        Group g = new Group();
+    private static void ensureScheduled(InputGraph a) {
+        if (a.getBlocks().isEmpty()) {
+            Scheduler s = Lookup.getDefault().lookup(Scheduler.class);
+            a.clearBlocks();
+            s.schedule(a);
+            a.ensureNodesInBlocks();
+        }
+    }
+
+    private static InputGraph createDiff(InputGraph a, InputGraph b, Set<NodePair> pairs) {
+        ensureScheduled(a);
+        ensureScheduled(b);
+
+        Group g = new Group(null);
         g.setMethod(a.getGroup().getMethod());
-        g.setAssembly(a.getGroup().getAssembly());
+        if (a.getGroup() == b.getGroup()) {
+            g.getProperties().add(a.getGroup().getProperties());
+        } else {
+            // copy properties that have the same value in both groups
+            Properties bps = b.getGroup().getProperties();
+            for (Property p : a.getGroup().getProperties()) {
+                String value = p.getValue();
+                if (value != null && value.equals(bps.get(p.getName()))) {
+                    g.getProperties().setProperty(p.getName(), value);
+                }
+            }
+        }
         g.getProperties().setProperty("name", "Difference");
-        InputGraph graph = new InputGraph(g, null);
-        graph.setName(a.getName() + ", " + b.getName());
-        graph.setIsDifferenceGraph(true);
+        InputGraph graph = new InputGraph(a.getName() + ", " + b.getName());
+        g.addElement(graph);
 
-        Set<InputNode> nodesA = new HashSet<InputNode>(a.getNodes());
-        Set<InputNode> nodesB = new HashSet<InputNode>(b.getNodes());
+        Map<InputBlock, InputBlock> blocksMap = new HashMap<>();
+        for (InputBlock blk : a.getBlocks()) {
+            InputBlock diffblk = graph.addBlock(blk.getName());
+            blocksMap.put(blk, diffblk);
+        }
+        for (InputBlock blk : b.getBlocks()) {
+            InputBlock diffblk = graph.getBlock(blk.getName());
+            if (diffblk == null) {
+                diffblk = graph.addBlock(blk.getName());
+            }
+            blocksMap.put(blk, diffblk);
+        }
 
-        Map<InputNode, InputNode> inputNodeMap = new HashMap<InputNode, InputNode>();
-        for (Pair p : pairs) {
-            InputNode n = p.getN1();
+        // Difference between block edges
+        Set<Pair<String, String>> aEdges = new HashSet<>();
+        for (InputBlockEdge edge : a.getBlockEdges()) {
+            aEdges.add(new Pair<>(edge.getFrom().getName(), edge.getTo().getName()));
+        }
+        for (InputBlockEdge bEdge : b.getBlockEdges()) {
+            InputBlock from = bEdge.getFrom();
+            InputBlock to = bEdge.getTo();
+            Pair<String, String> pair = new Pair<>(from.getName(), to.getName());
+            if (aEdges.contains(pair)) {
+                // same
+                graph.addBlockEdge(blocksMap.get(from), blocksMap.get(to));
+                aEdges.remove(pair);
+            } else {
+                // added
+                InputBlockEdge edge = graph.addBlockEdge(blocksMap.get(from), blocksMap.get(to));
+                edge.setState(InputBlockEdge.State.NEW);
+            }
+        }
+        for (Pair<String, String> deleted : aEdges) {
+            // removed
+            InputBlock from = graph.getBlock(deleted.getLeft());
+            InputBlock to = graph.getBlock(deleted.getRight());
+            InputBlockEdge edge = graph.addBlockEdge(from, to);
+            edge.setState(InputBlockEdge.State.DELETED);
+        }
+
+        Set<InputNode> nodesA = new HashSet<>(a.getNodes());
+        Set<InputNode> nodesB = new HashSet<>(b.getNodes());
+
+        Map<InputNode, InputNode> inputNodeMap = new HashMap<>(pairs.size());
+        for (NodePair p : pairs) {
+            InputNode n = p.getLeft();
             assert nodesA.contains(n);
-            InputNode nB = p.getN2();
+            InputNode nB = p.getRight();
             assert nodesB.contains(nB);
 
             nodesA.remove(n);
@@ -107,41 +164,59 @@
             inputNodeMap.put(n, n2);
             inputNodeMap.put(nB, n2);
             graph.addNode(n2);
+            InputBlock block = blocksMap.get(a.getBlock(n));
+            block.addNode(n2.getId());
             markAsChanged(n2, n, nB);
         }
 
         for (InputNode n : nodesA) {
             InputNode n2 = new InputNode(n);
             graph.addNode(n2);
-            markAsNew(n2);
+            InputBlock block = blocksMap.get(a.getBlock(n));
+            block.addNode(n2.getId());
+            markAsDeleted(n2);
             inputNodeMap.put(n, n2);
         }
 
+        int curIndex = 0;
         for (InputNode n : nodesB) {
             InputNode n2 = new InputNode(n);
-            n2.setId(-n2.getId());
+
+            // Find new ID for node of b, does not change the id property
+            while (graph.getNode(curIndex) != null) {
+                curIndex++;
+            }
+
+            n2.setId(curIndex);
             graph.addNode(n2);
-            markAsDeleted(n2);
+            InputBlock block = blocksMap.get(b.getBlock(n));
+            block.addNode(n2.getId());
+            markAsNew(n2);
             inputNodeMap.put(n, n2);
         }
 
         Collection<InputEdge> edgesA = a.getEdges();
         Collection<InputEdge> edgesB = b.getEdges();
 
-        Set<InputEdge> newEdges = new HashSet<InputEdge>();
+        Set<InputEdge> newEdges = new HashSet<>();
 
         for (InputEdge e : edgesA) {
             int from = e.getFrom();
             int to = e.getTo();
             InputNode nodeFrom = inputNodeMap.get(a.getNode(from));
             InputNode nodeTo = inputNodeMap.get(a.getNode(to));
-            char index = e.getToIndex();
+            char fromIndex = e.getFromIndex();
+            char toIndex = e.getToIndex();
 
-            InputEdge newEdge = new InputEdge(index, nodeFrom.getId(), nodeTo.getId());
-            if (!newEdges.contains(newEdge)) {
-                markAsNew(newEdge);
-                newEdges.add(newEdge);
-                graph.addEdge(newEdge);
+            if (nodeFrom == null || nodeTo == null) {
+                System.out.println("Unexpected edge : " + from + " -> " + to);
+            } else {
+                InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId(), e.getLabel(), e.getType());
+                if (!newEdges.contains(newEdge)) {
+                    markAsDeleted(newEdge);
+                    newEdges.add(newEdge);
+                    graph.addEdge(newEdge);
+                }
             }
         }
 
@@ -150,40 +225,41 @@
             int to = e.getTo();
             InputNode nodeFrom = inputNodeMap.get(b.getNode(from));
             InputNode nodeTo = inputNodeMap.get(b.getNode(to));
-            char index = e.getToIndex();
+            char fromIndex = e.getFromIndex();
+            char toIndex = e.getToIndex();
 
-            InputEdge newEdge = new InputEdge(index, nodeFrom.getId(), nodeTo.getId());
-            if (!newEdges.contains(newEdge)) {
-                markAsDeleted(newEdge);
-                newEdges.add(newEdge);
-                graph.addEdge(newEdge);
+            if (nodeFrom == null || nodeTo == null) {
+                System.out.println("Unexpected edge : " + from + " -> " + to);
             } else {
-                newEdges.remove(newEdge);
-                graph.removeEdge(newEdge);
-                markAsSame(newEdge);
-                newEdges.add(newEdge);
-                graph.addEdge(newEdge);
+                InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId(), e.getLabel(), e.getType());
+                if (!newEdges.contains(newEdge)) {
+                    markAsNew(newEdge);
+                    newEdges.add(newEdge);
+                    graph.addEdge(newEdge);
+                } else {
+                    newEdges.remove(newEdge);
+                    graph.removeEdge(newEdge);
+                    markAsSame(newEdge);
+                    newEdges.add(newEdge);
+                    graph.addEdge(newEdge);
+                }
             }
         }
 
-        g.addGraph(graph);
         return graph;
     }
 
-    private static class Pair {
+    private static class NodePair extends Pair<InputNode, InputNode> {
+
 
-        private InputNode n1;
-        private InputNode n2;
-
-        public Pair(InputNode n1, InputNode n2) {
-            this.n1 = n1;
-            this.n2 = n2;
+        public NodePair(InputNode n1, InputNode n2) {
+            super(n1, n2);
         }
 
         public double getValue() {
 
             double result = 0.0;
-            for (Property p : n1.getProperties()) {
+            for (Property p : getLeft().getProperties()) {
                 double faktor = 1.0;
                 for (String forbidden : IGNORE_PROPERTIES) {
                     if (p.getName().equals(forbidden)) {
@@ -191,7 +267,7 @@
                         break;
                     }
                 }
-                String p2 = n2.getProperties().get(p.getName());
+                String p2 = getRight().getProperties().get(p.getName());
                 result += evaluate(p.getValue(), p2) * faktor;
             }
 
@@ -208,21 +284,13 @@
                 return (double) (Math.abs(p.length() - p2.length())) / p.length() + 0.5;
             }
         }
-
-        public InputNode getN1() {
-            return n1;
-        }
-
-        public InputNode getN2() {
-            return n2;
-        }
     }
 
     private static InputGraph createDiff(InputGraph a, InputGraph b) {
 
-        Set<InputNode> matched = new HashSet<InputNode>();
+        Set<InputNode> matched = new HashSet<>();
 
-        Set<Pair> pairs = new HashSet<Pair>();
+        Set<NodePair> pairs = new HashSet<>();
         for (InputNode n : a.getNodes()) {
             String s = n.getProperties().get(MAIN_PROPERTY);
             if (s == null) {
@@ -235,18 +303,18 @@
                 }
 
                 if (s.equals(s2)) {
-                    Pair p = new Pair(n, n2);
+                    NodePair p = new NodePair(n, n2);
                     pairs.add(p);
                 }
             }
         }
 
-        Set<Pair> selectedPairs = new HashSet<Pair>();
+        Set<NodePair> selectedPairs = new HashSet<>();
         while (pairs.size() > 0) {
 
             double min = Double.MAX_VALUE;
-            Pair minPair = null;
-            for (Pair p : pairs) {
+            NodePair minPair = null;
+            for (NodePair p : pairs) {
                 double cur = p.getValue();
                 if (cur < min) {
                     minPair = p;
@@ -259,9 +327,9 @@
             } else {
                 selectedPairs.add(minPair);
 
-                Set<Pair> toRemove = new HashSet<Pair>();
-                for (Pair p : pairs) {
-                    if (p.getN1() == minPair.getN1() || p.getN2() == minPair.getN2()) {
+                Set<NodePair> toRemove = new HashSet<>();
+                for (NodePair p : pairs) {
+                    if (p.getLeft() == minPair.getLeft() || p.getRight() == minPair.getRight()) {
                         toRemove.add(p);
                     }
                 }
@@ -292,7 +360,7 @@
             String s = firstNode.getProperties().get(p.getName());
             if (!p.getValue().equals(s)) {
                 difference = true;
-                n.getProperties().setProperty(OLD_PREFIX + p.getName(), p.getValue());
+                n.getProperties().setProperty(NEW_PREFIX + p.getName(), p.getValue());
             }
         }
 
@@ -300,7 +368,7 @@
             String s = otherNode.getProperties().get(p.getName());
             if (s == null && p.getValue().length() > 0) {
                 difference = true;
-                n.getProperties().setProperty(OLD_PREFIX + p.getName(), "");
+                n.getProperties().setProperty(NEW_PREFIX + p.getName(), "");
             }
         }
 
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/nbproject/project.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/nbproject/project.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/nbproject/project.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/nbproject/project.xml	Fri May 08 13:25:11 2015 -0400
@@ -23,12 +23,28 @@
                     </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>org.jdesktop.layout</code-name-base>
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.4.1</specification-version>
+                        <specification-version>1.16.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.awt</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.30.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -36,7 +52,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.5.1</specification-version>
+                        <specification-version>7.18.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -44,7 +60,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.3</specification-version>
+                        <specification-version>7.46.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -52,7 +68,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.2.0.1</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -60,7 +76,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.9.0.1</specification-version>
+                        <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>
@@ -68,7 +92,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.16</specification-version>
+                        <specification-version>6.39.1</specification-version>
                     </run-dependency>
                 </dependency>
             </module-dependencies>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/META-INF/services/com.sun.hotspot.igv.filter.ScriptEngineAbstraction	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-com.sun.hotspot.igv.filter.JavaSE6ScriptEngine
\ No newline at end of file
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/AbstractFilter.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/AbstractFilter.java	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, 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
@@ -42,14 +42,17 @@
         properties = new Properties();
     }
 
+    @Override
     public Properties getProperties() {
         return properties;
     }
 
+    @Override
     public OpenCookie getEditor() {
         return null;
     }
 
+    @Override
     public ChangedEvent<Filter> getChangedEvent() {
         return changedEvent;
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/ColorFilter.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/ColorFilter.java	Fri May 08 13:25:11 2015 -0400
@@ -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,13 +23,9 @@
  */
 package com.sun.hotspot.igv.filter;
 
-import com.sun.hotspot.igv.graph.Connection;
+import com.sun.hotspot.igv.data.Properties;
 import com.sun.hotspot.igv.graph.Connection.ConnectionStyle;
-import com.sun.hotspot.igv.graph.Diagram;
-import com.sun.hotspot.igv.graph.Figure;
-import com.sun.hotspot.igv.graph.OutputSlot;
-import com.sun.hotspot.igv.graph.Selector;
-import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.graph.*;
 import java.awt.Color;
 import java.util.ArrayList;
 import java.util.List;
@@ -45,16 +41,18 @@
 
     public ColorFilter(String name) {
         this.name = name;
-        colorRules = new ArrayList<ColorRule>();
+        colorRules = new ArrayList<>();
     }
 
+    @Override
     public String getName() {
         return name;
     }
 
+    @Override
     public void apply(Diagram diagram) {
 
-        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<Figure>(diagram.getFigures());
+        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(diagram.getFigures());
         for (ColorRule rule : colorRules) {
             if (rule.getSelector() != null) {
                 List<Figure> figures = rule.getSelector().selected(diagram);
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CombineFilter.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CombineFilter.java	Fri May 08 13:25:11 2015 -0400
@@ -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,13 +23,9 @@
  */
 package com.sun.hotspot.igv.filter;
 
-import com.sun.hotspot.igv.graph.Connection;
-import com.sun.hotspot.igv.graph.Diagram;
-import com.sun.hotspot.igv.graph.Figure;
-import com.sun.hotspot.igv.graph.InputSlot;
-import com.sun.hotspot.igv.graph.OutputSlot;
 import com.sun.hotspot.igv.data.Properties;
 import com.sun.hotspot.igv.data.Properties.PropertyMatcher;
+import com.sun.hotspot.igv.graph.*;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -46,23 +42,25 @@
 
     public CombineFilter(String name) {
         this.name = name;
-        rules = new ArrayList<CombineRule>();
+        rules = new ArrayList<>();
     }
 
+    @Override
     public String getName() {
         return name;
     }
 
+    @Override
     public void apply(Diagram diagram) {
 
-        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<Figure>(diagram.getFigures());
+        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(diagram.getFigures());
         for (CombineRule r : rules) {
 
             List<Figure> list = selector.selectMultiple(r.getFirstMatcher());
-            Set<Figure> figuresToRemove = new HashSet<Figure>();
+            Set<Figure> figuresToRemove = new HashSet<>();
             for (Figure f : list) {
 
-                List<Figure> successors = new ArrayList<Figure>(f.getSuccessors());
+                List<Figure> successors = new ArrayList<>(f.getSuccessors());
                 if (r.isReversed()) {
                     if (successors.size() == 1) {
                         Figure succ = successors.get(0);
@@ -76,21 +74,30 @@
                             }
                         }
 
-                        assert slot != null;
-                        slot.setName(f.getProperties().get("dump_spec"));
-                        if (f.getProperties().get("short_name") != null) {
-                            slot.setShortName(f.getProperties().get("short_name"));
+                        slot.getSource().addSourceNodes(f.getSource());
+                        if (r.getShortProperty() != null) {
+                            String s = f.getProperties().get(r.getShortProperty());
+                            if (s != null && s.length() > 0) {
+                                slot.setShortName(s);
+                                slot.setText(s);
+                                slot.setColor(f.getColor());
+                            }
                         } else {
-                            String s = f.getProperties().get("dump_spec");
-                            if (s != null && s.length() <= 5) {
-                                slot.setShortName(s);
+                            assert slot != null;
+                            slot.setText(f.getProperties().get("dump_spec"));
+                            if (f.getProperties().get("short_name") != null) {
+                                slot.setShortName(f.getProperties().get("short_name"));
+                            } else {
+                                String s = f.getProperties().get("dump_spec");
+                                if (s != null && s.length() <= 5) {
+                                    slot.setShortName(s);
+                                }
                             }
-
                         }
 
                         for (InputSlot s : f.getInputSlots()) {
                             for (Connection c : s.getConnections()) {
-                                Connection newConn = diagram.createConnection(slot, c.getOutputSlot());
+                                Connection newConn = diagram.createConnection(slot, c.getOutputSlot(), c.getLabel(), c.getType());
                                 newConn.setColor(c.getColor());
                                 newConn.setStyle(c.getStyle());
                             }
@@ -101,7 +108,7 @@
                 } else {
 
                     for (Figure succ : successors) {
-                        if (succ.getPredecessors().size() == 1) {
+                        if (succ.getPredecessors().size() == 1 && succ.getInputSlots().size() == 1) {
                             if (succ.getProperties().selectSingle(r.getSecondMatcher()) != null && succ.getOutputSlots().size() == 1) {
 
 
@@ -122,22 +129,32 @@
                                     pos = Integer.parseInt(succ.getProperties().get("con"));
                                 }
                                 OutputSlot slot = f.createOutputSlot(pos);
-                                slot.setName(succ.getProperties().get("dump_spec"));
-                                if (succ.getProperties().get("short_name") != null) {
-                                    slot.setShortName(succ.getProperties().get("short_name"));
+                                slot.getSource().addSourceNodes(succ.getSource());
+                                if (r.getShortProperty() != null) {
+                                    String s = succ.getProperties().get(r.getShortProperty());
+                                    if (s != null && s.length() > 0) {
+                                        slot.setShortName(s);
+                                        slot.setText(s);
+                                        slot.setColor(succ.getColor());
+                                    }
                                 } else {
-                                    String s = succ.getProperties().get("dump_spec");
-                                    if (s != null && s.length() <= 2) {
-                                        slot.setShortName(s);
+                                    slot.setText(succ.getProperties().get("dump_spec"));
+                                    if (succ.getProperties().get("short_name") != null) {
+                                        slot.setShortName(succ.getProperties().get("short_name"));
                                     } else {
-                                        String tmpName = succ.getProperties().get("name");
-                                        if (tmpName != null && tmpName.length() > 0) {
-                                            slot.setShortName(tmpName.substring(0, 1));
+                                        String s = succ.getProperties().get("dump_spec");
+                                        if (s != null && s.length() <= 2) {
+                                            slot.setShortName(s);
+                                        } else {
+                                            String tmpName = succ.getProperties().get("name");
+                                            if (tmpName != null && tmpName.length() > 0) {
+                                                slot.setShortName(tmpName.substring(0, 1));
+                                            }
                                         }
                                     }
                                 }
                                 for (Connection c : nextSlot.getConnections()) {
-                                    Connection newConn = diagram.createConnection(c.getInputSlot(), slot);
+                                    Connection newConn = diagram.createConnection(c.getInputSlot(), slot, c.getLabel(), c.getType());
                                     newConn.setColor(c.getColor());
                                     newConn.setStyle(c.getStyle());
                                 }
@@ -167,6 +184,7 @@
         private PropertyMatcher first;
         private PropertyMatcher second;
         private boolean reversed;
+        private String shortProperty;
 
         public CombineRule(PropertyMatcher first, PropertyMatcher second) {
             this(first, second, false);
@@ -174,9 +192,14 @@
         }
 
         public CombineRule(PropertyMatcher first, PropertyMatcher second, boolean reversed) {
+            this(first, second, reversed, null);
+        }
+
+        public CombineRule(PropertyMatcher first, PropertyMatcher second, boolean reversed, String shortProperty) {
             this.first = first;
             this.second = second;
             this.reversed = reversed;
+            this.shortProperty = shortProperty;
         }
 
         public boolean isReversed() {
@@ -190,5 +213,9 @@
         public PropertyMatcher getSecondMatcher() {
             return second;
         }
+
+        public String getShortProperty() {
+            return shortProperty;
+        }
     }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/ConnectionFilter.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/ConnectionFilter.java	Fri May 08 13:25:11 2015 -0400
@@ -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,12 +23,8 @@
  */
 package com.sun.hotspot.igv.filter;
 
-import com.sun.hotspot.igv.graph.Connection;
-import com.sun.hotspot.igv.graph.Diagram;
-import com.sun.hotspot.igv.graph.Figure;
-import com.sun.hotspot.igv.graph.OutputSlot;
-import com.sun.hotspot.igv.graph.Selector;
 import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.graph.*;
 import java.awt.Color;
 import java.util.ArrayList;
 import java.util.List;
@@ -44,16 +40,18 @@
 
     public ConnectionFilter(String name) {
         this.name = name;
-        connectionStyleRules = new ArrayList<ConnectionStyleRule>();
+        connectionStyleRules = new ArrayList<>();
     }
 
+    @Override
     public String getName() {
         return name;
     }
 
+    @Override
     public void apply(Diagram diagram) {
 
-        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<Figure>(diagram.getFigures());
+        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(diagram.getFigures());
         for (ConnectionStyleRule rule : connectionStyleRules) {
             List<Figure> figures = null;
             if (rule.getSelector() != null) {
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CustomFilter.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CustomFilter.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -29,17 +29,13 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
-import java.util.Collection;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-import org.openide.DialogDisplayer;
-import org.openide.NotifyDescriptor;
+import javax.script.*;
 import org.openide.cookies.OpenCookie;
-import org.openide.filesystems.Repository;
-import org.openide.filesystems.FileSystem;
 import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
 import org.openide.util.Exceptions;
-import org.openide.util.Lookup;
 
 /**
  *
@@ -48,7 +44,6 @@
 public class CustomFilter extends AbstractFilter {
 
     public static final String JAVASCRIPT_HELPER_ID = "JavaScriptHelper";
-    private static ScriptEngineAbstraction engine;
     private String code;
     private String name;
 
@@ -58,6 +53,7 @@
         getProperties().setProperty("name", name);
     }
 
+    @Override
     public String getName() {
         return name;
     }
@@ -80,6 +76,7 @@
     public OpenCookie getEditor() {
         return new OpenCookie() {
 
+            @Override
             public void open() {
                 openInEditor();
             }
@@ -89,7 +86,9 @@
     public boolean openInEditor() {
         EditFilterDialog dialog = new EditFilterDialog(CustomFilter.this);
         dialog.setVisible(true);
-        return dialog.wasAccepted();
+        boolean result = dialog.wasAccepted();
+        this.getChangedEvent().fire();
+        return result;
     }
 
     @Override
@@ -97,41 +96,16 @@
         return getName();
     }
 
-    public static ScriptEngineAbstraction getEngine() {
-        if (engine == null) {
-
-            ScriptEngineAbstraction chosen = null;
-            try {
-                Collection<? extends ScriptEngineAbstraction> list = Lookup.getDefault().lookupAll(ScriptEngineAbstraction.class);
-                for (ScriptEngineAbstraction s : list) {
-                    if (s.initialize(getJsHelperText())) {
-                        if (chosen == null || !(chosen instanceof JavaSE6ScriptEngine)) {
-                            chosen = s;
-                        }
-                    }
-                }
-            } catch (NoClassDefFoundError ncdfe) {
-                Logger.getLogger("global").log(Level.SEVERE, null, ncdfe);
-            }
-
-            if (chosen == null) {
-                NotifyDescriptor message = new NotifyDescriptor.Message("Could not find a scripting engine. Please make sure that the Rhino scripting engine is available. Otherwise filter cannot be used.", NotifyDescriptor.ERROR_MESSAGE);
-                DialogDisplayer.getDefault().notifyLater(message);
-                chosen = new NullScriptEngine();
-            }
-
-            engine = chosen;
-        }
-
-        return engine;
-    }
-
     private static String getJsHelperText() {
         InputStream is = null;
-        StringBuilder sb = new StringBuilder("importPackage(Packages.com.sun.hotspot.igv.filter);importPackage(Packages.com.sun.hotspot.igv.graph);importPackage(Packages.com.sun.hotspot.igv.data);importPackage(Packages.com.sun.hotspot.igv.util);importPackage(java.awt);");
+        StringBuilder sb = new StringBuilder("if (typeof importPackage === 'undefined') { try { load('nashorn:mozilla_compat.js'); } catch (e) {} }"
+                + "importPackage(Packages.com.sun.hotspot.igv.filter);"
+                + "importPackage(Packages.com.sun.hotspot.igv.graph);"
+                + "importPackage(Packages.com.sun.hotspot.igv.data);"
+                + "importPackage(Packages.com.sun.hotspot.igv.util);"
+                + "importPackage(java.awt);");
         try {
-            FileSystem fs = Repository.getDefault().getDefaultFileSystem();
-            FileObject fo = fs.getRoot().getFileObject(JAVASCRIPT_HELPER_ID);
+            FileObject fo = FileUtil.getConfigRoot().getFileObject(JAVASCRIPT_HELPER_ID);
             is = fo.getInputStream();
             BufferedReader r = new BufferedReader(new InputStreamReader(is));
             String s;
@@ -152,7 +126,18 @@
         return sb.toString();
     }
 
+    @Override
     public void apply(Diagram d) {
-        getEngine().execute(d, code);
+        try {
+            ScriptEngineManager sem = new ScriptEngineManager();
+            ScriptEngine e = sem.getEngineByName("ECMAScript");
+            e.eval(getJsHelperText());
+            Bindings b = e.getContext().getBindings(ScriptContext.ENGINE_SCOPE);
+            b.put("graph", d);
+            b.put("IO", System.out);
+            e.eval(code, b);
+        } catch (ScriptException ex) {
+            Exceptions.printStackTrace(ex);
+        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/EdgeColorIndexFilter.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2011, 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.filter;
+
+import com.sun.hotspot.igv.graph.*;
+import java.awt.Color;
+import java.util.List;
+
+public class EdgeColorIndexFilter extends AbstractFilter {
+
+    public static final String INPUTS = "INPUTS";
+    public static final String OUTPUTS = "OUTPUTS";
+    private final String applyTo;
+    private final Color[] colors;
+
+    public EdgeColorIndexFilter(String applyTo, Color... color) {
+        if (!applyTo.equals(INPUTS) && !applyTo.equals(OUTPUTS)) {
+            throw new IllegalArgumentException("applyTo");
+        }
+
+        this.applyTo = applyTo;
+        this.colors = color;
+    }
+
+    @Override
+    public String getName() {
+        return "Edge Color Index Filter";
+    }
+
+    @Override
+    public void apply(Diagram d) {
+        List<Figure> figures = d.getFigures();
+        for (Figure f : figures) {
+            Slot[] slots;
+            if (applyTo.equals(INPUTS)) {
+                List<InputSlot> inputSlots = f.getInputSlots();
+                slots = inputSlots.toArray(new Slot[inputSlots.size()]);
+            } else {
+                List<OutputSlot> outputSlots = f.getOutputSlots();
+                slots = outputSlots.toArray(new Slot[outputSlots.size()]);
+            }
+            int index = 0;
+            for (Slot slot : slots) {
+                if (index < colors.length && colors[index] != null) {
+                    slot.setColor(colors[index]);
+                    for (Connection c : slot.getConnections()) {
+
+                        c.setColor(colors[index]);
+                    }
+                }
+                index++;
+            }
+
+        }
+    }
+}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/EditFilterDialog.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/EditFilterDialog.java	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, 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
@@ -137,14 +137,14 @@
     }// </editor-fold>//GEN-END:initComponents
 
 private void okButtonClicked(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonClicked
-        this.customFilter.setName(this.nameTextField.getText());
-        this.customFilter.setCode(this.sourceTextArea.getText());
-        accepted = true;
-        setVisible(false);
+    this.customFilter.setName(this.nameTextField.getText());
+    this.customFilter.setCode(this.sourceTextArea.getText());
+    accepted = true;
+    setVisible(false);
 }//GEN-LAST:event_okButtonClicked
 
 private void cancelButtonClicked(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonClicked
-        setVisible(false);
+    setVisible(false);
 }//GEN-LAST:event_cancelButtonClicked
 
 
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/Filter.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/Filter.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -41,5 +41,6 @@
 
     OpenCookie getEditor();
 
+    @Override
     ChangedEvent<Filter> getChangedEvent();
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/FilterChain.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/FilterChain.java	Fri May 08 13:25:11 2015 -0400
@@ -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,9 +23,10 @@
  */
 package com.sun.hotspot.igv.filter;
 
-import com.sun.hotspot.igv.graph.Diagram;
 import com.sun.hotspot.igv.data.ChangedEvent;
 import com.sun.hotspot.igv.data.ChangedEventProvider;
+import com.sun.hotspot.igv.data.ChangedListener;
+import com.sun.hotspot.igv.graph.Diagram;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -38,20 +39,25 @@
 
     private List<Filter> filters;
     private transient ChangedEvent<FilterChain> changedEvent;
-    private boolean fireEvents;
+
+    private ChangedListener<Filter> changedListener = new ChangedListener<Filter>() {
+        @Override
+        public void changed(Filter source) {
+            changedEvent.fire();
+        }
+    };
 
     public FilterChain() {
-        filters = new ArrayList<Filter>();
-        changedEvent = new ChangedEvent<FilterChain>(this);
-        this.fireEvents = true;
+        filters = new ArrayList<>();
+        changedEvent = new ChangedEvent<>(this);
     }
 
     public FilterChain(FilterChain f) {
-        this.filters = new ArrayList<Filter>(f.filters);
-        changedEvent = new ChangedEvent<FilterChain>(this);
-        this.fireEvents = true;
+        this.filters = new ArrayList<>(f.filters);
+        changedEvent = new ChangedEvent<>(this);
     }
 
+    @Override
     public ChangedEvent<FilterChain> getChangedEvent() {
         return changedEvent;
     }
@@ -68,7 +74,7 @@
     }
 
     public void apply(Diagram d, FilterChain sequence) {
-        List<Filter> applied = new ArrayList<Filter>();
+        List<Filter> applied = new ArrayList<>();
         for (Filter f : sequence.getFilters()) {
             if (filters.contains(f)) {
                 f.apply(d);
@@ -84,29 +90,12 @@
         }
     }
 
-    public void beginAtomic() {
-        this.fireEvents = false;
-    }
-
-    public void endAtomic() {
-        this.fireEvents = true;
-        changedEvent.fire();
-    }
 
     public void addFilter(Filter filter) {
         assert filter != null;
         filters.add(filter);
-        if (fireEvents) {
-            changedEvent.fire();
-        }
-    }
-
-    public void addFilterSameSequence(Filter filter) {
-        assert filter != null;
-        filters.add(filter);
-        if (fireEvents) {
-            changedEvent.fire();
-        }
+        filter.getChangedEvent().addListener(changedListener);
+        changedEvent.fire();
     }
 
     public boolean containsFilter(Filter filter) {
@@ -116,9 +105,8 @@
     public void removeFilter(Filter filter) {
         assert filters.contains(filter);
         filters.remove(filter);
-        if (fireEvents) {
-            changedEvent.fire();
-        }
+        filter.getChangedEvent().removeListener(changedListener);
+        changedEvent.fire();
     }
 
     public void moveFilterUp(Filter filter) {
@@ -128,9 +116,7 @@
             filters.remove(index);
             filters.add(index - 1, filter);
         }
-        if (fireEvents) {
-            changedEvent.fire();
-        }
+        changedEvent.fire();
     }
 
     public void moveFilterDown(Filter filter) {
@@ -140,16 +126,10 @@
             filters.remove(index);
             filters.add(index + 1, filter);
         }
-        if (fireEvents) {
-            changedEvent.fire();
-        }
+        changedEvent.fire();
     }
 
     public List<Filter> getFilters() {
         return Collections.unmodifiableList(filters);
     }
-
-    public void clear() {
-        filters.clear();
-    }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/FilterChainProvider.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/FilterChainProvider.java	Fri May 08 13:25:11 2015 -0400
@@ -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
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/FilterSetting.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/FilterSetting.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -42,7 +42,7 @@
 
     public FilterSetting(String name) {
         this.name = name;
-        filters = new HashSet<Filter>();
+        filters = new HashSet<>();
     }
 
     public Set<Filter> getFilters() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/GradientColorFilter.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2011, 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.filter;
+
+import com.sun.hotspot.igv.graph.Diagram;
+import com.sun.hotspot.igv.graph.Figure;
+import java.awt.*;
+import java.awt.geom.AffineTransform;
+import java.awt.image.Raster;
+import java.util.List;
+
+/**
+ * Filter that colors nodes using a customizable color gradient, based on how
+ * a numeric property is located in a specified interval.
+ *
+ * @author Peter Hofer
+ */
+public class GradientColorFilter extends AbstractFilter {
+
+    public static final String LINEAR = "LINEAR";
+    public static final String LOGARITHMIC = "LOGARITHMIC";
+
+    private String propertyName = "probability";
+    private float minValue = 0;
+    private float maxValue = 500;
+    private float[] fractions = {0, 0.5f, 1};
+    private Color[] colors = {Color.BLUE, Color.YELLOW, Color.RED};
+    private int shadeCount = 8;
+    private String mode = LINEAR;
+
+    @Override
+    public String getName() {
+        return "Gradient Color Filter";
+    }
+
+    @Override
+    public void apply(Diagram d) {
+        boolean logarithmic = mode.equalsIgnoreCase(LOGARITHMIC);
+        if (!logarithmic && !mode.equalsIgnoreCase(LINEAR)) {
+            throw new RuntimeException("Unknown mode: " + mode);
+        }
+
+        Rectangle bounds = new Rectangle(shadeCount, 1);
+        LinearGradientPaint lgp = new LinearGradientPaint(bounds.x, bounds.y, bounds.width, bounds.y, fractions, colors);
+        PaintContext context = lgp.createContext(null, bounds, bounds.getBounds2D(), AffineTransform.getTranslateInstance(0, 0), new RenderingHints(null));
+        Raster raster = context.getRaster(bounds.x, bounds.y, bounds.width, bounds.height);
+        int[] rgb = raster.getPixels(bounds.x, bounds.y, bounds.width, bounds.height, (int[]) null);
+        Color[] shades = new Color[rgb.length / 3];
+        for (int i = 0; i < shades.length; ++i) {
+            shades[i] = new Color(rgb[i * 3], rgb[i * 3 + 1], rgb[i * 3 + 2]);
+        }
+
+        List<Figure> figures = d.getFigures();
+        for (Figure f : figures) {
+            String property = f.getProperties().get(propertyName);
+            if (property != null) {
+                try {
+                    float value = Float.parseFloat(property);
+
+                    Color nodeColor;
+                    if (value <= minValue) {
+                        nodeColor = colors[0];
+                    } else if (value >= maxValue) {
+                        nodeColor = colors[colors.length - 1];
+                    } else {
+                        double normalized = value - minValue;
+                        double interval = maxValue - minValue;
+                        int index;
+                        // Use Math.ceil() to make values above zero distinguishable from zero
+                        if (logarithmic) {
+                            index = (int) Math.ceil(shades.length * Math.log(1 + normalized) / Math.log(1 + interval));
+                        } else {
+                            index = (int) Math.ceil(shades.length * normalized / interval);
+                        }
+                        nodeColor = shades[index];
+                    }
+                    f.setColor(nodeColor);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    public String getPropertyName() {
+        return propertyName;
+    }
+
+    public void setPropertyName(String propertyName) {
+        this.propertyName = propertyName;
+    }
+
+    public float getMinValue() {
+        return minValue;
+    }
+
+    public void setMinValue(float minValue) {
+        this.minValue = minValue;
+    }
+
+    public float getMaxValue() {
+        return maxValue;
+    }
+
+    public void setMaxValue(float maxValue) {
+        this.maxValue = maxValue;
+    }
+
+    public float[] getFractions() {
+        return fractions;
+    }
+
+    public void setFractions(float[] fractions) {
+        this.fractions = fractions;
+    }
+
+    public Color[] getColors() {
+        return colors;
+    }
+
+    public void setColors(Color[] colors) {
+        this.colors = colors;
+    }
+
+    public int getShadeCount() {
+        return shadeCount;
+    }
+
+    public void setShadeCount(int shadeCount) {
+        this.shadeCount = shadeCount;
+    }
+
+    public String getMode() {
+        return mode;
+    }
+
+    public void setMode(String mode) {
+        this.mode = mode;
+    }
+}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/JavaSE6ScriptEngine.java	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 1998, 2007, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.sun.hotspot.igv.filter;
-
-import com.sun.hotspot.igv.graph.Diagram;
-import javax.script.Bindings;
-import javax.script.ScriptContext;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-import javax.script.ScriptException;
-import org.openide.util.Exceptions;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class JavaSE6ScriptEngine implements ScriptEngineAbstraction {
-
-    private ScriptEngine engine;
-    private Bindings bindings;
-
-    public boolean initialize(String jsHelperText) {
-        try {
-            ScriptEngineManager sem = new ScriptEngineManager();
-            ScriptEngine e = sem.getEngineByName("ECMAScript");
-            engine = e;
-            e.eval(jsHelperText);
-            Bindings b = e.getContext().getBindings(ScriptContext.ENGINE_SCOPE);
-            b.put("IO", System.out);
-            bindings = b;
-            return true;
-        } catch (Exception e) {
-            return false;
-        }
-    }
-
-    public void execute(Diagram d, String code) {
-        try {
-            Bindings b = bindings;
-            b.put("graph", d);
-            engine.eval(code, b);
-        } catch (ScriptException ex) {
-            Exceptions.printStackTrace(ex);
-        }
-    }
-}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/NullScriptEngine.java	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * 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.filter;
-
-import com.sun.hotspot.igv.graph.Diagram;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class NullScriptEngine implements ScriptEngineAbstraction {
-
-    public boolean initialize(String jsHelperText) {
-        return true;
-    }
-
-    public void execute(Diagram d, String code) {
-    }
-}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveFilter.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveFilter.java	Fri May 08 13:25:11 2015 -0400
@@ -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,7 @@
 
 import com.sun.hotspot.igv.graph.Diagram;
 import com.sun.hotspot.igv.graph.Figure;
-import com.sun.hotspot.igv.graph.InputSlot;
 import com.sun.hotspot.igv.graph.Selector;
-import com.sun.hotspot.igv.data.Properties;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -44,56 +42,36 @@
 
     public RemoveFilter(String name) {
         this.name = name;
-        rules = new ArrayList<RemoveRule>();
+        rules = new ArrayList<>();
     }
 
+    @Override
     public String getName() {
         return name;
     }
 
+    @Override
     public void apply(Diagram diagram) {
-
         for (RemoveRule r : rules) {
+            List<Figure> selected = r.getSelector().selected(diagram);
+            Set<Figure> toRemove = new HashSet<>(selected);
 
-            List<Figure> list = r.getSelector().selected(diagram);
-            Set<Figure> figuresToRemove = new HashSet<Figure>();
-
-            List<Figure> protectedFigures = null;
-            if (r.getRemoveAllWithoutPredecessor()) {
-                protectedFigures = diagram.getRootFigures();
+            if (r.getRemoveOrphans()) {
+                boolean changed;
+                do {
+                    changed = false;
+                    for (Figure f : diagram.getFigures()) {
+                        if (!toRemove.contains(f)) {
+                            if (toRemove.containsAll(f.getPredecessors()) && toRemove.containsAll(f.getSuccessors())) {
+                                toRemove.add(f);
+                                changed = true;
+                            }
+                        }
+                    }
+                } while (changed);
             }
 
-            for (Figure f : list) {
-                if (r.getRemoveOnlyInputs()) {
-                    List<InputSlot> inputSlots = new ArrayList<InputSlot>();
-                    for (InputSlot is : f.getInputSlots()) {
-                        inputSlots.add(is);
-                    }
-                    for (InputSlot is : inputSlots) {
-                        f.removeSlot(is);
-                    }
-
-                    f.createInputSlot();
-                } else {
-                    figuresToRemove.add(f);
-                }
-            }
-
-            if (r.getRemoveAllWithoutPredecessor()) {
-                boolean progress = true;
-                while (progress) {
-                    List<Figure> rootFigures = diagram.getRootFigures();
-                    progress = false;
-                    for (Figure f : rootFigures) {
-                        if (!protectedFigures.contains(f)) {
-                            figuresToRemove.add(f);
-                            progress = true;
-                        }
-                    }
-                }
-            }
-
-            diagram.removeAllFigures(figuresToRemove);
+            diagram.removeAllFigures(toRemove);
         }
     }
 
@@ -104,29 +82,23 @@
     public static class RemoveRule {
 
         private Selector selector;
-        private boolean removeAllWithoutPredecessor;
-        private boolean removeOnlyInputs;
+        private boolean removeOrphans;
 
-        public RemoveRule(Selector selector, boolean b) {
-            this(selector, b, false);
+        public RemoveRule(Selector selector) {
+            this(selector, false);
         }
 
-        public RemoveRule(Selector selector, boolean removeAllWithoutPredecessor, boolean removeOnlyInputs) {
+        public RemoveRule(Selector selector, boolean removeOrphans) {
             this.selector = selector;
-            this.removeOnlyInputs = removeOnlyInputs;
-            this.removeAllWithoutPredecessor = removeAllWithoutPredecessor;
+            this.removeOrphans = removeOrphans;
         }
 
         public Selector getSelector() {
             return selector;
         }
 
-        public boolean getRemoveOnlyInputs() {
-            return removeOnlyInputs;
-        }
-
-        public boolean getRemoveAllWithoutPredecessor() {
-            return removeAllWithoutPredecessor;
+        public boolean getRemoveOrphans() {
+            return removeOrphans;
         }
     }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveInputsFilter.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveInputsFilter.java	Fri May 08 13:25:11 2015 -0400
@@ -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,12 +23,7 @@
  */
 package com.sun.hotspot.igv.filter;
 
-import com.sun.hotspot.igv.graph.Connection;
-import com.sun.hotspot.igv.graph.Diagram;
-import com.sun.hotspot.igv.graph.Figure;
-import com.sun.hotspot.igv.graph.InputSlot;
-import com.sun.hotspot.igv.graph.OutputSlot;
-import com.sun.hotspot.igv.graph.Selector;
+import com.sun.hotspot.igv.graph.*;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -43,13 +38,15 @@
 
     public RemoveInputsFilter(String name) {
         this.name = name;
-        rules = new ArrayList<RemoveInputsRule>();
+        rules = new ArrayList<>();
     }
 
+    @Override
     public String getName() {
         return name;
     }
 
+    @Override
     public void apply(Diagram diagram) {
 
         for (RemoveInputsRule r : rules) {
@@ -57,7 +54,7 @@
             List<Figure> list = r.getSelector().selected(diagram);
             for (Figure f : list) {
                 int z = 0;
-                List<InputSlot> last = new ArrayList<InputSlot>();
+                List<InputSlot> last = new ArrayList<>();
                 for (InputSlot is : f.getInputSlots()) {
                     if (z >= r.getStartingIndex() && z <= r.getEndIndex() && is.getConnections().size() > 0) {
                         StringBuilder sb = new StringBuilder();
@@ -73,7 +70,7 @@
                         }
                         is.removeAllConnections();
                         is.setShortName("X");
-                        is.setName(sb.toString());
+                        is.setText(sb.toString());
                         last.add(is);
                     } else {
                         last.clear();
@@ -91,10 +88,10 @@
                         if (i != 0) {
                             sb.append("<BR>");
                         }
-                        sb.append(is2.getName());
+                        sb.append(is2.getText());
                     }
 
-                    first.setName(sb.toString());
+                    first.setText(sb.toString());
 
                     for (int i = 1; i < last.size(); i++) {
                         f.removeSlot(last.get(i));
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveSelfLoopsFilter.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveSelfLoopsFilter.java	Fri May 08 13:25:11 2015 -0400
@@ -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,11 +23,7 @@
  */
 package com.sun.hotspot.igv.filter;
 
-import com.sun.hotspot.igv.graph.Connection;
-import com.sun.hotspot.igv.graph.Diagram;
-import com.sun.hotspot.igv.graph.Figure;
-import com.sun.hotspot.igv.graph.InputSlot;
-import com.sun.hotspot.igv.graph.OutputSlot;
+import com.sun.hotspot.igv.graph.*;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -44,17 +40,19 @@
         this.name = name;
     }
 
+    @Override
     public String getName() {
         return name;
     }
 
+    @Override
     public void apply(Diagram d) {
 
         for (Figure f : d.getFigures()) {
 
             for (InputSlot is : f.getInputSlots()) {
 
-                List<Connection> toRemove = new ArrayList<Connection>();
+                List<Connection> toRemove = new ArrayList<>();
                 for (Connection c : is.getConnections()) {
 
                     if (c.getOutputSlot().getFigure() == f) {
@@ -72,7 +70,7 @@
                     }
 
                     c.getInputSlot().setShortName("O");
-                    c.getInputSlot().setName("Self Loop");
+                    c.getInputSlot().setText("Self Loop");
                 }
             }
         }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/ScriptEngineAbstraction.java	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 1998, 2007, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.sun.hotspot.igv.filter;
-
-import com.sun.hotspot.igv.graph.Diagram;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public interface ScriptEngineAbstraction {
-
-    public boolean initialize(String jsHelperText);
-
-    public void execute(Diagram d, String code);
-}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/SplitFilter.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/SplitFilter.java	Fri May 08 13:25:11 2015 -0400
@@ -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,12 +23,7 @@
  */
 package com.sun.hotspot.igv.filter;
 
-import com.sun.hotspot.igv.graph.Connection;
-import com.sun.hotspot.igv.graph.Diagram;
-import com.sun.hotspot.igv.graph.Figure;
-import com.sun.hotspot.igv.graph.InputSlot;
-import com.sun.hotspot.igv.graph.OutputSlot;
-import com.sun.hotspot.igv.graph.Selector;
+import com.sun.hotspot.igv.graph.*;
 import java.util.List;
 
 /**
@@ -39,25 +34,52 @@
 
     private String name;
     private Selector selector;
+    private String propertyName;
 
-    public SplitFilter(String name, Selector selector) {
+    public SplitFilter(String name, Selector selector, String propertyName) {
         this.name = name;
         this.selector = selector;
+        this.propertyName = propertyName;
     }
 
+    @Override
     public String getName() {
         return name;
     }
 
+    @Override
     public void apply(Diagram d) {
         List<Figure> list = selector.selected(d);
 
         for (Figure f : list) {
+
+            for (InputSlot is : f.getInputSlots()) {
+                for (Connection c : is.getConnections()) {
+                    OutputSlot os = c.getOutputSlot();
+                    if (f.getSource().getSourceNodes().size() > 0) {
+                        os.getSource().addSourceNodes(f.getSource());
+                        os.setAssociatedNode(f.getSource().getSourceNodes().get(0));
+                        os.setColor(f.getColor());
+                    }
+
+
+                    String s = Figure.resolveString(propertyName, f.getProperties());
+                    if (s != null) {
+                        os.setShortName(s);
+                    }
+
+                }
+            }
             for (OutputSlot os : f.getOutputSlots()) {
                 for (Connection c : os.getConnections()) {
                     InputSlot is = c.getInputSlot();
-                    is.setName(f.getProperties().get("dump_spec"));
-                    String s = f.getProperties().get("short_name");
+                    if (f.getSource().getSourceNodes().size() > 0) {
+                        is.getSource().addSourceNodes(f.getSource());
+                        is.setAssociatedNode(f.getSource().getSourceNodes().get(0));
+                        is.setColor(f.getColor());
+                    }
+
+                    String s = Figure.resolveString(propertyName, f.getProperties());
                     if (s != null) {
                         is.setShortName(s);
                     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/UnconnectedSlotFilter.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011, 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.filter;
+
+import com.sun.hotspot.igv.graph.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Filter that hides slots with no connections.
+ */
+public class UnconnectedSlotFilter extends AbstractFilter {
+
+    private final boolean removeInputs;
+    private final boolean removeOutputs;
+
+    public UnconnectedSlotFilter(boolean inputs, boolean outputs) {
+        this.removeInputs = inputs;
+        this.removeOutputs = outputs;
+    }
+
+    @Override
+    public String getName() {
+        return "Unconnected Slot Filter";
+    }
+
+    @Override
+    public void apply(Diagram d) {
+        if (!removeInputs && !removeOutputs) {
+            return;
+        }
+
+        List<Figure> figures = d.getFigures();
+        for (Figure f : figures) {
+            List<Slot> remove = new ArrayList<>();
+            if (removeInputs) {
+                for (InputSlot is : f.getInputSlots()) {
+                    if (is.getConnections().isEmpty()) {
+                        remove.add(is);
+                    }
+                }
+            }
+            if (removeOutputs) {
+                for (OutputSlot os : f.getOutputSlots()) {
+                    if (os.getConnections().isEmpty()) {
+                        remove.add(os);
+                    }
+                }
+            }
+            for (Slot s : remove) {
+                f.removeSlot(s);
+            }
+        }
+    }
+}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/helper.js	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/helper.js	Fri May 08 13:25:11 2015 -0400
@@ -21,26 +21,35 @@
  * questions.
  *
  */
-
+ 
  /**
  *
  * @author Thomas Wuerthinger
  */
-
+ 
 function colorize(property, regexp, color) {
     var f = new ColorFilter("");
     f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), color));
-    f.apply(graph);
+    f.apply(graph); 
 }
 
 function remove(property, regexp) {
     var f = new RemoveFilter("");
-    f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), false, false));
+    f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp))));
     f.apply(graph);
 }
 
-function split(property, regexp) {
-    var f = new SplitFilter("", new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)));
+function removeIncludingOrphans(property, regexp) {
+    var f = new RemoveFilter("");
+    f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), true));
+    f.apply(graph);
+}
+
+function split(property, regexp, propertyName) {
+    if (propertyName == undefined) {
+        propertyName = graph.getNodeText();
+    }
+    var f = new SplitFilter("", new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), propertyName);
     f.apply(graph);
 }
 
@@ -56,6 +65,40 @@
     f.apply(graph);
 }
 
+function removeUnconnectedSlots(inputs, outputs) {
+    var f = new UnconnectedSlotFilter(inputs, outputs);
+    f.apply(graph);
+}
+
+function colorizeGradient(property, min, max) {
+    var f = new GradientColorFilter();
+    f.setPropertyName(property);
+    f.setMinValue(min);
+    f.setMaxValue(max);
+    f.apply(graph);
+}
+
+function colorizeGradientWithMode(property, min, max, mode) {
+    var f = new GradientColorFilter();
+    f.setPropertyName(property);
+    f.setMinValue(min);
+    f.setMaxValue(max);
+    f.setMode(mode);
+    f.apply(graph);
+}
+
+function colorizeGradientCustom(property, min, max, mode, colors, fractions, nshades) {
+    var f = new GradientColorFilter();
+    f.setPropertyName(property);
+    f.setMinValue(min);
+    f.setMaxValue(max);
+    f.setMode(mode);
+    f.setColors(colors);
+    f.setFractions(fractions);
+    f.setShadeCount(nshades);
+    f.apply(graph);
+}
+
 var black = Color.black;
 var blue = Color.blue;
 var cyan = Color.cyan;
@@ -68,4 +111,4 @@
 var pink = Color.pink
 var red = Color.red;
 var yellow = Color.yellow;
-var white = Color.white;
+var white = Color.white;
\ No newline at end of file
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/build-impl.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/build-impl.xml	Fri May 08 13:25:11 2015 -0400
@@ -4,6 +4,13 @@
 ***         EDIT ../build.xml INSTEAD         ***
 -->
 <project name="com.sun.hotspot.igv.filterwindow-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
     <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>
@@ -16,13 +23,21 @@
             <property name="@{name}" value="${@{value}}"/>
         </sequential>
     </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" 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'">
+    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
         <condition>
             <not>
-                <available file="${harness.dir}" type="dir"/>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
             </not>
         </condition>
     </fail>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/genfiles.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/genfiles.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,8 +1,5 @@
-build.xml.data.CRC32=401b2654
-build.xml.script.CRC32=9c158403
-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=401b2654
-nbproject/build-impl.xml.script.CRC32=19fb08e0
-nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
+nbproject/build-impl.xml.data.CRC32=5b8e8a60
+nbproject/build-impl.xml.script.CRC32=e4293f0e
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.67.1
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/project.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/project.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/project.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/project.xml	Fri May 08 13:25:11 2015 -0400
@@ -43,7 +43,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.6.1.1</specification-version>
+                        <specification-version>6.21.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.awt</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.39.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -51,7 +59,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.5.1</specification-version>
+                        <specification-version>7.18.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -59,7 +67,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.12.1</specification-version>
+                        <specification-version>6.34.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -67,7 +75,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.3.1</specification-version>
+                        <specification-version>7.46.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -75,7 +83,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.7.1</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -83,7 +91,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.2.1.1</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -91,7 +99,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.10.1.1</specification-version>
+                        <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>
@@ -99,7 +115,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.18.1</specification-version>
+                        <specification-version>6.39.1</specification-version>
                     </run-dependency>
                 </dependency>
             </module-dependencies>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/Bundle.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/Bundle.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,3 +1,3 @@
 OpenIDE-Module-Name=FilterWindow
-CTL_FilterTopComponent=Filter Window
-HINT_FilterTopComponent=This is a Filter window
+CTL_FilterTopComponent=Filters
+HINT_FilterTopComponent=Allows to choose active filters and modify them.
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckListView.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckListView.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -44,8 +44,8 @@
     }
 
     @Override
-    protected JList createList() {
-        JList tmpList = super.createList();
+    protected JList<Object> createList() {
+        JList<Object> tmpList = super.createList();
         tmpList.setCellRenderer(new CheckRenderer(tmpList));
         return tmpList;
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckNode.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckNode.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -40,7 +40,7 @@
 
     public CheckNode(Children c, Lookup lookup) {
         super(c, lookup);
-        selectionChangedEvent = new ChangedEvent<CheckNode>(this);
+        selectionChangedEvent = new ChangedEvent<>(this);
         selected = false;
         enabled = true;
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckNodeListModel.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckNodeListModel.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -24,7 +24,7 @@
 package com.sun.hotspot.igv.filterwindow;
 
 import org.openide.explorer.view.NodeListModel;
-import org.openide.nodes.Node;
+import org.openide.explorer.view.Visualizer;
 
 /**
  *
@@ -32,15 +32,11 @@
  */
 public class CheckNodeListModel extends NodeListModel {
 
-    private Node rootNode;
-
-    @Override
-    public void setNode(Node rootNode) {
-        this.rootNode = rootNode;
-        super.setNode(rootNode);
-    }
-
     public CheckNode getCheckNodeAt(int index) {
-        return (CheckNode) rootNode.getChildren().getNodes()[index];
+        Object item = getElementAt(index);
+        if (item != null) {
+            return (CheckNode) Visualizer.findNode(item);
+        }
+        return null;
     }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckRenderer.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckRenderer.java	Fri May 08 13:25:11 2015 -0400
@@ -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,11 +23,7 @@
  */
 package com.sun.hotspot.igv.filterwindow;
 
-import java.awt.Color;
-import java.awt.Component;
-import java.awt.Dimension;
-import java.awt.Point;
-import java.awt.Rectangle;
+import java.awt.*;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import javax.swing.JCheckBox;
@@ -37,12 +33,12 @@
 /**
  * @author Thomas Wuerthinger
  */
-public class CheckRenderer extends JCheckBox implements ListCellRenderer {
+public class CheckRenderer extends JCheckBox implements ListCellRenderer<Object> {
 
-    private JList list;
+    private JList<Object> list;
     private Color startBackground;
 
-    public CheckRenderer(final JList list) {
+    public CheckRenderer(final JList<Object> list) {
         this.list = list;
         list.addMouseListener(
                 new MouseAdapter() {
@@ -65,7 +61,8 @@
         startBackground = this.getBackground();
     }
 
-    public Component getListCellRendererComponent(final JList list, Object value, final int index, boolean isSelected, boolean cellHasFocus) {
+    @Override
+    public Component getListCellRendererComponent(final JList<? extends Object> list, Object value, final int index, boolean isSelected, boolean cellHasFocus) {
         setText(value.toString());
         CheckNode node = ((CheckNodeListModel) list.getModel()).getCheckNodeAt(index);
         this.setSelected(node.isSelected());
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterChainProviderImplementation.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterChainProviderImplementation.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -32,10 +32,12 @@
  */
 public class FilterChainProviderImplementation implements FilterChainProvider {
 
+    @Override
     public FilterChain getFilterChain() {
         return FilterTopComponent.findInstance().getFilterChain();
     }
 
+    @Override
     public FilterChain getSequence() {
         return FilterTopComponent.findInstance().getSequence();
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterNode.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterNode.java	Fri May 08 13:25:11 2015 -0400
@@ -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,12 +23,12 @@
  */
 package com.sun.hotspot.igv.filterwindow;
 
+import com.sun.hotspot.igv.data.ChangedListener;
+import com.sun.hotspot.igv.filter.Filter;
+import com.sun.hotspot.igv.filter.FilterChain;
 import com.sun.hotspot.igv.filterwindow.actions.MoveFilterDownAction;
 import com.sun.hotspot.igv.filterwindow.actions.MoveFilterUpAction;
 import com.sun.hotspot.igv.filterwindow.actions.RemoveFilterAction;
-import com.sun.hotspot.igv.filter.Filter;
-import com.sun.hotspot.igv.filter.FilterChain;
-import com.sun.hotspot.igv.data.ChangedListener;
 import com.sun.hotspot.igv.util.PropertiesSheet;
 import javax.swing.Action;
 import org.openide.actions.OpenAction;
@@ -48,7 +48,7 @@
 public class FilterNode extends CheckNode implements LookupListener, ChangedListener<FilterTopComponent> {
 
     private Filter filter;
-    private Lookup.Result result;
+    private Lookup.Result<FilterChain> result;
 
     public FilterNode(Filter filter) {
         this(filter, new InstanceContent());
@@ -62,6 +62,7 @@
         this.filter = filter;
         filter.getChangedEvent().addListener(new ChangedListener<Filter>() {
 
+            @Override
             public void changed(Filter source) {
                 update();
             }
@@ -69,12 +70,14 @@
 
         update();
 
-        Lookup.Template<FilterChain> tpl = new Lookup.Template<FilterChain>(FilterChain.class);
+        Lookup.Template<FilterChain> tpl = new Lookup.Template<>(FilterChain.class);
         result = Utilities.actionsGlobalContext().lookup(tpl);
         result.addLookupListener(this);
 
         FilterTopComponent.findInstance().getFilterSettingsChangedEvent().addListener(this);
         resultChanged(null);
+
+        setShortDescription("Double-click to open filter");
     }
 
     private void update() {
@@ -102,10 +105,12 @@
         return OpenAction.get(OpenAction.class).createContextAwareInstance(Utilities.actionsGlobalContext());
     }
 
+    @Override
     public void resultChanged(LookupEvent lookupEvent) {
         changed(FilterTopComponent.findInstance());
     }
 
+    @Override
     public void changed(FilterTopComponent source) {
         setSelected(source.getFilterChain().containsFilter(filter));
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponent.form	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponent.form	Fri May 08 13:25:11 2015 -0400
@@ -3,6 +3,8 @@
 <Form version="1.2" maxVersion="1.2" 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"/>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponent.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponent.java	Fri May 08 13:25:11 2015 -0400
@@ -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,65 +23,38 @@
  */
 package com.sun.hotspot.igv.filterwindow;
 
-import com.sun.hotspot.igv.filterwindow.actions.MoveFilterDownAction;
-import com.sun.hotspot.igv.filterwindow.actions.MoveFilterUpAction;
-import com.sun.hotspot.igv.filterwindow.actions.NewFilterAction;
-import com.sun.hotspot.igv.filterwindow.actions.RemoveFilterAction;
-import com.sun.hotspot.igv.filterwindow.actions.RemoveFilterSettingsAction;
-import com.sun.hotspot.igv.filterwindow.actions.SaveFilterSettingsAction;
+import com.sun.hotspot.igv.data.ChangedEvent;
+import com.sun.hotspot.igv.data.ChangedListener;
 import com.sun.hotspot.igv.filter.CustomFilter;
 import com.sun.hotspot.igv.filter.Filter;
 import com.sun.hotspot.igv.filter.FilterChain;
 import com.sun.hotspot.igv.filter.FilterSetting;
-import com.sun.hotspot.igv.data.ChangedEvent;
-import com.sun.hotspot.igv.data.ChangedListener;
+import com.sun.hotspot.igv.filterwindow.actions.*;
 import java.awt.BorderLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.io.BufferedReader;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Serializable;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.io.*;
+import java.util.*;
 import javax.swing.JComboBox;
 import javax.swing.UIManager;
 import javax.swing.border.Border;
 import org.openide.DialogDisplayer;
 import org.openide.ErrorManager;
 import org.openide.NotifyDescriptor;
+import org.openide.awt.Toolbar;
 import org.openide.awt.ToolbarPool;
 import org.openide.explorer.ExplorerManager;
 import org.openide.explorer.ExplorerUtils;
+import org.openide.filesystems.FileLock;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
 import org.openide.nodes.AbstractNode;
 import org.openide.nodes.Children;
 import org.openide.nodes.Node;
-import org.openide.util.Exceptions;
-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.awt.Toolbar;
-import org.openide.filesystems.FileLock;
+import org.openide.util.*;
 import org.openide.util.actions.SystemAction;
 import org.openide.windows.TopComponent;
 import org.openide.windows.WindowManager;
-import org.openide.filesystems.Repository;
-import org.openide.filesystems.FileSystem;
-import org.openide.filesystems.FileObject;
 
 /**
  *
@@ -98,13 +71,14 @@
     private ExplorerManager manager;
     private FilterChain filterChain;
     private FilterChain sequence;
-    private Lookup.Result result;
+    private Lookup.Result<FilterChain> result;
     private JComboBox comboBox;
     private List<FilterSetting> filterSettings;
     private FilterSetting customFilterSetting = new FilterSetting("-- Custom --");
     private ChangedEvent<FilterTopComponent> filterSettingsChangedEvent;
     private ActionListener comboBoxActionListener = new ActionListener() {
 
+        @Override
         public void actionPerformed(ActionEvent e) {
             comboBoxSelectionChanged();
         }
@@ -139,8 +113,8 @@
 
         if (s != customFilterSetting) {
             FilterChain chain = getFilterChain();
-            chain.beginAtomic();
-            List<Filter> toRemove = new ArrayList<Filter>();
+            chain.getChangedEvent().beginAtomic();
+            List<Filter> toRemove = new ArrayList<>();
             for (Filter f : chain.getFilters()) {
                 if (!s.containsFilter(f)) {
                     toRemove.add(f);
@@ -156,7 +130,7 @@
                 }
             }
 
-            chain.endAtomic();
+            chain.getChangedEvent().endAtomic();
             filterSettingsChangedEvent.fire();
         } else {
             this.updateComboBoxSelection();
@@ -177,14 +151,14 @@
     }
 
     public void addFilterSetting() {
-        NotifyDescriptor.InputLine l = new NotifyDescriptor.InputLine("Enter a name:", "Filter");
+        NotifyDescriptor.InputLine l = new NotifyDescriptor.InputLine("Name of the new profile:", "Filter Profile");
         if (DialogDisplayer.getDefault().notify(l) == NotifyDescriptor.OK_OPTION) {
             String name = l.getInputText();
 
             FilterSetting toRemove = null;
             for (FilterSetting s : filterSettings) {
                 if (s.getName().equals(name)) {
-                    NotifyDescriptor.Confirmation conf = new NotifyDescriptor.Confirmation("Filter \"" + name + "\" already exists, to you want to overwrite?", "Filter");
+                    NotifyDescriptor.Confirmation conf = new NotifyDescriptor.Confirmation("Filter profile \"" + name + "\" already exists, do you want to replace it?", "Filter");
                     if (DialogDisplayer.getDefault().notify(conf) == NotifyDescriptor.YES_OPTION) {
                         toRemove = s;
                         break;
@@ -203,6 +177,7 @@
             // Sort alphabetically
             Collections.sort(filterSettings, new Comparator<FilterSetting>() {
 
+                @Override
                 public int compare(FilterSetting o1, FilterSetting o2) {
                     return o1.getName().compareTo(o2.getName());
                 }
@@ -223,7 +198,7 @@
             FilterSetting f = (FilterSetting) o;
             assert f != customFilterSetting;
             assert filterSettings.contains(f);
-            NotifyDescriptor.Confirmation l = new NotifyDescriptor.Confirmation("Do you really want to remove filter \"" + f + "\"?", "Filter");
+            NotifyDescriptor.Confirmation l = new NotifyDescriptor.Confirmation("Do you really want to remove filter profile \"" + f + "\"?", "Filter Profile");
             if (DialogDisplayer.getDefault().notify(l) == NotifyDescriptor.YES_OPTION) {
                 filterSettings.remove(f);
                 updateComboBox();
@@ -267,28 +242,26 @@
         }
     }
 
-    private class FilterChildren extends Children.Keys implements ChangedListener<CheckNode> {
+    private class FilterChildren extends Children.Keys<Filter> implements ChangedListener<CheckNode> {
+
+        private HashMap<Filter, Node> nodeHash = new HashMap<>();
 
-        //private Node[] oldSelection;
-        //private ArrayList<Node> newSelection;
-        private HashMap<Object, Node> nodeHash = new HashMap<Object, Node>();
-
-        protected Node[] createNodes(Object object) {
-            if (nodeHash.containsKey(object)) {
-                return new Node[]{nodeHash.get(object)};
+        @Override
+        protected Node[] createNodes(Filter filter) {
+            if (nodeHash.containsKey(filter)) {
+                return new Node[]{nodeHash.get(filter)};
             }
 
-            assert object instanceof Filter;
-            Filter filter = (Filter) object;
-            com.sun.hotspot.igv.filterwindow.FilterNode node = new com.sun.hotspot.igv.filterwindow.FilterNode(filter);
+            FilterNode node = new FilterNode(filter);
             node.getSelectionChangedEvent().addListener(this);
-            nodeHash.put(object, node);
+            nodeHash.put(filter, node);
             return new Node[]{node};
         }
 
         public FilterChildren() {
             sequence.getChangedEvent().addListener(new ChangedListener<FilterChain>() {
 
+                @Override
                 public void changed(FilterChain source) {
                     addNotify();
                 }
@@ -297,11 +270,13 @@
             setBefore(false);
         }
 
+        @Override
         protected void addNotify() {
             setKeys(sequence.getFilters());
             updateSelection();
         }
 
+        @Override
         public void changed(CheckNode source) {
             FilterNode node = (FilterNode) source;
             Filter f = node.getFilter();
@@ -322,16 +297,11 @@
     }
 
     public FilterChain getFilterChain() {
-        return filterChain;/*
-    EditorTopComponent tc = EditorTopComponent.getActive();
-    if (tc == null) {
-    return filterChain;
-    }
-    return tc.getFilterChain();*/
+        return filterChain;
     }
 
     private FilterTopComponent() {
-        filterSettingsChangedEvent = new ChangedEvent<FilterTopComponent>(this);
+        filterSettingsChangedEvent = new ChangedEvent<>(this);
         initComponents();
         setName(NbBundle.getMessage(FilterTopComponent.class, "CTL_FilterTopComponent"));
         setToolTipText(NbBundle.getMessage(FilterTopComponent.class, "HINT_FilterTopComponent"));
@@ -355,13 +325,13 @@
         toolBar.add(SaveFilterSettingsAction.get(SaveFilterSettingsAction.class));
         toolBar.add(RemoveFilterSettingsAction.get(RemoveFilterSettingsAction.class));
         toolBar.addSeparator();
+        toolBar.add(NewFilterAction.get(NewFilterAction.class));
+        toolBar.add(RemoveFilterAction.get(RemoveFilterAction.class).createContextAwareInstance(this.getLookup()));
         toolBar.add(MoveFilterUpAction.get(MoveFilterUpAction.class).createContextAwareInstance(this.getLookup()));
         toolBar.add(MoveFilterDownAction.get(MoveFilterDownAction.class).createContextAwareInstance(this.getLookup()));
-        toolBar.add(RemoveFilterAction.get(RemoveFilterAction.class).createContextAwareInstance(this.getLookup()));
-        toolBar.add(NewFilterAction.get(NewFilterAction.class));
         this.add(view, BorderLayout.CENTER);
 
-        filterSettings = new ArrayList<FilterSetting>();
+        filterSettings = new ArrayList<>();
         updateComboBox();
 
         comboBox.addActionListener(comboBoxActionListener);
@@ -401,6 +371,7 @@
             filter = cf;
         }
 
+        @Override
         public void changed(Filter source) {
             try {
                 if (!fileObject.getName().equals(filter.getName())) {
@@ -409,15 +380,14 @@
                     lock.releaseLock();
                     FileObject newFileObject = fileObject.getParent().getFileObject(filter.getName());
                     fileObject = newFileObject;
-
                 }
 
                 FileLock lock = fileObject.lock();
                 OutputStream os = fileObject.getOutputStream(lock);
-                Writer w = new OutputStreamWriter(os);
-                String s = filter.getCode();
-                w.write(s);
-                w.close();
+                try (Writer w = new OutputStreamWriter(os)) {
+                    String s = filter.getCode();
+                    w.write(s);
+                }
                 lock.releaseLock();
 
             } catch (IOException ex) {
@@ -427,15 +397,13 @@
     }
 
     public void initFilters() {
-
-        FileSystem fs = Repository.getDefault().getDefaultFileSystem();
-        FileObject folder = fs.getRoot().getFileObject(FOLDER_ID);
+        FileObject folder = FileUtil.getConfigRoot().getFileObject(FOLDER_ID);
         FileObject[] children = folder.getChildren();
 
-        List<CustomFilter> customFilters = new ArrayList<CustomFilter>();
-        HashMap<CustomFilter, String> afterMap = new HashMap<CustomFilter, String>();
-        Set<CustomFilter> enabledSet = new HashSet<CustomFilter>();
-        HashMap<String, CustomFilter> map = new HashMap<String, CustomFilter>();
+        List<CustomFilter> customFilters = new ArrayList<>();
+        HashMap<CustomFilter, String> afterMap = new HashMap<>();
+        Set<CustomFilter> enabledSet = new HashSet<>();
+        HashMap<String, CustomFilter> map = new HashMap<>();
 
         for (final FileObject fo : children) {
             InputStream is = null;
@@ -447,13 +415,12 @@
                 is = fo.getInputStream();
                 BufferedReader r = new BufferedReader(new InputStreamReader(is));
                 String s;
-                StringBuffer sb = new StringBuffer();
+                StringBuilder sb = new StringBuilder();
                 while ((s = r.readLine()) != null) {
                     sb.append(s);
                     sb.append("\n");
                 }
                 code = sb.toString();
-
             } catch (FileNotFoundException ex) {
                 Exceptions.printStackTrace(ex);
             } catch (IOException ex) {
@@ -488,7 +455,7 @@
 
         for (int j = 0; j < customFilters.size(); j++) {
             for (int i = 0; i < customFilters.size(); i++) {
-                List<CustomFilter> copiedList = new ArrayList<CustomFilter>(customFilters);
+                List<CustomFilter> copiedList = new ArrayList<>(customFilters);
                 for (CustomFilter cf : copiedList) {
 
                     String after = afterMap.get(cf);
@@ -573,7 +540,7 @@
 
     @Override
     public void componentOpened() {
-        Lookup.Template<FilterChain> tpl = new Lookup.Template<FilterChain>(FilterChain.class);
+        Lookup.Template<FilterChain> tpl = new Lookup.Template<>(FilterChain.class);
         result = Utilities.actionsGlobalContext().lookup(tpl);
         result.addLookupListener(this);
     }
@@ -584,13 +551,9 @@
         result = null;
     }
 
+    @Override
     public void resultChanged(LookupEvent lookupEvent) {
         setChain(Utilities.actionsGlobalContext().lookup(FilterChain.class));
-    /*
-    EditorTopComponent tc = EditorTopComponent.getActive();
-    if (tc != null) {
-    setChain(tc.getFilterChain());
-    }*/
     }
 
     public void setChain(FilterChain chain) {
@@ -598,10 +561,10 @@
     }
 
     private FileObject getFileObject(CustomFilter cf) {
-        FileObject fo = Repository.getDefault().getDefaultFileSystem().getRoot().getFileObject(FOLDER_ID + "/" + cf.getName());
+        FileObject fo = FileUtil.getConfigRoot().getFileObject(FOLDER_ID + "/" + cf.getName());
         if (fo == null) {
             try {
-                fo = org.openide.filesystems.Repository.getDefault().getDefaultFileSystem().getRoot().getFileObject(FOLDER_ID).createData(cf.getName());
+                fo = FileUtil.getConfigRoot().getFileObject(FOLDER_ID).createData(cf.getName());
             } catch (IOException ex) {
                 Exceptions.printStackTrace(ex);
             }
@@ -610,6 +573,24 @@
     }
 
     @Override
+    public boolean requestFocus(boolean temporary) {
+        view.requestFocus();
+        return super.requestFocus(temporary);
+    }
+
+    @Override
+    protected boolean requestFocusInWindow(boolean temporary) {
+        view.requestFocus();
+        return super.requestFocusInWindow(temporary);
+    }
+
+    @Override
+    public void requestActive() {
+        super.requestActive();
+        view.requestFocus();
+    }
+
+    @Override
     public void writeExternal(ObjectOutput out) throws IOException {
         super.writeExternal(out);
 
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/Bundle.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/Bundle.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,10 +1,7 @@
-# To change this template, choose Tools | Templates
-# and open the template in the editor.
-
-CTL_FilterAction=Open Filter Window
+CTL_FilterAction=Filters
+CTL_MoveFilterUpAction=Move upwards
 CTL_MoveFilterDownAction=Move downwards
-CTL_MoveFilterUpAction=Move upwards
-CTL_NewFilterAction=New filter...
 CTL_RemoveFilterAction=Remove
 CTL_RemoveFilterSettingsAction=Remove filter setting
-CTL_SaveFilterSettingsAction=Save filter settings...
+CTL_SaveFilterSettingsAction=Create filter profile...
+CTL_NewFilterAction=New filter...
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/FilterAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/FilterAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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,7 +23,7 @@
  */
 package com.sun.hotspot.igv.filterwindow.actions;
 
-import com.sun.hotspot.igv.filterwindow.*;
+import com.sun.hotspot.igv.filterwindow.FilterTopComponent;
 import java.awt.event.ActionEvent;
 import javax.swing.AbstractAction;
 import org.openide.util.NbBundle;
@@ -39,6 +39,7 @@
         super(NbBundle.getMessage(FilterAction.class, "CTL_FilterAction"));
     }
 
+    @Override
     public void actionPerformed(ActionEvent evt) {
         TopComponent win = FilterTopComponent.findInstance();
         win.open();
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/MoveFilterDownAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/MoveFilterDownAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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,8 +23,8 @@
  */
 package com.sun.hotspot.igv.filterwindow.actions;
 
+import com.sun.hotspot.igv.filter.Filter;
 import com.sun.hotspot.igv.filterwindow.FilterTopComponent;
-import com.sun.hotspot.igv.filter.Filter;
 import javax.swing.Action;
 import org.openide.nodes.Node;
 import org.openide.util.HelpCtx;
@@ -37,6 +37,7 @@
  */
 public final class MoveFilterDownAction extends CookieAction {
 
+    @Override
     protected void performAction(Node[] activatedNodes) {
         for (Node n : activatedNodes) {
             Filter c = n.getLookup().lookup(Filter.class);
@@ -44,19 +45,22 @@
         }
     }
 
+    @Override
     protected int mode() {
         return CookieAction.MODE_EXACTLY_ONE;
     }
 
     public MoveFilterDownAction() {
 
-        putValue(Action.SHORT_DESCRIPTION, "Move filter downwards");
+        putValue(Action.SHORT_DESCRIPTION, "Move selected filter downwards");
     }
 
+    @Override
     public String getName() {
         return NbBundle.getMessage(MoveFilterUpAction.class, "CTL_MoveFilterDownAction");
     }
 
+    @Override
     protected Class[] cookieClasses() {
         return new Class[]{
             Filter.class
@@ -65,7 +69,7 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/filterwindow/images/down.gif";
+        return "com/sun/hotspot/igv/filterwindow/images/down.png";
     }
 
     @Override
@@ -74,6 +78,7 @@
         putValue("noIconInMenu", Boolean.TRUE);
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/MoveFilterUpAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/MoveFilterUpAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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,8 +23,8 @@
  */
 package com.sun.hotspot.igv.filterwindow.actions;
 
+import com.sun.hotspot.igv.filter.Filter;
 import com.sun.hotspot.igv.filterwindow.FilterTopComponent;
-import com.sun.hotspot.igv.filter.Filter;
 import javax.swing.Action;
 import org.openide.nodes.Node;
 import org.openide.util.HelpCtx;
@@ -37,6 +37,7 @@
  */
 public final class MoveFilterUpAction extends CookieAction {
 
+    @Override
     protected void performAction(Node[] activatedNodes) {
         for (Node n : activatedNodes) {
             Filter c = n.getLookup().lookup(Filter.class);
@@ -44,18 +45,21 @@
         }
     }
 
+    @Override
     protected int mode() {
         return CookieAction.MODE_EXACTLY_ONE;
     }
 
     public MoveFilterUpAction() {
-        putValue(Action.SHORT_DESCRIPTION, "Move filter upwards");
+        putValue(Action.SHORT_DESCRIPTION, "Move selected filter upwards");
     }
 
+    @Override
     public String getName() {
         return NbBundle.getMessage(MoveFilterUpAction.class, "CTL_MoveFilterUpAction");
     }
 
+    @Override
     protected Class[] cookieClasses() {
         return new Class[]{
             Filter.class
@@ -64,7 +68,7 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/filterwindow/images/up.gif";
+        return "com/sun/hotspot/igv/filterwindow/images/up.png";
     }
 
     @Override
@@ -73,6 +77,7 @@
         putValue("noIconInMenu", Boolean.TRUE);
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/NewFilterAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/NewFilterAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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,10 +39,12 @@
         putValue(Action.SHORT_DESCRIPTION, "Create new filter");
     }
 
+    @Override
     public void performAction() {
         FilterTopComponent.findInstance().newFilter();
     }
 
+    @Override
     public String getName() {
         return NbBundle.getMessage(SaveFilterSettingsAction.class, "CTL_NewFilterAction");
     }
@@ -52,6 +54,7 @@
         super.initialize();
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
@@ -63,6 +66,6 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/filterwindow/images/plus.gif";
+        return "com/sun/hotspot/igv/filterwindow/images/plus.png";
     }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/RemoveFilterAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/RemoveFilterAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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,8 +23,8 @@
  */
 package com.sun.hotspot.igv.filterwindow.actions;
 
+import com.sun.hotspot.igv.filter.Filter;
 import com.sun.hotspot.igv.filterwindow.FilterTopComponent;
-import com.sun.hotspot.igv.filter.Filter;
 import javax.swing.Action;
 import javax.swing.JOptionPane;
 import org.openide.nodes.Node;
@@ -39,13 +39,14 @@
  */
 public final class RemoveFilterAction extends CookieAction {
 
+    @Override
     protected void performAction(Node[] activatedNodes) {
         Object[] options = {"Yes",
             "No",
             "Cancel"
         };
         int n = JOptionPane.showOptionDialog(WindowManager.getDefault().getMainWindow(),
-                "Do you really want to delete " + activatedNodes.length + " filter/s?", "Delete?",
+                "Do you really want to delete " + activatedNodes.length + " filter(s)?", "Delete Filters",
                 JOptionPane.YES_NO_CANCEL_OPTION,
                 JOptionPane.QUESTION_MESSAGE,
                 null,
@@ -59,18 +60,21 @@
         }
     }
 
+    @Override
     protected int mode() {
         return CookieAction.MODE_ALL;
     }
 
+    @Override
     public String getName() {
         return NbBundle.getMessage(RemoveFilterAction.class, "CTL_RemoveFilterAction");
     }
 
     public RemoveFilterAction() {
-        putValue(Action.SHORT_DESCRIPTION, "Remove filter");
+        putValue(Action.SHORT_DESCRIPTION, "Remove selected filter");
     }
 
+    @Override
     protected Class[] cookieClasses() {
         return new Class[]{
             Filter.class
@@ -85,9 +89,10 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/filterwindow/images/minus.gif";
+        return "com/sun/hotspot/igv/filterwindow/images/minus.png";
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/RemoveFilterSettingsAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/RemoveFilterSettingsAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -35,16 +35,18 @@
  */
 public final class RemoveFilterSettingsAction extends CallableSystemAction {
 
+    @Override
     public void performAction() {
         FilterTopComponent.findInstance().removeFilterSetting();
     }
 
+    @Override
     public String getName() {
         return NbBundle.getMessage(RemoveFilterSettingsAction.class, "CTL_RemoveFilterSettingsAction");
     }
 
     public RemoveFilterSettingsAction() {
-        putValue(Action.SHORT_DESCRIPTION, "Remove filter profile");
+        putValue(Action.SHORT_DESCRIPTION, "Delete current filter profile");
     }
 
     @Override
@@ -52,6 +54,7 @@
         super.initialize();
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
@@ -63,6 +66,6 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/filterwindow/images/delete.gif";
+        return "com/sun/hotspot/igv/filterwindow/images/delete.png";
     }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/SaveFilterSettingsAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/SaveFilterSettingsAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -35,10 +35,12 @@
  */
 public final class SaveFilterSettingsAction extends CallableSystemAction {
 
+    @Override
     public void performAction() {
         FilterTopComponent.findInstance().addFilterSetting();
     }
 
+    @Override
     public String getName() {
         return NbBundle.getMessage(SaveFilterSettingsAction.class, "CTL_SaveFilterSettingsAction");
     }
@@ -49,9 +51,10 @@
     }
 
     public SaveFilterSettingsAction() {
-        putValue(Action.SHORT_DESCRIPTION, "Create new filter profile");
+        putValue(Action.SHORT_DESCRIPTION, "Save filter configuration as profile...");
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
@@ -63,6 +66,6 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/filterwindow/images/add.gif";
+        return "com/sun/hotspot/igv/filterwindow/images/add.png";
     }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/customRightTopWsmode.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/customRightTopWsmode.xml	Fri May 08 13:25:11 2015 -0400
@@ -4,8 +4,8 @@
     <kind type="view" />
     <state type="joined" />
     <constraints>
-        <path orientation="horizontal" number="45" weight="0.21761006289308177"/>
-        <path orientation="vertical" number="0" weight="0.2510122989593188"/>
+        <path orientation="horizontal" number="90" weight="0.2"/>
+        <path orientation="vertical" number="0" weight="0.75"/>
     </constraints>
     <bounds x="0" y="0" width="0" height="0" />
     <frame state="0"/>
Binary file hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/add.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/add.png has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/delete.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/delete.png has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/down.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/down.png has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/minus.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/minus.png has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/plus.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/plus.png has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/up.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/up.png has changed
--- a/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/layer.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/layer.xml	Fri May 08 13:25:11 2015 -0400
@@ -18,8 +18,11 @@
             <attr name="position" intvalue="900"/>
         </file>
     </folder>
-    <folder name="Window">
-        <file name="com-sun-hotspot-igv-coordinator-actions-FilterAction.instance"/>
+    
+    <folder name="Actions">
+        <folder name="Window">
+            <file name="com-sun-hotspot-igv-filterwindow-actions-FilterAction.instance"/>
+        </folder>
     </folder>
     <folder name="Menu">
         <folder name="Window">
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graal/build.xml	Fri May 08 13:25:11 2015 -0400
@@ -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.graal" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.graal.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graal/manifest.mf	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.graal
+OpenIDE-Module-Layer: com/sun/hotspot/igv/graal/layer.xml
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/graal/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graal/nbproject/build-impl.xml	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.graal-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
+    <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>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" 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="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
+        <condition>
+            <not>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graal/nbproject/genfiles.properties	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=92ea213f
+build.xml.script.CRC32=3534d355
+build.xml.stylesheet.CRC32=a56c6a5b@2.67.1
+# 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=92ea213f
+nbproject/build-impl.xml.script.CRC32=2867f2d5
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.67.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graal/nbproject/project.properties	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,2 @@
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graal/nbproject/project.xml	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,45 @@
+<?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.graal</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.filter</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.graph</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages/>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graal/nbproject/suite.properties	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/Bundle.properties	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=Graal Compiler Support
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalCFGFilter.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011, 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.graal.filters;
+
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.filter.AbstractFilter;
+import com.sun.hotspot.igv.graph.Connection;
+import com.sun.hotspot.igv.graph.Diagram;
+import com.sun.hotspot.igv.graph.Figure;
+import com.sun.hotspot.igv.graph.InputSlot;
+import com.sun.hotspot.igv.graph.OutputSlot;
+import java.util.HashSet;
+import java.util.Set;
+
+public class GraalCFGFilter extends AbstractFilter {
+
+    @Override
+    public String getName() {
+        return "Graal CFG Filter";
+    }
+
+    @Override
+    public void apply(Diagram d) {
+        Set<Connection> connectionsToRemove = new HashSet<>();
+
+        for (Figure f : d.getFigures()) {
+            Properties p = f.getProperties();
+            int predCount;
+            String predCountString = p.get("predecessorCount");
+            if (predCountString != null) {
+                predCount = Integer.parseInt(predCountString);
+            } else if (Boolean.parseBoolean(p.get("hasPredecessor"))) {
+                predCount = 1;
+            } else {
+                predCount = 0;
+            }
+            for (InputSlot is : f.getInputSlots()) {
+                if (is.getPosition() >= predCount && !"EndNode".equals(is.getProperties().get("class"))) {
+                    for (Connection c : is.getConnections()) {
+                        if (!"EndNode".equals(c.getOutputSlot().getFigure().getProperties().get("class"))) {
+                            connectionsToRemove.add(c);
+                        }
+                    }
+                }
+            }
+        }
+
+        for (Connection c : connectionsToRemove) {
+            c.remove();
+        }
+
+        Set<Figure> figuresToRemove = new HashSet<>();
+        next: for (Figure f : d.getFigures()) {
+            for (InputSlot is : f.getInputSlots()) {
+                if (!is.getConnections().isEmpty()) {
+                    continue next;
+                }
+            }
+            for (OutputSlot os : f.getOutputSlots()) {
+                if (!os.getConnections().isEmpty()) {
+                    continue next;
+                }
+            }
+            figuresToRemove.add(f);
+        }
+        d.removeAllFigures(figuresToRemove);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalColoringFilter.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2011, 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.graal.filters;
+
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.filter.AbstractFilter;
+import com.sun.hotspot.igv.graph.Diagram;
+import com.sun.hotspot.igv.graph.Figure;
+import java.awt.Color;
+import java.util.List;
+
+public class GraalColoringFilter extends AbstractFilter {
+
+    private String colorName;
+
+    public GraalColoringFilter(String colorName) {
+        this.colorName = colorName;
+    }
+
+    @Override
+    public String getName() {
+        return "Graal Coloring Filter (" + colorName + ")";
+    }
+
+    @Override
+    public void apply(Diagram d) {
+        List<Figure> figures = d.getFigures();
+        int colors = 0;
+        for (Figure f : figures) {
+            Properties p = f.getProperties();
+            final String prop = p.get(colorName + "Color");
+            if (prop == null) {
+                continue;
+            }
+            try {
+                int color = Integer.parseInt(prop);
+                if (color > colors) {
+                    colors = color;
+                }
+            } catch (NumberFormatException nfe) {
+                // nothing to do
+            }
+        }
+        colors++;
+        for (Figure f : figures) {
+            Properties p = f.getProperties();
+            final String prop = p.get(colorName + "Color");
+            if (prop == null) {
+                continue;
+            }
+            try {
+                int color = Integer.parseInt(prop);
+                Color c = Color.getHSBColor((float) color / colors, 1.0f, 0.7f);
+                f.setColor(c);
+            } catch (NumberFormatException nfe) {
+                // nothing to do
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2011, 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.graal.filters;
+
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.filter.AbstractFilter;
+import com.sun.hotspot.igv.graph.Connection;
+import com.sun.hotspot.igv.graph.Connection.ConnectionStyle;
+import com.sun.hotspot.igv.graph.Diagram;
+import com.sun.hotspot.igv.graph.Figure;
+import com.sun.hotspot.igv.graph.InputSlot;
+import java.awt.Color;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Filter that colors usage and successor edges differently.
+ *
+ * @author Peter Hofer
+ */
+public class GraalEdgeColorFilter extends AbstractFilter {
+
+    private final HashMap<String,Color> usageColor = new HashMap<>();
+    private Color otherUsageColor = Color.BLACK;
+
+    public GraalEdgeColorFilter() {
+    }
+
+    @Override
+    public String getName() {
+        return "Graal Edge Color Filter";
+    }
+
+    @Override
+    public void apply(Diagram d) {
+        List<Figure> figures = d.getFigures();
+        for (Figure f : figures) {
+            for (InputSlot is : f.getInputSlots()) {
+                for (Connection c : is.getConnections()) {
+                    String type = c.getType();
+                    if (type == "Association" && "EndNode".equals(c.getOutputSlot().getFigure().getProperties().get("class"))) {
+                        type = "Successor";
+                    }
+
+                    if (type != null) {
+                        Color typeColor = usageColor.get(type);
+                        if (typeColor == null) {
+                            c.setColor(otherUsageColor);
+                        } else {
+                            c.setColor(typeColor);
+                        }
+                        if (c.getStyle() != ConnectionStyle.DASHED && type == "Successor") {
+                            c.setStyle(ConnectionStyle.BOLD);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    public Color getUsageColor(String type) {
+        return usageColor.get(type);
+    }
+
+    public void setUsageColor(String type, Color usageColor) {
+        this.usageColor.put(type, usageColor);
+    }
+
+    public Color getOtherUsageColor() {
+        return otherUsageColor;
+    }
+
+    public void setOtherUsageColor(Color otherUsageColor) {
+        this.otherUsageColor = otherUsageColor;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/callgraph.filter	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,4 @@
+colorize("name", "<init>.*", yellow);
+colorize("name", "<clinit>.*", pink);
+colorize("leaf", "1", lightGray);
+colorize("cutoff", "1", red);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/color.filter	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,31 @@
+var red =  new java.awt.Color(240, 59, 32);
+var orange = new java.awt.Color(254, 178, 76);
+var yellow = new java.awt.Color(255, 237, 160);
+var middleBlue = new java.awt.Color(100, 147, 224);
+var lightGreen = new java.awt.Color(173, 221, 142);
+var lightBlue = new java.awt.Color(200, 200, 250);
+var gray = new java.awt.Color(220, 220, 220);
+var violet = new java.awt.Color(201, 148, 199);
+var black = new java.awt.Color(0, 0, 0);
+
+colorize("category", "controlSink", red);
+colorize("category", "controlSplit", red);
+colorize("category", "merge", red);
+colorize("category", "begin", orange);
+colorize("category", "end", orange);
+colorize("category", "fixed", yellow);
+colorize("category", "state", lightGreen);
+colorize("category", "phi", middleBlue);
+colorize("category", "proxy", middleBlue);
+colorize("category", "floating", lightBlue);
+colorize("class", "ConstantLocationNode", gray);
+colorize("class", "ParameterNode", gray);
+colorize("class", "ConstantNode", gray);
+colorize("class", "GuardNode", violet);
+colorize("class", "BlackholeNode", black);
+
+var f = new com.sun.hotspot.igv.graal.filters.GraalEdgeColorFilter();
+f.setUsageColor("Successor", red);
+f.setUsageColor("Value", blue);
+f.setUsageColor("Memory", new Color(0.0, 0.5, 0.0));
+f.apply(graph);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/probability.filter	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,3 @@
+colorizeGradientWithMode("probability", 0, 500, "logarithmic");
+
+// more parameters: colorizeGradientCustom("probability", 0, 500, "logarithmic", [blue, yellow, red], [0, 0.5, 1], 16);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/reduceEdges.filter	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,3 @@
+split("class", "ConstantLocationNode");
+split("class", "ParameterNode");
+split("class", "ConstantNode");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/removeFloating.filter	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,4 @@
+remove("category", "floating");
+remove("category", "state");
+remove("category", "phi");
+remove("category", "proxy");
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/removeState.filter	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,1 @@
+remove("category", "state");
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/stampColor.filter	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,16 @@
+var red =  new java.awt.Color(240, 59, 32);
+var orange = new java.awt.Color(254, 178, 76);
+var yellow = new java.awt.Color(255, 237, 160);
+var middleBlue = new java.awt.Color(100, 147, 224);
+var lightGreen = new java.awt.Color(173, 221, 142);
+var lightBlue = new java.awt.Color(200, 200, 250);
+var gray = new java.awt.Color(220, 220, 220);
+var violet = new java.awt.Color(201, 148, 199);
+
+colorize("stamp", ".*", white);
+colorize("stamp", "void", gray);
+colorize("stamp", "a.*", yellow);
+colorize("stamp", "a#.*", orange);
+colorize("stamp", "a!.*", red);
+colorize("stamp", "i.*", middleBlue);
+colorize("stamp", "f.*", lightGreen);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/layer.xml	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,34 @@
+<?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="Filters">
+        <file name="Coloring" url="filters/color.filter">
+            <attr name="enabled" boolvalue="true"/>
+        </file>
+        
+        
+        <file name="Stamp Coloring" url="filters/stampColor.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+      
+        <file name="Probability Coloring" url="filters/probability.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+        
+        <file name="Call Graph Coloring" url="filters/callgraph.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+        
+        <file name="Reduce Edges" url="filters/reduceEdges.filter">
+            <attr name="enabled" boolvalue="true"/>
+        </file>
+        
+        <file name="Remove State" url="filters/removeState.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+        
+        <file name="Remove Floating" url="filters/removeFloating.filter">
+            <attr name="enabled" boolvalue="false"/>
+        </file>
+    </folder>
+</filesystem>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/nbproject/project.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/nbproject/project.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/nbproject/project.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/nbproject/project.xml	Fri May 08 13:25:11 2015 -0400
@@ -25,6 +25,7 @@
             </module-dependencies>
             <public-packages>
                 <package>com.sun.hotspot.igv.graph</package>
+                <package>com.sun.hotspot.igv.graph.services</package>
             </public-packages>
         </data>
     </configuration>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/AndSelector.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/AndSelector.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -40,10 +40,11 @@
         this.selector2 = s2;
     }
 
+    @Override
     public List<Figure> selected(Diagram d) {
         List<Figure> l1 = selector1.selected(d);
         List<Figure> l2 = selector2.selected(d);
-        List<Figure> result = new ArrayList<Figure>();
+        List<Figure> result = new ArrayList<>();
         for (Figure f : l2) {
             if (l1.contains(f)) {
                 result.add(f);
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Block.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Block.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -60,14 +60,6 @@
         return succs;
     }
 
-    public Set<? extends Cluster> getPredecessors() {
-        Set<Block> succs = new HashSet<Block>();
-        for (InputBlock b : inputBlock.getPredecessors()) {
-            succs.add(diagram.getBlock(b));
-        }
-        return succs;
-    }
-
     public void setBounds(Rectangle r) {
         this.bounds = r;
     }
@@ -79,4 +71,10 @@
     public int compareTo(Cluster o) {
         return toString().compareTo(o.toString());
     }
+
+    @Override
+    public String toString() {
+        return inputBlock.getName();
+    }
 }
+
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Connection.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Connection.java	Fri May 08 13:25:11 2015 -0400
@@ -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.Source;
 import com.sun.hotspot.igv.layout.Link;
 import com.sun.hotspot.igv.layout.Port;
 import java.awt.Color;
@@ -36,6 +37,11 @@
  */
 public class Connection implements Source.Provider, Link {
 
+    @Override
+    public boolean isVIP() {
+        return style == ConnectionStyle.BOLD;
+    }
+
     public enum ConnectionStyle {
 
         NORMAL,
@@ -48,13 +54,17 @@
     private Color color;
     private ConnectionStyle style;
     private List<Point> controlPoints;
+    private String label;
+    private String type;
 
-    protected Connection(InputSlot inputSlot, OutputSlot outputSlot) {
+    protected Connection(InputSlot inputSlot, OutputSlot outputSlot, String label, String type) {
         this.inputSlot = inputSlot;
         this.outputSlot = outputSlot;
+        this.label = label;
+        this.type = type;
         this.inputSlot.connections.add(this);
         this.outputSlot.connections.add(this);
-        controlPoints = new ArrayList<Point>();
+        controlPoints = new ArrayList<>();
         Figure sourceFigure = this.outputSlot.getFigure();
         Figure destFigure = this.inputSlot.getFigure();
         sourceFigure.addSuccessor(destFigure);
@@ -89,10 +99,19 @@
         style = s;
     }
 
+    @Override
     public Source getSource() {
         return source;
     }
 
+    public String getLabel() {
+        return label;
+    }
+
+    public String getType() {
+        return type;
+    }
+
     public void remove() {
         inputSlot.getFigure().removePredecessor(outputSlot.getFigure());
         inputSlot.connections.remove(this);
@@ -100,24 +119,44 @@
         outputSlot.connections.remove(this);
     }
 
+    public String getToolTipText() {
+        StringBuilder builder = new StringBuilder();
+        if (label != null) {
+            builder.append(label).append(": ");
+        }
+        if (type != null) {
+            builder.append(type).append(" ");
+        }
+        builder.append("from ");
+        builder.append(getOutputSlot().getFigure().getSource().getSourceNodes().get(0).getId());
+        builder.append(" to ");
+        builder.append(getInputSlot().getFigure().getSource().getSourceNodes().get(0).getId());
+        return builder.toString();
+    }
+
     @Override
     public String toString() {
-        return "Connection(" + getFrom().getVertex() + " to " + getTo().getVertex() + ")";
+        return "Connection('" + label + "', " + getFrom().getVertex() + " to " + getTo().getVertex() + ")";
     }
 
+    @Override
     public Port getFrom() {
         return outputSlot;
     }
 
+    @Override
     public Port getTo() {
         return inputSlot;
     }
 
+    @Override
     public List<Point> getControlPoints() {
         return controlPoints;
     }
 
+    @Override
     public void setControlPoints(List<Point> list) {
         controlPoints = list;
     }
 }
+
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -28,17 +28,9 @@
 import com.sun.hotspot.igv.data.InputGraph;
 import com.sun.hotspot.igv.data.InputNode;
 import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.data.Properties.StringPropertyMatcher;
 import java.awt.Font;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 /**
  *
@@ -51,20 +43,33 @@
     private InputGraph graph;
     private int curId;
     private String nodeText;
-    private Font font;
+    private final Font font;
+    private final Font slotFont;
+    private final Font boldFont;
 
     public Font getFont() {
         return font;
     }
 
+    public Font getSlotFont() {
+        return slotFont;
+    }
+
+    public Font getBoldFont() {
+        return boldFont;
+    }
+
     private Diagram() {
-        figures = new ArrayList<Figure>();
-        blocks = new HashMap<InputBlock, Block>();
+        figures = new ArrayList<>();
+        blocks = new LinkedHashMap<>(8);
         this.nodeText = "";
-        this.font = new Font("Serif", Font.PLAIN, 14);
+        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);
     }
 
@@ -72,12 +77,7 @@
         return nodeText;
     }
 
-    public void schedule(Collection<InputBlock> newBlocks) {
-        graph.schedule(newBlocks);
-        updateBlocks();
-    }
-
-    private void updateBlocks() {
+    public void updateBlocks() {
         blocks.clear();
         for (InputBlock b : graph.getBlocks()) {
             Block curBlock = new Block(b, this);
@@ -108,10 +108,26 @@
         return f;
     }
 
-    public Connection createConnection(InputSlot inputSlot, OutputSlot outputSlot) {
+    public Connection createConnection(InputSlot inputSlot, OutputSlot outputSlot, String label, String type) {
         assert inputSlot.getFigure().getDiagram() == this;
         assert outputSlot.getFigure().getDiagram() == this;
-        return new Connection(inputSlot, outputSlot);
+        return new Connection(inputSlot, outputSlot, label, type);
+    }
+
+    public Map<InputNode, Set<Figure>> calcSourceToFigureRelation() {
+        Map<InputNode, Set<Figure>> map = new HashMap<>();
+
+        for(InputNode node : this.getGraph().getNodes()) {
+            map.put(node, new HashSet<Figure>());
+        }
+
+        for(Figure f : this.getFigures()) {
+            for(InputNode node : f.getSource().getSourceNodes()) {
+                map.get(node).add(f);
+            }
+        }
+
+        return map;
     }
 
     public static Diagram createDiagram(InputGraph graph, String nodeText) {
@@ -126,11 +142,12 @@
         d.updateBlocks();
 
         Collection<InputNode> nodes = graph.getNodes();
-        HashMap<Integer, Figure> figureHash = new HashMap<Integer, Figure>();
+        Hashtable<Integer, Figure> figureHash = new Hashtable<>();
         for (InputNode n : nodes) {
             Figure f = d.createFigure();
             f.getSource().addSourceNode(n);
             f.getProperties().add(n.getProperties());
+            f.setSubgraphs(n.getSubgraphs());
             figureHash.put(n.getId(), f);
         }
 
@@ -140,23 +157,23 @@
             int to = e.getTo();
             Figure fromFigure = figureHash.get(from);
             Figure toFigure = figureHash.get(to);
+
+            if(fromFigure == null || toFigure == null) continue;
             assert fromFigure != null && toFigure != null;
 
+            int fromIndex = e.getFromIndex();
+            while (fromFigure.getOutputSlots().size() <= fromIndex) {
+                fromFigure.createOutputSlot();
+            }
+            OutputSlot outputSlot = fromFigure.getOutputSlots().get(fromIndex);
+
             int toIndex = e.getToIndex();
-
-            while (fromFigure.getOutputSlots().size() <= 0) {
-                fromFigure.createOutputSlot();
-            }
-
-            OutputSlot outputSlot = fromFigure.getOutputSlots().get(0);
-
             while (toFigure.getInputSlots().size() <= toIndex) {
                 toFigure.createInputSlot();
             }
-
             InputSlot inputSlot = toFigure.getInputSlots().get(toIndex);
 
-            Connection c = d.createConnection(inputSlot, outputSlot);
+            Connection c = d.createConnection(inputSlot, outputSlot, e.getLabel(), e.getType());
 
             if (e.getState() == InputEdge.State.NEW) {
                 c.setStyle(Connection.ConnectionStyle.BOLD);
@@ -174,7 +191,7 @@
             freeFigure(f);
         }
 
-        ArrayList<Figure> newFigures = new ArrayList<Figure>();
+        ArrayList<Figure> newFigures = new ArrayList<>();
         for (Figure f : this.figures) {
             if (!figuresToRemove.contains(f)) {
                 newFigures.add(f);
@@ -185,12 +202,12 @@
 
     private void freeFigure(Figure succ) {
 
-        List<InputSlot> inputSlots = new ArrayList<InputSlot>(succ.getInputSlots());
+        List<InputSlot> inputSlots = new ArrayList<>(succ.getInputSlots());
         for (InputSlot s : inputSlots) {
             succ.removeInputSlot(s);
         }
 
-        List<OutputSlot> outputSlots = new ArrayList<OutputSlot>(succ.getOutputSlots());
+        List<OutputSlot> outputSlots = new ArrayList<>(succ.getOutputSlots());
         for (OutputSlot s : outputSlots) {
             succ.removeOutputSlot(s);
         }
@@ -219,7 +236,7 @@
 
     public Set<Connection> getConnections() {
 
-        Set<Connection> connections = new HashSet<Connection>();
+        Set<Connection> connections = new HashSet<>();
         for (Figure f : figures) {
 
             for (InputSlot s : f.getInputSlots()) {
@@ -231,10 +248,10 @@
     }
 
     public Figure getRootFigure() {
-        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<Figure>(figures);
-        Figure root = selector.selectSingle("name", "Root");
+        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(figures);
+        Figure root = selector.selectSingle(new StringPropertyMatcher("name", "Root"));
         if (root == null) {
-            root = selector.selectSingle("name", "Start");
+            root = selector.selectSingle(new StringPropertyMatcher("name", "Start"));
         }
         if (root == null) {
             List<Figure> rootFigures = getRootFigures();
@@ -258,9 +275,10 @@
         System.out.println("Number of figures: " + tmpFigures.size());
         System.out.println("Number of connections: " + connections.size());
 
-        List<Figure> figuresSorted = new ArrayList<Figure>(tmpFigures);
+        List<Figure> figuresSorted = new ArrayList<>(tmpFigures);
         Collections.sort(figuresSorted, new Comparator<Figure>() {
 
+            @Override
             public int compare(Figure a, Figure b) {
                 return b.getPredecessors().size() + b.getSuccessors().size() - a.getPredecessors().size() - a.getSuccessors().size();
             }
@@ -283,7 +301,7 @@
     }
 
     public List<Figure> getRootFigures() {
-        ArrayList<Figure> rootFigures = new ArrayList<Figure>();
+        ArrayList<Figure> rootFigures = new ArrayList<>();
         for (Figure f : figures) {
             if (f.getPredecessors().size() == 0) {
                 rootFigures.add(f);
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Figure.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Figure.java	Fri May 08 13:25:11 2015 -0400
@@ -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,30 +23,25 @@
  */
 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 com.sun.hotspot.igv.data.Properties;
-import java.awt.Color;
-import java.awt.Dimension;
-import java.awt.FontMetrics;
-import java.awt.Graphics;
-import java.awt.Point;
+import java.awt.*;
 import java.awt.image.BufferedImage;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
+import java.util.*;
 
-/**
- *
- * @author Thomas Wuerthinger
- */
 public class Figure extends Properties.Entity implements Source.Provider, Vertex {
 
-    public static final int INSET = 6;
-    public static final int SLOT_WIDTH = 10;
-    public static final int SLOT_START = 3;
+    public static final int INSET = 8;
+    public static int SLOT_WIDTH = 10;
+    public static final int OVERLAPPING = 6;
+    public static final int SLOT_START = 4;
+    public static final int SLOT_OFFSET = 8;
     public static final boolean VERTICAL_LAYOUT = true;
     protected List<InputSlot> inputSlots;
     protected List<OutputSlot> outputSlots;
@@ -55,6 +50,7 @@
     private Point position;
     private List<Figure> predecessors;
     private List<Figure> successors;
+    private List<InputGraph> subgraphs;
     private Color color;
     private int id;
     private String idString;
@@ -66,7 +62,7 @@
         if (heightCash == -1) {
             BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
             Graphics g = image.getGraphics();
-            g.setFont(diagram.getFont());
+            g.setFont(diagram.getFont().deriveFont(Font.BOLD));
             FontMetrics metrics = g.getFontMetrics();
             String nodeText = diagram.getNodeText();
             heightCash = nodeText.split("\n").length * metrics.getHeight() + INSET;
@@ -74,20 +70,41 @@
         return heightCash;
     }
 
+    public static <T> List<T> getAllBefore(List<T> inputList, T tIn) {
+        List<T> result = new ArrayList<>();
+        for(T t : inputList) {
+            if(t.equals(tIn)) {
+                break;
+            }
+            result.add(t);
+        }
+        return result;
+    }
+
+    public static int getSlotsWidth(Collection<? extends Slot> slots) {
+        int result = Figure.SLOT_OFFSET;
+        for(Slot s : slots) {
+            result += s.getWidth() + Figure.SLOT_OFFSET;
+        }
+        return result;
+    }
+
     public int getWidth() {
         if (widthCash == -1) {
             int max = 0;
             BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
             Graphics g = image.getGraphics();
-            g.setFont(diagram.getFont());
+            g.setFont(diagram.getFont().deriveFont(Font.BOLD));
             FontMetrics metrics = g.getFontMetrics();
-            for (String s : lines) {
+            for (String s : getLines()) {
                 int cur = metrics.stringWidth(s);
                 if (cur > max) {
                     max = cur;
                 }
             }
             widthCash = max + INSET;
+            widthCash = Math.max(widthCash, Figure.getSlotsWidth(inputSlots));
+            widthCash = Math.max(widthCash, Figure.getSlotsWidth(outputSlots));
         }
         return widthCash;
     }
@@ -95,10 +112,10 @@
     protected Figure(Diagram diagram, int id) {
         this.diagram = diagram;
         this.source = new Source();
-        inputSlots = new ArrayList<InputSlot>(5);
-        outputSlots = new ArrayList<OutputSlot>(1);
-        predecessors = new ArrayList<Figure>(6);
-        successors = new ArrayList<Figure>(6);
+        inputSlots = new ArrayList<>(5);
+        outputSlots = new ArrayList<>(1);
+        predecessors = new ArrayList<>(6);
+        successors = new ArrayList<>(6);
         this.id = id;
         idString = Integer.toString(id);
 
@@ -123,7 +140,7 @@
     }
 
     public Set<Figure> getPredecessorSet() {
-        Set<Figure> result = new HashSet<Figure>();
+        Set<Figure> result = new HashSet<>();
         for (Figure f : getPredecessors()) {
             result.add(f);
         }
@@ -131,7 +148,7 @@
     }
 
     public Set<Figure> getSuccessorSet() {
-        Set<Figure> result = new HashSet<Figure>();
+        Set<Figure> result = new HashSet<>();
         for (Figure f : getSuccessors()) {
             result.add(f);
         }
@@ -160,10 +177,20 @@
         successors.remove(f);
     }
 
+    public List<InputGraph> getSubgraphs() {
+        return subgraphs;
+    }
+
+    public void setSubgraphs(List<InputGraph> subgraphs) {
+        this.subgraphs = subgraphs;
+    }
+
+    @Override
     public void setPosition(Point p) {
         this.position = p;
     }
 
+    @Override
     public Point getPosition() {
         return position;
     }
@@ -172,6 +199,7 @@
         return diagram;
     }
 
+    @Override
     public Source getSource() {
         return source;
     }
@@ -193,7 +221,7 @@
 
         assert inputSlots.contains(s) || outputSlots.contains(s);
 
-        List<Connection> connections = new ArrayList<Connection>(s.getConnections());
+        List<Connection> connections = new ArrayList<>(s.getConnections());
         for (Connection c : connections) {
             c.remove();
         }
@@ -222,6 +250,13 @@
         return Collections.unmodifiableList(inputSlots);
     }
 
+    public Set<Slot> getSlots() {
+        Set<Slot> result = new HashSet<>();
+        result.addAll(getInputSlots());
+        result.addAll(getOutputSlots());
+        return result;
+    }
+
     public List<OutputSlot> getOutputSlots() {
         return Collections.unmodifiableList(outputSlots);
     }
@@ -248,13 +283,13 @@
         String[] result = new String[strings.length];
 
         for (int i = 0; i < strings.length; i++) {
-            result[i] = resolveString(strings[i]);
+            result[i] = resolveString(strings[i], getProperties());
         }
 
         lines = result;
     }
 
-    private String resolveString(String string) {
+    public static final String resolveString(String string, Properties properties) {
 
         StringBuilder sb = new StringBuilder();
         boolean inBrackets = false;
@@ -264,7 +299,7 @@
             char c = string.charAt(i);
             if (inBrackets) {
                 if (c == ']') {
-                    String value = getProperties().get(curIdent.toString());
+                    String value = properties.get(curIdent.toString());
                     if (value == null) {
                         value = "";
                     }
@@ -286,13 +321,16 @@
         return sb.toString();
     }
 
+    @Override
     public Dimension getSize() {
         if (VERTICAL_LAYOUT) {
             int width = Math.max(getWidth(), Figure.SLOT_WIDTH * (Math.max(inputSlots.size(), outputSlots.size()) + 1));
-            int height = getHeight() + 2 * Figure.SLOT_WIDTH;
+            int height = getHeight() + 2 * Figure.SLOT_WIDTH - 2 * Figure.OVERLAPPING;
+
+
             return new Dimension(width, height);
         } else {
-            int width = getWidth() + 2 * Figure.SLOT_WIDTH;
+            int width = getWidth() + 2 * Figure.SLOT_WIDTH - 2*Figure.OVERLAPPING;
             int height = Figure.SLOT_WIDTH * (Math.max(inputSlots.size(), outputSlots.size()) + 1);
             return new Dimension(width, height);
         }
@@ -308,21 +346,31 @@
             assert false : "Should never reach here, every figure must have at least one source node!";
             return null;
         } else {
-            Cluster result = diagram.getBlock(diagram.getGraph().getBlock(getSource().getSourceNodes().get(0)));
+            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() {
-        if (source.getSourceNodes().size() > 0 && source.getSourceNodes().get(0).getProperties().get("name").equals("Root")) {
-            return true;
+
+        List<InputNode> sourceNodes = source.getSourceNodes();
+        if (sourceNodes.size() > 0 && sourceNodes.get(0).getProperties().get("name") != null) {
+            return source.getSourceNodes().get(0).getProperties().get("name").equals("Root");
         } else {
             return false;
         }
     }
 
+    @Override
     public int compareTo(Vertex f) {
         return toString().compareTo(f.toString());
     }
+
+    public Rectangle getBounds() {
+        return new Rectangle(this.getPosition(), new Dimension(this.getWidth(), this.getHeight()));
+    }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/InputSlot.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/InputSlot.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -36,18 +36,24 @@
         super(figure, wantedIndex);
     }
 
+    @Override
     public int getPosition() {
         return getFigure().getInputSlots().indexOf(this);
     }
 
+    @Override
     public void setPosition(int position) {
         List<InputSlot> inputSlots = getFigure().inputSlots;
         InputSlot s = inputSlots.remove(position);
         inputSlots.add(position, s);
     }
-
+    @Override
     public Point getRelativePosition() {
-        return new Point(getFigure().getWidth() * (getPosition() + 1) / (getFigure().getInputSlots().size() + 1), Figure.SLOT_WIDTH - Figure.SLOT_START);
+        int gap = getFigure().getWidth() - Figure.getSlotsWidth(getFigure().getInputSlots());
+        double gapRatio = (double)gap / (double)(getFigure().getInputSlots().size() + 1);
+        int gapAmount = (int)((getPosition() + 1)*gapRatio);
+        return new Point(gapAmount + Figure.getSlotsWidth(Figure.getAllBefore(getFigure().getInputSlots(), this)) + getWidth()/2, -Figure.SLOT_START);
+        //return new Point((getFigure().getWidth() / (getFigure().getInputSlots().size() * 2)) * (getPosition() * 2 + 1), -Figure.SLOT_START);
     }
 
     @Override
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/InvertSelector.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/InvertSelector.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -38,9 +38,10 @@
         this.selector = selector;
     }
 
+    @Override
     public List<Figure> selected(Diagram d) {
 
-        List<Figure> result = new ArrayList<Figure>();
+        List<Figure> result = new ArrayList<>();
         List<Figure> otherResult = selector.selected(d);
         for (Figure f : d.getFigures()) {
             if (!otherResult.contains(f)) {
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/MatcherSelector.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/MatcherSelector.java	Fri May 08 13:25:11 2015 -0400
@@ -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,8 +39,9 @@
         this.matcher = matcher;
     }
 
+    @Override
     public List<Figure> selected(Diagram d) {
-        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<Figure>(d.getFigures());
+        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(d.getFigures());
         List<Figure> list = selector.selectMultiple(matcher);
         return list;
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/OrSelector.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/OrSelector.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -40,6 +40,7 @@
         this.selector2 = s2;
     }
 
+    @Override
     public List<Figure> selected(Diagram d) {
 
         List<Figure> l1 = selector1.selected(d);
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/OutputSlot.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/OutputSlot.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -35,17 +35,26 @@
         super(figure, wantedIndex);
     }
 
+    @Override
     public int getPosition() {
         return getFigure().getOutputSlots().indexOf(this);
     }
 
+    @Override
     public void setPosition(int position) {
         OutputSlot s = getFigure().outputSlots.remove(position);
         getFigure().outputSlots.add(position, s);
     }
 
+    @Override
     public Point getRelativePosition() {
-        return new Point(getFigure().getWidth() * (getPosition() + 1) / (getFigure().getOutputSlots().size() + 1), getFigure().getSize().height - Figure.SLOT_WIDTH + Figure.SLOT_START);
+        int gap = getFigure().getWidth() - Figure.getSlotsWidth(getFigure().getOutputSlots());
+        if(gap < 0) {
+            gap = 0;
+        }
+        double gapRatio = (double)gap / (double)(getFigure().getOutputSlots().size() + 1);
+        int gapAmount = (int)((getPosition() + 1)*gapRatio);
+        return new Point(gapAmount + Figure.getSlotsWidth(Figure.getAllBefore(getFigure().getOutputSlots(), this)) + getWidth()/2, Figure.SLOT_START);
     }
 
     @Override
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/PredecessorSelector.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/PredecessorSelector.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -38,9 +38,10 @@
         this.innerSelector = innerSelector;
     }
 
+    @Override
     public List<Figure> selected(Diagram d) {
         List<Figure> inner = innerSelector.selected(d);
-        List<Figure> result = new ArrayList<Figure>();
+        List<Figure> result = new ArrayList<>();
         for (Figure f : d.getFigures()) {
             boolean saved = false;
             for (Figure f2 : f.getSuccessors()) {
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Selector.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Selector.java	Fri May 08 13:25:11 2015 -0400
@@ -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
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Slot.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Slot.java	Fri May 08 13:25:11 2015 -0400
@@ -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,63 +23,111 @@
  */
 package com.sun.hotspot.igv.graph;
 
+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.Port;
 import com.sun.hotspot.igv.layout.Vertex;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
-import java.util.Comparator;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
-public abstract class Slot implements Port, Source.Provider {
+public abstract class Slot implements Port, Source.Provider, Properties.Provider {
 
     private int wantedIndex;
-    private String name;
-    private String shortName; // 1 - 2 characters
     private Source source;
     protected List<Connection> connections;
+    private InputNode associatedNode;
+    private Color color;
+    private String text;
+    private String shortName;
     private Figure figure;
 
     protected Slot(Figure figure, int wantedIndex) {
         this.figure = figure;
-        connections = new ArrayList<Connection>(2);
+        connections = new ArrayList<>(2);
         source = new Source();
         this.wantedIndex = wantedIndex;
-        name = "";
+        text = "";
         shortName = "";
         assert figure != null;
     }
+
+    @Override
+    public Properties getProperties() {
+        Properties p = new Properties();
+        if (source.getSourceNodes().size() > 0) {
+            for (InputNode n : source.getSourceNodes()) {
+                p.add(n.getProperties());
+            }
+        } else {
+            p.setProperty("name", "Slot");
+            p.setProperty("figure", figure.getProperties().get("name"));
+            p.setProperty("connectionCount", Integer.toString(connections.size()));
+        }
+        return p;
+    }
     public static final Comparator<Slot> slotIndexComparator = new Comparator<Slot>() {
 
+        @Override
         public int compare(Slot o1, Slot o2) {
             return o1.wantedIndex - o2.wantedIndex;
         }
     };
     public static final Comparator<Slot> slotFigureComparator = new Comparator<Slot>() {
 
+        @Override
         public int compare(Slot o1, Slot o2) {
             return o1.figure.getId() - o2.figure.getId();
         }
     };
 
+    public InputNode getAssociatedNode() {
+        return associatedNode;
+    }
+
+    public void setAssociatedNode(InputNode node) {
+        associatedNode = node;
+    }
+
+    public int getWidth() {
+        if (shortName == null || shortName.length() <= 1) {
+            return Figure.SLOT_WIDTH;
+        } else {
+            BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
+            Graphics g = image.getGraphics();
+            g.setFont(figure.getDiagram().getSlotFont().deriveFont(Font.BOLD));
+            FontMetrics metrics = g.getFontMetrics();
+            return Math.max(Figure.SLOT_WIDTH, metrics.stringWidth(shortName) + 6);
+        }
+    }
+
     public int getWantedIndex() {
         return wantedIndex;
     }
 
+    @Override
     public Source getSource() {
         return source;
     }
 
-    public String getName() {
-        return name;
+    public String getText() {
+        return text;
     }
 
     public void setShortName(String s) {
         assert s != null;
-        assert s.length() <= 2;
+//        assert s.length() <= 2;
         this.shortName = s;
 
     }
@@ -88,15 +136,27 @@
         return shortName;
     }
 
-    public boolean getShowName() {
+    public String getToolTipText() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(text);
+
+        for (InputNode n : getSource().getSourceNodes()) {
+            sb.append("Node (ID=" + n.getId() + "): " + n.getProperties().get("name"));
+            sb.append("<br>");
+        }
+
+        return sb.toString();
+    }
+
+    public boolean shouldShowName() {
         return getShortName() != null && getShortName().length() > 0;
     }
 
-    public void setName(String s) {
+    public void setText(String s) {
         if (s == null) {
             s = "";
         }
-        this.name = s;
+        this.text = s;
     }
 
     public Figure getFigure() {
@@ -104,17 +164,26 @@
         return figure;
     }
 
+    public Color getColor() {
+        return this.color;
+    }
+
+    public void setColor(Color c) {
+        color = c;
+    }
+
     public List<Connection> getConnections() {
         return Collections.unmodifiableList(connections);
     }
 
     public void removeAllConnections() {
-        List<Connection> connectionsCopy = new ArrayList<Connection>(this.connections);
+        List<Connection> connectionsCopy = new ArrayList<>(this.connections);
         for (Connection c : connectionsCopy) {
             c.remove();
         }
     }
 
+    @Override
     public Vertex getVertex() {
         return figure;
     }
@@ -123,3 +192,4 @@
 
     public abstract void setPosition(int position);
 }
+
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Source.java	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/*
- * 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.data.InputGraph;
-import com.sun.hotspot.igv.data.InputNode;
-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 Source {
-
-    private List<InputNode> sourceNodes;
-    private Set<Integer> set;
-
-    public Source() {
-        sourceNodes = new ArrayList<InputNode>(1);
-    }
-
-    public List<InputNode> getSourceNodes() {
-        return Collections.unmodifiableList(sourceNodes);
-    }
-
-    public Set<Integer> getSourceNodesAsSet() {
-        if (set == null) {
-            set = new HashSet<Integer>();
-            for (InputNode n : sourceNodes) {
-                int id = n.getId();
-                //if(id < 0) id = -id;
-                set.add(id);
-            }
-        }
-        return set;
-    }
-
-    public void addSourceNode(InputNode n) {
-        sourceNodes.add(n);
-        set = null;
-    }
-
-    public void removeSourceNode(InputNode n) {
-        sourceNodes.remove(n);
-        set = null;
-    }
-
-    public interface Provider {
-
-        public Source getSource();
-    }
-
-    public void setSourceNodes(List<InputNode> sourceNodes) {
-        this.sourceNodes = sourceNodes;
-        set = null;
-    }
-
-    public void addSourceNodes(Source s) {
-        for (InputNode n : s.getSourceNodes()) {
-            sourceNodes.add(n);
-        }
-        set = null;
-    }
-
-    public boolean isInBlock(InputGraph g, InputBlock blockNode) {
-
-        for (InputNode n : this.getSourceNodes()) {
-            if (g.getBlock(n) == blockNode) {
-                return true;
-            }
-        }
-        return false;
-    }
-}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/SuccessorSelector.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/SuccessorSelector.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -38,9 +38,10 @@
         this.innerSelector = innerSelector;
     }
 
+    @Override
     public List<Figure> selected(Diagram d) {
         List<Figure> inner = innerSelector.selected(d);
-        List<Figure> result = new ArrayList<Figure>();
+        List<Figure> result = new ArrayList<>();
         for (Figure f : d.getFigures()) {
             boolean saved = false;
             for (Figure f2 : f.getPredecessors()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/services/DiagramProvider.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,38 @@
+/*
+ * 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.graph.services;
+
+import com.sun.hotspot.igv.data.ChangedEvent;
+import com.sun.hotspot.igv.graph.Diagram;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public interface DiagramProvider {
+    Diagram getDiagram();
+    ChangedEvent<DiagramProvider> getChangedEvent();
+
+}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/nbproject/project.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/nbproject/project.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterEdge.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterEdge.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -60,4 +60,8 @@
     public List<Point> getControlPoints() {
         return points;
     }
+
+    public boolean isVIP() {
+        return false;
+    }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterIngoingConnection.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterIngoingConnection.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -73,4 +73,8 @@
     public List<Point> getControlPoints() {
         return controlPoints;
     }
+
+    public boolean isVIP() {
+        return false;
+    }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterInputSlotNode.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterInputSlotNode.java	Fri May 08 13:25:11 2015 -0400
@@ -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
--- a/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterNode.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterNode.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -93,7 +93,7 @@
         outputSlot = new Port() {
 
             public Point getRelativePosition() {
-                return new Point(size.width / 2, size.height);
+                return new Point(size.width / 2, 0);//size.height);
             }
 
             public Vertex getVertex() {
@@ -183,7 +183,7 @@
 
         for (Link e : subEdges) {
             List<Point> arr = e.getControlPoints();
-            ArrayList<Point> newArr = new ArrayList<Point>();
+            ArrayList<Point> newArr = new ArrayList<Point>(arr.size());
             for (Point p : arr) {
                 if (p != null) {
                     Point p2 = new Point(p);
--- a/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterOutgoingConnection.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterOutgoingConnection.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -65,4 +65,8 @@
     public List<Point> getControlPoints() {
         return intermediatePoints;
     }
+
+    public boolean isVIP() {
+        return false;
+    }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterOutputSlotNode.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/ClusterOutputSlotNode.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -88,7 +88,7 @@
             public Point getRelativePosition() {
                 Point p = new Point(thisNode.getPosition());
                 p.x += ClusterNode.BORDER;
-                p.y = thisBlockNode.getSize().height;
+                p.y = 0;//thisBlockNode.getSize().height;
                 return p;
             }
 
--- a/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Edge.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Edge.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -83,6 +83,7 @@
         dest.addInEdge(this);
     }
 
+    @Override
     public String toString() {
         return "Edge (" + source + " -- " + dest + "): " + data;
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Graph.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Graph.java	Fri May 08 13:25:11 2015 -0400
@@ -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,13 +23,7 @@
  */
 package com.sun.hotspot.igv.hierarchicallayout;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Queue;
+import java.util.*;
 
 /**
  *
@@ -42,13 +36,13 @@
     private List<Node<N, E>> nodeList;
 
     public Graph() {
-        nodes = new HashMap<Object, Node<N, E>>();
-        edges = new HashMap<Object, Edge<N, E>>();
-        nodeList = new ArrayList<Node<N, E>>();
+        nodes = new HashMap<>();
+        edges = new HashMap<>();
+        nodeList = new ArrayList<>();
     }
 
     public Node<N, E> createNode(N data, Object key) {
-        Node<N, E> n = new Node<N, E>(this, data);
+        Node<N, E> n = new Node<>(this, data);
         assert key == null || !nodes.containsKey(key);
         if (key != null) {
             nodes.put(key, n);
@@ -58,7 +52,7 @@
     }
 
     public Edge<N, E> createEdge(Node<N, E> source, Node<N, E> dest, E data, Object key) {
-        Edge<N, E> e = new Edge<N, E>(this, source, dest, data);
+        Edge<N, E> e = new Edge<>(this, source, dest, data);
         source.addOutEdge(e);
         dest.addInEdge(e);
         if (key != null) {
@@ -114,7 +108,7 @@
 
     public List<Node<N, E>> getNodesWithInDegree(int x, boolean countSelfLoops) {
 
-        List<Node<N, E>> result = new ArrayList<Node<N, E>>();
+        List<Node<N, E>> result = new ArrayList<>();
         for (Node<N, E> n : getNodes()) {
             if (n.getInDegree(countSelfLoops) == x) {
                 result.add(n);
@@ -126,7 +120,7 @@
     }
 
     private void markReachable(Node<N, E> startingNode) {
-        ArrayList<Node<N, E>> arr = new ArrayList<Node<N, E>>();
+        ArrayList<Node<N, E>> arr = new ArrayList<>();
         arr.add(startingNode);
         for (Node<N, E> n : getNodes()) {
             n.setReachable(false);
@@ -151,7 +145,7 @@
             n.setActive(false);
         }
 
-        Queue<Node<N, E>> queue = new LinkedList<Node<N, E>>();
+        Queue<Node<N, E>> queue = new LinkedList<>();
         queue.add(startingNode);
         startingNode.setVisited(true);
         int layer = 0;
--- a/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalClusterLayoutManager.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalClusterLayoutManager.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -44,12 +44,12 @@
  */
 public class HierarchicalClusterLayoutManager implements LayoutManager {
 
-    private OldHierarchicalLayoutManager.Combine combine;
-    private LayoutManager subManager = new OldHierarchicalLayoutManager(combine);
-    private LayoutManager manager = new OldHierarchicalLayoutManager(combine, 150);
+    private HierarchicalLayoutManager.Combine combine;
+    private LayoutManager subManager = new HierarchicalLayoutManager(combine);
+    private LayoutManager manager = new HierarchicalLayoutManager(combine);
     private static final boolean TRACE = false;
 
-    public HierarchicalClusterLayoutManager(OldHierarchicalLayoutManager.Combine combine) {
+    public HierarchicalClusterLayoutManager(HierarchicalLayoutManager.Combine combine) {
         this.combine = combine;
     }
 
@@ -57,6 +57,10 @@
         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;
     }
@@ -116,7 +120,7 @@
 
         for (Vertex v : graph.getVertices()) {
             Cluster c = v.getCluster();
-            assert c != null;
+            assert c != null : "Cluster of vertex " + v + " is null!";
             clusterNodes.get(c).addSubNode(v);
         }
 
@@ -130,9 +134,9 @@
             Cluster toCluster = toVertex.getCluster();
 
             Port samePort = null;
-            if (combine == OldHierarchicalLayoutManager.Combine.SAME_INPUTS) {
+            if (combine == HierarchicalLayoutManager.Combine.SAME_INPUTS) {
                 samePort = toPort;
-            } else if (combine == OldHierarchicalLayoutManager.Combine.SAME_OUTPUTS) {
+            } else if (combine == HierarchicalLayoutManager.Combine.SAME_OUTPUTS) {
                 samePort = fromPort;
             }
 
@@ -196,7 +200,7 @@
 
         for (Cluster c : cluster) {
             ClusterNode n = clusterNodes.get(c);
-            subManager.doLayout(new LayoutGraph(n.getSubEdges(), n.getSubNodes()), clusterInputSlotSet.get(c), clusterOutputSlotSet.get(c), new HashSet<Link>());
+            subManager.doLayout(new LayoutGraph(n.getSubEdges(), n.getSubNodes()), new HashSet<Link>());
             n.updateSize();
         }
 
@@ -206,7 +210,7 @@
             ((ClusterNode) v).setRoot(true);
         }
 
-        manager.doLayout(new LayoutGraph(clusterEdges, clusterNodeSet), new HashSet<Vertex>(), new HashSet<Vertex>(), interClusterEdges);
+        manager.doLayout(new LayoutGraph(clusterEdges, clusterNodeSet), interClusterEdges);
 
         for (Cluster c : cluster) {
             ClusterNode n = clusterNodes.get(c);
--- a/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalLayoutManager.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalLayoutManager.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -29,18 +29,7 @@
 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.Comparator;
-import java.util.HashSet;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Queue;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.Stack;
-import java.util.TreeSet;
+import java.util.*;
 
 /**
  *
@@ -54,10 +43,11 @@
     public static final int CROSSING_ITERATIONS = 2;
     public static final int DUMMY_HEIGHT = 1;
     public static final int DUMMY_WIDTH = 1;
-    public static final int X_OFFSET = 9;
-    public static final int LAYER_OFFSET = 30;
+    public static final int X_OFFSET = 8;
+    public static final int LAYER_OFFSET = 8;
     public static final int MAX_LAYER_LENGTH = -1;
     public static final int MIN_LAYER_DIFFERENCE = 1;
+    public static final int VIP_BONUS = 10;
 
     public enum Combine {
 
@@ -85,8 +75,6 @@
     private LayoutGraph graph;
     private List<LayoutNode>[] layers;
     private int layerCount;
-    private Set<? extends Vertex> firstLayerHint;
-    private Set<? extends Vertex> lastLayerHint;
     private Set<? extends Link> importantLinks;
     private Set<Link> linksToFollow;
 
@@ -101,11 +89,13 @@
         public int yOffset;
         public int bottomYOffset;
         public Vertex vertex; // Only used for non-dummy nodes, otherwise null
-        public List<LayoutEdge> preds = new ArrayList<LayoutEdge>();
-        public List<LayoutEdge> succs = new ArrayList<LayoutEdge>();
-        public HashMap<Integer, Integer> outOffsets = new HashMap<Integer, Integer>();
-        public HashMap<Integer, Integer> inOffsets = new HashMap<Integer, Integer>();
+
+        public List<LayoutEdge> preds = new ArrayList<>();
+        public List<LayoutEdge> succs = new ArrayList<>();
+        public HashMap<Integer, Integer> outOffsets = new HashMap<>();
+        public HashMap<Integer, Integer> inOffsets = new HashMap<>();
         public int pos = -1; // Position within layer
+
         public int crossingNumber;
 
         @Override
@@ -121,6 +111,7 @@
         public int relativeFrom;
         public int relativeTo;
         public Link link;
+        public boolean vip;
     }
 
     private abstract class AlgorithmPart {
@@ -171,7 +162,7 @@
         this.layerOffset = LAYER_OFFSET;
         this.maxLayerLength = MAX_LAYER_LENGTH;
         this.minLayerDifference = MIN_LAYER_DIFFERENCE;
-        this.linksToFollow = new HashSet<Link>();
+        this.linksToFollow = new HashSet<>();
     }
 
     public int getMaxLayerLength() {
@@ -186,26 +177,26 @@
         minLayerDifference = v;
     }
 
+    @Override
     public void doLayout(LayoutGraph graph) {
-        doLayout(graph, new HashSet<Vertex>(), new HashSet<Vertex>(), new HashSet<Link>());
+        doLayout(graph, new HashSet<Link>());
 
     }
 
-    public void doLayout(LayoutGraph graph, Set<? extends Vertex> firstLayerHint, Set<? extends Vertex> lastLayerHint, Set<? extends Link> importantLinks) {
+    @Override
+    public void doLayout(LayoutGraph graph, Set<? extends Link> importantLinks) {
 
         this.importantLinks = importantLinks;
         this.graph = graph;
-        this.firstLayerHint = firstLayerHint;
-        this.lastLayerHint = lastLayerHint;
 
-        vertexToLayoutNode = new HashMap<Vertex, LayoutNode>();
-        reversedLinks = new HashSet<Link>();
-        reversedLinkStartPoints = new HashMap<Link, List<Point>>();
-        reversedLinkEndPoints = new HashMap<Link, List<Point>>();
-        bottomEdgeHash = new HashMap<LayoutEdge, LayoutEdge>();
-        nodes = new ArrayList<LayoutNode>();
-        splitStartPoints = new HashMap<Link, List<Point>>();
-        splitEndPoints = new HashMap<Link, List<Point>>();
+        vertexToLayoutNode = new HashMap<>();
+        reversedLinks = new HashSet<>();
+        reversedLinkStartPoints = new HashMap<>();
+        reversedLinkEndPoints = new HashMap<>();
+        bottomEdgeHash = new HashMap<>();
+        nodes = new ArrayList<>();
+        splitStartPoints = new HashMap<>();
+        splitEndPoints = new HashMap<>();
 
         // #############################################################
         // Step 1: Build up data structure
@@ -216,7 +207,7 @@
         new ReverseEdges().start();
 
         for (LayoutNode n : nodes) {
-            ArrayList<LayoutEdge> tmpArr = new ArrayList<LayoutEdge>();
+            ArrayList<LayoutEdge> tmpArr = new ArrayList<>();
             for (LayoutEdge e : n.succs) {
                 if (importantLinks.contains(e.link)) {
                     tmpArr.add(e);
@@ -224,7 +215,6 @@
             }
 
             for (LayoutEdge e : tmpArr) {
-                //System.out.println("Removed " + e);
                 e.from.succs.remove(e);
                 e.to.preds.remove(e);
             }
@@ -244,8 +234,7 @@
 
         // #############################################################
         // STEP 7: Assign X coordinates
-        //new AssignXCoordinates().start();
-        new AssignXCoordinates2().start();
+        new AssignXCoordinates().start();
 
         // #############################################################
         // STEP 6: Assign Y coordinates
@@ -260,10 +249,11 @@
 
         private int pointCount;
 
+        @Override
         protected void run() {
 
-            HashMap<Vertex, Point> vertexPositions = new HashMap<Vertex, Point>();
-            HashMap<Link, List<Point>> linkPositions = new HashMap<Link, List<Point>>();
+            HashMap<Vertex, Point> vertexPositions = new HashMap<>();
+            HashMap<Link, List<Point>> linkPositions = new HashMap<>();
             for (Vertex v : graph.getVertices()) {
                 LayoutNode n = vertexToLayoutNode.get(v);
                 assert !vertexPositions.containsKey(v);
@@ -274,12 +264,12 @@
 
                 for (LayoutEdge e : n.preds) {
                     if (e.link != null) {
-                        ArrayList<Point> points = new ArrayList<Point>();
+                        ArrayList<Point> points = new ArrayList<>();
 
-                        Point p = new Point(e.to.x + e.relativeTo, e.to.y + e.to.yOffset);
+                        Point p = new Point(e.to.x + e.relativeTo, e.to.y + e.to.yOffset + e.link.getTo().getRelativePosition().y);
                         points.add(p);
                         if (e.to.inOffsets.containsKey(e.relativeTo)) {
-                            points.add(new Point(p.x, p.y + e.to.inOffsets.get(e.relativeTo)));
+                            points.add(new Point(p.x, p.y + e.to.inOffsets.get(e.relativeTo) + e.link.getTo().getRelativePosition().y));
                         }
 
                         LayoutNode cur = e.from;
@@ -299,16 +289,14 @@
                             cur = curEdge.from;
                         }
 
-                        p = new Point(cur.x + curEdge.relativeFrom, cur.y + cur.height - cur.bottomYOffset);
+                        p = new Point(cur.x + curEdge.relativeFrom, cur.y + cur.height - cur.bottomYOffset + (curEdge.link == null ? 0 : curEdge.link.getFrom().getRelativePosition().y));
                         if (curEdge.from.outOffsets.containsKey(curEdge.relativeFrom)) {
-                            points.add(new Point(p.x, p.y + curEdge.from.outOffsets.get(curEdge.relativeFrom)));
+                            points.add(new Point(p.x, p.y + curEdge.from.outOffsets.get(curEdge.relativeFrom) + (curEdge.link == null ? 0 : curEdge.link.getFrom().getRelativePosition().y)));
                         }
                         points.add(p);
 
                         Collections.reverse(points);
 
-
-
                         if (cur.vertex == null && cur.preds.size() == 0) {
 
                             if (reversedLinkEndPoints.containsKey(e.link)) {
@@ -359,17 +347,17 @@
 
                 for (LayoutEdge e : n.succs) {
                     if (e.link != null) {
-                        ArrayList<Point> points = new ArrayList<Point>();
-                        Point p = new Point(e.from.x + e.relativeFrom, e.from.y + e.from.height - e.from.bottomYOffset);
+                        ArrayList<Point> points = new ArrayList<>();
+                        Point p = new Point(e.from.x + e.relativeFrom, e.from.y + e.from.height - e.from.bottomYOffset + e.link.getFrom().getRelativePosition().y);
                         points.add(p);
                         if (e.from.outOffsets.containsKey(e.relativeFrom)) {
-                            points.add(new Point(p.x, p.y + e.from.outOffsets.get(e.relativeFrom)));
+                            points.add(new Point(p.x, p.y + e.from.outOffsets.get(e.relativeFrom) + e.link.getFrom().getRelativePosition().y));
                         }
 
                         LayoutNode cur = e.to;
                         LayoutNode other = e.from;
                         LayoutEdge curEdge = e;
-                        while (cur.vertex == null && cur.succs.size() != 0) {
+                        while (cur.vertex == null && !cur.succs.isEmpty()) {
                             if (points.size() > 1 && points.get(points.size() - 1).x == cur.x + cur.width / 2 && points.get(points.size() - 2).x == cur.x + cur.width / 2) {
                                 points.remove(points.size() - 1);
                             }
@@ -378,7 +366,7 @@
                                 points.remove(points.size() - 1);
                             }
                             points.add(new Point(cur.x + cur.width / 2, cur.y + cur.height));
-                            if (cur.succs.size() == 0) {
+                            if (cur.succs.isEmpty()) {
                                 break;
                             }
                             assert cur.succs.size() == 1;
@@ -386,15 +374,13 @@
                             cur = curEdge.to;
                         }
 
-
-                        p = new Point(cur.x + curEdge.relativeTo, cur.y + cur.yOffset);
+                        p = new Point(cur.x + curEdge.relativeTo, cur.y + cur.yOffset + ((curEdge.link == null) ? 0 : curEdge.link.getTo().getRelativePosition().y));
                         points.add(p);
                         if (curEdge.to.inOffsets.containsKey(curEdge.relativeTo)) {
-                            points.add(new Point(p.x, p.y + curEdge.to.inOffsets.get(curEdge.relativeTo)));
+                            points.add(new Point(p.x, p.y + curEdge.to.inOffsets.get(curEdge.relativeTo) + ((curEdge.link == null) ? 0 : curEdge.link.getTo().getRelativePosition().y)));
                         }
 
-
-                        if (cur.succs.size() == 0 && cur.vertex == null) {
+                        if (cur.succs.isEmpty() && cur.vertex == null) {
                             if (reversedLinkStartPoints.containsKey(e.link)) {
                                 for (Point p1 : reversedLinkStartPoints.get(e.link)) {
                                     points.add(0, new Point(p1.x + other.x, p1.y + other.y));
@@ -495,13 +481,14 @@
 
         public float d;
         public int orderNumber = -1;
-        public ArrayList<LayoutNode> nodes = new ArrayList<LayoutNode>();
-        public HashSet<Segment> succs = new HashSet<Segment>();
-        public HashSet<Segment> preds = new HashSet<Segment>();
+        public ArrayList<LayoutNode> nodes = new ArrayList<>();
+        public HashSet<Segment> succs = new HashSet<>();
+        public HashSet<Segment> preds = new HashSet<>();
         public Region region;
     }
     private static final Comparator<Segment> segmentComparator = new Comparator<Segment>() {
 
+        @Override
         public int compare(Segment s1, Segment s2) {
             return s1.orderNumber - s2.orderNumber;
         }
@@ -511,26 +498,46 @@
 
         public float d;
         public int minOrderNumber;
-        public SortedSet<Segment> segments = new TreeSet<Segment>(segmentComparator);
-        public HashSet<Region> succs = new HashSet<Region>(4);
-        public HashSet<Region> preds = new HashSet<Region>(4);
+        public SortedSet<Segment> segments = new TreeSet<>(segmentComparator);
+        public HashSet<Region> succs = new HashSet<>(4);
+        public HashSet<Region> preds = new HashSet<>(4);
     }
     private static final Comparator<Region> regionComparator = new Comparator<Region>() {
 
+        @Override
         public int compare(Region r1, Region r2) {
             return r1.minOrderNumber - r2.minOrderNumber;
         }
     };
     private static final Comparator<LayoutNode> nodePositionComparator = new Comparator<LayoutNode>() {
 
+        @Override
         public int compare(LayoutNode n1, LayoutNode n2) {
             return n1.pos - n2.pos;
         }
     };
     private static final Comparator<LayoutNode> nodeProcessingDownComparator = new Comparator<LayoutNode>() {
-
+        @Override
         public int compare(LayoutNode n1, LayoutNode n2) {
+            int n1VIP = 0;
+            for (LayoutEdge e : n1.preds) {
+                if (e.vip) {
+                    n1VIP++;
+                }
+            }
+            int n2VIP = 0;
+            for (LayoutEdge e : n2.preds) {
+                if (e.vip) {
+                    n2VIP++;
+                }
+            }
+            if (n1VIP != n2VIP) {
+                return n2VIP - n1VIP;
+            }
             if (n1.vertex == null) {
+                if (n2.vertex == null) {
+                    return 0;
+                }
                 return -1;
             }
             if (n2.vertex == null) {
@@ -541,8 +548,27 @@
     };
     private static final Comparator<LayoutNode> nodeProcessingUpComparator = new Comparator<LayoutNode>() {
 
+        @Override
         public int compare(LayoutNode n1, LayoutNode n2) {
+            int n1VIP = 0;
+            for (LayoutEdge e : n1.succs) {
+                if (e.vip) {
+                    n1VIP++;
+                }
+            }
+            int n2VIP = 0;
+            for (LayoutEdge e : n2.succs) {
+                if (e.vip) {
+                    n2VIP++;
+                }
+            }
+            if (n1VIP != n2VIP) {
+                return n2VIP - n1VIP;
+            }
             if (n1.vertex == null) {
+                if (n2.vertex == null) {
+                    return 0;
+                }
                 return -1;
             }
             if (n2.vertex == null) {
@@ -552,7 +578,7 @@
         }
     };
 
-    private class AssignXCoordinates2 extends AlgorithmPart {
+    private class AssignXCoordinates extends AlgorithmPart {
 
         private ArrayList<Integer>[] space;
         private ArrayList<LayoutNode>[] downProcessingOrder;
@@ -564,16 +590,21 @@
             }
         }
 
-        protected void run() {
-
+        @SuppressWarnings("unchecked")
+        private void createArrays() {
             space = new ArrayList[layers.length];
             downProcessingOrder = new ArrayList[layers.length];
             upProcessingOrder = new ArrayList[layers.length];
+        }
+
+        @Override
+        protected void run() {
+            createArrays();
 
             for (int i = 0; i < layers.length; i++) {
-                space[i] = new ArrayList<Integer>();
-                downProcessingOrder[i] = new ArrayList<LayoutNode>();
-                upProcessingOrder[i] = new ArrayList<LayoutNode>();
+                space[i] = new ArrayList<>();
+                downProcessingOrder[i] = new ArrayList<>();
+                upProcessingOrder[i] = new ArrayList<>();
 
                 int curX = 0;
                 for (LayoutNode n : layers[i]) {
@@ -590,72 +621,106 @@
             initialPositions();
             for (int i = 0; i < SWEEP_ITERATIONS; i++) {
                 sweepDown();
-                sweepUp();
+                adjustSpace();
+                sweepUp(false);
+                adjustSpace();
             }
 
-            for (int i = 0; i < SWEEP_ITERATIONS; i++) {
-                doubleSweep();
+            sweepDown();
+            adjustSpace();
+            sweepUp(true);
+        }
+
+        private void adjustSpace() {
+            for (int i = 0; i < layers.length; i++) {
+                //               space[i] = new ArrayList<>();
+                int curX = 0;
+                for (LayoutNode n : layers[i]) {
+                    space[i].add(n.x);
+//                    curX += n.width + xOffset;
+                }
             }
         }
 
         private int calculateOptimalDown(LayoutNode n) {
-
-            List<Integer> values = new ArrayList<Integer>();
-            if (n.preds.size() == 0) {
+            int size = n.preds.size();
+            if (size == 0) {
                 return n.x;
             }
+            int vipCount = 0;
             for (LayoutEdge e : n.preds) {
-                int cur = e.from.x + e.relativeFrom - e.relativeTo;
-                values.add(cur);
+                if (e.vip) {
+                    vipCount++;
+                }
             }
-            return median(values);
+
+            if (vipCount == 0) {
+                int[] values = new int[size];
+                for (int i = 0; i < size; i++) {
+                    LayoutEdge e = n.preds.get(i);
+                    values[i] = e.from.x + e.relativeFrom - e.relativeTo;
+                }
+                return median(values);
+            } else {
+                int z = 0;
+                int[] values = new int[vipCount];
+                for (int i = 0; i < size; i++) {
+                    LayoutEdge e = n.preds.get(i);
+                    if (e.vip) {
+                        values[z++] = e.from.x + e.relativeFrom - e.relativeTo;
+                    }
+                }
+                return median(values);
+            }
         }
 
         private int calculateOptimalBoth(LayoutNode n) {
-
-            List<Integer> values = new ArrayList<Integer>();
-            if (n.preds.size() == 0 + n.succs.size()) {
+            if (n.preds.size() == n.succs.size()) {
                 return n.x;
             }
+
+            int[] values = new int[n.preds.size() + n.succs.size()];
+            int i = 0;
+
             for (LayoutEdge e : n.preds) {
-                int cur = e.from.x + e.relativeFrom - e.relativeTo;
-                values.add(cur);
+                values[i] = e.from.x + e.relativeFrom - e.relativeTo;
+                i++;
             }
 
             for (LayoutEdge e : n.succs) {
-                int cur = e.to.x + e.relativeTo - e.relativeFrom;
-                values.add(cur);
+                values[i] = e.to.x + e.relativeTo - e.relativeFrom;
+                i++;
             }
 
             return median(values);
         }
 
         private int calculateOptimalUp(LayoutNode n) {
-
-            //List<Integer> values = new ArrayList<Integer>();
             int size = n.succs.size();
             if (size == 0) {
                 return n.x;
+            }
+            int[] values = new int[size];
+            for (int i = 0; i < size; i++) {
+                LayoutEdge e = n.succs.get(i);
+                values[i] = e.to.x + e.relativeTo - e.relativeFrom;
+                if (e.vip) {
+                    return values[i];
+                }
+            }
+            return median(values);
+        }
+
+        private int median(int[] values) {
+            Arrays.sort(values);
+            if (values.length % 2 == 0) {
+                return (values[values.length / 2 - 1] + values[values.length / 2]) / 2;
             } else {
-                int result = 0;
-                for (LayoutEdge e : n.succs) {
-                    int cur = e.to.x + e.relativeTo - e.relativeFrom;
-                    result += cur;
-                }
-                return result / size; //median(values);
+                return values[values.length / 2];
             }
         }
 
-        private int median(List<Integer> values) {
-            Collections.sort(values);
-            if (values.size() % 2 == 0) {
-                return (values.get(values.size() / 2 - 1) + values.get(values.size() / 2)) / 2;
-            } else {
-                return values.get(values.size() / 2);
-            }
-        }
-
-        private void sweepUp() {
+        private void sweepUp(boolean onlyDummies) {
             for (int i = layers.length - 1; i >= 0; i--) {
                 NodeRow r = new NodeRow(space[i]);
                 for (LayoutNode n : upProcessingOrder[i]) {
@@ -663,14 +728,6 @@
                     r.insert(n, optimal);
                 }
             }
-        /*
-        for(int i=0; i<layers.length; i++) {
-        NodeRow r = new NodeRow(space[i]);
-        for(LayoutNode n : upProcessingOrder[i]) {
-        int optimal = calculateOptimalUp(n);
-        r.insert(n, optimal);
-        }
-        }*/
         }
 
         private void doubleSweep() {
@@ -700,7 +757,7 @@
         private ArrayList<Integer> space;
 
         public NodeRow(ArrayList<Integer> space) {
-            treeSet = new TreeSet<LayoutNode>(nodePositionComparator);
+            treeSet = new TreeSet<>(nodePositionComparator);
             this.space = space;
         }
 
@@ -739,357 +796,15 @@
                     n.x = pos;
                 }
 
-                assert minX <= maxX;
+                assert minX <= maxX : minX + " vs " + maxX;
             }
 
             treeSet.add(n);
         }
     }
-
-    private class AssignXCoordinates extends AlgorithmPart {
-
-        HashMap<LayoutNode, Segment> hashMap = new HashMap<LayoutNode, Segment>();
-        ArrayList<Segment> segments = new ArrayList<Segment>();
-
-        private void generateSegments() {
-
-            for (int i = 0; i < layerCount; i++) {
-                for (LayoutNode n : layers[i]) {
-                    if (!hashMap.containsKey(n)) {
-                        Segment s = new Segment();
-                        segments.add(s);
-                        LayoutNode curNode = n;
-
-                        int maxLength = 0;
-                        while (curNode.succs.size() == 1 && curNode.preds.size() == 1) {
-                            s.nodes.add(curNode);
-                            assert !hashMap.containsKey(curNode);
-                            hashMap.put(curNode, s);
-                            curNode = curNode.succs.get(0).to;
-                            maxLength++;
-                        //if(maxLength > 10) break;
-                        }
-
-                        if (s.nodes.size() > 0 && curNode.preds.size() == 1 && curNode.vertex == null) {
-                            s.nodes.add(curNode);
-                            assert !hashMap.containsKey(curNode);
-                            hashMap.put(curNode, s);
-                        }
-
-                        if (s.nodes.size() == 0) {
-                            // Simple segment with a single node
-                            s.nodes.add(n);
-                            hashMap.put(n, s);
-                        }
-                    }
-                }
-            }
-        }
-
-        private void addEdges() {
-
-            for (int i = 0; i < layerCount; i++) {
-                LayoutNode prev = null;
-                for (LayoutNode n : layers[i]) {
-
-                    if (prev != null) {
-                        Segment s1 = hashMap.get(prev);
-                        Segment s2 = hashMap.get(n);
-
-                        if (s1 != s2) {
-                            s1.succs.add(s2);
-                            s2.preds.add(s1);
-                        }
-                    }
-                    prev = n;
-
-                }
-            }
-        }
-
-        private void topologicalSorting() {
-
-            Queue<Segment> queue = new LinkedList<Segment>();
-
-            int index = 0;
-            ArrayList<Segment> newList = new ArrayList<Segment>();
-            for (Segment s : segments) {
-                if (s.preds.size() == 0) {
-                    s.orderNumber = index;
-                    newList.add(s);
-                    index++;
-                    queue.add(s);
-                }
-            }
-
-            while (!queue.isEmpty()) {
-                Segment s = queue.remove();
-
-                for (Segment succ : s.succs) {
-                    succ.preds.remove(s);
-                    if (succ.preds.size() == 0) {
-                        queue.add(succ);
-                        succ.orderNumber = index;
-                        newList.add(succ);
-                        index++;
-                    }
-                }
-            }
-
-            segments = newList;
-        }
-
-        private void initialPositions() {
-
-            int[] minPos = new int[layers.length];
-
-            for (Segment s : segments) {
-                int max = 0;
-                for (LayoutNode n : s.nodes) {
-                    int x = minPos[n.layer];
-                    if (x > max) {
-                        max = x;
-                    }
-                }
-
-                for (LayoutNode n : s.nodes) {
-                    minPos[n.layer] = max + n.width + xOffset;
-                    n.x = max;
-                }
-            }
-        }
-
-        private int predSum(LayoutNode n) {
-            int sum = 0;
-            for (LayoutEdge e : n.preds) {
-                assert e.to == n;
-                //sum += (e.from.x + e.relativeFrom + (int)hashMap.get(e.from).d) - (e.to.x + e.relativeTo + (int)hashMap.get(e.to).d);
-                sum += (e.from.x + e.relativeFrom) - (e.to.x + e.relativeTo);
-            }
-
-            return sum;
-        }
-
-        private int succSum(LayoutNode n) {
-            int sum = 0;
-            for (LayoutEdge e : n.succs) {
-
-                assert e.from == n;
-                sum += (e.to.x + e.relativeTo) - (e.from.x + e.relativeFrom);
-            //sum += (e.to.x + e.relativeTo + (int)hashMap.get(e.to).d) - (e.from.x + e.relativeFrom + (int)hashMap.get(e.from).d);
-            }
-
-            return sum;
-
-        }
-
-        private void downValues() {
-
-            for (Segment s : segments) {
-                downValues(s);
-
-            }
-
-        }
-
-        private void downValues(Segment s) {
-            LayoutNode n = s.nodes.get(0); // Only first node needed, all other have same coordinate
-
-            if (n.preds.size() == 0) {
-                // Value is 0.0;
-                if (n.succs.size() == 0) {
-                    s.d = 0.0f;
-                } else {
-                    s.d = (((float) succSum(n) / (float) n.succs.size())) / 2;
-                }
-            } else {
-                s.d = (float) predSum(n) / (float) n.preds.size();
-            }
-        }
-
-        private void upValues() {
-            for (Segment s : segments) {
-                upValues(s);
-            }
-        }
-
-        private void upValues(Segment s) {
-            LayoutNode n = s.nodes.get(0); // Only first node needed, all other have same coordinate
-
-            if (n.succs.size() == 0) {
-                // Value is 0.0;
-                if (n.preds.size() == 0) {
-                    s.d = 0.0f;
-                } else {
-                    s.d = (float) predSum(n) / (float) n.preds.size();
-                }
-            } else {
-                s.d = ((float) succSum(n) / (float) n.succs.size()) / 2;
-            }
-        }
-
-        private void sweep(boolean down) {
-
-            if (down) {
-                downValues();
-            } else {
-                upValues();
-            }
-
-            SortedSet<Region> regions = new TreeSet<Region>(regionComparator);
-            for (Segment s : segments) {
-                s.region = new Region();
-                s.region.minOrderNumber = s.orderNumber;
-                s.region.segments.add(s);
-                s.region.d = s.d;
-                regions.add(s.region);
-            }
-
-            for (Segment s : segments) {
-                for (LayoutNode n : s.nodes) {
-                    if (n.pos != 0) {
-                        LayoutNode prevNode = layers[n.layer].get(n.pos - 1);
-                        if (prevNode.x + prevNode.width + xOffset == n.x) {
-                            Segment other = hashMap.get(prevNode);
-                            Region r1 = s.region;
-                            Region r2 = other.region;
-                            // They are close together
-                            if (r1 != r2 && r2.d >= r1.d) {
-
-                                if (r2.segments.size() < r1.segments.size()) {
-
-                                    r1.d = (r1.d * r1.segments.size() + r2.d * r2.segments.size()) / (r1.segments.size() + r2.segments.size());
-
-                                    for (Segment tempS : r2.segments) {
-                                        r1.segments.add(tempS);
-                                        tempS.region = r1;
-                                        r1.minOrderNumber = Math.min(r1.minOrderNumber, tempS.orderNumber);
-                                    }
-
-                                    regions.remove(r2);
-                                } else {
-
-                                    r2.d = (r1.d * r1.segments.size() + r2.d * r2.segments.size()) / (r1.segments.size() + r2.segments.size());
-
-                                    for (Segment tempS : r1.segments) {
-                                        r2.segments.add(tempS);
-                                        tempS.region = r2;
-                                        r2.minOrderNumber = Math.min(r2.minOrderNumber, tempS.orderNumber);
-                                    }
-
-                                    regions.remove(r1);
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-
-
-
-            ArrayList<Region> reversedRegions = new ArrayList<Region>();
-            for (Region r : regions) {
-                if (r.d < 0) {
-                    processRegion(r, down);
-                } else {
-                    reversedRegions.add(0, r);
-                }
-            }
-
-            for (Region r : reversedRegions) {
-                processRegion(r, down);
-            }
-
-        }
-
-        private void processRegion(Region r, boolean down) {
-
-            // Do not move
-            if ((int) r.d == 0) {
-                return;
-            }
-
-            ArrayList<Segment> arr = new ArrayList<Segment>();
-            for (Segment s : r.segments) {
-                arr.add(s);
-            }
-
-            if (r.d > 0) {
-                Collections.reverse(arr);
-            }
-
-            for (Segment s : arr) {
-
-
-                int min = (int) r.d;
-                if (min < 0) {
-                    min = -min;
-                }
-
-                for (LayoutNode n : s.nodes) {
-
-                    int layer = n.layer;
-                    int pos = n.pos;
-
-
-                    if (r.d > 0) {
-
-                        if (pos != layers[layer].size() - 1) {
-
-                            int off = layers[layer].get(pos + 1).x - n.x - xOffset - n.width;
-                            assert off >= 0;
-                            if (off < min) {
-                                min = off;
-                            }
-                        }
-
-                    } else {
-
-                        if (pos != 0) {
-
-                            int off = n.x - xOffset - layers[layer].get(pos - 1).x - layers[layer].get(pos - 1).width;
-                            assert off >= 0;
-                            if (off < min) {
-                                min = off;
-                            }
-                        }
-                    }
-                }
-
-                assert min >= 0;
-                if (min != 0) {
-                    for (LayoutNode n : s.nodes) {
-                        if (r.d > 0) {
-                            n.x += min;
-                        } else {
-                            n.x -= min;
-                        }
-
-                    }
-                }
-            }
-        }
-
-        protected void run() {
-
-            generateSegments();
-            addEdges();
-            topologicalSorting();
-            initialPositions();
-            for (int i = 0; i < SWEEP_ITERATIONS; i++) {
-
-                sweep(true);
-                sweep(true);
-                sweep(false);
-                sweep(false);
-            }
-
-            sweep(true);
-            sweep(true);
-        }
-    }
     private static Comparator<LayoutNode> crossingNodeComparator = new Comparator<LayoutNode>() {
 
+        @Override
         public int compare(LayoutNode n1, LayoutNode n2) {
             return n1.crossingNumber - n2.crossingNumber;
         }
@@ -1104,22 +819,26 @@
             }
         }
 
-        protected void run() {
-
+        @SuppressWarnings("unchecked")
+        private void createLayers() {
             layers = new List[layerCount];
 
             for (int i = 0; i < layerCount; i++) {
-                layers[i] = new ArrayList<LayoutNode>();
+                layers[i] = new ArrayList<>();
             }
+        }
 
+        @Override
+        protected void run() {
+            createLayers();
 
             // Generate initial ordering
-            HashSet<LayoutNode> visited = new HashSet<LayoutNode>();
+            HashSet<LayoutNode> visited = new HashSet<>();
             for (LayoutNode n : nodes) {
                 if (n.layer == 0) {
                     layers[0].add(n);
                     visited.add(n);
-                } else if (n.preds.size() == 0) {
+                } else if (n.preds.isEmpty()) {
                     layers[n.layer].add(n);
                     visited.add(n);
                 }
@@ -1136,7 +855,6 @@
                 }
             }
 
-
             updatePositions();
 
             initX();
@@ -1146,10 +864,7 @@
                 downSweep();
                 upSweep();
             }
-
-        /*for(int i=0; i<CROSSING_ITERATIONS; i++) {
-        doubleSweep();
-        }*/
+            downSweep();
         }
 
         private void initX() {
@@ -1191,25 +906,23 @@
                 for (LayoutNode n : layers[i]) {
 
                     int sum = 0;
+                    int count = 0;
                     for (LayoutEdge e : n.preds) {
                         int cur = e.from.x + e.relativeFrom;
-
-                        /*pos;
-                        if(e.from.width != 0 && e.relativeFrom != 0) {
-                        cur += (float)e.relativeFrom / (float)(e.from.width);
-                        }*/
-
-                        sum += cur;
+                        int factor = 1;
+                        if (e.vip) {
+                            factor = VIP_BONUS;
+                        }
+                        sum += cur * factor;
+                        count += factor;
                     }
 
-                    if (n.preds.size() > 0) {
-                        sum /= n.preds.size();
+                    if (count > 0) {
+                        sum /= count;
                         n.crossingNumber = sum;
-                    //if(n.vertex == null) n.crossingNumber += layers[i].size();
                     }
                 }
 
-
                 updateCrossingNumbers(i, true);
                 Collections.sort(layers[i], crossingNodeComparator);
                 updateXOfLayer(i);
@@ -1234,9 +947,9 @@
                     next = layers[index].get(i + 1);
                 }
 
-                boolean cond = (n.succs.size() == 0);
+                boolean cond = n.succs.isEmpty();
                 if (down) {
-                    cond = (n.preds.size() == 0);
+                    cond = n.preds.isEmpty();
                 }
 
                 if (cond) {
@@ -1251,44 +964,6 @@
                 }
             }
         }
-        /*
-        private void doubleSweep() {
-        // Downsweep
-        for(int i=0; i<layerCount*2; i++) {
-        int index = i;
-        if(index >= layerCount) {
-        index = 2*layerCount - i - 1;
-        }
-        for(LayoutNode n : layers[index]) {
-        float sum = 0.0f;
-        for(LayoutEdge e : n.preds) {
-        float cur = e.from.pos;
-        if(e.from.width != 0 && e.relativeFrom != 0) {
-        cur += (float)e.relativeFrom / (float)(e.from.width);
-        }
-        sum += cur;
-        }
-        for(LayoutEdge e : n.succs) {
-        float cur = e.to.pos;
-        if(e.to.width != 0 && e.relativeTo != 0) {
-        cur += (float)e.relativeTo / (float)(e.to.width);
-        }
-        sum += cur;
-        }
-        if(n.preds.size() + n.succs.size() > 0) {
-        sum /= n.preds.size() + n.succs.size();
-        n.crossingNumber = sum;
-        }
-        }
-        Collections.sort(layers[index], crossingNodeComparator);
-        updateXOfLayer(index);
-        int z = 0;
-        for(LayoutNode n : layers[index]) {
-        n.pos = z;
-        z++;
-        }
-        }
-        }*/
 
         private void upSweep() {
             // Upsweep
@@ -1300,21 +975,21 @@
 
                 for (LayoutNode n : layers[i]) {
 
+                    int count = 0;
                     int sum = 0;
                     for (LayoutEdge e : n.succs) {
-                        int cur = e.to.x + e.relativeTo;//pos;
-                                                /*
-                        if(e.to.width != 0 && e.relativeTo != 0) {
-                        cur += (float)e.relativeTo / (float)(e.to.width);
-                        }*/
-
-                        sum += cur;
+                        int cur = e.to.x + e.relativeTo;
+                        int factor = 1;
+                        if (e.vip) {
+                            factor = VIP_BONUS;
+                        }
+                        sum += cur * factor;
+                        count += factor;
                     }
 
-                    if (n.succs.size() > 0) {
-                        sum /= n.succs.size();
+                    if (count > 0) {
+                        sum /= count;
                         n.crossingNumber = sum;
-                    //if(n.vertex == null) n.crossingNumber += layers[i].size();
                     }
 
                 }
@@ -1331,15 +1006,10 @@
             }
         }
 
-        private int evaluate() {
-            // TODO: Implement efficient evaluate / crossing min
-            return 0;
-        }
-
         @Override
         public void postCheck() {
 
-            HashSet<LayoutNode> visited = new HashSet<LayoutNode>();
+            HashSet<LayoutNode> visited = new HashSet<>();
             for (int i = 0; i < layers.length; i++) {
                 for (LayoutNode n : layers[i]) {
                     assert !visited.contains(n);
@@ -1353,9 +1023,10 @@
 
     private class AssignYCoordinates extends AlgorithmPart {
 
+        @Override
         protected void run() {
             int curY = 0;
-            //maxLayerHeight = new int[layers.length];
+
             for (int i = 0; i < layers.length; i++) {
                 int maxHeight = 0;
                 int baseLine = 0;
@@ -1383,10 +1054,8 @@
                     }
                 }
 
-                //maxLayerHeight[i] = maxHeight + baseLine + bottomBaseLine;
-
                 curY += maxHeight + baseLine + bottomBaseLine;
-                curY += layerOffset + (int) Math.sqrt(maxXOffset);
+                curY += layerOffset + ((int) (Math.sqrt(maxXOffset) * 1.5));
             }
         }
     }
@@ -1411,26 +1080,27 @@
             }
         }
 
+        @Override
         protected void run() {
             oldNodeCount = nodes.size();
 
-
             if (combine == Combine.SAME_OUTPUTS) {
 
                 Comparator<LayoutEdge> comparator = new Comparator<LayoutEdge>() {
 
+                    @Override
                     public int compare(LayoutEdge e1, LayoutEdge e2) {
                         return e1.to.layer - e2.to.layer;
                     }
                 };
-                HashMap<Integer, List<LayoutEdge>> portHash = new HashMap<Integer, List<LayoutEdge>>();
-                ArrayList<LayoutNode> currentNodes = new ArrayList<LayoutNode>(nodes);
+                HashMap<Integer, List<LayoutEdge>> portHash = new HashMap<>();
+                ArrayList<LayoutNode> currentNodes = new ArrayList<>(nodes);
                 for (LayoutNode n : currentNodes) {
                     portHash.clear();
 
-                    ArrayList<LayoutEdge> succs = new ArrayList<LayoutEdge>(n.succs);
-                    HashMap<Integer, LayoutNode> topNodeHash = new HashMap<Integer, LayoutNode>();
-                    HashMap<Integer, HashMap<Integer, LayoutNode>> bottomNodeHash = new HashMap<Integer, HashMap<Integer, LayoutNode>>();
+                    ArrayList<LayoutEdge> succs = new ArrayList<>(n.succs);
+                    HashMap<Integer, LayoutNode> topNodeHash = new HashMap<>();
+                    HashMap<Integer, HashMap<Integer, LayoutNode>> bottomNodeHash = new HashMap<>();
                     for (LayoutEdge e : succs) {
                         assert e.from.layer < e.to.layer;
                         if (e.from.layer != e.to.layer - 1) {
@@ -1449,6 +1119,7 @@
                                     topEdge.relativeTo = topNode.width / 2;
                                     topEdge.to = topNode;
                                     topEdge.link = e.link;
+                                    topEdge.vip = e.vip;
                                     e.from.succs.add(topEdge);
                                     topNode.preds.add(topEdge);
                                 } else {
@@ -1464,6 +1135,7 @@
                                     topEdge.relativeTo = topNode.width / 2;
                                     topEdge.to = topNode;
                                     topEdge.link = e.link;
+                                    topEdge.vip = e.vip;
                                     e.from.succs.add(topEdge);
                                     topNode.preds.add(topEdge);
                                     topNodeHash.put(e.relativeFrom, topNode);
@@ -1491,6 +1163,7 @@
                                 bottomEdge.relativeFrom = bottomNode.width / 2;
                                 bottomEdge.from = bottomNode;
                                 bottomEdge.link = e.link;
+                                bottomEdge.vip = e.vip;
                                 e.to.preds.add(bottomEdge);
                                 bottomEdgeHash.put(topEdge, bottomEdge);
                                 bottomNode.succs.add(bottomEdge);
@@ -1500,17 +1173,12 @@
                                 if (!portHash.containsKey(i)) {
                                     portHash.put(i, new ArrayList<LayoutEdge>());
                                 }
-
-                                if (n.vertex.toString().equals("1012 CastPP")) {
-                                    int x = 0;
-                                }
-
                                 portHash.get(i).add(e);
                             }
                         }
                     }
 
-                    succs = new ArrayList<LayoutEdge>(n.succs);
+                    succs = new ArrayList<>(n.succs);
                     for (LayoutEdge e : succs) {
 
                         Integer i = e.relativeFrom;
@@ -1528,13 +1196,13 @@
                                     maxLayer = Math.max(maxLayer, curEdge.to.layer);
                                 }
 
-
                                 int cnt = maxLayer - n.layer - 1;
                                 LayoutEdge[] edges = new LayoutEdge[cnt];
                                 LayoutNode[] nodes = new LayoutNode[cnt];
                                 edges[0] = new LayoutEdge();
                                 edges[0].from = n;
                                 edges[0].relativeFrom = i;
+                                edges[0].vip = e.vip;
                                 n.succs.add(edges[0]);
 
                                 nodes[0] = new LayoutNode();
@@ -1546,6 +1214,7 @@
                                 edges[0].relativeTo = nodes[0].width / 2;
                                 for (int j = 1; j < cnt; j++) {
                                     edges[j] = new LayoutEdge();
+                                    edges[j].vip = e.vip;
                                     edges[j].from = nodes[j - 1];
                                     edges[j].relativeFrom = nodes[j - 1].width / 2;
                                     nodes[j - 1].succs.add(edges[j]);
@@ -1577,7 +1246,7 @@
             } else if (combine == Combine.SAME_INPUTS) {
                 throw new UnsupportedOperationException("Currently not supported");
             } else {
-                ArrayList<LayoutNode> currentNodes = new ArrayList<LayoutNode>(nodes);
+                ArrayList<LayoutNode> currentNodes = new ArrayList<>(nodes);
                 for (LayoutNode n : currentNodes) {
                     for (LayoutEdge e : n.succs) {
                         processSingleEdge(e);
@@ -1604,6 +1273,7 @@
             n.preds.add(e);
             nodes.add(n);
             LayoutEdge result = new LayoutEdge();
+            result.vip = e.vip;
             n.succs.add(result);
             result.from = n;
             result.relativeFrom = n.width / 2;
@@ -1623,7 +1293,7 @@
 
         @Override
         public void postCheck() {
-            ArrayList<LayoutNode> currentNodes = new ArrayList<LayoutNode>(nodes);
+            ArrayList<LayoutNode> currentNodes = new ArrayList<>(nodes);
             for (LayoutNode n : currentNodes) {
                 for (LayoutEdge e : n.succs) {
                     assert e.from.layer == e.to.layer - 1;
@@ -1648,91 +1318,114 @@
             }
         }
 
+        @Override
         protected void run() {
-            HashSet<LayoutNode> set = new HashSet<LayoutNode>();
+            assignLayerDownwards();
+            assignLayerUpwards();
+        }
+
+        private void assignLayerDownwards() {
+            ArrayList<LayoutNode> hull = new ArrayList<>();
             for (LayoutNode n : nodes) {
-                if (n.preds.size() == 0) {
-                    set.add(n);
+                if (n.preds.isEmpty()) {
+                    hull.add(n);
                     n.layer = 0;
                 }
             }
 
             int z = minLayerDifference;
-            HashSet<LayoutNode> newSet = new HashSet<LayoutNode>();
-            HashSet<LayoutNode> failed = new HashSet<LayoutNode>();
-            while (!set.isEmpty()) {
-
-                newSet.clear();
-                failed.clear();
-
-                for (LayoutNode n : set) {
-
+            while (!hull.isEmpty()) {
+                ArrayList<LayoutNode> newSet = new ArrayList<>();
+                for (LayoutNode n : hull) {
                     for (LayoutEdge se : n.succs) {
                         LayoutNode s = se.to;
-                        if (!newSet.contains(s) && !failed.contains(s)) {
-                            boolean ok = true;
+                        if (s.layer != -1) {
+                            // This node was assigned before.
+                        } else {
+                            boolean unassignedPred = false;
                             for (LayoutEdge pe : s.preds) {
                                 LayoutNode p = pe.from;
-                                if (p.layer == -1) {
-                                    ok = false;
+                                if (p.layer == -1 || p.layer >= z) {
+                                    // This now has an unscheduled successor or a successor that was scheduled only in this round.
+                                    unassignedPred = true;
                                     break;
                                 }
                             }
 
-                            if (ok) {
+                            if (unassignedPred) {
+                                // This successor node can not yet be assigned.
+                            } else {
+                                s.layer = z;
                                 newSet.add(s);
-                            } else {
-                                failed.add(s);
                             }
                         }
                     }
-
                 }
 
-                for (LayoutNode n : newSet) {
-                    n.layer = z;
-                }
-
-                // Swap sets
-                HashSet<LayoutNode> tmp = set;
-                set = newSet;
-                newSet = tmp;
+                hull = newSet;
                 z += minLayerDifference;
             }
 
-            optimize(set);
+            layerCount = z - minLayerDifference;
+            for (LayoutNode n : nodes) {
+                n.layer = (layerCount - 1 - n.layer);
+            }
+        }
+
+        private void assignLayerUpwards() {
+            ArrayList<LayoutNode> hull = new ArrayList<>();
+            for (LayoutNode n : nodes) {
+                if (n.succs.isEmpty()) {
+                    hull.add(n);
+                } else {
+                    n.layer = -1;
+                }
+            }
+
+            int z = minLayerDifference;
+            while (!hull.isEmpty()) {
+                ArrayList<LayoutNode> newSet = new ArrayList<>();
+                for (LayoutNode n : hull) {
+                    if (n.layer < z) {
+                        for (LayoutEdge se : n.preds) {
+                            LayoutNode s = se.from;
+                            if (s.layer != -1) {
+                                // This node was assigned before.
+                            } else {
+                                boolean unassignedSucc = false;
+                                for (LayoutEdge pe : s.succs) {
+                                    LayoutNode p = pe.to;
+                                    if (p.layer == -1 || p.layer >= z) {
+                                        // This now has an unscheduled successor or a successor that was scheduled only in this round.
+                                        unassignedSucc = true;
+                                        break;
+                                    }
+                                }
+
+                                if (unassignedSucc) {
+                                    // This predecessor node can not yet be assigned.
+                                } else {
+                                    s.layer = z;
+                                    newSet.add(s);
+                                }
+                            }
+                        }
+                    } else {
+                        newSet.add(n);
+                    }
+                }
+
+                hull = newSet;
+                z += minLayerDifference;
+            }
 
             layerCount = z - minLayerDifference;
 
-            for (Vertex v : lastLayerHint) {
-
-                LayoutNode n = vertexToLayoutNode.get(v);
-                assert n.succs.size() == 0;
-                n.layer = layerCount - 1;
-            }
-
-            for (Vertex v : firstLayerHint) {
-                LayoutNode n = vertexToLayoutNode.get(v);
-                assert n.preds.size() == 0;
-                assert n.layer == 0;
+            for (LayoutNode n : nodes) {
+                n.layer = (layerCount - 1 - n.layer);
             }
         }
 
-        public void optimize(HashSet<LayoutNode> set) {
-
-            for (LayoutNode n : set) {
-                if (n.preds.size() == 0 && n.succs.size() > 0) {
-                    int minLayer = n.succs.get(0).to.layer;
-                    for (LayoutEdge e : n.succs) {
-                        minLayer = Math.min(minLayer, e.to.layer);
-                    }
-
-                    n.layer = minLayer - 1;
-                }
-            }
-
-        }
-
         @Override
         public void postCheck() {
             for (LayoutNode n : nodes) {
@@ -1750,11 +1443,12 @@
         private HashSet<LayoutNode> visited;
         private HashSet<LayoutNode> active;
 
+        @Override
         protected void run() {
 
-            // Remove self-edges, TODO: Special treatment
+            // Remove self-edges
             for (LayoutNode node : nodes) {
-                ArrayList<LayoutEdge> succs = new ArrayList<LayoutEdge>(node.succs);
+                ArrayList<LayoutEdge> succs = new ArrayList<>(node.succs);
                 for (LayoutEdge e : succs) {
                     assert e.from == node;
                     if (e.to == node) {
@@ -1780,18 +1474,16 @@
                 }
             }
 
-
             // Start DFS and reverse back edges
-            visited = new HashSet<LayoutNode>();
-            active = new HashSet<LayoutNode>();
+            visited = new HashSet<>();
+            active = new HashSet<>();
             for (LayoutNode node : nodes) {
                 DFS(node);
             }
 
-
             for (LayoutNode node : nodes) {
 
-                SortedSet<Integer> reversedDown = new TreeSet<Integer>();
+                SortedSet<Integer> reversedDown = new TreeSet<>();
 
                 for (LayoutEdge e : node.succs) {
                     if (reversedLinks.contains(e.link)) {
@@ -1799,12 +1491,11 @@
                     }
                 }
 
-
                 SortedSet<Integer> reversedUp = null;
                 if (reversedDown.size() == 0) {
-                    reversedUp = new TreeSet<Integer>(Collections.reverseOrder());
+                    reversedUp = new TreeSet<>(Collections.reverseOrder());
                 } else {
-                    reversedUp = new TreeSet<Integer>();
+                    reversedUp = new TreeSet<>();
                 }
 
                 for (LayoutEdge e : node.preds) {
@@ -1818,7 +1509,7 @@
                 int curX = 0;
                 int curWidth = node.width + reversedDown.size() * offset;
                 for (int pos : reversedDown) {
-                    ArrayList<LayoutEdge> reversedSuccs = new ArrayList<LayoutEdge>();
+                    ArrayList<LayoutEdge> reversedSuccs = new ArrayList<>();
                     for (LayoutEdge e : node.succs) {
                         if (e.relativeFrom == pos && reversedLinks.contains(e.link)) {
                             reversedSuccs.add(e);
@@ -1826,7 +1517,7 @@
                         }
                     }
 
-                    ArrayList<Point> startPoints = new ArrayList<Point>();
+                    ArrayList<Point> startPoints = new ArrayList<>();
                     startPoints.add(new Point(curWidth, curX));
                     startPoints.add(new Point(pos, curX));
                     startPoints.add(new Point(pos, reversedDown.size() * offset));
@@ -1856,7 +1547,7 @@
 
                 int oldNodeHeight = node.height;
                 for (int pos : reversedUp) {
-                    ArrayList<LayoutEdge> reversedPreds = new ArrayList<LayoutEdge>();
+                    ArrayList<LayoutEdge> reversedPreds = new ArrayList<>();
                     for (LayoutEdge e : node.preds) {
                         if (e.relativeTo == pos && reversedLinks.contains(e.link)) {
                             if (reversedDown.size() == 0) {
@@ -1869,7 +1560,7 @@
                         }
                     }
                     node.height += offset;
-                    ArrayList<Point> endPoints = new ArrayList<Point>();
+                    ArrayList<Point> endPoints = new ArrayList<>();
 
                     if (reversedDown.size() == 0) {
 
@@ -1887,7 +1578,6 @@
                     curX += offset;
                     node.bottomYOffset += offset;
 
-
                     endPoints.add(new Point(pos, node.height));
                     endPoints.add(new Point(pos, oldNodeHeight));
                     for (LayoutEdge e : reversedPreds) {
@@ -1895,7 +1585,6 @@
                     }
                 }
 
-
                 if (minX < 0) {
                     for (LayoutEdge e : node.preds) {
                         e.relativeTo -= minX;
@@ -1917,7 +1606,7 @@
                 return;
             }
 
-            Stack<LayoutNode> stack = new Stack<LayoutNode>();
+            Stack<LayoutNode> stack = new Stack<>();
             stack.push(startNode);
 
             while (!stack.empty()) {
@@ -1934,7 +1623,7 @@
                 visited.add(node);
                 active.add(node);
 
-                ArrayList<LayoutEdge> succs = new ArrayList<LayoutEdge>(node.succs);
+                ArrayList<LayoutEdge> succs = new ArrayList<>(node.succs);
                 for (LayoutEdge e : succs) {
                     if (active.contains(e.to)) {
                         assert visited.contains(e.to);
@@ -1989,8 +1678,8 @@
 
             for (LayoutNode n : nodes) {
 
-                HashSet<LayoutNode> curVisited = new HashSet<LayoutNode>();
-                Queue<LayoutNode> queue = new LinkedList<LayoutNode>();
+                HashSet<LayoutNode> curVisited = new HashSet<>();
+                Queue<LayoutNode> queue = new LinkedList<>();
                 for (LayoutEdge e : n.succs) {
                     LayoutNode s = e.to;
                     queue.add(s);
@@ -2013,7 +1702,15 @@
     }
     private Comparator<Link> linkComparator = new Comparator<Link>() {
 
+        @Override
         public int compare(Link l1, Link l2) {
+            if (l1.isVIP() && !l2.isVIP()) {
+                return -1;
+            }
+
+            if (!l1.isVIP() && l2.isVIP()) {
+                return 1;
+            }
 
             int result = l1.getFrom().getVertex().compareTo(l2.getFrom().getVertex());
             if (result != 0) {
@@ -2034,9 +1731,10 @@
 
     private class BuildDatastructure extends AlgorithmPart {
 
+        @Override
         protected void run() {
             // Set up nodes
-            List<Vertex> vertices = new ArrayList<Vertex>(graph.getVertices());
+            List<Vertex> vertices = new ArrayList<>(graph.getVertices());
             Collections.sort(vertices);
 
             for (Vertex v : vertices) {
@@ -2050,7 +1748,7 @@
             }
 
             // Set up edges
-            List<Link> links = new ArrayList<Link>(graph.getLinks());
+            List<Link> links = new ArrayList<>(graph.getLinks());
             Collections.sort(links, linkComparator);
             for (Link l : links) {
                 LayoutEdge edge = new LayoutEdge();
@@ -2061,14 +1759,15 @@
                 edge.relativeFrom = l.getFrom().getRelativePosition().x;
                 edge.relativeTo = l.getTo().getRelativePosition().x;
                 edge.link = l;
+                edge.vip = l.isVIP();
                 edge.from.succs.add(edge);
                 edge.to.preds.add(edge);
-            //assert edge.from != edge.to; // No self-loops allowed
+                //assert edge.from != edge.to; // No self-loops allowed
             }
 
             for (Link l : importantLinks) {
-                if (!vertexToLayoutNode.containsKey(l.getFrom().getVertex()) ||
-                        vertexToLayoutNode.containsKey(l.getTo().getVertex())) {
+                if (!vertexToLayoutNode.containsKey(l.getFrom().getVertex())
+                        || vertexToLayoutNode.containsKey(l.getTo().getVertex())) {
                     continue;
                 }
                 LayoutNode from = vertexToLayoutNode.get(l.getFrom().getVertex());
@@ -2104,7 +1803,8 @@
         }
     }
 
+    @Override
     public void doRouting(LayoutGraph graph) {
-    // Do nothing for now
+        // Do nothing for now
     }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/InterClusterConnection.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/InterClusterConnection.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -73,4 +73,8 @@
     public String toString() {
         return "InterClusterConnection[from=" + getFrom() + ", to=" + getTo() + "]";
     }
+
+    public boolean isVIP() {
+        return false;
+    }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Node.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Node.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -90,8 +90,8 @@
     protected Node(Graph<N, E> graph, N data) {
         setData(data);
         this.graph = graph;
-        inEdges = new ArrayList<Edge<N, E>>();
-        outEdges = new ArrayList<Edge<N, E>>();
+        inEdges = new ArrayList<>();
+        outEdges = new ArrayList<>();
     }
 
     protected void addInEdge(Edge<N, E> e) {
@@ -125,7 +125,7 @@
     }
 
     public List<Node<N, E>> getSuccessors() {
-        ArrayList<Node<N, E>> succ = new ArrayList<Node<N, E>>();
+        ArrayList<Node<N, E>> succ = new ArrayList<>();
         for (Edge<N, E> e : getOutEdges()) {
             Node<N, E> n = e.getDest();
             if (!succ.contains(n)) {
@@ -136,7 +136,7 @@
     }
 
     public List<Node<N, E>> getPredecessors() {
-        ArrayList<Node<N, E>> pred = new ArrayList<Node<N, E>>();
+        ArrayList<Node<N, E>> pred = new ArrayList<>();
         for (Edge<N, E> e : getInEdges()) {
             Node<N, E> n = e.getSource();
             if (!pred.contains(n)) {
--- a/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/OldHierarchicalLayoutManager.java	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1222 +0,0 @@
-/*
- * 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 java.awt.Point;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-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 OldHierarchicalLayoutManager implements LayoutManager {
-
-    public static final int DUMMY_WIDTH = 0;
-    public static final int DUMMY_HEIGHT = 0;
-    public static final int LAYER_OFFSET = 50;
-    public static final int OFFSET = 8;
-    public static final boolean VERTICAL_LAYOUT = true;
-    public static final boolean ASSERT = false;
-    public static final boolean TRACE = false;
-    public static final Timing initTiming = new Timing("init");
-    public static final Timing removeCyclesTiming = new Timing("removeCycles");
-    public static final Timing reversedEdgesTiming = new Timing("reversedEdges");
-    public static final Timing assignLayersTiming = new Timing("assignLayers");
-    public static final Timing dummyNodesTiming = new Timing("dummyNodes");
-    public static final Timing crossingReductionTiming = new Timing("crossingReduction");
-    public static final Timing assignCoordinatesTiming = new Timing("assignCoordinates");
-    public static final Timing assignRealTiming = new Timing("assignReal");
-    public static final Timing rootVertexTiming = new Timing("rootVertex");
-    public static final Timing createEdgesTiming = new Timing("createEdges");
-    public static final Timing optimizeMedianTiming = new Timing("optimizeMedian");
-    private Combine combine;
-
-    public enum Combine {
-
-        NONE,
-        SAME_INPUTS,
-        SAME_OUTPUTS
-    }
-
-    private class NodeData {
-
-        private Map<Port, Integer> reversePositions;
-        private Vertex node;
-        private Link edge;
-        private int layer;
-        private int x;
-        private int y;
-        private int width;
-
-        public NodeData(Vertex node) {
-            reversePositions = new HashMap<Port, Integer>();
-            layer = -1;
-            this.node = node;
-            assert node != null;
-
-            if (VERTICAL_LAYOUT) {
-                width = node.getSize().width;
-            } else {
-                width = node.getSize().height;
-            }
-        }
-
-        public NodeData(Link edge) {
-            layer = -1;
-            this.edge = edge;
-            assert edge != null;
-
-            if (VERTICAL_LAYOUT) {
-                width = DUMMY_WIDTH;
-            } else {
-                width = DUMMY_HEIGHT;
-            }
-        }
-
-        public Vertex getNode() {
-            return node;
-        }
-
-        public Link getEdge() {
-            return edge;
-        }
-
-        public int getCoordinate() {
-            return x;
-        }
-
-        public void setCoordinate(int x) {
-            this.x = x;
-        }
-
-        public int getX() {
-            if (VERTICAL_LAYOUT) {
-                return x;
-            } else {
-                return y;
-            }
-        }
-
-        public int getY() {
-            if (VERTICAL_LAYOUT) {
-                return y;
-            } else {
-                return x;
-            }
-        }
-
-        public void setLayerCoordinate(int y) {
-            this.y = y;
-        }
-
-        public void setLayer(int x) {
-            layer = x;
-        }
-
-        public int getLayer() {
-            return layer;
-        }
-
-        public boolean isDummy() {
-            return edge != null;
-        }
-
-        public int getWidth() {
-            return width;
-        }
-
-        public void addReversedStartEdge(Edge<NodeData, EdgeData> e) {
-            assert e.getData().isReversed();
-            Port port = e.getData().getEdge().getTo();
-            int pos = addReversedPort(port);
-            Point start = e.getData().getRelativeStart();
-            e.getData().addStartPoint(start);
-            int yCoord = node.getSize().height + width - node.getSize().width;
-            e.getData().addStartPoint(new Point(start.x, yCoord));
-            e.getData().addStartPoint(new Point(pos, yCoord));
-            e.getData().setRelativeStart(new Point(pos, 0));
-        }
-
-        private int addReversedPort(Port p) {
-            if (reversePositions.containsKey(p)) {
-                return reversePositions.get(p);
-            } else {
-                width += OFFSET;
-                reversePositions.put(p, width);
-                return width;
-            }
-        }
-
-        public void addReversedEndEdge(Edge<NodeData, EdgeData> e) {
-            assert e.getData().isReversed();
-            int pos = addReversedPort(e.getData().getEdge().getFrom());
-            Point end = e.getData().getRelativeEnd();
-            e.getData().setRelativeEnd(new Point(pos, node.getSize().height));
-            int yCoord = 0 - width + node.getSize().width;
-            e.getData().addEndPoint(new Point(pos, yCoord));
-            e.getData().addEndPoint(new Point(end.x, yCoord));
-            e.getData().addEndPoint(end);
-        }
-
-        public int getHeight() {
-            if (isDummy()) {
-                if (VERTICAL_LAYOUT) {
-                    return DUMMY_HEIGHT;
-                } else {
-                    return DUMMY_WIDTH;
-                }
-
-            } else {
-                if (VERTICAL_LAYOUT) {
-                    return node.getSize().height;
-                } else {
-                    return node.getSize().width;
-                }
-            }
-        }
-
-        @Override
-        public String toString() {
-            if (isDummy()) {
-                return edge.toString() + "(layer=" + layer + ")";
-            } else {
-                return node.toString() + "(layer=" + layer + ")";
-            }
-        }
-    }
-
-    private class EdgeData {
-
-        private Point relativeEnd;
-        private Point relativeStart;
-        private List<Point> startPoints;
-        private List<Point> endPoints;
-        private boolean important;
-        private boolean reversed;
-        private Link edge;
-
-        public EdgeData(Link edge) {
-            this(edge, false);
-        }
-
-        public EdgeData(Link edge, boolean rev) {
-            this.edge = edge;
-            reversed = rev;
-            relativeStart = edge.getFrom().getRelativePosition();
-            relativeEnd = edge.getTo().getRelativePosition();
-            assert relativeStart.x >= 0 && relativeStart.x <= edge.getFrom().getVertex().getSize().width;
-            assert relativeStart.y >= 0 && relativeStart.y <= edge.getFrom().getVertex().getSize().height;
-            assert relativeEnd.x >= 0 && relativeEnd.x <= edge.getTo().getVertex().getSize().width;
-            assert relativeEnd.y >= 0 && relativeEnd.y <= edge.getTo().getVertex().getSize().height;
-            startPoints = new ArrayList<Point>();
-            endPoints = new ArrayList<Point>();
-            this.important = true;
-        }
-
-        public boolean isImportant() {
-            return important;
-        }
-
-        public void setImportant(boolean b) {
-            this.important = b;
-        }
-
-        public List<Point> getStartPoints() {
-            return startPoints;
-        }
-
-        public List<Point> getEndPoints() {
-            return endPoints;
-        }
-
-        public List<Point> getAbsoluteEndPoints() {
-            if (endPoints.size() == 0) {
-                return endPoints;
-            }
-
-            List<Point> result = new ArrayList<Point>();
-            Point point = edge.getTo().getVertex().getPosition();
-            for (Point p : endPoints) {
-                Point p2 = new Point(p.x + point.x, p.y + point.y);
-                result.add(p2);
-            }
-
-            return result;
-        }
-
-        public List<Point> getAbsoluteStartPoints() {
-            if (startPoints.size() == 0) {
-                return startPoints;
-            }
-
-            List<Point> result = new ArrayList<Point>();
-            Point point = edge.getFrom().getVertex().getPosition();
-            for (Point p : startPoints) {
-                Point p2 = new Point(p.x + point.x, p.y + point.y);
-                result.add(p2);
-            }
-
-            return result;
-        }
-
-        public void addEndPoint(Point p) {
-            endPoints.add(p);
-        }
-
-        public void addStartPoint(Point p) {
-            startPoints.add(p);
-        }
-
-        public Link getEdge() {
-            return edge;
-        }
-
-        public void setRelativeEnd(Point p) {
-            relativeEnd = p;
-        }
-
-        public void setRelativeStart(Point p) {
-            relativeStart = p;
-        }
-
-        public Point getRelativeEnd() {
-            return relativeEnd;
-        }
-
-        public Point getRelativeStart() {
-            return relativeStart;
-        }
-
-        public boolean isReversed() {
-            return reversed;
-        }
-
-        public void setReversed(boolean b) {
-            reversed = b;
-        }
-
-        @Override
-        public String toString() {
-            return "EdgeData[reversed=" + reversed + "]";
-        }
-    }
-    private Graph<NodeData, EdgeData> graph;
-    private Map<Vertex, Node<NodeData, EdgeData>> nodeMap;
-    private int layerOffset;
-
-    /** Creates a new instance of HierarchicalPositionManager */
-    public OldHierarchicalLayoutManager(Combine combine) {
-        this(combine, LAYER_OFFSET);
-    }
-
-    public OldHierarchicalLayoutManager(Combine combine, int layerOffset) {
-        this.combine = combine;
-        this.layerOffset = layerOffset;
-    }
-
-    public void doRouting(LayoutGraph graph) {
-    }
-
-    //public void setPositions(PositionedNode rootNode, List<? extends PositionedNode> nodes, List<? extends PositionedEdge> edges) {
-    public void doLayout(LayoutGraph layoutGraph) {
-        doLayout(layoutGraph, new HashSet<Vertex>(), new HashSet<Vertex>());
-    }
-
-    public void doLayout(LayoutGraph layoutGraph, Set<? extends Vertex> firstLayerHint, Set<? extends Vertex> lastLayerHint) {
-        doLayout(layoutGraph, firstLayerHint, lastLayerHint, new HashSet<Link>());
-    }
-
-    public void doLayout(LayoutGraph layoutGraph, Set<? extends Vertex> firstLayerHint, Set<? extends Vertex> lastLayerHint, Set<? extends Link> importantLinksHint) {
-
-        if (TRACE) {
-            System.out.println("HierarchicalPositionManager.doLayout called");
-            System.out.println("Vertex count = " + layoutGraph.getVertices().size() + " Link count = " + layoutGraph.getLinks().size());
-        }
-
-        // Nothing to do => quit immediately
-        if (layoutGraph.getVertices().size() == 0) {
-            return;
-        }
-
-        initTiming.start();
-
-        // Mapping vertex to Node in graph
-        nodeMap = new HashMap<Vertex, Node<NodeData, EdgeData>>();
-
-        graph = new Graph<NodeData, EdgeData>();
-
-        Set<Node<NodeData, EdgeData>> rootNodes = new HashSet<Node<NodeData, EdgeData>>();
-        Set<Vertex> startRootVertices = new HashSet<Vertex>();
-
-        for (Vertex v : layoutGraph.getVertices()) {
-            if (v.isRoot()) {
-                startRootVertices.add(v);
-            }
-        }
-
-        rootVertexTiming.start();
-        Set<Vertex> rootVertices = layoutGraph.findRootVertices(startRootVertices);
-        rootVertexTiming.stop();
-
-
-        for (Vertex node : layoutGraph.getVertices()) {
-
-            NodeData data = new NodeData(node);
-            Node<NodeData, EdgeData> n = graph.createNode(data, node);
-            nodeMap.put(node, n);
-
-            if (rootVertices.contains(node)) {
-                rootNodes.add(n);
-            }
-        }
-
-        Set<? extends Link> links = layoutGraph.getLinks();
-        Link[] linkArr = new Link[links.size()];
-        links.toArray(linkArr);
-
-        List<Link> linkList = new ArrayList<Link>();
-        for (Link l : linkArr) {
-            linkList.add(l);
-        }
-
-        createEdgesTiming.start();
-        Collections.sort(linkList, new Comparator<Link>() {
-
-            public int compare(Link o1, Link o2) {
-                int result = o1.getFrom().getVertex().compareTo(o2.getFrom().getVertex());
-                if (result == 0) {
-                    return o1.getTo().getVertex().compareTo(o2.getTo().getVertex());
-                } else {
-                    return result;
-                }
-            }
-        });
-
-        for (Link edge : linkList) {
-            EdgeData data = new EdgeData(edge);
-            graph.createEdge(graph.getNode(edge.getFrom().getVertex()), graph.getNode(edge.getTo().getVertex()), data, data);
-            if (importantLinksHint.size() > 0 && !importantLinksHint.contains(edge)) {
-                data.setImportant(false);
-            }
-        }
-        createEdgesTiming.stop();
-
-        initTiming.stop();
-
-        removeCyclesTiming.start();
-
-        // STEP 1: Remove cycles!
-        removeCycles(rootNodes);
-        if (ASSERT) {
-            assert checkRemoveCycles();
-        }
-
-        removeCyclesTiming.stop();
-
-        reversedEdgesTiming.start();
-
-        for (Node<NodeData, EdgeData> n : graph.getNodes()) {
-            List<Edge<NodeData, EdgeData>> edges = new ArrayList<Edge<NodeData, EdgeData>>(n.getOutEdges());
-            Collections.sort(edges, new Comparator<Edge<NodeData, EdgeData>>() {
-
-                public int compare(Edge<NodeData, EdgeData> o1, Edge<NodeData, EdgeData> o2) {
-                    return o2.getData().getRelativeEnd().x - o1.getData().getRelativeEnd().x;
-                }
-            });
-
-
-            for (Edge<NodeData, EdgeData> e : edges) {
-
-                if (e.getData().isReversed()) {
-                    e.getSource().getData().addReversedEndEdge(e);
-                }
-            }
-        }
-
-        for (Node<NodeData, EdgeData> n : graph.getNodes()) {
-            List<Edge<NodeData, EdgeData>> edges = new ArrayList<Edge<NodeData, EdgeData>>(n.getInEdges());
-            Collections.sort(edges, new Comparator<Edge<NodeData, EdgeData>>() {
-
-                public int compare(Edge<NodeData, EdgeData> o1, Edge<NodeData, EdgeData> o2) {
-                    return o2.getData().getRelativeStart().x - o1.getData().getRelativeStart().x;
-                }
-            });
-
-
-            for (Edge<NodeData, EdgeData> e : edges) {
-                if (e.getData().isReversed()) {
-                    e.getDest().getData().addReversedStartEdge(e);
-                }
-            }
-        }
-
-        reversedEdgesTiming.stop();
-
-        assignLayersTiming.start();
-        // STEP 2: Assign layers!
-        int maxLayer = assignLayers(rootNodes, firstLayerHint, lastLayerHint);
-        if (ASSERT) {
-            assert checkAssignLayers();
-        }
-
-        // Put into layer array
-        //int maxLayer = 0;
-        //for(Node<NodeData, EdgeData> n : graph.getNodes()) {
-        //    maxLayer = Math.max(maxLayer, n.getData().getLayer());
-        //}
-
-
-        ArrayList<Node<NodeData, EdgeData>> layers[] = new ArrayList[maxLayer + 1];
-        int layerSizes[] = new int[maxLayer + 1];
-        for (int i = 0; i < maxLayer + 1; i++) {
-            layers[i] = new ArrayList<Node<NodeData, EdgeData>>();
-        }
-
-        for (Node<NodeData, EdgeData> n : graph.getNodes()) {
-            int curLayer = n.getData().getLayer();
-            layers[curLayer].add(n);
-        }
-
-        assignLayersTiming.stop();
-
-        // STEP 3: Insert dummy nodes!
-        dummyNodesTiming.start();
-        insertDummyNodes(layers);
-        if (ASSERT) {
-            assert checkDummyNodes();
-        }
-        dummyNodesTiming.stop();
-
-        crossingReductionTiming.start();
-        // STEP 4: Assign Y coordinates
-        assignLayerCoordinates(layers, layerSizes);
-
-        // STEP 5: Crossing reduction
-        crossingReduction(layers);
-        crossingReductionTiming.stop();
-
-        // STEP 6: Assign Y coordinates
-        assignCoordinatesTiming.start();
-        assignCoordinates(layers);
-        assignCoordinatesTiming.stop();
-
-        assignRealTiming.start();
-
-        // Assign coordinates of nodes to real objects
-        for (Node<NodeData, EdgeData> n : graph.getNodes()) {
-            if (!n.getData().isDummy()) {
-
-                Vertex node = n.getData().getNode();
-                node.setPosition(new Point(n.getData().getX(), n.getData().getY()));
-            }
-        }
-
-        for (Node<NodeData, EdgeData> n : graph.getNodes()) {
-            if (!n.getData().isDummy()) {
-
-                Vertex node = n.getData().getNode();
-
-                List<Edge<NodeData, EdgeData>> outEdges = n.getOutEdges();
-                for (Edge<NodeData, EdgeData> e : outEdges) {
-                    Node<NodeData, EdgeData> succ = e.getDest();
-                    if (succ.getData().isDummy()) {
-                        //PositionedEdge edge = succ.getData().getEdge();
-                        List<Point> points = new ArrayList<Point>();
-                        assignToRealObjects(layerSizes, succ, points);
-                    } else {
-                        List<Point> points = new ArrayList<Point>();
-
-                        EdgeData otherEdgeData = e.getData();
-                        points.addAll(otherEdgeData.getAbsoluteStartPoints());
-                        Link otherEdge = otherEdgeData.getEdge();
-                        Point relFrom = new Point(otherEdgeData.getRelativeStart());
-                        Point from = otherEdge.getFrom().getVertex().getPosition();
-                        relFrom.move(relFrom.x + from.x, relFrom.y + from.y);
-                        points.add(relFrom);
-
-                        Point relTo = new Point(otherEdgeData.getRelativeEnd());
-                        Point to = otherEdge.getTo().getVertex().getPosition();
-                        relTo.move(relTo.x + to.x, relTo.y + to.y);
-                        assert from != null;
-                        assert to != null;
-                        points.add(relTo);
-                        points.addAll(otherEdgeData.getAbsoluteEndPoints());
-                        e.getData().getEdge().setControlPoints(points);
-                    }
-                }
-            }
-        }
-
-        assignRealTiming.stop();
-
-        initTiming.print();
-        removeCyclesTiming.print();
-        reversedEdgesTiming.print();
-        assignLayersTiming.print();
-        dummyNodesTiming.print();
-        crossingReductionTiming.print();
-        assignCoordinatesTiming.print();
-        assignRealTiming.print();
-        rootVertexTiming.print();
-        createEdgesTiming.print();
-        optimizeMedianTiming.print();
-    }
-
-    public boolean onOneLine(Point p1, Point p2, Point p3) {
-        int xoff1 = p1.x - p2.x;
-        int yoff1 = p1.y - p2.y;
-        int xoff2 = p3.x - p2.x;
-        int yoff2 = p3.y - p2.x;
-
-        return (xoff1 * yoff2 - yoff1 * xoff2 == 0);
-    }
-
-    private void assignToRealObjects(int layerSizes[], Node<NodeData, EdgeData> cur, List<Point> points) {
-        assert cur.getData().isDummy();
-
-        ArrayList<Point> otherPoints = new ArrayList<Point>(points);
-
-        int size = layerSizes[cur.getData().getLayer()];
-        otherPoints.add(new Point(cur.getData().getX(), cur.getData().getY() - size / 2));
-        if (otherPoints.size() >= 3 && onOneLine(otherPoints.get(otherPoints.size() - 1), otherPoints.get(otherPoints.size() - 2), otherPoints.get(otherPoints.size() - 3))) {
-            otherPoints.remove(otherPoints.size() - 2);
-        }
-        otherPoints.add(new Point(cur.getData().getX(), cur.getData().getY() + size / 2));
-        if (otherPoints.size() >= 3 && onOneLine(otherPoints.get(otherPoints.size() - 1), otherPoints.get(otherPoints.size() - 2), otherPoints.get(otherPoints.size() - 3))) {
-            otherPoints.remove(otherPoints.size() - 2);
-        }
-
-        for (int i = 0; i < cur.getOutEdges().size(); i++) {
-            Node<NodeData, EdgeData> otherSucc = cur.getOutEdges().get(i).getDest();
-
-            if (otherSucc.getData().isDummy()) {
-                assignToRealObjects(layerSizes, otherSucc, otherPoints);
-            } else {
-                EdgeData otherEdgeData = cur.getOutEdges().get(i).getData();
-                Link otherEdge = otherEdgeData.getEdge();
-
-                List<Point> middlePoints = new ArrayList<Point>(otherPoints);
-                if (cur.getOutEdges().get(i).getData().isReversed()) {
-                    Collections.reverse(middlePoints);
-                }
-
-                ArrayList<Point> copy = new ArrayList<Point>();
-                Point relFrom = new Point(otherEdgeData.getRelativeStart());
-                Point from = otherEdge.getFrom().getVertex().getPosition();
-                //int moveUp = (size - otherEdge.getFrom().getVertex().getSize().height) / 2;
-                relFrom.move(relFrom.x + from.x, relFrom.y + from.y);
-                copy.addAll(otherEdgeData.getAbsoluteStartPoints());
-                copy.add(relFrom);
-                copy.addAll(middlePoints);
-
-                Point relTo = new Point(otherEdgeData.getRelativeEnd());
-                Point to = otherEdge.getTo().getVertex().getPosition();
-                relTo.move(relTo.x + to.x, relTo.y + to.y);
-                copy.add(relTo);
-
-                copy.addAll(otherEdgeData.getAbsoluteEndPoints());
-
-
-                otherEdge.setControlPoints(copy);
-            }
-        }
-    }
-
-    private boolean checkDummyNodes() {
-        for (Edge<NodeData, EdgeData> e : graph.getEdges()) {
-            if (e.getSource().getData().getLayer() != e.getDest().getData().getLayer() - 1) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    private void insertDummyNodes(ArrayList<Node<NodeData, EdgeData>> layers[]) {
-
-        int sum = 0;
-        List<Node<NodeData, EdgeData>> nodes = new ArrayList<Node<NodeData, EdgeData>>(graph.getNodes());
-        int edgeCount = 0;
-        int innerMostLoop = 0;
-
-        for (Node<NodeData, EdgeData> n : nodes) {
-            List<Edge<NodeData, EdgeData>> edges = new ArrayList<Edge<NodeData, EdgeData>>(n.getOutEdges());
-            for (Edge<NodeData, EdgeData> e : edges) {
-
-                edgeCount++;
-                Link edge = e.getData().getEdge();
-                Node<NodeData, EdgeData> destNode = e.getDest();
-                Node<NodeData, EdgeData> lastNode = n;
-                Edge<NodeData, EdgeData> lastEdge = e;
-
-                boolean searchForNode = (combine != Combine.NONE);
-                for (int i = n.getData().getLayer() + 1; i < destNode.getData().getLayer(); i++) {
-
-                    Node<NodeData, EdgeData> foundNode = null;
-                    if (searchForNode) {
-                        for (Node<NodeData, EdgeData> sameLayerNode : layers[i]) {
-                            innerMostLoop++;
-
-                            if (combine == Combine.SAME_OUTPUTS) {
-                                if (sameLayerNode.getData().isDummy() && sameLayerNode.getData().getEdge().getFrom() == edge.getFrom()) {
-                                    foundNode = sameLayerNode;
-                                    break;
-                                }
-                            } else if (combine == Combine.SAME_INPUTS) {
-                                if (sameLayerNode.getData().isDummy() && sameLayerNode.getData().getEdge().getTo() == edge.getTo()) {
-                                    foundNode = sameLayerNode;
-                                    break;
-                                }
-                            }
-                        }
-                    }
-
-                    if (foundNode == null) {
-                        searchForNode = false;
-                        NodeData intermediateData = new NodeData(edge);
-                        Node<NodeData, EdgeData> curNode = graph.createNode(intermediateData, null);
-                        curNode.getData().setLayer(i);
-                        layers[i].add(0, curNode);
-                        sum++;
-                        lastEdge.remove();
-                        graph.createEdge(lastNode, curNode, e.getData(), null);
-                        assert lastNode.getData().getLayer() == curNode.getData().getLayer() - 1;
-                        lastEdge = graph.createEdge(curNode, destNode, e.getData(), null);
-                        lastNode = curNode;
-                    } else {
-                        lastEdge.remove();
-                        lastEdge = graph.createEdge(foundNode, destNode, e.getData(), null);
-                        lastNode = foundNode;
-                    }
-
-                }
-            }
-        }
-
-        if (TRACE) {
-            System.out.println("Number of edges: " + edgeCount);
-        }
-        if (TRACE) {
-            System.out.println("Dummy nodes inserted: " + sum);
-        }
-    }
-
-    private void assignLayerCoordinates(ArrayList<Node<NodeData, EdgeData>> layers[], int layerSizes[]) {
-        int cur = 0;
-        for (int i = 0; i < layers.length; i++) {
-            int maxHeight = 0;
-            for (Node<NodeData, EdgeData> n : layers[i]) {
-                maxHeight = Math.max(maxHeight, n.getData().getHeight());
-            }
-
-            layerSizes[i] = maxHeight;
-            for (Node<NodeData, EdgeData> n : layers[i]) {
-                int curCoordinate = cur + (maxHeight - n.getData().getHeight()) / 2;
-                n.getData().setLayerCoordinate(curCoordinate);
-            }
-            cur += maxHeight + layerOffset;
-
-        }
-    }
-
-    private void assignCoordinates(ArrayList<Node<NodeData, EdgeData>> layers[]) {
-
-        // TODO: change this
-        for (int i = 0; i < layers.length; i++) {
-            ArrayList<Node<NodeData, EdgeData>> curArray = layers[i];
-            int curY = 0;
-            for (Node<NodeData, EdgeData> n : curArray) {
-
-                n.getData().setCoordinate(curY);
-                if (!n.getData().isDummy()) {
-                    curY += n.getData().getWidth();
-                }
-                curY += OFFSET;
-
-            }
-        }
-
-        int curSol = evaluateSolution();
-        if (TRACE) {
-            System.out.println("First coordinate solution found: " + curSol);
-        }
-
-        // Sort to correct order
-        for (int i = 0; i < layers.length; i++) {
-            Collections.sort(layers[i], new Comparator<Node<NodeData, EdgeData>>() {
-
-                public int compare(Node<NodeData, EdgeData> o1, Node<NodeData, EdgeData> o2) {
-                    if (o2.getData().isDummy()) {
-                        return 1;
-                    } else if (o1.getData().isDummy()) {
-                        return -1;
-                    }
-                    return o2.getInEdges().size() + o2.getOutEdges().size() - o1.getInEdges().size() - o1.getOutEdges().size();
-                }
-            });
-        }
-
-
-        optimizeMedianTiming.start();
-        for (int i = 0; i < 2; i++) {
-            optimizeMedian(layers);
-            curSol = evaluateSolution();
-            if (TRACE) {
-                System.out.println("Current coordinate solution found: " + curSol);
-            }
-        }
-        optimizeMedianTiming.stop();
-        normalizeCoordinate();
-
-    }
-
-    private void normalizeCoordinate() {
-
-        int min = Integer.MAX_VALUE;
-        for (Node<NodeData, EdgeData> n : graph.getNodes()) {
-            min = Math.min(min, n.getData().getCoordinate());
-        }
-
-        for (Node<NodeData, EdgeData> n : graph.getNodes()) {
-            n.getData().setCoordinate(n.getData().getCoordinate() - min);
-        }
-
-    }
-
-    private void optimizeMedian(ArrayList<Node<NodeData, EdgeData>> layers[]) {
-
-        // Downsweep
-        for (int i = 1; i < layers.length; i++) {
-
-            ArrayList<Node<NodeData, EdgeData>> processingList = layers[i];
-            ArrayList<Node<NodeData, EdgeData>> alreadyAssigned = new ArrayList<Node<NodeData, EdgeData>>();
-            for (Node<NodeData, EdgeData> n : processingList) {
-
-
-                ArrayList<Node<NodeData, EdgeData>> preds = new ArrayList<Node<NodeData, EdgeData>>(n.getPredecessors());
-                int pos = n.getData().getCoordinate();
-                if (preds.size() > 0) {
-
-                    Collections.sort(preds, new Comparator<Node<NodeData, EdgeData>>() {
-
-                        public int compare(Node<NodeData, EdgeData> o1, Node<NodeData, EdgeData> o2) {
-                            return o1.getData().getCoordinate() - o2.getData().getCoordinate();
-                        }
-                    });
-
-                    if (preds.size() % 2 == 0) {
-                        assert preds.size() >= 2;
-                        pos = (preds.get(preds.size() / 2).getData().getCoordinate() - calcRelativeCoordinate(preds.get(preds.size() / 2), n) + preds.get(preds.size() / 2 - 1).getData().getCoordinate() - calcRelativeCoordinate(preds.get(preds.size() / 2 - 1), n)) / 2;
-                    } else {
-                        assert preds.size() >= 1;
-                        pos = preds.get(preds.size() / 2).getData().getCoordinate() - calcRelativeCoordinate(preds.get(preds.size() / 2), n);
-                    }
-                }
-
-                tryAdding(alreadyAssigned, n, pos);
-            }
-        }
-        // Upsweep
-        for (int i = layers.length - 2; i >= 0; i--) {
-            ArrayList<Node<NodeData, EdgeData>> processingList = layers[i];
-            ArrayList<Node<NodeData, EdgeData>> alreadyAssigned = new ArrayList<Node<NodeData, EdgeData>>();
-            for (Node<NodeData, EdgeData> n : processingList) {
-
-                ArrayList<Node<NodeData, EdgeData>> succs = new ArrayList<Node<NodeData, EdgeData>>(n.getSuccessors());
-                int pos = n.getData().getCoordinate();
-                if (succs.size() > 0) {
-
-                    Collections.sort(succs, new Comparator<Node<NodeData, EdgeData>>() {
-
-                        public int compare(Node<NodeData, EdgeData> o1, Node<NodeData, EdgeData> o2) {
-                            return o1.getData().getCoordinate() - o2.getData().getCoordinate();
-                        }
-                    });
-
-                    if (succs.size() % 2 == 0) {
-                        assert succs.size() >= 2;
-                        pos = (succs.get(succs.size() / 2).getData().getCoordinate() - calcRelativeCoordinate(n, succs.get(succs.size() / 2)) + succs.get(succs.size() / 2 - 1).getData().getCoordinate() - calcRelativeCoordinate(n, succs.get(succs.size() / 2 - 1))) / 2;
-                    } else {
-                        assert succs.size() >= 1;
-                        pos = succs.get(succs.size() / 2).getData().getCoordinate() - calcRelativeCoordinate(n, succs.get(succs.size() / 2));
-                    }
-                }
-
-                tryAdding(alreadyAssigned, n, pos);
-            }
-        }
-    }
-
-    private int median(ArrayList<Integer> arr) {
-        assert arr.size() > 0;
-        Collections.sort(arr);
-        if (arr.size() % 2 == 0) {
-            return (arr.get(arr.size() / 2) + arr.get(arr.size() / 2 - 1)) / 2;
-        } else {
-            return arr.get(arr.size() / 2);
-        }
-    }
-
-    private int calcRelativeCoordinate(Node<NodeData, EdgeData> n, Node<NodeData, EdgeData> succ) {
-
-        if (n.getData().isDummy() && succ.getData().isDummy()) {
-            return 0;
-        }
-
-        int pos = 0;
-        int pos2 = 0;
-        ArrayList<Integer> coords2 = new ArrayList<Integer>();
-        ArrayList<Integer> coords = new ArrayList<Integer>();
-        /*if(!n.getData().isDummy())*/ {
-            for (Edge<NodeData, EdgeData> e : n.getOutEdges()) {
-
-                //System.out.println("reversed: " + e.getData().isReversed());
-                if (e.getDest() == succ) {
-
-                    if (e.getData().isReversed()) {
-                        if (!n.getData().isDummy()) {
-                            coords.add(e.getData().getRelativeEnd().x);
-                        }
-
-                        if (!succ.getData().isDummy()) {
-                            coords2.add(e.getData().getRelativeStart().x);
-                        }
-                    } else {
-                        if (!n.getData().isDummy()) {
-                            coords.add(e.getData().getRelativeStart().x);
-                        }
-
-                        if (!succ.getData().isDummy()) {
-                            coords2.add(e.getData().getRelativeEnd().x);
-                        }
-                    }
-                }
-            }
-
-            // assert coords.size() > 0;
-            if (!n.getData().isDummy()) {
-                pos = median(coords);
-            }
-
-            if (!succ.getData().isDummy()) {
-                pos2 = median(coords2);
-            }
-        }
-        //System.out.println("coords=" + coords);
-        //System.out.println("coords2=" + coords2);
-
-        return pos - pos2;
-    }
-
-    private boolean intersect(int v1, int w1, int v2, int w2) {
-        if (v1 >= v2 && v1 < v2 + w2) {
-            return true;
-        }
-        if (v1 + w1 > v2 && v1 + w1 < v2 + w2) {
-            return true;
-        }
-        if (v1 < v2 && v1 + w1 > v2) {
-            return true;
-        }
-        return false;
-    }
-
-    private boolean intersect(Node<NodeData, EdgeData> n1, Node<NodeData, EdgeData> n2) {
-        return intersect(n1.getData().getCoordinate(), n1.getData().getWidth() + OFFSET, n2.getData().getCoordinate(), n2.getData().getWidth() + OFFSET);
-    }
-
-    private void tryAdding(List<Node<NodeData, EdgeData>> alreadyAssigned, Node<NodeData, EdgeData> node, int pos) {
-
-        boolean doesIntersect = false;
-        node.getData().setCoordinate(pos);
-        for (Node<NodeData, EdgeData> n : alreadyAssigned) {
-            if (n.getData().getCoordinate() + n.getData().getWidth() < pos) {
-                break;
-            } else if (intersect(node, n)) {
-                doesIntersect = true;
-                break;
-            }
-
-        }
-
-        if (!doesIntersect) {
-
-            // Everything fine, just place the node
-            int z = 0;
-            for (Node<NodeData, EdgeData> n : alreadyAssigned) {
-                if (pos > n.getData().getCoordinate()) {
-                    break;
-                }
-                z++;
-            }
-
-            if (z == -1) {
-                z = alreadyAssigned.size();
-            }
-
-
-            if (ASSERT) {
-                assert !findOverlap(alreadyAssigned, node);
-            }
-            alreadyAssigned.add(z, node);
-
-        } else {
-
-            assert alreadyAssigned.size() > 0;
-
-            // Search for alternative location
-            int minOffset = Integer.MAX_VALUE;
-            int minIndex = -1;
-            int minPos = 0;
-            int w = node.getData().getWidth() + OFFSET;
-
-            // Try top-most
-            minIndex = 0;
-            minPos = alreadyAssigned.get(0).getData().getCoordinate() + alreadyAssigned.get(0).getData().getWidth() + OFFSET;
-            minOffset = Math.abs(minPos - pos);
-
-            // Try bottom-most
-            Node<NodeData, EdgeData> lastNode = alreadyAssigned.get(alreadyAssigned.size() - 1);
-            int lastPos = lastNode.getData().getCoordinate() - w;
-            int lastOffset = Math.abs(lastPos - pos);
-            if (lastOffset < minOffset) {
-                minPos = lastPos;
-                minOffset = lastOffset;
-                minIndex = alreadyAssigned.size();
-            }
-
-            // Try between
-            for (int i = 0; i < alreadyAssigned.size() - 1; i++) {
-                Node<NodeData, EdgeData> curNode = alreadyAssigned.get(i);
-                Node<NodeData, EdgeData> nextNode = alreadyAssigned.get(i + 1);
-
-                int start = nextNode.getData().getCoordinate() + nextNode.getData().getWidth() + OFFSET;
-                int end = curNode.getData().getCoordinate() - OFFSET;
-
-                int bestPoss = end - node.getData().getWidth();
-                if (bestPoss < pos && pos - bestPoss > minOffset) {
-                    // No better solution possible => break
-                    break;
-                }
-
-                if (end - start >= node.getData().getWidth()) {
-                    // Node could fit here
-                    int cand1 = start;
-                    int cand2 = end - node.getData().getWidth();
-                    int off1 = Math.abs(cand1 - pos);
-                    int off2 = Math.abs(cand2 - pos);
-                    if (off1 < minOffset) {
-                        minPos = cand1;
-                        minOffset = off1;
-                        minIndex = i + 1;
-                    }
-
-                    if (off2 < minOffset) {
-                        minPos = cand2;
-                        minOffset = off2;
-                        minIndex = i + 1;
-                    }
-                }
-            }
-
-            assert minIndex != -1;
-            node.getData().setCoordinate(minPos);
-            if (ASSERT) {
-                assert !findOverlap(alreadyAssigned, node);
-            }
-            alreadyAssigned.add(minIndex, node);
-        }
-
-    }
-
-    private boolean findOverlap(List<Node<NodeData, EdgeData>> nodes, Node<NodeData, EdgeData> node) {
-
-        for (Node<NodeData, EdgeData> n1 : nodes) {
-            if (intersect(n1, node)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    private int evaluateSolution() {
-
-        int sum = 0;
-        for (Edge<NodeData, EdgeData> e : graph.getEdges()) {
-            Node<NodeData, EdgeData> source = e.getSource();
-            Node<NodeData, EdgeData> dest = e.getDest();
-            int offset = 0;
-            offset = Math.abs(source.getData().getCoordinate() - dest.getData().getCoordinate());
-            sum += offset;
-        }
-
-        return sum;
-    }
-
-    private void crossingReduction(ArrayList<Node<NodeData, EdgeData>> layers[]) {
-
-        for (int i = 0; i < layers.length - 1; i++) {
-
-            ArrayList<Node<NodeData, EdgeData>> curNodes = layers[i];
-            ArrayList<Node<NodeData, EdgeData>> nextNodes = layers[i + 1];
-            for (Node<NodeData, EdgeData> n : curNodes) {
-                for (Node<NodeData, EdgeData> succ : n.getSuccessors()) {
-                    if (ASSERT) {
-                        assert nextNodes.contains(succ);
-                    }
-                    nextNodes.remove(succ);
-                    nextNodes.add(succ);
-                }
-            }
-
-        }
-
-    }
-
-    private void removeCycles(Set<Node<NodeData, EdgeData>> rootNodes) {
-        final List<Edge<NodeData, EdgeData>> reversedEdges = new ArrayList<Edge<NodeData, EdgeData>>();
-
-
-        int removedCount = 0;
-        int reversedCount = 0;
-
-        Graph.DFSTraversalVisitor visitor = graph.new DFSTraversalVisitor() {
-
-            @Override
-            public boolean visitEdge(Edge<NodeData, EdgeData> e, boolean backEdge) {
-                if (backEdge) {
-                    if (ASSERT) {
-                        assert !reversedEdges.contains(e);
-                    }
-                    reversedEdges.add(e);
-                    e.getData().setReversed(!e.getData().isReversed());
-                }
-
-                return e.getData().isImportant();
-            }
-        };
-        Set<Node<NodeData, EdgeData>> nodes = new HashSet<Node<NodeData, EdgeData>>();
-        nodes.addAll(rootNodes);
-
-        assert nodes.size() > 0;
-
-        this.graph.traverseDFS(nodes, visitor);
-
-        for (Edge<NodeData, EdgeData> e : reversedEdges) {
-            if (e.isSelfLoop()) {
-                e.remove();
-                removedCount++;
-            } else {
-                e.reverse();
-                reversedCount++;
-            }
-        }
-    }
-
-    private boolean checkRemoveCycles() {
-        return !graph.hasCycles();
-    }
-    // Only used by assignLayers
-    private int maxLayerTemp;
-
-    private int assignLayers(Set<Node<NodeData, EdgeData>> rootNodes, Set<? extends Vertex> firstLayerHints,
-            Set<? extends Vertex> lastLayerHints) {
-        this.maxLayerTemp = -1;
-        for (Node<NodeData, EdgeData> n : graph.getNodes()) {
-            n.getData().setLayer(-1);
-        }
-
-        Graph.BFSTraversalVisitor traverser = graph.new BFSTraversalVisitor() {
-
-            @Override
-            public void visitNode(Node<NodeData, EdgeData> n, int depth) {
-                if (depth > n.getData().getLayer()) {
-                    n.getData().setLayer(depth);
-                    maxLayerTemp = Math.max(maxLayerTemp, depth);
-                }
-            }
-        };
-
-        for (Node<NodeData, EdgeData> n : rootNodes) {
-            if (n.getData().getLayer() == -1) {
-                this.graph.traverseBFS(n, traverser, true);
-            }
-        }
-
-        for (Vertex v : firstLayerHints) {
-            assert nodeMap.containsKey(v);
-            nodeMap.get(v).getData().setLayer(0);
-        }
-
-        for (Vertex v : lastLayerHints) {
-            assert nodeMap.containsKey(v);
-            nodeMap.get(v).getData().setLayer(maxLayerTemp);
-        }
-
-        return maxLayerTemp;
-    }
-
-    private boolean checkAssignLayers() {
-
-        for (Edge<NodeData, EdgeData> e : graph.getEdges()) {
-            Node<NodeData, EdgeData> source = e.getSource();
-            Node<NodeData, EdgeData> dest = e.getDest();
-
-
-            if (source.getData().getLayer() >= dest.getData().getLayer()) {
-                return false;
-            }
-        }
-        int maxLayer = 0;
-        for (Node<NodeData, EdgeData> n : graph.getNodes()) {
-            assert n.getData().getLayer() >= 0;
-            if (n.getData().getLayer() > maxLayer) {
-                maxLayer = n.getData().getLayer();
-            }
-        }
-
-        int countPerLayer[] = new int[maxLayer + 1];
-        for (Node<NodeData, EdgeData> n : graph.getNodes()) {
-            countPerLayer[n.getData().getLayer()]++;
-        }
-
-        if (TRACE) {
-            System.out.println("Number of layers: " + maxLayer);
-        }
-        return true;
-    }
-}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Timing.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Timing.java	Fri May 08 13:25:11 2015 -0400
@@ -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
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Layout/nbproject/project.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Layout/nbproject/project.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Cluster.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Cluster.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -37,6 +37,4 @@
     public void setBounds(Rectangle r);
 
     public Set<? extends Cluster> getSuccessors();
-
-    public Set<? extends Cluster> getPredecessors();
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutGraph.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutGraph.java	Fri May 08 13:25:11 2015 -0400
@@ -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,11 +23,7 @@
  */
 package com.sun.hotspot.igv.layout;
 
-import java.util.HashSet;
-import java.util.HashMap;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
+import java.util.*;
 
 /**
  *
@@ -49,10 +45,10 @@
         this.links = links;
         assert verify();
 
-        vertices = new TreeSet<Vertex>();
-        portLinks = new HashMap<Port, Set<Link>>();
-        inputPorts = new HashMap<Vertex, Set<Port>>();
-        outputPorts = new HashMap<Vertex, Set<Port>>();
+        vertices = new TreeSet<>();
+        portLinks = new HashMap<>(links.size());
+        inputPorts = new HashMap<>(links.size());
+        outputPorts = new HashMap<>(links.size());
 
         for (Link l : links) {
             Port p = l.getFrom();
@@ -76,7 +72,7 @@
             }
 
             if (!portLinks.containsKey(p)) {
-                HashSet<Link> hashSet = new HashSet<Link>(3);
+                HashSet<Link> hashSet = new HashSet<>(3);
                 portLinks.put(p, hashSet);
             }
 
@@ -152,7 +148,7 @@
     //   whole graph is visited.
     public Set<Vertex> findRootVertices(Set<Vertex> startingRoots) {
 
-        Set<Vertex> notRootSet = new HashSet<Vertex>();
+        Set<Vertex> notRootSet = new HashSet<>();
         for (Vertex v : startingRoots) {
             if (!notRootSet.contains(v)) {
                 markNotRoot(notRootSet, v, v);
@@ -174,7 +170,7 @@
             }
         }
 
-        Set<Vertex> result = new HashSet<Vertex>();
+        Set<Vertex> result = new HashSet<>();
         for (Vertex v : tmpVertices) {
             if (!notRootSet.contains(v)) {
                 result.add(v);
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutManager.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutManager.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -33,7 +33,7 @@
 
     public void doLayout(LayoutGraph graph);
 
-    public void doLayout(LayoutGraph graph, Set<? extends Vertex> firstLayerHint, Set<? extends Vertex> lastLayerHint, Set<? extends Link> importantLinks);
+    public void doLayout(LayoutGraph graph, Set<? extends Link> importantLinks);
 
     public void doRouting(LayoutGraph graph);
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Link.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Link.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -36,6 +36,8 @@
 
     public Port getTo();
 
+    public boolean isVIP();
+
     public List<Point> getControlPoints();
 
     public void setControlPoints(List<Point> list);
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Port.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Port.java	Fri May 08 13:25:11 2015 -0400
@@ -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
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Vertex.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Layout/src/com/sun/hotspot/igv/layout/Vertex.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -32,8 +32,6 @@
  */
 public interface Vertex extends Comparable<Vertex> {
 
-    public Cluster getCluster();
-
     public Dimension getSize();
 
     public Point getPosition();
@@ -41,4 +39,6 @@
     public void setPosition(Point p);
 
     public boolean isRoot();
+
+    public Cluster getCluster();
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/NetworkConnection/nbproject/genfiles.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/NetworkConnection/nbproject/genfiles.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,8 +1,5 @@
-build.xml.data.CRC32=f8e21cb6
-build.xml.script.CRC32=a265137e
-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=f8e21cb6
-nbproject/build-impl.xml.script.CRC32=36f3138c
-nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
+nbproject/build-impl.xml.data.CRC32=5a0e591e
+nbproject/build-impl.xml.script.CRC32=4c38ce23
+nbproject/build-impl.xml.stylesheet.CRC32=e50cf570@2.62.1
--- a/hotspot/src/share/tools/IdealGraphVisualizer/NetworkConnection/nbproject/project.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/NetworkConnection/nbproject/project.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/hotspot/src/share/tools/IdealGraphVisualizer/NetworkConnection/nbproject/project.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/NetworkConnection/nbproject/project.xml	Fri May 08 13:25:11 2015 -0400
@@ -27,7 +27,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.11.1.1</specification-version>
+                        <specification-version>7.30.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -35,7 +35,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.5.1</specification-version>
+                        <specification-version>7.18.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -43,7 +43,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.10.1.1</specification-version>
+                        <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>
             </module-dependencies>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/NetworkConnection/src/META-INF/services/com.sun.hotspot.igv.data.services.GroupReceiver	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-com.sun.hotspot.igv.connection.Server
\ No newline at end of file
--- a/hotspot/src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/Client.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/Client.java	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -24,73 +24,48 @@
  */
 package com.sun.hotspot.igv.connection;
 
-import com.sun.hotspot.igv.data.Group;
-import com.sun.hotspot.igv.data.services.GroupCallback;
+import com.sun.hotspot.igv.data.GraphDocument;
+import com.sun.hotspot.igv.data.serialization.BinaryParser;
 import com.sun.hotspot.igv.data.serialization.Parser;
-import com.sun.hotspot.igv.data.Properties.RegexpPropertyMatcher;
+import com.sun.hotspot.igv.data.services.GroupCallback;
 import java.io.IOException;
-import java.io.InputStream;
-import java.net.Socket;
-import javax.swing.JTextField;
+import java.nio.channels.SocketChannel;
 import org.openide.util.Exceptions;
-import org.openide.xml.XMLUtil;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
 
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class Client implements Runnable, GroupCallback {
+public class Client implements Runnable {
+    private final boolean binary;
+    private final SocketChannel socket;
+    private final GraphDocument rootDocument;
+    private final GroupCallback callback;
 
-    private Socket socket;
-    private JTextField networkTextField;
-    private GroupCallback callback;
-
-    public Client(Socket socket, JTextField networkTextField, GroupCallback callback) {
+    public Client(SocketChannel socket, GraphDocument rootDocument, GroupCallback callback, boolean  binary) {
         this.callback = callback;
         this.socket = socket;
-        this.networkTextField = networkTextField;
+        this.binary = binary;
+        this.rootDocument = rootDocument;
     }
 
+    @Override
     public void run() {
 
         try {
-            InputStream inputStream = socket.getInputStream();
-
-            if (networkTextField.isEnabled()) {
-
-                socket.getOutputStream().write('y');
-                InputSource is = new InputSource(inputStream);
-
-                try {
-                    XMLReader reader = XMLUtil.createXMLReader();
-                    Parser parser = new Parser(this);
-                    parser.parse(reader, is, null);
-                } catch (SAXException ex) {
-                    ex.printStackTrace();
-                }
+            final SocketChannel channel = socket;
+            channel.configureBlocking(true);
+            if (binary) {
+                new BinaryParser(channel, null, rootDocument, callback).parse();
             } else {
-                socket.getOutputStream().write('n');
+                // signal readiness to client VM (old protocol)
+                channel.socket().getOutputStream().write('y');
+                new Parser(channel, null, callback).parse();
             }
-
-            socket.close();
         } catch (IOException ex) {
             Exceptions.printStackTrace(ex);
-        }
-    }
-
-    public void started(final Group g) {
-        try {
-            RegexpPropertyMatcher matcher = new RegexpPropertyMatcher("name", ".*" + networkTextField.getText() + ".*");
-            if (g.getProperties().selectSingle(matcher) != null && networkTextField.isEnabled()) {
-                socket.getOutputStream().write('y');
-                callback.started(g);
-            } else {
-                socket.getOutputStream().write('n');
+        } finally {
+            try {
+                socket.close();
+            } catch (IOException ex) {
+                Exceptions.printStackTrace(ex);
             }
-        } catch (IOException e) {
         }
     }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/Server.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/Server.java	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -24,17 +24,15 @@
  */
 package com.sun.hotspot.igv.connection;
 
-import com.sun.hotspot.igv.data.Group;
+import com.sun.hotspot.igv.data.GraphDocument;
 import com.sun.hotspot.igv.data.services.GroupCallback;
-import com.sun.hotspot.igv.data.services.GroupReceiver;
 import com.sun.hotspot.igv.settings.Settings;
-import java.awt.Component;
 import java.io.IOException;
-import java.net.ServerSocket;
-import java.net.Socket;
+import java.net.InetSocketAddress;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
 import java.util.prefs.PreferenceChangeEvent;
 import java.util.prefs.PreferenceChangeListener;
-import javax.swing.SwingUtilities;
 import org.openide.DialogDisplayer;
 import org.openide.NotifyDescriptor;
 import org.openide.util.RequestProcessor;
@@ -43,54 +41,26 @@
  *
  * @author Thomas Wuerthinger
  */
-public class Server implements GroupCallback, GroupReceiver, PreferenceChangeListener {
-
-    private javax.swing.JPanel jPanel1;
-    private javax.swing.JCheckBox networkCheckBox;
-    private javax.swing.JTextField networkTextField;
-    private ServerSocket serverSocket;
-    private GroupCallback callback;
+public class Server implements PreferenceChangeListener {
+    private final boolean binary;
+    private ServerSocketChannel serverSocket;
+    private final GraphDocument rootDocument;
+    private final GroupCallback callback;
     private int port;
     private Runnable serverRunnable;
 
-    public Component init(GroupCallback callback) {
-
+    public Server(GraphDocument rootDocument, GroupCallback callback, boolean binary) {
+        this.binary = binary;
+        this.rootDocument = rootDocument;
         this.callback = callback;
-
-        jPanel1 = new javax.swing.JPanel();
-        networkTextField = new javax.swing.JTextField();
-        networkCheckBox = new javax.swing.JCheckBox();
-
-
-        jPanel1.setBorder(javax.swing.BorderFactory.createEmptyBorder(5, 5, 5, 5));
-        jPanel1.setLayout(new java.awt.BorderLayout(10, 10));
-        jPanel1.add(networkTextField, java.awt.BorderLayout.CENTER);
-
-        networkCheckBox.setSelected(true);
-        org.openide.awt.Mnemonics.setLocalizedText(networkCheckBox, "Receive when name contains");
-        networkCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
-        networkCheckBox.setMargin(new java.awt.Insets(0, 0, 0, 0));
-        networkCheckBox.addChangeListener(new javax.swing.event.ChangeListener() {
-
-            public void stateChanged(javax.swing.event.ChangeEvent evt) {
-                networkCheckBoxChanged(evt);
-            }
-        });
-        jPanel1.add(networkCheckBox, java.awt.BorderLayout.WEST);
-        networkCheckBox.getAccessibleContext().setAccessibleName("Read from network when name contains");
-
         initializeNetwork();
         Settings.get().addPreferenceChangeListener(this);
-        return jPanel1;
     }
 
-    private void networkCheckBoxChanged(javax.swing.event.ChangeEvent evt) {
-        networkTextField.setEnabled(networkCheckBox.isSelected());
-    }
-
+    @Override
     public void preferenceChange(PreferenceChangeEvent e) {
 
-        int curPort = Integer.parseInt(Settings.get().get(Settings.PORT, Settings.PORT_DEFAULT));
+        int curPort = Integer.parseInt(Settings.get().get(binary ? Settings.PORT_BINARY : Settings.PORT, binary ? Settings.PORT_BINARY_DEFAULT : Settings.PORT_DEFAULT));
         if (curPort != port) {
             initializeNetwork();
         }
@@ -98,30 +68,32 @@
 
     private void initializeNetwork() {
 
-        int curPort = Integer.parseInt(Settings.get().get(Settings.PORT, Settings.PORT_DEFAULT));
+        int curPort = Integer.parseInt(Settings.get().get(binary ? Settings.PORT_BINARY : Settings.PORT, binary ? Settings.PORT_BINARY_DEFAULT : Settings.PORT_DEFAULT));
         this.port = curPort;
         try {
-            serverSocket = new java.net.ServerSocket(curPort);
-        } catch (IOException ex) {
-            NotifyDescriptor message = new NotifyDescriptor.Message("Could not create server. Listening for incoming data is disabled.", NotifyDescriptor.ERROR_MESSAGE);
+            serverSocket = ServerSocketChannel.open();
+            serverSocket.bind(new InetSocketAddress(curPort));
+        } catch (Throwable ex) {
+            NotifyDescriptor message = new NotifyDescriptor.Message("Could not create server. Listening for incoming binary data is disabled.", NotifyDescriptor.ERROR_MESSAGE);
             DialogDisplayer.getDefault().notifyLater(message);
             return;
         }
 
         Runnable runnable = new Runnable() {
 
+            @Override
             public void run() {
                 while (true) {
                     try {
-                        Socket clientSocket = serverSocket.accept();
+                        SocketChannel clientSocket = serverSocket.accept();
                         if (serverRunnable != this) {
                             clientSocket.close();
                             return;
                         }
-                        RequestProcessor.getDefault().post(new Client(clientSocket, networkTextField, Server.this), 0, Thread.MAX_PRIORITY);
+                        RequestProcessor.getDefault().post(new Client(clientSocket, rootDocument, callback, binary), 0, Thread.MAX_PRIORITY);
                     } catch (IOException ex) {
                         serverSocket = null;
-                        NotifyDescriptor message = new NotifyDescriptor.Message("Error during listening for incoming connections. Listening for incoming data is disabled.", NotifyDescriptor.ERROR_MESSAGE);
+                        NotifyDescriptor message = new NotifyDescriptor.Message("Error during listening for incoming connections. Listening for incoming binary data is disabled.", NotifyDescriptor.ERROR_MESSAGE);
                         DialogDisplayer.getDefault().notifyLater(message);
                         return;
                     }
@@ -133,13 +105,4 @@
 
         RequestProcessor.getDefault().post(runnable, 0, Thread.MAX_PRIORITY);
     }
-
-    public void started(final Group g) {
-        SwingUtilities.invokeLater(new Runnable() {
-
-            public void run() {
-                callback.started(g);
-            }
-        });
-    }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/README	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-The Ideal Graph Visualizer is a tool developed to help examine the
-intermediate representation of C2 which is commonly referred to as the
-"ideal graph".  It was developed in collaboration with the University
-of Linz in Austria and has been included as part of hotspot since that
-was the primary target of the tool.  The tool itself is fairly general
-with only a few modules that contain C2 specific elements.
-
-The tool is built on top of the NetBeans 6.1 rich client
-infrastructure and so requires NetBeans to build.  It currently
-requires Java 6 to run as it needs support for JavaScript for its
-filtering mechanism and assumes it's built into the platform.  It
-should build out of the box with NetBeans 6.1 and Java 6 or later.
-It's possible to run it on 1.5 by including Rhino on the classpath
-though that currently isn't working correctly.  Support for exporting
-graphs as SVG can be enabled by adding batik to the classpath which
-isn't included by default.  It can be built on top of NetBeans 6.0 if
-you change the required modules to be platform7 instead of platform8.
-
-The JVM support is controlled by the flag -XX:PrintIdealGraphLevel=#
-where # is:
-
-  0: no output, the default
-  1: dumps graph after parsing, before matching, and final code.
-     also dumps graph for failed compiles, if available
-  2: more detail, including after loop opts
-  3: even more detail
-  4: prints graph after parsing every bytecode (very slow)
-
-By default the JVM expects that it will connect to a visualizer on the
-local host on port 4444.  This can be configured using the options
--XX:PrintIdealGraphAddress= and -XX:PrintIdealGraphPort=.
-PrintIdealGraphAddress can actually be a hostname.
-
-Alternatively the output can be sent to a file using
--XX:PrintIdealGraphFile=filename.  Each compiler thread will get it's
-own file with unique names being generated by adding a number onto the
-provided file name.
-
-More information about the tool is available at
-http://wikis.sun.com/display/HotSpotInternals/IdealGraphVisualizer.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/README.md	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,50 @@
+# Overview
+
+The Ideal Graph Visualizer is a tool developed to help examine the intermediate
+representation of C2 which is commonly referred to as the "ideal graph". It was
+developed in collaboration with the University of Linz in Austria and has been
+included as part of hotspot since that was the primary target of the tool. The
+tool itself is fairly general with only a few modules that contain C2 specific
+elements.
+
+The tool is built on top of the NetBeans 7 rich client infrastructure and so
+requires NetBeans to build. It currently requires at least Java 6 to run as it
+needs support for JavaScript for its filtering mechanism and assumes it's built
+into the platform.  It should build out of the box with NetBeans 7.0 and Java 6
+or later.
+
+# Building and Running
+
+The build system used for IGV is ant. To download all required libraries and
+build IGV, issue `ant build`. To run IGV, use the `igv.sh` command; it will put
+all log messages generated by the run to the file `.igv.log`. To see all log
+messages generated during an IGV run, use `ant run`.
+
+# Usage
+
+The JVM support is controlled by the flag `-XX:PrintIdealGraphLevel=#` where `#`
+is:
+
+* 0: no output, the default
+* 1: dumps graph after parsing, before matching, and final code (also dumps
+     graphs for failed compilations, if available)
+* 2: more detail, including after loop opts
+* 3: even more detail
+* 4: prints graph after parsing every bytecode (very slow)
+
+By default the JVM expects that it will connect to a visualizer on the local
+host on port 4444. This can be configured using the options
+`-XX:PrintIdealGraphAddress=` and `-XX:PrintIdealGraphPort=`.
+`PrintIdealGraphAddress` can actually be a hostname.
+
+It is advisable to run the JVM with background compilation disabled (-Xbatch).
+Compilations going on in the background may be cancelled when the VM terminates,
+which can lead to incomplete dumps being sent to IGV.
+
+Alternatively the output can be sent to a file using
+`-XX:PrintIdealGraphFile=filename`. Each compiler thread will get it's own file
+with unique names being generated by adding a number onto the provided file
+name.
+
+More information about the tool is available at
+https://wikis.oracle.com/display/HotSpotInternals/IdealGraphVisualizer.
--- a/hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/build.xml	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-<?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.rhino" default="netbeans" basedir=".">
-    <description>Builds, tests, and runs the project com.sun.hotspot.igv.rhino.</description>
-    <import file="nbproject/build-impl.xml"/>
-</project>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/manifest.mf	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-Manifest-Version: 1.0
-OpenIDE-Module: com.sun.hotspot.igv.rhino
-OpenIDE-Module-Layer: com/sun/hotspot/igv/rhino/layer.xml
-OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/rhino/Bundle.properties
-OpenIDE-Module-Specification-Version: 1.0
-
--- a/hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/build-impl.xml	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-*** GENERATED FROM project.xml - DO NOT EDIT  ***
-***         EDIT ../build.xml INSTEAD         ***
--->
-<project name="com.sun.hotspot.igv.rhino-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>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/genfiles.properties	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-build.xml.data.CRC32=0c3e7912
-build.xml.script.CRC32=44d0050c
-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=0c3e7912
-nbproject/build-impl.xml.script.CRC32=7aab3f52
-nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- a/hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/project.properties	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
--- a/hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/project.xml	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-<?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.rhino</code-name-base>
-            <suite-component/>
-            <module-dependencies>
-                <dependency>
-                    <code-name-base>com.sun.hotspot.igv.filter</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.graph</code-name-base>
-                    <build-prerequisite/>
-                    <compile-dependency/>
-                    <run-dependency>
-                        <specification-version>1.0</specification-version>
-                    </run-dependency>
-                </dependency>
-            </module-dependencies>
-            <public-packages>
-                <package>com.sun.hotspot.igv.rhino</package>
-            </public-packages>
-        </data>
-    </configuration>
-</project>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/nbproject/suite.properties	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-suite.dir=${basedir}/..
--- a/hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/src/META-INF/services/com.sun.hotspot.igv.filter.ScriptEngineAbstraction	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-com.sun.hotspot.igv.rhino.RhinoScriptEngine
\ No newline at end of file
--- a/hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/src/com/sun/hotspot/igv/rhino/Bundle.properties	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-OpenIDE-Module-Name=RhinoScriptEngineProxy
--- a/hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/src/com/sun/hotspot/igv/rhino/RhinoScriptEngine.java	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 1998, 2007, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.rhino;
-
-import com.sun.hotspot.igv.filter.ScriptEngineAbstraction;
-import com.sun.hotspot.igv.graph.Diagram;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class RhinoScriptEngine implements ScriptEngineAbstraction {
-
-    private String jsHelperText;
-    private Constructor importer;
-    private Method scope_put;
-    private Method cx_evaluateString;
-    private Method context_enter;
-    private Method context_exit;
-
-    public boolean initialize(String s) {
-        this.jsHelperText = s;
-        Class importerTopLevel = null;
-        try {
-            ClassLoader cl = RhinoScriptEngine.class.getClassLoader();
-            Class context = cl.loadClass("org.mozilla.javascript.Context");
-            Class scriptable = cl.loadClass("org.mozilla.javascript.Scriptable");
-            importerTopLevel = cl.loadClass("org.mozilla.javascript.ImporterTopLevel");
-            importer = importerTopLevel.getDeclaredConstructor(context);
-            scope_put = importerTopLevel.getMethod("put", new Class[]{String.class, scriptable, Object.class});
-            cx_evaluateString = context.getDeclaredMethod("evaluateString", new Class[]{scriptable, String.class, String.class, Integer.TYPE, Object.class});
-            context_enter = context.getDeclaredMethod("enter", new Class[0]);
-            context_exit = context.getDeclaredMethod("exit", new Class[0]);
-            return true;
-        } catch (NoSuchMethodException nsme) {
-            return false;
-        } catch (ClassNotFoundException cnfe) {
-            return false;
-        }
-    }
-
-    public void execute(Diagram d, String code) {
-        try {
-            Object cx = context_enter.invoke(null, (Object[]) null);
-            try {
-                Object scope = importer.newInstance(cx);
-                scope_put.invoke(scope, "IO", scope, System.out);
-                scope_put.invoke(scope, "graph", scope, d);
-                cx_evaluateString.invoke(cx, scope, jsHelperText, "jsHelper.js", 1, null);
-                cx_evaluateString.invoke(cx, scope, code, "<cmd>", 1, null);
-            } finally {
-                // Exit from the context.
-                context_exit.invoke(null, (Object[]) null);
-            }
-        } catch (InvocationTargetException iae) {
-        } catch (IllegalAccessException iae) {
-        } catch (InstantiationException iae) {
-        }
-    }
-}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/RhinoScriptEngineProxy/src/com/sun/hotspot/igv/rhino/layer.xml	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-<?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>
-</filesystem>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/build.xml	Fri May 08 13:25:11 2015 -0400
@@ -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.selectioncoordinator" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.sun.hotspot.igv.selectioncoordinator.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/manifest.mf	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.sun.hotspot.igv.selectioncoordinator
+OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/selectioncoordinator/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/nbproject/build-impl.xml	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.sun.hotspot.igv.selectioncoordinator-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
+    <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>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" 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="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
+        <condition>
+            <not>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/nbproject/genfiles.properties	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,5 @@
+# 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=13553862
+nbproject/build-impl.xml.script.CRC32=3db87c68
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.67.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/nbproject/platform.properties	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,129 @@
+# Deprecated since 5.0u1; for compatibility with 5.0:
+disabled.clusters=\
+    apisupport1,\
+    gsf1,\
+    harness,\
+    java2,\
+    nb6.1,\
+    profiler3
+disabled.modules=\
+    org.apache.xml.resolver,\
+    org.netbeans.api.debugger,\
+    org.netbeans.api.xml,\
+    org.netbeans.core.execution,\
+    org.netbeans.core.ide,\
+    org.netbeans.core.multiview,\
+    org.netbeans.core.nativeaccess,\
+    org.netbeans.core.output2,\
+    org.netbeans.insane,\
+    org.netbeans.lib.cvsclient,\
+    org.netbeans.libs.commons_logging,\
+    org.netbeans.libs.freemarker,\
+    org.netbeans.libs.ini4j,\
+    org.netbeans.libs.jna,\
+    org.netbeans.libs.jsch,\
+    org.netbeans.libs.jsr223,\
+    org.netbeans.libs.lucene,\
+    org.netbeans.libs.svnClientAdapter,\
+    org.netbeans.libs.xerces,\
+    org.netbeans.modules.applemenu,\
+    org.netbeans.modules.autoupdate.services,\
+    org.netbeans.modules.autoupdate.ui,\
+    org.netbeans.modules.classfile,\
+    org.netbeans.modules.core.kit,\
+    org.netbeans.modules.db,\
+    org.netbeans.modules.db.core,\
+    org.netbeans.modules.db.drivers,\
+    org.netbeans.modules.db.kit,\
+    org.netbeans.modules.db.mysql,\
+    org.netbeans.modules.db.sql.editor,\
+    org.netbeans.modules.db.sql.visualeditor,\
+    org.netbeans.modules.dbapi,\
+    org.netbeans.modules.defaults,\
+    org.netbeans.modules.diff,\
+    org.netbeans.modules.editor.bookmarks,\
+    org.netbeans.modules.editor.bracesmatching,\
+    org.netbeans.modules.editor.codetemplates,\
+    org.netbeans.modules.editor.completion,\
+    org.netbeans.modules.editor.errorstripe,\
+    org.netbeans.modules.editor.errorstripe.api,\
+    org.netbeans.modules.editor.guards,\
+    org.netbeans.modules.editor.highlights,\
+    org.netbeans.modules.editor.macros,\
+    org.netbeans.modules.editor.plain,\
+    org.netbeans.modules.editor.plain.lib,\
+    org.netbeans.modules.editor.structure,\
+    org.netbeans.modules.extbrowser,\
+    org.netbeans.modules.favorites,\
+    org.netbeans.modules.gototest,\
+    org.netbeans.modules.httpserver,\
+    org.netbeans.modules.ide.kit,\
+    org.netbeans.modules.image,\
+    org.netbeans.modules.javahelp,\
+    org.netbeans.modules.jumpto,\
+    org.netbeans.modules.languages,\
+    org.netbeans.modules.languages.bat,\
+    org.netbeans.modules.languages.diff,\
+    org.netbeans.modules.languages.manifest,\
+    org.netbeans.modules.languages.sh,\
+    org.netbeans.modules.lexer.editorbridge,\
+    org.netbeans.modules.lexer.nbbridge,\
+    org.netbeans.modules.localhistory,\
+    org.netbeans.modules.masterfs,\
+    org.netbeans.modules.mercurial,\
+    org.netbeans.modules.progress.ui,\
+    org.netbeans.modules.project.ant,\
+    org.netbeans.modules.project.libraries,\
+    org.netbeans.modules.projectui,\
+    org.netbeans.modules.projectuiapi,\
+    org.netbeans.modules.properties,\
+    org.netbeans.modules.properties.syntax,\
+    org.netbeans.modules.refactoring.api,\
+    org.netbeans.modules.schema2beans,\
+    org.netbeans.modules.sendopts,\
+    org.netbeans.modules.server,\
+    org.netbeans.modules.servletapi,\
+    org.netbeans.modules.subversion,\
+    org.netbeans.modules.tasklist.kit,\
+    org.netbeans.modules.tasklist.projectint,\
+    org.netbeans.modules.tasklist.todo,\
+    org.netbeans.modules.tasklist.ui,\
+    org.netbeans.modules.templates,\
+    org.netbeans.modules.timers,\
+    org.netbeans.modules.usersguide,\
+    org.netbeans.modules.utilities,\
+    org.netbeans.modules.utilities.project,\
+    org.netbeans.modules.versioning,\
+    org.netbeans.modules.versioning.system.cvss,\
+    org.netbeans.modules.versioning.util,\
+    org.netbeans.modules.web.flyingsaucer,\
+    org.netbeans.modules.xml,\
+    org.netbeans.modules.xml.axi,\
+    org.netbeans.modules.xml.catalog,\
+    org.netbeans.modules.xml.core,\
+    org.netbeans.modules.xml.lexer,\
+    org.netbeans.modules.xml.multiview,\
+    org.netbeans.modules.xml.retriever,\
+    org.netbeans.modules.xml.schema.completion,\
+    org.netbeans.modules.xml.schema.model,\
+    org.netbeans.modules.xml.tax,\
+    org.netbeans.modules.xml.text,\
+    org.netbeans.modules.xml.tools,\
+    org.netbeans.modules.xml.wsdl.model,\
+    org.netbeans.modules.xml.xam,\
+    org.netbeans.modules.xml.xdm,\
+    org.netbeans.modules.xsl,\
+    org.netbeans.spi.debugger.ui,\
+    org.netbeans.spi.editor.hints,\
+    org.netbeans.spi.navigator,\
+    org.netbeans.spi.palette,\
+    org.netbeans.spi.tasklist,\
+    org.netbeans.spi.viewmodel,\
+    org.netbeans.swing.dirchooser,\
+    org.openide.compat,\
+    org.openide.util.enumerations
+enabled.clusters=\
+    ide9,\
+    platform8
+nbjdk.active=default
+nbplatform.active=default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/nbproject/project.properties	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,2 @@
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/nbproject/project.xml	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,23 @@
+<?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.selectioncoordinator</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>
+            </module-dependencies>
+            <public-packages>
+                <package>com.sun.hotspot.igv.selectioncoordinator</package>
+            </public-packages>
+        </data>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/nbproject/suite.properties	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,1 @@
+suite.dir=${basedir}/..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/src/com/sun/hotspot/igv/selectioncoordinator/Bundle.properties	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,1 @@
+OpenIDE-Module-Name=SelectionCoordinator
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/SelectionCoordinator/src/com/sun/hotspot/igv/selectioncoordinator/SelectionCoordinator.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2011, 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.selectioncoordinator;
+
+import com.sun.hotspot.igv.data.ChangedEvent;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ *
+ * @author Thomas
+ */
+public class SelectionCoordinator {
+
+    private static SelectionCoordinator singleInstance = new SelectionCoordinator();
+    private Set<Object> selectedObjects;
+    private Set<Object> highlightedObjects;
+    private ChangedEvent<SelectionCoordinator> selectedChangedEvent;
+    private ChangedEvent<SelectionCoordinator> highlightedChangedEvent;
+
+    public static SelectionCoordinator getInstance() {
+        return singleInstance;
+    }
+
+    private SelectionCoordinator() {
+        selectedChangedEvent = new ChangedEvent<>(this);
+        highlightedChangedEvent = new ChangedEvent<>(this);
+        selectedObjects = new HashSet<>();
+        highlightedObjects = new HashSet<>();
+    }
+
+    public Set<Object> getSelectedObjects() {
+        return Collections.unmodifiableSet(selectedObjects);
+    }
+
+    public Set<Object> getHighlightedObjects() {
+        return Collections.unmodifiableSet(highlightedObjects);
+    }
+
+    public ChangedEvent<SelectionCoordinator> getHighlightedChangedEvent() {
+        return highlightedChangedEvent;
+    }
+
+    public ChangedEvent<SelectionCoordinator> getSelectedChangedEvent() {
+        return selectedChangedEvent;
+    }
+
+    public void addHighlighted(Object o) {
+        if (!highlightedObjects.contains(o)) {
+            highlightedObjects.add(o);
+            highlightedObjectsChanged();
+        }
+    }
+
+    public void removeHighlighted(Object o) {
+        if (highlightedObjects.contains(o)) {
+            highlightedObjects.remove(o);
+            highlightedObjectsChanged();
+        }
+    }
+
+    public void addAllHighlighted(Set<? extends Object> s) {
+        int oldSize = highlightedObjects.size();
+        highlightedObjects.addAll(s);
+        if (oldSize != highlightedObjects.size()) {
+            highlightedObjectsChanged();
+        }
+    }
+
+    public void removeAllHighlighted(Set<? extends Object> s) {
+        int oldSize = highlightedObjects.size();
+        highlightedObjects.removeAll(s);
+        if (oldSize != highlightedObjects.size()) {
+            highlightedObjectsChanged();
+        }
+    }
+
+    private void highlightedObjectsChanged() {
+        highlightedChangedEvent.fire();
+
+    }
+
+    public void addAllSelected(Set<? extends Object> s) {
+        int oldSize = selectedObjects.size();
+        selectedObjects.addAll(s);
+        if (oldSize != selectedObjects.size()) {
+            selectedObjectsChanged();
+        }
+    }
+
+    public void removeAllSelected(Set<? extends Object> s) {
+        int oldSize = selectedObjects.size();
+        selectedObjects.removeAll(s);
+        if (oldSize != selectedObjects.size()) {
+            selectedObjectsChanged();
+        }
+    }
+
+    public void setSelectedObjects(Set<? extends Object> s) {
+        assert s != null;
+        selectedObjects.clear();
+        selectedObjects.addAll(s);
+        selectedObjectsChanged();
+    }
+
+    private void selectedObjectsChanged() {
+        selectedChangedEvent.fire();
+    }
+
+    public void setHighlightedObjects(Set<? extends Object> s) {
+        assert s != null;
+        this.highlightedObjects.clear();
+        this.highlightedObjects.addAll(s);
+        highlightedObjectsChanged();
+    }
+}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/nbproject/project.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/nbproject/project.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/nbproject/project.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/nbproject/project.xml	Fri May 08 13:25:11 2015 -0400
@@ -1,21 +1,29 @@
-<?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.servercompiler</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>
-            </module-dependencies>
-            <public-packages/>
-        </data>
-    </configuration>
-</project>
+<?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.servercompiler</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.graph</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages/>
+        </data>
+    </configuration>
+</project>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/META-INF/services/com.sun.hotspot.igv.data.services.GroupOrganizer	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-com.sun.hotspot.igv.servercompiler.JavaGroupOrganizer
\ No newline at end of file
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/JavaGroupOrganizer.java	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,200 +0,0 @@
-/*
- * Copyright (c) 1998, 2007, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.servercompiler;
-
-import com.sun.hotspot.igv.data.Group;
-import com.sun.hotspot.igv.data.services.GroupOrganizer;
-import com.sun.hotspot.igv.data.Pair;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class JavaGroupOrganizer implements GroupOrganizer {
-
-    public String getName() {
-        return "Java structure";
-    }
-
-    public List<Pair<String, List<Group>>> organize(List<String> subFolders, List<Group> groups) {
-
-        List<Pair<String, List<Group>>> result = new ArrayList<Pair<String, List<Group>>>();
-
-        if (subFolders.size() == 0) {
-            buildResult(result, groups, packageNameProvider);
-        } else if (subFolders.size() == 1) {
-            buildResult(result, groups, classNameProvider);
-        } else if (subFolders.size() == 2) {
-            for (Group g : groups) {
-                List<Group> children = new ArrayList<Group>();
-                children.add(g);
-                Pair<String, List<Group>> p = new Pair<String, List<Group>>();
-                p.setLeft(reducedNameProvider.getName(g));
-                p.setRight(children);
-                result.add(p);
-            }
-        } else {
-            result.add(new Pair<String, List<Group>>("", groups));
-        }
-
-        return result;
-    }
-
-    private void buildResult(List<Pair<String, List<Group>>> result, List<Group> groups, NameProvider provider) {
-        HashMap<String, List<Group>> map = new HashMap<String, List<Group>>();
-        for (Group g : groups) {
-            String s = provider.getName(g);
-
-            if (!map.containsKey(s)) {
-                List<Group> list = new ArrayList<Group>();
-                Pair<String, List<Group>> pair = new Pair<String, List<Group>>(s, list);
-                result.add(pair);
-                map.put(s, list);
-            }
-
-            List<Group> curList = map.get(s);
-            curList.add(g);
-        }
-
-        Collections.sort(result, new Comparator<Pair<String, List<Group>>>() {
-
-            public int compare(Pair<String, List<Group>> a, Pair<String, List<Group>> b) {
-                return a.getLeft().compareTo(b.getLeft());
-            }
-        });
-    }
-
-    private static interface NameProvider {
-
-        public String getName(Group g);
-    }
-    private NameProvider reducedNameProvider = new NameProvider() {
-
-        public String getName(Group g) {
-            String name = g.getName();
-            assert name != null : "name of group must be set!";
-            final String noReducedName = name;
-
-            int firstPoint = name.indexOf(".");
-            if (firstPoint == -1) {
-                return noReducedName;
-            }
-
-            int firstParenthese = name.indexOf("(");
-            if (firstParenthese == -1 || firstParenthese < firstPoint) {
-                return noReducedName;
-            }
-
-            int current = firstPoint;
-            while (current > 0 && name.charAt(current) != ' ') {
-                current--;
-            }
-
-            String tmp = name.substring(0, firstParenthese);
-            int lastPoint = tmp.lastIndexOf(".");
-            if (lastPoint == -1) {
-                return noReducedName;
-            }
-
-            name = name.substring(0, current + 1) + name.substring(lastPoint + 1);
-            return name;
-        }
-    };
-    private NameProvider packageNameProvider = new NameProvider() {
-
-        public String getName(Group g) {
-            String name = g.getName();
-            assert name != null : "name of group must be set!";
-            final String noPackage = "<default>";
-
-            int firstPoint = name.indexOf(".");
-            if (firstPoint == -1) {
-                return noPackage;
-            }
-
-            int firstParenthese = name.indexOf("(");
-            if (firstParenthese == -1 || firstParenthese < firstPoint) {
-                return noPackage;
-            }
-
-            int current = firstPoint;
-            while (current > 0 && name.charAt(current) != ' ') {
-                current--;
-            }
-
-            String fullClassName = name.substring(current + 1, firstParenthese);
-            int lastPoint = fullClassName.lastIndexOf(".");
-            if (lastPoint == -1) {
-                return noPackage;
-            }
-            lastPoint = fullClassName.lastIndexOf(".", lastPoint - 1);
-            if (lastPoint == -1) {
-                return noPackage;
-            }
-
-            String packageName = fullClassName.substring(0, lastPoint);
-            return packageName;
-        }
-    };
-    private NameProvider classNameProvider = new NameProvider() {
-
-        public String getName(Group g) {
-            String name = g.getName();
-            assert name != null : "name of group must be set!";
-
-            final String noClass = "<noclass>";
-
-            int firstPoint = name.indexOf(".");
-            if (firstPoint == -1) {
-                return noClass;
-            }
-
-            int firstParenthese = name.indexOf("(");
-            if (firstParenthese == -1 || firstParenthese < firstPoint) {
-                return noClass;
-            }
-
-            int current = firstPoint;
-            while (current > 0 && name.charAt(current) != ' ') {
-                current--;
-            }
-
-            String fullClassName = name.substring(current + 1, firstParenthese);
-            int lastPoint = fullClassName.lastIndexOf(".");
-            if (lastPoint == -1) {
-                return noClass;
-            }
-            int lastlastPoint = fullClassName.lastIndexOf(".", lastPoint - 1);
-
-            String className = fullClassName.substring(lastlastPoint + 1, lastPoint);
-            return className;
-        }
-    };
-}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/ServerCompilerScheduler.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/ServerCompilerScheduler.java	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, 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
@@ -29,17 +29,7 @@
 import com.sun.hotspot.igv.data.InputGraph;
 import com.sun.hotspot.igv.data.InputNode;
 import com.sun.hotspot.igv.data.services.Scheduler;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.Stack;
-import java.util.Vector;
+import java.util.*;
 
 /**
  *
@@ -50,8 +40,8 @@
     private static class Node {
 
         public InputNode inputNode;
-        public Set<Node> succs = new HashSet<Node>();
-        public List<Node> preds = new ArrayList<Node>();
+        public Set<Node> succs = new HashSet<>();
+        public List<Node> preds = new ArrayList<>();
         public InputBlock block;
         public boolean isBlockProjection;
         public boolean isBlockStart;
@@ -65,6 +55,7 @@
     private InputBlock[][] commonDominator;
     private static final Comparator<InputEdge> edgeComparator = new Comparator<InputEdge>() {
 
+        @Override
         public int compare(InputEdge o1, InputEdge o2) {
             return o1.getToIndex() - o2.getToIndex();
         }
@@ -72,13 +63,13 @@
 
     public void buildBlocks() {
 
-        blocks = new Vector<InputBlock>();
+        blocks = new Vector<>();
         Node root = findRoot();
         if (root == null) {
             return;
         }
-        Stack<Node> stack = new Stack<Node>();
-        Set<Node> visited = new HashSet<Node>();
+        Stack<Node> stack = new Stack<>();
+        Set<Node> visited = new HashSet<>();
         stack.add(root);
         int blockCount = 0;
         InputBlock rootBlock = null;
@@ -93,7 +84,7 @@
 
             if (!visited.contains(parent)) {
                 visited.add(parent);
-                InputBlock block = new InputBlock(graph, "" + blockCount);
+                InputBlock block = graph.addBlock(Integer.toString(blockCount));
                 blocks.add(block);
                 if (parent == root) {
                     rootBlock = block;
@@ -111,7 +102,12 @@
                         p = parent;
                         break;
                     }
+
                     p = p.preds.get(0);
+                    if (p == proj) {
+                        // Cycle, stop
+                        break;
+                    }
 
                     if (p.block == null) {
                         p.block = block;
@@ -125,7 +121,7 @@
                                 n = n.preds.get(0);
                             }
                             if (n.block != null) {
-                                n.block.addSuccessor(block);
+                                graph.addBlockEdge(n.block, block);
                             }
                         }
                     }
@@ -136,12 +132,12 @@
                         for (Node n2 : n.succs) {
 
                             if (n2 != parent && n2.block != null && n2.block != rootBlock) {
-                                block.addSuccessor(n2.block);
+                                graph.addBlockEdge(block, n2.block);
                             }
                         }
                     } else {
                         if (n != parent && n.block != null && n.block != rootBlock) {
-                            block.addSuccessor(n.block);
+                            graph.addBlockEdge(block, n.block);
                         }
                     }
                 }
@@ -161,7 +157,7 @@
                 }
 
                 if (pushed == 0 && p == root) {
-                // TODO: special handling when root backedges are not built yet
+                    // TODO: special handling when root backedges are not built yet
                 }
             }
         }
@@ -174,7 +170,7 @@
         }
 
         int z = 0;
-        blockIndex = new HashMap<InputBlock, Integer>();
+        blockIndex = new HashMap<>(blocks.size());
         for (InputBlock b : blocks) {
             blockIndex.put(b, z);
             z++;
@@ -185,20 +181,25 @@
         return n.getProperties().get("block");
     }
 
+    @Override
     public Collection<InputBlock> schedule(InputGraph graph) {
+        if (graph.getNodes().isEmpty()) {
+            return Collections.emptyList();
+        }
+
         if (graph.getBlocks().size() > 0) {
-            Collection<InputNode> tmpNodes = new ArrayList<InputNode>(graph.getNodes());
+            Collection<InputNode> tmpNodes = new ArrayList<>(graph.getNodes());
             for (InputNode n : tmpNodes) {
                 String block = getBlockName(n);
                 if (graph.getBlock(n) == null) {
-                    graph.getBlock(block).addNode(n);
+                    graph.getBlock(block).addNode(n.getId());
                     assert graph.getBlock(n) != null;
                 }
             }
             return graph.getBlocks();
         } else {
-            nodes = new ArrayList<Node>();
-            inputNodeToNode = new HashMap<InputNode, Node>();
+            nodes = new ArrayList<>();
+            inputNodeToNode = new HashMap<>(graph.getNodes().size());
 
             this.graph = graph;
             buildUpGraph();
@@ -207,7 +208,16 @@
             buildCommonDominators();
             scheduleLatest();
 
+            InputBlock noBlock = null;
             for (InputNode n : graph.getNodes()) {
+                if (graph.getBlock(n) == null) {
+                    if (noBlock == null) {
+                        noBlock = graph.addBlock("(no block)");
+                        blocks.add(noBlock);
+                    }
+
+                    graph.setBlock(n, noBlock);
+                }
                 assert graph.getBlock(n) != null;
             }
 
@@ -215,15 +225,17 @@
         }
     }
 
-    public void scheduleLatest() {
-
-
+    private void scheduleLatest() {
         Node root = findRoot();
+        if(root == null) {
+            assert false : "No root found!";
+            return;
+        }
 
         // Mark all nodes reachable in backward traversal from root
-        Set<Node> reachable = new HashSet<Node>();
+        Set<Node> reachable = new HashSet<>();
         reachable.add(root);
-        Stack<Node> stack = new Stack<Node>();
+        Stack<Node> stack = new Stack<>();
         stack.push(root);
         while (!stack.isEmpty()) {
             Node cur = stack.pop();
@@ -235,7 +247,7 @@
             }
         }
 
-        Set<Node> unscheduled = new HashSet<Node>();
+        Set<Node> unscheduled = new HashSet<>();
         for (Node n : this.nodes) {
             if (n.block == null && reachable.contains(n)) {
                 unscheduled.add(n);
@@ -245,7 +257,7 @@
         while (unscheduled.size() > 0) {
             boolean progress = false;
 
-            Set<Node> newUnscheduled = new HashSet<Node>();
+            Set<Node> newUnscheduled = new HashSet<>();
             for (Node n : unscheduled) {
 
                 InputBlock block = null;
@@ -285,7 +297,7 @@
             }
         }
 
-        Set<Node> curReachable = new HashSet<Node>(reachable);
+        Set<Node> curReachable = new HashSet<>(reachable);
         for (Node n : curReachable) {
             if (n.block != null) {
                 for (Node s : n.succs) {
@@ -300,7 +312,7 @@
 
     private void markWithBlock(Node n, InputBlock b, Set<Node> reachable) {
         assert !reachable.contains(n);
-        Stack<Node> stack = new Stack<Node>();
+        Stack<Node> stack = new Stack<>();
         stack.push(n);
         n.block = b;
         b.addNode(n.inputNode.getId());
@@ -356,7 +368,7 @@
         if (ba == bb) {
             return ba;
         }
-        Set<InputBlock> visited = new HashSet<InputBlock>();
+        Set<InputBlock> visited = new HashSet<>();
         while (ba != null) {
             visited.add(ba);
             ba = dominatorMap.get(ba);
@@ -374,12 +386,12 @@
     }
 
     public void buildDominators() {
-        dominatorMap = new HashMap<InputBlock, InputBlock>();
+        dominatorMap = new HashMap<>(graph.getBlocks().size());
         if (blocks.size() == 0) {
             return;
         }
-        Vector<BlockIntermediate> intermediate = new Vector<BlockIntermediate>();
-        Map<InputBlock, BlockIntermediate> map = new HashMap<InputBlock, BlockIntermediate>();
+        Vector<BlockIntermediate> intermediate = new Vector<>(graph.getBlocks().size());
+        Map<InputBlock, BlockIntermediate> map = new HashMap<>(graph.getBlocks().size());
         int z = 0;
         for (InputBlock b : blocks) {
             BlockIntermediate bi = new BlockIntermediate();
@@ -390,16 +402,16 @@
             bi.parent = -1;
             bi.label = z;
             bi.ancestor = -1;
-            bi.pred = new ArrayList<Integer>();
-            bi.bucket = new ArrayList<Integer>();
+            bi.pred = new ArrayList<>();
+            bi.bucket = new ArrayList<>();
             intermediate.add(bi);
             map.put(b, bi);
             z++;
         }
-        Stack<Integer> stack = new Stack<Integer>();
+        Stack<Integer> stack = new Stack<>();
         stack.add(0);
 
-        Vector<BlockIntermediate> array = new Vector<BlockIntermediate>();
+        Vector<BlockIntermediate> array = new Vector<>();
         intermediate.get(0).dominator = 0;
 
         int n = 0;
@@ -538,15 +550,30 @@
     }
 
     private Node findRoot() {
+        Node minNode = null;
+        Node alternativeRoot = null;
 
-        for (Node n : nodes) {
-            InputNode inputNode = n.inputNode;
-            if (inputNode.getProperties().get("name").equals("Root")) {
-                return n;
+        for (Node node : nodes) {
+            InputNode inputNode = node.inputNode;
+            String s = inputNode.getProperties().get("name");
+            if (s != null && s.equals("Root")) {
+                return node;
+            }
+
+            if (alternativeRoot == null && node.preds.isEmpty()) {
+                alternativeRoot = node;
+            }
+
+            if (minNode == null || node.inputNode.getId() < minNode.inputNode.getId()) {
+                minNode = node;
             }
         }
 
-        return null;
+        if (alternativeRoot != null) {
+            return alternativeRoot;
+        } else {
+            return minNode;
+        }
     }
 
     public void buildUpGraph() {
@@ -562,7 +589,7 @@
             inputNodeToNode.put(n, node);
         }
 
-        Map<Integer, List<InputEdge>> edgeMap = new HashMap<Integer, List<InputEdge>>();
+        Map<Integer, List<InputEdge>> edgeMap = new HashMap<>(graph.getEdges().size());
         for (InputEdge e : graph.getEdges()) {
 
             int to = e.getTo();
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/color.filter	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/color.filter	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,18 @@
 colorize("name", ".*", yellow);
 colorize("name", "Catch.*", blue);
-
 colorize("name", "Region|Loop|CountedLoop|Root", red);
 colorize("name", "CProj|IfFalse|IfTrue|JProj|CatchProj", magenta);
+colorize("name", "Con.*", orange);
+colorize("name", "Parm|Proj", lightGray);
+
+// Nodes with bci
+colorize("bci", "..*", magenta);
+
+// Line style
+var f = new ColorFilter("Line Style filter");
+f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "int:")), null, Color.BLUE, null));
+f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "control")), null, Color.RED, null));
+f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "memory")), null, Color.GREEN, null));
+f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "tuple:")), null, Color.MAGENTA, null));
+f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "bottom")), null, Color.LIGHT_GRAY, null));
+f.apply(graph);
\ No newline at end of file
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/combine.filter	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-var f = new CombineFilter("Combine Filter");
-f.addRule(new CombineFilter.CombineRule(new Properties.RegexpPropertyMatcher("name", ".*"), new Properties.RegexpPropertyMatcher("name", "Proj|IfFalse|IfTrue|JProj|MachProj|JumpProj|CatchProj")));
-f.addRule(new CombineFilter.CombineRule(new Properties.RegexpPropertyMatcher("name", "Cmp.*"), new Properties.RegexpPropertyMatcher("name", "Bool")));
-f.apply(graph);
\ No newline at end of file
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/extendedColor.filter	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-colorize("name", "Con.*", orange);
-colorize("name", "Parm|Proj", lightGray);
-colorize("bci", "..*", magenta);
\ No newline at end of file
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/linestyle.filter	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-var f = new ColorFilter("Line Style filter");
-f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "int:")), null, Color.BLUE, null));
-f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "control")), null, Color.RED, null));
-f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "memory")), null, Color.GREEN, null));
-f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "tuple:")), null, Color.MAGENTA, null));
-f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "bottom")), null, Color.LIGHT_GRAY, null));
-f.apply(graph);
\ No newline at end of file
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/onlyControlFlow.filter	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/onlyControlFlow.filter	Fri May 08 13:25:11 2015 -0400
@@ -20,5 +20,5 @@
     ), false
   )
 );
-f.addRule( new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.RegexpPropertyMatcher("name", "Phi|Store.")), false));
+f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.RegexpPropertyMatcher("name", "Phi|Store."))));
 f.apply(graph);
\ No newline at end of file
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/register.filter	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/register.filter	Fri May 08 13:25:11 2015 -0400
@@ -1,4 +1,5 @@
+// Register coloring
 colorize("reg", "EAX", green);
 colorize("reg", "EFLAGS", gray);
 colorize("reg", "EBP", orange);
-colorize("reg", "ECX", cyan);
+colorize("reg", "ECX", cyan);
\ No newline at end of file
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/remove.filter	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/remove.filter	Fri May 08 13:25:11 2015 -0400
@@ -1,1 +1,8 @@
-remove("dump_spec", "FramePtr|ReturnAdr|I_O"); 
\ No newline at end of file
+remove("dump_spec", "FramePtr|ReturnAdr|I_O"); 
+removeInputs("name", "Root");
+var f = new RemoveSelfLoopsFilter("Remove Self-Loops");
+f.apply(graph);
+removeInputs("name", "SafePoint|CallStaticJava|CallDynamicJava|CallJava|CallLeaf|CallRuntime|AbstractLock|CallLeafNoFP|Call|CallStaticJavaDirect", 5);
+removeInputs("name", "Unlock|Lock", 7);
+removeInputs("name", "Allocate", 7);
+removeInputs("name", "AllocateArray", 9);
\ No newline at end of file
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/removeMemory.filter	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-
-//var f = new RemoveFilter("Remove Memory");
-//f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.StringPropertyMatcher("dump_spec", "Memory")), false));
-//f.addRule(new RemoveFilter.RemoveRule(new AndSelector(new MatcherSelector(new Properties.StringPropertyMatcher("name", "Proj")), new MatcherSelector(new Properties.StringPropertyMatcher("type", "memory"))), false));
-//f.apply(graph);
-
-remove("dump_spec", "Memory");
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/removeRootInputs.filter	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-removeInputs("name", "Root");
\ No newline at end of file
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/removeSafepointInputs.filter	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-removeInputs("name", "SafePoint|CallStaticJava|CallDynamicJava|CallJava|CallLeaf|CallRuntime|AbstractLock|CallLeafNoFP|Call|CallStaticJavaDirect", 5);
-removeInputs("name", "Unlock|Lock", 7);
-removeInputs("name", "Allocate", 7);
-removeInputs("name", "AllocateArray", 9);
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/removeSelfLoops.filter	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-var f = new RemoveSelfLoopsFilter("Remove Self-Loops");
-f.apply(graph);
\ No newline at end of file
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/split.filter	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-split("name", "BoxLock");
-split("name", "(Con.*)|(loadCon.*)");
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/structural.filter	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,6 @@
+var f = new CombineFilter("Combine Filter");
+f.addRule(new CombineFilter.CombineRule(new Properties.RegexpPropertyMatcher("name", ".*"), new Properties.RegexpPropertyMatcher("name", "Proj|IfFalse|IfTrue|JProj|MachProj|JumpProj|CatchProj")));
+f.addRule(new CombineFilter.CombineRule(new Properties.RegexpPropertyMatcher("name", "Cmp.*"), new Properties.RegexpPropertyMatcher("name", "Bool")));
+f.apply(graph);
+split("name", "BoxLock");
+split("name", "(Con.*)|(loadCon.*)", "[dump_spec]");
\ No newline at end of file
--- a/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/layer.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/layer.xml	Fri May 08 13:25:11 2015 -0400
@@ -2,60 +2,28 @@
 <!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
 <filesystem>
       <folder name="Filters">
-        <file name="Basic Coloring" url="filters/color.filter">
-            <attr name="enabled" boolvalue="true"/>
-        </file>
-        <file name="Matcher Flags Coloring" url="filters/matchingFlags.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Basic Coloring"/>
-        </file>
-        <file name="Register Coloring" url="filters/register.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Matcher Flags Coloring"/>
+        <file name="C2 Basic Coloring" url="filters/color.filter">
+            <attr name="enabled" boolvalue="false"/>
         </file>
-        <file name="Extended Coloring" url="filters/extendedColor.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Register Coloring"/>
-        </file>
-        <file name="Line Coloring" url="filters/linestyle.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Extended Coloring"/>
+        <file name="C2 Matcher Flags Coloring" url="filters/matchingFlags.filter">
+            <attr name="enabled" boolvalue="false"/>
+            <attr name="after" stringvalue="C2 Basic Coloring"/>
         </file>
-        <file name="Difference Coloring" url="filters/difference.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Line Coloring"/>
-        </file>
-        <file name="Only Control Flow" url="filters/onlyControlFlow.filter">
+        <file name="C2 Register Coloring" url="filters/register.filter">
             <attr name="enabled" boolvalue="false"/>
-            <attr name="after" stringvalue="Difference Coloring"/>
+            <attr name="after" stringvalue="C2 Matcher Flags Coloring"/>
         </file>
-        <file name="Remove FramePtr, I_O and Return Address" url="filters/remove.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Only Control Flow"/>
-        </file>
-        <file name="Remove Memory" url="filters/removeMemory.filter">
+        <file name="C2 Only Control Flow" url="filters/onlyControlFlow.filter">
             <attr name="enabled" boolvalue="false"/>
-            <attr name="after" stringvalue="Remove FramePtr, I_O and Return Address"/>
-        </file>
-        <file name="Remove Root Inputs" url="filters/removeRootInputs.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Remove Memory"/>
+            <attr name="after" stringvalue="C2 Register Coloring"/>
         </file>
-        <file name="Remove Safepoint Inputs" url="filters/removeSafepointInputs.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Remove Root Inputs"/>
-        </file>
-        <file name="Remove Self Loops" url="filters/removeSelfLoops.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Remove Safepoint Inputs"/>
+        <file name="C2 Remove Filter" url="filters/remove.filter">
+            <attr name="enabled" boolvalue="false"/>
+            <attr name="after" stringvalue="C2 Only Control Flow"/>
         </file>
-        <file name="Combine" url="filters/combine.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Remove Self Loops"/>
+        <file name="C2 Structural" url="filters/structural.filter">
+            <attr name="enabled" boolvalue="false"/>
+            <attr name="after" stringvalue="C2 Remove Filter"/>
         </file>
-        <file name="Split" url="filters/split.filter">
-            <attr name="enabled" boolvalue="true"/>
-            <attr name="after" stringvalue="Combine"/>
-        </file>
-    </folder>
+    </folder>	
 </filesystem>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Settings/nbproject/project.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Settings/nbproject/project.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Settings/nbproject/project.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Settings/nbproject/project.xml	Fri May 08 13:25:11 2015 -0400
@@ -12,7 +12,7 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.4</specification-version>
+                        <specification-version>1.16.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -21,7 +21,7 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>1</release-version>
-                        <specification-version>1.5</specification-version>
+                        <specification-version>1.21.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -29,7 +29,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.11.0.1</specification-version>
+                        <specification-version>7.30.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -37,7 +37,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.9.0.1</specification-version>
+                        <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>
             </module-dependencies>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/Settings.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/Settings.java	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, 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
@@ -37,7 +37,9 @@
     public final static String NODE_WIDTH = "nodeWidth";
     public final static String NODE_WIDTH_DEFAULT = "100";
     public final static String PORT = "port";
+    public final static String PORT_BINARY = "portBinary";
     public final static String PORT_DEFAULT = "4444";
+    public final static String PORT_BINARY_DEFAULT = "4445";
     public final static String DIRECTORY = "directory";
     public final static String DIRECTORY_DEFAULT = System.getProperty("user.dir");
 
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/ViewOptionsCategory.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/ViewOptionsCategory.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -27,8 +27,8 @@
 import javax.swing.ImageIcon;
 import org.netbeans.spi.options.OptionsCategory;
 import org.netbeans.spi.options.OptionsPanelController;
+import org.openide.util.ImageUtilities;
 import org.openide.util.NbBundle;
-import org.openide.util.Utilities;
 
 /**
  *
@@ -38,17 +38,20 @@
 
     @Override
     public Icon getIcon() {
-        return new ImageIcon(Utilities.loadImage("com/sun/hotspot/igv/settings/settings.gif"));
+        return new ImageIcon(ImageUtilities.loadImage("com/sun/hotspot/igv/settings/settings.png"));
     }
 
+    @Override
     public String getCategoryName() {
         return NbBundle.getMessage(ViewOptionsCategory.class, "OptionsCategory_Name_View");
     }
 
+    @Override
     public String getTitle() {
         return NbBundle.getMessage(ViewOptionsCategory.class, "OptionsCategory_Title_View");
     }
 
+    @Override
     public OptionsPanelController create() {
         return new ViewOptionsPanelController();
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/ViewOptionsPanelController.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/ViewOptionsPanelController.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -40,40 +40,49 @@
     private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
     private boolean changed;
 
+    @Override
     public void update() {
         getPanel().load();
         changed = false;
     }
 
+    @Override
     public void applyChanges() {
         getPanel().store();
         changed = false;
     }
 
+    @Override
     public void cancel() {
     // need not do anything special, if no changes have been persisted yet
     }
 
+    @Override
     public boolean isValid() {
         return getPanel().valid();
     }
 
+    @Override
     public boolean isChanged() {
         return changed;
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return null; // new HelpCtx("...ID") if you have a help set
     }
 
+    @Override
     public JComponent getComponent(Lookup masterLookup) {
         return getPanel();
     }
 
+    @Override
     public void addPropertyChangeListener(PropertyChangeListener l) {
         pcs.addPropertyChangeListener(l);
     }
 
+    @Override
     public void removePropertyChangeListener(PropertyChangeListener l) {
         pcs.removePropertyChangeListener(l);
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/ViewPanel.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/ViewPanel.java	Fri May 08 13:25:11 2015 -0400
@@ -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
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/layer.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/layer.xml	Fri May 08 13:25:11 2015 -0400
@@ -2,8 +2,10 @@
 <!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
 <filesystem>
     <folder name="OptionsDialog">
-        <file name="Advanced.instance_hidden"/>
-        <file name="General.instance_hidden"/>
-        <file name="com-sun-hotspot-igv-settings-ViewOptionsCategory.instance"/>
+      <!-- <file name="Advanced.instance_hidden"/>
+        <file name="General.instance_hidden"/>-->
+        <file name="com-sun-hotspot-igv-settings-ViewOptionsCategory.instance">
+            <attr name="position" intvalue="100" />
+        </file>
     </folder>
 </filesystem>
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/settings.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/settings.png has changed
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Util/nbproject/project.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Util/nbproject/project.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Util/nbproject/project.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Util/nbproject/project.xml	Fri May 08 13:25:11 2015 -0400
@@ -19,7 +19,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>2.9</specification-version>
+                        <specification-version>2.27.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.awt</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.39.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -27,7 +35,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.2.1.1</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -35,7 +43,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.10.1.1</specification-version>
+                        <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>
             </module-dependencies>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/BoundedZoomAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/BoundedZoomAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/ColorIcon.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/ColorIcon.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -34,21 +34,26 @@
  */
 public class ColorIcon implements Icon {
 
-    private Color color;
+    private final Color color;
 
     public ColorIcon(Color c) {
         color = c;
     }
 
+    @Override
     public void paintIcon(Component c, Graphics g, int x, int y) {
+        Color oldColor = g.getColor();
         g.setColor(color);
         g.fillRect(x, y, 16, 16);
+        g.setColor(oldColor);
     }
 
+    @Override
     public int getIconWidth() {
         return 16;
     }
 
+    @Override
     public int getIconHeight() {
         return 16;
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/ContextAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/ContextAction.java	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, 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
@@ -25,11 +25,7 @@
 package com.sun.hotspot.igv.util;
 
 import java.awt.EventQueue;
-import org.openide.util.ContextAwareAction;
-import org.openide.util.Lookup;
-import org.openide.util.LookupEvent;
-import org.openide.util.LookupListener;
-import org.openide.util.Utilities;
+import org.openide.util.*;
 import org.openide.util.actions.CallableSystemAction;
 
 /**
@@ -56,6 +52,7 @@
         resultChanged(null);
     }
 
+    @Override
     public void resultChanged(LookupEvent e) {
         if (result.allItems().size() != 0) {
             update(result.allInstances().iterator().next());
@@ -71,6 +68,7 @@
         // Ensure it's AWT event thread
         EventQueue.invokeLater(new Runnable() {
 
+            @Override
             public void run() {
                 performAction(t);
             }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/DoubleClickAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/DoubleClickAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/DoubleClickHandler.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/DoubleClickHandler.java	Fri May 08 13:25:11 2015 -0400
@@ -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
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/ExtendedSatelliteComponent.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/ExtendedSatelliteComponent.java	Fri May 08 13:25:11 2015 -0400
@@ -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,11 +23,10 @@
  */
 package com.sun.hotspot.igv.util;
 
-import org.netbeans.api.visual.widget.Scene;
-
-import javax.swing.*;
 import java.awt.*;
 import java.awt.event.*;
+import javax.swing.JComponent;
+import org.netbeans.api.visual.widget.Scene;
 
 /**
  * @author David Kaspar
@@ -118,27 +117,34 @@
         }
     }
 
+    @Override
     public void mouseClicked(MouseEvent e) {
     }
 
+    @Override
     public void mousePressed(MouseEvent e) {
         moveVisibleRect(e.getPoint());
     }
 
+    @Override
     public void mouseReleased(MouseEvent e) {
         moveVisibleRect(e.getPoint());
     }
 
+    @Override
     public void mouseEntered(MouseEvent e) {
     }
 
+    @Override
     public void mouseExited(MouseEvent e) {
     }
 
+    @Override
     public void mouseDragged(MouseEvent e) {
         moveVisibleRect(e.getPoint());
     }
 
+    @Override
     public void mouseMoved(MouseEvent e) {
     }
 
@@ -170,26 +176,33 @@
 
     }
 
+    @Override
     public void sceneRepaint() {
     }
 
+    @Override
     public void sceneValidating() {
     }
 
+    @Override
     public void sceneValidated() {
     }
 
+    @Override
     public void componentResized(ComponentEvent e) {
         repaint();
     }
 
+    @Override
     public void componentMoved(ComponentEvent e) {
         repaint();
     }
 
+    @Override
     public void componentShown(ComponentEvent e) {
     }
 
+    @Override
     public void componentHidden(ComponentEvent e) {
     }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/ExtendedSelectAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/ExtendedSelectAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/LookupHistory.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2011, 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.util;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.openide.util.Lookup.Result;
+import org.openide.util.LookupEvent;
+import org.openide.util.LookupListener;
+import org.openide.util.Utilities;
+
+/**
+ *
+ * @author Thomas
+ */
+public class LookupHistory {
+
+    private static Map<Class, LookupHistoryImpl> cache = new HashMap<>();
+
+    private static class LookupHistoryImpl<T> implements LookupListener {
+
+        private Class<T> klass;
+        private Result<T> result;
+        private T last;
+
+        public LookupHistoryImpl(Class<T> klass) {
+            this.klass = klass;
+            result = Utilities.actionsGlobalContext().lookupResult(klass);
+            result.addLookupListener(this);
+            last = Utilities.actionsGlobalContext().lookup(klass);
+        }
+
+        public T getLast() {
+            return last;
+        }
+
+        @Override
+        public void resultChanged(LookupEvent ev) {
+            T current = Utilities.actionsGlobalContext().lookup(klass);
+            if (current != null) {
+                last = current;
+            }
+        }
+    }
+
+    public static <T> void init(Class<T> klass) {
+        if (!cache.containsKey(klass)) {
+            cache.put(klass, new LookupHistoryImpl<>(klass));
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> T getLast(Class<T> klass) {
+        init(klass);
+        assert cache.containsKey(klass);
+        return (T) cache.get(klass).getLast();
+    }
+}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/PropertiesSheet.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/PropertiesSheet.java	Fri May 08 13:25:11 2015 -0400
@@ -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
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSlider.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSlider.java	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, 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
@@ -25,33 +25,27 @@
 package com.sun.hotspot.igv.util;
 
 import com.sun.hotspot.igv.data.ChangedListener;
-import java.awt.Color;
-import java.awt.Cursor;
-import java.awt.Dimension;
-import java.awt.FontMetrics;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.RenderingHints;
+import java.awt.*;
+import java.awt.geom.*;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.awt.event.MouseMotionListener;
 import java.util.List;
-import javax.swing.JComponent;
+import javax.swing.*;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
-public class RangeSlider extends JComponent implements ChangedListener<RangeSliderModel>, MouseListener, MouseMotionListener {
+public class RangeSlider extends JComponent implements ChangedListener<RangeSliderModel>, MouseListener, MouseMotionListener, Scrollable {
 
     public static final int HEIGHT = 40;
-    public static final int BAR_HEIGHT = 22;
-    public static final int BAR_SELECTION_ENDING_HEIGHT = 16;
-    public static final int BAR_SELECTION_HEIGHT = 10;
-    public static final int BAR_THICKNESS = 2;
-    public static final int BAR_CIRCLE_SIZE = 9;
+    public static final float BAR_HEIGHT = 22;
+    public static final float BAR_SELECTION_ENDING_HEIGHT = 16;
+    public static final float BAR_SELECTION_HEIGHT = 10;
+    public static final float BAR_THICKNESS = 2;
+    public static final float BAR_CIRCLE_SIZE = 9;
+    public static final float BAR_CIRCLE_CONNECTOR_SIZE = 6;
     public static final int MOUSE_ENDING_OFFSET = 3;
     public static final Color BACKGROUND_COLOR = Color.white;
     public static final Color BAR_COLOR = Color.black;
@@ -98,14 +92,61 @@
         return model;
     }
 
+    /**
+     * Returns the preferred size of the viewport for a view component.
+     * For example, the preferred size of a <code>JList</code> component
+     * is the size required to accommodate all of the cells in its list.
+     * However, the value of <code>preferredScrollableViewportSize</code>
+     * is the size required for <code>JList.getVisibleRowCount</code> rows.
+     * A component without any properties that would affect the viewport
+     * size should just return <code>getPreferredSize</code> here.
+     *
+     * @return the preferredSize of a <code>JViewport</code> whose view
+     *    is this <code>Scrollable</code>
+     * @see JViewport#getPreferredSize
+     */
+    public Dimension getPreferredScrollableViewportSize() {
+        return getPreferredSize();
+    }
+
+    public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
+        if (orientation == SwingConstants.VERTICAL) {
+            return 1;
+        }
+
+        return (int)(BAR_CIRCLE_SIZE + BAR_CIRCLE_CONNECTOR_SIZE);
+    }
+
+    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
+        return orientation == SwingConstants.VERTICAL ? visibleRect.height / 2 : visibleRect.width / 2;
+    }
+
+    public boolean getScrollableTracksViewportWidth() {
+        return false;
+    }
+
+    public boolean getScrollableTracksViewportHeight() {
+        return true;
+    }
+
     @Override
     public Dimension getPreferredSize() {
         Dimension d = super.getPreferredSize();
         d.height = HEIGHT;
+        d.width = Math.max(d.width, (int)(2 * BAR_CIRCLE_CONNECTOR_SIZE + getPaintingModel().getPositions().size() * (BAR_CIRCLE_SIZE + BAR_CIRCLE_CONNECTOR_SIZE)));
         return d;
     }
 
+    @Override
     public void changed(RangeSliderModel source) {
+        revalidate();
+
+        float barStartY = getBarStartY();
+        int circleCenterY = (int)(barStartY + BAR_HEIGHT / 2);
+        int startX = (int)getStartXPosition(model.getFirstPosition());
+        int endX = (int)getEndXPosition(model.getSecondPosition());
+        Rectangle r = new Rectangle(startX, circleCenterY, endX - startX, 1);
+        scrollRectToVisible(r);
         update();
     }
 
@@ -113,22 +154,22 @@
         this.repaint();
     }
 
-    private int getXPosition(int index) {
+    private float getXPosition(int index) {
         assert index >= 0 && index < getPaintingModel().getPositions().size();
         return getXOffset() * (index + 1);
     }
 
-    private int getXOffset() {
+    private float getXOffset() {
         int size = getPaintingModel().getPositions().size();
-        int width = getWidth();
+        float width = (float)getWidth();
         return (width / (size + 1));
     }
 
-    private int getEndXPosition(int index) {
+    private float getEndXPosition(int index) {
         return getXPosition(index) + getXOffset() / 2;
     }
 
-    private int getStartXPosition(int index) {
+    private float getStartXPosition(int index) {
         return getXPosition(index) - getXOffset() / 2;
     }
 
@@ -142,7 +183,7 @@
         int height = getHeight();
 
         g2.setColor(BACKGROUND_COLOR);
-        g2.fillRect(0, 0, width, height);
+        g2.fill(new Rectangle2D.Float(0, 0, width, height));
 
         // Nothing to paint?
         if (getPaintingModel() == null || getPaintingModel().getPositions().size() == 0) {
@@ -157,30 +198,30 @@
 
     }
 
-    private int getBarStartY() {
-        return getHeight() - BAR_HEIGHT;
+    private float getBarStartY() {
+        return getHeight() / 2 - BAR_HEIGHT / 2;
     }
 
     private void paintBar(Graphics2D g) {
         List<String> list = getPaintingModel().getPositions();
-        int barStartY = getBarStartY();
+        float barStartY = getBarStartY();
 
         g.setColor(BAR_COLOR);
-        g.fillRect(getXPosition(0), barStartY + BAR_HEIGHT / 2 - BAR_THICKNESS / 2, getXPosition(list.size() - 1) - getXPosition(0), BAR_THICKNESS);
+        g.fill(new Rectangle2D.Float(getXPosition(0), barStartY + BAR_HEIGHT / 2 - BAR_THICKNESS / 2, getXPosition(list.size() - 1) - getXPosition(0), BAR_THICKNESS));
 
-        int circleCenterY = barStartY + BAR_HEIGHT / 2;
+        float circleCenterY = barStartY + BAR_HEIGHT / 2;
         for (int i = 0; i < list.size(); i++) {
-            int curX = getXPosition(i);
+            float curX = getXPosition(i);
             g.setColor(getPaintingModel().getColors().get(i));
-            g.fillOval(curX - BAR_CIRCLE_SIZE / 2, circleCenterY - BAR_CIRCLE_SIZE / 2, BAR_CIRCLE_SIZE, BAR_CIRCLE_SIZE);
+            g.fill(new Ellipse2D.Float(curX - BAR_CIRCLE_SIZE / 2, circleCenterY - BAR_CIRCLE_SIZE / 2, BAR_CIRCLE_SIZE, BAR_CIRCLE_SIZE));
             g.setColor(Color.black);
-            g.drawOval(curX - BAR_CIRCLE_SIZE / 2, circleCenterY - BAR_CIRCLE_SIZE / 2, BAR_CIRCLE_SIZE, BAR_CIRCLE_SIZE);
+            g.draw(new Ellipse2D.Float(curX - BAR_CIRCLE_SIZE / 2, circleCenterY - BAR_CIRCLE_SIZE / 2, BAR_CIRCLE_SIZE, BAR_CIRCLE_SIZE));
 
 
             String curS = list.get(i);
             if (curS != null && curS.length() > 0) {
-                int startX = getStartXPosition(i);
-                int endX = getEndXPosition(i);
+                float startX = getStartXPosition(i);
+                float endX = getEndXPosition(i);
                 FontMetrics metrics = g.getFontMetrics();
                 Rectangle bounds = metrics.getStringBounds(curS, g).getBounds();
                 if (bounds.width < endX - startX && bounds.height < barStartY) {
@@ -194,10 +235,10 @@
 
     private void paintSelected(Graphics2D g, int start, int end) {
 
-        int startX = getStartXPosition(start);
-        int endX = getEndXPosition(end);
-        int barStartY = getBarStartY();
-        int barSelectionEndingStartY = barStartY + BAR_HEIGHT / 2 - BAR_SELECTION_ENDING_HEIGHT / 2;
+        float startX = getStartXPosition(start);
+        float endX = getEndXPosition(end);
+        float barStartY = getBarStartY();
+        float barSelectionEndingStartY = barStartY + BAR_HEIGHT / 2 - BAR_SELECTION_ENDING_HEIGHT / 2;
         paintSelectedEnding(g, startX, barSelectionEndingStartY);
         paintSelectedEnding(g, endX, barSelectionEndingStartY);
 
@@ -207,18 +248,18 @@
         } else if (isOverBar) {
             g.setColor(BAR_SELECTION_COLOR_ROLLOVER);
         }
-        g.fillRect(startX, barStartY + BAR_HEIGHT / 2 - BAR_SELECTION_HEIGHT / 2, endX - startX, BAR_SELECTION_HEIGHT);
+        g.fill(new Rectangle2D.Float(startX, barStartY + BAR_HEIGHT / 2 - BAR_SELECTION_HEIGHT / 2, endX - startX, BAR_SELECTION_HEIGHT));
     }
 
-    private void paintSelectedEnding(Graphics g, int x, int y) {
+    private void paintSelectedEnding(Graphics2D g, float x, float y) {
         g.setColor(BAR_COLOR);
-        g.fillRect(x - BAR_THICKNESS / 2, y, BAR_THICKNESS, BAR_SELECTION_ENDING_HEIGHT);
+        g.fill(new Rectangle2D.Float(x - BAR_THICKNESS / 2, y, BAR_THICKNESS, BAR_SELECTION_ENDING_HEIGHT));
     }
 
     private boolean isOverSecondPosition(Point p) {
         if (p.y >= getBarStartY()) {
-            int destX = getEndXPosition(getPaintingModel().getSecondPosition());
-            int off = Math.abs(destX - p.x);
+            float destX = getEndXPosition(getPaintingModel().getSecondPosition());
+            float off = Math.abs(destX - p.x);
             return off <= MOUSE_ENDING_OFFSET;
         }
         return false;
@@ -226,8 +267,8 @@
 
     private boolean isOverFirstPosition(Point p) {
         if (p.y >= getBarStartY()) {
-            int destX = getStartXPosition(getPaintingModel().getFirstPosition());
-            int off = Math.abs(destX - p.x);
+            float destX = getStartXPosition(getPaintingModel().getFirstPosition());
+            float off = Math.abs(destX - p.x);
             return off <= MOUSE_ENDING_OFFSET;
         }
         return false;
@@ -240,10 +281,14 @@
         return false;
     }
 
+    @Override
     public void mouseDragged(MouseEvent e) {
+        Rectangle r = new Rectangle(e.getX(), e.getY(), 1, 1);
+        scrollRectToVisible(r);
+
         if (state == State.DragBar) {
-            int firstX = this.getStartXPosition(model.getFirstPosition());
-            int newFirstX = firstX + e.getPoint().x - startPoint.x;
+            float firstX = this.getStartXPosition(model.getFirstPosition());
+            float newFirstX = firstX + e.getPoint().x - startPoint.x;
             int newIndex = getIndexFromPosition(newFirstX) + 1;
             if (newIndex + model.getSecondPosition() - model.getFirstPosition() >= model.getPositions().size()) {
                 newIndex = model.getPositions().size() - (model.getSecondPosition() - model.getFirstPosition()) - 1;
@@ -270,13 +315,13 @@
         }
     }
 
-    private int getIndexFromPosition(int x) {
+    private int getIndexFromPosition(float x) {
         if (x < getXPosition(0)) {
             return -1;
         }
         for (int i = 0; i < getPaintingModel().getPositions().size() - 1; i++) {
-            int startX = getXPosition(i);
-            int endX = getXPosition(i + 1);
+            float startX = getXPosition(i);
+            float endX = getXPosition(i + 1);
             if (x >= startX && x <= endX) {
                 return i;
             }
@@ -286,7 +331,7 @@
 
     private int getCircleIndexFromPosition(int x) {
         int result = 0;
-        for (int i = 1; i < getPaintingModel().getPositions().size() - 1; i++) {
+        for (int i = 1; i < getPaintingModel().getPositions().size(); i++) {
             if (x > getStartXPosition(i)) {
                 result = i;
             }
@@ -294,6 +339,7 @@
         return result;
     }
 
+    @Override
     public void mouseMoved(MouseEvent e) {
         isOverBar = false;
         if (model == null) {
@@ -313,6 +359,7 @@
         repaint();
     }
 
+    @Override
     public void mouseClicked(MouseEvent e) {
         if (e.getClickCount() > 1) {
             // Double click
@@ -321,6 +368,7 @@
         }
     }
 
+    @Override
     public void mousePressed(MouseEvent e) {
         if (model == null) {
             return;
@@ -341,6 +389,7 @@
         tempModel = model.copy();
     }
 
+    @Override
     public void mouseReleased(MouseEvent e) {
         if (model == null || tempModel == null) {
             return;
@@ -350,9 +399,11 @@
         tempModel = null;
     }
 
+    @Override
     public void mouseEntered(MouseEvent e) {
     }
 
+    @Override
     public void mouseExited(MouseEvent e) {
         isOverBar = false;
         repaint();
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSliderModel.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSliderModel.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -24,8 +24,8 @@
  */
 package com.sun.hotspot.igv.util;
 
+import com.sun.hotspot.igv.data.ChangedEvent;
 import com.sun.hotspot.igv.data.ChangedEventProvider;
-import com.sun.hotspot.igv.data.ChangedEvent;
 import java.awt.Color;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -65,17 +65,19 @@
 
     public RangeSliderModel(List<String> positions) {
         assert positions.size() > 0;
-        this.changedEvent = new ChangedEvent<RangeSliderModel>(this);
-        this.colorChangedEvent = new ChangedEvent<RangeSliderModel>(this);
+        this.changedEvent = new ChangedEvent<>(this);
+        this.colorChangedEvent = new ChangedEvent<>(this);
         setPositions(positions);
     }
 
     protected void setPositions(List<String> positions) {
         this.positions = positions;
-        colors = new ArrayList<Color>();
+        colors = new ArrayList<>();
         for (int i = 0; i < positions.size(); i++) {
             colors.add(Color.black);
         }
+        firstPosition = Math.min(firstPosition, positions.size() - 1);
+        secondPosition = Math.min(secondPosition, positions.size() - 1);
         changedEvent.fire();
         colorChangedEvent.fire();
     }
@@ -91,9 +93,7 @@
 
     public RangeSliderModel copy() {
         RangeSliderModel newModel = new RangeSliderModel(positions);
-        newModel.firstPosition = firstPosition;
-        newModel.secondPosition = secondPosition;
-        newModel.colors = colors;
+        newModel.setData(this);
         return newModel;
     }
 
@@ -130,6 +130,7 @@
         return colorChangedEvent;
     }
 
+    @Override
     public ChangedEvent<RangeSliderModel> getChangedEvent() {
         return changedEvent;
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/nbproject/project.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/nbproject/project.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,2 +1,2 @@
-javac.source=1.5
-javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/nbproject/project.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/nbproject/project.xml	Fri May 08 13:25:11 2015 -0400
@@ -55,6 +55,14 @@
                     </run-dependency>
                 </dependency>
                 <dependency>
+                    <code-name-base>com.sun.hotspot.igv.selectioncoordinator</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.settings</code-name-base>
                     <build-prerequisite/>
                     <compile-dependency/>
@@ -83,7 +91,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>2.9</specification-version>
+                        <specification-version>2.27.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.spi.quicksearch</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.0</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -91,7 +107,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.6.0.1</specification-version>
+                        <specification-version>6.21.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -99,7 +115,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.11.0.1</specification-version>
+                        <specification-version>7.30.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -107,7 +123,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.5.1</specification-version>
+                        <specification-version>7.18.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -115,7 +131,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.7</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -123,7 +139,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.2.1.1</specification-version>
+                        <specification-version>7.20.1</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -131,7 +147,15 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>7.9.0.1</specification-version>
+                        <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>
@@ -139,7 +163,7 @@
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <specification-version>6.16</specification-version>
+                        <specification-version>6.39.1</specification-version>
                     </run-dependency>
                 </dependency>
             </module-dependencies>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/META-INF/services/com.sun.hotspot.igv.data.services.InputGraphProvider	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-com.sun.hotspot.igv.view.EditorInputGraphProvider
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/BoundedZoomAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/BoundedZoomAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/Bundle.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/Bundle.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,3 +1,3 @@
-HINT_EditorTopComponent=This is a Editor window
-OpenIDE-Module-Name=View
-CTL_EditorTopComponent=Editor Window
+HINT_EditorTopComponent=Visualizes a graph.
+OpenIDE-Module-Name=View
+CTL_EditorTopComponent=Graph
\ No newline at end of file
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/ConnectionAnchor.java	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * 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;
-
-import com.sun.hotspot.igv.view.widgets.SlotWidget;
-import java.awt.Point;
-import java.awt.Rectangle;
-import org.netbeans.api.visual.anchor.Anchor;
-import org.netbeans.api.visual.anchor.Anchor.Entry;
-import org.netbeans.api.visual.anchor.Anchor.Result;
-import org.netbeans.api.visual.widget.Widget;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class ConnectionAnchor extends Anchor {
-
-    public enum HorizontalAlignment {
-
-        Left,
-        Center,
-        Right
-    }
-    private HorizontalAlignment alignment;
-
-    public ConnectionAnchor(Widget widget) {
-        this(HorizontalAlignment.Center, widget);
-    }
-
-    public ConnectionAnchor(HorizontalAlignment alignment, Widget widget) {
-        super(widget);
-        this.alignment = alignment;
-    }
-
-    public Result compute(Entry entry) {
-        return new Result(getRelatedSceneLocation(), Anchor.DIRECTION_ANY);
-    }
-
-    @Override
-    public Point getRelatedSceneLocation() {
-        Point p = null;
-        Widget w = getRelatedWidget();
-        if (w != null) {
-            if (w instanceof SlotWidget) {
-                p = ((SlotWidget) w).getAnchorPosition();
-            } else {
-                Rectangle r = w.convertLocalToScene(w.getBounds());
-                int y = r.y + r.height / 2;
-                int x = r.x;
-                if (alignment == HorizontalAlignment.Center) {
-                    x = r.x + r.width / 2;
-                } else if (alignment == HorizontalAlignment.Right) {
-                    x = r.x + r.width;
-                }
-
-                p = new Point(x, y);
-            }
-        }
-
-        return p;
-    }
-}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java	Fri May 08 13:25:11 2015 -0400
@@ -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,77 +23,42 @@
  */
 package com.sun.hotspot.igv.view;
 
-import com.sun.hotspot.igv.view.widgets.BlockWidget;
-import com.sun.hotspot.igv.view.widgets.LineWidget;
-import com.sun.hotspot.igv.util.DoubleClickAction;
+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.graph.Connection;
-import com.sun.hotspot.igv.graph.Diagram;
-import com.sun.hotspot.igv.graph.Figure;
-import com.sun.hotspot.igv.graph.InputSlot;
-import com.sun.hotspot.igv.graph.OutputSlot;
-import com.sun.hotspot.igv.graph.Slot;
+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.OldHierarchicalLayoutManager;
 import com.sun.hotspot.igv.hierarchicallayout.HierarchicalLayoutManager;
-import com.sun.hotspot.igv.view.widgets.FigureWidget;
-import com.sun.hotspot.igv.view.widgets.InputSlotWidget;
-import com.sun.hotspot.igv.view.widgets.OutputSlotWidget;
-import com.sun.hotspot.igv.view.widgets.SlotWidget;
 import com.sun.hotspot.igv.layout.LayoutGraph;
-import com.sun.hotspot.igv.data.services.Scheduler;
-import com.sun.hotspot.igv.data.ChangedListener;
-import com.sun.hotspot.igv.graph.Block;
+import com.sun.hotspot.igv.selectioncoordinator.SelectionCoordinator;
 import com.sun.hotspot.igv.util.ColorIcon;
-import com.sun.hotspot.igv.util.ExtendedSelectAction;
-import java.awt.Color;
-import java.awt.Dimension;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.event.ActionEvent;
-import java.awt.event.FocusEvent;
-import java.awt.event.FocusListener;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseListener;
-import java.awt.event.MouseMotionListener;
-import java.awt.event.MouseWheelEvent;
-import java.awt.event.MouseWheelListener;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.HashMap;
+import com.sun.hotspot.igv.util.DoubleClickAction;
+import com.sun.hotspot.igv.util.PropertiesSheet;
+import com.sun.hotspot.igv.view.actions.CustomizablePanAction;
+import com.sun.hotspot.igv.view.widgets.*;
+import java.awt.*;
+import java.awt.event.*;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.swing.AbstractAction;
-import javax.swing.Action;
-import javax.swing.BorderFactory;
-import javax.swing.JComponent;
-import javax.swing.JPopupMenu;
-import javax.swing.JScrollPane;
-import javax.swing.SwingUtilities;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
+import java.util.*;
+import javax.swing.*;
 import javax.swing.event.UndoableEditEvent;
 import javax.swing.undo.AbstractUndoableEdit;
 import javax.swing.undo.CannotRedoException;
 import javax.swing.undo.CannotUndoException;
-import org.netbeans.api.visual.action.ActionFactory;
-import org.netbeans.api.visual.action.PopupMenuProvider;
-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.action.*;
 import org.netbeans.api.visual.animator.SceneAnimator;
 import org.netbeans.api.visual.layout.LayoutFactory;
-import org.netbeans.api.visual.widget.ConnectionWidget;
+import org.netbeans.api.visual.model.*;
 import org.netbeans.api.visual.widget.LayerWidget;
-import org.netbeans.api.visual.widget.Scene;
 import org.netbeans.api.visual.widget.Widget;
-import org.netbeans.api.visual.widget.LabelWidget;
 import org.openide.awt.UndoRedo;
+import org.openide.nodes.AbstractNode;
+import org.openide.nodes.Children;
+import org.openide.nodes.Sheet;
 import org.openide.util.Lookup;
 import org.openide.util.lookup.AbstractLookup;
 import org.openide.util.lookup.InstanceContent;
@@ -102,54 +67,58 @@
  *
  * @author Thomas Wuerthinger
  */
-public class DiagramScene extends Scene implements ChangedListener<DiagramViewModel> {
+public class DiagramScene extends ObjectScene implements DiagramViewer {
 
-    private HashMap<Figure, FigureWidget> figureWidgets;
-    private HashMap<Slot, SlotWidget> slotWidgets;
-    private HashMap<Connection, ConnectionWidget> connectionWidgets;
-    private HashMap<InputBlock, BlockWidget> blockWidgets;
-    private Widget hoverWidget;
+    private CustomizablePanAction panAction;
     private WidgetAction hoverAction;
-    private List<FigureWidget> selectedWidgets;
+    private WidgetAction selectAction;
     private Lookup lookup;
     private InstanceContent content;
     private Action[] actions;
+    private Action[] actionsWithSelection;
     private LayerWidget connectionLayer;
     private JScrollPane scrollPane;
     private UndoRedo.Manager undoRedoManager;
     private LayerWidget mainLayer;
-    private LayerWidget slotLayer;
     private LayerWidget blockLayer;
-    private double realZoomFactor;
-    private BoundedZoomAction zoomAction;
-    private WidgetAction panAction;
     private Widget topLeft;
     private Widget bottomRight;
-    private LayerWidget startLayer;
-    private LabelWidget startLabel;
     private DiagramViewModel model;
     private DiagramViewModel modelCopy;
-    public static final int AFTER = 1;
-    public static final int BEFORE = 1;
+    private WidgetAction zoomAction;
+    private boolean rebuilding;
+
+    /**
+     * The alpha level of partially visible figures.
+     */
     public static final float ALPHA = 0.4f;
-    public static final int GRID_SIZE = 30;
+
+    /**
+     * The offset of the graph to the border of the window showing it.
+     */
     public static final int BORDER_SIZE = 20;
+
+
     public static final int UNDOREDO_LIMIT = 100;
     public static final int SCROLL_UNIT_INCREMENT = 80;
     public static final int SCROLL_BLOCK_INCREMENT = 400;
     public static final float ZOOM_MAX_FACTOR = 3.0f;
     public static final float ZOOM_MIN_FACTOR = 0.0f;//0.15f;
     public static final float ZOOM_INCREMENT = 1.5f;
-    public static final int SLOT_OFFSET = 6;
+    public static final int SLOT_OFFSET = 8;
     public static final int ANIMATION_LIMIT = 40;
+
     private PopupMenuProvider popupMenuProvider = new PopupMenuProvider() {
 
+        @Override
         public JPopupMenu getPopupMenu(Widget widget, Point localLocation) {
             return DiagramScene.this.createPopupMenu();
         }
     };
+
     private RectangularSelectDecorator rectangularSelectDecorator = new RectangularSelectDecorator() {
 
+        @Override
         public Widget createSelectionWidget() {
             Widget widget = new Widget(DiagramScene.this);
             widget.setBorder(BorderFactory.createLineBorder(Color.black, 2));
@@ -157,8 +126,98 @@
             return widget;
         }
     };
+
+    @SuppressWarnings("unchecked")
+    public <T> T getWidget(Object o) {
+        Widget w = this.findWidget(o);
+        return (T) w;
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T getWidget(Object o, Class<T> klass) {
+        Widget w = this.findWidget(o);
+        return (T) w;
+    }
+
+    private static boolean intersects(Set<? extends Object> s1, Set<? extends Object> s2) {
+        for (Object o : s1) {
+            if (s2.contains(o)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public void zoomOut() {
+        double zoom = getZoomFactor();
+        Point viewPosition = getScrollPane().getViewport().getViewPosition();
+        double newZoom = zoom / DiagramScene.ZOOM_INCREMENT;
+        if (newZoom > DiagramScene.ZOOM_MIN_FACTOR) {
+            setZoomFactor(newZoom);
+            validate();
+            getScrollPane().getViewport().setViewPosition(new Point((int) (viewPosition.x / DiagramScene.ZOOM_INCREMENT), (int) (viewPosition.y / DiagramScene.ZOOM_INCREMENT)));
+        }
+    }
+
+    @Override
+    public void zoomIn() {
+
+        double zoom = getZoomFactor();
+        Point viewPosition = getScrollPane().getViewport().getViewPosition();
+        double newZoom = zoom * DiagramScene.ZOOM_INCREMENT;
+        if (newZoom < DiagramScene.ZOOM_MAX_FACTOR) {
+            setZoomFactor(newZoom);
+            validate();
+            getScrollPane().getViewport().setViewPosition(new Point((int) (viewPosition.x * DiagramScene.ZOOM_INCREMENT), (int) (viewPosition.y * DiagramScene.ZOOM_INCREMENT)));
+        }
+    }
+
+
+    @Override
+    public void centerFigures(List<Figure> list) {
+
+        boolean b = getUndoRedoEnabled();
+        setUndoRedoEnabled(false);
+        gotoFigures(list);
+        setUndoRedoEnabled(b);
+    }
+
+    private Set<Object> getObjectsFromIdSet(Set<Object> set) {
+        Set<Object> selectedObjects = new HashSet<>();
+        for (Figure f : getModel().getDiagramToView().getFigures()) {
+            if (intersects(f.getSource().getSourceNodesAsSet(), set)) {
+                selectedObjects.add(f);
+            }
+
+            for (Slot s : f.getSlots()) {
+                if (intersects(s.getSource().getSourceNodesAsSet(), set)) {
+                    selectedObjects.add(s);
+                }
+            }
+        }
+        return selectedObjects;
+    }
+    private ControllableChangedListener<SelectionCoordinator> highlightedCoordinatorListener = new ControllableChangedListener<SelectionCoordinator>() {
+
+        @Override
+        public void filteredChanged(SelectionCoordinator source) {
+            DiagramScene.this.setHighlightedObjects(getObjectsFromIdSet(source.getHighlightedObjects()));
+            DiagramScene.this.validate();
+        }
+    };
+    private ControllableChangedListener<SelectionCoordinator> selectedCoordinatorListener = new ControllableChangedListener<SelectionCoordinator>() {
+
+        @Override
+        public void filteredChanged(SelectionCoordinator source) {
+            DiagramScene.this.gotoSelection(source.getSelectedObjects());
+            DiagramScene.this.validate();
+        }
+    };
+
     private RectangularSelectProvider rectangularSelectProvider = new RectangularSelectProvider() {
 
+        @Override
         public void performSelection(Rectangle rectangle) {
             if (rectangle.width < 0) {
                 rectangle.x += rectangle.width;
@@ -170,168 +229,44 @@
                 rectangle.height *= -1;
             }
 
-            boolean updated = false;
+            Set<Object> selectedObjects = new HashSet<>();
             for (Figure f : getModel().getDiagramToView().getFigures()) {
-                FigureWidget w = figureWidgets.get(f);
-                Rectangle r = new Rectangle(w.getBounds());
-                r.setLocation(w.getLocation());
-                if (r.intersects(rectangle)) {
-                    if (!selectedWidgets.contains(w)) {
-                        addToSelection(w);
-                        updated = true;
+                FigureWidget w = getWidget(f);
+                if (w != null) {
+                    Rectangle r = new Rectangle(w.getBounds());
+                    r.setLocation(w.getLocation());
+
+                    if (r.intersects(rectangle)) {
+                        selectedObjects.add(f);
+                    }
+
+                    for (Slot s : f.getSlots()) {
+                        SlotWidget sw = getWidget(s);
+                        Rectangle r2 = new Rectangle(sw.getBounds());
+                        r2.setLocation(sw.convertLocalToScene(new Point(0, 0)));
+
+                        if (r2.intersects(rectangle)) {
+                            selectedObjects.add(s);
+                        }
                     }
                 } else {
-                    if (selectedWidgets.contains(w)) {
-                        selectedWidgets.remove(w);
-                        content.remove(w.getNode());
-                        w.setState(w.getState().deriveSelected(false));
-                        updated = true;
-                    }
-                }
-            }
-
-            if (updated) {
-                selectionUpdated();
-            }
-        }
-    };
-    private SelectProvider selectProvider = new SelectProvider() {
-
-        public boolean isAimingAllowed(Widget widget, Point point, boolean b) {
-            return false;
-        }
-
-        public boolean isSelectionAllowed(Widget widget, Point point, boolean b) {
-            return widget instanceof FigureWidget || widget == DiagramScene.this;
-        }
-
-        public void select(Widget w, Point point, boolean change) {
-
-            boolean updated = false;
-
-            if (w == DiagramScene.this) {
-                if (DiagramScene.this.selectedWidgets.size() != 0) {
-                    clearSelection();
-                    selectionUpdated();
-                }
-                return;
-            }
-
-            FigureWidget widget = (FigureWidget) w;
-
-
-            if (change) {
-                if (widget.getState().isSelected()) {
-                    assert selectedWidgets.contains(widget);
-                    widget.setState(widget.getState().deriveSelected(false));
-                    selectedWidgets.remove(widget);
-                    content.remove(widget.getNode());
-                    updated = true;
-                } else {
-                    assert !selectedWidgets.contains(widget);
-                    addToSelection(widget);
-                    updated = true;
-                    assert widget.getState().isSelected();
-                }
-            } else {
-
-                if (widget.getState().isSelected()) {
-                    assert selectedWidgets.contains(widget);
-                } else {
-
-                    assert !selectedWidgets.contains(widget);
-                    clearSelection();
-                    addToSelection(widget);
-                    updated = true;
-                    assert widget.getState().isSelected();
+                    assert false : "w should not be null here!";
                 }
             }
 
-            if (updated) {
-                selectionUpdated();
-            }
-
+            setSelectedObjects(selectedObjects);
         }
     };
 
-    private FigureWidget getFigureWidget(Figure f) {
-        return figureWidgets.get(f);
-    }
-    private FocusListener focusListener = new FocusListener() {
-
-        public void focusGained(FocusEvent e) {
-            DiagramScene.this.getView().requestFocus();
-        }
-
-        public void focusLost(FocusEvent e) {
-        }
-    };
     private MouseWheelListener mouseWheelListener = new MouseWheelListener() {
 
+        @Override
         public void mouseWheelMoved(MouseWheelEvent e) {
-            DiagramScene.this.zoomAction.mouseWheelMoved(DiagramScene.this, new WidgetAction.WidgetMouseWheelEvent(0, e));
-            DiagramScene.this.validate();
+            if (e.isControlDown()) {
+                DiagramScene.this.relayoutWithoutLayout(null);
+            }
         }
     };
-    private MouseListener mouseListener = new MouseListener() {
-
-        public void mouseClicked(MouseEvent e) {
-            DiagramScene.this.panAction.mouseClicked(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e));
-        }
-
-        public void mousePressed(MouseEvent e) {
-            DiagramScene.this.panAction.mousePressed(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e));
-        }
-
-        public void mouseReleased(MouseEvent e) {
-            DiagramScene.this.panAction.mouseReleased(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e));
-        }
-
-        public void mouseEntered(MouseEvent e) {
-            DiagramScene.this.panAction.mouseEntered(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e));
-        }
-
-        public void mouseExited(MouseEvent e) {
-            DiagramScene.this.panAction.mouseExited(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e));
-        }
-    };
-    private MouseMotionListener mouseMotionListener = new MouseMotionListener() {
-
-        public void mouseDragged(MouseEvent e) {
-            DiagramScene.this.panAction.mouseDragged(DiagramScene.this, new WidgetAction.WidgetMouseEvent(0, e));
-        }
-
-        public void mouseMoved(MouseEvent e) {
-        }
-    };
-    private ScrollChangeListener scrollChangeListener = new ScrollChangeListener();
-
-    private class ScrollChangeListener implements ChangeListener {
-
-        private Map<Widget, Point> relativePositions = new HashMap<Widget, Point>();
-        private Point oldPosition;
-
-        public void register(Widget w, Point p) {
-            relativePositions.put(w, p);
-        }
-
-        public void unregister(Widget w) {
-            relativePositions.remove(w);
-        }
-
-        public void stateChanged(ChangeEvent e) {
-            Point p = DiagramScene.this.getScrollPane().getViewport().getViewPosition();
-            if (oldPosition == null || !p.equals(oldPosition)) {
-                for (Widget w : relativePositions.keySet()) {
-                    Point curPoint = relativePositions.get(w);
-                    Point newPoint = new Point(p.x + curPoint.x, p.y + curPoint.y);
-                    w.setPreferredLocation(newPoint);
-                    DiagramScene.this.validate();
-                }
-                oldPosition = p;
-            }
-        }
-    }
 
     public Point getScrollPosition() {
         return getScrollPane().getViewport().getViewPosition();
@@ -341,42 +276,138 @@
         getScrollPane().getViewport().setViewPosition(p);
     }
 
-    public DiagramScene(Action[] actions, DiagramViewModel model) {
-        this.actions = actions;
-        selectedWidgets = new ArrayList<FigureWidget>();
-        content = new InstanceContent();
-        lookup = new AbstractLookup(content);
-        this.setCheckClipping(true);
-        this.getInputBindings().setZoomActionModifiers(0);
-
+    private JScrollPane createScrollPane() {
         JComponent comp = this.createView();
         comp.setDoubleBuffered(true);
         comp.setBackground(Color.WHITE);
         comp.setOpaque(true);
-
         this.setBackground(Color.WHITE);
         this.setOpaque(true);
-        scrollPane = new JScrollPane(comp);
-        scrollPane.setBackground(Color.WHITE);
-        scrollPane.getVerticalScrollBar().setUnitIncrement(SCROLL_UNIT_INCREMENT);
-        scrollPane.getVerticalScrollBar().setBlockIncrement(SCROLL_BLOCK_INCREMENT);
-        scrollPane.getHorizontalScrollBar().setUnitIncrement(SCROLL_UNIT_INCREMENT);
-        scrollPane.getHorizontalScrollBar().setBlockIncrement(SCROLL_BLOCK_INCREMENT);
-        scrollPane.getViewport().addChangeListener(scrollChangeListener);
-        hoverAction = this.createWidgetHoverAction();
+        JScrollPane result = new JScrollPane(comp);
+        result.setBackground(Color.WHITE);
+        result.getVerticalScrollBar().setUnitIncrement(SCROLL_UNIT_INCREMENT);
+        result.getVerticalScrollBar().setBlockIncrement(SCROLL_BLOCK_INCREMENT);
+        result.getHorizontalScrollBar().setUnitIncrement(SCROLL_UNIT_INCREMENT);
+        result.getHorizontalScrollBar().setBlockIncrement(SCROLL_BLOCK_INCREMENT);
+        return result;
+    }
+    private ObjectSceneListener selectionChangedListener = new ObjectSceneListener() {
+
+        @Override
+        public void objectAdded(ObjectSceneEvent arg0, Object arg1) {
+        }
+
+        @Override
+        public void objectRemoved(ObjectSceneEvent arg0, Object arg1) {
+        }
+
+        @Override
+        public void objectStateChanged(ObjectSceneEvent e, Object o, ObjectState oldState, ObjectState newState) {
+        }
+
+        @Override
+        public void selectionChanged(ObjectSceneEvent e, Set<Object> oldSet, Set<Object> newSet) {
+            DiagramScene scene = (DiagramScene) e.getObjectScene();
+            if (scene.isRebuilding()) {
+                return;
+            }
+
+            content.set(newSet, null);
+
+            Set<Integer> nodeSelection = new HashSet<>();
+            for (Object o : newSet) {
+                if (o instanceof Properties.Provider) {
+                    final Properties.Provider provider = (Properties.Provider) o;
+                    AbstractNode node = new AbstractNode(Children.LEAF) {
+
+                        @Override
+                        protected Sheet createSheet() {
+                            Sheet s = super.createSheet();
+                            PropertiesSheet.initializeSheet(provider.getProperties(), s);
+                            return s;
+                        }
+                    };
+                    node.setDisplayName(provider.getProperties().get("name"));
+                    content.add(node);
+                }
+
+
+                if (o instanceof Figure) {
+                    nodeSelection.addAll(((Figure) o).getSource().getSourceNodesAsSet());
+                } else if (o instanceof Slot) {
+                    nodeSelection.addAll(((Slot) o).getSource().getSourceNodesAsSet());
+                }
+            }
+            getModel().setSelectedNodes(nodeSelection);
+
+            boolean b = selectedCoordinatorListener.isEnabled();
+            selectedCoordinatorListener.setEnabled(false);
+            SelectionCoordinator.getInstance().setSelectedObjects(nodeSelection);
+            selectedCoordinatorListener.setEnabled(b);
+
+        }
+
+        @Override
+        public void highlightingChanged(ObjectSceneEvent e, Set<Object> oldSet, Set<Object> newSet) {
+            Set<Integer> nodeHighlighting = new HashSet<>();
+            for (Object o : newSet) {
+                if (o instanceof Figure) {
+                    nodeHighlighting.addAll(((Figure) o).getSource().getSourceNodesAsSet());
+                } else if (o instanceof Slot) {
+                    nodeHighlighting.addAll(((Slot) o).getSource().getSourceNodesAsSet());
+                }
+            }
+            boolean b = highlightedCoordinatorListener.isEnabled();
+            highlightedCoordinatorListener.setEnabled(false);
+            SelectionCoordinator.getInstance().setHighlightedObjects(nodeHighlighting);
+            highlightedCoordinatorListener.setEnabled(true);
+        }
+
+        @Override
+        public void hoverChanged(ObjectSceneEvent e, Object oldObject, Object newObject) {
+            Set<Object> newHighlightedObjects = new HashSet<>(DiagramScene.this.getHighlightedObjects());
+            if (oldObject != null) {
+                newHighlightedObjects.remove(oldObject);
+            }
+            if (newObject != null) {
+                newHighlightedObjects.add(newObject);
+            }
+            DiagramScene.this.setHighlightedObjects(newHighlightedObjects);
+        }
+
+        @Override
+        public void focusChanged(ObjectSceneEvent arg0, Object arg1, Object arg2) {
+        }
+    };
+
+    public DiagramScene(Action[] actions, Action[] actionsWithSelection, DiagramViewModel model) {
+
+        this.actions = actions;
+        this.actionsWithSelection = actionsWithSelection;
+
+        content = new InstanceContent();
+        lookup = new AbstractLookup(content);
+
+        this.setCheckClipping(true);
+
+        scrollPane = createScrollPane();
+
+        hoverAction = createObjectHoverAction();
+
+        // This panAction handles the event only when the left mouse button is
+        // pressed without any modifier keys, otherwise it will not consume it
+        // and the selection action (below) will handle the event
+        panAction = new CustomizablePanAction(~0, MouseEvent.BUTTON1_DOWN_MASK);
+        this.getActions().addAction(panAction);
+
+        selectAction = createSelectAction();
+        this.getActions().addAction(selectAction);
 
         blockLayer = new LayerWidget(this);
         this.addChild(blockLayer);
 
-        startLayer = new LayerWidget(this);
-        this.addChild(startLayer);
-        // TODO: String startLabelString = "Loading graph with " + originalDiagram.getFigures().size() + " figures and " + originalDiagram.getConnections().size() + " connections...";
-        String startLabelString = "";
-        LabelWidget w = new LabelWidget(this, startLabelString);
-        scrollChangeListener.register(w, new Point(10, 10));
-        w.setAlignment(LabelWidget.Alignment.CENTER);
-        startLabel = w;
-        startLayer.addChild(w);
+        connectionLayer = new LayerWidget(this);
+        this.addChild(connectionLayer);
 
         mainLayer = new LayerWidget(this);
         this.addChild(mainLayer);
@@ -385,83 +416,53 @@
         topLeft.setPreferredLocation(new Point(-BORDER_SIZE, -BORDER_SIZE));
         this.addChild(topLeft);
 
-
         bottomRight = new Widget(this);
         bottomRight.setPreferredLocation(new Point(-BORDER_SIZE, -BORDER_SIZE));
         this.addChild(bottomRight);
 
-        slotLayer = new LayerWidget(this);
-        this.addChild(slotLayer);
-
-        connectionLayer = new LayerWidget(this);
-        this.addChild(connectionLayer);
-
         LayerWidget selectionLayer = new LayerWidget(this);
         this.addChild(selectionLayer);
 
         this.setLayout(LayoutFactory.createAbsoluteLayout());
 
-        this.getActions().addAction(hoverAction);
-        zoomAction = new BoundedZoomAction(1.1, false);
-        zoomAction.setMaxFactor(ZOOM_MAX_FACTOR);
-        zoomAction.setMinFactor(ZOOM_MIN_FACTOR);
-        this.getActions().addAction(ActionFactory.createMouseCenteredZoomAction(1.1));
-        panAction = new ExtendedPanAction();
-        this.getActions().addAction(panAction);
+        this.getInputBindings().setZoomActionModifiers(KeyEvent.CTRL_MASK);
+        zoomAction = ActionFactory.createMouseCenteredZoomAction(1.2);
+        this.getActions().addAction(zoomAction);
+        this.getView().addMouseWheelListener(mouseWheelListener);
         this.getActions().addAction(ActionFactory.createPopupMenuAction(popupMenuProvider));
 
+        this.getActions().addAction(ActionFactory.createWheelPanAction());
+
         LayerWidget selectLayer = new LayerWidget(this);
         this.addChild(selectLayer);
         this.getActions().addAction(ActionFactory.createRectangularSelectAction(rectangularSelectDecorator, selectLayer, rectangularSelectProvider));
 
-        blockWidgets = new HashMap<InputBlock, BlockWidget>();
-
         boolean b = this.getUndoRedoEnabled();
         this.setUndoRedoEnabled(false);
         this.setNewModel(model);
         this.setUndoRedoEnabled(b);
-    }
-
-    private void selectionUpdated() {
-        getModel().setSelectedNodes(this.getSelectedNodes());
-        addUndo();
+        this.addObjectSceneListener(selectionChangedListener, ObjectSceneEventType.OBJECT_SELECTION_CHANGED, ObjectSceneEventType.OBJECT_HIGHLIGHTING_CHANGED, ObjectSceneEventType.OBJECT_HOVER_CHANGED);
     }
 
     public DiagramViewModel getModel() {
         return model;
     }
 
-    public void setRealZoomFactor(double d) {
-        this.realZoomFactor = d;
-    }
-
-    public double getRealZoomFactor() {
-        if (realZoomFactor == 0.0) {
-            return getZoomFactor();
-        } else {
-            return realZoomFactor;
-        }
-    }
-
     public JScrollPane getScrollPane() {
         return scrollPane;
     }
 
+    @Override
+    public Component getComponent() {
+        return scrollPane;
+    }
+
     public boolean isAllVisible() {
-        return getModel().getHiddenNodes().size() == 0;
+        return getModel().getHiddenNodes().isEmpty();
     }
 
     public Action createGotoAction(final Figure f) {
         final DiagramScene diagramScene = this;
-        Action a = new AbstractAction() {
-
-            public void actionPerformed(ActionEvent e) {
-                diagramScene.gotoFigure(f);
-            }
-        };
-
-        a.setEnabled(true);
-        a.putValue(Action.SMALL_ICON, new ColorIcon(f.getColor()));
         String name = f.getLines()[0];
 
         name += " (";
@@ -469,112 +470,81 @@
         if (f.getCluster() != null) {
             name += "B" + f.getCluster().toString();
         }
-        if (!this.getFigureWidget(f).isVisible()) {
+        final boolean hidden = !this.getWidget(f, FigureWidget.class).isVisible();
+        if (hidden) {
             if (f.getCluster() != null) {
                 name += ", ";
             }
             name += "hidden";
         }
         name += ")";
-        a.putValue(Action.NAME, name);
+        Action a = new AbstractAction(name, new ColorIcon(f.getColor())) {
+
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                diagramScene.gotoFigure(f);
+            }
+        };
+
+        a.setEnabled(true);
         return a;
     }
 
     public void setNewModel(DiagramViewModel model) {
-        if (this.model != null) {
-            this.model.getDiagramChangedEvent().removeListener(this);
-            this.model.getViewPropertiesChangedEvent().removeListener(this);
-        }
+        assert this.model == null : "can set model only once!";
         this.model = model;
+        this.modelCopy = null;
 
-        if (this.model == null) {
-            this.modelCopy = null;
-        } else {
-            this.modelCopy = this.model.copy();
-        }
-
-        model.getDiagramChangedEvent().addListener(this);
-        model.getViewPropertiesChangedEvent().addListener(this);
-
+        model.getDiagramChangedEvent().addListener(fullChange);
+        model.getViewPropertiesChangedEvent().addListener(fullChange);
+        model.getViewChangedEvent().addListener(selectionChange);
+        model.getHiddenNodesChangedEvent().addListener(hiddenNodesChange);
         update();
     }
 
     private void update() {
-
-        /*if (startLabel != null) {
-        // Animate fade-out
-        final LabelWidget labelWidget = this.startLabel;
-        labelWidget.setVisible(true);
-        RequestProcessor.getDefault().post(new Runnable() {
-        public void run() {
-        final int Sleep = 200;
-        final int Progress = 10;
-        for (int i = 0; i < 255 / Progress + 1; i++) {
-        try {
-        SwingUtilities.invokeAndWait(new Runnable() {
-        public void run() {
-        Color c = labelWidget.getForeground();
-        int v = c.getRed();
-        v += Progress;
-        if (v > 255) {
-        v = 255;
-        }
-        labelWidget.setForeground(new Color(v, v, v, 255 - v));
-        labelWidget.getScene().validate();
-        }
-        });
-        } catch (InterruptedException ex) {
-        } catch (InvocationTargetException ex) {
-        }
-        try {
-        Thread.sleep(Sleep);
-        } catch (InterruptedException ex) {
-        }
-        }
-        labelWidget.setVisible(false);
-        DiagramScene.this.scrollChangeListener.unregister(labelWidget);
-        }
-        }, 1000);
-        startLabel = null;
-        }*/
-
-        slotLayer.removeChildren();
         mainLayer.removeChildren();
         blockLayer.removeChildren();
 
-        blockWidgets.clear();
-        figureWidgets = new HashMap<Figure, FigureWidget>();
-        slotWidgets = new HashMap<Slot, SlotWidget>();
-        connectionWidgets = new HashMap<Connection, ConnectionWidget>();
+        rebuilding = true;
 
-        WidgetAction selectAction = new ExtendedSelectAction(selectProvider);
+        Collection<Object> objects = new ArrayList<>(this.getObjects());
+        for (Object o : objects) {
+            this.removeObject(o);
+        }
+
         Diagram d = getModel().getDiagramToView();
 
-        if (getModel().getShowBlocks()) {
+        if (d.getGraph().getBlocks().isEmpty()) {
             Scheduler s = Lookup.getDefault().lookup(Scheduler.class);
-            Collection<InputBlock> newBlocks = new ArrayList<InputBlock>(s.schedule(d.getGraph()));
-            d.schedule(newBlocks);
+            d.getGraph().clearBlocks();
+            s.schedule(d.getGraph());
+            d.getGraph().ensureNodesInBlocks();
+            d.updateBlocks();
         }
 
         for (Figure f : d.getFigures()) {
-            FigureWidget w = new FigureWidget(f, this, mainLayer);
+            FigureWidget w = new FigureWidget(f, hoverAction, selectAction, this, mainLayer);
+            w.getActions().addAction(ActionFactory.createPopupMenuAction(w));
             w.getActions().addAction(selectAction);
             w.getActions().addAction(hoverAction);
-            w.getActions().addAction(ActionFactory.createPopupMenuAction(w));
-            w.getActions().addAction(new DoubleClickAction(w));
             w.setVisible(false);
 
-            figureWidgets.put(f, w);
+            this.addObject(f, w);
 
             for (InputSlot s : f.getInputSlots()) {
-                SlotWidget sw = new InputSlotWidget(s, this, slotLayer, w);
-                slotWidgets.put(s, sw);
+                SlotWidget sw = new InputSlotWidget(s, this, w, w);
+                addObject(s, sw);
+                sw.getActions().addAction(new DoubleClickAction(sw));
+                sw.getActions().addAction(hoverAction);
                 sw.getActions().addAction(selectAction);
             }
 
             for (OutputSlot s : f.getOutputSlots()) {
-                SlotWidget sw = new OutputSlotWidget(s, this, slotLayer, w);
-                slotWidgets.put(s, sw);
+                SlotWidget sw = new OutputSlotWidget(s, this, w, w);
+                addObject(s, sw);
+                sw.getActions().addAction(new DoubleClickAction(sw));
+                sw.getActions().addAction(hoverAction);
                 sw.getActions().addAction(selectAction);
             }
         }
@@ -583,28 +553,30 @@
             for (InputBlock bn : d.getGraph().getBlocks()) {
                 BlockWidget w = new BlockWidget(this, d, bn);
                 w.setVisible(false);
-                blockWidgets.put(bn, w);
+                this.addObject(bn, w);
                 blockLayer.addChild(w);
             }
         }
 
+        rebuilding = false;
         this.smallUpdate(true);
+    }
 
+    public boolean isRebuilding() {
+        return rebuilding;
     }
 
     private void smallUpdate(boolean relayout) {
-
         this.updateHiddenNodes(model.getHiddenNodes(), relayout);
         boolean b = this.getUndoRedoEnabled();
         this.setUndoRedoEnabled(false);
-        this.setSelection(getModel().getSelectedNodes());
         this.setUndoRedoEnabled(b);
         this.validate();
     }
 
     private boolean isVisible(Connection c) {
-        FigureWidget w1 = figureWidgets.get(c.getInputSlot().getFigure());
-        FigureWidget w2 = figureWidgets.get(c.getOutputSlot().getFigure());
+        FigureWidget w1 = getWidget(c.getInputSlot().getFigure());
+        FigureWidget w2 = getWidget(c.getOutputSlot().getFigure());
 
         if (w1.isVisible() && w2.isVisible()) {
             return true;
@@ -614,19 +586,18 @@
     }
 
     private void relayout(Set<Widget> oldVisibleWidgets) {
-
         Diagram diagram = getModel().getDiagramToView();
 
-        HashSet<Figure> figures = new HashSet<Figure>();
+        HashSet<Figure> figures = new HashSet<>();
 
         for (Figure f : diagram.getFigures()) {
-            FigureWidget w = figureWidgets.get(f);
+            FigureWidget w = getWidget(f);
             if (w.isVisible()) {
                 figures.add(f);
             }
         }
 
-        HashSet<Connection> edges = new HashSet<Connection>();
+        HashSet<Connection> edges = new HashSet<>();
 
         for (Connection c : diagram.getConnections()) {
             if (isVisible(c)) {
@@ -635,24 +606,31 @@
         }
 
         if (getModel().getShowBlocks()) {
-            HierarchicalClusterLayoutManager m = new HierarchicalClusterLayoutManager(OldHierarchicalLayoutManager.Combine.SAME_OUTPUTS);
+            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<>();
+
+    private void relayoutWithoutLayout(Set<Widget> oldVisibleWidgets) {
+
+        Diagram diagram = getModel().getDiagramToView();
+
         int maxX = -BORDER_SIZE;
         int maxY = -BORDER_SIZE;
         for (Figure f : diagram.getFigures()) {
-            FigureWidget w = figureWidgets.get(f);
+            FigureWidget w = getWidget(f);
             if (w.isVisible()) {
                 Point p = f.getPosition();
                 Dimension d = f.getSize();
@@ -663,8 +641,8 @@
 
         for (Connection c : diagram.getConnections()) {
             List<Point> points = c.getControlPoints();
-            FigureWidget w1 = figureWidgets.get((Figure) c.getTo().getVertex());
-            FigureWidget w2 = figureWidgets.get((Figure) c.getFrom().getVertex());
+            FigureWidget w1 = getWidget((Figure) c.getTo().getVertex());
+            FigureWidget w2 = getWidget((Figure) c.getFrom().getVertex());
             if (w1.isVisible() && w2.isVisible()) {
                 for (Point p : points) {
                     if (p != null) {
@@ -677,7 +655,7 @@
 
         if (getModel().getShowBlocks()) {
             for (Block b : diagram.getBlocks()) {
-                BlockWidget w = blockWidgets.get(b.getInputBlock());
+                BlockWidget w = getWidget(b.getInputBlock());
                 if (w != null && w.isVisible()) {
                     Rectangle r = b.getBounds();
                     maxX = Math.max(maxX, r.x + r.width);
@@ -693,6 +671,8 @@
         int curHeight = maxY + 2 * BORDER_SIZE;
 
         Rectangle bounds = this.getScrollPane().getBounds();
+        bounds.width /= getZoomFactor();
+        bounds.height /= getZoomFactor();
         if (curWidth < bounds.width) {
             offx = (bounds.width - curWidth) / 2;
         }
@@ -708,62 +688,61 @@
         connectionLayer.removeChildren();
         int visibleFigureCount = 0;
         for (Figure f : diagram.getFigures()) {
-            if (figureWidgets.get(f).isVisible()) {
+            if (getWidget(f, FigureWidget.class).isVisible()) {
                 visibleFigureCount++;
             }
         }
 
+
+        Set<Pair<Point, Point>> lastLineCache = lineCache;
+        lineCache = new HashSet<>();
+        for (Figure f : diagram.getFigures()) {
+            for (OutputSlot s : f.getOutputSlots()) {
+                SceneAnimator anim = animator;
+                if (visibleFigureCount > ANIMATION_LIMIT || oldVisibleWidgets == null) {
+                    anim = null;
+                }
+                processOutputSlot(lastLineCache, s, s.getConnections(), 0, null, null, offx2, offy2, anim);
+            }
+        }
+
         for (Figure f : diagram.getFigures()) {
-            for (OutputSlot s : f.getOutputSlots()) {
-                SceneAnimator anim = animator;
-                if (visibleFigureCount > ANIMATION_LIMIT) {
-                    anim = null;
-                }
-                processOutputSlot(s, s.getConnections(), 0, null, null, offx2, offy2, anim);
-            }
-        }
-
-        for (Figure f : diagram.getFigures()) {
-            FigureWidget w = figureWidgets.get(f);
+            FigureWidget w = getWidget(f);
             if (w.isVisible()) {
                 Point p = f.getPosition();
                 Point p2 = new Point(p.x + offx2, p.y + offy2);
-                Rectangle r = new Rectangle(p.x + offx2, p.y + offy2, f.getSize().width, f.getSize().height);
-                if (oldVisibleWidgets.contains(w)) {
-                    if (visibleFigureCount > ANIMATION_LIMIT) {
-                        w.setPreferredLocation(p2);
-                    } else {
-                        animator.animatePreferredLocation(w, p2);
-                    }
+                if ((visibleFigureCount <= ANIMATION_LIMIT && oldVisibleWidgets != null && oldVisibleWidgets.contains(w))) {
+                    animator.animatePreferredLocation(w, p2);
                 } else {
                     w.setPreferredLocation(p2);
+                    animator.animatePreferredLocation(w, p2);
                 }
             }
         }
 
         if (getModel().getShowBlocks()) {
             for (Block b : diagram.getBlocks()) {
-                BlockWidget w = blockWidgets.get(b.getInputBlock());
+                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 (oldVisibleWidgets.contains(w)) {
-                        if (visibleFigureCount > ANIMATION_LIMIT) {
-                            w.setPreferredBounds(r);
-                        } else {
-                            animator.animatePreferredBounds(w, r);
-                        }
+
+                    if ((visibleFigureCount <= ANIMATION_LIMIT && oldVisibleWidgets != null && oldVisibleWidgets.contains(w))) {
+                        animator.animatePreferredBounds(w, r);
                     } else {
                         w.setPreferredBounds(r);
+                        animator.animatePreferredBounds(w, r);
                     }
                 }
             }
         }
+
+        this.validate();
     }
     private final Point specialNullPoint = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE);
 
-    private void processOutputSlot(OutputSlot s, List<Connection> connections, int controlPointIndex, Point lastPoint, LineWidget predecessor, int offx, int offy, SceneAnimator animator) {
-        Map<Point, List<Connection>> pointMap = new HashMap<Point, List<Connection>>();
+    private void processOutputSlot(Set<Pair<Point, Point>> lastLineCache, OutputSlot s, List<Connection> connections, int controlPointIndex, Point lastPoint, LineWidget predecessor, int offx, int offy, SceneAnimator animator) {
+        Map<Point, List<Connection>> pointMap = new HashMap<>(connections.size());
 
         for (Connection c : connections) {
 
@@ -779,16 +758,16 @@
             Point cur = controlPoints.get(controlPointIndex);
             if (cur == null) {
                 cur = specialNullPoint;
-            } else if (controlPointIndex == 0 && !s.getShowName()) {
+            } else if (controlPointIndex == 0 && !s.shouldShowName()) {
                 cur = new Point(cur.x, cur.y - SLOT_OFFSET);
-            } else if (controlPointIndex == controlPoints.size() - 1 && !c.getInputSlot().getShowName()) {
+            } else if (controlPointIndex == controlPoints.size() - 1 && !c.getInputSlot().shouldShowName()) {
                 cur = new Point(cur.x, cur.y + SLOT_OFFSET);
             }
 
             if (pointMap.containsKey(cur)) {
                 pointMap.get(cur).add(c);
             } else {
-                List<Connection> newList = new ArrayList<Connection>(2);
+                List<Connection> newList = new ArrayList<>(2);
                 newList.add(c);
                 pointMap.put(cur, newList);
             }
@@ -814,44 +793,70 @@
 
             LineWidget newPredecessor = predecessor;
             if (p == specialNullPoint) {
-
             } else if (lastPoint == specialNullPoint) {
-
             } else if (lastPoint != null) {
                 Point p1 = new Point(lastPoint.x + offx, lastPoint.y + offy);
                 Point p2 = new Point(p.x + offx, p.y + offy);
-                LineWidget w = new LineWidget(this, s, connectionList, p1, p2, predecessor, animator, isBold, isDashed);
+
+                Pair<Point, Point> curPair = new Pair<>(p1, p2);
+                SceneAnimator curAnimator = animator;
+                if (lastLineCache.contains(curPair)) {
+                    curAnimator = null;
+                }
+                LineWidget w = new LineWidget(this, s, connectionList, p1, p2, predecessor, curAnimator, isBold, isDashed);
+                lineCache.add(curPair);
+
                 newPredecessor = w;
                 connectionLayer.addChild(w);
+                this.addObject(new ConnectionSet(connectionList), w);
                 w.getActions().addAction(hoverAction);
             }
 
-            processOutputSlot(s, connectionList, controlPointIndex + 1, p, newPredecessor, offx, offy, animator);
+            processOutputSlot(lastLineCache, s, connectionList, controlPointIndex + 1, p, newPredecessor, offx, offy, animator);
         }
     }
 
-    private void clearSelection() {
-        if (selectedWidgets.size() == 0) {
-            return;
-        }
-        for (FigureWidget w : selectedWidgets) {
-            assert w.getState().isSelected();
-            w.setState(w.getState().deriveSelected(false));
-            content.remove(w.getNode());
-        }
-        selectedWidgets.clear();
+    @Override
+    public void setInteractionMode(InteractionMode mode) {
+        panAction.setEnabled(mode == InteractionMode.PANNING);
+        // When panAction is not enabled, it does not consume the event
+        // and the selection action handles it instead
     }
 
+    private class ConnectionSet {
+
+        private Set<Connection> connections;
+
+        public ConnectionSet(Collection<Connection> connections) {
+            connections = new HashSet<>(connections);
+        }
+
+        public Set<Connection> getConnectionSet() {
+            return Collections.unmodifiableSet(connections);
+        }
+    }
+
+    @Override
     public Lookup getLookup() {
         return lookup;
     }
 
+    @Override
+    public void initialize() {
+        Figure f = getModel().getDiagramToView().getRootFigure();
+        if (f != null) {
+            setUndoRedoEnabled(false);
+            gotoFigure(f);
+            setUndoRedoEnabled(true);
+        }
+    }
+
     public void gotoFigures(final List<Figure> figures) {
         Rectangle overall = null;
-        showFigures(figures);
+        getModel().showFigures(figures);
         for (Figure f : figures) {
 
-            FigureWidget fw = getFigureWidget(f);
+            FigureWidget fw = getWidget(f);
             if (fw != null) {
                 Rectangle r = fw.getBounds();
                 Point p = fw.getLocation();
@@ -869,6 +874,54 @@
         }
     }
 
+    private Set<Object> idSetToObjectSet(Set<Object> ids) {
+
+        Set<Object> result = new HashSet<>();
+        for (Figure f : getModel().getDiagramToView().getFigures()) {
+            if (DiagramScene.doesIntersect(f.getSource().getSourceNodesAsSet(), ids)) {
+                result.add(f);
+            }
+
+            for (Slot s : f.getSlots()) {
+                if (DiagramScene.doesIntersect(s.getSource().getSourceNodesAsSet(), ids)) {
+                    result.add(s);
+                }
+            }
+        }
+        return result;
+    }
+
+    public void gotoSelection(Set<Object> ids) {
+
+        Rectangle overall = null;
+        Set<Integer> hiddenNodes = new HashSet<>(this.getModel().getHiddenNodes());
+        hiddenNodes.removeAll(ids);
+        this.getModel().showNot(hiddenNodes);
+
+        Set<Object> objects = idSetToObjectSet(ids);
+        for (Object o : objects) {
+
+            Widget w = getWidget(o);
+            if (w != null) {
+                Rectangle r = w.getBounds();
+                Point p = w.convertLocalToScene(new Point(0, 0));
+
+                Rectangle r2 = new Rectangle(p.x, p.y, r.width, r.height);
+
+                if (overall == null) {
+                    overall = r2;
+                } else {
+                    overall = overall.union(r2);
+                }
+            }
+        }
+        if (overall != null) {
+            centerRectangle(overall);
+        }
+
+        setSelectedObjects(objects);
+    }
+
     private Point calcCenter(Rectangle r) {
 
         Point center = new Point((int) r.getCenterX(), (int) r.getCenterY());
@@ -909,63 +962,9 @@
         }
     }
 
-    private void addToSelection(Figure f) {
-        FigureWidget w = getFigureWidget(f);
-        addToSelection(w);
-    }
-
-    private void addToSelection(FigureWidget w) {
-        assert !selectedWidgets.contains(w);
-        selectedWidgets.add(w);
-        content.add(w.getNode());
-        w.setState(w.getState().deriveSelected(true));
-    }
-
-    private void setSelection(Set<Integer> nodes) {
-        clearSelection();
-        for (Figure f : getModel().getDiagramToView().getFigures()) {
-            if (doesIntersect(f.getSource().getSourceNodesAsSet(), nodes)) {
-                addToSelection(f);
-            }
-        }
-        selectionUpdated();
-        this.validate();
-    }
-
+    @Override
     public void setSelection(Collection<Figure> list) {
-        clearSelection();
-        for (Figure f : list) {
-            addToSelection(f);
-        }
-
-        selectionUpdated();
-        this.validate();
-    }
-
-    public Set<Figure> getSelectedFigures() {
-        Set<Figure> result = new HashSet<Figure>();
-        for (Widget w : selectedWidgets) {
-            if (w instanceof FigureWidget) {
-                FigureWidget fw = (FigureWidget) w;
-                if (fw.getState().isSelected()) {
-                    result.add(fw.getFigure());
-                }
-            }
-        }
-        return result;
-    }
-
-    public Set<Integer> getSelectedNodes() {
-        Set<Integer> result = new HashSet<Integer>();
-        for (Widget w : selectedWidgets) {
-            if (w instanceof FigureWidget) {
-                FigureWidget fw = (FigureWidget) w;
-                if (fw.getState().isSelected()) {
-                    result.addAll(fw.getFigure().getSource().getSourceNodesAsSet());
-                }
-            }
-        }
-        return result;
+        super.setSelectedObjects(new HashSet<>(list));
     }
 
     private UndoRedo.Manager getUndoRedoManager() {
@@ -977,6 +976,7 @@
         return undoRedoManager;
     }
 
+    @Override
     public UndoRedo getUndoRedo() {
         return getUndoRedoManager();
     }
@@ -990,9 +990,9 @@
         return true;
     }
 
-    private boolean doesIntersect(Set s1, Set s2) {
+    public static boolean doesIntersect(Set<?> s1, Set<?> s2) {
         if (s1.size() > s2.size()) {
-            Set tmp = s1;
+            Set<?> tmp = s1;
             s1 = s2;
             s2 = tmp;
         }
@@ -1006,35 +1006,36 @@
         return false;
     }
 
-    public void showNot(final Set<Integer> nodes) {
-        updateHiddenNodes(nodes, true);
+    @Override
+    public void componentHidden() {
+        SelectionCoordinator.getInstance().getHighlightedChangedEvent().removeListener(highlightedCoordinatorListener);
+        SelectionCoordinator.getInstance().getSelectedChangedEvent().removeListener(selectedCoordinatorListener);
     }
 
-    public void showOnly(final Set<Integer> nodes) {
-        HashSet<Integer> allNodes = new HashSet<Integer>(getModel().getGraphToView().getGroup().getAllNodes());
-        allNodes.removeAll(nodes);
-        updateHiddenNodes(allNodes, true);
+    @Override
+    public void componentShowing() {
+        SelectionCoordinator.getInstance().getHighlightedChangedEvent().addListener(highlightedCoordinatorListener);
+        SelectionCoordinator.getInstance().getSelectedChangedEvent().addListener(selectedCoordinatorListener);
     }
 
     private void updateHiddenNodes(Set<Integer> newHiddenNodes, boolean doRelayout) {
 
-        Set<InputBlock> visibleBlocks = new HashSet<InputBlock>();
-
         Diagram diagram = getModel().getDiagramToView();
         assert diagram != null;
 
-        Set<Widget> oldVisibleWidgets = new HashSet<Widget>();
+        Set<InputBlock> visibleBlocks = new HashSet<InputBlock>();
+        Set<Widget> oldVisibleWidgets = new HashSet<>();
 
         for (Figure f : diagram.getFigures()) {
-            FigureWidget w = figureWidgets.get(f);
-            if (w.isVisible()) {
+            FigureWidget w = getWidget(f);
+            if (w != null && w.isVisible()) {
                 oldVisibleWidgets.add(w);
             }
         }
 
         if (getModel().getShowBlocks()) {
             for (InputBlock b : diagram.getGraph().getBlocks()) {
-                BlockWidget w = blockWidgets.get(b);
+                BlockWidget w = getWidget(b);
                 if (w.isVisible()) {
                     oldVisibleWidgets.add(w);
                 }
@@ -1044,7 +1045,7 @@
         for (Figure f : diagram.getFigures()) {
             boolean hiddenAfter = doesIntersect(f.getSource().getSourceNodesAsSet(), newHiddenNodes);
 
-            FigureWidget w = this.figureWidgets.get(f);
+            FigureWidget w = getWidget(f);
             w.setBoundary(false);
             if (!hiddenAfter) {
                 // Figure is shown
@@ -1059,16 +1060,16 @@
         }
 
         if (getModel().getShowNodeHull()) {
-            List<FigureWidget> boundaries = new ArrayList<FigureWidget>();
+            List<FigureWidget> boundaries = new ArrayList<>();
             for (Figure f : diagram.getFigures()) {
-                FigureWidget w = this.figureWidgets.get(f);
+                FigureWidget w = getWidget(f);
                 if (!w.isVisible()) {
-                    Set<Figure> set = new HashSet<Figure>(f.getPredecessorSet());
+                    Set<Figure> set = new HashSet<>(f.getPredecessorSet());
                     set.addAll(f.getSuccessorSet());
 
                     boolean b = false;
                     for (Figure neighbor : set) {
-                        FigureWidget neighborWidget = figureWidgets.get(neighbor);
+                        FigureWidget neighborWidget = getWidget(neighbor);
                         if (neighborWidget.isVisible()) {
                             b = true;
                             break;
@@ -1097,7 +1098,7 @@
 
                 boolean visibleAfter = visibleBlocks.contains(b);
 
-                BlockWidget w = blockWidgets.get(b);
+                BlockWidget w = getWidget(b);
                 if (visibleAfter) {
                     // Block must be shown
                     w.setVisible(true);
@@ -1108,7 +1109,6 @@
             }
         }
 
-        getModel().setHiddenNodes(newHiddenNodes);
         if (doRelayout) {
             relayout(oldVisibleWidgets);
         }
@@ -1116,51 +1116,50 @@
         addUndo();
     }
 
-    private void showFigures(Collection<Figure> f) {
-        HashSet<Integer> newHiddenNodes = new HashSet<Integer>(getModel().getHiddenNodes());
-        for (Figure fig : f) {
-            newHiddenNodes.removeAll(fig.getSource().getSourceNodesAsSet());
-        }
-        updateHiddenNodes(newHiddenNodes, true);
-    }
-
     private void showFigure(Figure f) {
-        HashSet<Integer> newHiddenNodes = new HashSet<Integer>(getModel().getHiddenNodes());
+        HashSet<Integer> newHiddenNodes = new HashSet<>(getModel().getHiddenNodes());
         newHiddenNodes.removeAll(f.getSource().getSourceNodesAsSet());
-        updateHiddenNodes(newHiddenNodes, true);
-    }
-
-    public void showAll(final Collection<Figure> f) {
-        showFigures(f);
-
+        this.model.setHiddenNodes(newHiddenNodes);
     }
 
     public void show(final Figure f) {
         showFigure(f);
     }
 
+    public void setSelectedObjects(Object... args) {
+        Set<Object> set = new HashSet<>();
+        for (Object o : args) {
+            set.add(o);
+        }
+        super.setSelectedObjects(set);
+    }
+
+    private void centerWidget(Widget w) {
+        Rectangle r = w.getBounds();
+        Point p = w.getLocation();
+        centerRectangle(new Rectangle(p.x, p.y, r.width, r.height));
+    }
+
     public void gotoFigure(final Figure f) {
-
         if (!isVisible(f)) {
             showFigure(f);
         }
 
-        FigureWidget fw = getFigureWidget(f);
+        FigureWidget fw = getWidget(f);
         if (fw != null) {
-            Rectangle r = fw.getBounds();
-            Point p = fw.getLocation();
-            centerRectangle(new Rectangle(p.x, p.y, r.width, r.height));
-
-            // Select figure
-            clearSelection();
-            addToSelection(fw);
-            selectionUpdated();
+            centerWidget(fw);
+            setSelection(Arrays.asList(f));
         }
     }
 
     public JPopupMenu createPopupMenu() {
         JPopupMenu menu = new JPopupMenu();
-        for (Action a : actions) {
+
+        Action[] currentActions = actionsWithSelection;
+        if (this.getSelectedObjects().isEmpty()) {
+            currentActions = actions;
+        }
+        for (Action a : currentActions) {
             if (a == null) {
                 menu.addSeparator();
             } else {
@@ -1208,6 +1207,7 @@
 
             SwingUtilities.invokeLater(new Runnable() {
 
+                @Override
                 public void run() {
                     scene.setScrollPosition(oldScrollPosition);
                 }
@@ -1216,9 +1216,10 @@
             scene.setUndoRedoEnabled(b);
         }
 
+        @Override
         public void changed(DiagramViewModel source) {
             scene.getModel().getViewChangedEvent().removeListener(this);
-            if (oldModel.getSelectedNodes().equals(newModel.getHiddenNodes())) {
+            if (oldModel.getHiddenNodes().equals(newModel.getHiddenNodes())) {
                 scene.smallUpdate(false);
             } else {
                 scene.smallUpdate(true);
@@ -1235,11 +1236,33 @@
         return undoRedoEnabled;
     }
 
-    public void changed(DiagramViewModel source) {
-        assert source == model : "Receive only changed event from current model!";
-        assert source != null;
-        update();
-    }
+    private final ChangedListener<DiagramViewModel> fullChange = new ChangedListener<DiagramViewModel>() {
+        @Override
+        public void changed(DiagramViewModel source) {
+            assert source == model : "Receive only changed event from current model!";
+            assert source != null;
+            update();
+        }
+    };
+
+    private final ChangedListener<DiagramViewModel> hiddenNodesChange = new ChangedListener<DiagramViewModel>() {
+        @Override
+        public void changed(DiagramViewModel source) {
+            assert source == model : "Receive only changed event from current model!";
+            assert source != null;
+            smallUpdate(true);
+        }
+    };
+
+    private final ChangedListener<DiagramViewModel> selectionChange = new ChangedListener<DiagramViewModel>() {
+        @Override
+        public void changed(DiagramViewModel source) {
+            assert source == model : "Receive only changed event from current model!";
+            assert source != null;
+            smallUpdate(false);
+        }
+    };
+
 
     private void addUndo() {
 
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -24,22 +24,16 @@
  */
 package com.sun.hotspot.igv.view;
 
-import com.sun.hotspot.igv.data.Group;
-import com.sun.hotspot.igv.data.InputGraph;
-import com.sun.hotspot.igv.data.InputNode;
+import com.sun.hotspot.igv.data.*;
 import com.sun.hotspot.igv.difference.Difference;
+import com.sun.hotspot.igv.filter.CustomFilter;
 import com.sun.hotspot.igv.filter.FilterChain;
 import com.sun.hotspot.igv.graph.Diagram;
-import com.sun.hotspot.igv.data.ChangedEvent;
+import com.sun.hotspot.igv.graph.Figure;
+import com.sun.hotspot.igv.settings.Settings;
 import com.sun.hotspot.igv.util.RangeSliderModel;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import com.sun.hotspot.igv.data.ChangedListener;
-import com.sun.hotspot.igv.settings.Settings;
 import java.awt.Color;
+import java.util.*;
 
 /**
  *
@@ -49,20 +43,25 @@
 
     // Warning: Update setData method if fields are added
     private Group group;
+    private ArrayList<InputGraph> graphs;
     private Set<Integer> hiddenNodes;
     private Set<Integer> onScreenNodes;
     private Set<Integer> selectedNodes;
     private FilterChain filterChain;
     private FilterChain sequenceFilterChain;
     private Diagram diagram;
+    private InputGraph inputGraph;
     private ChangedEvent<DiagramViewModel> groupChangedEvent;
     private ChangedEvent<DiagramViewModel> diagramChangedEvent;
     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>() {
 
+        @Override
         public void changed(FilterChain source) {
             diagramChanged();
         }
@@ -75,6 +74,10 @@
         return result;
     }
 
+    public Group getGroup() {
+        return group;
+    }
+
     public void setData(DiagramViewModel newModel) {
         super.setData(newModel);
         boolean diagramChanged = false;
@@ -83,6 +86,10 @@
 
         boolean groupChanged = (group == newModel.group);
         this.group = newModel.group;
+        if (groupChanged) {
+            filterGraphs();
+        }
+
         diagramChanged |= (filterChain != newModel.filterChain);
         this.filterChain = newModel.filterChain;
         diagramChanged |= (sequenceFilterChain != newModel.sequenceFilterChain);
@@ -100,7 +107,7 @@
         viewPropertiesChanged |= (showNodeHull != newModel.showNodeHull);
         this.showNodeHull = newModel.showNodeHull;
 
-        if(groupChanged) {
+        if (groupChanged) {
             groupChangedEvent.fire();
         }
 
@@ -133,53 +140,75 @@
         viewPropertiesChangedEvent.fire();
     }
 
-    public DiagramViewModel(Group g, FilterChain filterChain, FilterChain sequenceFilterChain) {
-        super(calculateStringList(g));
+    public boolean getHideDuplicates() {
+        return hideDuplicates;
+    }
 
+    public void setHideDuplicates(boolean b) {
+        System.err.println("setHideDuplicates: " + b);
+        hideDuplicates = b;
+        InputGraph currentGraph = getFirstGraph();
+        if (hideDuplicates) {
+            // Back up to the unhidden equivalent graph
+            int index = graphs.indexOf(currentGraph);
+            while (graphs.get(index).getProperties().get("_isDuplicate") != null) {
+                index--;
+            }
+            currentGraph = graphs.get(index);
+        }
+        filterGraphs();
+        selectGraph(currentGraph);
+        viewPropertiesChangedEvent.fire();
+    }
+
+    public DiagramViewModel(Group g, FilterChain filterChain, FilterChain sequenceFilterChain) {
+        super(Arrays.asList("default"));
+
+        this.showBlocks = false;
         this.showNodeHull = true;
-        this.showBlocks = true;
         this.group = g;
+        filterGraphs();
         assert filterChain != null;
         this.filterChain = filterChain;
         assert sequenceFilterChain != null;
         this.sequenceFilterChain = sequenceFilterChain;
-        hiddenNodes = new HashSet<Integer>();
-        onScreenNodes = new HashSet<Integer>();
-        selectedNodes = new HashSet<Integer>();
+        hiddenNodes = new HashSet<>();
+        onScreenNodes = new HashSet<>();
+        selectedNodes = new HashSet<>();
         super.getChangedEvent().addListener(this);
-        diagramChangedEvent = new ChangedEvent<DiagramViewModel>(this);
-        viewChangedEvent = new ChangedEvent<DiagramViewModel>(this);
-        viewPropertiesChangedEvent = new ChangedEvent<DiagramViewModel>(this);
-        groupChangedEvent = new ChangedEvent<DiagramViewModel>(this);
+        diagramChangedEvent = new ChangedEvent<>(this);
+        viewChangedEvent = new ChangedEvent<>(this);
+        hiddenNodesChangedEvent = new ChangedEvent<>(this);
+        viewPropertiesChangedEvent = new ChangedEvent<>(this);
+
+        groupChangedEvent = new ChangedEvent<>(this);
         groupChangedEvent.addListener(groupChangedListener);
         groupChangedEvent.fire();
 
         filterChain.getChangedEvent().addListener(filterChainChangedListener);
         sequenceFilterChain.getChangedEvent().addListener(filterChainChangedListener);
     }
-
     private final ChangedListener<DiagramViewModel> groupChangedListener = new ChangedListener<DiagramViewModel>() {
 
         private Group oldGroup;
 
+        @Override
         public void changed(DiagramViewModel source) {
-            if(oldGroup != null) {
+            if (oldGroup != null) {
                 oldGroup.getChangedEvent().removeListener(groupContentChangedListener);
             }
             group.getChangedEvent().addListener(groupContentChangedListener);
             oldGroup = group;
         }
     };
-
-
     private final ChangedListener<Group> groupContentChangedListener = new ChangedListener<Group>() {
 
+        @Override
         public void changed(Group source) {
             assert source == group;
-            setPositions(calculateStringList(source));
+            filterGraphs();
             setSelectedNodes(selectedNodes);
         }
-
     };
 
     public ChangedEvent<DiagramViewModel> getDiagramChangedEvent() {
@@ -190,25 +219,29 @@
         return viewChangedEvent;
     }
 
+    public ChangedEvent<DiagramViewModel> getHiddenNodesChangedEvent() {
+        return hiddenNodesChangedEvent;
+    }
+
     public ChangedEvent<DiagramViewModel> getViewPropertiesChangedEvent() {
         return viewPropertiesChangedEvent;
     }
 
     public Set<Integer> getSelectedNodes() {
-        return Collections.unmodifiableSet(selectedNodes);
+        return selectedNodes;
     }
 
     public Set<Integer> getHiddenNodes() {
-        return Collections.unmodifiableSet(hiddenNodes);
+        return hiddenNodes;
     }
 
     public Set<Integer> getOnScreenNodes() {
-        return Collections.unmodifiableSet(onScreenNodes);
+        return onScreenNodes;
     }
 
     public void setSelectedNodes(Set<Integer> nodes) {
         this.selectedNodes = nodes;
-        List<Color> colors = new ArrayList<Color>();
+        List<Color> colors = new ArrayList<>();
         for (String s : getPositions()) {
             colors.add(Color.black);
         }
@@ -219,14 +252,14 @@
                 }
                 InputNode last = null;
                 int index = 0;
-                for (InputGraph g : group.getGraphs()) {
+                for (InputGraph g : graphs) {
                     Color curColor = colors.get(index);
                     InputNode cur = g.getNode(id);
                     if (cur != null) {
                         if (last == null) {
                             curColor = Color.green;
                         } else {
-                            if (last.equals(cur)) {
+                            if (last.equals(cur) && last.getProperties().equals(cur.getProperties())) {
                                 if (curColor == Color.black) {
                                     curColor = Color.white;
                                 }
@@ -242,15 +275,49 @@
                     index++;
                 }
             }
-            this.setColors(colors);
         }
         setColors(colors);
         viewChangedEvent.fire();
     }
 
+    public void showNot(final Set<Integer> nodes) {
+        setHiddenNodes(nodes);
+    }
+
+    public void showFigures(Collection<Figure> f) {
+        HashSet<Integer> newHiddenNodes = new HashSet<>(getHiddenNodes());
+        for (Figure fig : f) {
+            newHiddenNodes.removeAll(fig.getSource().getSourceNodesAsSet());
+        }
+        setHiddenNodes(newHiddenNodes);
+    }
+
+
+    public Set<Figure> getSelectedFigures() {
+        Set<Figure> result = new HashSet<>();
+        for (Figure f : diagram.getFigures()) {
+            for (InputNode node : f.getSource().getSourceNodes()) {
+                if (getSelectedNodes().contains(node.getId())) {
+                    result.add(f);
+                }
+            }
+        }
+        return result;
+    }
+
+    public void showAll(final Collection<Figure> f) {
+        showFigures(f);
+    }
+
+    public void showOnly(final Set<Integer> nodes) {
+        final HashSet<Integer> allNodes = new HashSet<>(getGraphToView().getGroup().getAllNodes());
+        allNodes.removeAll(nodes);
+        setHiddenNodes(allNodes);
+    }
+
     public void setHiddenNodes(Set<Integer> nodes) {
         this.hiddenNodes = nodes;
-        viewChangedEvent.fire();
+        hiddenNodesChangedEvent.fire();
     }
 
     public void setOnScreenNodes(Set<Integer> onScreenNodes) {
@@ -289,27 +356,44 @@
         diagramChanged();
     }
 
-    private static List<String> calculateStringList(Group g) {
-        List<String> result = new ArrayList<String>();
-        for (InputGraph graph : g.getGraphs()) {
-            result.add(graph.getName());
+    /*
+     * Select the set of graphs to be presented.
+     */
+    private void filterGraphs() {
+        ArrayList<InputGraph> result = new ArrayList<>();
+        List<String> positions = new ArrayList<>();
+        for (InputGraph graph : group.getGraphs()) {
+            String duplicate = graph.getProperties().get("_isDuplicate");
+            if (duplicate == null || !hideDuplicates) {
+                result.add(graph);
+                positions.add(graph.getName());
+            }
         }
-        return result;
+        this.graphs = result;
+        setPositions(positions);
     }
 
     public InputGraph getFirstGraph() {
-        return group.getGraphs().get(getFirstPosition());
+        if (getFirstPosition() < graphs.size()) {
+            return graphs.get(getFirstPosition());
+        }
+        return graphs.get(graphs.size() - 1);
     }
 
     public InputGraph getSecondGraph() {
-        List<InputGraph> graphs = group.getGraphs();
-        if (graphs.size() >= getSecondPosition())
-            return group.getGraphs().get(getSecondPosition());
+        if (getSecondPosition() < graphs.size()) {
+            return graphs.get(getSecondPosition());
+        }
         return getFirstGraph();
     }
 
     public void selectGraph(InputGraph g) {
-        int index = group.getGraphs().indexOf(g);
+        int index = graphs.indexOf(g);
+        if (index == -1 && hideDuplicates) {
+            // A graph was selected that's currently hidden, so unhide and select it.
+            setHideDuplicates(false);
+            index = graphs.indexOf(g);
+        }
         assert index != -1;
         setPositions(index, index);
     }
@@ -319,22 +403,47 @@
         if (diagram == null) {
             diagram = Diagram.createDiagram(getGraphToView(), Settings.get().get(Settings.NODE_TEXT, Settings.NODE_TEXT_DEFAULT));
             getFilterChain().apply(diagram, getSequenceFilterChain());
+            if (getFirstPosition() != getSecondPosition()) {
+                CustomFilter f = new CustomFilter(
+                        "difference", "colorize('state', 'same', white);"
+                        + "colorize('state', 'changed', orange);"
+                        + "colorize('state', 'new', green);"
+                        + "colorize('state', 'deleted', red);");
+                f.apply(diagram);
+           }
         }
 
         return diagram;
     }
 
     public InputGraph getGraphToView() {
-        if (getFirstGraph() != getSecondGraph()) {
-            InputGraph inputGraph = Difference.createDiffGraph(getSecondGraph(), getFirstGraph());
-            return inputGraph;
-        } else {
-            InputGraph inputGraph = getFirstGraph();
-            return inputGraph;
+        if (inputGraph == null) {
+            if (getFirstGraph() != getSecondGraph()) {
+                inputGraph = Difference.createDiffGraph(getFirstGraph(), getSecondGraph());
+            } else {
+                inputGraph = getFirstGraph();
+            }
         }
+
+        return inputGraph;
     }
 
+    @Override
     public void changed(RangeSliderModel source) {
+        inputGraph = null;
         diagramChanged();
     }
+
+    void setSelectedFigures(List<Figure> list) {
+        Set<Integer> newSelectedNodes = new HashSet<>();
+        for (Figure f : list) {
+            newSelectedNodes.addAll(f.getSource().getSourceNodesAsSet());
+        }
+        this.setSelectedNodes(newSelectedNodes);
+    }
+
+    void close() {
+        filterChain.getChangedEvent().removeListener(filterChainChangedListener);
+        sequenceFilterChain.getChangedEvent().removeListener(filterChainChangedListener);
 }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewer.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,73 @@
+/*
+ * 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;
+
+import com.sun.hotspot.igv.graph.Figure;
+import java.awt.Component;
+import java.awt.Graphics2D;
+import java.util.Collection;
+import java.util.List;
+import javax.swing.JComponent;
+import org.openide.awt.UndoRedo;
+import org.openide.util.Lookup;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+interface DiagramViewer {
+
+    enum InteractionMode {
+        SELECTION,
+        PANNING,
+    }
+
+    public void paint(Graphics2D svgGenerator);
+
+    public Lookup getLookup();
+
+    public JComponent createSatelliteView();
+
+    public Component getComponent();
+
+    public void zoomOut();
+
+    public void zoomIn();
+
+    public UndoRedo getUndoRedo();
+
+    public void componentHidden();
+
+    public void componentShowing();
+
+    public void initialize();
+
+    public void setSelection(Collection<Figure> list);
+
+    public void centerFigures(List<Figure> list);
+
+    public void setInteractionMode(InteractionMode mode);
+
+}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorInputGraphProvider.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorInputGraphProvider.java	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, 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
@@ -25,8 +25,8 @@
 package com.sun.hotspot.igv.view;
 
 import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.InputNode;
 import com.sun.hotspot.igv.data.services.InputGraphProvider;
-import com.sun.hotspot.igv.data.InputNode;
 import java.util.Set;
 
 /**
@@ -35,18 +35,19 @@
  */
 public class EditorInputGraphProvider implements InputGraphProvider {
 
-    public InputGraph getGraph() {
-        EditorTopComponent e = EditorTopComponent.getActive();
-        if (e == null) {
-            return null;
-        }
-        return e.getDiagramModel().getGraphToView();
+    private EditorTopComponent editor;
+
+    public EditorInputGraphProvider(EditorTopComponent editor) {
+        this.editor = editor;
     }
 
+    @Override
+    public InputGraph getGraph() {
+        return editor.getDiagramModel().getGraphToView();
+    }
+
+    @Override
     public void setSelectedNodes(Set<InputNode> nodes) {
-        EditorTopComponent e = EditorTopComponent.getActive();
-        if (e != null) {
-            e.setSelectedNodes(nodes);
-        }
+        editor.setSelectedNodes(nodes);
     }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.form	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.form	Fri May 08 13:25:11 2015 -0400
@@ -18,6 +18,8 @@
   </NonVisualComponents>
   <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"/>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java	Fri May 08 13:25:11 2015 -0400
@@ -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,62 +23,35 @@
  */
 package com.sun.hotspot.igv.view;
 
+import com.sun.hotspot.igv.data.ChangedEvent;
+import com.sun.hotspot.igv.data.ChangedListener;
 import com.sun.hotspot.igv.data.InputNode;
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.data.Properties.PropertyMatcher;
+import com.sun.hotspot.igv.data.services.InputGraphProvider;
 import com.sun.hotspot.igv.filter.FilterChain;
+import com.sun.hotspot.igv.filter.FilterChainProvider;
 import com.sun.hotspot.igv.graph.Diagram;
 import com.sun.hotspot.igv.graph.Figure;
-import com.sun.hotspot.igv.view.actions.EnableBlockLayoutAction;
-import com.sun.hotspot.igv.view.actions.ExpandPredecessorsAction;
-import com.sun.hotspot.igv.view.actions.ExpandSuccessorsAction;
-import com.sun.hotspot.igv.view.actions.ExtractAction;
-import com.sun.hotspot.igv.view.actions.HideAction;
-import com.sun.hotspot.igv.view.actions.NextDiagramAction;
-import com.sun.hotspot.igv.view.actions.NodeFindAction;
-import com.sun.hotspot.igv.view.actions.OverviewAction;
-import com.sun.hotspot.igv.view.actions.PredSuccAction;
-import com.sun.hotspot.igv.view.actions.PrevDiagramAction;
-import com.sun.hotspot.igv.view.actions.ShowAllAction;
-import com.sun.hotspot.igv.view.actions.ZoomInAction;
-import com.sun.hotspot.igv.view.actions.ZoomOutAction;
-import com.sun.hotspot.igv.data.ChangedListener;
-import com.sun.hotspot.igv.data.Properties;
-import com.sun.hotspot.igv.data.Properties.PropertyMatcher;
-import com.sun.hotspot.igv.filter.FilterChainProvider;
+import com.sun.hotspot.igv.graph.services.DiagramProvider;
+import com.sun.hotspot.igv.svg.BatikSVG;
+import com.sun.hotspot.igv.util.LookupHistory;
 import com.sun.hotspot.igv.util.RangeSlider;
-import com.sun.hotspot.igv.util.RangeSliderModel;
-import com.sun.hotspot.igv.svg.BatikSVG;
-import java.awt.BorderLayout;
-import java.awt.CardLayout;
-import java.awt.Color;
-import java.awt.Dimension;
-import java.awt.Graphics2D;
-import java.awt.Point;
+import com.sun.hotspot.igv.view.actions.*;
+import java.awt.*;
 import java.awt.event.HierarchyBoundsListener;
 import java.awt.event.HierarchyEvent;
 import java.awt.event.KeyEvent;
 import java.awt.event.KeyListener;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.UnsupportedEncodingException;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.HashSet;
+import java.io.*;
 import java.util.List;
-import java.util.Set;
-import javax.swing.Action;
-import javax.swing.ActionMap;
-import javax.swing.JPanel;
-import javax.swing.JToggleButton;
-import javax.swing.SwingUtilities;
-import javax.swing.UIManager;
+import java.util.*;
+import javax.swing.*;
 import javax.swing.border.Border;
 import org.openide.DialogDisplayer;
-import org.openide.actions.FindAction;
+import org.openide.NotifyDescriptor;
 import org.openide.actions.RedoAction;
 import org.openide.actions.UndoAction;
 import org.openide.awt.Toolbar;
@@ -86,40 +59,44 @@
 import org.openide.awt.UndoRedo;
 import org.openide.util.Lookup;
 import org.openide.util.NbBundle;
-import org.openide.util.actions.CallbackSystemAction;
-import org.openide.util.actions.SystemAction;
+import org.openide.util.Utilities;
+import org.openide.util.actions.Presenter;
 import org.openide.util.lookup.AbstractLookup;
 import org.openide.util.lookup.InstanceContent;
 import org.openide.util.lookup.ProxyLookup;
 import org.openide.windows.Mode;
 import org.openide.windows.TopComponent;
 import org.openide.windows.WindowManager;
-import org.openide.NotifyDescriptor;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
-public final class EditorTopComponent extends TopComponent implements ChangedListener<RangeSliderModel>, PropertyChangeListener {
+public final class EditorTopComponent extends TopComponent implements PropertyChangeListener {
 
-    private DiagramScene scene;
+    private DiagramViewer scene;
     private InstanceContent content;
-    private FindPanel findPanel;
+    private InstanceContent graphContent;
     private EnableBlockLayoutAction blockLayoutAction;
     private OverviewAction overviewAction;
+    private HideDuplicatesAction hideDuplicatesAction;
     private PredSuccAction predSuccAction;
+    private SelectionModeAction selectionModeAction;
+    private PanModeAction panModeAction;
     private boolean notFirstTime;
-    private ExtendedSatelliteComponent satelliteComponent;
+    private JComponent satelliteComponent;
     private JPanel centerPanel;
     private CardLayout cardLayout;
     private RangeSlider rangeSlider;
     private JToggleButton overviewButton;
+    private JToggleButton hideDuplicatesButton;
     private static final String PREFERRED_ID = "EditorTopComponent";
     private static final String SATELLITE_STRING = "satellite";
     private static final String SCENE_STRING = "scene";
     private DiagramViewModel rangeSliderModel;
     private ExportCookie exportCookie = new ExportCookie() {
 
+        @Override
         public void export(File f) {
 
             Graphics2D svgGenerator = BatikSVG.createGraphicsObject();
@@ -152,12 +129,32 @@
         }
     };
 
+    private DiagramProvider diagramProvider = new DiagramProvider() {
+
+        @Override
+        public Diagram getDiagram() {
+            return getModel().getDiagramToView();
+        }
+
+        @Override
+        public ChangedEvent<DiagramProvider> getChangedEvent() {
+            return diagramChangedEvent;
+        }
+    };
+
+    private ChangedEvent<DiagramProvider> diagramChangedEvent = new ChangedEvent<>(diagramProvider);
+
+
     private void updateDisplayName() {
         setDisplayName(getDiagram().getName());
+        setToolTipText(getDiagram().getGraph().getGroup().getName());
     }
 
     public EditorTopComponent(Diagram diagram) {
 
+        LookupHistory.init(InputGraphProvider.class);
+        LookupHistory.init(DiagramProvider.class);
+        this.setFocusable(true);
         FilterChain filterChain = null;
         FilterChain sequence = null;
         FilterChainProvider provider = Lookup.getDefault().lookup(FilterChainProvider.class);
@@ -182,16 +179,19 @@
             null,
             ZoomInAction.get(ZoomInAction.class),
             ZoomOutAction.get(ZoomOutAction.class),
+        };
+
+
+        Action[] actionsWithSelection = new Action[]{
+            ExtractAction.get(ExtractAction.class),
+            ShowAllAction.get(HideAction.class),
             null,
             ExpandPredecessorsAction.get(ExpandPredecessorsAction.class),
             ExpandSuccessorsAction.get(ExpandSuccessorsAction.class)
         };
 
-
         initComponents();
 
-        ActionMap actionMap = getActionMap();
-
         ToolbarPool.getDefault().setPreferredIconSize(16);
         Toolbar toolBar = new Toolbar();
         Border b = (Border) UIManager.get("Nb.Editor.Toolbar.border"); //NOI18N
@@ -202,24 +202,30 @@
         container.add(BorderLayout.NORTH, toolBar);
 
         rangeSliderModel = new DiagramViewModel(diagram.getGraph().getGroup(), filterChain, sequence);
-        rangeSliderModel.selectGraph(diagram.getGraph());
         rangeSlider = new RangeSlider();
         rangeSlider.setModel(rangeSliderModel);
-        rangeSliderModel.getChangedEvent().addListener(this);
-        container.add(BorderLayout.CENTER, rangeSlider);
+        JScrollPane pane = new JScrollPane(rangeSlider, ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+        container.add(BorderLayout.CENTER, pane);
 
-        scene = new DiagramScene(actions, rangeSliderModel);
+        scene = new DiagramScene(actions, actionsWithSelection, rangeSliderModel);
         content = new InstanceContent();
-        this.associateLookup(new ProxyLookup(new Lookup[]{scene.getLookup(), new AbstractLookup(content)}));
+        graphContent = new InstanceContent();
+        this.associateLookup(new ProxyLookup(new Lookup[]{scene.getLookup(), new AbstractLookup(graphContent), new AbstractLookup(content)}));
         content.add(exportCookie);
         content.add(rangeSliderModel);
+        content.add(diagramProvider);
+
+        rangeSliderModel.getDiagramChangedEvent().addListener(diagramChangedListener);
+        rangeSliderModel.selectGraph(diagram.getGraph());
+        rangeSliderModel.getViewPropertiesChangedEvent().addListener(new ChangedListener<DiagramViewModel>() {
+                @Override
+                public void changed(DiagramViewModel source) {
+                    hideDuplicatesButton.setSelected(getModel().getHideDuplicates());
+                    hideDuplicatesAction.setState(getModel().getHideDuplicates());
+                }
+            });
 
 
-        findPanel = new FindPanel(diagram.getFigures());
-        findPanel.setMaximumSize(new Dimension(200, 50));
-        toolBar.add(findPanel);
-        toolBar.add(NodeFindAction.get(NodeFindAction.class));
-        toolBar.addSeparator();
         toolBar.add(NextDiagramAction.get(NextDiagramAction.class));
         toolBar.add(PrevDiagramAction.get(PrevDiagramAction.class));
         toolBar.addSeparator();
@@ -232,7 +238,7 @@
 
         blockLayoutAction = new EnableBlockLayoutAction();
         JToggleButton button = new JToggleButton(blockLayoutAction);
-        button.setSelected(true);
+        button.setSelected(false);
         toolBar.add(button);
         blockLayoutAction.addPropertyChangeListener(this);
 
@@ -248,59 +254,91 @@
         toolBar.add(button);
         predSuccAction.addPropertyChangeListener(this);
 
+        hideDuplicatesAction = new HideDuplicatesAction();
+        hideDuplicatesButton = new JToggleButton(hideDuplicatesAction);
+        hideDuplicatesButton.setSelected(false);
+        toolBar.add(hideDuplicatesButton);
+        hideDuplicatesAction.addPropertyChangeListener(this);
+
         toolBar.addSeparator();
         toolBar.add(UndoAction.get(UndoAction.class));
         toolBar.add(RedoAction.get(RedoAction.class));
 
+        toolBar.addSeparator();
+        ButtonGroup interactionButtons = new ButtonGroup();
+
+        panModeAction = new PanModeAction();
+        panModeAction.setSelected(true);
+        button = new JToggleButton(panModeAction);
+        button.setSelected(true);
+        interactionButtons.add(button);
+        toolBar.add(button);
+        panModeAction.addPropertyChangeListener(this);
+
+        selectionModeAction = new SelectionModeAction();
+        button = new JToggleButton(selectionModeAction);
+        interactionButtons.add(button);
+        toolBar.add(button);
+        selectionModeAction.addPropertyChangeListener(this);
+
+        toolBar.add(Box.createHorizontalGlue());
+        Action action = Utilities.actionsForPath("QuickSearchShadow").get(0);
+        Component quicksearch = ((Presenter.Toolbar) action).getToolbarPresenter();
+        try {
+            // (aw) workaround for disappearing search bar due to reparenting one shared component instance.
+            quicksearch = (Component) quicksearch.getClass().getConstructor(KeyStroke.class).newInstance(new Object[]{null});
+        } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) {
+        }
+        quicksearch.setMinimumSize(quicksearch.getPreferredSize()); // necessary for GTK LAF
+        toolBar.add(quicksearch);
+
         centerPanel = new JPanel();
         this.add(centerPanel, BorderLayout.CENTER);
         cardLayout = new CardLayout();
         centerPanel.setLayout(cardLayout);
-        centerPanel.add(SCENE_STRING, scene.getScrollPane());
+        centerPanel.add(SCENE_STRING, scene.getComponent());
         centerPanel.setBackground(Color.WHITE);
-        satelliteComponent = new ExtendedSatelliteComponent(scene);
+        satelliteComponent = scene.createSatelliteView();
         satelliteComponent.setSize(200, 200);
         centerPanel.add(SATELLITE_STRING, satelliteComponent);
 
-        CallbackSystemAction callFindAction = (CallbackSystemAction) SystemAction.get(FindAction.class);
-        NodeFindAction findAction = NodeFindAction.get(NodeFindAction.class);
-        Object key = callFindAction.getActionMapKey();
-        actionMap.put(key, findAction);
+        // TODO: Fix the hot key for entering the satellite view
+        this.addKeyListener(keyListener);
 
-        scene.getScrollPane().addKeyListener(keyListener);
-        scene.getView().addKeyListener(keyListener);
-        satelliteComponent.addKeyListener(keyListener);
+        scene.getComponent().addHierarchyBoundsListener(new HierarchyBoundsListener() {
 
-        scene.getScrollPane().addHierarchyBoundsListener(new HierarchyBoundsListener() {
-
+            @Override
             public void ancestorMoved(HierarchyEvent e) {
             }
 
+            @Override
             public void ancestorResized(HierarchyEvent e) {
-                if (!notFirstTime && scene.getScrollPane().getBounds().width > 0) {
+                if (!notFirstTime && scene.getComponent().getBounds().width > 0) {
                     notFirstTime = true;
                     SwingUtilities.invokeLater(new Runnable() {
 
+                        @Override
                         public void run() {
-                            Figure f = EditorTopComponent.this.scene.getModel().getDiagramToView().getRootFigure();
-                            if (f != null) {
-                                scene.setUndoRedoEnabled(false);
-                                scene.gotoFigure(f);
-                                scene.setUndoRedoEnabled(true);
-                            }
+                            EditorTopComponent.this.scene.initialize();
                         }
                     });
                 }
             }
         });
 
+        if (diagram.getGraph().getGroup().getGraphsCount() == 1) {
+            rangeSlider.setVisible(false);
+        }
+
         updateDisplayName();
     }
     private KeyListener keyListener = new KeyListener() {
 
+        @Override
         public void keyTyped(KeyEvent e) {
         }
 
+        @Override
         public void keyPressed(KeyEvent e) {
             if (e.getKeyCode() == KeyEvent.VK_S) {
                 EditorTopComponent.this.overviewButton.setSelected(true);
@@ -308,6 +346,7 @@
             }
         }
 
+        @Override
         public void keyReleased(KeyEvent e) {
             if (e.getKeyCode() == KeyEvent.VK_S) {
                 EditorTopComponent.this.overviewButton.setSelected(false);
@@ -317,7 +356,7 @@
     };
 
     public DiagramViewModel getDiagramModel() {
-        return scene.getModel();
+        return rangeSliderModel;
     }
 
     private void showSatellite() {
@@ -328,35 +367,15 @@
 
     private void showScene() {
         cardLayout.show(centerPanel, SCENE_STRING);
-        scene.getView().requestFocus();
-    }
-
-    public void findNode() {
-        findPanel.find();
+        scene.getComponent().requestFocus();
     }
 
     public void zoomOut() {
-        double zoom = scene.getZoomFactor();
-        Point viewPosition = scene.getScrollPane().getViewport().getViewPosition();
-        double newZoom = zoom / DiagramScene.ZOOM_INCREMENT;
-        if (newZoom > DiagramScene.ZOOM_MIN_FACTOR) {
-            scene.setZoomFactor(newZoom);
-            scene.validate();
-            scene.getScrollPane().getViewport().setViewPosition(new Point((int) (viewPosition.x / DiagramScene.ZOOM_INCREMENT), (int) (viewPosition.y / DiagramScene.ZOOM_INCREMENT)));
-            this.satelliteComponent.update();
-        }
+        scene.zoomOut();
     }
 
     public void zoomIn() {
-        double zoom = scene.getZoomFactor();
-        Point viewPosition = scene.getScrollPane().getViewport().getViewPosition();
-        double newZoom = zoom * DiagramScene.ZOOM_INCREMENT;
-        if (newZoom < DiagramScene.ZOOM_MAX_FACTOR) {
-            scene.setZoomFactor(newZoom);
-            scene.validate();
-            scene.getScrollPane().getViewport().setViewPosition(new Point((int) (viewPosition.x * DiagramScene.ZOOM_INCREMENT), (int) (viewPosition.y * DiagramScene.ZOOM_INCREMENT)));
-            this.satelliteComponent.update();
-        }
+        scene.zoomIn();
     }
 
     public void showPrevDiagram() {
@@ -370,11 +389,11 @@
     }
 
     public DiagramViewModel getModel() {
-        return scene.getModel();
+        return rangeSliderModel;
     }
 
     public FilterChain getFilterChain() {
-        return this.scene.getModel().getFilterChain();
+        return getModel().getFilterChain();
     }
 
     public static EditorTopComponent getActive() {
@@ -407,6 +426,7 @@
         // Variables declaration - do not modify//GEN-BEGIN:variables
         private javax.swing.JCheckBox jCheckBox1;
         // End of variables declaration//GEN-END:variables
+
     @Override
     public int getPersistenceType() {
         return TopComponent.PERSISTENCE_NEVER;
@@ -418,6 +438,7 @@
 
     @Override
     public void componentClosed() {
+        rangeSliderModel.close();
     }
 
     @Override
@@ -425,9 +446,18 @@
         return PREFERRED_ID;
     }
 
-    public void changed(RangeSliderModel model) {
-        updateDisplayName();
-    }
+    private ChangedListener<DiagramViewModel> diagramChangedListener = new ChangedListener<DiagramViewModel>() {
+
+        @Override
+        public void changed(DiagramViewModel source) {
+            updateDisplayName();
+            Collection<Object> list = new ArrayList<>();
+            list.add(new EditorInputGraphProvider(EditorTopComponent.this));
+            graphContent.set(list, null);
+            diagramProvider.getChangedEvent().fire();
+        }
+
+    };
 
     public boolean showPredSucc() {
         return (Boolean) predSuccAction.getValue(PredSuccAction.STATE);
@@ -435,24 +465,25 @@
 
     public void setSelection(PropertyMatcher matcher) {
 
-        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<Figure>(scene.getModel().getDiagramToView().getFigures());
+        Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(getModel().getDiagramToView().getFigures());
         List<Figure> list = selector.selectMultiple(matcher);
-        boolean b = scene.getUndoRedoEnabled();
-        scene.setUndoRedoEnabled(false);
-        scene.gotoFigures(list);
-        scene.setUndoRedoEnabled(b);
+        setSelectedFigures(list);
+    }
+
+    public void setSelectedFigures(List<Figure> list) {
         scene.setSelection(list);
+        scene.centerFigures(list);
     }
 
     public void setSelectedNodes(Set<InputNode> nodes) {
 
-        List<Figure> list = new ArrayList<Figure>();
-        Set<Integer> ids = new HashSet<Integer>();
+        List<Figure> list = new ArrayList<>();
+        Set<Integer> ids = new HashSet<>();
         for (InputNode n : nodes) {
             ids.add(n.getId());
         }
 
-        for (Figure f : scene.getModel().getDiagramToView().getFigures()) {
+        for (Figure f : getModel().getDiagramToView().getFigures()) {
             for (InputNode n : f.getSource().getSourceNodes()) {
                 if (ids.contains(n.getId())) {
                     list.add(f);
@@ -461,10 +492,10 @@
             }
         }
 
-        scene.gotoFigures(list);
-        scene.setSelection(list);
+        setSelectedFigures(list);
     }
 
+    @Override
     public void propertyChange(PropertyChangeEvent evt) {
         if (evt.getSource() == this.predSuccAction) {
             boolean b = (Boolean) predSuccAction.getValue(PredSuccAction.STATE);
@@ -478,27 +509,35 @@
             }
         } else if (evt.getSource() == this.blockLayoutAction) {
             boolean b = (Boolean) blockLayoutAction.getValue(EnableBlockLayoutAction.STATE);
-            System.out.println("Showblocks = " + b);
             this.getModel().setShowBlocks(b);
+        } else if (evt.getSource() == this.hideDuplicatesAction) {
+            boolean b = (Boolean) hideDuplicatesAction.getValue(HideDuplicatesAction.STATE);
+            this.getModel().setHideDuplicates(b);
+        } else if (evt.getSource() == this.selectionModeAction || evt.getSource() == this.panModeAction) {
+            if (panModeAction.isSelected()) {
+                scene.setInteractionMode(DiagramViewer.InteractionMode.PANNING);
+            } else if (selectionModeAction.isSelected()) {
+                scene.setInteractionMode(DiagramViewer.InteractionMode.SELECTION);
+            }
         } else {
             assert false : "Unknown event source";
         }
     }
 
     public void extract() {
-        scene.showOnly(scene.getSelectedNodes());
+        getModel().showOnly(getModel().getSelectedNodes());
     }
 
     public void hideNodes() {
-        Set<Integer> selectedNodes = this.scene.getSelectedNodes();
-        HashSet<Integer> nodes = new HashSet<Integer>(scene.getModel().getHiddenNodes());
+        Set<Integer> selectedNodes = this.getModel().getSelectedNodes();
+        HashSet<Integer> nodes = new HashSet<>(getModel().getHiddenNodes());
         nodes.addAll(selectedNodes);
-        this.scene.showNot(nodes);
+        this.getModel().showNot(nodes);
     }
 
     public void expandPredecessors() {
-        Set<Figure> oldSelection = scene.getSelectedFigures();
-        Set<Figure> figures = new HashSet<Figure>();
+        Set<Figure> oldSelection = getModel().getSelectedFigures();
+        Set<Figure> figures = new HashSet<>();
 
         for (Figure f : this.getDiagramModel().getDiagramToView().getFigures()) {
             boolean ok = false;
@@ -518,12 +557,12 @@
             }
         }
 
-        scene.showAll(figures);
+        getModel().showAll(figures);
     }
 
     public void expandSuccessors() {
-        Set<Figure> oldSelection = scene.getSelectedFigures();
-        Set<Figure> figures = new HashSet<Figure>();
+        Set<Figure> oldSelection = getModel().getSelectedFigures();
+        Set<Figure> figures = new HashSet<>();
 
         for (Figure f : this.getDiagramModel().getDiagramToView().getFigures()) {
             boolean ok = false;
@@ -543,11 +582,11 @@
             }
         }
 
-        scene.showAll(figures);
+        getModel().showAll(figures);
     }
 
     public void showAll() {
-        scene.showNot(new HashSet<Integer>());
+        getModel().showNot(new HashSet<Integer>());
     }
 
     public Diagram getDiagram() {
@@ -555,23 +594,31 @@
     }
 
     @Override
-    protected void componentActivated() {
+    protected void componentHidden() {
+        super.componentHidden();
+        scene.componentHidden();
+
     }
 
     @Override
-    public void requestFocus() {
-        super.requestFocus();
-        scene.getView().requestFocus();
+    protected void componentShowing() {
+        super.componentShowing();
+        scene.componentShowing();
     }
 
     @Override
-    public boolean requestFocusInWindow() {
-        super.requestFocusInWindow();
-        return scene.getView().requestFocusInWindow();
+    public void requestActive() {
+        super.requestActive();
+        scene.getComponent().requestFocus();
     }
 
     @Override
     public UndoRedo getUndoRedo() {
         return scene.getUndoRedo();
     }
+
+    @Override
+    protected Object writeReplace() throws ObjectStreamException {
+        throw new NotSerializableException();
 }
+}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/ExportCookie.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/ExportCookie.java	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, 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
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/ExtendedPanAction.java	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/*
- * 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;
-
-import java.awt.Container;
-import java.awt.Dimension;
-import java.awt.Point;
-import org.netbeans.api.visual.widget.Scene;
-import org.netbeans.api.visual.widget.Widget;
-import org.netbeans.api.visual.action.WidgetAction;
-
-import java.awt.event.MouseEvent;
-import javax.swing.JComponent;
-import javax.swing.JScrollPane;
-import javax.swing.SwingUtilities;
-
-/**
- * @author David Kaspar
- * @author Thomas Wuerthinger
- */
-public class ExtendedPanAction extends WidgetAction.LockedAdapter {
-
-    private Scene scene;
-    private JScrollPane scrollPane;
-    private Point lastLocation;
-
-    protected boolean isLocked() {
-        return scrollPane != null;
-    }
-
-    @Override
-    public State mousePressed(Widget widget, WidgetMouseEvent event) {
-        if (event.getButton() == MouseEvent.BUTTON2 || event.getButton() == MouseEvent.BUTTON1 && ((event.getModifiers() & MouseEvent.CTRL_MASK) != 0)) {
-            scene = widget.getScene();
-            scrollPane = findScrollPane(scene.getView());
-            if (scrollPane != null) {
-                lastLocation = scene.convertSceneToView(widget.convertLocalToScene(event.getPoint()));
-                SwingUtilities.convertPointToScreen(lastLocation, scrollPane.getViewport().getView());
-                return State.createLocked(widget, this);
-            }
-        }
-        return State.REJECTED;
-    }
-
-    private JScrollPane findScrollPane(JComponent component) {
-        for (;;) {
-            if (component == null) {
-                return null;
-            }
-            if (component instanceof JScrollPane) {
-                return ((JScrollPane) component);
-            }
-            Container parent = component.getParent();
-            if (!(parent instanceof JComponent)) {
-                return null;
-            }
-            component = (JComponent) parent;
-        }
-    }
-
-    @Override
-    public State mouseReleased(Widget widget, WidgetMouseEvent event) {
-        boolean state = pan(widget, event.getPoint());
-        if (state) {
-            scrollPane = null;
-        }
-        return state ? State.createLocked(widget, this) : State.REJECTED;
-    }
-
-    @Override
-    public State mouseDragged(Widget widget, WidgetMouseEvent event) {
-        return pan(widget, event.getPoint()) ? State.createLocked(widget, this) : State.REJECTED;
-    }
-
-    private boolean pan(Widget widget, Point newLocation) {
-        if (scrollPane == null || scene != widget.getScene()) {
-            return false;
-        }
-        newLocation = scene.convertSceneToView(widget.convertLocalToScene(newLocation));
-        SwingUtilities.convertPointToScreen(newLocation, scrollPane.getViewport().getView());
-        Point viewPosition = scrollPane.getViewport().getViewPosition();
-        Dimension viewSize = scrollPane.getViewport().getViewSize();
-        Dimension viewPortSize = scrollPane.getViewport().getSize();
-
-        int xOffset = lastLocation.x - newLocation.x;
-        int yOffset = lastLocation.y - newLocation.y;
-
-        if (viewPortSize.height == viewSize.height) {
-            yOffset = 0;
-        }
-
-        if (viewPortSize.width == viewSize.width) {
-            xOffset = 0;
-        }
-
-        if (xOffset == 0 && yOffset == 0) {
-            return true;
-        }
-        viewPosition = new Point(viewPosition.x + xOffset, viewPosition.y + yOffset);
-        viewPosition.x = Math.max(viewPosition.x, 0);
-        viewPosition.y = Math.max(viewPosition.y, 0);
-        viewPosition.x = Math.min(viewPosition.x, scrollPane.getViewport().getView().getSize().width - scrollPane.getViewport().getSize().width);
-        viewPosition.y = Math.min(viewPosition.y, scrollPane.getViewport().getView().getSize().height - scrollPane.getViewport().getSize().height);
-
-        scrollPane.getViewport().setViewPosition(viewPosition);
-        scrollPane.getViewport().getView().repaint();
-        lastLocation = newLocation;
-        return true;
-    }
-}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/ExtendedSatelliteComponent.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/ExtendedSatelliteComponent.java	Fri May 08 13:25:11 2015 -0400
@@ -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,11 +23,10 @@
  */
 package com.sun.hotspot.igv.view;
 
-import org.netbeans.api.visual.widget.Scene;
-
-import javax.swing.*;
 import java.awt.*;
 import java.awt.event.*;
+import javax.swing.JComponent;
+import org.netbeans.api.visual.widget.Scene;
 
 /**
  * @author David Kaspar
@@ -48,6 +47,7 @@
         addMouseMotionListener(this);
     }
 
+    @Override
     public void addNotify() {
         super.addNotify();
         scene.addSceneListener(this);
@@ -59,6 +59,7 @@
         repaint();
     }
 
+    @Override
     public void removeNotify() {
         scene.getView().removeComponentListener(this);
         scene.removeSceneListener(this);
@@ -74,6 +75,7 @@
         }
     }
 
+    @Override
     public void paint(Graphics g) {
         Graphics2D gr = (Graphics2D) g;
         super.paint(g);
@@ -91,15 +93,15 @@
 
 
         if (image == null || vw != imageWidth || vh != imageHeight) {
-
             imageWidth = vw;
             imageHeight = vh;
             image = this.createImage(imageWidth, imageHeight);
             Graphics2D ig = (Graphics2D) image.getGraphics();
             ig.scale(scale, scale);
-            scene.setRealZoomFactor(scale);
+            double oldFactor = scene.getZoomFactor();
+            scene.setZoomFactor(scale);
             scene.paint(ig);
-            scene.setRealZoomFactor(0.0);
+            scene.setZoomFactor(oldFactor);
         }
 
         gr.drawImage(image, vx, vy, this);
@@ -121,27 +123,34 @@
         }
     }
 
+    @Override
     public void mouseClicked(MouseEvent e) {
     }
 
+    @Override
     public void mousePressed(MouseEvent e) {
         moveVisibleRect(e.getPoint());
     }
 
+    @Override
     public void mouseReleased(MouseEvent e) {
         moveVisibleRect(e.getPoint());
     }
 
+    @Override
     public void mouseEntered(MouseEvent e) {
     }
 
+    @Override
     public void mouseExited(MouseEvent e) {
     }
 
+    @Override
     public void mouseDragged(MouseEvent e) {
         moveVisibleRect(e.getPoint());
     }
 
+    @Override
     public void mouseMoved(MouseEvent e) {
     }
 
@@ -174,27 +183,34 @@
         this.repaint();
     }
 
+    @Override
     public void sceneRepaint() {
     //repaint ();
     }
 
+    @Override
     public void sceneValidating() {
     }
 
+    @Override
     public void sceneValidated() {
     }
 
+    @Override
     public void componentResized(ComponentEvent e) {
         repaint();
     }
 
+    @Override
     public void componentMoved(ComponentEvent e) {
         repaint();
     }
 
+    @Override
     public void componentShown(ComponentEvent e) {
     }
 
+    @Override
     public void componentHidden(ComponentEvent e) {
     }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/FindPanel.java	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * 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;
-
-import com.sun.hotspot.igv.graph.Figure;
-import com.sun.hotspot.igv.data.Properties;
-import com.sun.hotspot.igv.data.Properties.RegexpPropertyMatcher;
-import com.sun.hotspot.igv.data.Property;
-import java.awt.GridLayout;
-import java.awt.event.KeyEvent;
-import java.awt.event.KeyListener;
-import java.util.List;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import javax.swing.JComboBox;
-import javax.swing.JPanel;
-import javax.swing.JTextField;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-class FindPanel extends JPanel implements KeyListener {
-
-    private JComboBox nameComboBox;
-    private JTextField valueTextField;
-
-    public FindPanel(List<Figure> figures) {
-        createDesign();
-        updateComboBox(figures);
-    }
-
-    protected void createDesign() {
-        setLayout(new GridLayout());
-        nameComboBox = new JComboBox();
-        valueTextField = new JTextField();
-        add(nameComboBox);
-        add(valueTextField);
-        valueTextField.addKeyListener(this);
-    }
-
-    public void updateComboBox(List<Figure> figures) {
-
-        String sel = (String) nameComboBox.getSelectedItem();
-        SortedSet<String> propertyNames = new TreeSet<String>();
-
-        for (Figure f : figures) {
-            Properties prop = f.getProperties();
-            for (Property p : prop) {
-                if (!propertyNames.contains(p.getName())) {
-                    propertyNames.add(p.getName());
-                }
-            }
-        }
-
-        for (String s : propertyNames) {
-            nameComboBox.addItem(s);
-        }
-        nameComboBox.setSelectedItem(sel);
-    }
-
-    public String getNameText() {
-        return (String) nameComboBox.getSelectedItem();
-    }
-
-    public String getValueText() {
-        return valueTextField.getText();
-    }
-
-    public void keyTyped(KeyEvent e) {
-    }
-
-    public void keyPressed(KeyEvent e) {
-        if (e.getKeyCode() == KeyEvent.VK_ENTER) {
-            find();
-        }
-    }
-
-    public void find() {
-        EditorTopComponent comp = EditorTopComponent.getActive();
-        if (comp != null) {
-            RegexpPropertyMatcher matcher = new RegexpPropertyMatcher(getNameText(), getValueText());
-            comp.setSelection(matcher);
-        }
-    }
-
-    public void keyReleased(KeyEvent e) {
-
-    }
-}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/GraphViewerImplementation.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/GraphViewerImplementation.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -27,6 +27,9 @@
 import com.sun.hotspot.igv.data.services.GraphViewer;
 import com.sun.hotspot.igv.graph.Diagram;
 import com.sun.hotspot.igv.settings.Settings;
+import org.openide.windows.Mode;
+import org.openide.windows.TopComponent;
+import org.openide.windows.WindowManager;
 
 /**
  *
@@ -34,7 +37,25 @@
  */
 public class GraphViewerImplementation implements GraphViewer {
 
-    public void view(InputGraph graph) {
+    @Override
+    public void view(InputGraph graph, boolean clone) {
+
+        if (!clone) {
+            WindowManager manager = WindowManager.getDefault();
+            for (Mode m : manager.getModes()) {
+                for (TopComponent t : manager.getOpenedTopComponents(m)) {
+                    if (t instanceof EditorTopComponent) {
+                        EditorTopComponent etc = (EditorTopComponent) t;
+                        if (etc.getModel().getGroup().getGraphs().contains(graph)) {
+                            etc.getModel().selectGraph(graph);
+                            t.requestActive();
+                            return;
+                        }
+                    }
+                }
+            }
+        }
+
         Diagram diagram = Diagram.createDiagram(graph, Settings.get().get(Settings.NODE_TEXT, Settings.NODE_TEXT_DEFAULT));
         EditorTopComponent tc = new EditorTopComponent(diagram);
         tc.open();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/NodeQuickSearch.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,142 @@
+/*
+ * 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;
+
+import com.sun.hotspot.igv.data.InputNode;
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.data.Properties.RegexpPropertyMatcher;
+import com.sun.hotspot.igv.data.services.InputGraphProvider;
+import com.sun.hotspot.igv.util.LookupHistory;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+import org.netbeans.spi.quicksearch.SearchProvider;
+import org.netbeans.spi.quicksearch.SearchRequest;
+import org.netbeans.spi.quicksearch.SearchResponse;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.NotifyDescriptor.Message;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public class NodeQuickSearch implements SearchProvider {
+
+    private static final String DEFAULT_PROPERTY = "name";
+
+    /**
+     * Method is called by infrastructure when search operation was requested.
+     * Implementors should evaluate given request and fill response object with
+     * apropriate results
+     *
+     * @param request Search request object that contains information what to search for
+     * @param response Search response object that stores search results. Note that it's important to react to return value of SearchResponse.addResult(...) method and stop computation if false value is returned.
+     */
+    @Override
+    public void evaluate(SearchRequest request, SearchResponse response) {
+        String query = request.getText();
+        if (query.trim().isEmpty()) {
+            return;
+        }
+
+        final String[] parts = query.split("=", 2);
+
+        String name;
+        String value;
+
+        if (parts.length == 1) {
+            name = DEFAULT_PROPERTY;
+            value = ".*" + Pattern.quote(parts[0]) + ".*";
+        } else {
+            name = parts[0];
+            value = parts[1];
+        }
+
+        if (value.isEmpty()) {
+            value = ".*";
+        }
+
+        final InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);
+        if (p != null && p.getGraph() != null) {
+            List<InputNode> matches = null;
+            try {
+                RegexpPropertyMatcher matcher = new RegexpPropertyMatcher(name, value, Pattern.CASE_INSENSITIVE);
+                Properties.PropertySelector<InputNode> selector = new Properties.PropertySelector<>(p.getGraph().getNodes());
+
+                matches = selector.selectMultiple(matcher);
+            } catch (Exception e) {
+                final String msg = e.getMessage();
+                response.addResult(new Runnable() {
+                    @Override
+                        public void run() {
+                            Message desc = new NotifyDescriptor.Message("An exception occurred during the search, "
+                                    + "perhaps due to a malformed query string:\n" + msg,
+                                    NotifyDescriptor.WARNING_MESSAGE);
+                            DialogDisplayer.getDefault().notify(desc);
+                        }
+                    },
+                    "(Error during search)"
+                );
+            }
+
+            if (matches != null) {
+                final Set<InputNode> set = new HashSet<>(matches);
+                response.addResult(new Runnable() {
+                    @Override
+                        public void run() {
+                            final EditorTopComponent comp = EditorTopComponent.getActive();
+                            if (comp != null) {
+                                comp.setSelectedNodes(set);
+                                comp.requestActive();
+                            }
+                        }
+                    },
+                    "All " + matches.size() + " matching nodes (" + name + "=" + value + ")"
+                );
+
+                // Single matches
+                for (final InputNode n : matches) {
+                    response.addResult(new Runnable() {
+                        @Override
+                            public void run() {
+                                final EditorTopComponent comp = EditorTopComponent.getActive();
+                                if (comp != null) {
+                                    final Set<InputNode> tmpSet = new HashSet<>();
+                                    tmpSet.add(n);
+                                    comp.setSelectedNodes(tmpSet);
+                                    comp.requestActive();
+                                }
+                            }
+                        },
+                        n.getProperties().get(name) + " (" + n.getId() + " " + n.getProperties().get("name") + ")"
+                    );
+                }
+            }
+        } else {
+            System.out.println("no input graph provider!");
+        }
+    }
+}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/PreferenceConstants.java	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * 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;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class PreferenceConstants {
-
-    public static final String KEY_LINE_GENERATOR = "lineGenerator";
-    public static final String DEFAULT_LINE_GENERATOR = "com.sun.hotspot.igv.positioning.BasicLineGenerator";
-}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/SlotLayout.java	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,171 +0,0 @@
-/*
- * 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;
-
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.util.Collection;
-import java.util.List;
-import org.netbeans.api.visual.layout.Layout;
-import org.netbeans.api.visual.layout.LayoutFactory;
-import org.netbeans.api.visual.widget.Widget;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class SlotLayout implements Layout {
-
-    public enum HorizontalAlignment {
-
-        Left,
-        Center,
-        Right
-    }
-    private Layout baseLayout;
-    private HorizontalAlignment alignment;
-    private boolean vertical;
-
-    public SlotLayout() {
-        this(HorizontalAlignment.Center, false);
-    }
-
-    public SlotLayout(HorizontalAlignment alignment, boolean vertical) {
-        this.alignment = alignment;
-        baseLayout = LayoutFactory.createVerticalFlowLayout();
-        this.vertical = vertical;
-    }
-
-    public void layout(Widget widget) {
-        if (!vertical) {
-            Collection<Widget> children = widget.getChildren();
-            int gap = 0;
-            int max = 0;
-            for (Widget child : children) {
-                Rectangle preferredBounds = child.getPreferredBounds();
-                int i = preferredBounds.width;
-                if (i > max) {
-                    max = i;
-                }
-            }
-            int pos = 0;
-            for (Widget child : children) {
-                Rectangle preferredBounds = child.getPreferredBounds();
-                int x = preferredBounds.x;
-                int y = preferredBounds.y;
-                int width = preferredBounds.width;
-                int height = preferredBounds.height;
-                if (pos == 0) {
-                    pos += height / 2;
-                }
-                int lx = -x;
-                int ly = pos - y;
-                switch (alignment) {
-                    case Center:
-                        lx += (max - width) / 2;
-                        break;
-                    case Left:
-                        break;
-                    case Right:
-                        lx += max - width;
-                        break;
-                }
-                child.resolveBounds(new Point(lx, ly), new Rectangle(x, y, width, height));
-                pos += height + gap;
-            }
-        } else {
-
-            Collection<Widget> children = widget.getChildren();
-            int gap = 0;
-            int max = 0;
-            for (Widget child : children) {
-                Rectangle preferredBounds = child.getPreferredBounds();
-                int i = preferredBounds.height;
-                if (i > max) {
-                    max = i;
-                }
-            }
-            int pos = 0;
-            for (Widget child : children) {
-                Rectangle preferredBounds = child.getPreferredBounds();
-                int x = preferredBounds.x;
-                int y = preferredBounds.y;
-                int width = preferredBounds.width;
-                int height = preferredBounds.height;
-                if (pos == 0) {
-                    pos += width / 2;
-                }
-                int lx = pos - x;
-                int ly = -y;
-                switch (alignment) {
-                    case Center:
-                        ly += (max - height) / 2;
-                        break;
-                    case Left:
-                        break;
-                    case Right:
-                        ly += max - height;
-                        break;
-                }
-                child.resolveBounds(new Point(lx, ly), new Rectangle(x, y, width, height));
-                pos += width + gap;
-            }
-
-        }
-    }
-
-    public boolean requiresJustification(Widget widget) {
-        return true;
-    }
-
-    public void justify(Widget widget) {
-        baseLayout.justify(widget);
-
-        Rectangle client = widget.getClientArea();
-        List<Widget> children = widget.getChildren();
-
-        int count = children.size();
-        int z = 0;
-
-        int maxWidth = 0;
-        for (Widget c : children) {
-            if (c.getPreferredBounds().width > maxWidth) {
-                maxWidth = c.getPreferredBounds().width;
-            }
-        }
-
-        for (Widget c : children) {
-            z++;
-            Point curLocation = c.getLocation();
-            Rectangle curBounds = c.getBounds();
-
-
-            Point location = new Point(curLocation.x, client.y + client.height * z / (count + 1) - curBounds.height / 2);
-            if (vertical) {
-                location = new Point(client.x + client.width * z / (count + 1) - maxWidth / 2, curLocation.y);
-            }
-            c.resolveBounds(location, null);
-        }
-    }
-}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/Bundle.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/Bundle.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,7 +1,6 @@
 CTL_EditorAction=Open Editor Window
-CTL_LineGeneratorAction=Line Generator
 CTL_NextDiagramAction=Show next graph
 CTL_EnableBlockLayoutAction=Enable block layout
 CTL_NodeFindAction=Find
 CTL_PrevDiagramAction=Show previous graph
-CTL_ExportAction=Export...
+CTL_ExportAction=Export current graph...
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/CustomizablePanAction.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,146 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
+ * Microsystems, Inc. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package com.sun.hotspot.igv.view.actions;
+
+import java.awt.Container;
+import java.awt.Point;
+import java.awt.Rectangle;
+import javax.swing.JComponent;
+import javax.swing.JScrollPane;
+import javax.swing.SwingUtilities;
+import org.netbeans.api.visual.action.WidgetAction;
+import org.netbeans.api.visual.action.WidgetAction.State;
+import org.netbeans.api.visual.action.WidgetAction.WidgetMouseEvent;
+import org.netbeans.api.visual.widget.Scene;
+import org.netbeans.api.visual.widget.Widget;
+
+/**
+ * @author David Kaspar
+ * @author Peter Hofer
+ */
+public class CustomizablePanAction extends WidgetAction.LockedAdapter {
+    private boolean enabled = true;
+
+    private Scene scene;
+    private JScrollPane scrollPane;
+    private Point lastLocation;
+
+    private final int modifiersExMask;
+    private final int modifiersEx;
+
+    public CustomizablePanAction(int modifiersExMask, int modifiersEx) {
+        this.modifiersExMask = modifiersExMask;
+        this.modifiersEx = modifiersEx;
+    }
+
+    @Override
+    protected boolean isLocked() {
+        return scrollPane != null;
+    }
+
+    public void setEnabled(boolean enabled) {
+        if (this.enabled != enabled) {
+            if (isLocked())
+                throw new IllegalStateException();
+
+            this.enabled = enabled;
+        }
+    }
+
+    @Override
+    public State mousePressed (Widget widget, WidgetMouseEvent event) {
+        if (isLocked ())
+            return State.createLocked (widget, this);
+        if (enabled && (event.getModifiersEx() & modifiersExMask) == modifiersEx) {
+            scene = widget.getScene ();
+            scrollPane = findScrollPane (scene.getView ());
+            if (scrollPane != null) {
+                lastLocation = scene.convertSceneToView (widget.convertLocalToScene (event.getPoint ()));
+                SwingUtilities.convertPointToScreen (lastLocation, scene.getView ());
+                return State.createLocked (widget, this);
+            }
+        }
+        return State.REJECTED;
+    }
+
+    private JScrollPane findScrollPane (JComponent component) {
+        for (;;) {
+            if (component == null)
+                return null;
+            if (component instanceof JScrollPane)
+                return ((JScrollPane) component);
+            Container parent = component.getParent ();
+            if (! (parent instanceof JComponent))
+                return null;
+            component = (JComponent) parent;
+        }
+    }
+
+    @Override
+    public State mouseReleased (Widget widget, WidgetMouseEvent event) {
+        boolean state = pan (widget, event.getPoint ());
+        if (state)
+            scrollPane = null;
+        return state ? State.createLocked (widget, this) : State.REJECTED;
+    }
+
+    @Override
+    public State mouseDragged (Widget widget, WidgetMouseEvent event) {
+        return pan (widget, event.getPoint ()) ? State.createLocked (widget, this) : State.REJECTED;
+    }
+
+    private boolean pan (Widget widget, Point newLocation) {
+        if (scrollPane == null  ||  scene != widget.getScene ())
+            return false;
+        newLocation = scene.convertSceneToView (widget.convertLocalToScene (newLocation));
+        SwingUtilities.convertPointToScreen (newLocation, scene.getView ());
+        JComponent view = scene.getView ();
+        Rectangle rectangle = view.getVisibleRect ();
+        rectangle.x += lastLocation.x - newLocation.x;
+        rectangle.y += lastLocation.y - newLocation.y;
+        view.scrollRectToVisible (rectangle);
+        lastLocation = newLocation;
+        return true;
+    }
+}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/EnableBlockLayoutAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/EnableBlockLayoutAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -27,6 +27,7 @@
 import javax.swing.AbstractAction;
 import javax.swing.Action;
 import javax.swing.ImageIcon;
+import org.openide.util.ImageUtilities;
 
 /**
  *
@@ -38,9 +39,9 @@
     public static final String STATE = "state";
 
     public EnableBlockLayoutAction() {
-        state = true;
-        putValue(AbstractAction.SMALL_ICON, new ImageIcon(org.openide.util.Utilities.loadImage(iconResource())));
-        putValue(STATE, true);
+        state = false;
+        putValue(AbstractAction.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(iconResource())));
+        putValue(STATE, state);
         putValue(Action.SHORT_DESCRIPTION, "Cluster nodes into blocks");
     }
 
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExpandPredecessorsAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExpandPredecessorsAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -33,6 +33,7 @@
  */
 public final class ExpandPredecessorsAction extends CallableSystemAction {
 
+    @Override
     public void performAction() {
         EditorTopComponent editor = EditorTopComponent.getActive();
         if (editor != null) {
@@ -40,8 +41,9 @@
         }
     }
 
+    @Override
     public String getName() {
-        return "Expand Predecessors";
+        return "Expand Above";
     }
 
     @Override
@@ -49,6 +51,7 @@
         super.initialize();
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExpandSuccessorsAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExpandSuccessorsAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -33,6 +33,7 @@
  */
 public final class ExpandSuccessorsAction extends CallableSystemAction {
 
+    @Override
     public void performAction() {
         EditorTopComponent editor = EditorTopComponent.getActive();
         if (editor != null) {
@@ -40,8 +41,9 @@
         }
     }
 
+    @Override
     public String getName() {
-        return "Expand Successors";
+        return "Expand Below";
     }
 
     @Override
@@ -49,6 +51,7 @@
         super.initialize();
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExportAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExportAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -32,12 +32,7 @@
 import javax.swing.JFileChooser;
 import javax.swing.KeyStroke;
 import javax.swing.filechooser.FileFilter;
-import org.openide.util.HelpCtx;
-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.util.*;
 import org.openide.util.actions.CallableSystemAction;
 
 /**
@@ -50,27 +45,31 @@
     private final Lookup.Result<ExportCookie> result;
 
     public ExportAction() {
-        putValue(Action.SHORT_DESCRIPTION, "Export current graph as an SVG file");
+        putValue(Action.SHORT_DESCRIPTION, "Export current graph as SVG file");
         putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.CTRL_MASK));
         lookup = Utilities.actionsGlobalContext();
-        result = lookup.lookup(new Lookup.Template<ExportCookie>(ExportCookie.class));
+        result = lookup.lookup(new Lookup.Template<>(ExportCookie.class));
         result.addLookupListener(this);
         resultChanged(null);
     }
 
+    @Override
     public void resultChanged(LookupEvent e) {
         super.setEnabled(result.allInstances().size() > 0);
     }
 
+    @Override
     public void performAction() {
 
         JFileChooser fc = new JFileChooser();
         fc.setFileFilter(new FileFilter() {
 
+            @Override
             public boolean accept(File f) {
                 return true;
             }
 
+            @Override
             public String getDescription() {
                 return "SVG files (*.svg)";
             }
@@ -97,15 +96,17 @@
         }
     }
 
+    @Override
     public String getName() {
         return NbBundle.getMessage(ExportAction.class, "CTL_ExportAction");
     }
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/view/images/export.gif";
+        return "com/sun/hotspot/igv/view/images/export.png";
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExtractAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ExtractAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -37,6 +37,7 @@
  */
 public final class ExtractAction extends CallableSystemAction {
 
+    @Override
     public void performAction() {
         EditorTopComponent editor = EditorTopComponent.getActive();
         if (editor != null) {
@@ -49,6 +50,7 @@
         putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_X, Event.CTRL_MASK, false));
     }
 
+    @Override
     public String getName() {
         return "Extract action";
     }
@@ -58,6 +60,7 @@
         super.initialize();
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/HideAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/HideAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -37,6 +37,7 @@
  */
 public final class HideAction extends CallableSystemAction {
 
+    @Override
     public void performAction() {
         EditorTopComponent editor = EditorTopComponent.getActive();
         if (editor != null) {
@@ -49,6 +50,7 @@
         putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_H, Event.CTRL_MASK, false));
     }
 
+    @Override
     public String getName() {
         return "Hide";
     }
@@ -58,6 +60,7 @@
         super.initialize();
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/HideDuplicatesAction.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014, 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 Tom Rodriguez
+ */
+public class HideDuplicatesAction extends AbstractAction {
+
+    private boolean state;
+    public static final String STATE = "state";
+
+    public HideDuplicatesAction() {
+        putValue(AbstractAction.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(iconResource())));
+        putValue(Action.SHORT_DESCRIPTION, "Hide graphs which are the same as the previous graph");
+        setState(false);
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent ev) {
+        setState(!state);
+    }
+
+    public void setState(boolean b) {
+        this.putValue(STATE, b);
+        this.state = b;
+    }
+
+    protected String iconResource() {
+        return "com/sun/hotspot/igv/view/images/hideDuplicates.png";
+    }
+}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/MouseOverAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/MouseOverAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/NextDiagramAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/NextDiagramAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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,15 +23,12 @@
  */
 package com.sun.hotspot.igv.view.actions;
 
-import com.sun.hotspot.igv.view.DiagramViewModel;
 import com.sun.hotspot.igv.data.ChangedListener;
 import com.sun.hotspot.igv.util.ContextAction;
+import com.sun.hotspot.igv.view.DiagramViewModel;
 import javax.swing.Action;
 import javax.swing.ImageIcon;
-import org.openide.util.HelpCtx;
-import org.openide.util.Lookup;
-import org.openide.util.NbBundle;
-import org.openide.util.Utilities;
+import org.openide.util.*;
 
 /**
  *
@@ -47,13 +44,15 @@
 
     public NextDiagramAction(Lookup lookup) {
         putValue(Action.SHORT_DESCRIPTION, "Show next graph of current group");
-        putValue(Action.SMALL_ICON, new ImageIcon(Utilities.loadImage("com/sun/hotspot/igv/view/images/next_diagram.png")));
+        putValue(Action.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage("com/sun/hotspot/igv/view/images/next_diagram.png")));
     }
 
+    @Override
     public String getName() {
         return NbBundle.getMessage(NextDiagramAction.class, "CTL_NextDiagramAction");
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
@@ -95,10 +94,12 @@
         return model.getSecondPosition() != model.getPositions().size() - 1;
     }
 
+    @Override
     public Action createContextAwareInstance(Lookup arg0) {
         return new NextDiagramAction(arg0);
     }
 
+    @Override
     public void changed(DiagramViewModel source) {
         update(source);
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/NodeFindAction.java	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * 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.actions;
-
-import com.sun.hotspot.igv.view.EditorTopComponent;
-import javax.swing.Action;
-import org.openide.util.HelpCtx;
-import org.openide.util.NbBundle;
-import org.openide.util.actions.CallableSystemAction;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public final class NodeFindAction extends CallableSystemAction {
-
-    public void performAction() {
-        EditorTopComponent comp = EditorTopComponent.getActive();
-        if (comp != null) {
-            comp.findNode();
-        }
-    }
-
-    public NodeFindAction() {
-        putValue(Action.SHORT_DESCRIPTION, "Find nodes");
-    }
-
-    public String getName() {
-        return NbBundle.getMessage(NodeFindAction.class, "CTL_NodeFindAction");
-    }
-
-    public HelpCtx getHelpCtx() {
-        return HelpCtx.DEFAULT_HELP;
-    }
-
-    @Override
-    protected boolean asynchronous() {
-        return false;
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return true;
-    }
-
-    @Override
-    protected String iconResource() {
-        return "com/sun/hotspot/igv/view/images/search.gif";
-    }
-}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/OverviewAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/OverviewAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -27,6 +27,7 @@
 import javax.swing.AbstractAction;
 import javax.swing.Action;
 import javax.swing.ImageIcon;
+import org.openide.util.ImageUtilities;
 
 /**
  *
@@ -38,11 +39,12 @@
     public static final String STATE = "state";
 
     public OverviewAction() {
-        putValue(AbstractAction.SMALL_ICON, new ImageIcon(org.openide.util.Utilities.loadImage(iconResource())));
+        putValue(AbstractAction.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(iconResource())));
         putValue(Action.SHORT_DESCRIPTION, "Show satellite view of whole graph");
         setState(false);
     }
 
+    @Override
     public void actionPerformed(ActionEvent ev) {
         setState(!state);
     }
@@ -53,6 +55,6 @@
     }
 
     protected String iconResource() {
-        return "com/sun/hotspot/igv/view/images/overview.gif";
+        return "com/sun/hotspot/igv/view/images/overview.png";
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/PanModeAction.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2011, 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;
+
+public class PanModeAction extends AbstractAction {
+
+    private boolean state;
+
+    public PanModeAction() {
+        putValue(AbstractAction.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(iconResource())));
+        putValue(SELECTED_KEY, false);
+        putValue(Action.SHORT_DESCRIPTION, "Panning mode");
+    }
+
+    public boolean isSelected() {
+        return (Boolean)getValue(SELECTED_KEY);
+    }
+
+    public void setSelected(boolean b) {
+        if (isSelected() != b) {
+            this.putValue(SELECTED_KEY, b);
+        }
+    }
+
+    protected String iconResource() {
+        return "com/sun/hotspot/igv/view/images/pan_mode.png";
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+    }
+}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/PredSuccAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/PredSuccAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -27,6 +27,7 @@
 import javax.swing.AbstractAction;
 import javax.swing.Action;
 import javax.swing.ImageIcon;
+import org.openide.util.ImageUtilities;
 
 /**
  *
@@ -39,11 +40,12 @@
 
     public PredSuccAction() {
         state = true;
-        putValue(AbstractAction.SMALL_ICON, new ImageIcon(org.openide.util.Utilities.loadImage(iconResource())));
+        putValue(AbstractAction.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(iconResource())));
         putValue(STATE, true);
         putValue(Action.SHORT_DESCRIPTION, "Show neighboring nodes of fully visible nodes semi-transparent");
     }
 
+    @Override
     public void actionPerformed(ActionEvent ev) {
         this.state = !state;
         this.putValue(STATE, state);
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/PrevDiagramAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/PrevDiagramAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -24,14 +24,11 @@
 package com.sun.hotspot.igv.view.actions;
 
 import com.sun.hotspot.igv.data.ChangedListener;
+import com.sun.hotspot.igv.util.ContextAction;
 import com.sun.hotspot.igv.view.DiagramViewModel;
-import com.sun.hotspot.igv.util.ContextAction;
 import javax.swing.Action;
 import javax.swing.ImageIcon;
-import org.openide.util.HelpCtx;
-import org.openide.util.Lookup;
-import org.openide.util.NbBundle;
-import org.openide.util.Utilities;
+import org.openide.util.*;
 
 /**
  *
@@ -47,13 +44,15 @@
 
     public PrevDiagramAction(Lookup lookup) {
         putValue(Action.SHORT_DESCRIPTION, "Show previous graph of current group");
-        putValue(Action.SMALL_ICON, new ImageIcon(Utilities.loadImage("com/sun/hotspot/igv/view/images/prev_diagram.png")));
+        putValue(Action.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage("com/sun/hotspot/igv/view/images/prev_diagram.png")));
     }
 
+    @Override
     public String getName() {
         return NbBundle.getMessage(PrevDiagramAction.class, "CTL_PrevDiagramAction");
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
@@ -95,10 +94,12 @@
         return model.getFirstPosition() != 0;
     }
 
+    @Override
     public Action createContextAwareInstance(Lookup arg0) {
         return new PrevDiagramAction(arg0);
     }
 
+    @Override
     public void changed(DiagramViewModel source) {
         update(source);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/SelectionModeAction.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2011, 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;
+
+public class SelectionModeAction extends AbstractAction {
+
+    public SelectionModeAction() {
+        putValue(AbstractAction.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(iconResource())));
+        putValue(SELECTED_KEY, false);
+        putValue(Action.SHORT_DESCRIPTION, "Selection mode");
+    }
+
+    public boolean isSelected() {
+        return (Boolean)getValue(SELECTED_KEY);
+    }
+
+    public void setSelected(boolean b) {
+        if (isSelected() != b) {
+            this.putValue(SELECTED_KEY, b);
+        }
+    }
+
+    protected String iconResource() {
+        return "com/sun/hotspot/igv/view/images/selection_mode.png";
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+    }
+}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ShowAllAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ShowAllAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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,7 +23,7 @@
  */
 package com.sun.hotspot.igv.view.actions;
 
-import com.sun.hotspot.igv.view.*;
+import com.sun.hotspot.igv.view.EditorTopComponent;
 import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
 import javax.swing.Action;
@@ -37,6 +37,7 @@
  */
 public final class ShowAllAction extends CallableSystemAction {
 
+    @Override
     public void performAction() {
         EditorTopComponent editor = EditorTopComponent.getActive();
         if (editor != null) {
@@ -49,6 +50,7 @@
         putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_MASK));
     }
 
+    @Override
     public String getName() {
         return "Show all";
     }
@@ -58,6 +60,7 @@
         super.initialize();
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ZoomInAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ZoomInAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -37,6 +37,7 @@
  */
 public final class ZoomInAction extends CallableSystemAction {
 
+    @Override
     public void performAction() {
         EditorTopComponent editor = EditorTopComponent.getActive();
         if (editor != null) {
@@ -44,6 +45,7 @@
         }
     }
 
+    @Override
     public String getName() {
         return "Zoom in";
     }
@@ -53,6 +55,7 @@
         putValue(Action.SHORT_DESCRIPTION, "Zoom in");
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
@@ -64,6 +67,6 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/view/images/zoomin.gif";
+        return "com/sun/hotspot/igv/view/images/zoom_in.png";
     }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ZoomOutAction.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/actions/ZoomOutAction.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -37,6 +37,7 @@
  */
 public final class ZoomOutAction extends CallableSystemAction {
 
+    @Override
     public void performAction() {
         EditorTopComponent editor = EditorTopComponent.getActive();
         if (editor != null) {
@@ -50,6 +51,7 @@
         putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, Event.CTRL_MASK, false));
     }
 
+    @Override
     public String getName() {
         return "Zoom out";
     }
@@ -59,6 +61,7 @@
         super.initialize();
     }
 
+    @Override
     public HelpCtx getHelpCtx() {
         return HelpCtx.DEFAULT_HELP;
     }
@@ -70,6 +73,6 @@
 
     @Override
     protected String iconResource() {
-        return "com/sun/hotspot/igv/view/images/zoomout.gif";
+        return "com/sun/hotspot/igv/view/images/zoom_out.png";
     }
 }
Binary file hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/export.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/export.png has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/hideDuplicates.png has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/overview.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/overview.png has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/pan_mode.png has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/search.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/selection_mode.png has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/zoom_in.png has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/zoom_out.png has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/zoomin.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/images/zoomout.gif has changed
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/layer.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/layer.xml	Fri May 08 13:25:11 2015 -0400
@@ -24,36 +24,65 @@
         <folder name="View">
             <file name="com-sun-hotspot-igv-view-actions-PrevDiagramAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/View/com-sun-hotspot-igv-view-actions-PrevDiagramAction.instance"/>
+                <attr name="position" intvalue="100"/>
             </file>
             <file name="com-sun-hotspot-igv-view-actions-NextDiagramAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/View/com-sun-hotspot-igv-view-actions-NextDiagramAction.instance"/>
+                <attr name="position" intvalue="150"/>
             </file>
             <file name="com-sun-hotspot-igv-view-actions-ShowAllAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/View/com-sun-hotspot-igv-view-actions-ShowAllAction.instance"/>
+                <attr name="position" intvalue="200"/>
             </file>
             <file name="com-sun-hotspot-igv-view-actions-ExtractAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/View/com-sun-hotspot-igv-view-actions-ExtractAction.instance"/>
+                <attr name="position" intvalue="300"/>
             </file>
             <file name="com-sun-hotspot-igv-view-actions-HideAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/View/com-sun-hotspot-igv-view-actions-HideAction.instance"/>
+                <attr name="position" intvalue="400"/>
             </file>
             <file name="com-sun-hotspot-igv-view-actions-ZoomInAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/View/com-sun-hotspot-igv-view-actions-ZoomInAction.instance"/>
+                <attr name="position" intvalue="500"/>
             </file>
             <file name="com-sun-hotspot-igv-view-actions-ZoomOutAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/View/com-sun-hotspot-igv-view-actions-ZoomOutAction.instance"/>
+                <attr name="position" intvalue="550"/>
             </file>
         </folder>
         <folder name="File">
+            <file name="ExportActionSeparator.instance">
+                <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
+                <attr name="position" intvalue="700"/>
+            </file>
             <file name="com-sun-hotspot-igv-view-actions-ExportAction.shadow">
                 <attr name="originalFile" stringvalue="Actions/File/com-sun-hotspot-igv-view-actions-ExportAction.instance"/>
-                <attr name="position" intvalue="600"/>
+                <attr name="position" intvalue="710"/>
             </file>
         </folder>
     </folder>
-    <folder name="Toolbars">
-        <folder name="Edit">
-            <attr name="com-sun-hotspot-igv-view-actions-LineGeneratorAction.shadow/com-sun-hotspot-igv-coordinator-actions-OpenGraphAction.shadow" boolvalue="true"/>
+
+    <folder name="QuickSearch">
+        <folder name="Nodes">
+            <attr name="command" stringvalue="n"/>
+            <attr name="position" intvalue="0"/>
+            <file name="com-sun-hotspot-igv-view-NodeQuickSearch.instance"/>
+        </folder>
+    </folder>
+    
+    <folder name="QuickSearchShadow">
+        <file name="org-netbeans-modules-quicksearch-QuickSearchAction.shadow">
+            <attr name="originalFile" stringvalue="Actions/Edit/org-netbeans-modules-quicksearch-QuickSearchAction.instance"/>
+            
+        </file>    
+    </folder>
+    <folder name="Windows2">
+        <folder name="Modes">
+            <folder name="properties">
+                <file name="properties.wstcref" url="propertiesWstcref.xml"/>
+            </folder>
+            <file name="properties.wsmode" url="propertiesWsmode.xml"/>
         </folder>
     </folder>
 </filesystem>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/propertiesWsmode.xml	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE mode PUBLIC
+          "-//NetBeans//DTD Mode Properties 2.0//EN"
+          "http://www.netbeans.org/dtds/mode-properties2_0.dtd">
+
+<mode version="2.0">
+    <name unique="properties" />
+    <kind type="view" />
+    <state type="joined" />
+    <constraints>
+        <path orientation="horizontal" number="90" weight="0.2"/>
+        <path orientation="vertical" number="1" weight="0.50"/>
+    </constraints>
+    <relative-bounds x="75" y="56" width="15" height="32" />
+    <active-tc id="properties" />
+    <empty-behavior permanent="true" />
+</mode>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/propertiesWstcref.xml	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,11 @@
+<?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="org.netbeans.core.ui/1" spec="1.2" />
+    <tc-id id="properties" />
+    <state opened="true" />
+</tc-ref>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/BlockWidget.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/BlockWidget.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -74,7 +74,7 @@
         g.setColor(titleColor);
         g.setFont(titleFont);
 
-        String s = "B" + blockNode.toString();
+        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/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/DiagramConnectionWidget.java	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,251 +0,0 @@
-/*
- * 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.graph.Connection;
-import com.sun.hotspot.igv.graph.Figure;
-import com.sun.hotspot.igv.view.DiagramScene;
-import java.awt.BasicStroke;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.Stroke;
-import java.util.ArrayList;
-import java.util.List;
-import org.netbeans.api.visual.anchor.AnchorShape;
-import org.netbeans.api.visual.model.ObjectState;
-import org.netbeans.api.visual.widget.ConnectionWidget;
-import org.netbeans.api.visual.widget.Scene;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class DiagramConnectionWidget extends ConnectionWidget {
-
-    private static Stroke DASHED_STROKE = new BasicStroke(
-            1,
-            BasicStroke.CAP_BUTT,
-            BasicStroke.JOIN_ROUND,
-            0,
-            new float[]{2},
-            0);
-    private static Stroke NORMAL_STROKE = new BasicStroke(1);
-    private static Stroke BOLD_STROKE = new BasicStroke(3);
-    public static int WHITE_FACTOR = 5;
-    private Connection connection;
-    private Color color;
-    private Point lastSourceAnchor;
-    private Point lastTargetAnchor;
-    private List<Point> controlPoints;
-    private Rectangle clientArea;
-    private boolean split;
-    private int[] xPoints;
-    private int[] yPoints;
-    private int pointCount;
-
-    /** Creates a new instance of ConnectionWidget */
-    public DiagramConnectionWidget(Connection connection, Scene scene) {
-        super(scene);
-        this.connection = connection;
-        color = connection.getColor();
-        if (connection.getStyle() == Connection.ConnectionStyle.DASHED) {
-            this.setStroke(DASHED_STROKE);
-        } else if (connection.getStyle() == Connection.ConnectionStyle.BOLD) {
-            this.setStroke(BOLD_STROKE);
-        } else {
-            this.setStroke(NORMAL_STROKE);
-        }
-        this.setCheckClipping(true);
-        clientArea = new Rectangle();
-        updateControlPoints();
-    }
-
-    public Connection getConnection() {
-        return connection;
-    }
-
-    public void updateControlPoints() {
-        List<Point> newControlPoints = connection.getControlPoints();
-        Connection c = connection;
-        Figure f = c.getInputSlot().getFigure();
-        Point p = new Point(f.getPosition());
-        p.translate(c.getInputSlot().getRelativePosition().x, f.getSize().height / 2);
-        Point p4 = new Point(f.getPosition());
-        p4.translate(c.getInputSlot().getRelativePosition().x, c.getInputSlot().getRelativePosition().y);
-
-        Figure f2 = c.getOutputSlot().getFigure();
-        Point p2 = new Point(f2.getPosition());
-        p2.translate(c.getOutputSlot().getRelativePosition().x, f2.getSize().height / 2);
-        Point p3 = new Point(f2.getPosition());
-        p3.translate(c.getOutputSlot().getRelativePosition().x, c.getOutputSlot().getRelativePosition().y);
-
-        /*if(controlPoints.size() >= 2) {
-        String className = Preferences.userNodeForPackage(PreferenceConstants.class).get(PreferenceConstants.KEY_LINE_GENERATOR, PreferenceConstants.DEFAULT_LINE_GENERATOR);
-        try {
-        LineGenerator lg = (LineGenerator)Class.forName(className).newInstance();
-        controlPoints = lg.createLine(controlPoints, p2, p);
-        } catch (InstantiationException ex) {
-        } catch (IllegalAccessException ex) {
-        } catch (ClassNotFoundException ex) {
-        }
-        }*/
-
-        this.controlPoints = newControlPoints;
-        pointCount = newControlPoints.size();
-        xPoints = new int[pointCount];
-        yPoints = new int[pointCount];
-        int minX = Integer.MAX_VALUE;
-        int maxX = Integer.MIN_VALUE;
-        int minY = Integer.MAX_VALUE;
-        int maxY = Integer.MIN_VALUE;
-        split = false;
-        for (int i = 0; i < pointCount; i++) {
-            if (newControlPoints.get(i) == null) {
-                split = true;
-            } else {
-                int curX = newControlPoints.get(i).x;
-                int curY = newControlPoints.get(i).y;
-                this.xPoints[i] = curX;
-                this.yPoints[i] = curY;
-                minX = Math.min(minX, curX);
-                maxX = Math.max(maxX, curX);
-                minY = Math.min(minY, curY);
-                maxY = Math.max(maxY, curY);
-            }
-        }
-
-        this.clientArea = new Rectangle(minX, minY, maxX - minX, maxY - minY);
-    }
-
-    @Override
-    protected void paintWidget() {
-        Graphics2D g = this.getGraphics();
-
-        if (xPoints.length == 0 || Math.abs(xPoints[0] - xPoints[xPoints.length - 1]) > 2000) {
-            return;
-        }
-
-        //g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
-        //g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
-        //g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
-
-        DiagramScene ds = (DiagramScene) this.getScene();
-        boolean shouldHide = false;//ds.getShouldHide(this);
-
-        Composite oldComposite = null;
-        if (shouldHide) {
-            Color c = new Color(255 - (255 - color.getRed()) / WHITE_FACTOR, 255 - (255 - color.getGreen()) / WHITE_FACTOR, 255 - (255 - color.getBlue()) / WHITE_FACTOR);
-            g.setPaint(c);
-        } else {
-            g.setPaint(color);
-        }
-
-        if (split) {
-            for (int i = 1; i < controlPoints.size(); i++) {
-                Point prev = controlPoints.get(i - 1);
-                Point cur = controlPoints.get(i);
-                if (cur == null || prev == null) {
-                    continue;
-                }
-
-                g.drawLine(prev.x, prev.y, cur.x, cur.y);
-            }
-        } else {
-            g.drawPolyline(xPoints, yPoints, pointCount);
-        }
-
-        /*for(int i=0; i<xPoints.length; i++) {
-        int x = xPoints[i];
-        int y = yPoints[i];
-        g.fillOval(x - 2, y - 2, 4, 4);
-        }*/
-
-        if (xPoints.length >= 2) {
-            Graphics2D g2 = (Graphics2D) g.create();
-            int xOff = xPoints[xPoints.length - 2] - xPoints[xPoints.length - 1];
-            int yOff = yPoints[yPoints.length - 2] - yPoints[yPoints.length - 1];
-            if (xOff == 0 && yOff == 0 && yPoints.length >= 3) {
-                xOff = xPoints[xPoints.length - 3] - xPoints[xPoints.length - 1];
-                yOff = yPoints[yPoints.length - 3] - yPoints[yPoints.length - 1];
-            }
-            g2.translate(xPoints[xPoints.length - 1], yPoints[yPoints.length - 1]);
-            g2.rotate(Math.atan2(yOff, xOff));
-
-            g2.scale(0.55, 0.80);
-            AnchorShape.TRIANGLE_FILLED.paint(g2, false);
-        }
-    }
-
-    @Override
-    public void notifyStateChanged(ObjectState previousState, ObjectState state) {
-
-        if (previousState.isHovered() != state.isHovered()) {
-            color = connection.getColor();
-            if (state.isHovered()) {
-                this.setStroke(BOLD_STROKE);
-            } else {
-                this.setStroke(NORMAL_STROKE);
-            }
-
-            if (state.isHovered()) {
-                this.setStroke(BOLD_STROKE);
-            } else {
-                this.setStroke(NORMAL_STROKE);
-            }
-
-            repaint();
-        }
-        super.notifyStateChanged(previousState, state);
-    }
-
-    @Override
-    public List<Point> getControlPoints() {
-        if (split) {
-            ArrayList<Point> result = new ArrayList<Point>();
-            for (Point p : controlPoints) {
-                if (p != null) {
-                    result.add(p);
-                }
-            }
-            return result;
-        } else {
-            return controlPoints;
-        }
-    }
-
-    @Override
-    public String toString() {
-        return "ConnectionWidget[" + connection + "]";
-    }
-
-    @Override
-    protected Rectangle calculateClientArea() {
-        Rectangle result = new Rectangle(clientArea);
-        result.grow(10, 10);
-        return result;
-    }
-}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/FigureWidget.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/FigureWidget.java	Fri May 08 13:25:11 2015 -0400
@@ -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,36 +23,37 @@
  */
 package com.sun.hotspot.igv.view.widgets;
 
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.data.services.GraphViewer;
 import com.sun.hotspot.igv.graph.Figure;
-import com.sun.hotspot.igv.view.DiagramScene;
-import com.sun.hotspot.igv.view.SlotLayout;
+import com.sun.hotspot.igv.util.DoubleClickAction;
 import com.sun.hotspot.igv.util.DoubleClickHandler;
-import com.sun.hotspot.igv.data.Properties;
 import com.sun.hotspot.igv.util.PropertiesSheet;
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.Dimension;
-import java.awt.Font;
-import java.awt.Graphics;
-import java.awt.Point;
+import com.sun.hotspot.igv.view.DiagramScene;
+import java.awt.*;
+import java.awt.event.ActionEvent;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Set;
+import javax.swing.AbstractAction;
 import javax.swing.Action;
 import javax.swing.BorderFactory;
 import javax.swing.JMenu;
 import javax.swing.JPopupMenu;
+import javax.swing.event.MenuEvent;
+import javax.swing.event.MenuListener;
 import org.netbeans.api.visual.action.PopupMenuProvider;
 import org.netbeans.api.visual.action.WidgetAction;
+import org.netbeans.api.visual.layout.LayoutFactory;
 import org.netbeans.api.visual.model.ObjectState;
+import org.netbeans.api.visual.widget.LabelWidget;
 import org.netbeans.api.visual.widget.Widget;
-import org.netbeans.api.visual.layout.LayoutFactory;
-import org.netbeans.api.visual.widget.LabelWidget;
 import org.openide.nodes.AbstractNode;
 import org.openide.nodes.Children;
 import org.openide.nodes.Node;
 import org.openide.nodes.Sheet;
+import org.openide.util.Lookup;
 
 /**
  *
@@ -61,12 +62,7 @@
 public class FigureWidget extends Widget implements Properties.Provider, PopupMenuProvider, DoubleClickHandler {
 
     public static final boolean VERTICAL_LAYOUT = true;
-    public static final int DEPTH = 5;
-    public static final int MAX_STRING_LENGTH = 20;
     private static final double LABEL_ZOOM_FACTOR = 0.3;
-    private static final double ZOOM_FACTOR = 0.1;
-    private Font font;
-    private Font boldFont;
     private Figure figure;
     private Widget leftWidget;
     private Widget rightWidget;
@@ -74,7 +70,8 @@
     private ArrayList<LabelWidget> labelWidgets;
     private DiagramScene diagramScene;
     private boolean boundary;
-    private Node node;
+    private final Node node;
+    private Widget dummyTop;
 
     public void setBoundary(boolean b) {
         boundary = b;
@@ -88,80 +85,58 @@
         return node;
     }
 
-    private String shortenString(String string) {
-        if (string.length() > MAX_STRING_LENGTH) {
-            StringBuilder sb = new StringBuilder();
-            for (int i = 0; i < string.length(); i++) {
-                char c = string.charAt(i);
-                if (!Character.isLetter(c) || Character.isUpperCase(c)) {
-                    sb.append(c);
-                }
-            }
-            string = sb.toString();
-        }
-        return string;
+    @Override
+    public boolean isHitAt(Point localLocation) {
+        return middleWidget.isHitAt(localLocation);
     }
 
-    public FigureWidget(final Figure f, DiagramScene s, Widget parent) {
-
-        super(s);
-
+    public FigureWidget(final Figure f, WidgetAction hoverAction, WidgetAction selectAction, DiagramScene scene, Widget parent) {
+        super(scene);
 
-        font = f.getDiagram().getFont();
-        boldFont = f.getDiagram().getFont().deriveFont(Font.BOLD);
-        this.setCheckClipping(true);
-        this.diagramScene = s;
-
-        parent.addChild(this);
-        this.figure = f;
-        this.resolveBounds(null, calculateClientArea());
+        assert this.getScene() != null;
+        assert this.getScene().getView() != null;
 
-        leftWidget = new Widget(s);
-        this.addChild(leftWidget);
-        leftWidget.setLayout(new SlotLayout(SlotLayout.HorizontalAlignment.Right, VERTICAL_LAYOUT));//LayoutFactory.createVerticalFlowLayout(LayoutFactory.SerialAlignment.JUSTIFY, 0));
-
-        middleWidget = new Widget(s);
-        this.addChild(middleWidget);
+        this.figure = f;
+        this.setCheckClipping(true);
+        this.diagramScene = scene;
+        parent.addChild(this);
 
-        if (VERTICAL_LAYOUT) {
-            this.setLayout(LayoutFactory.createVerticalFlowLayout());
-        } else {
-            this.setLayout(LayoutFactory.createHorizontalFlowLayout());
-        }
+        Widget outer = new Widget(scene);
+        outer.setBackground(f.getColor());
+        outer.setLayout(LayoutFactory.createOverlayLayout());
 
-        middleWidget.setLayout(LayoutFactory.createVerticalFlowLayout());
-
+        middleWidget = new Widget(scene);
+        middleWidget.setLayout(LayoutFactory.createVerticalFlowLayout(LayoutFactory.SerialAlignment.CENTER, 0));
         middleWidget.setBackground(f.getColor());
         middleWidget.setOpaque(true);
-        assert this.getScene() != null;
-        assert this.getScene().getView() != null;
-        middleWidget.setBorder(BorderFactory.createLineBorder(Color.BLACK));
+        middleWidget.getActions().addAction(new DoubleClickAction(this));
+        middleWidget.setCheckClipping(true);
 
-
-        labelWidgets = new ArrayList<LabelWidget>();
+        dummyTop = new Widget(scene);
+        dummyTop.setMinimumSize(new Dimension(Figure.INSET / 2, 1));
+        middleWidget.addChild(dummyTop);
 
         String[] strings = figure.getLines();
-
-        for (String cur : strings) {
+        labelWidgets = new ArrayList<>(strings.length);
 
-            String displayString = cur;
-
-            LabelWidget lw = new LabelWidget(s);
+        for (String displayString : strings) {
+            LabelWidget lw = new LabelWidget(scene);
             labelWidgets.add(lw);
             middleWidget.addChild(lw);
             lw.setLabel(displayString);
-
-            lw.setFont(font);
-            lw.setForeground(Color.BLACK);
+            lw.setFont(figure.getDiagram().getFont());
+            lw.setForeground(getTextColor());
             lw.setAlignment(LabelWidget.Alignment.CENTER);
             lw.setVerticalAlignment(LabelWidget.VerticalAlignment.CENTER);
-            lw.setMaximumSize(new Dimension(f.getWidth(), 20000));
-            lw.setMinimumSize(new Dimension(f.getWidth(), 20));
+            lw.setBorder(BorderFactory.createEmptyBorder());
         }
 
-        rightWidget = new Widget(s);
-        this.addChild(rightWidget);
-        rightWidget.setLayout(new SlotLayout(SlotLayout.HorizontalAlignment.Left, VERTICAL_LAYOUT));//LayoutFactory.createVerticalLayout(LayoutFactory.SerialAlignment.JUSTIFY, 0));
+        Widget dummyBottom = new Widget(scene);
+        dummyBottom.setMinimumSize(new Dimension(Figure.INSET / 2, 1));
+        middleWidget.addChild(dummyBottom);
+
+        middleWidget.setPreferredBounds(new Rectangle(0, Figure.SLOT_WIDTH - Figure.OVERLAPPING, f.getWidth(), f.getHeight()));
+        this.addChild(middleWidget);
 
         // Initialize node for property sheet
         node = new AbstractNode(Children.LEAF) {
@@ -175,22 +150,6 @@
         };
         node.setDisplayName(getName());
     }
-    private boolean firstTime = true;
-
-    @Override
-    protected void paintWidget() {
-        if (firstTime) {
-            firstTime = false;
-            for (LabelWidget w : labelWidgets) {
-                String cur = w.getLabel();
-                Graphics graphics = this.getGraphics();
-                if (graphics.getFontMetrics().stringWidth(cur) > figure.getWidth()) {
-                    w.setLabel(shortenString(cur));
-                }
-            }
-        }
-        super.paintWidget();
-    }
 
     public Widget getLeftWidget() {
         return leftWidget;
@@ -204,40 +163,29 @@
     protected void notifyStateChanged(ObjectState previousState, ObjectState state) {
         super.notifyStateChanged(previousState, state);
 
-        Color borderColor = Color.BLACK;
-        int thickness = 1;
-        boolean repaint = false;
-        Font f = font;
+        Font font = this.figure.getDiagram().getFont();
         if (state.isSelected()) {
-            thickness = 1;
-            f = boldFont;
-        }
-
-        if (state.isHovered()) {
-            borderColor = Color.BLUE;
+            font = this.figure.getDiagram().getBoldFont();
         }
 
-        if (state.isHovered() != previousState.isHovered()) {
-            repaint = true;
-        }
-
-        if (state.isSelected() != previousState.isSelected()) {
-            repaint = true;
+        Color borderColor = Color.BLACK;
+        Color innerBorderColor = getFigure().getColor();
+        if (state.isHighlighted()) {
+            innerBorderColor = borderColor = Color.BLUE;
         }
 
-        if (repaint) {
-            middleWidget.setBorder(BorderFactory.createLineBorder(borderColor, thickness));
-            for (LabelWidget labelWidget : labelWidgets) {
-                labelWidget.setFont(f);
-            }
-            repaint();
+        middleWidget.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(borderColor, 1), BorderFactory.createLineBorder(innerBorderColor, 1)));
+        for (LabelWidget labelWidget : labelWidgets) {
+            labelWidget.setFont(font);
         }
+        repaint();
     }
 
     public String getName() {
         return getProperties().get("name");
     }
 
+    @Override
     public Properties getProperties() {
         return figure.getProperties();
     }
@@ -246,13 +194,18 @@
         return figure;
     }
 
+    private Color getTextColor() {
+        Color bg = figure.getColor();
+        double brightness = bg.getRed() * 0.21 + bg.getGreen() * 0.72 + bg.getBlue() * 0.07;
+        if (brightness < 150) {
+            return Color.WHITE;
+        } else {
+            return Color.BLACK;
+        }
+    }
+
     @Override
     protected void paintChildren() {
-
-        if (diagramScene.getRealZoomFactor() < ZOOM_FACTOR && diagramScene.getModel().getShowBlocks()) {
-            return;
-        }
-
         Composite oldComposite = null;
         if (boundary) {
             oldComposite = getScene().getGraphics().getComposite();
@@ -260,8 +213,7 @@
             this.getScene().getGraphics().setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
         }
 
-        if (diagramScene.getRealZoomFactor() < LABEL_ZOOM_FACTOR) {
-
+        if (diagramScene.getZoomFactor() < LABEL_ZOOM_FACTOR) {
             for (LabelWidget labelWidget : labelWidgets) {
                 labelWidget.setVisible(false);
             }
@@ -269,9 +221,20 @@
             for (LabelWidget labelWidget : labelWidgets) {
                 labelWidget.setVisible(true);
             }
-
         } else {
+            Color oldColor = null;
+            if (boundary) {
+                for (LabelWidget labelWidget : labelWidgets) {
+                    oldColor = labelWidget.getForeground();
+                    labelWidget.setForeground(Color.BLACK);
+                }
+            }
             super.paintChildren();
+            if (boundary) {
+                for (LabelWidget labelWidget : labelWidgets) {
+                    labelWidget.setForeground(oldColor);
+                }
+            }
         }
 
         if (boundary) {
@@ -279,80 +242,126 @@
         }
     }
 
+    @Override
     public JPopupMenu getPopupMenu(Widget widget, Point point) {
-        JPopupMenu m = diagramScene.createPopupMenu();
+        JPopupMenu menu = diagramScene.createPopupMenu();
+        menu.addSeparator();
 
-        JMenu predecessors = new JMenu("Predecessors");
-        addFigureToSubMenu(predecessors, getFigure(), false, DEPTH);
+        build(menu, getFigure(), this, false, diagramScene);
+        menu.addSeparator();
+        build(menu, getFigure(), this, true, diagramScene);
+
+        if (getFigure().getSubgraphs() != null) {
+            menu.addSeparator();
+            JMenu subgraphs = new JMenu("Subgraphs");
+            menu.add(subgraphs);
 
-        JMenu successors = new JMenu("Successors");
-        addFigureToSubMenu(successors, getFigure(), true, DEPTH);
+            final GraphViewer viewer = Lookup.getDefault().lookup(GraphViewer.class);
+            for (final InputGraph subgraph : getFigure().getSubgraphs()) {
+                Action a = new AbstractAction() {
 
-        m.addSeparator();
-        m.add(predecessors);
-        m.add(successors);
-        return m;
+                    @Override
+                    public void actionPerformed(ActionEvent e) {
+                        viewer.view(subgraph, true);
+                    }
+                };
+
+                a.setEnabled(true);
+                a.putValue(Action.NAME, subgraph.getName());
+                subgraphs.add(a);
+            }
+        }
+
+        return menu;
     }
 
-    public void addFigureToSubMenu(JMenu subMenu, final Figure f, boolean successor, int depth) {
-        Set<Figure> set = f.getPredecessorSet();
-        if (successor) {
-            set = f.getSuccessorSet();
+    public static void build(JPopupMenu menu, Figure figure, FigureWidget figureWidget, boolean successors, DiagramScene diagramScene) {
+        Set<Figure> set = figure.getPredecessorSet();
+        if (successors) {
+            set = figure.getSuccessorSet();
         }
 
-        int count = set.size();
-        if (set.contains(f)) {
-            count--;
-        }
-
-        for (Figure f2 : set) {
-            if (f2 == f) {
+        boolean first = true;
+        for (Figure f : set) {
+            if (f == figure) {
                 continue;
             }
 
-            count--;
-            addFigureToMenu(subMenu, f2, successor, depth - 1);
-            if (count > 0) {
-                subMenu.addSeparator();
+            if (first) {
+                first = false;
+            } else {
+                menu.addSeparator();
             }
+
+            Action go = diagramScene.createGotoAction(f);
+            menu.add(go);
+
+            JMenu preds = new JMenu("Nodes Above");
+            preds.addMenuListener(figureWidget.new NeighborMenuListener(preds, f, false));
+            menu.add(preds);
+
+            JMenu succs = new JMenu("Nodes Below");
+            succs.addMenuListener(figureWidget.new NeighborMenuListener(succs, f, true));
+            menu.add(succs);
+        }
+
+        if (figure.getPredecessorSet().isEmpty() && figure.getSuccessorSet().isEmpty()) {
+            menu.add("(none)");
         }
     }
 
-    public void addFigureToMenu(JMenu m, final Figure f, boolean successor, int depth) {
+    /**
+     * Builds the submenu for a figure's neighbors on demand.
+     */
+    public class NeighborMenuListener implements MenuListener {
 
-        Action a = diagramScene.createGotoAction(f);
-
+        private final JMenu menu;
+        private final Figure figure;
+        private final boolean successors;
 
-        m.add(a);
+        public NeighborMenuListener(JMenu menu, Figure figure, boolean successors) {
+            this.menu = menu;
+            this.figure = figure;
+            this.successors = successors;
+        }
 
-        if (depth > 0) {
-            String name = "Predecessors";
-            if (successor) {
-                name = "Successors";
+        @Override
+        public void menuSelected(MenuEvent e) {
+            if (menu.getItemCount() > 0) {
+                // already built before
+                return;
             }
 
-            JMenu subMenu = new JMenu(name);
-            addFigureToSubMenu(subMenu, f, successor, depth);
-            m.add(subMenu);
+            build(menu.getPopupMenu(), figure, FigureWidget.this, successors, diagramScene);
+        }
+
+        @Override
+        public void menuDeselected(MenuEvent e) {
+            // ignore
         }
 
+        @Override
+        public void menuCanceled(MenuEvent e) {
+            // ignore
+        }
     }
 
+    @Override
     public void handleDoubleClick(Widget w, WidgetAction.WidgetMouseEvent e) {
 
         if (diagramScene.isAllVisible()) {
-            Set<Integer> hiddenNodes = new HashSet<Integer>(diagramScene.getModel().getGraphToView().getGroup().getAllNodes());
+            final Set<Integer> hiddenNodes = new HashSet<>(diagramScene.getModel().getGraphToView().getGroup().getAllNodes());
             hiddenNodes.removeAll(this.getFigure().getSource().getSourceNodesAsSet());
-            this.diagramScene.showNot(hiddenNodes);
+            this.diagramScene.getModel().showNot(hiddenNodes);
         } else if (isBoundary()) {
 
-            Set<Integer> hiddenNodes = new HashSet<Integer>(diagramScene.getModel().getHiddenNodes());
+            final Set<Integer> hiddenNodes = new HashSet<>(diagramScene.getModel().getHiddenNodes());
             hiddenNodes.removeAll(this.getFigure().getSource().getSourceNodesAsSet());
-            this.diagramScene.showNot(hiddenNodes);
+            this.diagramScene.getModel().showNot(hiddenNodes);
         } else {
-            Set<Integer> hiddenNodes = new HashSet<Integer>(diagramScene.getModel().getHiddenNodes());
+            final Set<Integer> hiddenNodes = new HashSet<>(diagramScene.getModel().getHiddenNodes());
             hiddenNodes.addAll(this.getFigure().getSource().getSourceNodesAsSet());
-            this.diagramScene.showNot(hiddenNodes);
+            this.diagramScene.getModel().showNot(hiddenNodes);
         }
     }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/InputSlotWidget.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/InputSlotWidget.java	Fri May 08 13:25:11 2015 -0400
@@ -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.view.widgets;
 
+import com.sun.hotspot.igv.graph.Figure;
 import com.sun.hotspot.igv.graph.InputSlot;
 import com.sun.hotspot.igv.view.DiagramScene;
 import java.awt.Point;
@@ -40,14 +41,25 @@
     public InputSlotWidget(InputSlot slot, DiagramScene scene, Widget parent, FigureWidget fw) {
         super(slot, scene, parent, fw);
         inputSlot = slot;
-        init();
-        getFigureWidget().getLeftWidget().addChild(this);
+        //init();
+        //getFigureWidget().getLeftWidget().addChild(this);
+        Point p = inputSlot.getRelativePosition();
+        p.x -= this.calculateClientArea().width / 2;
+        p.y += Figure.SLOT_START;
+        this.setPreferredLocation(p);
     }
 
     public InputSlot getInputSlot() {
         return inputSlot;
     }
 
+    @Override
+    protected int calculateSlotWidth() {
+        List<InputSlot> slots = getSlot().getFigure().getInputSlots();
+        assert slots.contains(getSlot());
+        return calculateWidth(slots.size());
+    }
+/*
     protected Point calculateRelativeLocation() {
         if (getFigureWidget().getBounds() == null) {
             return new Point(0, 0);
@@ -57,5 +69,5 @@
         List<InputSlot> slots = inputSlot.getFigure().getInputSlots();
         assert slots.contains(inputSlot);
         return new Point((int) x, (int) (calculateRelativeY(slots.size(), slots.indexOf(inputSlot))));
-    }
+    }*/
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/LineWidget.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/LineWidget.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -24,23 +24,22 @@
 package com.sun.hotspot.igv.view.widgets;
 
 import com.sun.hotspot.igv.graph.Connection;
+import com.sun.hotspot.igv.graph.Figure;
 import com.sun.hotspot.igv.graph.InputSlot;
 import com.sun.hotspot.igv.graph.OutputSlot;
 import com.sun.hotspot.igv.view.DiagramScene;
-import java.awt.BasicStroke;
-import java.awt.Color;
-import java.awt.Graphics2D;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.Stroke;
+import java.awt.*;
 import java.awt.geom.Line2D;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import javax.swing.JPopupMenu;
 import javax.swing.event.PopupMenuEvent;
 import javax.swing.event.PopupMenuListener;
 import org.netbeans.api.visual.action.ActionFactory;
 import org.netbeans.api.visual.action.PopupMenuProvider;
+import org.netbeans.api.visual.action.SelectProvider;
 import org.netbeans.api.visual.animator.SceneAnimator;
 import org.netbeans.api.visual.model.ObjectState;
 import org.netbeans.api.visual.widget.Widget;
@@ -51,7 +50,7 @@
  */
 public class LineWidget extends Widget implements PopupMenuProvider {
 
-    public final int BORDER = 8;
+    public final int BORDER = 5;
     public final int ARROW_SIZE = 6;
     public final int BOLD_ARROW_SIZE = 7;
     public final int HOVER_ARROW_SIZE = 8;
@@ -80,7 +79,7 @@
         this.from = from;
         this.to = to;
         this.predecessor = predecessor;
-        this.successors = new ArrayList<LineWidget>();
+        this.successors = new ArrayList<>();
         if (predecessor != null) {
             predecessor.addSuccessor(this);
         }
@@ -110,6 +109,7 @@
         if (connections.size() > 0) {
             color = connections.get(0).getColor();
         }
+        this.setToolTipText("<HTML>" + generateToolTipText(this.connections) + "</HTML>");
 
         this.setCheckClipping(true);
 
@@ -120,6 +120,38 @@
             this.setBackground(Color.WHITE);
             animator.animateBackgroundColor(this, color);
         }
+
+        this.getActions().addAction(ActionFactory.createSelectAction(new SelectProvider() {
+
+            @Override
+            public boolean isAimingAllowed(Widget arg0, Point arg1, boolean arg2) {
+                return true;
+            }
+
+            @Override
+            public boolean isSelectionAllowed(Widget arg0, Point arg1, boolean arg2) {
+                return true;
+            }
+
+            @Override
+            public void select(Widget arg0, Point arg1, boolean arg2) {
+                Set<Figure> set = new HashSet<>();
+                for (Connection c : LineWidget.this.connections) {
+                    set.add(c.getInputSlot().getFigure());
+                    set.add(c.getOutputSlot().getFigure());
+                }
+                LineWidget.this.scene.setSelectedObjects(set);
+            }
+        }));
+    }
+
+    private String generateToolTipText(List<Connection> conn) {
+        StringBuilder sb = new StringBuilder();
+        for (Connection c : conn) {
+            sb.append(c.getToolTipText());
+            sb.append("<br>");
+        }
+        return sb.toString();
     }
 
     public Point getFrom() {
@@ -141,13 +173,12 @@
 
     @Override
     protected void paintWidget() {
-        if (scene.getRealZoomFactor() < ZOOM_FACTOR) {
+        if (scene.getZoomFactor() < ZOOM_FACTOR) {
             return;
         }
 
         Graphics2D g = getScene().getGraphics();
         g.setPaint(this.getBackground());
-        ObjectState state = this.getState();
         float width = 1.0f;
 
         if (isBold) {
@@ -171,7 +202,7 @@
         g.drawLine(from.x, from.y, to.x, to.y);
 
         boolean sameFrom = false;
-        boolean sameTo = successors.size() == 0;
+        boolean sameTo = successors.isEmpty();
         for (LineWidget w : successors) {
             if (w.getFrom().equals(getTo())) {
                 sameTo = true;
@@ -207,6 +238,20 @@
 
     private void setHighlighted(boolean b) {
         this.highlighted = b;
+        Set<Object> highlightedObjects = new HashSet<>(scene.getHighlightedObjects());
+        Set<Object> highlightedObjectsChange = new HashSet<>();
+        for (Connection c : connections) {
+            highlightedObjectsChange.add(c.getInputSlot().getFigure());
+            highlightedObjectsChange.add(c.getInputSlot());
+            highlightedObjectsChange.add(c.getOutputSlot().getFigure());
+            highlightedObjectsChange.add(c.getOutputSlot());
+        }
+        if(b) {
+            highlightedObjects.addAll(highlightedObjectsChange);
+        } else {
+            highlightedObjects.removeAll(highlightedObjectsChange);
+        }
+        scene.setHighlightedObjects(highlightedObjects);
         this.revalidate(true);
     }
 
@@ -263,6 +308,7 @@
         }
     }
 
+    @Override
     public JPopupMenu getPopupMenu(Widget widget, Point localLocation) {
         JPopupMenu menu = new JPopupMenu();
         menu.add(scene.createGotoAction(outputSlot.getFigure()));
@@ -276,14 +322,17 @@
         final LineWidget w = this;
         menu.addPopupMenuListener(new PopupMenuListener() {
 
+            @Override
             public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
                 w.setRecursivePopupVisible(true);
             }
 
+            @Override
             public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
                 w.setRecursivePopupVisible(false);
             }
 
+            @Override
             public void popupMenuCanceled(PopupMenuEvent e) {
             }
         });
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/MultiConnectionWidget.java	Tue May 05 16:09:30 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,281 +0,0 @@
-/*
- * 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.graph.Connection;
-import com.sun.hotspot.igv.graph.InputSlot;
-import com.sun.hotspot.igv.graph.OutputSlot;
-import com.sun.hotspot.igv.graph.Slot;
-import com.sun.hotspot.igv.view.DiagramScene;
-import java.awt.BasicStroke;
-import java.awt.Color;
-import java.awt.Graphics2D;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.Stroke;
-import java.awt.geom.Line2D;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import javax.swing.JPopupMenu;
-import javax.swing.event.PopupMenuEvent;
-import javax.swing.event.PopupMenuListener;
-import org.netbeans.api.visual.action.PopupMenuProvider;
-import org.netbeans.api.visual.model.ObjectState;
-import org.netbeans.api.visual.widget.Widget;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public class MultiConnectionWidget extends Widget implements PopupMenuProvider {
-
-    public final int BORDER = 4;
-    public final int HOVER_STROKE_WIDTH = 3;
-
-    private static class Route {
-
-        public Point from;
-        public Point to;
-        public SortedSet<InputSlot> inputSlots;
-        public boolean decorateStart;
-        public boolean decorateEnd;
-
-        public Route(Point from, Point to) {
-            assert from != null;
-            assert to != null;
-            this.from = from;
-            this.to = to;
-            this.inputSlots = new TreeSet<InputSlot>();
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-
-            if (obj instanceof Route) {
-                Route r = (Route) obj;
-                return r.from.equals(from) && r.to.equals(to);
-            }
-
-            return super.equals(obj);
-        }
-
-        @Override
-        public int hashCode() {
-            return ((((from.x * 1711) + from.y) * 1711 + to.x) * 1711 + to.y);
-        }
-    }
-    private Rectangle clientArea;
-    private OutputSlot outputSlot;
-    private Map<Route, SortedSet<InputSlot>> routeMap;
-    private List<Route> routeList;
-    private Color color;
-    private DiagramScene diagramScene;
-    private boolean popupVisible;
-
-    /** Creates a new instance of MultiConnectionWidget */
-    public MultiConnectionWidget(OutputSlot outputSlot, DiagramScene scene) {
-        super(scene);
-
-        this.diagramScene = scene;
-        this.outputSlot = outputSlot;
-        this.setCheckClipping(true);
-
-        routeMap = new HashMap<Route, SortedSet<InputSlot>>();
-        routeList = new ArrayList<Route>();
-        color = Color.BLACK;
-
-        for (Connection c : outputSlot.getConnections()) {
-            List<Point> controlPoints = c.getControlPoints();
-            InputSlot inputSlot = (InputSlot) c.getTo();
-            color = c.getColor();
-
-            for (int i = 1; i < controlPoints.size(); i++) {
-                Point prev = controlPoints.get(i - 1);
-                Point cur = controlPoints.get(i);
-
-                if (prev != null && cur != null) {
-                    Route r = new Route(prev, cur);
-                    if (routeMap.containsKey(r)) {
-                        SortedSet<InputSlot> set = routeMap.get(r);
-                        set.add(inputSlot);
-                    } else {
-                        SortedSet<InputSlot> set = new TreeSet<InputSlot>(Slot.slotFigureComparator);
-                        set.add(inputSlot);
-                        routeMap.put(r, set);
-                        routeList.add(r);
-                    }
-                }
-            }
-        }
-
-        if (routeList.size() == 0) {
-            clientArea = new Rectangle();
-        } else {
-            for (Route r : routeList) {
-
-                int x = r.from.x;
-                int y = r.from.y;
-
-                int x2 = r.to.x;
-                int y2 = r.to.y;
-
-                if (x > x2) {
-                    int tmp = x;
-                    x = x2;
-                    x2 = tmp;
-                }
-
-                if (y > y2) {
-                    int tmp = y;
-                    y = y2;
-                    y2 = tmp;
-                }
-
-                int width = x2 - x + 1;
-                int height = y2 - y + 1;
-
-                Rectangle rect = new Rectangle(x, y, width, height);
-                if (clientArea == null) {
-                    clientArea = rect;
-                } else {
-                    clientArea = clientArea.union(rect);
-                }
-            }
-
-            clientArea.grow(BORDER, BORDER);
-        }
-    }
-
-    private void setHoverPosition(Point location) {
-        Route r = getNearest(location);
-    }
-
-    private Route getNearest(Point localLocation) {
-
-        double minDist = Double.MAX_VALUE;
-        Route result = null;
-        for (Route r : routeList) {
-            double dist = Line2D.ptSegDistSq((double) r.from.x, (double) r.from.y, (double) r.to.x, (double) r.to.y, (double) localLocation.x, (double) localLocation.y);
-            if (dist < minDist) {
-                result = r;
-                minDist = dist;
-            }
-        }
-
-        assert result != null;
-
-        return result;
-    }
-
-    @Override
-    public boolean isHitAt(Point localLocation) {
-        if (!super.isHitAt(localLocation)) {
-            return false;
-        }
-
-        for (Route r : routeList) {
-            double dist = Line2D.ptSegDistSq((double) r.from.x, (double) r.from.y, (double) r.to.x, (double) r.to.y, (double) localLocation.x, (double) localLocation.y);
-            if (dist < BORDER * BORDER) {
-                setHoverPosition(localLocation);
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    @Override
-    protected Rectangle calculateClientArea() {
-        return clientArea;
-    }
-
-    @Override
-    protected void paintWidget() {
-        Graphics2D g = getScene().getGraphics();
-        //g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
-        g.setColor(this.color);
-        ObjectState state = this.getState();
-        float width = 1.0f;
-        if (state.isHovered() || this.popupVisible) {
-            width = HOVER_STROKE_WIDTH;
-        }
-
-        Stroke oldStroke = g.getStroke();
-        g.setStroke(new BasicStroke(width));
-        for (Route r : routeList) {
-            g.drawLine(r.from.x, r.from.y, r.to.x, r.to.y);
-        }
-        g.setStroke(oldStroke);
-    }
-
-    @Override
-    protected void notifyStateChanged(ObjectState previousState, ObjectState state) {
-
-        boolean repaint = false;
-
-        if (state.isHovered() != previousState.isHovered()) {
-            repaint = true;
-        }
-
-        repaint();
-    }
-
-    public JPopupMenu getPopupMenu(Widget widget, Point localLocation) {
-        JPopupMenu menu = new JPopupMenu();
-        Route r = getNearest(localLocation);
-        assert r != null;
-        assert routeMap.containsKey(r);
-
-        menu.add(diagramScene.createGotoAction(outputSlot.getFigure()));
-        menu.addSeparator();
-
-        SortedSet<InputSlot> set = this.routeMap.get(r);
-        for (InputSlot s : set) {
-            menu.add(diagramScene.createGotoAction(s.getFigure()));
-        }
-
-        final MultiConnectionWidget w = this;
-        menu.addPopupMenuListener(new PopupMenuListener() {
-
-            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
-                w.popupVisible = true;
-                w.repaint();
-            }
-
-            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
-                w.popupVisible = false;
-                w.repaint();
-            }
-
-            public void popupMenuCanceled(PopupMenuEvent e) {
-            }
-        });
-
-        return menu;
-    }
-}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/OutputSlotWidget.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/OutputSlotWidget.java	Fri May 08 13:25:11 2015 -0400
@@ -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.view.widgets;
 
+import com.sun.hotspot.igv.graph.Figure;
 import com.sun.hotspot.igv.graph.OutputSlot;
 import com.sun.hotspot.igv.view.DiagramScene;
 import java.awt.Point;
@@ -40,22 +41,21 @@
     public OutputSlotWidget(OutputSlot slot, DiagramScene scene, Widget parent, FigureWidget fw) {
         super(slot, scene, parent, fw);
         outputSlot = slot;
-        init();
-        getFigureWidget().getRightWidget().addChild(this);
+        Point p = outputSlot.getRelativePosition();
+        p.y += getSlot().getFigure().getHeight() - Figure.SLOT_START;
+        p.x -= this.calculateClientArea().width / 2;
+        this.setPreferredLocation(p);
     }
 
     public OutputSlot getOutputSlot() {
         return outputSlot;
     }
 
-    protected Point calculateRelativeLocation() {
-        if (getFigureWidget().getBounds() == null) {
-            return new Point(0, 0);
-        }
+    @Override
+    protected int calculateSlotWidth() {
+        List<OutputSlot> slots = getSlot().getFigure().getOutputSlots();
+        assert slots.contains(getSlot());
+        return calculateWidth(slots.size());
 
-        double x = this.getFigureWidget().getBounds().width;
-        List<OutputSlot> slots = outputSlot.getFigure().getOutputSlots();
-        assert slots.contains(outputSlot);
-        return new Point((int) x, (int) (calculateRelativeY(slots.size(), slots.indexOf(outputSlot))));
     }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/SlotWidget.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/SlotWidget.java	Fri May 08 13:25:11 2015 -0400
@@ -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
@@ -26,51 +26,47 @@
 import com.sun.hotspot.igv.graph.Figure;
 import com.sun.hotspot.igv.graph.OutputSlot;
 import com.sun.hotspot.igv.graph.Slot;
-import com.sun.hotspot.igv.view.*;
+import com.sun.hotspot.igv.util.DoubleClickHandler;
+import com.sun.hotspot.igv.view.DiagramScene;
 import java.awt.Color;
 import java.awt.Font;
 import java.awt.Graphics2D;
-import java.awt.Image;
-import java.awt.Point;
 import java.awt.Rectangle;
 import java.awt.geom.Rectangle2D;
+import java.util.HashSet;
+import java.util.Set;
+import org.netbeans.api.visual.action.WidgetAction;
+import org.netbeans.api.visual.model.ObjectState;
 import org.netbeans.api.visual.widget.Widget;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
-public abstract class SlotWidget extends Widget {
+public abstract class SlotWidget extends Widget implements DoubleClickHandler {
 
     private Slot slot;
     private FigureWidget figureWidget;
-    private Image bufferImage;
     private static double TEXT_ZOOM_FACTOR = 0.9;
     private static double ZOOM_FACTOR = 0.6;
-    private DiagramScene scene;
+    private DiagramScene diagramScene;
 
     public SlotWidget(Slot slot, DiagramScene scene, Widget parent, FigureWidget fw) {
         super(scene);
-        this.scene = scene;
+        this.diagramScene = scene;
         this.slot = slot;
         figureWidget = fw;
-        this.setToolTipText("<HTML>" + slot.getName() + "</HTML>");
+        this.setToolTipText("<HTML>" + slot.getToolTipText() + "</HTML>");
         this.setCheckClipping(true);
+        parent.addChild(this);
+
+        //this.setPreferredBounds(this.calculateClientArea());
     }
 
-    public Point getAnchorPosition() {
-        Point p = new Point(figureWidget.getFigure().getPosition());
-        Point p2 = slot.getRelativePosition();
-        p.translate(p2.x, p2.y);
-        return p;
-    }
-
-    protected void init() {
-
-        Point p = calculateRelativeLocation();
-        Rectangle r = calculateClientArea();
-        p = new Point(p.x, p.y - r.height / 2);
-        this.setPreferredLocation(p);
+    @Override
+    protected void notifyStateChanged(ObjectState previousState, ObjectState state) {
+        super.notifyStateChanged(previousState, state);
+        repaint();
     }
 
     public Slot getSlot() {
@@ -84,43 +80,98 @@
     @Override
     protected void paintWidget() {
 
-        if (scene.getRealZoomFactor() < ZOOM_FACTOR) {
+        if (getScene().getZoomFactor() < ZOOM_FACTOR) {
             return;
         }
 
-        if (bufferImage == null) {
-            Graphics2D g = this.getGraphics();
-            g.setColor(Color.DARK_GRAY);
-            int w = this.getBounds().width;
-            int h = this.getBounds().height;
+        Graphics2D g = this.getGraphics();
+        // g.setColor(Color.DARK_GRAY);
+        int w = this.getBounds().width;
+        int h = this.getBounds().height;
+
+        if (getSlot().getSource().getSourceNodes().size() > 0) {
+            final int SMALLER = 0;
+            g.setColor(getSlot().getColor());
+
+            int FONT_OFFSET = 2;
+
+            int s = h - SMALLER;
+            int rectW = s;
+
+            Font font = this.getSlot().getFigure().getDiagram().getSlotFont();
+            if (this.getState().isSelected()) {
+                font = font.deriveFont(Font.BOLD);
+            }
+
+            if (getSlot().getShortName() != null && getSlot().getShortName().length() > 0) {
+                g.setFont(font);
+                Rectangle2D r1 = g.getFontMetrics().getStringBounds(getSlot().getShortName(), g);
+                rectW = (int) r1.getWidth() + FONT_OFFSET * 2;
+            }
+            g.fillRect(w / 2 - rectW / 2, 0, rectW - 1, s - 1);
 
-            if (getSlot().getShortName() != null && getSlot().getShortName().length() > 0 && scene.getRealZoomFactor() >= TEXT_ZOOM_FACTOR) {
-                Font f = new Font("Arial", Font.PLAIN, 8);
-                g.setFont(f.deriveFont(7.5f));
-                Rectangle2D r1 = g.getFontMetrics().getStringBounds(getSlot().getShortName(), g);
-                g.drawString(getSlot().getShortName(), (int) (this.getBounds().width - r1.getWidth()) / 2, (int) (this.getBounds().height + r1.getHeight()) / 2);
+            if (this.getState().isHighlighted()) {
+                g.setColor(Color.BLUE);
             } else {
+                g.setColor(Color.BLACK);
+            }
+            g.drawRect(w / 2 - rectW / 2, 0, rectW - 1, s - 1);
 
+            if (getSlot().getShortName() != null && getSlot().getShortName().length() > 0 && getScene().getZoomFactor() >= TEXT_ZOOM_FACTOR) {
+                Rectangle2D r1 = g.getFontMetrics().getStringBounds(getSlot().getShortName(), g);
+                g.drawString(getSlot().getShortName(), (int) (w - r1.getWidth()) / 2, g.getFontMetrics().getAscent() - 1);//(int) (r1.getHeight()));
+            }
+
+        } else {
+
+            if (this.getSlot().getConnections().isEmpty()) {
+                if (this.getState().isHighlighted()) {
+                    g.setColor(Color.BLUE);
+                } else {
+                    g.setColor(Color.BLACK);
+                }
+                int r = 2;
                 if (slot instanceof OutputSlot) {
-                    g.fillArc(w / 4, -h / 4 - 1, w / 2, h / 2, 180, 180);
+                    g.fillOval(w / 2 - r, Figure.SLOT_WIDTH - Figure.SLOT_START - r, 2 * r, 2 * r);
                 } else {
-                    g.fillArc(w / 4, 3 * h / 4, w / 2, h / 2, 0, 180);
+                    g.fillOval(w / 2 - r, Figure.SLOT_START - r, 2 * r, 2 * r);
                 }
+            } else {
+                // Do not paint a slot with connections.
             }
         }
     }
 
     @Override
     protected Rectangle calculateClientArea() {
-        return new Rectangle(0, 0, Figure.SLOT_WIDTH, Figure.SLOT_WIDTH);
+        return new Rectangle(0, 0, slot.getWidth(), Figure.SLOT_WIDTH);
+    }
+
+    protected abstract int calculateSlotWidth();
+
+    protected int calculateWidth(int count) {
+        return getFigureWidget().getFigure().getWidth() / count;
     }
 
-    protected abstract Point calculateRelativeLocation();
+    @Override
+    public void handleDoubleClick(Widget w, WidgetAction.WidgetMouseEvent e) {
+        Set<Integer> hiddenNodes = new HashSet<>(diagramScene.getModel().getHiddenNodes());
+        if (diagramScene.isAllVisible()) {
+            hiddenNodes = new HashSet<>(diagramScene.getModel().getGraphToView().getGroup().getAllNodes());
+        }
 
-    protected double calculateRelativeY(int size, int index) {
-        assert index >= 0 && index < size;
-        assert size > 0;
-        double height = getFigureWidget().getBounds().getHeight();
-        return height * (index + 1) / (size + 1);
+        boolean progress = false;
+        for (Figure f : diagramScene.getModel().getDiagramToView().getFigures()) {
+            for (Slot s : f.getSlots()) {
+                if (DiagramScene.doesIntersect(s.getSource().getSourceNodesAsSet(), slot.getSource().getSourceNodesAsSet())) {
+                    progress = true;
+                    hiddenNodes.removeAll(f.getSource().getSourceNodesAsSet());
+                }
+            }
+        }
+
+        if (progress) {
+            this.diagramScene.getModel().showNot(hiddenNodes);
+        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/branding.jnlp	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE jnlp PUBLIC "-//Sun Microsystems, Inc//DTD JNLP Descriptor 6.0//EN" "http://java.sun.com/dtd/JNLP-6.0.dtd">
+<jnlp spec="1.0+" codebase="$$codebase">
+  <information>
+      <title>${app.title}</title>
+      <vendor>${app.title} vendor</vendor>
+      <description>${app.name} application</description>
+      <icon href="${app.icon}"/>
+  </information>
+  ${jnlp.permissions}
+  <resources>
+    ${jnlp.branding.jars}
+  </resources>
+  <component-desc/>
+</jnlp>  
--- a/hotspot/src/share/tools/IdealGraphVisualizer/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,7 +1,7 @@
 currentVersion=IdealGraphVisualizer {0}
 LBL_splash_window_title=Starting IdealGraphVisualizer
 SPLASH_WIDTH=475
-SplashProgressBarBounds=0,268,473,6
+SplashProgressBarBounds=0,273,475,6
 SplashProgressBarColor=0xFFFFFF
-SplashRunningTextBounds=269,253,205,12
+SplashRunningTextBounds=10,283,460,12
 SplashRunningTextColor=0xFFFFFF
Binary file hotspot/src/share/tools/IdealGraphVisualizer/branding/core/core.jar/org/netbeans/core/startup/frame.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/branding/core/core.jar/org/netbeans/core/startup/frame32.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/branding/core/core.jar/org/netbeans/core/startup/frame48.gif has changed
Binary file hotspot/src/share/tools/IdealGraphVisualizer/branding/core/core.jar/org/netbeans/core/startup/splash.gif has changed
--- a/hotspot/src/share/tools/IdealGraphVisualizer/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,2 +1,2 @@
-CTL_MainWindow_Title=IdealGraphVisualizer {0}
-CTL_MainWindow_Title_No_Project=IdealGraphVisualizer {0}
+CTL_MainWindow_Title=IdealGraphVisualizer
+CTL_MainWindow_Title_No_Project=IdealGraphVisualizer
--- a/hotspot/src/share/tools/IdealGraphVisualizer/build.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/build.xml	Fri May 08 13:25:11 2015 -0400
@@ -5,4 +5,12 @@
 <project name="IdealGraphVisualizer" basedir=".">
     <description>Builds the module suite IdealGraphVisualizer.</description>
     <import file="nbproject/build-impl.xml"/>
+    
+    <target name="build-launchers" depends="suite.build-launchers">
+        <!-- Drop memory presets (-Xms, -Xmx) from default_options of packaged builds and let the executing VM choose reasonable defaults -->
+        <replaceregexp file="${build.launcher.dir}/etc/${app.name}.conf" byline="true" match="^default_options=.*" replace='default_options="--branding idealgraphvisualizer"' />
+    </target>
+    
+    <!-- Local (environment-specific) extensions/modifications to the build -->
+    <import file="build-local.xml" optional="true" />
 </project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/igv.sh	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,23 @@
+#!/bin/sh
+# Copyright (c) 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.
+ant run >.igv.log 2>&1
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/master.jnlp	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE jnlp PUBLIC "-//Sun Microsystems, Inc//DTD JNLP Descriptor 6.0//EN" "http://java.sun.com/dtd/JNLP-6.0.dtd">
+<jnlp spec="1.0+" codebase="$$codebase" href="master.jnlp">
+  <information>
+      <title>Ideal Graph Visualizer</title>
+      <vendor>Ideal Graph Visualizer Team</vendor>
+      <description>A graph visualization tool designed for analyzing evolving compiler graphs. It was originally designed for the ideal graph in the HotSpot server compiler, but can be used to visualize arbitrary graph data structures.</description>
+      <icon href="${app.icon}"/>
+  </information>
+  <security><all-permissions/></security>
+  <resources>
+    <!-- The following property is needed when running with unsigned jars: -->
+    <property name="netbeans.jnlp.fixPolicy" value="${netbeans.jnlp.fixPolicy}"/>
+    <extension name='branding' href='branding.jnlp' />
+<!-- The following line will be replaced with an automatically generated list of resources: -->
+<!--${jnlp.resources}-->
+  </resources>
+  <resources os="Mac OS X">
+      <property name="netbeans.user" value="${user.home}/Library/Application Support/${app.name}"/>
+  </resources>
+  <application-desc>
+    <argument>--branding</argument>
+    <argument>${branding.token}</argument>
+  </application-desc>
+</jnlp>  
--- a/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/build-impl.xml	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/build-impl.xml	Fri May 08 13:25:11 2015 -0400
@@ -4,6 +4,13 @@
 ***         EDIT ../build.xml INSTEAD         ***
 -->
 <project name="IdealGraphVisualizer-impl" basedir=".." xmlns:sproject="http://www.netbeans.org/ns/nb-module-suite-project/1">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
     <property file="nbproject/private/platform-private.properties"/>
     <property file="nbproject/platform.properties"/>
     <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-suite-project/1">
@@ -13,13 +20,29 @@
             <property name="@{name}" value="${@{value}}"/>
         </sequential>
     </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-suite-project/1">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" value="@{value}"/>
+        </sequential>
+    </macrodef>
     <property file="${user.properties.file}"/>
     <sproject:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir"/>
-    <sproject:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir"/>
-    <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
+    <sproject:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir"/>
+    <sproject:evalprops property="cluster.path.evaluated" value="${cluster.path}"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
         <condition>
             <not>
-                <available file="${harness.dir}" type="dir"/>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
+            </not>
+        </condition>
+    </fail>
+    <ant antfile="nbproject/platform.xml"/>
+    <fail message="Cannot find NetBeans build harness. ${line.separator}Check that nbplatform.${nbplatform.active}.netbeans.dest.dir and nbplatform.${nbplatform.active}.harness.dir are defined. ${line.separator}On a developer machine these are normally defined in ${user.properties.file}=${netbeans.user}/build.properties ${line.separator}but for automated builds you should pass these properties to Ant explicitly. ${line.separator}You may instead download the harness and platform: -Dbootstrap.url=.../tasks.jar -Dautoupdate.catalog.url=.../updates.xml">
+        <condition>
+            <not>
+                <available file="${harness.dir}/suite.xml"/>
             </not>
         </condition>
     </fail>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/genfiles.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/genfiles.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,8 +1,11 @@
-build.xml.data.CRC32=72833581
-build.xml.script.CRC32=e9c757c5
-build.xml.stylesheet.CRC32=531c622b
+build.xml.data.CRC32=3c2c6126
+build.xml.script.CRC32=48934e60
+build.xml.stylesheet.CRC32=eaf9f76a@1.45.1
 # 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=72833581
-nbproject/build-impl.xml.script.CRC32=1b6f3648
-nbproject/build-impl.xml.stylesheet.CRC32=196c7090
+nbproject/build-impl.xml.data.CRC32=3c2c6126
+nbproject/build-impl.xml.script.CRC32=b26e57e5
+nbproject/build-impl.xml.stylesheet.CRC32=0f381476@2.62.1
+nbproject/platform.xml.data.CRC32=3c2c6126
+nbproject/platform.xml.script.CRC32=6dcbd131
+nbproject/platform.xml.stylesheet.CRC32=4e1f53d4@2.62.1
--- a/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/platform.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/platform.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,29 +1,18 @@
-# Deprecated since 5.0u1; for compatibility with 5.0:
-disabled.clusters=\
-    apisupport1,\
-    gsf1,\
-    harness,\
-    ide9,\
-    java2,\
-    nb6.1,\
-    profiler3
-disabled.modules=\
-    org.netbeans.core.execution,\
-    org.netbeans.core.multiview,\
-    org.netbeans.core.output2,\
-    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=\
-    platform8
-nbjdk.active=default
+branding.token=idealgraphvisualizer
+cluster.path=\
+    ${nbplatform.active.dir}/ide:\
+    ${nbplatform.active.dir}/platform
+disabled.modules=
+nbplatform.active.dir=${suite.dir}/nbplatform
+nbplatform.default.netbeans.dest.dir=${suite.dir}/nbplatform
+nbplatform.default.harness.dir=${nbplatform.default.netbeans.dest.dir}/harness
+bootstrap.url=http://deadlock.netbeans.org/hudson/job/nbms-and-javadoc/lastSuccessfulBuild/artifact/nbbuild/netbeans/harness/tasks.jar
+autoupdate.catalog.url=http://updates.netbeans.org/netbeans/updates/7.4/uc/final/distribution/catalog.xml.gz
+suite.dir=${basedir}
 nbplatform.active=default
+## Not disabled because of NetBeans bug 206347:
+## Applications not using OSGi don't start on NbP 7.1
+#   org.netbeans.core.netigso,\
+#   org.netbeans.libs.felix,\
+#   org.netbeans.libs.osgi,\
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/platform.xml	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="platform" default="download" basedir="..">
+    <condition property="download.required">
+        <and>
+            <not>
+                <available file="${harness.dir}/suite.xml"/>
+            </not>
+            <isset property="bootstrap.url"/>
+            <isset property="autoupdate.catalog.url"/>
+        </and>
+    </condition>
+    <target name="download" if="download.required">
+        <mkdir dir="${harness.dir}"/>
+        <pathconvert pathsep="|" property="download.clusters">
+            <mapper type="flatten"/>
+            <path path="${cluster.path}"/>
+        </pathconvert>
+        <property name="disabled.modules" value=""/>
+        <pathconvert property="module.includes" pathsep="">
+            <mapper type="glob" from="${basedir}${file.separator}*" to="(?!^\Q*\E$)"/>
+            <path>
+                <filelist files="${disabled.modules}" dir="."/>
+            </path>
+        </pathconvert>
+        <echo message="Downloading clusters ${download.clusters}"/>
+        <property name="tasks.jar" location="${java.io.tmpdir}/tasks.jar"/>
+        <get src="${bootstrap.url}" dest="${tasks.jar}" usetimestamp="true" verbose="true"/>
+        <taskdef name="autoupdate" classname="org.netbeans.nbbuild.AutoUpdate" classpath="${tasks.jar}"/>
+        <autoupdate installdir="${nbplatform.active.dir}" updatecenter="${autoupdate.catalog.url}">
+            <modules includes="${module.includes}.*" clusters="${download.clusters}"/>
+            <modules includes="org[.]netbeans[.]modules[.]apisupport[.]harness" clusters="harness"/>
+        </autoupdate>
+    </target>
+</project>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/project.properties	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/project.properties	Fri May 08 13:25:11 2015 -0400
@@ -1,7 +1,13 @@
 app.icon=branding/core/core.jar/org/netbeans/core/startup/frame48.gif
-app.name=idealgraphvisualizer
+app.name=${branding.token}
 app.title=IdealGraphVisualizer
-branding.token=${app.name}
+auxiliary.org-netbeans-modules-apisupport-installer.license-type=no
+auxiliary.org-netbeans-modules-apisupport-installer.os-linux=false
+auxiliary.org-netbeans-modules-apisupport-installer.os-macosx=true
+auxiliary.org-netbeans-modules-apisupport-installer.os-solaris=false
+auxiliary.org-netbeans-modules-apisupport-installer.os-windows=false
+auxiliary.org-netbeans-modules-apisupport-installer.pack200-enabled=false
+auxiliary.org-netbeans-spi-editor-hints-projects.perProjectHintSettingsFile=nbproject/cfg_hints.xml
 modules=\
     ${project.com.sun.hotspot.igv.graph}:\
     ${project.com.sun.hotspot.igv.coordinator}:\
@@ -18,7 +24,9 @@
     ${project.com.sun.hotspot.igv.svg}:\
     ${project.com.sun.hotspot.connection}:\
     ${project.com.sun.hotspot.igv.servercompilerscheduler}:\
-    ${project.com.sun.hotspot.igv.filterwindow}
+    ${project.com.sun.hotspot.igv.filterwindow}:\
+    ${project.com.sun.hotspot.igv.selectioncoordinator}:\
+    ${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
@@ -27,13 +35,18 @@
 project.com.sun.hotspot.igv.difference=Difference
 project.com.sun.hotspot.igv.filter=Filter
 project.com.sun.hotspot.igv.filterwindow=FilterWindow
+project.com.sun.hotspot.igv.graal=Graal
 project.com.sun.hotspot.igv.graph=Graph
 project.com.sun.hotspot.igv.hierarchicallayout=HierarchicalLayout
 project.com.sun.hotspot.igv.layout=Layout
+project.com.sun.hotspot.igv.selectioncoordinator=SelectionCoordinator
 project.com.sun.hotspot.igv.servercompilerscheduler=ServerCompiler
 project.com.sun.hotspot.igv.settings=Settings
 project.com.sun.hotspot.igv.svg=BatikSVGProxy
 project.com.sun.hotspot.igv.view=View
 project.com.sun.hotspot.igv.util=Util
-run.args = -J-server -J-Xms64m -J-Xmx1g -J-da
-run.args.extra = -J-server -J-Xms64m -J-Xmx1g -J-da
+
+# Disable assertions for RequestProcessor to prevent annoying messages in case
+# of multiple SceneAnimator update tasks in the default RequestProcessor.
+run.args.extra = -J-server -J-da:org.openide.util.RequestProcessor -J-Xms2g -J-Xmx8g -J-Djava.lang.Integer.IntegerCache.high=20000
+debug.args.extra = -J-server -J-da:org.openide.util.RequestProcessor
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp	Fri May 08 13:25:11 2015 -0400
@@ -1018,7 +1018,7 @@
           // NOTE we use pc() not original_pc() because we already know they are
           // identical otherwise we'd have never entered this block of code
 
-          OopMap* map = caller_code->oop_map_for_return_address(caller_frame.pc());
+          const ImmutableOopMap* map = caller_code->oop_map_for_return_address(caller_frame.pc());
           assert(map != NULL, "null check");
           map->print();
           tty->cr();
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Fri May 08 13:25:11 2015 -0400
@@ -591,6 +591,9 @@
   template(classLoader_name,                           "classLoader")                                             \
   template(componentType_name,                         "componentType")                                           \
                                                                                                                   \
+  /* forEachRemaining support */                                                                                  \
+  template(java_util_stream_StreamsRangeIntSpliterator,          "java/util/stream/Streams$RangeIntSpliterator")  \
+                                                                                                                  \
   /* trace signatures */                                                                                          \
   TRACE_TEMPLATES(template)                                                                                       \
                                                                                                                   \
@@ -1121,6 +1124,11 @@
   do_intrinsic(_Double_valueOf,           java_lang_Double,       valueOf_name, Double_valueOf_signature, F_S)          \
    do_name(     Double_valueOf_signature,                        "(D)Ljava/lang/Double;")                               \
                                                                                                                         \
+  /* forEachRemaining */                                                                             \
+  do_intrinsic(_forEachRemaining, java_util_stream_StreamsRangeIntSpliterator, forEachRemaining_name, forEachRemaining_signature, F_R) \
+   do_name(     forEachRemaining_name,    "forEachRemaining")                                                           \
+   do_name(     forEachRemaining_signature,                      "(Ljava/util/function/IntConsumer;)V")                 \
+
     /*end*/
 
 
--- a/hotspot/src/share/vm/code/codeBlob.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/code/codeBlob.cpp	Fri May 08 13:25:11 2015 -0400
@@ -129,9 +129,7 @@
   // Danger Will Robinson! This method allocates a big
   // chunk of memory, its your job to free it.
   if (p != NULL) {
-    // We need to allocate a chunk big enough to hold the OopMapSet and all of its OopMaps
-    _oop_maps = (OopMapSet* )NEW_C_HEAP_ARRAY(unsigned char, p->heap_size(), mtCode);
-    p->copy_to((address)_oop_maps);
+    _oop_maps = ImmutableOopMapSet::build_from(p);
   } else {
     _oop_maps = NULL;
   }
@@ -175,7 +173,7 @@
 }
 
 
-OopMap* CodeBlob::oop_map_for_return_address(address return_address) {
+const ImmutableOopMap* CodeBlob::oop_map_for_return_address(address return_address) {
   assert(oop_maps() != NULL, "nope");
   return oop_maps()->find_map_at_offset((intptr_t) return_address - (intptr_t) code_begin());
 }
--- a/hotspot/src/share/vm/code/codeBlob.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/code/codeBlob.hpp	Fri May 08 13:25:11 2015 -0400
@@ -77,7 +77,7 @@
                                                  // which we don't detect.
   int        _data_offset;                       // offset to where data region begins
   int        _frame_size;                        // size of stack frame
-  OopMapSet* _oop_maps;                          // OopMap for this CodeBlob
+  ImmutableOopMapSet* _oop_maps;                 // OopMap for this CodeBlob
   CodeStrings _strings;
 
  public:
@@ -171,9 +171,9 @@
   virtual bool is_alive() const                  = 0;
 
   // OopMap for frame
-  OopMapSet* oop_maps() const                    { return _oop_maps; }
+  ImmutableOopMapSet* oop_maps() const           { return _oop_maps; }
   void set_oop_maps(OopMapSet* p);
-  OopMap* oop_map_for_return_address(address return_address);
+  const ImmutableOopMap* oop_map_for_return_address(address return_address);
   virtual void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f)  { ShouldNotReachHere(); }
 
   // Frame support
--- a/hotspot/src/share/vm/code/codeCache.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/code/codeCache.cpp	Fri May 08 13:25:11 2015 -0400
@@ -1372,10 +1372,10 @@
         if (cb->is_alive()) {
           number_of_blobs++;
           code_size += cb->code_size();
-          OopMapSet* set = cb->oop_maps();
+          ImmutableOopMapSet* set = cb->oop_maps();
           if (set != NULL) {
-            number_of_oop_maps += set->size();
-            map_size           += set->heap_size();
+            number_of_oop_maps += set->count();
+            map_size           += set->size();
           }
         }
       }
--- a/hotspot/src/share/vm/code/nmethod.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/code/nmethod.cpp	Fri May 08 13:25:11 2015 -0400
@@ -2987,11 +2987,12 @@
   // We use the odd half-closed interval so that oop maps and scope descs
   // which are tied to the byte after a call are printed with the call itself.
   address base = code_begin();
-  OopMapSet* oms = oop_maps();
+  ImmutableOopMapSet* oms = oop_maps();
   if (oms != NULL) {
     for (int i = 0, imax = oms->size(); i < imax; i++) {
-      OopMap* om = oms->at(i);
-      address pc = base + om->offset();
+      const ImmutableOopMapPair* pair = oms->pair_at(i);
+      const ImmutableOopMap* om = pair->get_from(oms);
+      address pc = base + pair->pc_offset();
       if (pc > begin) {
         if (pc <= end) {
           st->move_to(column);
--- a/hotspot/src/share/vm/compiler/oopMap.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/compiler/oopMap.cpp	Fri May 08 13:25:11 2015 -0400
@@ -42,27 +42,18 @@
 
 // OopMapStream
 
-OopMapStream::OopMapStream(OopMap* oop_map) {
-  if(oop_map->omv_data() == NULL) {
-    _stream = new CompressedReadStream(oop_map->write_stream()->buffer());
-  } else {
-    _stream = new CompressedReadStream(oop_map->omv_data());
-  }
-  _mask = OopMapValue::type_mask_in_place;
+OopMapStream::OopMapStream(OopMap* oop_map, int oop_types_mask) {
+  _stream = new CompressedReadStream(oop_map->write_stream()->buffer());
+  _mask = oop_types_mask;
   _size = oop_map->omv_count();
   _position = 0;
   _valid_omv = false;
 }
 
-
-OopMapStream::OopMapStream(OopMap* oop_map, int oop_types_mask) {
-  if(oop_map->omv_data() == NULL) {
-    _stream = new CompressedReadStream(oop_map->write_stream()->buffer());
-  } else {
-    _stream = new CompressedReadStream(oop_map->omv_data());
-  }
+OopMapStream::OopMapStream(const ImmutableOopMap* oop_map, int oop_types_mask) {
+  _stream = new CompressedReadStream(oop_map->data_addr());
   _mask = oop_types_mask;
-  _size = oop_map->omv_count();
+  _size = oop_map->count();
   _position = 0;
   _valid_omv = false;
 }
@@ -87,7 +78,6 @@
 OopMap::OopMap(int frame_size, int arg_count) {
   // OopMaps are usually quite so small, so pick a small initial size
   set_write_stream(new CompressedWriteStream(32));
-  set_omv_data(NULL);
   set_omv_count(0);
 
 #ifdef ASSERT
@@ -102,7 +92,6 @@
   // This constructor does a deep copy
   // of the source OopMap.
   set_write_stream(new CompressedWriteStream(source->omv_count() * 2));
-  set_omv_data(NULL);
   set_omv_count(0);
   set_offset(source->offset());
 
@@ -125,25 +114,14 @@
   return new OopMap(_deep_copy_token, this);
 }
 
-
-void OopMap::copy_to(address addr) {
-  memcpy(addr,this,sizeof(OopMap));
-  memcpy(addr + sizeof(OopMap),write_stream()->buffer(),write_stream()->position());
-  OopMap* new_oop = (OopMap*)addr;
-  new_oop->set_omv_data_size(write_stream()->position());
-  new_oop->set_omv_data((unsigned char *)(addr + sizeof(OopMap)));
-  new_oop->set_write_stream(NULL);
+void OopMap::copy_data_to(address addr) const {
+  memcpy(addr, write_stream()->buffer(), write_stream()->position());
 }
 
-
 int OopMap::heap_size() const {
   int size = sizeof(OopMap);
   int align = sizeof(void *) - 1;
-  if(write_stream() != NULL) {
-    size += write_stream()->position();
-  } else {
-    size += omv_data_size();
-  }
+  size += write_stream()->position();
   // Align to a reasonable ending point
   size = ((size+align) & ~align);
   return size;
@@ -222,30 +200,6 @@
 }
 
 
-void OopMapSet::copy_to(address addr) {
-  address temp = addr;
-  int align = sizeof(void *) - 1;
-  // Copy this
-  memcpy(addr,this,sizeof(OopMapSet));
-  temp += sizeof(OopMapSet);
-  temp = (address)((intptr_t)(temp + align) & ~align);
-  // Do the needed fixups to the new OopMapSet
-  OopMapSet* new_set = (OopMapSet*)addr;
-  new_set->set_om_data((OopMap**)temp);
-  // Allow enough space for the OopMap pointers
-  temp += (om_count() * sizeof(OopMap*));
-
-  for(int i=0; i < om_count(); i++) {
-    OopMap* map = at(i);
-    map->copy_to((address)temp);
-    new_set->set(i,(OopMap*)temp);
-    temp += map->heap_size();
-  }
-  // This "locks" the OopMapSet
-  new_set->set_om_size(-1);
-}
-
-
 void OopMapSet::add_gc_map(int pc_offset, OopMap *map ) {
   assert(om_size() != -1,"Cannot grow a fixed OopMapSet");
 
@@ -334,8 +288,8 @@
   // Print oopmap and regmap
   tty->print_cr("------ ");
   CodeBlob* cb = fr->cb();
-  OopMapSet* maps = cb->oop_maps();
-  OopMap* map = cb->oop_map_for_return_address(fr->pc());
+  ImmutableOopMapSet* maps = cb->oop_maps();
+  const ImmutableOopMap* map = cb->oop_map_for_return_address(fr->pc());
   map->print();
   if( cb->is_nmethod() ) {
     nmethod* nm = (nmethod*)cb;
@@ -371,8 +325,8 @@
 
   NOT_PRODUCT(if (TraceCodeBlobStacks) trace_codeblob_maps(fr, reg_map);)
 
-  OopMapSet* maps = cb->oop_maps();
-  OopMap* map = cb->oop_map_for_return_address(fr->pc());
+  ImmutableOopMapSet* maps = cb->oop_maps();
+  const ImmutableOopMap* map = cb->oop_map_for_return_address(fr->pc());
   assert(map != NULL, "no ptr map found");
 
   // handle derived pointers first (otherwise base pointer may be
@@ -483,7 +437,7 @@
   // (we do not do update in place, since info could be overwritten)
 
   address pc = fr->pc();
-  OopMap* map  = cb->oop_map_for_return_address(pc);
+  const ImmutableOopMap* map  = cb->oop_map_for_return_address(pc);
   assert(map != NULL, "no ptr map found");
   DEBUG_ONLY(int nof_callee = 0;)
 
@@ -508,7 +462,7 @@
 
 #ifndef PRODUCT
 
-bool OopMap::has_derived_pointer() const {
+bool ImmutableOopMap::has_derived_pointer() const {
 #ifndef TIERED
   COMPILER1_PRESENT(return false);
 #endif // !TIERED
@@ -550,7 +504,6 @@
   }
 }
 
-
 void OopMapValue::print_on(outputStream* st) const {
   reg()->print_on(st);
   st->print("=");
@@ -558,6 +511,15 @@
   st->print(" ");
 }
 
+void ImmutableOopMap::print_on(outputStream* st) const {
+  OopMapValue omv;
+  st->print("ImmutableOopMap{");
+  for(OopMapStream oms(this); !oms.is_done(); oms.next()) {
+    omv = oms.current();
+    omv.print_on(st);
+  }
+  st->print("}");
+}
 
 void OopMap::print_on(outputStream* st) const {
   OopMapValue omv;
@@ -569,6 +531,20 @@
   st->print("off=%d}", (int) offset());
 }
 
+void ImmutableOopMapSet::print_on(outputStream* st) const {
+  const ImmutableOopMap* last = NULL;
+  for (int i = 0; i < _count; ++i) {
+    const ImmutableOopMapPair* pair = pair_at(i);
+    const ImmutableOopMap* map = pair->get_from(this);
+    if (map != last) {
+      st->cr();
+      map->print_on(st);
+      st->print("pc offsets: ");
+    }
+    last = map;
+    st->print("%d ", pair->pc_offset());
+  }
+}
 
 void OopMapSet::print_on(outputStream* st) const {
   int i, len = om_count();
@@ -583,6 +559,217 @@
   }
 }
 
+bool OopMap::equals(const OopMap* other) const {
+  if (other->_omv_count != _omv_count) {
+    return false;
+  }
+  if (other->write_stream()->position() != write_stream()->position()) {
+    return false;
+  }
+  if (memcmp(other->write_stream()->buffer(), write_stream()->buffer(), write_stream()->position()) != 0) {
+    return false;
+  }
+  return true;
+}
+
+const ImmutableOopMap* ImmutableOopMapSet::find_map_at_offset(int pc_offset) const {
+  ImmutableOopMapPair* pairs = get_pairs();
+  ImmutableOopMapPair* last = NULL;
+
+  for (int i = 0; i < _count; ++i) {
+    if (pairs[i].pc_offset() >= pc_offset) {
+      last = &pairs[i];
+      break;
+    }
+  }
+
+  assert(last->pc_offset() == pc_offset, "oopmap not found");
+  return last->get_from(this);
+}
+
+const ImmutableOopMap* ImmutableOopMapPair::get_from(const ImmutableOopMapSet* set) const {
+  return set->oopmap_at_offset(_oopmap_offset);
+}
+
+ImmutableOopMap::ImmutableOopMap(const OopMap* oopmap) : _count(oopmap->count()) {
+  address addr = data_addr();
+  oopmap->copy_data_to(addr);
+}
+
+class ImmutableOopMapBuilder {
+private:
+  class Mapping;
+
+private:
+  const OopMapSet* _set;
+  const OopMap* _empty;
+  const OopMap* _last;
+  int _empty_offset;
+  int _last_offset;
+  int _offset;
+  Mapping* _mapping;
+  ImmutableOopMapSet* _new_set;
+
+  /* Used for bookkeeping when building ImmutableOopMaps */
+  class Mapping : public ResourceObj {
+  public:
+    enum kind_t { OOPMAP_UNKNOWN = 0, OOPMAP_NEW = 1, OOPMAP_EMPTY = 2, OOPMAP_DUPLICATE = 3 };
+
+    kind_t _kind;
+    int _offset;
+    int _size;
+    const OopMap* _map;
+    const OopMap* _other;
+
+    Mapping() : _kind(OOPMAP_UNKNOWN), _offset(-1), _size(-1), _map(NULL) {}
+
+    void set(kind_t kind, int offset, int size, const OopMap* map = 0, const OopMap* other = 0) {
+      _kind = kind;
+      _offset = offset;
+      _size = size;
+      _map = map;
+      _other = other;
+    }
+  };
+
+public:
+  ImmutableOopMapBuilder(const OopMapSet* set) : _set(set), _new_set(NULL), _empty(NULL), _last(NULL), _empty_offset(-1), _last_offset(-1), _offset(0) {
+    _mapping = NEW_RESOURCE_ARRAY(Mapping, _set->size());
+  }
+
+  int heap_size();
+  ImmutableOopMapSet* build();
+private:
+  bool is_empty(const OopMap* map) const {
+    return map->count() == 0;
+  }
+
+  bool is_last_duplicate(const OopMap* map) {
+    if (_last != NULL && _last->count() > 0 && _last->equals(map)) {
+      return true;
+    }
+    return false;
+  }
+
+#ifdef ASSERT
+  void verify(address buffer, int size);
+#endif
+
+  bool has_empty() const {
+    return _empty_offset != -1;
+  }
+
+  int size_for(const OopMap* map) const;
+  void fill_pair(ImmutableOopMapPair* pair, const OopMap* map, int offset);
+  int fill_map(ImmutableOopMapPair* pair, const OopMap* map, int offset);
+  void fill(ImmutableOopMapSet* set, int size);
+};
+
+int ImmutableOopMapBuilder::size_for(const OopMap* map) const {
+  return align_size_up(sizeof(ImmutableOopMap) + map->data_size(), 8);
+}
+
+int ImmutableOopMapBuilder::heap_size() {
+  int base = sizeof(ImmutableOopMapSet);
+  base = align_size_up(base, 8);
+
+  // all of ours pc / offset pairs
+  int pairs = _set->size() * sizeof(ImmutableOopMapPair);
+  pairs = align_size_up(pairs, 8);
+
+  for (int i = 0; i < _set->size(); ++i) {
+    int size = 0;
+    OopMap* map = _set->at(i);
+
+    if (is_empty(map)) {
+      /* only keep a single empty map in the set */
+      if (has_empty()) {
+        _mapping[i].set(Mapping::OOPMAP_EMPTY, _empty_offset, 0, map, _empty);
+      } else {
+        _empty_offset = _offset;
+        _empty = map;
+        size = size_for(map);
+        _mapping[i].set(Mapping::OOPMAP_NEW, _offset, size, map);
+      }
+    } else if (is_last_duplicate(map)) {
+      /* if this entry is identical to the previous one, just point it there */
+      _mapping[i].set(Mapping::OOPMAP_DUPLICATE, _last_offset, 0, map, _last);
+    } else {
+      /* not empty, not an identical copy of the previous entry */
+      size = size_for(map);
+      _mapping[i].set(Mapping::OOPMAP_NEW, _offset, size, map);
+      _last_offset = _offset;
+      _last = map;
+    }
+
+    assert(_mapping[i]._map == map, "check");
+    _offset += size;
+  }
+
+  int total = base + pairs + _offset;
+  DEBUG_ONLY(total += 8);
+  return total;
+}
+
+void ImmutableOopMapBuilder::fill_pair(ImmutableOopMapPair* pair, const OopMap* map, int offset) {
+  new ((address) pair) ImmutableOopMapPair(map->offset(), offset);
+}
+
+int ImmutableOopMapBuilder::fill_map(ImmutableOopMapPair* pair, const OopMap* map, int offset) {
+  fill_pair(pair, map, offset);
+  address addr = (address) pair->get_from(_new_set); // location of the ImmutableOopMap
+
+  new (addr) ImmutableOopMap(map);
+  return align_size_up(sizeof(ImmutableOopMap) + map->data_size(), 8);
+}
+
+void ImmutableOopMapBuilder::fill(ImmutableOopMapSet* set, int sz) {
+  ImmutableOopMapPair* pairs = set->get_pairs();
+
+  for (int i = 0; i < set->count(); ++i) {
+    const OopMap* map = _mapping[i]._map;
+    ImmutableOopMapPair* pair = NULL;
+    int size = 0;
+
+    if (_mapping[i]._kind == Mapping::OOPMAP_NEW) {
+      size = fill_map(&pairs[i], map, _mapping[i]._offset);
+    } else if (_mapping[i]._kind == Mapping::OOPMAP_DUPLICATE || _mapping[i]._kind == Mapping::OOPMAP_EMPTY) {
+      fill_pair(&pairs[i], map, _mapping[i]._offset);
+    }
+
+    const ImmutableOopMap* nv = set->find_map_at_offset(map->offset());
+    assert(memcmp(map->data(), nv->data_addr(), map->data_size()) == 0, "check identity");
+  }
+}
+
+#ifdef ASSERT
+void ImmutableOopMapBuilder::verify(address buffer, int size) {
+  for (int i = 0; i < 8; ++i) {
+    assert(buffer[size - 8 + i] == (unsigned char) 0xff, "overwritten memory check");
+  }
+}
+#endif
+
+ImmutableOopMapSet* ImmutableOopMapBuilder::build() {
+  int required = heap_size();
+
+  // We need to allocate a chunk big enough to hold the ImmutableOopMapSet and all of its ImmutableOopMaps
+  address buffer = (address) NEW_C_HEAP_ARRAY(unsigned char, required, mtCode);
+  DEBUG_ONLY(memset(&buffer[required-8], 0xff, 8));
+
+  _new_set = new (buffer) ImmutableOopMapSet(_set, required);
+  fill(_new_set, required);
+
+  DEBUG_ONLY(verify(buffer, required));
+
+  return _new_set;
+}
+
+ImmutableOopMapSet* ImmutableOopMapSet::build_from(const OopMapSet* oopmap_set) {
+  ResourceMark mark;
+  ImmutableOopMapBuilder builder(oopmap_set);
+  return builder.build();
+}
 
 
 //------------------------------DerivedPointerTable---------------------------
--- a/hotspot/src/share/vm/compiler/oopMap.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/compiler/oopMap.hpp	Fri May 08 13:25:11 2015 -0400
@@ -143,19 +143,13 @@
   friend class OopMapStream;
   friend class VMStructs;
  private:
-  int  _pc_offset;
-  int  _omv_count;
-  int  _omv_data_size;
-  unsigned char* _omv_data;
+  int  _pc_offset; // offset in the code that this OopMap corresponds to
+  int  _omv_count; // number of OopMapValues in the stream
   CompressedWriteStream* _write_stream;
 
   debug_only( OopMapValue::oop_types* _locs_used; int _locs_length;)
 
   // Accessors
-  unsigned char* omv_data() const             { return _omv_data; }
-  void set_omv_data(unsigned char* value)     { _omv_data = value; }
-  int omv_data_size() const                   { return _omv_data_size; }
-  void set_omv_data_size(int value)           { _omv_data_size = value; }
   int omv_count() const                       { return _omv_count; }
   void set_omv_count(int value)               { _omv_count = value; }
   void increment_count()                      { _omv_count++; }
@@ -172,6 +166,9 @@
   // pc-offset handling
   int offset() const     { return _pc_offset; }
   void set_offset(int o) { _pc_offset = o; }
+  int count() const { return _omv_count; }
+  int data_size() const  { return write_stream()->position(); }
+  address data() const { return write_stream()->buffer(); }
 
   // Check to avoid double insertion
   debug_only(OopMapValue::oop_types locs_used( int indx ) { return _locs_used[indx]; })
@@ -188,11 +185,9 @@
   void set_xxx(VMReg reg, OopMapValue::oop_types x, VMReg optional);
 
   int heap_size() const;
-  void copy_to(address addr);
+  void copy_data_to(address addr) const;
   OopMap* deep_copy();
 
-  bool has_derived_pointer() const PRODUCT_RETURN0;
-
   bool legal_vm_reg_name(VMReg local) {
      return OopMapValue::legal_vm_reg_name(local);
   }
@@ -200,6 +195,7 @@
   // Printing
   void print_on(outputStream* st) const;
   void print() const { print_on(tty); }
+  bool equals(const OopMap* other) const;
 };
 
 
@@ -239,7 +235,6 @@
   OopMap* find_map_at_offset(int pc_offset) const;
 
   int heap_size() const;
-  void copy_to(address addr);
 
   // Methods oops_do() and all_do() filter out NULL oops and
   // oop == Universe::narrow_oop_base() before passing oops
@@ -261,6 +256,79 @@
   void print() const { print_on(tty); }
 };
 
+class ImmutableOopMapBuilder;
+
+class ImmutableOopMap {
+  friend class OopMapStream;
+  friend class VMStructs;
+#ifdef ASSERT
+  friend class ImmutableOopMapBuilder;
+#endif
+private:
+  int _count; // contains the number of entries in this OopMap
+
+  address data_addr() const { return (address) this + sizeof(ImmutableOopMap); }
+public:
+  ImmutableOopMap(const OopMap* oopmap);
+
+  bool has_derived_pointer() const PRODUCT_RETURN0;
+  int count() const { return _count; }
+
+  // Printing
+  void print_on(outputStream* st) const;
+  void print() const { print_on(tty); }
+};
+
+class ImmutableOopMapSet;
+class ImmutableOopMap;
+class OopMapSet;
+
+class ImmutableOopMapPair {
+  friend class VMStructs;
+private:
+  int _pc_offset; // program counter offset from the beginning of the method
+  int _oopmap_offset; // offset in the data in the ImmutableOopMapSet where the ImmutableOopMap is located
+public:
+  ImmutableOopMapPair(int pc_offset, int oopmap_offset) : _pc_offset(pc_offset), _oopmap_offset(oopmap_offset) {
+    assert(pc_offset >= 0 && oopmap_offset >= 0, "check");
+  }
+  const ImmutableOopMap* get_from(const ImmutableOopMapSet* set) const;
+
+  int pc_offset() const { return _pc_offset; }
+  int oopmap_offset() const { return _oopmap_offset; }
+};
+
+class ImmutableOopMapSet {
+  friend class VMStructs;
+private:
+  int _count; // nr of ImmutableOopMapPairs in the Set
+  int _size; // nr of bytes including ImmutableOopMapSet itself
+
+  address data() const { return (address) this + sizeof(*this) + sizeof(ImmutableOopMapPair) * _count; }
+
+public:
+  ImmutableOopMapSet(const OopMapSet* oopmap_set, int size) : _count(oopmap_set->size()), _size(size) {}
+
+  ImmutableOopMap* oopmap_at_offset(int offset) const {
+    assert(offset >= 0 && offset < _size, "must be within boundaries");
+    address addr = data() + offset;
+    return (ImmutableOopMap*) addr;
+  }
+
+  ImmutableOopMapPair* get_pairs() const { return (ImmutableOopMapPair*) ((address) this + sizeof(*this)); }
+
+  static ImmutableOopMapSet* build_from(const OopMapSet* oopmap_set);
+
+  const ImmutableOopMap* find_map_at_offset(int pc_offset) const;
+
+  const ImmutableOopMapPair* pair_at(int index) const { assert(index >= 0 && index < _count, "check"); return &get_pairs()[index]; }
+
+  int count() const { return _count; }
+  int size() const { return _size; }
+
+  void print_on(outputStream* st) const;
+  void print() const { print_on(tty); }
+};
 
 class OopMapStream : public StackObj {
  private:
@@ -273,8 +341,8 @@
   void find_next();
 
  public:
-  OopMapStream(OopMap* oop_map);
-  OopMapStream(OopMap* oop_map, int oop_types_mask);
+  OopMapStream(OopMap* oop_map, int oop_types_mask = OopMapValue::type_mask_in_place);
+  OopMapStream(const ImmutableOopMap* oop_map, int oop_types_mask = OopMapValue::type_mask_in_place);
   bool is_done()                        { if(!_valid_omv) { find_next(); } return !_valid_omv; }
   void next()                           { find_next(); }
   OopMapValue current()                 { return _omv; }
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/adaptiveFreeList.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/adaptiveFreeList.hpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -22,8 +22,8 @@
  *
  */
 
-#ifndef SHARE_VM_MEMORY_ADAPTIVEFREELIST_HPP
-#define SHARE_VM_MEMORY_ADAPTIVEFREELIST_HPP
+#ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_ADAPTIVEFREELIST_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_ADAPTIVEFREELIST_HPP
 
 #include "memory/freeList.hpp"
 #include "gc_implementation/shared/allocationStats.hpp"
@@ -226,4 +226,4 @@
 #endif  // NOT PRODUCT
 };
 
-#endif // SHARE_VM_MEMORY_ADAPTIVEFREELIST_HPP
+#endif // SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_ADAPTIVEFREELIST_HPP
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp	Fri May 08 13:25:11 2015 -0400
@@ -28,6 +28,7 @@
 #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp"
 #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp"
 #include "oops/oop.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
 
 // Trim our work_queue so its length is below max at return
 inline void Par_MarkRefsIntoAndScanClosure::trim_queue(uint max) {
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Fri May 08 13:25:11 2015 -0400
@@ -1082,17 +1082,6 @@
 bool CompactibleFreeListSpace::block_is_obj(const HeapWord* p) const {
   FreeChunk* fc = (FreeChunk*)p;
   assert(is_in_reserved(p), "Should be in space");
-  // When doing a mark-sweep-compact of the CMS generation, this
-  // assertion may fail because prepare_for_compaction() uses
-  // space that is garbage to maintain information on ranges of
-  // live objects so that these live ranges can be moved as a whole.
-  // Comment out this assertion until that problem can be solved
-  // (i.e., that the block start calculation may look at objects
-  // at address below "p" in finding the object that contains "p"
-  // and those objects (if garbage) may have been modified to hold
-  // live range information.
-  // assert(CollectedHeap::use_parallel_gc_threads() || _bt.block_start(p) == p,
-  //        "Should be a block boundary");
   if (FreeChunk::indicatesFreeChunk(p)) return false;
   Klass* k = oop(p)->klass_or_null();
   if (k != NULL) {
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Fri May 08 13:25:11 2015 -0400
@@ -66,6 +66,7 @@
 #include "services/memoryService.hpp"
 #include "services/runtimeService.hpp"
 #include "utilities/stack.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
 
 // statics
 CMSCollector* ConcurrentMarkSweepGeneration::_collector = NULL;
@@ -224,16 +225,12 @@
            "Offset of FreeChunk::_prev within FreeChunk must match"
            "  that of OopDesc::_klass within OopDesc");
   )
-  if (CollectedHeap::use_parallel_gc_threads()) {
-    typedef CMSParGCThreadState* CMSParGCThreadStatePtr;
-    _par_gc_thread_states =
-      NEW_C_HEAP_ARRAY(CMSParGCThreadStatePtr, ParallelGCThreads, mtGC);
-    for (uint i = 0; i < ParallelGCThreads; i++) {
-      _par_gc_thread_states[i] = new CMSParGCThreadState(cmsSpace());
-    }
-  } else {
-    _par_gc_thread_states = NULL;
-  }
+
+  _par_gc_thread_states = NEW_C_HEAP_ARRAY(CMSParGCThreadState*, ParallelGCThreads, mtGC);
+  for (uint i = 0; i < ParallelGCThreads; i++) {
+    _par_gc_thread_states[i] = new CMSParGCThreadState(cmsSpace());
+  }
+
   _incremental_collection_failed = false;
   // The "dilatation_factor" is the expansion that can occur on
   // account of the fact that the minimum object size in the CMS
@@ -459,7 +456,6 @@
   _markBitMap(0, Mutex::leaf + 1, "CMS_markBitMap_lock"),
   _modUnionTable((CardTableModRefBS::card_shift - LogHeapWordSize),
                  -1 /* lock-free */, "No_lock" /* dummy */),
-  _modUnionClosure(&_modUnionTable),
   _modUnionClosurePar(&_modUnionTable),
   // Adjust my span to cover old (cms) gen
   _span(cmsGen->reserved()),
@@ -2129,10 +2125,7 @@
 
   bool registerClosure = duringMarking;
 
-  ModUnionClosure* muc = CollectedHeap::use_parallel_gc_threads() ?
-                                               &_modUnionClosurePar
-                                               : &_modUnionClosure;
-  _cmsGen->gc_prologue_work(full, registerClosure, muc);
+  _cmsGen->gc_prologue_work(full, registerClosure, &_modUnionClosurePar);
 
   if (!full) {
     stats().record_gc0_begin();
@@ -2905,8 +2898,8 @@
 class CMSParMarkTask : public AbstractGangTask {
  protected:
   CMSCollector*     _collector;
-  int               _n_workers;
-  CMSParMarkTask(const char* name, CMSCollector* collector, int n_workers) :
+  uint              _n_workers;
+  CMSParMarkTask(const char* name, CMSCollector* collector, uint n_workers) :
       AbstractGangTask(name),
       _collector(collector),
       _n_workers(n_workers) {}
@@ -2920,7 +2913,7 @@
 // Parallel initial mark task
 class CMSParInitialMarkTask: public CMSParMarkTask {
  public:
-  CMSParInitialMarkTask(CMSCollector* collector, int n_workers) :
+  CMSParInitialMarkTask(CMSCollector* collector, uint n_workers) :
       CMSParMarkTask("Scan roots and young gen for initial mark in parallel",
                      collector, n_workers) {}
   void work(uint worker_id);
@@ -3005,11 +2998,11 @@
 
   {
     COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;)
-    if (CMSParallelInitialMarkEnabled && CollectedHeap::use_parallel_gc_threads()) {
+    if (CMSParallelInitialMarkEnabled) {
       // The parallel version.
       FlexibleWorkGang* workers = gch->workers();
       assert(workers != NULL, "Need parallel worker threads.");
-      int n_workers = workers->active_workers();
+      uint n_workers = workers->active_workers();
       CMSParInitialMarkTask tsk(this, n_workers);
       gch->set_par_threads(n_workers);
       initialize_sequential_subtasks_for_young_gen_rescan(n_workers);
@@ -3150,7 +3143,7 @@
 // MT Concurrent Marking Task
 class CMSConcMarkingTask: public YieldingFlexibleGangTask {
   CMSCollector* _collector;
-  int           _n_workers;                  // requested/desired # workers
+  uint          _n_workers;       // requested/desired # workers
   bool          _result;
   CompactibleFreeListSpace*  _cms_space;
   char          _pad_front[64];   // padding to ...
@@ -3196,7 +3189,7 @@
 
   CMSConcMarkingTerminator* terminator() { return &_term; }
 
-  virtual void set_for_termination(int active_workers) {
+  virtual void set_for_termination(uint active_workers) {
     terminator()->reset_for_reuse(active_workers);
   }
 
@@ -3642,10 +3635,9 @@
 
 bool CMSCollector::do_marking_mt() {
   assert(ConcGCThreads > 0 && conc_workers() != NULL, "precondition");
-  int num_workers = AdaptiveSizePolicy::calc_active_conc_workers(
-                                       conc_workers()->total_workers(),
-                                       conc_workers()->active_workers(),
-                                       Threads::number_of_non_daemon_threads());
+  uint num_workers = AdaptiveSizePolicy::calc_active_conc_workers(conc_workers()->total_workers(),
+                                                                  conc_workers()->active_workers(),
+                                                                  Threads::number_of_non_daemon_threads());
   conc_workers()->set_active_workers(num_workers);
 
   CompactibleFreeListSpace* cms_space  = _cmsGen->cmsSpace();
@@ -4347,7 +4339,7 @@
     // dirtied since the first checkpoint in this GC cycle and prior to
     // the most recent young generation GC, minus those cleaned up by the
     // concurrent precleaning.
-    if (CMSParallelRemarkEnabled && CollectedHeap::use_parallel_gc_threads()) {
+    if (CMSParallelRemarkEnabled) {
       GCTraceTime t("Rescan (parallel) ", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
       do_remark_parallel();
     } else {
@@ -4491,7 +4483,7 @@
   // workers to be taken from the active workers in the work gang.
   CMSParRemarkTask(CMSCollector* collector,
                    CompactibleFreeListSpace* cms_space,
-                   int n_workers, FlexibleWorkGang* workers,
+                   uint n_workers, FlexibleWorkGang* workers,
                    OopTaskQueueSet* task_queues):
     CMSParMarkTask("Rescan roots and grey objects in parallel",
                    collector, n_workers),
@@ -4504,7 +4496,7 @@
   OopTaskQueue* work_queue(int i) { return task_queues()->queue(i); }
 
   ParallelTaskTerminator* terminator() { return &_term; }
-  int n_workers() { return _n_workers; }
+  uint n_workers() { return _n_workers; }
 
   void work(uint worker_id);
 
@@ -5067,7 +5059,7 @@
   // Choose to use the number of GC workers most recently set
   // into "active_workers".  If active_workers is not set, set it
   // to ParallelGCThreads.
-  int n_workers = workers->active_workers();
+  uint n_workers = workers->active_workers();
   if (n_workers == 0) {
     assert(n_workers > 0, "Should have been set during scavenge");
     n_workers = ParallelGCThreads;
@@ -5433,7 +5425,7 @@
       // That is OK as long as the Reference lists are balanced (see
       // balance_all_queues() and balance_queues()).
       GenCollectedHeap* gch = GenCollectedHeap::heap();
-      int active_workers = ParallelGCThreads;
+      uint active_workers = ParallelGCThreads;
       FlexibleWorkGang* workers = gch->workers();
       if (workers != NULL) {
         active_workers = workers->active_workers();
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Fri May 08 13:25:11 2015 -0400
@@ -647,7 +647,6 @@
   // Keep this textually after _markBitMap and _span; c'tor dependency.
 
   ConcurrentMarkSweepThread*     _cmsThread;   // The thread doing the work
-  ModUnionClosure    _modUnionClosure;
   ModUnionClosurePar _modUnionClosurePar;
 
   // CMS abstract state machine
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Fri May 08 13:25:11 2015 -0400
@@ -54,6 +54,7 @@
 #include "runtime/atomic.inline.hpp"
 #include "runtime/prefetch.inline.hpp"
 #include "services/memTracker.hpp"
+#include "utilities/taskqueue.inline.hpp"
 
 // Concurrent marking bit map wrapper
 
@@ -2314,13 +2315,13 @@
   G1CollectedHeap* _g1h;
   ConcurrentMark*  _cm;
   WorkGang*        _workers;
-  int              _active_workers;
+  uint             _active_workers;
 
 public:
   G1CMRefProcTaskExecutor(G1CollectedHeap* g1h,
-                        ConcurrentMark* cm,
-                        WorkGang* workers,
-                        int n_workers) :
+                          ConcurrentMark* cm,
+                          WorkGang* workers,
+                          uint n_workers) :
     _g1h(g1h), _cm(cm),
     _workers(workers), _active_workers(n_workers) { }
 
@@ -2551,31 +2552,50 @@
   _nextMarkBitMap  = (CMBitMap*)  temp;
 }
 
-class CMObjectClosure;
-
-// Closure for iterating over objects, currently only used for
-// processing SATB buffers.
-class CMObjectClosure : public ObjectClosure {
+// Closure for marking entries in SATB buffers.
+class CMSATBBufferClosure : public SATBBufferClosure {
 private:
   CMTask* _task;
+  G1CollectedHeap* _g1h;
+
+  // This is very similar to CMTask::deal_with_reference, but with
+  // more relaxed requirements for the argument, so this must be more
+  // circumspect about treating the argument as an object.
+  void do_entry(void* entry) const {
+    _task->increment_refs_reached();
+    HeapRegion* hr = _g1h->heap_region_containing_raw(entry);
+    if (entry < hr->next_top_at_mark_start()) {
+      // Until we get here, we don't know whether entry refers to a valid
+      // object; it could instead have been a stale reference.
+      oop obj = static_cast<oop>(entry);
+      assert(obj->is_oop(true /* ignore mark word */),
+             err_msg("Invalid oop in SATB buffer: " PTR_FORMAT, p2i(obj)));
+      _task->make_reference_grey(obj, hr);
+    }
+  }
 
 public:
-  void do_object(oop obj) {
-    _task->deal_with_reference(obj);
+  CMSATBBufferClosure(CMTask* task, G1CollectedHeap* g1h)
+    : _task(task), _g1h(g1h) { }
+
+  virtual void do_buffer(void** buffer, size_t size) {
+    for (size_t i = 0; i < size; ++i) {
+      do_entry(buffer[i]);
+    }
   }
-
-  CMObjectClosure(CMTask* task) : _task(task) { }
 };
 
 class G1RemarkThreadsClosure : public ThreadClosure {
-  CMObjectClosure _cm_obj;
+  CMSATBBufferClosure _cm_satb_cl;
   G1CMOopClosure _cm_cl;
   MarkingCodeBlobClosure _code_cl;
   int _thread_parity;
 
  public:
   G1RemarkThreadsClosure(G1CollectedHeap* g1h, CMTask* task) :
-    _cm_obj(task), _cm_cl(g1h, g1h->concurrent_mark(), task), _code_cl(&_cm_cl, !CodeBlobToOopClosure::FixRelocations),
+    _cm_satb_cl(task, g1h),
+    _cm_cl(g1h, g1h->concurrent_mark(), task),
+    _code_cl(&_cm_cl, !CodeBlobToOopClosure::FixRelocations),
     _thread_parity(Threads::thread_claim_parity()) {}
 
   void do_thread(Thread* thread) {
@@ -2591,11 +2611,11 @@
         // live by the SATB invariant but other oops recorded in nmethods may behave differently.
         jt->nmethods_do(&_code_cl);
 
-        jt->satb_mark_queue().apply_closure_and_empty(&_cm_obj);
+        jt->satb_mark_queue().apply_closure_and_empty(&_cm_satb_cl);
       }
     } else if (thread->is_VM_thread()) {
       if (thread->claim_oops_do(true, _thread_parity)) {
-        JavaThread::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(&_cm_obj);
+        JavaThread::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(&_cm_satb_cl);
       }
     }
   }
@@ -2630,7 +2650,7 @@
     }
   }
 
-  CMRemarkTask(ConcurrentMark* cm, int active_workers) :
+  CMRemarkTask(ConcurrentMark* cm, uint active_workers) :
     AbstractGangTask("Par Remark"), _cm(cm) {
     _cm->terminator()->reset_for_reuse(active_workers);
   }
@@ -3008,7 +3028,7 @@
   ConcurrentMark* _cm;
   BitMap* _cm_card_bm;
   uint _max_worker_id;
-  int _active_workers;
+  uint _active_workers;
   HeapRegionClaimer _hrclaimer;
 
 public:
@@ -3016,7 +3036,7 @@
                            ConcurrentMark* cm,
                            BitMap* cm_card_bm,
                            uint max_worker_id,
-                           int n_workers) :
+                           uint n_workers) :
       AbstractGangTask("Count Aggregation"),
       _g1h(g1h), _cm(cm), _cm_card_bm(cm_card_bm),
       _max_worker_id(max_worker_id),
@@ -3033,7 +3053,7 @@
 
 
 void ConcurrentMark::aggregate_count_data() {
-  int n_workers = _g1h->workers()->active_workers();
+  uint n_workers = _g1h->workers()->active_workers();
 
   G1AggregateCountDataTask g1_par_agg_task(_g1h, this, &_card_bm,
                                            _max_worker_id, n_workers);
@@ -3693,13 +3713,13 @@
   // very counter productive if it did that. :-)
   _draining_satb_buffers = true;
 
-  CMObjectClosure oc(this);
+  CMSATBBufferClosure satb_cl(this, _g1h);
   SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
 
   // This keeps claiming and applying the closure to completed buffers
   // until we run out of buffers or we need to abort.
   while (!has_aborted() &&
-         satb_mq_set.apply_closure_to_completed_buffer(&oc)) {
+         satb_mq_set.apply_closure_to_completed_buffer(&satb_cl)) {
     if (_cm->verbose_medium()) {
       gclog_or_tty->print_cr("[%u] processed an SATB buffer", _worker_id);
     }
@@ -3758,6 +3778,10 @@
 #endif // _MARKING_STATS_
 }
 
+bool ConcurrentMark::try_stealing(uint worker_id, int* hash_seed, oop& obj) {
+  return _task_queues->steal(worker_id, hash_seed, obj);
+}
+
 /*****************************************************************************
 
     The do_marking_step(time_target_ms, ...) method is the building
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Fri May 08 13:25:11 2015 -0400
@@ -139,6 +139,11 @@
   static size_t compute_size(size_t heap_size);
   // Returns the amount of bytes on the heap between two marks in the bitmap.
   static size_t mark_distance();
+  // Returns how many bytes (or bits) of the heap a single byte (or bit) of the
+  // mark bitmap corresponds to. This is the same as the mark distance above.
+  static size_t heap_map_factor() {
+    return mark_distance();
+  }
 
   CMBitMap() : CMBitMapRO(LogMinObjAlignment), _listener() { _listener.set_bitmap(this); }
 
@@ -671,9 +676,7 @@
   }
 
   // Attempts to steal an object from the task queues of other tasks
-  bool try_stealing(uint worker_id, int* hash_seed, oop& obj) {
-    return _task_queues->steal(worker_id, hash_seed, obj);
-  }
+  bool try_stealing(uint worker_id, int* hash_seed, oop& obj);
 
   ConcurrentMark(G1CollectedHeap* g1h,
                  G1RegionToSpaceMapper* prev_bitmap_storage,
@@ -1095,9 +1098,9 @@
   void regular_clock_call();
   bool concurrent() { return _concurrent; }
 
-  // Test whether objAddr might have already been passed over by the
+  // Test whether obj might have already been passed over by the
   // mark bitmap scan, and so needs to be pushed onto the mark stack.
-  bool is_below_finger(HeapWord* objAddr, HeapWord* global_finger) const;
+  bool is_below_finger(oop obj, HeapWord* global_finger) const;
 
   template<bool scan> void process_grey_object(oop obj);
 
@@ -1148,8 +1151,18 @@
 
   void set_cm_oop_closure(G1CMOopClosure* cm_oop_closure);
 
-  // It grays the object by marking it and, if necessary, pushing it
-  // on the local queue
+  // Increment the number of references this task has visited.
+  void increment_refs_reached() { ++_refs_reached; }
+
+  // Grey the object by marking it.  If not already marked, push it on
+  // the local queue if below the finger.
+  // Precondition: obj is in region.
+  // Precondition: obj is below region's NTAMS.
+  inline void make_reference_grey(oop obj, HeapRegion* region);
+
+  // Grey the object (by calling make_grey_reference) if required,
+  // e.g. obj is below its containing region's NTAMS.
+  // Precondition: obj is a valid heap object.
   inline void deal_with_reference(oop obj);
 
   // It scans an object and visits its children.
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp	Fri May 08 13:25:11 2015 -0400
@@ -27,6 +27,7 @@
 
 #include "gc_implementation/g1/concurrentMark.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
 
 // Utility routine to set an exclusive range of cards on the given
 // card liveness bitmap
@@ -259,15 +260,15 @@
              ++_local_pushes );
 }
 
-inline bool CMTask::is_below_finger(HeapWord* objAddr,
-                                    HeapWord* global_finger) const {
-  // If objAddr is above the global finger, then the mark bitmap scan
+inline bool CMTask::is_below_finger(oop obj, HeapWord* global_finger) const {
+  // If obj is above the global finger, then the mark bitmap scan
   // will find it later, and no push is needed.  Similarly, if we have
-  // a current region and objAddr is between the local finger and the
+  // a current region and obj is between the local finger and the
   // end of the current region, then no push is needed.  The tradeoff
   // of checking both vs only checking the global finger is that the
   // local check will be more accurate and so result in fewer pushes,
   // but may also be a little slower.
+  HeapWord* objAddr = (HeapWord*)obj;
   if (_finger != NULL) {
     // We have a current region.
 
@@ -277,7 +278,7 @@
     assert(_region_limit != NULL, "invariant");
     assert(_region_limit <= global_finger, "invariant");
 
-    // True if objAddr is less than the local finger, or is between
+    // True if obj is less than the local finger, or is between
     // the region limit and the global finger.
     if (objAddr < _finger) {
       return true;
@@ -289,13 +290,65 @@
   return objAddr < global_finger;
 }
 
+inline void CMTask::make_reference_grey(oop obj, HeapRegion* hr) {
+  if (_cm->par_mark_and_count(obj, hr, _marked_bytes_array, _card_bm)) {
+
+    if (_cm->verbose_high()) {
+      gclog_or_tty->print_cr("[%u] marked object " PTR_FORMAT,
+                             _worker_id, p2i(obj));
+    }
+
+    // No OrderAccess:store_load() is needed. It is implicit in the
+    // CAS done in CMBitMap::parMark() call in the routine above.
+    HeapWord* global_finger = _cm->finger();
+
+    // We only need to push a newly grey object on the mark
+    // stack if it is in a section of memory the mark bitmap
+    // scan has already examined.  Mark bitmap scanning
+    // maintains progress "fingers" for determining that.
+    //
+    // Notice that the global finger might be moving forward
+    // concurrently. This is not a problem. In the worst case, we
+    // mark the object while it is above the global finger and, by
+    // the time we read the global finger, it has moved forward
+    // past this object. In this case, the object will probably
+    // be visited when a task is scanning the region and will also
+    // be pushed on the stack. So, some duplicate work, but no
+    // correctness problems.
+    if (is_below_finger(obj, global_finger)) {
+      if (obj->is_typeArray()) {
+        // Immediately process arrays of primitive types, rather
+        // than pushing on the mark stack.  This keeps us from
+        // adding humongous objects to the mark stack that might
+        // be reclaimed before the entry is processed - see
+        // selection of candidates for eager reclaim of humongous
+        // objects.  The cost of the additional type test is
+        // mitigated by avoiding a trip through the mark stack,
+        // by only doing a bookkeeping update and avoiding the
+        // actual scan of the object - a typeArray contains no
+        // references, and the metadata is built-in.
+        process_grey_object<false>(obj);
+      } else {
+        if (_cm->verbose_high()) {
+          gclog_or_tty->print_cr("[%u] below a finger (local: " PTR_FORMAT
+                                 ", global: " PTR_FORMAT ") pushing "
+                                 PTR_FORMAT " on mark stack",
+                                 _worker_id, p2i(_finger),
+                                 p2i(global_finger), p2i(obj));
+        }
+        push(obj);
+      }
+    }
+  }
+}
+
 inline void CMTask::deal_with_reference(oop obj) {
   if (_cm->verbose_high()) {
     gclog_or_tty->print_cr("[%u] we're dealing with reference = "PTR_FORMAT,
                            _worker_id, p2i((void*) obj));
   }
 
-  ++_refs_reached;
+  increment_refs_reached();
 
   HeapWord* objAddr = (HeapWord*) obj;
   assert(obj->is_oop_or_null(true /* ignore mark word */), err_msg("Expected an oop or NULL at " PTR_FORMAT, p2i(obj)));
@@ -307,55 +360,7 @@
       // anything with it).
       HeapRegion* hr = _g1h->heap_region_containing_raw(obj);
       if (!hr->obj_allocated_since_next_marking(obj)) {
-        if (_cm->verbose_high()) {
-          gclog_or_tty->print_cr("[%u] "PTR_FORMAT" is not considered marked",
-                                 _worker_id, p2i((void*) obj));
-        }
-
-        // we need to mark it first
-        if (_cm->par_mark_and_count(obj, hr, _marked_bytes_array, _card_bm)) {
-          // No OrderAccess:store_load() is needed. It is implicit in the
-          // CAS done in CMBitMap::parMark() call in the routine above.
-          HeapWord* global_finger = _cm->finger();
-
-          // We only need to push a newly grey object on the mark
-          // stack if it is in a section of memory the mark bitmap
-          // scan has already examined.  Mark bitmap scanning
-          // maintains progress "fingers" for determining that.
-          //
-          // Notice that the global finger might be moving forward
-          // concurrently. This is not a problem. In the worst case, we
-          // mark the object while it is above the global finger and, by
-          // the time we read the global finger, it has moved forward
-          // past this object. In this case, the object will probably
-          // be visited when a task is scanning the region and will also
-          // be pushed on the stack. So, some duplicate work, but no
-          // correctness problems.
-          if (is_below_finger(objAddr, global_finger)) {
-            if (obj->is_typeArray()) {
-              // Immediately process arrays of primitive types, rather
-              // than pushing on the mark stack.  This keeps us from
-              // adding humongous objects to the mark stack that might
-              // be reclaimed before the entry is processed - see
-              // selection of candidates for eager reclaim of humongous
-              // objects.  The cost of the additional type test is
-              // mitigated by avoiding a trip through the mark stack,
-              // by only doing a bookkeeping update and avoiding the
-              // actual scan of the object - a typeArray contains no
-              // references, and the metadata is built-in.
-              process_grey_object<false>(obj);
-            } else {
-              if (_cm->verbose_high()) {
-                gclog_or_tty->print_cr("[%u] below a finger (local: " PTR_FORMAT
-                                       ", global: " PTR_FORMAT ") pushing "
-                                       PTR_FORMAT " on mark stack",
-                                       _worker_id, p2i(_finger),
-                                       p2i(global_finger), p2i(objAddr));
-              }
-              push(obj);
-            }
-          }
-        }
+        make_reference_grey(obj, hr);
       }
     }
   }
--- a/hotspot/src/share/vm/gc_implementation/g1/evacuationInfo.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/evacuationInfo.hpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -22,8 +22,8 @@
  *
  */
 
-#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_EVACUATIONINFO_HPP
-#define SHARE_VM_GC_IMPLEMENTATION_SHARED_EVACUATIONINFO_HPP
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_EVACUATIONINFO_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_EVACUATIONINFO_HPP
 
 #include "memory/allocation.hpp"
 
@@ -78,4 +78,4 @@
   uint   regions_freed()             { return _regions_freed; }
 };
 
-#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_EVACUATIONINFO_HPP
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_EVACUATIONINFO_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.cpp	Fri May 08 13:25:11 2015 -0400
@@ -24,7 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc_implementation/g1/g1Allocator.hpp"
-#include "gc_implementation/g1/g1CollectedHeap.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
 #include "gc_implementation/g1/heapRegion.inline.hpp"
 #include "gc_implementation/g1/heapRegionSet.inline.hpp"
@@ -119,7 +119,6 @@
   size_t gclab_word_size = _g1h->desired_plab_sz(dest);
   if (word_sz * 100 < gclab_word_size * ParallelGCBufferWastePct) {
     G1PLAB* alloc_buf = alloc_buffer(dest, context);
-    add_to_alloc_buffer_waste(alloc_buf->words_remaining());
     alloc_buf->retire();
 
     HeapWord* buf = _g1h->par_allocate_during_gc(dest, gclab_word_size, context);
@@ -153,8 +152,19 @@
   for (uint state = 0; state < InCSetState::Num; state++) {
     G1PLAB* const buf = _alloc_buffers[state];
     if (buf != NULL) {
-      add_to_alloc_buffer_waste(buf->words_remaining());
       buf->flush_and_retire_stats(_g1h->alloc_buffer_stats(state));
     }
   }
 }
+
+void G1DefaultParGCAllocator::waste(size_t& wasted, size_t& undo_wasted) {
+  wasted = 0;
+  undo_wasted = 0;
+  for (uint state = 0; state < InCSetState::Num; state++) {
+    G1PLAB * const buf = _alloc_buffers[state];
+    if (buf != NULL) {
+      wasted += buf->waste();
+      undo_wasted += buf->undo_waste();
+    }
+  }
+}
--- a/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.hpp	Fri May 08 13:25:11 2015 -0400
@@ -188,12 +188,6 @@
   // architectures have a special compare against zero instructions.
   const uint _survivor_alignment_bytes;
 
-  size_t _alloc_buffer_waste;
-  size_t _undo_waste;
-
-  void add_to_alloc_buffer_waste(size_t waste) { _alloc_buffer_waste += waste; }
-  void add_to_undo_waste(size_t waste)         { _undo_waste += waste; }
-
   virtual void retire_alloc_buffers() = 0;
   virtual G1PLAB* alloc_buffer(InCSetState dest, AllocationContext_t context) = 0;
 
@@ -213,15 +207,12 @@
 
 public:
   G1ParGCAllocator(G1CollectedHeap* g1h) :
-    _g1h(g1h), _survivor_alignment_bytes(calc_survivor_alignment_bytes()),
-    _alloc_buffer_waste(0), _undo_waste(0) {
-  }
+    _g1h(g1h), _survivor_alignment_bytes(calc_survivor_alignment_bytes()) { }
   virtual ~G1ParGCAllocator() { }
 
   static G1ParGCAllocator* create_allocator(G1CollectedHeap* g1h);
 
-  size_t alloc_buffer_waste() { return _alloc_buffer_waste; }
-  size_t undo_waste() {return _undo_waste; }
+  virtual void waste(size_t& wasted, size_t& undo_wasted) = 0;
 
   // Allocate word_sz words in dest, either directly into the regions or by
   // allocating a new PLAB. Returns the address of the allocated memory, NULL if
@@ -253,14 +244,7 @@
   }
 
   void undo_allocation(InCSetState dest, HeapWord* obj, size_t word_sz, AllocationContext_t context) {
-    if (alloc_buffer(dest, context)->contains(obj)) {
-      assert(alloc_buffer(dest, context)->contains(obj + word_sz - 1),
-             "should contain whole object");
-      alloc_buffer(dest, context)->undo_allocation(obj, word_sz);
-    } else {
-      CollectedHeap::fill_with_object(obj, word_sz);
-      add_to_undo_waste(word_sz);
-    }
+    alloc_buffer(dest, context)->undo_allocation(obj, word_sz);
   }
 };
 
@@ -280,7 +264,9 @@
     return _alloc_buffers[dest.value()];
   }
 
-  virtual void retire_alloc_buffers() ;
+  virtual void retire_alloc_buffers();
+
+  virtual void waste(size_t& wasted, size_t& undo_wasted);
 };
 
 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1ALLOCATOR_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp	Fri May 08 13:25:11 2015 -0400
@@ -23,8 +23,8 @@
  */
 
 #include "precompiled.hpp"
-#include "gc_implementation/g1/g1CollectedHeap.hpp"
 #include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/heapRegion.hpp"
 #include "memory/space.hpp"
 #include "oops/oop.inline.hpp"
@@ -66,6 +66,20 @@
   return (delta & right_n_bits(LogN_words)) == (size_t)NoBits;
 }
 
+#ifdef ASSERT
+void G1BlockOffsetSharedArray::check_index(size_t index, const char* msg) const {
+  assert((index) < (_reserved.word_size() >> LogN_words),
+         err_msg("%s - index: "SIZE_FORMAT", _vs.committed_size: "SIZE_FORMAT,
+                 msg, (index), (_reserved.word_size() >> LogN_words)));
+  assert(G1CollectedHeap::heap()->is_in_exact(address_for_index_raw(index)),
+         err_msg("Index "SIZE_FORMAT" corresponding to "PTR_FORMAT
+                 " (%u) is not in committed area.",
+                 (index),
+                 p2i(address_for_index_raw(index)),
+                 G1CollectedHeap::heap()->addr_to_region(address_for_index_raw(index))));
+}
+#endif // ASSERT
+
 //////////////////////////////////////////////////////////////////////
 // G1BlockOffsetArray
 //////////////////////////////////////////////////////////////////////
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp	Fri May 08 13:25:11 2015 -0400
@@ -170,6 +170,8 @@
 
   bool is_card_boundary(HeapWord* p) const;
 
+  void check_index(size_t index, const char* msg) const NOT_DEBUG_RETURN;
+
 public:
 
   // Return the number of slots needed for an offset array
@@ -179,6 +181,11 @@
     return ReservedSpace::allocation_align_size_up(number_of_slots);
   }
 
+  // Returns how many bytes of the heap a single byte of the BOT corresponds to.
+  static size_t heap_map_factor() {
+    return N_bytes;
+  }
+
   enum SomePublicConstants {
     LogN = 9,
     LogN_words = LogN - LogHeapWordSize,
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -26,7 +26,6 @@
 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1BLOCKOFFSETTABLE_INLINE_HPP
 
 #include "gc_implementation/g1/g1BlockOffsetTable.hpp"
-#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/heapRegion.inline.hpp"
 #include "memory/space.hpp"
 
@@ -47,17 +46,6 @@
   }
 }
 
-#define check_index(index, msg)                                                \
-  assert((index) < (_reserved.word_size() >> LogN_words),                      \
-         err_msg("%s - index: "SIZE_FORMAT", _vs.committed_size: "SIZE_FORMAT, \
-                 msg, (index), (_reserved.word_size() >> LogN_words)));        \
-  assert(G1CollectedHeap::heap()->is_in_exact(address_for_index_raw(index)),   \
-         err_msg("Index "SIZE_FORMAT" corresponding to "PTR_FORMAT             \
-                 " (%u) is not in committed area.",                            \
-                 (index),                                                      \
-                 p2i(address_for_index_raw(index)),                            \
-                 G1CollectedHeap::heap()->addr_to_region(address_for_index_raw(index))));
-
 u_char G1BlockOffsetSharedArray::offset_array(size_t index) const {
   check_index(index, "index out of range");
   return _offset_array[index];
@@ -119,8 +107,6 @@
   return result;
 }
 
-#undef check_index
-
 inline size_t
 G1BlockOffsetArray::block_size(const HeapWord* p) const {
   return gsp()->block_size(p);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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,6 +39,17 @@
   _counts->clear_range(mr);
 }
 
+size_t G1CardCounts::compute_size(size_t mem_region_size_in_words) {
+  // We keep card counts for every card, so the size of the card counts table must
+  // be the same as the card table.
+  return G1SATBCardTableLoggingModRefBS::compute_size(mem_region_size_in_words);
+}
+
+size_t G1CardCounts::heap_map_factor() {
+  // See G1CardCounts::compute_size() why we reuse the card table value.
+  return G1SATBCardTableLoggingModRefBS::heap_map_factor();
+}
+
 void G1CardCounts::clear_range(size_t from_card_num, size_t to_card_num) {
   if (has_count_table()) {
     assert(from_card_num < to_card_num,
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp	Fri May 08 13:25:11 2015 -0400
@@ -101,6 +101,14 @@
  public:
   G1CardCounts(G1CollectedHeap* g1h);
 
+  // Return the number of slots needed for a card counts table
+  // that covers mem_region_words words.
+  static size_t compute_size(size_t mem_region_size_in_words);
+
+  // Returns how many bytes of the heap a single byte of the card counts table
+  // corresponds to.
+  static size_t heap_map_factor();
+
   void initialize(G1RegionToSpaceMapper* mapper);
 
   // Increments the refinement count for the given card.
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Fri May 08 13:25:11 2015 -0400
@@ -66,6 +66,7 @@
 #include "runtime/vmThread.hpp"
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/stack.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
 
 size_t G1CollectedHeap::_humongous_object_threshold_in_words = 0;
 
@@ -1083,11 +1084,9 @@
 class RebuildRSOutOfRegionClosure: public HeapRegionClosure {
   G1CollectedHeap*   _g1h;
   UpdateRSOopClosure _cl;
-  int                _worker_i;
 public:
-  RebuildRSOutOfRegionClosure(G1CollectedHeap* g1, int worker_i = 0) :
+  RebuildRSOutOfRegionClosure(G1CollectedHeap* g1, uint worker_i = 0) :
     _cl(g1->g1_rem_set(), worker_i),
-    _worker_i(worker_i),
     _g1h(g1)
   { }
 
@@ -1166,6 +1165,7 @@
   SvcGCMarker sgcm(SvcGCMarker::FULL);
   ResourceMark rm;
 
+  G1Log::update_level();
   print_heap_before_gc();
   trace_heap_before_gc(gc_tracer);
 
@@ -1890,24 +1890,24 @@
   G1RegionToSpaceMapper* bot_storage =
     create_aux_memory_mapper("Block offset table",
                              G1BlockOffsetSharedArray::compute_size(g1_rs.size() / HeapWordSize),
-                             G1BlockOffsetSharedArray::N_bytes);
+                             G1BlockOffsetSharedArray::heap_map_factor());
 
   ReservedSpace cardtable_rs(G1SATBCardTableLoggingModRefBS::compute_size(g1_rs.size() / HeapWordSize));
   G1RegionToSpaceMapper* cardtable_storage =
     create_aux_memory_mapper("Card table",
                              G1SATBCardTableLoggingModRefBS::compute_size(g1_rs.size() / HeapWordSize),
-                             G1BlockOffsetSharedArray::N_bytes);
+                             G1SATBCardTableLoggingModRefBS::heap_map_factor());
 
   G1RegionToSpaceMapper* card_counts_storage =
     create_aux_memory_mapper("Card counts table",
-                             G1BlockOffsetSharedArray::compute_size(g1_rs.size() / HeapWordSize),
-                             G1BlockOffsetSharedArray::N_bytes);
+                             G1CardCounts::compute_size(g1_rs.size() / HeapWordSize),
+                             G1CardCounts::heap_map_factor());
 
   size_t bitmap_size = CMBitMap::compute_size(g1_rs.size());
   G1RegionToSpaceMapper* prev_bitmap_storage =
-    create_aux_memory_mapper("Prev Bitmap", bitmap_size, CMBitMap::mark_distance());
+    create_aux_memory_mapper("Prev Bitmap", bitmap_size, CMBitMap::heap_map_factor());
   G1RegionToSpaceMapper* next_bitmap_storage =
-    create_aux_memory_mapper("Next Bitmap", bitmap_size, CMBitMap::mark_distance());
+    create_aux_memory_mapper("Next Bitmap", bitmap_size, CMBitMap::heap_map_factor());
 
   _hrm.initialize(heap_storage, prev_bitmap_storage, next_bitmap_storage, bot_storage, cardtable_storage, card_counts_storage);
   g1_barrier_set()->initialize(cardtable_storage);
@@ -3039,7 +3039,7 @@
       assert(UseDynamicNumberOfGCThreads ||
         workers()->active_workers() == workers()->total_workers(),
         "If not dynamic should be using all the workers");
-      int n_workers = workers()->active_workers();
+      uint n_workers = workers()->active_workers();
       set_par_threads(n_workers);
       workers()->run_task(&task);
       set_par_threads(0);
@@ -3577,9 +3577,9 @@
   print_taskqueue_stats_hdr(st);
 
   TaskQueueStats totals;
-  const int n = workers()->total_workers();
-  for (int i = 0; i < n; ++i) {
-    st->print("%3d ", i); task_queue(i)->stats.print(st); st->cr();
+  const uint n = workers()->total_workers();
+  for (uint i = 0; i < n; ++i) {
+    st->print("%3u ", i); task_queue(i)->stats.print(st); st->cr();
     totals += task_queue(i)->stats;
   }
   st->print_raw("tot "); totals.print(st); st->cr();
@@ -3588,8 +3588,8 @@
 }
 
 void G1CollectedHeap::reset_taskqueue_stats() {
-  const int n = workers()->total_workers();
-  for (int i = 0; i < n; ++i) {
+  const uint n = workers()->total_workers();
+  for (uint i = 0; i < n; ++i) {
     task_queue(i)->stats.reset();
   }
 }
@@ -3648,6 +3648,7 @@
   SvcGCMarker sgcm(SvcGCMarker::MINOR);
   ResourceMark rm;
 
+  G1Log::update_level();
   print_heap_before_gc();
   trace_heap_before_gc(_gc_tracer_stw);
 
@@ -4318,7 +4319,7 @@
 
   ParallelTaskTerminator* terminator() { return &_terminator; }
 
-  virtual void set_for_termination(int active_workers) {
+  virtual void set_for_termination(uint active_workers) {
     _root_processor->set_num_workers(active_workers);
     terminator()->reset_for_reuse(active_workers);
     _n_workers = active_workers;
@@ -4997,13 +4998,13 @@
   G1CollectedHeap*   _g1h;
   RefToScanQueueSet* _queues;
   FlexibleWorkGang*  _workers;
-  int                _active_workers;
+  uint               _active_workers;
 
 public:
   G1STWRefProcTaskExecutor(G1CollectedHeap* g1h,
-                        FlexibleWorkGang* workers,
-                        RefToScanQueueSet *task_queues,
-                        int n_workers) :
+                           FlexibleWorkGang* workers,
+                           RefToScanQueueSet *task_queues,
+                           uint n_workers) :
     _g1h(g1h),
     _queues(task_queues),
     _workers(workers),
@@ -5136,7 +5137,7 @@
   uint _n_workers;
 
 public:
-  G1ParPreserveCMReferentsTask(G1CollectedHeap* g1h,int workers, RefToScanQueueSet *task_queues) :
+  G1ParPreserveCMReferentsTask(G1CollectedHeap* g1h, uint workers, RefToScanQueueSet *task_queues) :
     AbstractGangTask("ParPreserveCMReferents"),
     _g1h(g1h),
     _queues(task_queues),
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Fri May 08 13:25:11 2015 -0400
@@ -979,7 +979,7 @@
 
   void set_refine_cte_cl_concurrency(bool concurrent);
 
-  RefToScanQueue *task_queue(int i) const;
+  RefToScanQueue *task_queue(uint i) const;
 
   // A set of cards where updates happened during the GC
   DirtyCardQueueSet& dirty_card_queue_set() { return _dirty_card_queue_set; }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp	Fri May 08 13:25:11 2015 -0400
@@ -210,7 +210,7 @@
   g1_barrier_set()->g1_mark_as_young(mr);
 }
 
-inline RefToScanQueue* G1CollectedHeap::task_queue(int i) const {
+inline RefToScanQueue* G1CollectedHeap::task_queue(uint i) const {
   return _task_queues->queue(i);
 }
 
--- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp	Fri May 08 13:25:11 2015 -0400
@@ -22,8 +22,8 @@
  *
  */
 
-#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP
-#define SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMES_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMES_HPP
 
 #include "memory/allocation.hpp"
 
@@ -286,4 +286,4 @@
   ~G1GCParPhaseTimesTracker();
 };
 
-#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMES_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1Log.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1Log.cpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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,17 +25,34 @@
 #include "precompiled.hpp"
 #include "gc_implementation/g1/g1_globals.hpp"
 #include "gc_implementation/g1/g1Log.hpp"
-#include "runtime/globals.hpp"
+#include "runtime/globals_extension.hpp"
 
 G1Log::LogLevel G1Log::_level = G1Log::LevelNone;
 
+
+// Updates _level based on PrintGC and PrintGCDetails values (unless
+// G1LogLevel is set explicitly)
+// - PrintGC maps to "fine".
+// - PrintGCDetails maps to "finer".
+void G1Log::update_level() {
+  if (FLAG_IS_DEFAULT(G1LogLevel)) {
+    _level = LevelNone;
+    if (PrintGCDetails) {
+      _level = LevelFiner;
+    } else if (PrintGC) {
+      _level = LevelFine;
+    }
+  }
+}
+
+
 // If G1LogLevel has not been set up we will use the values of PrintGC
 // and PrintGCDetails for the logging level.
-// - PrintGC maps to "fine".
-// - PrintGCDetails maps to "finer".
 void G1Log::init() {
-  if (G1LogLevel != NULL && G1LogLevel[0] != '\0') {
-    if (strncmp("none", G1LogLevel, 4) == 0 && G1LogLevel[4] == '\0') {
+  if (!FLAG_IS_DEFAULT(G1LogLevel)) {
+    // PrintGC flags change won't have any affect, because G1LogLevel
+    // is set explicitly
+    if (G1LogLevel[0] == '\0' || strncmp("none", G1LogLevel, 4) == 0 && G1LogLevel[4] == '\0') {
       _level = LevelNone;
     } else if (strncmp("fine", G1LogLevel, 4) == 0 && G1LogLevel[4] == '\0') {
       _level = LevelFine;
@@ -47,10 +64,7 @@
       warning("Unknown logging level '%s', should be one of 'fine', 'finer' or 'finest'.", G1LogLevel);
     }
   } else {
-    if (PrintGCDetails) {
-      _level = LevelFiner;
-    } else if (PrintGC) {
-      _level = LevelFine;
-    }
+    update_level();
   }
 }
+
--- a/hotspot/src/share/vm/gc_implementation/g1/g1Log.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1Log.hpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -57,6 +57,9 @@
   }
 
   static void init();
+
+  // Update to log level to reflect runtime changes to manageable flags
+  static void update_level();
 };
 
 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1LOG_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -76,9 +76,6 @@
 }
 
 void G1MMUTrackerQueue::add_pause(double start, double end, bool gc_thread) {
-  double longest_allowed = longest_pause_internal(start);
-  if (longest_allowed < 0.0)
-    longest_allowed = 0.0;
   double duration = end - start;
 
   remove_expired_entries(end);
@@ -111,41 +108,6 @@
 // this is for trying things out in the future and a couple
 // of other places (debugging)
 
-double G1MMUTrackerQueue::longest_pause(double current_time) {
-  if (_DISABLE_MMU)
-    return _max_gc_time;
-
-  MutexLockerEx x(MMUTracker_lock, Mutex::_no_safepoint_check_flag);
-  remove_expired_entries(current_time);
-
-  return longest_pause_internal(current_time);
-}
-
-double G1MMUTrackerQueue::longest_pause_internal(double current_time) {
-  double target_time = _max_gc_time;
-
-  while( 1 ) {
-    double gc_time =
-      calculate_gc_time(current_time + target_time);
-    double diff = target_time + gc_time - _max_gc_time;
-    if (!is_double_leq_0(diff)) {
-      target_time -= diff;
-      if (is_double_leq_0(target_time)) {
-        target_time = -1.0;
-        break;
-      }
-    } else {
-      break;
-    }
-  }
-
-  return target_time;
-}
-
-// basically the _internal call does not remove expired entries
-// this is for trying things out in the future and a couple
-// of other places (debugging)
-
 double G1MMUTrackerQueue::when_sec(double current_time, double pause_time) {
   if (_DISABLE_MMU)
     return 0.0;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -43,7 +43,6 @@
   G1MMUTracker(double time_slice, double max_gc_time);
 
   virtual void add_pause(double start, double end, bool gc_thread) = 0;
-  virtual double longest_pause(double current_time) = 0;
   virtual double when_sec(double current_time, double pause_time) = 0;
 
   double max_gc_time() {
@@ -122,7 +121,6 @@
   void remove_expired_entries(double current_time);
   double calculate_gc_time(double current_time);
 
-  double longest_pause_internal(double current_time);
   double when_internal(double current_time, double pause_time);
 
 public:
@@ -130,7 +128,6 @@
 
   virtual void add_pause(double start, double end, bool gc_thread);
 
-  virtual double longest_pause(double current_time);
   virtual double when_sec(double current_time, double pause_time);
 };
 
--- a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp	Fri May 08 13:25:11 2015 -0400
@@ -29,7 +29,7 @@
 #include "gc_implementation/g1/g1StringDedup.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/prefetch.inline.hpp"
-#include "utilities/stack.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
 
 G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp)
   : _g1h(g1h),
@@ -95,8 +95,9 @@
   const double elapsed_ms = elapsed_time() * 1000.0;
   const double s_roots_ms = strong_roots_time() * 1000.0;
   const double term_ms    = term_time() * 1000.0;
-  const size_t alloc_buffer_waste = _g1_par_allocator->alloc_buffer_waste();
-  const size_t undo_waste         = _g1_par_allocator->undo_waste();
+  size_t alloc_buffer_waste = 0;
+  size_t undo_waste = 0;
+  _g1_par_allocator->waste(alloc_buffer_waste, undo_waste);
   st->print_cr("%3d %9.2f %9.2f %6.2f "
                "%9.2f %6.2f " SIZE_FORMAT_W(8) " "
                SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7),
--- a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.hpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -54,9 +54,6 @@
   uint              _tenuring_threshold;
   G1ParScanClosure  _scanner;
 
-  size_t            _alloc_buffer_waste;
-  size_t            _undo_waste;
-
   OopsInHeapRegionClosure*      _evac_failure_cl;
 
   int  _hash_seed;
@@ -78,9 +75,6 @@
 
 #define PADDING_ELEM_NUM (DEFAULT_CACHE_LINE_SIZE / sizeof(size_t))
 
-  void   add_to_alloc_buffer_waste(size_t waste) { _alloc_buffer_waste += waste; }
-  void   add_to_undo_waste(size_t waste)         { _undo_waste += waste; }
-
   DirtyCardQueue& dirty_card_queue()             { return _dcq;  }
   G1SATBCardTableModRefBS* ctbs()                { return _ct_bs; }
 
@@ -106,10 +100,7 @@
   bool verify_task(StarTask ref) const;
 #endif // ASSERT
 
-  template <class T> void push_on_queue(T* ref) {
-    assert(verify_ref(ref), "sanity");
-    _refs->push(ref);
-  }
+  template <class T> void push_on_queue(T* ref);
 
   template <class T> void update_rs(HeapRegion* from, T* p, uint tid) {
     // If the new value of the field points to the same region or
--- a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp	Fri May 08 13:25:11 2015 -0400
@@ -59,6 +59,11 @@
   update_rs(from, p, queue_num());
 }
 
+template <class T> inline void G1ParScanThreadState::push_on_queue(T* ref) {
+  assert(verify_ref(ref), "sanity");
+  _refs->push(ref);
+}
+
 inline void G1ParScanThreadState::do_oop_partial_array(oop* p) {
   assert(has_partial_array_mask(p), "invariant");
   oop from_obj = clear_partial_array_mask(p);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RootProcessor.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RootProcessor.cpp	Fri May 08 13:25:11 2015 -0400
@@ -329,6 +329,6 @@
   _g1h->g1_rem_set()->oops_into_collection_set_do(scan_rs, &scavenge_cs_nmethods, worker_i);
 }
 
-void G1RootProcessor::set_num_workers(int active_workers) {
+void G1RootProcessor::set_num_workers(uint active_workers) {
   _process_strong_tasks->set_n_threads(active_workers);
 }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RootProcessor.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RootProcessor.hpp	Fri May 08 13:25:11 2015 -0400
@@ -22,8 +22,8 @@
  *
  */
 
-#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_ROOTPROCESSOR_HPP
-#define SHARE_VM_GC_IMPLEMENTATION_G1_ROOTPROCESSOR_HPP
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1ROOTPROCESSOR_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_G1ROOTPROCESSOR_HPP
 
 #include "memory/allocation.hpp"
 #include "memory/strongRootsScope.hpp"
@@ -115,7 +115,7 @@
                             uint worker_i);
 
   // Inform the root processor about the number of worker threads
-  void set_num_workers(int active_workers);
+  void set_num_workers(uint active_workers);
 };
 
-#endif // SHARE_VM_GC_IMPLEMENTATION_G1_ROOTPROCESSOR_HPP
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1ROOTPROCESSOR_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp	Fri May 08 13:25:11 2015 -0400
@@ -153,6 +153,11 @@
     return ReservedSpace::allocation_align_size_up(number_of_slots);
   }
 
+  // Returns how many bytes of the heap a single byte of the Card Table corresponds to.
+  static size_t heap_map_factor() {
+    return CardTableModRefBS::card_size;
+  }
+
   G1SATBCardTableLoggingModRefBS(MemRegion whole_heap);
 
   virtual void initialize() { }
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionBounds.inline.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionBounds.inline.hpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -22,6 +22,9 @@
  *
  */
 
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONBOUNDS_INLINE_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONBOUNDS_INLINE_HPP
+
 #include "gc_implementation/g1/heapRegionBounds.hpp"
 
 size_t HeapRegionBounds::min_size() {
@@ -35,3 +38,5 @@
 size_t HeapRegionBounds::target_number() {
   return TARGET_REGION_NUMBER;
 }
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONBOUNDS_INLINE_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp	Fri May 08 13:25:11 2015 -0400
@@ -29,6 +29,7 @@
 #include "memory/allocation.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/mutexLocker.hpp"
+#include "runtime/safepoint.hpp"
 #include "runtime/thread.hpp"
 #include "runtime/vmThread.hpp"
 
@@ -160,10 +161,7 @@
   assert(_lock == NULL || _lock->owned_by_self(),
          "we should have taken the lock before calling this");
 
-  // Even if G1SATBBufferEnqueueingThresholdPercent == 0 we have to
-  // filter the buffer given that this will remove any references into
-  // the CSet as we currently assume that no such refs will appear in
-  // enqueued buffers.
+  // If G1SATBBufferEnqueueingThresholdPercent == 0 we could skip filtering.
 
   // This method should only be called if there is a non-NULL buffer
   // that is full.
@@ -180,25 +178,19 @@
   return should_enqueue;
 }
 
-void ObjPtrQueue::apply_closure_and_empty(ObjectClosure* cl) {
+void ObjPtrQueue::apply_closure_and_empty(SATBBufferClosure* cl) {
+  assert(SafepointSynchronize::is_at_safepoint(),
+         "SATB queues must only be processed at safepoints");
   if (_buf != NULL) {
-    apply_closure_to_buffer(cl, _buf, _index, _sz);
+    assert(_index % sizeof(void*) == 0, "invariant");
+    assert(_sz % sizeof(void*) == 0, "invariant");
+    assert(_index <= _sz, "invariant");
+    cl->do_buffer(_buf + byte_index_to_index((int)_index),
+                  byte_index_to_index((int)(_sz - _index)));
     _index = _sz;
   }
 }
 
-void ObjPtrQueue::apply_closure_to_buffer(ObjectClosure* cl,
-                                          void** buf, size_t index, size_t sz) {
-  if (cl == NULL) return;
-  for (size_t i = index; i < sz; i += oopSize) {
-    oop obj = (oop)buf[byte_index_to_index((int)i)];
-    // There can be NULL entries because of destructors.
-    if (obj != NULL) {
-      cl->do_object(obj);
-    }
-  }
-}
-
 #ifndef PRODUCT
 // Helpful for debugging
 
@@ -289,7 +281,7 @@
   shared_satb_queue()->filter();
 }
 
-bool SATBMarkQueueSet::apply_closure_to_completed_buffer(ObjectClosure* cl) {
+bool SATBMarkQueueSet::apply_closure_to_completed_buffer(SATBBufferClosure* cl) {
   BufferNode* nd = NULL;
   {
     MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
@@ -303,7 +295,18 @@
   }
   if (nd != NULL) {
     void **buf = BufferNode::make_buffer_from_node(nd);
-    ObjPtrQueue::apply_closure_to_buffer(cl, buf, 0, _sz);
+    // Skip over NULL entries at beginning (e.g. push end) of buffer.
+    // Filtering can result in non-full completed buffers; see
+    // should_enqueue_buffer.
+    assert(_sz % sizeof(void*) == 0, "invariant");
+    size_t limit = ObjPtrQueue::byte_index_to_index((int)_sz);
+    for (size_t i = 0; i < limit; ++i) {
+      if (buf[i] != NULL) {
+        // Found the end of the block of NULLs; process the remainder.
+        cl->do_buffer(buf + i, limit - i);
+        break;
+      }
+    }
     deallocate_buffer(buf);
     return true;
   } else {
--- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp	Fri May 08 13:25:11 2015 -0400
@@ -25,29 +25,30 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_SATBQUEUE_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_G1_SATBQUEUE_HPP
 
+#include "memory/allocation.hpp"
 #include "gc_implementation/g1/ptrQueue.hpp"
 
-class ObjectClosure;
 class JavaThread;
 class SATBMarkQueueSet;
 
+// Base class for processing the contents of a SATB buffer.
+class SATBBufferClosure : public StackObj {
+protected:
+  ~SATBBufferClosure() { }
+
+public:
+  // Process the SATB entries in the designated buffer range.
+  virtual void do_buffer(void** buffer, size_t size) = 0;
+};
+
 // A ptrQueue whose elements are "oops", pointers to object heads.
 class ObjPtrQueue: public PtrQueue {
-  friend class Threads;
   friend class SATBMarkQueueSet;
-  friend class G1RemarkThreadsClosure;
 
 private:
   // Filter out unwanted entries from the buffer.
   void filter();
 
-  // Apply the closure to all elements and empty the buffer;
-  void apply_closure_and_empty(ObjectClosure* cl);
-
-  // Apply the closure to all elements of "buf", down to "index" (inclusive.)
-  static void apply_closure_to_buffer(ObjectClosure* cl,
-                                      void** buf, size_t index, size_t sz);
-
 public:
   ObjPtrQueue(PtrQueueSet* qset, bool perm = false) :
     // SATB queues are only active during marking cycles. We create
@@ -60,6 +61,10 @@
   // Process queue entries and free resources.
   void flush();
 
+  // Apply cl to the active part of the buffer.
+  // Prerequisite: Must be at a safepoint.
+  void apply_closure_and_empty(SATBBufferClosure* cl);
+
   // Overrides PtrQueue::should_enqueue_buffer(). See the method's
   // definition for more information.
   virtual bool should_enqueue_buffer();
@@ -97,10 +102,12 @@
   // Filter all the currently-active SATB buffers.
   void filter_thread_buffers();
 
-  // If there exists some completed buffer, pop it, then apply the
-  // closure to all its elements, and return true.  If no
-  // completed buffers exist, return false.
-  bool apply_closure_to_completed_buffer(ObjectClosure* closure);
+  // If there exists some completed buffer, pop and process it, and
+  // return true.  Otherwise return false.  Processing a buffer
+  // consists of applying the closure to the buffer range starting
+  // with the first non-NULL entry to the end of the buffer; the
+  // leading entries may be NULL due to filtering.
+  bool apply_closure_to_completed_buffer(SATBBufferClosure* cl);
 
 #ifndef PRODUCT
   // Helpful for debugging
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Fri May 08 13:25:11 2015 -0400
@@ -54,6 +54,7 @@
 #include "utilities/copy.hpp"
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/stack.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
 #include "utilities/workgroup.hpp"
 
 #ifdef _MSC_VER
@@ -272,16 +273,8 @@
 }
 
 
-void ParScanThreadState::undo_alloc_in_to_space(HeapWord* obj,
-                                                size_t word_sz) {
-  // Is the alloc in the current alloc buffer?
-  if (to_space_alloc_buffer()->contains(obj)) {
-    assert(to_space_alloc_buffer()->contains(obj + word_sz - 1),
-           "Should contain whole object.");
-    to_space_alloc_buffer()->undo_allocation(obj, word_sz);
-  } else {
-    CollectedHeap::fill_with_object(obj, word_sz);
-  }
+void ParScanThreadState::undo_alloc_in_to_space(HeapWord* obj, size_t word_sz) {
+  to_space_alloc_buffer()->undo_allocation(obj, word_sz);
 }
 
 void ParScanThreadState::print_promotion_failure_size() {
@@ -308,7 +301,7 @@
   inline ParScanThreadState& thread_state(int i);
 
   void trace_promotion_failed(const YoungGCTracer* gc_tracer);
-  void reset(int active_workers, bool promotion_failed);
+  void reset(uint active_workers, bool promotion_failed);
   void flush();
 
   #if TASKQUEUE_STATS
@@ -365,7 +358,7 @@
   }
 }
 
-void ParScanThreadStateSet::reset(int active_threads, bool promotion_failed)
+void ParScanThreadStateSet::reset(uint active_threads, bool promotion_failed)
 {
   _term.reset_for_reuse(active_threads);
   if (promotion_failed) {
@@ -583,7 +576,7 @@
 
 // Reset the terminator for the given number of
 // active threads.
-void ParNewGenTask::set_for_termination(int active_workers) {
+void ParNewGenTask::set_for_termination(uint active_workers) {
   _state_set->reset(active_workers, _gen->promotion_failed());
   // Should the heap be passed in?  There's only 1 for now so
   // grab it instead.
@@ -766,7 +759,7 @@
 
 private:
   virtual void work(uint worker_id);
-  virtual void set_for_termination(int active_workers) {
+  virtual void set_for_termination(uint active_workers) {
     _state_set.terminator()->reset_for_reuse(active_workers);
   }
 private:
@@ -912,10 +905,10 @@
   AdaptiveSizePolicy* size_policy = gch->gen_policy()->size_policy();
   FlexibleWorkGang* workers = gch->workers();
   assert(workers != NULL, "Need workgang for parallel work");
-  int active_workers =
-      AdaptiveSizePolicy::calc_active_workers(workers->total_workers(),
-                                   workers->active_workers(),
-                                   Threads::number_of_non_daemon_threads());
+  uint active_workers =
+       AdaptiveSizePolicy::calc_active_workers(workers->total_workers(),
+                                               workers->active_workers(),
+                                               Threads::number_of_non_daemon_threads());
   workers->set_active_workers(active_workers);
   _old_gen = gch->old_gen();
 
@@ -947,7 +940,7 @@
 
   gch->save_marks();
   assert(workers != NULL, "Need parallel worker threads.");
-  int n_workers = active_workers;
+  uint n_workers = active_workers;
 
   // Set the correct parallelism (number of queues) in the reference processor
   ref_processor()->set_active_mt_degree(n_workers);
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp	Fri May 08 13:25:11 2015 -0400
@@ -250,7 +250,7 @@
 
   // Reset the terminator in ParScanThreadStateSet for
   // "active_workers" threads.
-  virtual void set_for_termination(int active_workers);
+  virtual void set_for_termination(uint active_workers);
 };
 
 class KeepAliveClosure: public DefNewGeneration::KeepAliveClosure {
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp	Fri May 08 13:25:11 2015 -0400
@@ -57,7 +57,7 @@
   ParCompactionManager* cm =
     ParCompactionManager::gc_thread_compaction_manager(which);
 
-  PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
+  ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm);
   CLDToOopClosure mark_and_push_from_clds(&mark_and_push_closure, true);
   MarkingCodeBlobClosure mark_and_push_in_blobs(&mark_and_push_closure, !CodeBlobToOopClosure::FixRelocations);
 
@@ -85,8 +85,8 @@
     PrintGCDetails && TraceParallelOldGCTasks, true, NULL, PSParallelCompact::gc_tracer()->gc_id()));
   ParCompactionManager* cm =
     ParCompactionManager::gc_thread_compaction_manager(which);
-  PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
-  PSParallelCompact::FollowKlassClosure follow_klass_closure(&mark_and_push_closure);
+  ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm);
+  ParCompactionManager::FollowKlassClosure follow_klass_closure(&mark_and_push_closure);
 
   switch (_root_type) {
     case universe:
@@ -156,8 +156,8 @@
     PrintGCDetails && TraceParallelOldGCTasks, true, NULL, PSParallelCompact::gc_tracer()->gc_id()));
   ParCompactionManager* cm =
     ParCompactionManager::gc_thread_compaction_manager(which);
-  PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
-  PSParallelCompact::FollowStackClosure follow_stack_closure(cm);
+  ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm);
+  ParCompactionManager::FollowStackClosure follow_stack_closure(cm);
   _rp_task.work(_work_id, *PSParallelCompact::is_alive_closure(),
                 mark_and_push_closure, follow_stack_closure);
 }
@@ -213,7 +213,7 @@
 
   ParCompactionManager* cm =
     ParCompactionManager::gc_thread_compaction_manager(which);
-  PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
+  ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm);
 
   oop obj = NULL;
   ObjArrayTask task;
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp	Fri May 08 13:25:11 2015 -0400
@@ -37,7 +37,7 @@
 #include "oops/objArrayKlass.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/atomic.inline.hpp"
-#include "utilities/stack.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
 
 PSOldGen*            ParCompactionManager::_old_gen = NULL;
 ParCompactionManager**  ParCompactionManager::_manager_array = NULL;
@@ -179,11 +179,11 @@
 void InstanceKlass::oop_pc_follow_contents(oop obj, ParCompactionManager* cm) {
   assert(obj != NULL, "can't follow the content of NULL object");
 
-  PSParallelCompact::follow_klass(cm, this);
+  cm->follow_klass(this);
   // Only mark the header and let the scan of the meta-data mark
   // everything else.
 
-  PSParallelCompact::MarkAndPushClosure cl(cm);
+  ParCompactionManager::MarkAndPushClosure cl(cm);
   InstanceKlass::oop_oop_iterate_oop_maps<true>(obj, &cl);
 }
 
@@ -201,9 +201,9 @@
     // the call to follow_class_loader is made when the class loader itself
     // is handled.
     if (klass->oop_is_instance() && InstanceKlass::cast(klass)->is_anonymous()) {
-      PSParallelCompact::follow_class_loader(cm, klass->class_loader_data());
+      cm->follow_class_loader(klass->class_loader_data());
     } else {
-      PSParallelCompact::follow_klass(cm, klass);
+      cm->follow_klass(klass);
     }
   } else {
     // If klass is NULL then this a mirror for a primitive type.
@@ -212,7 +212,7 @@
     assert(java_lang_Class::is_primitive(obj), "Sanity check");
   }
 
-  PSParallelCompact::MarkAndPushClosure cl(cm);
+  ParCompactionManager::MarkAndPushClosure cl(cm);
   oop_oop_iterate_statics<true>(obj, &cl);
 }
 
@@ -221,7 +221,7 @@
 
   ClassLoaderData * const loader_data = java_lang_ClassLoader::loader_data(obj);
   if (loader_data != NULL) {
-    PSParallelCompact::follow_class_loader(cm, loader_data);
+    cm->follow_class_loader(loader_data);
   }
 }
 
@@ -253,37 +253,24 @@
           gclog_or_tty->print_cr("       Non NULL normal " PTR_FORMAT, p2i(obj));
         }
       )
-      PSParallelCompact::mark_and_push(cm, referent_addr);
+      cm->mark_and_push(referent_addr);
     }
   }
   T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
-  if (ReferenceProcessor::pending_list_uses_discovered_field()) {
-    // Treat discovered as normal oop, if ref is not "active",
-    // i.e. if next is non-NULL.
-    T  next_oop = oopDesc::load_heap_oop(next_addr);
-    if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
-      T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
-      debug_only(
-        if(TraceReferenceGC && PrintGCDetails) {
-          gclog_or_tty->print_cr("   Process discovered as normal "
-                                 PTR_FORMAT, p2i(discovered_addr));
-        }
-      )
-      PSParallelCompact::mark_and_push(cm, discovered_addr);
-    }
-  } else {
-#ifdef ASSERT
-    // In the case of older JDKs which do not use the discovered
-    // field for the pending list, an inactive ref (next != NULL)
-    // must always have a NULL discovered field.
-    T next = oopDesc::load_heap_oop(next_addr);
-    oop discovered = java_lang_ref_Reference::discovered(obj);
-    assert(oopDesc::is_null(next) || oopDesc::is_null(discovered),
-           err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field",
-                   p2i(obj)));
-#endif
+  // Treat discovered as normal oop, if ref is not "active",
+  // i.e. if next is non-NULL.
+  T  next_oop = oopDesc::load_heap_oop(next_addr);
+  if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
+    T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
+    debug_only(
+      if(TraceReferenceGC && PrintGCDetails) {
+        gclog_or_tty->print_cr("   Process discovered as normal "
+                               PTR_FORMAT, p2i(discovered_addr));
+      }
+    )
+    cm->mark_and_push(discovered_addr);
   }
-  PSParallelCompact::mark_and_push(cm, next_addr);
+  cm->mark_and_push(next_addr);
   klass->InstanceKlass::oop_pc_follow_contents(obj, cm);
 }
 
@@ -297,7 +284,7 @@
 }
 
 void ObjArrayKlass::oop_pc_follow_contents(oop obj, ParCompactionManager* cm) {
-  PSParallelCompact::follow_klass(cm, this);
+  cm->follow_klass(this);
 
   if (UseCompressedOops) {
     oop_pc_follow_contents_specialized<narrowOop>(objArrayOop(obj), 0, cm);
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp	Fri May 08 13:25:11 2015 -0400
@@ -29,11 +29,6 @@
 #include "utilities/stack.hpp"
 #include "utilities/taskqueue.hpp"
 
-// Move to some global location
-#define HAS_BEEN_MOVED 0x1501d01d
-// End move to some global location
-
-
 class MutableSpace;
 class PSOldGen;
 class ParCompactionManager;
@@ -170,24 +165,23 @@
   bool should_copy();
 
   // Save for later processing.  Must not fail.
-  inline void push(oop obj) { _marking_stack.push(obj); }
+  inline void push(oop obj);
   inline void push_objarray(oop objarray, size_t index);
   inline void push_region(size_t index);
 
+  // Check mark and maybe push on marking stack.
+  template <typename T> inline void mark_and_push(T* p);
+
+  inline void follow_klass(Klass* klass);
+
+  void follow_class_loader(ClassLoaderData* klass);
+
   // Access function for compaction managers
   static ParCompactionManager* gc_thread_compaction_manager(int index);
 
-  static bool steal(int queue_num, int* seed, oop& t) {
-    return stack_array()->steal(queue_num, seed, t);
-  }
-
-  static bool steal_objarray(int queue_num, int* seed, ObjArrayTask& t) {
-    return _objarray_queues->steal(queue_num, seed, t);
-  }
-
-  static bool steal(int queue_num, int* seed, size_t& region) {
-    return region_array()->steal(queue_num, seed, region);
-  }
+  static bool steal(int queue_num, int* seed, oop& t);
+  static bool steal_objarray(int queue_num, int* seed, ObjArrayTask& t);
+  static bool steal(int queue_num, int* seed, size_t& region);
 
   // Process tasks remaining on any marking stack
   void follow_marking_stacks();
@@ -200,6 +194,39 @@
   void follow_contents(objArrayOop array, int index);
 
   void update_contents(oop obj);
+
+  class MarkAndPushClosure: public ExtendedOopClosure {
+   private:
+    ParCompactionManager* _compaction_manager;
+   public:
+    MarkAndPushClosure(ParCompactionManager* cm) : _compaction_manager(cm) { }
+
+    template <typename T> void do_oop_nv(T* p);
+    virtual void do_oop(oop* p);
+    virtual void do_oop(narrowOop* p);
+
+    // This closure provides its own oop verification code.
+    debug_only(virtual bool should_verify_oops() { return false; })
+  };
+
+  class FollowStackClosure: public VoidClosure {
+   private:
+    ParCompactionManager* _compaction_manager;
+   public:
+    FollowStackClosure(ParCompactionManager* cm) : _compaction_manager(cm) { }
+    virtual void do_void();
+  };
+
+  // The one and only place to start following the classes.
+  // Should only be applied to the ClassLoaderData klasses list.
+  class FollowKlassClosure : public KlassClosure {
+   private:
+    MarkAndPushClosure* _mark_and_push_closure;
+   public:
+    FollowKlassClosure(MarkAndPushClosure* mark_and_push_closure) :
+        _mark_and_push_closure(mark_and_push_closure) { }
+    void do_klass(Klass* klass);
+  };
 };
 
 inline ParCompactionManager* ParCompactionManager::manager_array(int index) {
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.inline.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.inline.hpp	Fri May 08 13:25:11 2015 -0400
@@ -31,6 +31,23 @@
 #include "oops/oop.inline.hpp"
 #include "utilities/debug.hpp"
 #include "utilities/globalDefinitions.hpp"
+#include "utilities/taskqueue.inline.hpp"
+
+inline bool ParCompactionManager::steal(int queue_num, int* seed, oop& t) {
+  return stack_array()->steal(queue_num, seed, t);
+}
+
+inline bool ParCompactionManager::steal_objarray(int queue_num, int* seed, ObjArrayTask& t) {
+  return _objarray_queues->steal(queue_num, seed, t);
+}
+
+inline bool ParCompactionManager::steal(int queue_num, int* seed, size_t& region) {
+  return region_array()->steal(queue_num, seed, region);
+}
+
+inline void ParCompactionManager::push(oop obj) {
+  _marking_stack.push(obj);
+}
 
 void ParCompactionManager::push_objarray(oop obj, size_t index)
 {
@@ -50,6 +67,47 @@
   region_stack()->push(index);
 }
 
+template <typename T>
+inline void ParCompactionManager::mark_and_push(T* p) {
+  T heap_oop = oopDesc::load_heap_oop(p);
+  if (!oopDesc::is_null(heap_oop)) {
+    oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
+    assert(ParallelScavengeHeap::heap()->is_in(obj), "should be in heap");
+
+    if (mark_bitmap()->is_unmarked(obj) && PSParallelCompact::mark_obj(obj)) {
+      push(obj);
+    }
+  }
+}
+
+template <typename T>
+inline void ParCompactionManager::MarkAndPushClosure::do_oop_nv(T* p) {
+  _compaction_manager->mark_and_push(p);
+}
+
+inline void ParCompactionManager::MarkAndPushClosure::do_oop(oop* p)       { do_oop_nv(p); }
+inline void ParCompactionManager::MarkAndPushClosure::do_oop(narrowOop* p) { do_oop_nv(p); }
+
+inline void ParCompactionManager::follow_klass(Klass* klass) {
+  oop holder = klass->klass_holder();
+  mark_and_push(&holder);
+}
+
+inline void ParCompactionManager::FollowStackClosure::do_void() {
+  _compaction_manager->follow_marking_stacks();
+}
+
+inline void ParCompactionManager::FollowKlassClosure::do_klass(Klass* klass) {
+  klass->oops_do(_mark_and_push_closure);
+}
+
+inline void ParCompactionManager::follow_class_loader(ClassLoaderData* cld) {
+  MarkAndPushClosure mark_and_push_closure(this);
+  FollowKlassClosure follow_klass_closure(&mark_and_push_closure);
+
+  cld->oops_do(&mark_and_push_closure, &follow_klass_closure, true);
+}
+
 inline void ParCompactionManager::follow_contents(oop obj) {
   assert(PSParallelCompact::mark_bitmap()->is_marked(obj), "should be marked");
   obj->pc_follow_contents(this);
@@ -69,7 +127,7 @@
 
   // Push the non-NULL elements of the next stride on the marking stack.
   for (T* e = beg; e < end; e++) {
-    PSParallelCompact::mark_and_push<T>(cm, e);
+    cm->mark_and_push<T>(e);
   }
 
   if (end_index < len) {
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Fri May 08 13:25:11 2015 -0400
@@ -108,7 +108,6 @@
 bool      PSParallelCompact::_print_phases = false;
 
 ReferenceProcessor* PSParallelCompact::_ref_processor = NULL;
-Klass*              PSParallelCompact::_updated_int_array_klass_obj = NULL;
 
 double PSParallelCompact::_dwl_mean;
 double PSParallelCompact::_dwl_std_dev;
@@ -820,17 +819,9 @@
 
 bool PSParallelCompact::IsAliveClosure::do_object_b(oop p) { return mark_bitmap()->is_marked(p); }
 
-void PSParallelCompact::KeepAliveClosure::do_oop(oop* p)       { PSParallelCompact::KeepAliveClosure::do_oop_work(p); }
-void PSParallelCompact::KeepAliveClosure::do_oop(narrowOop* p) { PSParallelCompact::KeepAliveClosure::do_oop_work(p); }
-
 PSParallelCompact::AdjustPointerClosure PSParallelCompact::_adjust_pointer_closure;
 PSParallelCompact::AdjustKlassClosure PSParallelCompact::_adjust_klass_closure;
 
-void PSParallelCompact::FollowStackClosure::do_void() { _compaction_manager->follow_marking_stacks(); }
-
-void PSParallelCompact::FollowKlassClosure::do_klass(Klass* klass) {
-  klass->oops_do(_mark_and_push_closure);
-}
 void PSParallelCompact::AdjustKlassClosure::do_klass(Klass* klass) {
   klass->oops_do(&PSParallelCompact::_adjust_pointer_closure);
 }
@@ -2350,8 +2341,8 @@
   TaskQueueSetSuper* qset = ParCompactionManager::region_array();
   ParallelTaskTerminator terminator(active_gc_threads, qset);
 
-  PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
-  PSParallelCompact::FollowStackClosure follow_stack_closure(cm);
+  ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm);
+  ParCompactionManager::FollowStackClosure follow_stack_closure(cm);
 
   // Need new claim bits before marking starts.
   ClassLoaderDataGraph::clear_claimed_marks();
@@ -2425,14 +2416,6 @@
   _gc_tracer.report_object_count_after_gc(is_alive_closure());
 }
 
-void PSParallelCompact::follow_class_loader(ParCompactionManager* cm,
-                                            ClassLoaderData* cld) {
-  PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
-  PSParallelCompact::FollowKlassClosure follow_klass_closure(&mark_and_push_closure);
-
-  cld->oops_do(&mark_and_push_closure, &follow_klass_closure, true);
-}
-
 // This should be moved to the shared markSweep code!
 class PSAlwaysTrueClosure: public BoolObjectClosure {
 public:
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp	Fri May 08 13:25:11 2015 -0400
@@ -28,7 +28,6 @@
 #include "gc_implementation/parallelScavenge/objectStartArray.hpp"
 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
 #include "gc_implementation/parallelScavenge/parMarkBitMap.hpp"
-#include "gc_implementation/parallelScavenge/psCompactionManager.hpp"
 #include "gc_implementation/shared/collectorCounters.hpp"
 #include "gc_implementation/shared/mutableSpace.hpp"
 #include "gc_interface/collectedHeap.hpp"
@@ -933,25 +932,6 @@
     virtual bool do_object_b(oop p);
   };
 
-  class KeepAliveClosure: public OopClosure {
-   private:
-    ParCompactionManager* _compaction_manager;
-   protected:
-    template <class T> inline void do_oop_work(T* p);
-   public:
-    KeepAliveClosure(ParCompactionManager* cm) : _compaction_manager(cm) { }
-    virtual void do_oop(oop* p);
-    virtual void do_oop(narrowOop* p);
-  };
-
-  class FollowStackClosure: public VoidClosure {
-   private:
-    ParCompactionManager* _compaction_manager;
-   public:
-    FollowStackClosure(ParCompactionManager* cm) : _compaction_manager(cm) { }
-    virtual void do_void();
-  };
-
   class AdjustPointerClosure: public ExtendedOopClosure {
    public:
     template <typename T> void do_oop_nv(T* p);
@@ -967,12 +947,8 @@
     void do_klass(Klass* klass);
   };
 
-  friend class KeepAliveClosure;
-  friend class FollowStackClosure;
   friend class AdjustPointerClosure;
   friend class AdjustKlassClosure;
-  friend class FollowKlassClosure;
-  friend class InstanceClassLoaderKlass;
   friend class RefProcTaskProxy;
 
  private:
@@ -994,9 +970,6 @@
   // Reference processing (used in ...follow_contents)
   static ReferenceProcessor*  _ref_processor;
 
-  // Updated location of intArrayKlassObj.
-  static Klass* _updated_int_array_klass_obj;
-
   // Values computed at initialization and used by dead_wood_limiter().
   static double _dwl_mean;
   static double _dwl_std_dev;
@@ -1142,30 +1115,6 @@
   static void reset_millis_since_last_gc();
 
  public:
-  class MarkAndPushClosure: public ExtendedOopClosure {
-   private:
-    ParCompactionManager* _compaction_manager;
-   public:
-    MarkAndPushClosure(ParCompactionManager* cm) : _compaction_manager(cm) { }
-
-    template <typename T> void do_oop_nv(T* p);
-    virtual void do_oop(oop* p);
-    virtual void do_oop(narrowOop* p);
-
-    // This closure provides its own oop verification code.
-    debug_only(virtual bool should_verify_oops() { return false; })
-  };
-
-  // The one and only place to start following the classes.
-  // Should only be applied to the ClassLoaderData klasses list.
-  class FollowKlassClosure : public KlassClosure {
-   private:
-    MarkAndPushClosure* _mark_and_push_closure;
-   public:
-    FollowKlassClosure(MarkAndPushClosure* mark_and_push_closure) :
-        _mark_and_push_closure(mark_and_push_closure) { }
-    void do_klass(Klass* klass);
-  };
 
   PSParallelCompact();
 
@@ -1193,23 +1142,13 @@
 
   // Used to add tasks
   static GCTaskManager* const gc_task_manager();
-  static Klass* updated_int_array_klass_obj() {
-    return _updated_int_array_klass_obj;
-  }
 
   // Marking support
   static inline bool mark_obj(oop obj);
   static inline bool is_marked(oop obj);
-  // Check mark and maybe push on marking stack
-  template <class T> static inline void mark_and_push(ParCompactionManager* cm,
-                                                      T* p);
+
   template <class T> static inline void adjust_pointer(T* p);
 
-  static inline void follow_klass(ParCompactionManager* cm, Klass* klass);
-
-  static void follow_class_loader(ParCompactionManager* cm,
-                                  ClassLoaderData* klass);
-
   // Compaction support.
   // Return true if p is in the range [beg_addr, end_addr).
   static inline bool is_in(HeapWord* p, HeapWord* beg_addr, HeapWord* end_addr);
@@ -1337,11 +1276,6 @@
   return mark_bitmap()->is_marked(obj);
 }
 
-template <class T>
-inline void PSParallelCompact::KeepAliveClosure::do_oop_work(T* p) {
-  mark_and_push(_compaction_manager, p);
-}
-
 inline bool PSParallelCompact::print_phases() {
   return _print_phases;
 }
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.inline.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.inline.hpp	Fri May 08 13:25:11 2015 -0400
@@ -26,38 +26,11 @@
 #define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPARALLELCOMPACT_INLINE_HPP
 
 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
-#include "gc_implementation/parallelScavenge/psCompactionManager.hpp"
 #include "gc_implementation/parallelScavenge/psParallelCompact.hpp"
 #include "gc_interface/collectedHeap.hpp"
 #include "oops/klass.hpp"
 #include "oops/oop.inline.hpp"
 
-template <typename T>
-inline void PSParallelCompact::mark_and_push(ParCompactionManager* cm, T* p) {
-  T heap_oop = oopDesc::load_heap_oop(p);
-  if (!oopDesc::is_null(heap_oop)) {
-    oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
-    assert(ParallelScavengeHeap::heap()->is_in(obj), "should be in heap");
-
-    if (mark_bitmap()->is_unmarked(obj) && mark_obj(obj)) {
-      cm->push(obj);
-    }
-  }
-}
-
-template <typename T>
-inline void PSParallelCompact::MarkAndPushClosure::do_oop_nv(T* p) {
-  mark_and_push(_compaction_manager, p);
-}
-
-inline void PSParallelCompact::MarkAndPushClosure::do_oop(oop* p)       { do_oop_nv(p); }
-inline void PSParallelCompact::MarkAndPushClosure::do_oop(narrowOop* p) { do_oop_nv(p); }
-
-inline void PSParallelCompact::follow_klass(ParCompactionManager* cm, Klass* klass) {
-  oop holder = klass->klass_holder();
-  mark_and_push(cm, &holder);
-}
-
 template <class T>
 inline void PSParallelCompact::adjust_pointer(T* p) {
   T heap_oop = oopDesc::load_heap_oop(p);
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp	Fri May 08 13:25:11 2015 -0400
@@ -36,7 +36,7 @@
 #include "oops/instanceMirrorKlass.inline.hpp"
 #include "oops/objArrayKlass.inline.hpp"
 #include "oops/oop.inline.hpp"
-#include "utilities/stack.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
 
 PaddedEnd<PSPromotionManager>* PSPromotionManager::_manager_array = NULL;
 OopStarTaskQueueSet*           PSPromotionManager::_stack_array_depth = NULL;
@@ -365,33 +365,19 @@
   // Treat discovered as normal oop, if ref is not "active",
   // i.e. if next is non-NULL.
   T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
-  if (ReferenceProcessor::pending_list_uses_discovered_field()) {
-    T  next_oop = oopDesc::load_heap_oop(next_addr);
-    if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
-      T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
-      debug_only(
-        if(TraceReferenceGC && PrintGCDetails) {
-          gclog_or_tty->print_cr("   Process discovered as normal "
-                                 PTR_FORMAT, p2i(discovered_addr));
-        }
-      )
-      if (PSScavenge::should_scavenge(discovered_addr)) {
-        pm->claim_or_forward_depth(discovered_addr);
+  T  next_oop = oopDesc::load_heap_oop(next_addr);
+  if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
+    T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
+    debug_only(
+      if(TraceReferenceGC && PrintGCDetails) {
+        gclog_or_tty->print_cr("   Process discovered as normal "
+                               PTR_FORMAT, p2i(discovered_addr));
       }
+    )
+    if (PSScavenge::should_scavenge(discovered_addr)) {
+      pm->claim_or_forward_depth(discovered_addr);
     }
-  } else {
-#ifdef ASSERT
-    // In the case of older JDKs which do not use the discovered
-    // field for the pending list, an inactive ref (next != NULL)
-    // must always have a NULL discovered field.
-    oop next = oopDesc::load_decode_heap_oop(next_addr);
-    oop discovered = java_lang_ref_Reference::discovered(obj);
-    assert(oopDesc::is_null(next) || oopDesc::is_null(discovered),
-           err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field",
-                   p2i(obj)));
-#endif
   }
-
   // Treat next as normal oop;  next is a link in the reference queue.
   if (PSScavenge::should_scavenge(next_addr)) {
     pm->claim_or_forward_depth(next_addr);
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp	Fri May 08 13:25:11 2015 -0400
@@ -45,10 +45,6 @@
 // FIX ME FIX ME Add a destructor, and don't rely on the user to drain/flush/deallocate!
 //
 
-// Move to some global location
-#define HAS_BEEN_MOVED 0x1501d01d
-// End move to some global location
-
 class MutableSpace;
 class PSOldGen;
 class ParCompactionManager;
@@ -143,9 +139,7 @@
                                                     int start, int end);
   void process_array_chunk(oop old);
 
-  template <class T> void push_depth(T* p) {
-    claimed_stack_depth()->push(p);
-  }
+  template <class T> void push_depth(T* p);
 
   inline void promotion_trace_event(oop new_obj, oop old_obj, size_t obj_size,
                                     uint age, bool tenured,
@@ -163,9 +157,7 @@
   static PSPromotionManager* gc_thread_promotion_manager(int index);
   static PSPromotionManager* vm_thread_promotion_manager();
 
-  static bool steal_depth(int queue_num, int* seed, StarTask& t) {
-    return stack_array_depth()->steal(queue_num, seed, t);
-  }
+  static bool steal_depth(int queue_num, int* seed, StarTask& t);
 
   PSPromotionManager();
 
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp	Fri May 08 13:25:11 2015 -0400
@@ -31,6 +31,7 @@
 #include "gc_implementation/parallelScavenge/psPromotionLAB.inline.hpp"
 #include "gc_implementation/parallelScavenge/psScavenge.hpp"
 #include "oops/oop.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
 
 inline PSPromotionManager* PSPromotionManager::manager_array(int index) {
   assert(_manager_array != NULL, "access of NULL manager_array");
@@ -39,6 +40,11 @@
 }
 
 template <class T>
+inline void PSPromotionManager::push_depth(T* p) {
+  claimed_stack_depth()->push(p);
+}
+
+template <class T>
 inline void PSPromotionManager::claim_or_forward_internal_depth(T* p) {
   if (p != NULL) { // XXX: error if p != NULL here
     oop o = oopDesc::load_decode_heap_oop_not_null(p);
@@ -99,7 +105,7 @@
 // performance.
 //
 template<bool promote_immediately>
-oop PSPromotionManager::copy_to_survivor_space(oop o) {
+inline oop PSPromotionManager::copy_to_survivor_space(oop o) {
   assert(should_scavenge(&o), "Sanity");
 
   oop new_obj = NULL;
@@ -317,6 +323,10 @@
   }
 }
 
+inline bool PSPromotionManager::steal_depth(int queue_num, int* seed, StarTask& t) {
+  return stack_array_depth()->steal(queue_num, seed, t);
+}
+
 #if TASKQUEUE_STATS
 void PSPromotionManager::record_steal(StarTask& p) {
   if (is_oop_masked(p)) {
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp	Fri May 08 13:25:11 2015 -0400
@@ -39,8 +39,7 @@
 #include "runtime/thread.hpp"
 #include "runtime/vmThread.hpp"
 #include "services/management.hpp"
-#include "utilities/stack.inline.hpp"
-#include "utilities/taskqueue.hpp"
+#include "utilities/taskqueue.inline.hpp"
 
 //
 // ScavengeRootsTask
--- a/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -97,10 +97,10 @@
 //    Calculate the number of GC threads based on the size of the heap.
 //    Use the larger.
 
-int AdaptiveSizePolicy::calc_default_active_workers(uintx total_workers,
-                                            const uintx min_workers,
-                                            uintx active_workers,
-                                            uintx application_workers) {
+uint AdaptiveSizePolicy::calc_default_active_workers(uintx total_workers,
+                                                     const uintx min_workers,
+                                                     uintx active_workers,
+                                                     uintx application_workers) {
   // If the user has specifically set the number of
   // GC threads, use them.
 
@@ -178,9 +178,9 @@
   return new_active_workers;
 }
 
-int AdaptiveSizePolicy::calc_active_workers(uintx total_workers,
-                                            uintx active_workers,
-                                            uintx application_workers) {
+uint AdaptiveSizePolicy::calc_active_workers(uintx total_workers,
+                                             uintx active_workers,
+                                             uintx application_workers) {
   // If the user has specifically set the number of
   // GC threads, use them.
 
@@ -188,13 +188,14 @@
   // or the users has requested a specific number, set the active
   // number of workers to all the workers.
 
-  int new_active_workers;
+  uint new_active_workers;
   if (!UseDynamicNumberOfGCThreads ||
      (!FLAG_IS_DEFAULT(ParallelGCThreads) && !ForceDynamicNumberOfGCThreads)) {
     new_active_workers = total_workers;
   } else {
+    uintx min_workers = (total_workers == 1) ? 1 : 2;
     new_active_workers = calc_default_active_workers(total_workers,
-                                                     2, /* Minimum number of workers */
+                                                     min_workers,
                                                      active_workers,
                                                      application_workers);
   }
@@ -202,18 +203,17 @@
   return new_active_workers;
 }
 
-int AdaptiveSizePolicy::calc_active_conc_workers(uintx total_workers,
-                                                 uintx active_workers,
-                                                 uintx application_workers) {
+uint AdaptiveSizePolicy::calc_active_conc_workers(uintx total_workers,
+                                                  uintx active_workers,
+                                                  uintx application_workers) {
   if (!UseDynamicNumberOfGCThreads ||
      (!FLAG_IS_DEFAULT(ConcGCThreads) && !ForceDynamicNumberOfGCThreads)) {
     return ConcGCThreads;
   } else {
-    int no_of_gc_threads = calc_default_active_workers(
-                             total_workers,
-                             1, /* Minimum number of workers */
-                             active_workers,
-                             application_workers);
+    uint no_of_gc_threads = calc_default_active_workers(total_workers,
+                                                        1, /* Minimum number of workers */
+                                                        active_workers,
+                                                        application_workers);
     return no_of_gc_threads;
   }
 }
--- a/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.hpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -343,10 +343,10 @@
                      uint gc_cost_ratio);
 
   // Return number default  GC threads to use in the next GC.
-  static int calc_default_active_workers(uintx total_workers,
-                                         const uintx min_workers,
-                                         uintx active_workers,
-                                         uintx application_workers);
+  static uint calc_default_active_workers(uintx total_workers,
+                                          const uintx min_workers,
+                                          uintx active_workers,
+                                          uintx application_workers);
 
   // Return number of GC threads to use in the next GC.
   // This is called sparingly so as not to change the
@@ -358,14 +358,14 @@
   // GC workers from the calls above.  For example,
   // a CMS parallel remark uses the same number of GC
   // workers as the most recent ParNew collection.
-  static int calc_active_workers(uintx total_workers,
-                                 uintx active_workers,
-                                 uintx application_workers);
+  static uint calc_active_workers(uintx total_workers,
+                                  uintx active_workers,
+                                  uintx application_workers);
 
   // Return number of GC threads to use in the next concurrent GC phase.
-  static int calc_active_conc_workers(uintx total_workers,
-                                      uintx active_workers,
-                                      uintx application_workers);
+  static uint calc_active_conc_workers(uintx total_workers,
+                                       uintx active_workers,
+                                       uintx application_workers);
 
   bool is_gc_cms_adaptive_size_policy() {
     return kind() == _gc_cms_adaptive_size_policy;
--- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp	Fri May 08 13:25:11 2015 -0400
@@ -145,31 +145,18 @@
     }
   }
   T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
-  if (ReferenceProcessor::pending_list_uses_discovered_field()) {
-    // Treat discovered as normal oop, if ref is not "active",
-    // i.e. if next is non-NULL.
-    T  next_oop = oopDesc::load_heap_oop(next_addr);
-    if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
-      T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
-      debug_only(
-        if(TraceReferenceGC && PrintGCDetails) {
-          gclog_or_tty->print_cr("   Process discovered as normal "
-                                 PTR_FORMAT, p2i(discovered_addr));
-        }
-      )
-      MarkSweep::mark_and_push(discovered_addr);
-    }
-  } else {
-#ifdef ASSERT
-    // In the case of older JDKs which do not use the discovered
-    // field for the pending list, an inactive ref (next != NULL)
-    // must always have a NULL discovered field.
-    oop next = oopDesc::load_decode_heap_oop(next_addr);
-    oop discovered = java_lang_ref_Reference::discovered(obj);
-    assert(oopDesc::is_null(next) || oopDesc::is_null(discovered),
-        err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field",
-            p2i(obj)));
-#endif
+  // Treat discovered as normal oop, if ref is not "active",
+  // i.e. if next is non-NULL.
+  T  next_oop = oopDesc::load_heap_oop(next_addr);
+  if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
+    T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
+    debug_only(
+      if(TraceReferenceGC && PrintGCDetails) {
+        gclog_or_tty->print_cr("   Process discovered as normal "
+                               PTR_FORMAT, p2i(discovered_addr));
+      }
+    )
+    MarkSweep::mark_and_push(discovered_addr);
   }
   // treat next as normal oop.  next is a link in the reference queue.
   debug_only(
--- a/hotspot/src/share/vm/gc_implementation/shared/objectCountEventSender.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/shared/objectCountEventSender.hpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -22,8 +22,8 @@
  *
  */
 
-#ifndef SHARE_VM_OBJECT_COUNT_EVENT_SENDER_HPP
-#define SHARE_VM_OBJECT_COUNT_EVENT_SENDER_HPP
+#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_OBJECTCOUNTEVENTSENDER_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_SHARED_OBJECTCOUNTEVENTSENDER_HPP
 
 #include "gc_implementation/shared/gcTrace.hpp"
 #include "memory/allocation.hpp"
@@ -42,4 +42,4 @@
 
 #endif // INCLUDE_SERVICES
 
-#endif // SHARE_VM_OBJECT_COUNT_EVENT_SENDER
+#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_OBJECTCOUNTEVENTSENDER_HPP
--- a/hotspot/src/share/vm/gc_implementation/shared/plab.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/shared/plab.cpp	Fri May 08 13:25:11 2015 -0400
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc_implementation/shared/plab.hpp"
+#include "gc_interface/collectedHeap.hpp"
 #include "memory/threadLocalAllocBuffer.hpp"
 #include "oops/arrayOop.hpp"
 #include "oops/oop.inline.hpp"
@@ -39,7 +40,7 @@
 
 PLAB::PLAB(size_t desired_plab_sz_) :
   _word_sz(desired_plab_sz_), _bottom(NULL), _top(NULL),
-  _end(NULL), _hard_end(NULL), _allocated(0), _wasted(0)
+  _end(NULL), _hard_end(NULL), _allocated(0), _wasted(0), _undo_wasted(0)
 {
   // ArrayOopDesc::header_size depends on command line initialization.
   AlignmentReserve = oopDesc::header_size() > MinObjAlignment ? align_object_size(arrayOopDesc::header_size(T_INT)) : 0;
@@ -62,13 +63,15 @@
   // Now flush the statistics.
   stats->add_allocated(_allocated);
   stats->add_wasted(_wasted);
+  stats->add_undo_wasted(_undo_wasted);
   stats->add_unused(unused);
 
   // Since we have flushed the stats we need to clear  the _allocated and _wasted
   // fields in case somebody retains an instance of this over GCs. Not doing so
   // will artifically inflate the values in the statistics.
-  _allocated = 0;
-  _wasted = 0;
+  _allocated   = 0;
+  _wasted      = 0;
+  _undo_wasted = 0;
 }
 
 void PLAB::retire() {
@@ -84,6 +87,28 @@
   return result;
 }
 
+void PLAB::add_undo_waste(HeapWord* obj, size_t word_sz) {
+  CollectedHeap::fill_with_object(obj, word_sz);
+  _undo_wasted += word_sz;
+}
+
+void PLAB::undo_last_allocation(HeapWord* obj, size_t word_sz) {
+  assert(pointer_delta(_top, _bottom) >= word_sz, "Bad undo");
+  assert(pointer_delta(_top, obj) == word_sz, "Bad undo");
+  _top = obj;
+}
+
+void PLAB::undo_allocation(HeapWord* obj, size_t word_sz) {
+  // Is the alloc in the current alloc buffer?
+  if (contains(obj)) {
+    assert(contains(obj + word_sz - 1),
+      "should contain whole object");
+    undo_last_allocation(obj, word_sz);
+  } else {
+    add_undo_waste(obj, word_sz);
+  }
+}
+
 // Compute desired plab size and latch result for later
 // use. This should be called once at the end of parallel
 // scavenge; it clears the sensor accumulators.
@@ -98,8 +123,9 @@
            err_msg("Inconsistency in PLAB stats: "
                    "_allocated: "SIZE_FORMAT", "
                    "_wasted: "SIZE_FORMAT", "
-                   "_unused: "SIZE_FORMAT,
-                   _allocated, _wasted, _unused));
+                   "_unused: "SIZE_FORMAT", "
+                   "_undo_wasted: "SIZE_FORMAT,
+                   _allocated, _wasted, _unused, _undo_wasted));
 
     _allocated = 1;
   }
--- a/hotspot/src/share/vm/gc_implementation/shared/plab.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_implementation/shared/plab.hpp	Fri May 08 13:25:11 2015 -0400
@@ -45,6 +45,7 @@
   // In support of ergonomic sizing of PLAB's
   size_t    _allocated;     // in HeapWord units
   size_t    _wasted;        // in HeapWord units
+  size_t    _undo_wasted;
   char      tail[32];
   static size_t AlignmentReserve;
 
@@ -62,6 +63,12 @@
   // the amount of remaining space.
   size_t retire_internal();
 
+  void add_undo_waste(HeapWord* obj, size_t word_sz);
+
+  // Undo the last allocation in the buffer, which is required to be of the
+  // "obj" of the given "word_sz".
+  void undo_last_allocation(HeapWord* obj, size_t word_sz);
+
 public:
   // Initializes the buffer to be empty, but with the given "word_sz".
   // Must get initialized with "set_buf" for an allocation to succeed.
@@ -90,18 +97,17 @@
   // Allocate the object aligned to "alignment_in_bytes".
   HeapWord* allocate_aligned(size_t word_sz, unsigned short alignment_in_bytes);
 
-  // Undo the last allocation in the buffer, which is required to be of the
+  // Undo any allocation in the buffer, which is required to be of the
   // "obj" of the given "word_sz".
-  void undo_allocation(HeapWord* obj, size_t word_sz) {
-    assert(pointer_delta(_top, _bottom) >= word_sz, "Bad undo");
-    assert(pointer_delta(_top, obj)     == word_sz, "Bad undo");
-    _top = obj;
-  }
+  void undo_allocation(HeapWord* obj, size_t word_sz);
 
   // The total (word) size of the buffer, including both allocated and
   // unallocated space.
   size_t word_sz() { return _word_sz; }
 
+  size_t waste() { return _wasted; }
+  size_t undo_waste() { return _undo_wasted; }
+
   // Should only be done if we are about to reset with a new buffer of the
   // given size.
   void set_word_size(size_t new_word_sz) {
@@ -146,20 +152,23 @@
 class PLABStats VALUE_OBJ_CLASS_SPEC {
   size_t _allocated;      // Total allocated
   size_t _wasted;         // of which wasted (internal fragmentation)
+  size_t _undo_wasted;    // of which wasted on undo (is not used for calculation of PLAB size)
   size_t _unused;         // Unused in last buffer
   size_t _desired_plab_sz;// Output of filter (below), suitably trimmed and quantized
   AdaptiveWeightedAverage
          _filter;         // Integrator with decay
 
   void reset() {
-    _allocated = 0;
-    _wasted    = 0;
-    _unused    = 0;
+    _allocated   = 0;
+    _wasted      = 0;
+    _undo_wasted = 0;
+    _unused      = 0;
   }
  public:
   PLABStats(size_t desired_plab_sz_, unsigned wt) :
     _allocated(0),
     _wasted(0),
+    _undo_wasted(0),
     _unused(0),
     _desired_plab_sz(desired_plab_sz_),
     _filter(wt)
@@ -192,6 +201,10 @@
   void add_wasted(size_t v) {
     Atomic::add_ptr(v, &_wasted);
   }
+
+  void add_undo_wasted(size_t v) {
+    Atomic::add_ptr(v, &_undo_wasted);
+  }
 };
 
 #endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_PLAB_HPP
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp	Fri May 08 13:25:11 2015 -0400
@@ -598,13 +598,6 @@
 #endif
 
  public:
-  // This is a convenience method that is used in cases where
-  // the actual number of GC worker threads is not pertinent but
-  // only whether there more than 0.  Use of this method helps
-  // reduce the occurrence of ParallelGCThreads to uses where the
-  // actual number may be germane.
-  static bool use_parallel_gc_threads() { return ParallelGCThreads > 0; }
-
   // Copy the current allocation context statistics for the specified contexts.
   // For each context in contexts, set the corresponding entries in the totals
   // and accuracy arrays to the current values held by the statistics.  Each
--- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp	Fri May 08 13:25:11 2015 -0400
@@ -640,7 +640,7 @@
   // All threads execute the following. A specific chunk of buckets
   // from the StringTable are the individual tasks.
   if (weak_roots != NULL) {
-    if (CollectedHeap::use_parallel_gc_threads()) {
+    if (is_par) {
       StringTable::possibly_parallel_oops_do(weak_roots);
     } else {
       StringTable::oops_do(weak_roots);
--- a/hotspot/src/share/vm/memory/guardedMemory.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/memory/guardedMemory.hpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -22,8 +22,8 @@
  *
  */
 
-#ifndef SHARE_VM_MEMORY_GUARDED_MEMORY_HPP
-#define SHARE_VM_MEMORY_GUARDED_MEMORY_HPP
+#ifndef SHARE_VM_MEMORY_GUARDEDMEMORY_HPP
+#define SHARE_VM_MEMORY_GUARDEDMEMORY_HPP
 
 #include "memory/allocation.hpp"
 #include "utilities/globalDefinitions.hpp"
@@ -323,4 +323,4 @@
 #endif
 }; // GuardedMemory
 
-#endif // SHARE_VM_MEMORY_GUARDED_MEMORY_HPP
+#endif // SHARE_VM_MEMORY_GUARDEDMEMORY_HPP
--- a/hotspot/src/share/vm/memory/metaspace.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/memory/metaspace.cpp	Fri May 08 13:25:11 2015 -0400
@@ -252,7 +252,7 @@
 // Used to manage the free list of Metablocks (a block corresponds
 // to the allocation of a quantum of metadata).
 class BlockFreelist VALUE_OBJ_CLASS_SPEC {
-  BlockTreeDictionary* _dictionary;
+  BlockTreeDictionary* const _dictionary;
 
   // Only allocate and split from freelist if the size of the allocation
   // is at least 1/4th the size of the available block.
@@ -269,13 +269,7 @@
   MetaWord* get_block(size_t word_size);
   void return_block(MetaWord* p, size_t word_size);
 
-  size_t total_size() {
-  if (dictionary() == NULL) {
-    return 0;
-  } else {
-    return dictionary()->total_size();
-  }
-}
+  size_t total_size() { return dictionary()->total_size(); }
 
   void print_on(outputStream* st) const;
 };
@@ -814,30 +808,21 @@
 
 // BlockFreelist methods
 
-BlockFreelist::BlockFreelist() : _dictionary(NULL) {}
+BlockFreelist::BlockFreelist() : _dictionary(new BlockTreeDictionary()) {}
 
 BlockFreelist::~BlockFreelist() {
-  if (_dictionary != NULL) {
-    if (Verbose && TraceMetadataChunkAllocation) {
-      _dictionary->print_free_lists(gclog_or_tty);
-    }
-    delete _dictionary;
+  if (Verbose && TraceMetadataChunkAllocation) {
+    dictionary()->print_free_lists(gclog_or_tty);
   }
+  delete _dictionary;
 }
 
 void BlockFreelist::return_block(MetaWord* p, size_t word_size) {
   Metablock* free_chunk = ::new (p) Metablock(word_size);
-  if (dictionary() == NULL) {
-   _dictionary = new BlockTreeDictionary();
-  }
   dictionary()->return_chunk(free_chunk);
 }
 
 MetaWord* BlockFreelist::get_block(size_t word_size) {
-  if (dictionary() == NULL) {
-    return NULL;
-  }
-
   if (word_size < TreeChunk<Metablock, FreeList<Metablock> >::min_size()) {
     // Dark matter.  Too small for dictionary.
     return NULL;
@@ -866,9 +851,6 @@
 }
 
 void BlockFreelist::print_on(outputStream* st) const {
-  if (dictionary() == NULL) {
-    return;
-  }
   dictionary()->print_free_lists(st);
 }
 
--- a/hotspot/src/share/vm/memory/metaspaceChunkFreeListSummary.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/memory/metaspaceChunkFreeListSummary.hpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -21,8 +21,9 @@
  * questions.
  *
  */
-#ifndef SHARE_VM_MEMORY_METASPACE_CHUNK_FREE_LIST_SUMMARY_HPP
-#define SHARE_VM_MEMORY_METASPACE_CHUNK_FREE_LIST_SUMMARY_HPP
+
+#ifndef SHARE_VM_MEMORY_METASPACECHUNKFREELISTSUMMARY_HPP
+#define SHARE_VM_MEMORY_METASPACECHUNKFREELISTSUMMARY_HPP
 
 #include "memory/allocation.hpp"
 
@@ -100,4 +101,4 @@
   }
 };
 
-#endif // SHARE_VM_MEMORY_METASPACE_CHUNK_FREE_LIST_SUMMARY_HPP
+#endif // SHARE_VM_MEMORY_METASPACECHUNKFREELISTSUMMARY_HPP
--- a/hotspot/src/share/vm/memory/metaspaceGCThresholdUpdater.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/memory/metaspaceGCThresholdUpdater.hpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -22,8 +22,8 @@
  *
  */
 
-#ifndef SHARE_VM_MEMORY_METASPACE_GC_THRESHOLD_UPDATER_HPP
-#define SHARE_VM_MEMORY_METASPACE_GC_THRESHOLD_UPDATER_HPP
+#ifndef SHARE_VM_MEMORY_METASPACEGCTHRESHOLDUPDATER_HPP
+#define SHARE_VM_MEMORY_METASPACEGCTHRESHOLDUPDATER_HPP
 
 #include "memory/allocation.hpp"
 #include "utilities/debug.hpp"
@@ -49,4 +49,4 @@
   }
 };
 
-#endif // SHARE_VM_MEMORY_METASPACE_GC_THRESHOLD_UPDATER_HPP
+#endif // SHARE_VM_MEMORY_METASPACEGCTHRESHOLDUPDATER_HPP
--- a/hotspot/src/share/vm/memory/metaspaceShared.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/memory/metaspaceShared.hpp	Fri May 08 13:25:11 2015 -0400
@@ -21,8 +21,9 @@
  * questions.
  *
  */
-#ifndef SHARE_VM_MEMORY_METASPACE_SHARED_HPP
-#define SHARE_VM_MEMORY_METASPACE_SHARED_HPP
+
+#ifndef SHARE_VM_MEMORY_METASPACESHARED_HPP
+#define SHARE_VM_MEMORY_METASPACESHARED_HPP
 
 #include "classfile/compactHashtable.hpp"
 #include "memory/allocation.hpp"
@@ -153,4 +154,4 @@
   static int count_class(const char* classlist_file);
   static void estimate_regions_size() NOT_CDS_RETURN;
 };
-#endif // SHARE_VM_MEMORY_METASPACE_SHARED_HPP
+#endif // SHARE_VM_MEMORY_METASPACESHARED_HPP
--- a/hotspot/src/share/vm/memory/metaspaceTracer.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/memory/metaspaceTracer.hpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -22,8 +22,8 @@
  *
  */
 
-#ifndef SHARE_VM_MEMORY_METASPACE_TRACER_HPP
-#define SHARE_VM_MEMORY_METASPACE_TRACER_HPP
+#ifndef SHARE_VM_MEMORY_METASPACETRACER_HPP
+#define SHARE_VM_MEMORY_METASPACETRACER_HPP
 
 #include "memory/allocation.hpp"
 #include "memory/metaspace.hpp"
@@ -52,4 +52,4 @@
 
 };
 
-#endif // SHARE_VM_MEMORY_METASPACE_TRACER_HPP
+#endif // SHARE_VM_MEMORY_METASPACETRACER_HPP
--- a/hotspot/src/share/vm/memory/padded.inline.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/memory/padded.inline.hpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -22,6 +22,9 @@
  *
  */
 
+#ifndef SHARE_VM_MEMORY_PADDED_INLINE_HPP
+#define SHARE_VM_MEMORY_PADDED_INLINE_HPP
+
 #include "memory/allocation.inline.hpp"
 #include "memory/padded.hpp"
 #include "utilities/debug.hpp"
@@ -86,3 +89,5 @@
 
   return (T*)align_pointer_up(chunk, alignment);
 }
+
+#endif // SHARE_VM_MEMORY_PADDED_INLINE_HPP
--- a/hotspot/src/share/vm/memory/referenceProcessor.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp	Fri May 08 13:25:11 2015 -0400
@@ -37,7 +37,6 @@
 
 ReferencePolicy* ReferenceProcessor::_always_clear_soft_ref_policy = NULL;
 ReferencePolicy* ReferenceProcessor::_default_soft_ref_policy      = NULL;
-bool             ReferenceProcessor::_pending_list_uses_discovered_field = false;
 jlong            ReferenceProcessor::_soft_ref_timestamp_clock = 0;
 
 void referenceProcessor_init() {
@@ -63,7 +62,6 @@
   guarantee(RefDiscoveryPolicy == ReferenceBasedDiscovery ||
             RefDiscoveryPolicy == ReferentBasedDiscovery,
             "Unrecognized RefDiscoveryPolicy");
-  _pending_list_uses_discovered_field = JDK_Version::current().pending_list_uses_discovered_field();
 }
 
 void ReferenceProcessor::enable_discovery(bool check_no_refs) {
@@ -353,10 +351,6 @@
   // all linked Reference objects. Note that it is important to not dirty any
   // cards during reference processing since this will cause card table
   // verification to fail for G1.
-  //
-  // BKWRD COMPATIBILITY NOTE: For older JDKs (prior to the fix for 4956777),
-  // the "next" field is used to chain the pending list, not the discovered
-  // field.
   if (TraceReferenceGC && PrintGCDetails) {
     gclog_or_tty->print_cr("ReferenceProcessor::enqueue_discovered_reflist list "
                            INTPTR_FORMAT, p2i(refs_list.head()));
@@ -364,64 +358,30 @@
 
   oop obj = NULL;
   oop next_d = refs_list.head();
-  if (pending_list_uses_discovered_field()) { // New behavior
-    // Walk down the list, self-looping the next field
-    // so that the References are not considered active.
-    while (obj != next_d) {
-      obj = next_d;
-      assert(obj->is_instanceRef(), "should be reference object");
-      next_d = java_lang_ref_Reference::discovered(obj);
-      if (TraceReferenceGC && PrintGCDetails) {
-        gclog_or_tty->print_cr("        obj " INTPTR_FORMAT "/next_d " INTPTR_FORMAT,
-                               p2i(obj), p2i(next_d));
-      }
-      assert(java_lang_ref_Reference::next(obj) == NULL,
-             "Reference not active; should not be discovered");
-      // Self-loop next, so as to make Ref not active.
-      java_lang_ref_Reference::set_next_raw(obj, obj);
-      if (next_d != obj) {
-        oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(obj), next_d);
-      } else {
-        // This is the last object.
-        // Swap refs_list into pending_list_addr and
-        // set obj's discovered to what we read from pending_list_addr.
-        oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr);
-        // Need post-barrier on pending_list_addr. See enqueue_discovered_ref_helper() above.
-        java_lang_ref_Reference::set_discovered_raw(obj, old); // old may be NULL
-        oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(obj), old);
-      }
+  // Walk down the list, self-looping the next field
+  // so that the References are not considered active.
+  while (obj != next_d) {
+    obj = next_d;
+    assert(obj->is_instanceRef(), "should be reference object");
+    next_d = java_lang_ref_Reference::discovered(obj);
+    if (TraceReferenceGC && PrintGCDetails) {
+      gclog_or_tty->print_cr("        obj " INTPTR_FORMAT "/next_d " INTPTR_FORMAT,
+                             p2i(obj), p2i(next_d));
     }
-  } else { // Old behavior
-    // Walk down the list, copying the discovered field into
-    // the next field and clearing the discovered field.
-    while (obj != next_d) {
-      obj = next_d;
-      assert(obj->is_instanceRef(), "should be reference object");
-      next_d = java_lang_ref_Reference::discovered(obj);
-      if (TraceReferenceGC && PrintGCDetails) {
-        gclog_or_tty->print_cr("        obj " INTPTR_FORMAT "/next_d " INTPTR_FORMAT,
-                               p2i(obj), p2i(next_d));
-      }
-      assert(java_lang_ref_Reference::next(obj) == NULL,
-             "The reference should not be enqueued");
-      if (next_d == obj) {  // obj is last
-        // Swap refs_list into pending_list_addr and
-        // set obj's next to what we read from pending_list_addr.
-        oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr);
-        // Need oop_check on pending_list_addr above;
-        // see special oop-check code at the end of
-        // enqueue_discovered_reflists() further below.
-        if (old == NULL) {
-          // obj should be made to point to itself, since
-          // pending list was empty.
-          java_lang_ref_Reference::set_next(obj, obj);
-        } else {
-          java_lang_ref_Reference::set_next(obj, old);
-        }
-      } else {
-        java_lang_ref_Reference::set_next(obj, next_d);
-      }
-      java_lang_ref_Reference::set_discovered(obj, (oop) NULL);
+    assert(java_lang_ref_Reference::next(obj) == NULL,
+           "Reference not active; should not be discovered");
+    // Self-loop next, so as to make Ref not active.
+    java_lang_ref_Reference::set_next_raw(obj, obj);
+    if (next_d != obj) {
+      oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(obj), next_d);
+    } else {
+      // This is the last object.
+      // Swap refs_list into pending_list_addr and
+      // set obj's discovered to what we read from pending_list_addr.
+      oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr);
+      // Need post-barrier on pending_list_addr. See enqueue_discovered_ref_helper() above.
+      java_lang_ref_Reference::set_discovered_raw(obj, old); // old may be NULL
+      oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(obj), old);
     }
   }
 }
@@ -515,22 +475,6 @@
   _refs_list.dec_length(1);
 }
 
-// Make the Reference object active again.
-void DiscoveredListIterator::make_active() {
-  // The pre barrier for G1 is probably just needed for the old
-  // reference processing behavior. Should we guard this with
-  // ReferenceProcessor::pending_list_uses_discovered_field() ?
-  if (UseG1GC) {
-    HeapWord* next_addr = java_lang_ref_Reference::next_addr(_ref);
-    if (UseCompressedOops) {
-      oopDesc::bs()->write_ref_field_pre((narrowOop*)next_addr, NULL);
-    } else {
-      oopDesc::bs()->write_ref_field_pre((oop*)next_addr, NULL);
-    }
-  }
-  java_lang_ref_Reference::set_next_raw(_ref, NULL);
-}
-
 void DiscoveredListIterator::clear_referent() {
   oop_store_raw(_referent_addr, NULL);
 }
@@ -567,8 +511,6 @@
       }
       // Remove Reference object from list
       iter.remove();
-      // Make the Reference object active again
-      iter.make_active();
       // keep the referent around
       iter.make_referent_alive();
       iter.move_to_next();
--- a/hotspot/src/share/vm/memory/referenceProcessor.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/memory/referenceProcessor.hpp	Fri May 08 13:25:11 2015 -0400
@@ -161,9 +161,6 @@
   // Remove the current reference from the list
   void remove();
 
-  // Make the Reference object active again.
-  void make_active();
-
   // Make the referent alive.
   inline void make_referent_alive() {
     if (UseCompressedOops) {
@@ -200,9 +197,6 @@
   size_t total_count(DiscoveredList lists[]);
 
  protected:
-  // Compatibility with pre-4965777 JDK's
-  static bool _pending_list_uses_discovered_field;
-
   // The SoftReference master timestamp clock
   static jlong _soft_ref_timestamp_clock;
 
@@ -421,13 +415,6 @@
   bool discovery_is_atomic() const { return _discovery_is_atomic; }
   void set_atomic_discovery(bool atomic) { _discovery_is_atomic = atomic; }
 
-  // whether the JDK in which we are embedded is a pre-4965777 JDK,
-  // and thus whether or not it uses the discovered field to chain
-  // the entries in the pending list.
-  static bool pending_list_uses_discovered_field() {
-    return _pending_list_uses_discovered_field;
-  }
-
   // whether discovery is done by multiple threads same-old-timeously
   bool discovery_is_mt() const { return _discovery_is_mt; }
   void set_mt_discovery(bool mt) { _discovery_is_mt = mt; }
--- a/hotspot/src/share/vm/memory/referenceType.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/memory/referenceType.hpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -22,8 +22,8 @@
  *
  */
 
-#ifndef SHARE_VM_MEMORY_REFRERENCETYPE_HPP
-#define SHARE_VM_MEMORY_REFRERENCETYPE_HPP
+#ifndef SHARE_VM_MEMORY_REFERENCETYPE_HPP
+#define SHARE_VM_MEMORY_REFERENCETYPE_HPP
 
 #include "utilities/debug.hpp"
 
@@ -39,4 +39,4 @@
   REF_CLEANER    // Subclass of sun/misc/Cleaner
 };
 
-#endif // SHARE_VM_MEMORY_REFRERENCETYPE_HPP
+#endif // SHARE_VM_MEMORY_REFERENCETYPE_HPP
--- a/hotspot/src/share/vm/oops/instanceRefKlass.inline.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/oops/instanceRefKlass.inline.hpp	Fri May 08 13:25:11 2015 -0400
@@ -55,30 +55,17 @@
     }
   }
   T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
-  if (ReferenceProcessor::pending_list_uses_discovered_field()) {
-    T next_oop  = oopDesc::load_heap_oop(next_addr);
-    // Treat discovered as normal oop, if ref is not "active" (next non-NULL)
-    if (!oopDesc::is_null(next_oop) && contains(disc_addr)) {
-      // i.e. ref is not "active"
-      debug_only(
-        if(TraceReferenceGC && PrintGCDetails) {
-          gclog_or_tty->print_cr("   Process discovered as normal "
-                                 PTR_FORMAT, p2i(disc_addr));
-        }
-      )
-      Devirtualizer<nv>::do_oop(closure, disc_addr);
-    }
-  } else {
-    // In the case of older JDKs which do not use the discovered field for
-    // the pending list, an inactive ref (next != NULL) must always have a
-    // NULL discovered field.
+  T next_oop  = oopDesc::load_heap_oop(next_addr);
+  // Treat discovered as normal oop, if ref is not "active" (next non-NULL)
+  if (!oopDesc::is_null(next_oop) && contains(disc_addr)) {
+    // i.e. ref is not "active"
     debug_only(
-      T next_oop = oopDesc::load_heap_oop(next_addr);
-      T disc_oop = oopDesc::load_heap_oop(disc_addr);
-      assert(oopDesc::is_null(next_oop) || oopDesc::is_null(disc_oop),
-           err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL"
-                   "discovered field", p2i(obj)));
+      if(TraceReferenceGC && PrintGCDetails) {
+        gclog_or_tty->print_cr("   Process discovered as normal "
+                               PTR_FORMAT, p2i(disc_addr));
+      }
     )
+    Devirtualizer<nv>::do_oop(closure, disc_addr);
   }
   // treat next as normal oop
   if (contains(next_addr)) {
--- a/hotspot/src/share/vm/opto/c2_globals.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp	Fri May 08 13:25:11 2015 -0400
@@ -318,6 +318,9 @@
   notproduct(bool, TraceLoopUnswitching, false,                             \
           "Trace loop unswitching")                                         \
                                                                             \
+  product(bool, AllowVectorizeOnDemand, true,                               \
+          "Globally supress vectorization set in VectorizeMethod")          \
+                                                                            \
   product(bool, UseSuperWord, true,                                         \
           "Transform scalar operations into superword operations")          \
                                                                             \
--- a/hotspot/src/share/vm/opto/compile.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/opto/compile.cpp	Fri May 08 13:25:11 2015 -0400
@@ -453,6 +453,8 @@
   assert(compile == Compile::current(), "sanity");
 
   compile->set_type_dict(NULL);
+  compile->set_clone_map(new Dict(cmpkey, hashkey, _compile->comp_arena()));
+  compile->clone_map().set_clone_idx(0);
   compile->set_type_hwm(NULL);
   compile->set_type_last_size(0);
   compile->set_last_tf(NULL, NULL);
@@ -462,6 +464,7 @@
   Type::Initialize(compile);
   _compile->set_scratch_buffer_blob(NULL);
   _compile->begin_method();
+  _compile->clone_map().set_debug(_compile->has_method() && _compile->method_has_option(_compile->clone_map().debug_option_name));
 }
 CompileWrapper::~CompileWrapper() {
   _compile->end_method();
@@ -1091,6 +1094,24 @@
   set_do_scheduling(OptoScheduling);
   set_do_count_invocations(false);
   set_do_method_data_update(false);
+
+  set_do_vector_loop(false);
+
+  bool do_vector = false;
+  if (AllowVectorizeOnDemand) {
+    if (has_method() && (method()->has_option("Vectorize") || method()->has_option("VectorizeDebug"))) {
+      set_do_vector_loop(true);
+    } else if (has_method() && method()->name() != 0 &&
+               method()->intrinsic_id() == vmIntrinsics::_forEachRemaining) {
+      set_do_vector_loop(true);
+    }
+#ifndef PRODUCT
+    if (do_vector_loop() && Verbose) {
+      tty->print("Compile::Init: do vectorized loops (SIMD like) for method %s\n",  method()->name()->as_quoted_ascii());
+    }
+#endif
+  }
+
   set_age_code(has_method() && method()->profile_aging());
   set_rtm_state(NoRTM); // No RTM lock eliding by default
   method_has_option_value("MaxNodeLimit", _max_node_limit);
@@ -4334,3 +4355,63 @@
   assert(count > 0, "only positive");
   return (os::random() & RANDOMIZED_DOMAIN_MASK) < (RANDOMIZED_DOMAIN / count);
 }
+
+const char*   CloneMap::debug_option_name = "CloneMapDebug";
+CloneMap&     Compile::clone_map()                 { return _clone_map; }
+void          Compile::set_clone_map(Dict* d)      { _clone_map._dict = d; }
+
+void NodeCloneInfo::dump() const {
+  tty->print(" {%d:%d} ", idx(), gen());
+}
+
+void CloneMap::clone(Node* old, Node* nnn, int gen) {
+  uint64_t val = value(old->_idx);
+  NodeCloneInfo cio(val);
+  assert(val != 0, "old node should be in the map");
+  NodeCloneInfo cin(cio.idx(), gen + cio.gen());
+  insert(nnn->_idx, cin.get());
+#ifndef PRODUCT
+  if (is_debug()) {
+    tty->print_cr("CloneMap::clone inserted node %d info {%d:%d} into CloneMap", nnn->_idx, cin.idx(), cin.gen());
+  }
+#endif
+}
+
+void CloneMap::verify_insert_and_clone(Node* old, Node* nnn, int gen) {
+  NodeCloneInfo cio(value(old->_idx));
+  if (cio.get() == 0) {
+    cio.set(old->_idx, 0);
+    insert(old->_idx, cio.get());
+#ifndef PRODUCT
+    if (is_debug()) {
+      tty->print_cr("CloneMap::verify_insert_and_clone inserted node %d info {%d:%d} into CloneMap", old->_idx, cio.idx(), cio.gen());
+    }
+#endif
+  }
+  clone(old, nnn, gen);
+}
+
+int CloneMap::max_gen() const {
+  int g = 0;
+  DictI di(_dict);
+  for(; di.test(); ++di) {
+    int t = gen(di._key);
+    if (g < t) {
+      g = t;
+#ifndef PRODUCT
+      if (is_debug()) {
+        tty->print_cr("CloneMap::max_gen() update max=%d from %d", g, _2_node_idx_t(di._key));
+      }
+#endif
+    }
+  }
+  return g;
+}
+
+void CloneMap::dump(node_idx_t key) const {
+  uint64_t val = value(key);
+  if (val != 0) {
+    NodeCloneInfo ni(val);
+    ni.dump();
+  }
+}
--- a/hotspot/src/share/vm/opto/compile.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/opto/compile.hpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -47,6 +47,7 @@
 class Bundle;
 class C2Compiler;
 class CallGenerator;
+class CloneMap;
 class ConnectionGraph;
 class InlineTree;
 class Int_Array;
@@ -59,6 +60,7 @@
 class Node;
 class Node_Array;
 class Node_Notes;
+class NodeCloneInfo;
 class OptoReg;
 class PhaseCFG;
 class PhaseGVN;
@@ -84,6 +86,62 @@
 class Node_Stack;
 struct Final_Reshape_Counts;
 
+typedef unsigned int node_idx_t;
+class NodeCloneInfo {
+ private:
+  uint64_t  _idx_clone_orig;
+ public:
+
+  void set_idx(node_idx_t idx) {
+    _idx_clone_orig = _idx_clone_orig & 0xFFFFFFFF00000000 | idx;
+  }
+  node_idx_t idx() const { return (node_idx_t)(_idx_clone_orig & 0xFFFFFFFF); }
+
+  void set_gen(int generation) {
+    uint64_t  g = (uint64_t)generation << 32;
+    _idx_clone_orig = _idx_clone_orig & 0xFFFFFFFF | g;
+  }
+  int gen() const { return (int)(_idx_clone_orig >> 32); }
+
+  void set(uint64_t x) {  _idx_clone_orig = x; }
+  void set(node_idx_t x, int g) {  set_idx(x); set_gen(g); }
+  uint64_t get() const { return _idx_clone_orig; }
+
+  NodeCloneInfo(uint64_t idx_clone_orig) : _idx_clone_orig(idx_clone_orig) {}
+  NodeCloneInfo(node_idx_t x, int g) {set(x, g);}
+
+  void dump() const;
+};
+
+class CloneMap {
+  friend class Compile;
+ private:
+  bool      _debug;
+  Dict*     _dict;
+  int       _clone_idx;   // current cloning iteration/generation in loop unroll
+ public:
+  void*     _2p(node_idx_t key)   const          { return (void*)(intptr_t)key; } // 2 conversion functions to make gcc happy
+  node_idx_t _2_node_idx_t(const void* k) const  { return (node_idx_t)(intptr_t)k; }
+  Dict*     dict()                const          { return _dict; }
+  void insert(node_idx_t key, uint64_t val)      { assert(_dict->operator[](_2p(key)) == NULL, "key existed"); _dict->Insert(_2p(key), (void*)val); }
+  void insert(node_idx_t key, NodeCloneInfo& ci) { insert(key, ci.get()); }
+  void remove(node_idx_t key)                    { _dict->Delete(_2p(key)); }
+  uint64_t value(node_idx_t key)  const          { return (uint64_t)_dict->operator[](_2p(key)); }
+  node_idx_t idx(node_idx_t key)  const          { return NodeCloneInfo(value(key)).idx(); }
+  int gen(node_idx_t key)         const          { return NodeCloneInfo(value(key)).gen(); }
+  int gen(const void* k)          const          { return gen(_2_node_idx_t(k)); }
+  int max_gen()                   const;
+  void clone(Node* old, Node* nnn, int gen);
+  void verify_insert_and_clone(Node* old, Node* nnn, int gen);
+  void dump(node_idx_t key)       const;
+
+  int  clone_idx() const                         { return _clone_idx; }
+  void set_clone_idx(int x)                      { _clone_idx = x; }
+  bool is_debug()                 const          { return _debug; }
+  void set_debug(bool debug)                     { _debug = debug; }
+  static const char* debug_option_name;
+};
+
 //------------------------------Compile----------------------------------------
 // This class defines a top-level Compiler invocation.
 
@@ -312,6 +370,7 @@
   bool                  _do_freq_based_layout;  // True if we intend to do frequency based block layout
   bool                  _do_count_invocations;  // True if we generate code to count invocations
   bool                  _do_method_data_update; // True if we generate code to update MethodData*s
+  bool                  _do_vector_loop;        // True if allowed to execute loop in parallel iterations
   bool                  _age_code;              // True if we need to profile code age (decrement the aging counter)
   int                   _AliasLevel;            // Locally-adjusted version of AliasLevel flag.
   bool                  _print_assembly;        // True if we should dump assembly code for this compilation
@@ -380,6 +439,7 @@
   Arena                 _Compile_types;         // Arena for all types
   Arena*                _type_arena;            // Alias for _Compile_types except in Initialize_shared()
   Dict*                 _type_dict;             // Intern table
+  CloneMap              _clone_map;             // used for recording history of cloned nodes
   void*                 _type_hwm;              // Last allocation (see Type::operator new/delete)
   size_t                _type_last_size;        // Last allocation size (see Type::operator new/delete)
   ciMethod*             _last_tf_m;             // Cache for
@@ -586,6 +646,8 @@
   void          set_do_count_invocations(bool z){ _do_count_invocations = z; }
   bool              do_method_data_update() const { return _do_method_data_update; }
   void          set_do_method_data_update(bool z) { _do_method_data_update = z; }
+  bool              do_vector_loop() const      { return _do_vector_loop; }
+  void          set_do_vector_loop(bool z)      { _do_vector_loop = z; }
   bool              age_code() const             { return _age_code; }
   void          set_age_code(bool z)             { _age_code = z; }
   int               AliasLevel() const           { return _AliasLevel; }
@@ -1228,6 +1290,11 @@
 
   // Auxiliary method for randomized fuzzing/stressing
   static bool randomized_select(int count);
+
+  // supporting clone_map
+  CloneMap&     clone_map();
+  void          set_clone_map(Dict* d);
+
 };
 
 #endif // SHARE_VM_OPTO_COMPILE_HPP
--- a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -58,7 +58,7 @@
 const char *IdealGraphPrinter::GRAPH_NAME_PROPERTY = "name";
 const char *IdealGraphPrinter::INDEX_PROPERTY = "index";
 const char *IdealGraphPrinter::METHOD_ELEMENT = "method";
-const char *IdealGraphPrinter::INLINE_ELEMENT = "inline";
+const char *IdealGraphPrinter::INLINE_ELEMENT = "inlined";
 const char *IdealGraphPrinter::BYTECODES_ELEMENT = "bytecodes";
 const char *IdealGraphPrinter::METHOD_BCI_PROPERTY = "bci";
 const char *IdealGraphPrinter::METHOD_SHORT_NAME_PROPERTY = "shortName";
@@ -236,7 +236,6 @@
 }
 
 void IdealGraphPrinter::print_prop(const char *name, int val) {
-
   stringStream stream;
   stream.print("%d", val);
   print_prop(name, stream.as_string());
@@ -266,22 +265,22 @@
   end_head();
 
   head(BYTECODES_ELEMENT);
-  output()->print_cr("<![CDATA[");
-  method->print_codes_on(output());
-  output()->print_cr("]]>");
+  _xml->print_cr("<![CDATA[");
+  method->print_codes_on(_xml);
+  _xml->print_cr("]]>");
   tail(BYTECODES_ELEMENT);
 
-  head(INLINE_ELEMENT);
-  if (tree != NULL) {
+  if (tree != NULL && tree->subtrees().length() > 0) {
+    head(INLINE_ELEMENT);
     GrowableArray<InlineTree *> subtrees = tree->subtrees();
     for (int i = 0; i < subtrees.length(); i++) {
       print_inline_tree(subtrees.at(i));
     }
+    tail(INLINE_ELEMENT);
   }
-  tail(INLINE_ELEMENT);
 
   tail(METHOD_ELEMENT);
-  output()->flush();
+  _xml->flush();
 }
 
 void IdealGraphPrinter::print_inline_tree(InlineTree *tree) {
@@ -334,13 +333,7 @@
 
   tail(PROPERTIES_ELEMENT);
 
-  if (_stream) {
-    char answer = 0;
-    _xml->flush();
-    int result = _stream->read(&answer, 1);
-    _should_send_method = (answer == 'y');
-  }
-
+  _should_send_method = true;
   this->_current_method = method;
 
   _xml->flush();
@@ -358,7 +351,7 @@
 
 // Print indent
 void IdealGraphPrinter::print_indent() {
-  tty->print_cr("printing ident %d", _depth);
+  tty->print_cr("printing indent %d", _depth);
   for (int i = 0; i < _depth; i++) {
     _xml->print("%s", INDENT);
   }
@@ -372,22 +365,17 @@
   _traverse_outs = b;
 }
 
-intptr_t IdealGraphPrinter::get_node_id(Node *n) {
-  return (intptr_t)(n);
-}
-
 void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) {
 
   if (edges) {
 
     // Output edge
-    intptr_t dest_id = get_node_id(n);
+    node_idx_t dest_id = n->_idx;
     for ( uint i = 0; i < n->len(); i++ ) {
       if ( n->in(i) ) {
         Node *source = n->in(i);
         begin_elem(EDGE_ELEMENT);
-        intptr_t source_id = get_node_id(source);
-        print_attr(FROM_PROPERTY, source_id);
+        print_attr(FROM_PROPERTY, source->_idx);
         print_attr(TO_PROPERTY, dest_id);
         print_attr(INDEX_PROPERTY, i);
         end_elem();
@@ -398,7 +386,7 @@
 
     // Output node
     begin_head(NODE_ELEMENT);
-    print_attr(NODE_ID_PROPERTY, get_node_id(n));
+    print_attr(NODE_ID_PROPERTY, n->_idx);
     end_head();
 
     head(PROPERTIES_ELEMENT);
@@ -720,7 +708,7 @@
       head(NODES_ELEMENT);
       for (uint s = 0; s < block->number_of_nodes(); s++) {
         begin_elem(NODE_ELEMENT);
-        print_attr(NODE_ID_PROPERTY, get_node_id(block->get_node(s)));
+        print_attr(NODE_ID_PROPERTY, block->get_node(s)->_idx);
         end_elem();
       }
       tail(NODES_ELEMENT);
@@ -730,7 +718,7 @@
     tail(CONTROL_FLOW_ELEMENT);
   }
   tail(GRAPH_ELEMENT);
-  output()->flush();
+  _xml->flush();
 }
 
 // Should method be printed?
@@ -742,8 +730,4 @@
 
 extern const char *NodeClassNames[];
 
-outputStream *IdealGraphPrinter::output() {
-  return _xml;
-}
-
 #endif
--- a/hotspot/src/share/vm/opto/idealGraphPrinter.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/opto/idealGraphPrinter.hpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -127,7 +127,6 @@
 
   bool traverse_outs();
   void set_traverse_outs(bool b);
-  outputStream *output();
   void print_inlining(Compile* compile);
   void begin_method(Compile* compile);
   void end_method();
--- a/hotspot/src/share/vm/opto/loopTransform.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -1210,6 +1210,16 @@
     }
     loop->dump_head();
   }
+
+  if (C->do_vector_loop() && (PrintOpto && VerifyLoopOptimizations || TraceLoopOpts)) {
+    Arena* arena = Thread::current()->resource_area();
+    Node_Stack stack(arena, C->unique() >> 2);
+    Node_List rpo_list;
+    VectorSet visited(arena);
+    visited.set(loop_head->_idx);
+    rpo( loop_head, stack, visited, rpo_list );
+    dump(loop, rpo_list.size(), rpo_list );
+  }
 #endif
 
   // Remember loop node count before unrolling to detect
@@ -1497,6 +1507,30 @@
   }
 
   loop->record_for_igvn();
+
+#ifndef PRODUCT
+  if (C->do_vector_loop() && (PrintOpto && VerifyLoopOptimizations || TraceLoopOpts)) {
+    tty->print("\nnew loop after unroll\n");       loop->dump_head();
+    for (uint i = 0; i < loop->_body.size(); i++) {
+      loop->_body.at(i)->dump();
+    }
+    if(C->clone_map().is_debug()) {
+      tty->print("\nCloneMap\n");
+      Dict* dict = C->clone_map().dict();
+      DictI i(dict);
+      tty->print_cr("Dict@%p[%d] = ", dict, dict->Size());
+      for (int ii = 0; i.test(); ++i, ++ii) {
+        NodeCloneInfo cl((uint64_t)dict->operator[]((void*)i._key));
+        tty->print("%d->%d:%d,", (int)(intptr_t)i._key, cl.idx(), cl.gen());
+        if (ii % 10 == 9) {
+          tty->print_cr(" ");
+        }
+      }
+      tty->print_cr(" ");
+    }
+  }
+#endif
+
 }
 
 //------------------------------do_maximally_unroll----------------------------
--- a/hotspot/src/share/vm/opto/loopnode.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/opto/loopnode.cpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, 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
@@ -3678,6 +3678,7 @@
 }
 
 void PhaseIdealLoop::dump( IdealLoopTree *loop, uint idx, Node_List &rpo_list ) const {
+  CloneMap& cm = C->clone_map();
   loop->dump_head();
 
   // Now scan for CFG nodes in the same loop
@@ -3709,6 +3710,7 @@
         cached_idom = find_non_split_ctrl(cached_idom);
       }
       tty->print(" ID:%d",computed_idom->_idx);
+      cm.dump(n->_idx);
       n->dump();
       if( cached_idom != computed_idom ) {
         tty->print_cr("*** BROKEN IDOM!  Computed as: %d, cached as: %d",
@@ -3728,6 +3730,7 @@
           for( uint j = 0; j < loop->_nest; j++ )
             tty->print("  ");
           tty->print(" ");
+          cm.dump(m->_idx);
           m->dump();
         }
       }
--- a/hotspot/src/share/vm/opto/loopopts.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/opto/loopopts.cpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -1267,12 +1267,36 @@
 void PhaseIdealLoop::clone_loop( IdealLoopTree *loop, Node_List &old_new, int dd,
                                  Node* side_by_side_idom) {
 
+#ifndef PRODUCT
+  if (C->do_vector_loop() && PrintOpto) {
+    const char* mname = C->method()->name()->as_quoted_ascii();
+    if (mname != NULL) {
+      tty->print("PhaseIdealLoop::clone_loop: for vectorize method %s\n", mname);
+    }
+  }
+#endif
+
+  CloneMap& cm = C->clone_map();
+  Dict* dict = cm.dict();
+  if (C->do_vector_loop()) {
+    cm.set_clone_idx(cm.max_gen()+1);
+#ifndef PRODUCT
+    if (PrintOpto) {
+      tty->print_cr("PhaseIdealLoop::clone_loop: _clone_idx %d", cm.clone_idx());
+      loop->dump_head();
+    }
+#endif
+  }
+
   // Step 1: Clone the loop body.  Make the old->new mapping.
   uint i;
   for( i = 0; i < loop->_body.size(); i++ ) {
     Node *old = loop->_body.at(i);
     Node *nnn = old->clone();
     old_new.map( old->_idx, nnn );
+    if (C->do_vector_loop()) {
+      cm.verify_insert_and_clone(old, nnn, cm.clone_idx());
+    }
     _igvn.register_new_node_with_optimizer(nnn);
   }
 
@@ -1335,6 +1359,9 @@
 
         // Clone the loop exit control projection
         Node *newuse = use->clone();
+        if (C->do_vector_loop()) {
+          cm.verify_insert_and_clone(use, newuse, cm.clone_idx());
+        }
         newuse->set_req(0,nnn);
         _igvn.register_new_node_with_optimizer(newuse);
         set_loop(newuse, use_loop);
--- a/hotspot/src/share/vm/opto/node.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/opto/node.cpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -1658,6 +1658,9 @@
     return;                     // don't process dead nodes
   }
 
+  if (C->clone_map().value(_idx) != 0) {
+    C->clone_map().dump(_idx);
+  }
   // Dump node-specific info
   dump_spec(st);
 #ifdef ASSERT
--- a/hotspot/src/share/vm/opto/superword.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/opto/superword.cpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -54,6 +54,7 @@
   _mem_slice_head(arena(), 8,  0, NULL),  // memory slice heads
   _mem_slice_tail(arena(), 8,  0, NULL),  // memory slice tails
   _node_info(arena(), 8,  0, SWNodeInfo::initial), // info needed per node
+  _clone_map(phase->C->clone_map()),      // map of nodes created in cloning
   _align_to_ref(NULL),                    // memory reference to align vectors to
   _disjoint_ptrs(arena(), 8,  0, OrderedPair::initial), // runtime disambiguated pointer pairs
   _dg(_arena),                            // dependence graph
@@ -66,7 +67,14 @@
   _lp(NULL),                              // LoopNode
   _bb(NULL),                              // basic block
   _iv(NULL),                              // induction var
-  _race_possible(false)                   // cases where SDMU is true
+  _race_possible(false),                  // cases where SDMU is true
+  _num_work_vecs(0),                      // amount of vector work we have
+  _num_reductions(0),                     // amount of reduction work we have
+  _do_vector_loop(phase->C->do_vector_loop()),  // whether to do vectorization/simd style
+  _ii_first(-1),                          // first loop generation index - only if do_vector_loop()
+  _ii_last(-1),                           // last loop generation index - only if do_vector_loop()
+  _ii_order(arena(), 8, 0, 0),
+  _vector_loop_debug(phase->C->has_method() && phase->C->method_has_option("VectorizeDebug"))
 {}
 
 //------------------------------transform_loop---------------------------
@@ -145,14 +153,53 @@
 //
 void SuperWord::SLP_extract() {
 
+#ifndef PRODUCT
+  if (_do_vector_loop && TraceSuperWord) {
+    tty->print("SuperWord::SLP_extract\n");
+    tty->print("input loop\n");
+    _lpt->dump_head();
+    _lpt->dump();
+    for (uint i = 0; i < _lpt->_body.size(); i++) {
+      _lpt->_body.at(i)->dump();
+    }
+  }
+#endif
   // Ready the block
-  if (!construct_bb())
+  if (!construct_bb()) {
     return; // Exit if no interesting nodes or complex graph.
-
+  }
+  // build    _dg, _disjoint_ptrs
   dependence_graph();
 
+  // compute function depth(Node*)
   compute_max_depth();
 
+  if (_do_vector_loop) {
+    if (mark_generations() != -1) {
+      hoist_loads_in_graph(); // this only rebuild the graph; all basic structs need rebuild explicitly
+
+      if (!construct_bb()) {
+        return; // Exit if no interesting nodes or complex graph.
+      }
+      dependence_graph();
+      compute_max_depth();
+    }
+
+#ifndef PRODUCT
+    if (TraceSuperWord) {
+      tty->print_cr("\nSuperWord::_do_vector_loop: graph after hoist_loads_in_graph");
+      _lpt->dump_head();
+      for (int j = 0; j < _block.length(); j++) {
+        Node* n = _block.at(j);
+        int d = depth(n);
+        for (int i = 0;  i < d; i++) tty->print("%s", "  ");
+        tty->print("%d :", d);
+        n->dump();
+      }
+    }
+#endif
+  }
+
   compute_vector_element_type();
 
   // Attempt vectorization
@@ -161,6 +208,17 @@
 
   extend_packlist();
 
+  if (_do_vector_loop) {
+    if (_packset.length() == 0) {
+#ifndef PRODUCT
+      if (TraceSuperWord) {
+        tty->print_cr("\nSuperWord::_do_vector_loop DFA could not build packset, now trying to build anyway");
+      }
+#endif
+      pack_parallel();
+    }
+  }
+
   combine_packs();
 
   construct_my_pack_map();
@@ -226,7 +284,7 @@
     // Create initial pack pairs of memory operations for which
     // alignment is set and vectors will be aligned.
     bool create_pack = true;
-    if (memory_alignment(mem_ref, best_iv_adjustment) == 0) {
+    if (memory_alignment(mem_ref, best_iv_adjustment) == 0 || _do_vector_loop) {
       if (!Matcher::misaligned_vectors_ok()) {
         int vw = vector_width(mem_ref);
         int vw_best = vector_width(best_align_to_mem_ref);
@@ -272,7 +330,9 @@
               Node_List* pair = new Node_List();
               pair->push(s1);
               pair->push(s2);
-              _packset.append(pair);
+              if (!_do_vector_loop || _clone_map.idx(s1->_idx) == _clone_map.idx(s2->_idx)) {
+                _packset.append(pair);
+              }
             }
           }
         }
@@ -417,7 +477,7 @@
 
 #ifdef ASSERT
   if (TraceSuperWord && Verbose) {
-    tty->print_cr("\nVector memops after find_align_to_refs");
+    tty->print_cr("\nVector memops after find_align_to_ref");
     for (uint i = 0; i < memops.size(); i++) {
       MemNode* s = memops.at(i)->as_Mem();
       s->dump();
@@ -526,6 +586,14 @@
     // Get slice in predecessor order (last is first)
     mem_slice_preds(n_tail, n, _nlist);
 
+#ifndef PRODUCT
+    if(TraceSuperWord && Verbose) {
+      tty->print_cr("SuperWord::dependence_graph: built a new mem slice");
+      for (int j = _nlist.length() - 1; j >= 0 ; j--) {
+        _nlist.at(j)->dump();
+      }
+    }
+#endif
     // Make the slice dependent on the root
     DepMem* slice = _dg.dep(n);
     _dg.make_edge(_dg.root(), slice);
@@ -1112,7 +1180,6 @@
 //------------------------------filter_packs---------------------------
 // Remove packs that are not implemented or not profitable.
 void SuperWord::filter_packs() {
-
   // Remove packs that are not implemented
   for (int i = _packset.length() - 1; i >= 0; i--) {
     Node_List* pk = _packset.at(i);
@@ -1126,6 +1193,12 @@
 #endif
       remove_pack_at(i);
     }
+    Node *n = pk->at(0);
+    if (n->is_reduction()) {
+      _num_reductions++;
+    } else {
+      _num_work_vecs++;
+    }
   }
 
   // Remove packs that are not profitable
@@ -1167,7 +1240,12 @@
     uint size = p->size();
     if (p0->is_reduction()) {
       const Type *arith_type = p0->bottom_type();
-      retValue = ReductionNode::implemented(opc, size, arith_type->basic_type());
+      // Length 2 reductions of INT/LONG do not offer performance benefits
+      if (((arith_type->basic_type() == T_INT) || (arith_type->basic_type() == T_LONG)) && (size == 2)) {
+        retValue = false;
+      } else {
+        retValue = ReductionNode::implemented(opc, size, arith_type->basic_type());
+      }
     } else {
       retValue = VectorNode::implemented(opc, size, velt_basic_type(p0));
     }
@@ -1210,8 +1288,9 @@
   if (p0->is_reduction()) {
     Node* second_in = p0->in(2);
     Node_List* second_pk = my_pack(second_in);
-    if (second_pk == NULL) {
-      // Remove reduction flag if no parent pack, it is not profitable
+    if ((second_pk == NULL) || (_num_work_vecs == _num_reductions)) {
+      // Remove reduction flag if no parent pack or if not enough work
+      // to cover reduction expansion overhead
       p0->remove_flag(Node::Flag_is_reduction);
       return false;
     } else if (second_pk->size() != p->size()) {
@@ -2349,12 +2428,29 @@
   _data_entry.clear();
   _mem_slice_head.clear();
   _mem_slice_tail.clear();
+  _iteration_first.clear();
+  _iteration_last.clear();
   _node_info.clear();
   _align_to_ref = NULL;
   _lpt = NULL;
   _lp = NULL;
   _bb = NULL;
   _iv = NULL;
+  _race_possible = 0;
+  _num_work_vecs = 0;
+  _num_reductions = 0;
+}
+
+//------------------------------restart---------------------------
+void SuperWord::restart() {
+  _dg.init();
+  _packset.clear();
+  _disjoint_ptrs.clear();
+  _block.clear();
+  _data_entry.clear();
+  _mem_slice_head.clear();
+  _mem_slice_tail.clear();
+  _node_info.clear();
 }
 
 //------------------------------print_packset---------------------------
@@ -2734,3 +2830,401 @@
     _done = true;
   }
 }
+
+//
+// --------------------------------- vectorization/simd -----------------------------------
+//
+Node*  SuperWord::find_phi_for_mem_dep(LoadNode* ld) {
+  assert(in_bb(ld), "must be in block");
+  if (_clone_map.gen(ld->_idx) == _ii_first) {
+#ifndef PRODUCT
+    if (_vector_loop_debug) {
+      tty->print_cr("SuperWord::find_phi_for_mem_dep _clone_map.gen(ld->_idx)=%d",
+                    _clone_map.gen(ld->_idx));
+    }
+#endif
+    return NULL; //we think that any ld in the first gen being vectorizable
+  }
+
+  Node* mem = ld->in(MemNode::Memory);
+  if (mem->outcnt() <= 1) {
+    // we don't want to remove the only edge from mem node to load
+#ifndef PRODUCT
+    if (_vector_loop_debug) {
+      tty->print_cr("SuperWord::find_phi_for_mem_dep input node %d to load %d has no other outputs and edge mem->load cannot be removed",
+                    mem->_idx, ld->_idx);
+      ld->dump();
+      mem->dump();
+    }
+#endif
+    return NULL;
+  }
+  if (!in_bb(mem) || _clone_map.gen(mem->_idx) == _clone_map.gen(ld->_idx)) {
+#ifndef PRODUCT
+    if (_vector_loop_debug) {
+      tty->print_cr("SuperWord::find_phi_for_mem_dep _clone_map.gen(mem->_idx)=%d",
+                    _clone_map.gen(mem->_idx));
+    }
+#endif
+    return NULL; // does not depend on loop volatile node or depends on the same generation
+  }
+
+  //otherwise first node should depend on mem-phi
+  Node* first = first_node(ld);
+  assert(first->is_Load(), "must be Load");
+  Node* phi = first->as_Load()->in(MemNode::Memory);
+  if (!phi->is_Phi() || phi->bottom_type() != Type::MEMORY) {
+#ifndef PRODUCT
+    if (_vector_loop_debug) {
+      tty->print_cr("SuperWord::find_phi_for_mem_dep load is not vectorizable node, since it's `first` does not take input from mem phi");
+      ld->dump();
+      first->dump();
+    }
+#endif
+    return NULL;
+  }
+
+  Node* tail = 0;
+  for (int m = 0; m < _mem_slice_head.length(); m++) {
+    if (_mem_slice_head.at(m) == phi) {
+      tail = _mem_slice_tail.at(m);
+    }
+  }
+  if (tail == 0) { //test that found phi is in the list  _mem_slice_head
+#ifndef PRODUCT
+    if (_vector_loop_debug) {
+      tty->print_cr("SuperWord::find_phi_for_mem_dep load %d is not vectorizable node, its phi %d is not _mem_slice_head",
+                    ld->_idx, phi->_idx);
+      ld->dump();
+      phi->dump();
+    }
+#endif
+    return NULL;
+  }
+
+  // now all conditions are met
+  return phi;
+}
+
+Node* SuperWord::first_node(Node* nd) {
+  for (int ii = 0; ii < _iteration_first.length(); ii++) {
+    Node* nnn = _iteration_first.at(ii);
+    if (_clone_map.idx(nnn->_idx) == _clone_map.idx(nd->_idx)) {
+#ifndef PRODUCT
+      if (_vector_loop_debug) {
+        tty->print_cr("SuperWord::first_node: %d is the first iteration node for %d (_clone_map.idx(nnn->_idx) = %d)",
+                      nnn->_idx, nd->_idx, _clone_map.idx(nnn->_idx));
+      }
+#endif
+      return nnn;
+    }
+  }
+
+#ifndef PRODUCT
+  if (_vector_loop_debug) {
+    tty->print_cr("SuperWord::first_node: did not find first iteration node for %d (_clone_map.idx(nd->_idx)=%d)",
+                  nd->_idx, _clone_map.idx(nd->_idx));
+  }
+#endif
+  return 0;
+}
+
+Node* SuperWord::last_node(Node* nd) {
+  for (int ii = 0; ii < _iteration_last.length(); ii++) {
+    Node* nnn = _iteration_last.at(ii);
+    if (_clone_map.idx(nnn->_idx) == _clone_map.idx(nd->_idx)) {
+#ifndef PRODUCT
+      if (_vector_loop_debug) {
+        tty->print_cr("SuperWord::last_node _clone_map.idx(nnn->_idx)=%d, _clone_map.idx(nd->_idx)=%d",
+                      _clone_map.idx(nnn->_idx), _clone_map.idx(nd->_idx));
+      }
+#endif
+      return nnn;
+    }
+  }
+  return 0;
+}
+
+int SuperWord::mark_generations() {
+  Node *ii_err = 0, *tail_err;
+  for (int i = 0; i < _mem_slice_head.length(); i++) {
+    Node* phi  = _mem_slice_head.at(i);
+    assert(phi->is_Phi(), "must be phi");
+
+    Node* tail = _mem_slice_tail.at(i);
+    if (_ii_last == -1) {
+      tail_err = tail;
+      _ii_last = _clone_map.gen(tail->_idx);
+    }
+    else if (_ii_last != _clone_map.gen(tail->_idx)) {
+#ifndef PRODUCT
+      if (TraceSuperWord && Verbose) {
+        tty->print_cr("SuperWord::mark_generations _ii_last error - found different generations in two tail nodes ");
+        tail->dump();
+        tail_err->dump();
+      }
+#endif
+      return -1;
+    }
+
+    // find first iteration in the loop
+    for (DUIterator_Fast imax, i = phi->fast_outs(imax); i < imax; i++) {
+      Node* ii = phi->fast_out(i);
+      if (in_bb(ii) && ii->is_Store()) { // we speculate that normally Stores of one and one only generation have deps from mem phi
+        if (_ii_first == -1) {
+          ii_err = ii;
+          _ii_first = _clone_map.gen(ii->_idx);
+        } else if (_ii_first != _clone_map.gen(ii->_idx)) {
+#ifndef PRODUCT
+          if (TraceSuperWord && Verbose) {
+            tty->print_cr("SuperWord::mark_generations _ii_first error - found different generations in two nodes ");
+            ii->dump();
+            ii_err->dump();
+          }
+#endif
+          return -1; // this phi has Stores from different generations of unroll and cannot be simd/vectorized
+        }
+      }
+    }//for (DUIterator_Fast imax,
+  }//for (int i...
+
+  if (_ii_first == -1 || _ii_last == -1) {
+#ifndef PRODUCT
+    if (TraceSuperWord && Verbose) {
+      tty->print_cr("SuperWord::mark_generations unknown error, something vent wrong");
+    }
+#endif
+    return -1; // something vent wrong
+  }
+  // collect nodes in the first and last generations
+  assert(_iteration_first.length() == 0, "_iteration_first must be empty");
+  assert(_iteration_last.length() == 0, "_iteration_last must be empty");
+  for (int j = 0; j < _block.length(); j++) {
+    Node* n = _block.at(j);
+    node_idx_t gen = _clone_map.gen(n->_idx);
+    if ((signed)gen == _ii_first) {
+      _iteration_first.push(n);
+    } else if ((signed)gen == _ii_last) {
+      _iteration_last.push(n);
+    }
+  }
+
+  // building order of iterations
+  assert(_ii_order.length() == 0, "should be empty");
+  if (ii_err != 0) {
+    assert(in_bb(ii_err) && ii_err->is_Store(), "should be Store in bb");
+    Node* nd = ii_err;
+    while(_clone_map.gen(nd->_idx) != _ii_last) {
+      _ii_order.push(_clone_map.gen(nd->_idx));
+      bool found = false;
+      for (DUIterator_Fast imax, i = nd->fast_outs(imax); i < imax; i++) {
+        Node* use = nd->fast_out(i);
+        if (_clone_map.idx(use->_idx) == _clone_map.idx(nd->_idx) && use->as_Store()->in(MemNode::Memory) == nd) {
+          found = true;
+          nd = use;
+          break;
+        }
+      }//for
+
+      if (found == false) {
+#ifndef PRODUCT
+        if (TraceSuperWord && Verbose) {
+          tty->print_cr("SuperWord::mark_generations: Cannot build order of iterations - no dependent Store for %d", nd->_idx);
+        }
+#endif
+        _ii_order.clear();
+        return -1;
+      }
+    } //while
+    _ii_order.push(_clone_map.gen(nd->_idx));
+  }
+
+#ifndef PRODUCT
+  if (_vector_loop_debug) {
+    tty->print_cr("SuperWord::mark_generations");
+    tty->print_cr("First generation (%d) nodes:", _ii_first);
+    for (int ii = 0; ii < _iteration_first.length(); ii++)  _iteration_first.at(ii)->dump();
+    tty->print_cr("Last generation (%d) nodes:", _ii_last);
+    for (int ii = 0; ii < _iteration_last.length(); ii++)  _iteration_last.at(ii)->dump();
+    tty->print_cr(" ");
+
+    tty->print("SuperWord::List of generations: ");
+    for (int jj = 0; jj < _ii_order.length(); ++jj) {
+      tty->print("%d:%d ", jj, _ii_order.at(jj));
+    }
+    tty->print_cr(" ");
+  }
+#endif
+
+  return _ii_first;
+}
+
+bool SuperWord::fix_commutative_inputs(Node* gold, Node* fix) {
+  assert(gold->is_Add() && fix->is_Add() || gold->is_Mul() && fix->is_Mul(), "should be only Add or Mul nodes");
+  assert(_clone_map.idx(gold->_idx) == _clone_map.idx(fix->_idx), "should be clones of the same node");
+  Node* gin1 = gold->in(1);
+  Node* gin2 = gold->in(2);
+  Node* fin1 = fix->in(1);
+  Node* fin2 = fix->in(2);
+  bool swapped = false;
+
+  if (in_bb(gin1) && in_bb(gin2) && in_bb(fin1) && in_bb(fin1)) {
+    if (_clone_map.idx(gin1->_idx) == _clone_map.idx(fin1->_idx) &&
+        _clone_map.idx(gin2->_idx) == _clone_map.idx(fin2->_idx)) {
+      return true; // nothing to fix
+    }
+    if (_clone_map.idx(gin1->_idx) == _clone_map.idx(fin2->_idx) &&
+        _clone_map.idx(gin2->_idx) == _clone_map.idx(fin1->_idx)) {
+      fix->swap_edges(1, 2);
+      swapped = true;
+    }
+  }
+  // at least one input comes from outside of bb
+  if (gin1->_idx == fin1->_idx)  {
+    return true; // nothing to fix
+  }
+  if (!swapped && (gin1->_idx == fin2->_idx || gin2->_idx == fin1->_idx))  { //swapping is expensive, check condition first
+    fix->swap_edges(1, 2);
+    swapped = true;
+  }
+
+  if (swapped) {
+#ifndef PRODUCT
+    if (_vector_loop_debug) {
+      tty->print_cr("SuperWord::fix_commutative_inputs: fixed node %d", fix->_idx);
+    }
+#endif
+    return true;
+  }
+
+#ifndef PRODUCT
+  if (TraceSuperWord && Verbose) {
+    tty->print_cr("SuperWord::fix_commutative_inputs: cannot fix node %d", fix->_idx);
+  }
+#endif
+  return false;
+}
+
+bool SuperWord::pack_parallel() {
+#ifndef PRODUCT
+  if (_vector_loop_debug) {
+    tty->print_cr("SuperWord::pack_parallel: START");
+  }
+#endif
+
+  _packset.clear();
+
+  for (int ii = 0; ii < _iteration_first.length(); ii++) {
+    Node* nd = _iteration_first.at(ii);
+    if (in_bb(nd) && (nd->is_Load() || nd->is_Store() || nd->is_Add() || nd->is_Mul())) {
+      Node_List* pk = new Node_List();
+      pk->push(nd);
+      for (int gen = 1; gen < _ii_order.length(); ++gen) {
+        for (int kk = 0; kk < _block.length(); kk++) {
+          Node* clone = _block.at(kk);
+          if (_clone_map.idx(clone->_idx) == _clone_map.idx(nd->_idx) &&
+              _clone_map.gen(clone->_idx) == _ii_order.at(gen)) {
+            if (nd->is_Add() || nd->is_Mul()) {
+              fix_commutative_inputs(nd, clone);
+            }
+            pk->push(clone);
+            if (pk->size() == 4) {
+              _packset.append(pk);
+#ifndef PRODUCT
+              if (_vector_loop_debug) {
+                tty->print_cr("SuperWord::pack_parallel: added pack ");
+                pk->dump();
+              }
+#endif
+              if (_clone_map.gen(clone->_idx) != _ii_last) {
+                pk = new Node_List();
+              }
+            }
+            break;
+          }
+        }
+      }//for
+    }//if
+  }//for
+
+#ifndef PRODUCT
+  if (_vector_loop_debug) {
+    tty->print_cr("SuperWord::pack_parallel: END");
+  }
+#endif
+
+  return true;
+}
+
+bool SuperWord::hoist_loads_in_graph() {
+  GrowableArray<Node*> loads;
+
+#ifndef PRODUCT
+  if (_vector_loop_debug) {
+    tty->print_cr("SuperWord::hoist_loads_in_graph: total number _mem_slice_head.length() = %d", _mem_slice_head.length());
+  }
+#endif
+
+  for (int i = 0; i < _mem_slice_head.length(); i++) {
+    Node* n = _mem_slice_head.at(i);
+    if ( !in_bb(n) || !n->is_Phi() || n->bottom_type() != Type::MEMORY) {
+#ifndef PRODUCT
+      if (TraceSuperWord && Verbose) {
+        tty->print_cr("SuperWord::hoist_loads_in_graph: skipping unexpected node n=%d", n->_idx);
+      }
+#endif
+      continue;
+    }
+
+#ifndef PRODUCT
+    if (_vector_loop_debug) {
+      tty->print_cr("SuperWord::hoist_loads_in_graph: processing phi %d  = _mem_slice_head.at(%d);", n->_idx, i);
+    }
+#endif
+
+    for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
+      Node* ld = n->fast_out(i);
+      if (ld->is_Load() && ld->as_Load()->in(MemNode::Memory) == n && in_bb(ld)) {
+        for (int i = 0; i < _block.length(); i++) {
+          Node* ld2 = _block.at(i);
+          if (ld2->is_Load() &&
+              _clone_map.idx(ld->_idx) == _clone_map.idx(ld2->_idx) &&
+              _clone_map.gen(ld->_idx) != _clone_map.gen(ld2->_idx)) { // <= do not collect the first generation ld
+#ifndef PRODUCT
+            if (_vector_loop_debug) {
+              tty->print_cr("SuperWord::hoist_loads_in_graph: will try to hoist load ld2->_idx=%d, cloned from %d (ld->_idx=%d)",
+                            ld2->_idx, _clone_map.idx(ld->_idx), ld->_idx);
+            }
+#endif
+            // could not do on-the-fly, since iterator is immutable
+            loads.push(ld2);
+          }
+        }// for
+      }//if
+    }//for (DUIterator_Fast imax,
+  }//for (int i = 0; i
+
+  for (int i = 0; i < loads.length(); i++) {
+    LoadNode* ld = loads.at(i)->as_Load();
+    Node* phi = find_phi_for_mem_dep(ld);
+    if (phi != NULL) {
+#ifndef PRODUCT
+      if (_vector_loop_debug) {
+        tty->print_cr("SuperWord::hoist_loads_in_graph replacing MemNode::Memory(%d) edge in %d with one from %d",
+                      MemNode::Memory, ld->_idx, phi->_idx);
+      }
+#endif
+      _igvn.replace_input_of(ld, MemNode::Memory, phi);
+    }
+  }//for
+
+  restart(); // invalidate all basic structures, since we rebuilt the graph
+
+#ifndef PRODUCT
+  if (TraceSuperWord && Verbose) {
+    tty->print_cr("\nSuperWord::hoist_loads_in_graph() the graph was rebuilt, all structures invalidated and need rebuild");
+  }
+#endif
+  return true;
+}
+
--- a/hotspot/src/share/vm/opto/superword.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/opto/superword.hpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -218,8 +218,10 @@
   GrowableArray<Node*> _data_entry;      // Nodes with all inputs from outside
   GrowableArray<Node*> _mem_slice_head;  // Memory slice head nodes
   GrowableArray<Node*> _mem_slice_tail;  // Memory slice tail nodes
-
+  GrowableArray<Node*> _iteration_first; // nodes in the generation that has deps from phi
+  GrowableArray<Node*> _iteration_last;  // nodes in the generation that has deps to   phi
   GrowableArray<SWNodeInfo> _node_info;  // Info needed per node
+  CloneMap&                 _clone_map;  // map of nodes created in cloning
 
   MemNode* _align_to_ref;                // Memory reference that pre-loop will align to
 
@@ -250,6 +252,13 @@
   Node*          _bb;              // Current basic block
   PhiNode*       _iv;              // Induction var
   bool           _race_possible;   // In cases where SDMU is true
+  bool           _do_vector_loop;  // whether to do vectorization/simd style
+  bool           _vector_loop_debug; // provide more printing in debug mode
+  int            _num_work_vecs;   // Number of non memory vector operations
+  int            _num_reductions;  // Number of reduction expressions applied
+  int            _ii_first;        // generation with direct deps from mem phi
+  int            _ii_last;         // generation with direct deps to   mem phi
+  GrowableArray<int> _ii_order;
 
   // Accessors
   Arena* arena()                   { return _arena; }
@@ -324,6 +333,22 @@
   int get_iv_adjustment(MemNode* mem);
   // Can the preloop align the reference to position zero in the vector?
   bool ref_is_alignable(SWPointer& p);
+  // rebuild the graph so all loads in different iterations of cloned loop become dependant on phi node (in _do_vector_loop only)
+  bool hoist_loads_in_graph();
+  // Test whether MemNode::Memory dependency to the same load but in the first iteration of this loop is coming from memory phi
+  // Return false if failed.
+  Node* find_phi_for_mem_dep(LoadNode* ld);
+  // Return same node but from the first generation. Return 0, if not found
+  Node* first_node(Node* nd);
+  // Return same node as this but from the last generation. Return 0, if not found
+  Node* last_node(Node* n);
+  // Mark nodes belonging to first and last generation,
+  // returns first generation index or -1 if vectorization/simd is impossible
+  int mark_generations();
+  // swapping inputs of commutative instruction (Add or Mul)
+  bool fix_commutative_inputs(Node* gold, Node* fix);
+  // make packs forcefully (in _do_vector_loop only)
+  bool pack_parallel();
   // Construct dependency graph.
   void dependence_graph();
   // Return a memory slice (node list) in predecessor order starting at "start"
@@ -417,6 +442,8 @@
   // Is the use of d1 in u1 at the same operand position as d2 in u2?
   bool opnd_positions_match(Node* d1, Node* u1, Node* d2, Node* u2);
   void init();
+  // clean up some basic structures - used if the ideal graph was rebuilt
+  void restart();
 
   // print methods
   void print_packset();
--- a/hotspot/src/share/vm/runtime/interfaceSupport.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/runtime/interfaceSupport.cpp	Fri May 08 13:25:11 2015 -0400
@@ -239,7 +239,7 @@
     CodeBlob* cb = sfs.current()->cb();
     if (cb != NULL && cb->oop_maps() ) {
       // Find oopmap for current method
-      OopMap* map = cb->oop_map_for_return_address(sfs.current()->pc());
+      const ImmutableOopMap* map = cb->oop_map_for_return_address(sfs.current()->pc());
       assert(map != NULL, "no oopmap found for pc");
       found = map->has_derived_pointer();
     }
--- a/hotspot/src/share/vm/runtime/java.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/runtime/java.cpp	Fri May 08 13:25:11 2015 -0400
@@ -651,11 +651,15 @@
       minor = micro;
       micro = 0;
     }
+    // Incompatible with pre-4243978 JDK.
+    if (info.pending_list_uses_discovered_field == 0) {
+      vm_exit_during_initialization(
+        "Incompatible JDK is not using Reference.discovered field for pending list");
+    }
     _current = JDK_Version(major, minor, micro, info.update_version,
                            info.special_update_version, build,
                            info.thread_park_blocker == 1,
-                           info.post_vm_init_hook_enabled == 1,
-                           info.pending_list_uses_discovered_field == 1);
+                           info.post_vm_init_hook_enabled == 1);
   }
 }
 
--- a/hotspot/src/share/vm/runtime/java.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/runtime/java.hpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -91,7 +91,6 @@
   bool _partially_initialized;
 
   bool _thread_park_blocker;
-  bool _pending_list_uses_discovered_field;
   bool _post_vm_init_hook_enabled;
 
   bool is_valid() const {
@@ -114,18 +113,17 @@
 
   JDK_Version() : _major(0), _minor(0), _micro(0), _update(0),
                   _special(0), _build(0), _partially_initialized(false),
-                  _thread_park_blocker(false), _post_vm_init_hook_enabled(false),
-                  _pending_list_uses_discovered_field(false) {}
+                  _thread_park_blocker(false), _post_vm_init_hook_enabled(false)
+                  {}
 
   JDK_Version(uint8_t major, uint8_t minor = 0, uint8_t micro = 0,
               uint8_t update = 0, uint8_t special = 0, uint8_t build = 0,
-              bool thread_park_blocker = false, bool post_vm_init_hook_enabled = false,
-              bool pending_list_uses_discovered_field = false) :
+              bool thread_park_blocker = false, bool post_vm_init_hook_enabled = false) :
       _major(major), _minor(minor), _micro(micro), _update(update),
       _special(special), _build(build), _partially_initialized(false),
       _thread_park_blocker(thread_park_blocker),
-      _post_vm_init_hook_enabled(post_vm_init_hook_enabled),
-      _pending_list_uses_discovered_field(pending_list_uses_discovered_field) {}
+      _post_vm_init_hook_enabled(post_vm_init_hook_enabled)
+      {}
 
   // Returns the current running JDK version
   static JDK_Version current() { return _current; }
@@ -152,10 +150,6 @@
   bool post_vm_init_hook_enabled() const {
     return _post_vm_init_hook_enabled;
   }
-  // For compatibility wrt pre-4965777 JDK's
-  bool pending_list_uses_discovered_field() const {
-    return _pending_list_uses_discovered_field;
-  }
 
   // Performs a full ordering comparison using all fields (update, build, etc.)
   int compare(const JDK_Version& other) const;
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Fri May 08 13:25:11 2015 -0400
@@ -1793,7 +1793,9 @@
 
 // Handles the uncommon case in locking, i.e., contention or an inflated lock.
 JRT_BLOCK_ENTRY(void, SharedRuntime::complete_monitor_locking_C(oopDesc* _obj, BasicLock* lock, JavaThread* thread))
-  if (!SafepointSynchronize::is_synchronizing()) {
+  // Disable ObjectSynchronizer::quick_enter() in default config
+  // until JDK-8077392 is resolved.
+  if ((SyncFlags & 256) != 0 && !SafepointSynchronize::is_synchronizing()) {
     // Only try quick_enter() if we're not trying to reach a safepoint
     // so that the calling thread reaches the safepoint more quickly.
     if (ObjectSynchronizer::quick_enter(_obj, thread, lock)) return;
--- a/hotspot/src/share/vm/runtime/thread.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Fri May 08 13:25:11 2015 -0400
@@ -4209,13 +4209,13 @@
                Abstract_VM_Version::vm_info_string());
   st->cr();
 
-#if INCLUDE_ALL_GCS
+#if INCLUDE_SERVICES
   // Dump concurrent locks
   ConcurrentLocksDump concurrent_locks;
   if (print_concurrent_locks) {
     concurrent_locks.dump_at_safepoint();
   }
-#endif // INCLUDE_ALL_GCS
+#endif // INCLUDE_SERVICES
 
   ALL_JAVA_THREADS(p) {
     ResourceMark rm;
@@ -4228,11 +4228,11 @@
       }
     }
     st->cr();
-#if INCLUDE_ALL_GCS
+#if INCLUDE_SERVICES
     if (print_concurrent_locks) {
       concurrent_locks.print_locks_on(p, st);
     }
-#endif // INCLUDE_ALL_GCS
+#endif // INCLUDE_SERVICES
   }
 
   VMThread::vm_thread()->print_on(st);
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Fri May 08 13:25:11 2015 -0400
@@ -860,7 +860,7 @@
   nonstatic_field(CodeBlob,                    _frame_complete_offset,                        int)                                   \
   nonstatic_field(CodeBlob,                    _data_offset,                                  int)                                   \
   nonstatic_field(CodeBlob,                    _frame_size,                                   int)                                   \
-  nonstatic_field(CodeBlob,                    _oop_maps,                                     OopMapSet*)                            \
+  nonstatic_field(CodeBlob,                    _oop_maps,                                     ImmutableOopMapSet*)                   \
                                                                                                                                      \
   nonstatic_field(RuntimeStub,                 _caller_must_gc_arguments,                     bool)                                  \
                                                                                                                                      \
@@ -966,13 +966,19 @@
                                                                                                                                      \
   nonstatic_field(OopMap,                      _pc_offset,                                    int)                                   \
   nonstatic_field(OopMap,                      _omv_count,                                    int)                                   \
-  nonstatic_field(OopMap,                      _omv_data_size,                                int)                                   \
-  nonstatic_field(OopMap,                      _omv_data,                                     unsigned char*)                        \
   nonstatic_field(OopMap,                      _write_stream,                                 CompressedWriteStream*)                \
   nonstatic_field(OopMapSet,                   _om_count,                                     int)                                   \
   nonstatic_field(OopMapSet,                   _om_size,                                      int)                                   \
   nonstatic_field(OopMapSet,                   _om_data,                                      OopMap**)                              \
                                                                                                                                      \
+  nonstatic_field(ImmutableOopMapSet,          _count,                                        int)                                   \
+  nonstatic_field(ImmutableOopMapSet,          _size,                                         int)                                   \
+                                                                                                                                     \
+  nonstatic_field(ImmutableOopMapPair,         _pc_offset,                                    int)                                   \
+  nonstatic_field(ImmutableOopMapPair,         _oopmap_offset,                                int)                                   \
+                                                                                                                                     \
+  nonstatic_field(ImmutableOopMap,             _count,                                        int)                                   \
+                                                                                                                                     \
   /*********************************/                                                                                                \
   /* JNIHandles and JNIHandleBlock */                                                                                                \
   /*********************************/                                                                                                \
@@ -1689,6 +1695,9 @@
                                                                           \
   declare_toplevel_type(OopMap)                                           \
   declare_toplevel_type(OopMapSet)                                        \
+  declare_toplevel_type(ImmutableOopMapSet)                               \
+  declare_toplevel_type(ImmutableOopMapPair)                              \
+  declare_toplevel_type(ImmutableOopMap)                                  \
                                                                           \
   /********************/                                                  \
   /* CompressedStream */                                                  \
--- a/hotspot/src/share/vm/runtime/vm_version.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/runtime/vm_version.cpp	Fri May 08 13:25:11 2015 -0400
@@ -78,7 +78,7 @@
 int Abstract_VM_Version::_vm_micro_version = 0;
 int Abstract_VM_Version::_vm_build_number = 0;
 bool Abstract_VM_Version::_initialized = false;
-int Abstract_VM_Version::_parallel_worker_threads = 0;
+unsigned int Abstract_VM_Version::_parallel_worker_threads = 0;
 bool Abstract_VM_Version::_parallel_worker_threads_initialized = false;
 
 #ifdef ASSERT
--- a/hotspot/src/share/vm/runtime/vm_version.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/runtime/vm_version.hpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -48,7 +48,7 @@
   static int          _vm_micro_version;
   static int          _vm_build_number;
   static bool         _initialized;
-  static int          _parallel_worker_threads;
+  static unsigned int _parallel_worker_threads;
   static bool         _parallel_worker_threads_initialized;
   static int          _reserve_for_allocation_prefetch;
 
--- a/hotspot/src/share/vm/utilities/hashtable.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/utilities/hashtable.cpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -381,3 +381,4 @@
 template class BasicHashtable<mtSymbol>;
 template class BasicHashtable<mtCode>;
 template class BasicHashtable<mtInternal>;
+template class BasicHashtable<mtCompiler>;
--- a/hotspot/src/share/vm/utilities/taskqueue.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/utilities/taskqueue.cpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -31,8 +31,6 @@
 #include "utilities/stack.inline.hpp"
 #include "utilities/taskqueue.hpp"
 
-PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
-
 #ifdef TRACESPINNING
 uint ParallelTaskTerminator::_total_yields = 0;
 uint ParallelTaskTerminator::_total_spins = 0;
@@ -131,7 +129,7 @@
 }
 
 ParallelTaskTerminator::
-ParallelTaskTerminator(int n_threads, TaskQueueSetSuper* queue_set) :
+ParallelTaskTerminator(uint n_threads, TaskQueueSetSuper* queue_set) :
   _n_threads(n_threads),
   _queue_set(queue_set),
   _offered_termination(0) {}
@@ -154,7 +152,7 @@
 ParallelTaskTerminator::offer_termination(TerminatorTerminator* terminator) {
   assert(_n_threads > 0, "Initialization is incorrect");
   assert(_offered_termination < _n_threads, "Invariant");
-  Atomic::inc(&_offered_termination);
+  Atomic::inc((int *)&_offered_termination);
 
   uint yield_count = 0;
   // Number of hard spin loops done since last yield
@@ -216,8 +214,8 @@
       } else {
         if (PrintGCDetails && Verbose) {
          gclog_or_tty->print_cr("ParallelTaskTerminator::offer_termination() "
-           "thread %d sleeps after %d yields",
-           Thread::current(), yield_count);
+           "thread " PTR_FORMAT " sleeps after %u yields",
+           p2i(Thread::current()), yield_count);
         }
         yield_count = 0;
         // A sleep will cause this processor to seek work on another processor's
@@ -232,7 +230,7 @@
 #endif
       if (peek_in_queue_set() ||
           (terminator != NULL && terminator->should_exit_termination())) {
-        Atomic::dec(&_offered_termination);
+        Atomic::dec((int *)&_offered_termination);
         assert(_offered_termination < _n_threads, "Invariant");
         return false;
       }
@@ -265,7 +263,7 @@
 }
 #endif // ASSERT
 
-void ParallelTaskTerminator::reset_for_reuse(int n_threads) {
+void ParallelTaskTerminator::reset_for_reuse(uint n_threads) {
   reset_for_reuse();
   _n_threads = n_threads;
 }
--- a/hotspot/src/share/vm/utilities/taskqueue.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/utilities/taskqueue.hpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -26,9 +26,6 @@
 #define SHARE_VM_UTILITIES_TASKQUEUE_HPP
 
 #include "memory/allocation.hpp"
-#include "memory/allocation.inline.hpp"
-#include "runtime/mutex.hpp"
-#include "runtime/orderAccess.inline.hpp"
 #include "utilities/stack.hpp"
 
 // Simple TaskQueue stats that are collected by default in debug builds.
@@ -134,11 +131,7 @@
       if (_fields._top == 0) ++_fields._tag;
     }
 
-    Age cmpxchg(const Age new_age, const Age old_age) volatile {
-      return (size_t) Atomic::cmpxchg_ptr((intptr_t)new_age._data,
-                                          (volatile intptr_t *)&_data,
-                                          (intptr_t)old_age._data);
-    }
+    Age cmpxchg(const Age new_age, const Age old_age) volatile;
 
     bool operator ==(const Age& other) const { return _data == other._data; }
 
@@ -315,121 +308,6 @@
   assert(sizeof(Age) == sizeof(size_t), "Depends on this.");
 }
 
-template<class E, MEMFLAGS F, unsigned int N>
-void GenericTaskQueue<E, F, N>::initialize() {
-  _elems = _array_allocator.allocate(N);
-}
-
-template<class E, MEMFLAGS F, unsigned int N>
-void GenericTaskQueue<E, F, N>::oops_do(OopClosure* f) {
-  // tty->print_cr("START OopTaskQueue::oops_do");
-  uint iters = size();
-  uint index = _bottom;
-  for (uint i = 0; i < iters; ++i) {
-    index = decrement_index(index);
-    // tty->print_cr("  doing entry %d," INTPTR_T " -> " INTPTR_T,
-    //            index, &_elems[index], _elems[index]);
-    E* t = (E*)&_elems[index];      // cast away volatility
-    oop* p = (oop*)t;
-    assert((*t)->is_oop_or_null(), err_msg("Expected an oop or NULL at " PTR_FORMAT, p2i(*t)));
-    f->do_oop(p);
-  }
-  // tty->print_cr("END OopTaskQueue::oops_do");
-}
-
-template<class E, MEMFLAGS F, unsigned int N>
-bool GenericTaskQueue<E, F, N>::push_slow(E t, uint dirty_n_elems) {
-  if (dirty_n_elems == N - 1) {
-    // Actually means 0, so do the push.
-    uint localBot = _bottom;
-    // g++ complains if the volatile result of the assignment is
-    // unused, so we cast the volatile away.  We cannot cast directly
-    // to void, because gcc treats that as not using the result of the
-    // assignment.  However, casting to E& means that we trigger an
-    // unused-value warning.  So, we cast the E& to void.
-    (void)const_cast<E&>(_elems[localBot] = t);
-    OrderAccess::release_store(&_bottom, increment_index(localBot));
-    TASKQUEUE_STATS_ONLY(stats.record_push());
-    return true;
-  }
-  return false;
-}
-
-// pop_local_slow() is done by the owning thread and is trying to
-// get the last task in the queue.  It will compete with pop_global()
-// that will be used by other threads.  The tag age is incremented
-// whenever the queue goes empty which it will do here if this thread
-// gets the last task or in pop_global() if the queue wraps (top == 0
-// and pop_global() succeeds, see pop_global()).
-template<class E, MEMFLAGS F, unsigned int N>
-bool GenericTaskQueue<E, F, N>::pop_local_slow(uint localBot, Age oldAge) {
-  // This queue was observed to contain exactly one element; either this
-  // thread will claim it, or a competing "pop_global".  In either case,
-  // the queue will be logically empty afterwards.  Create a new Age value
-  // that represents the empty queue for the given value of "_bottom".  (We
-  // must also increment "tag" because of the case where "bottom == 1",
-  // "top == 0".  A pop_global could read the queue element in that case,
-  // then have the owner thread do a pop followed by another push.  Without
-  // the incrementing of "tag", the pop_global's CAS could succeed,
-  // allowing it to believe it has claimed the stale element.)
-  Age newAge((idx_t)localBot, oldAge.tag() + 1);
-  // Perhaps a competing pop_global has already incremented "top", in which
-  // case it wins the element.
-  if (localBot == oldAge.top()) {
-    // No competing pop_global has yet incremented "top"; we'll try to
-    // install new_age, thus claiming the element.
-    Age tempAge = _age.cmpxchg(newAge, oldAge);
-    if (tempAge == oldAge) {
-      // We win.
-      assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
-      TASKQUEUE_STATS_ONLY(stats.record_pop_slow());
-      return true;
-    }
-  }
-  // We lose; a completing pop_global gets the element.  But the queue is empty
-  // and top is greater than bottom.  Fix this representation of the empty queue
-  // to become the canonical one.
-  _age.set(newAge);
-  assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
-  return false;
-}
-
-template<class E, MEMFLAGS F, unsigned int N>
-bool GenericTaskQueue<E, F, N>::pop_global(volatile E& t) {
-  Age oldAge = _age.get();
-  // Architectures with weak memory model require a barrier here
-  // to guarantee that bottom is not older than age,
-  // which is crucial for the correctness of the algorithm.
-#if !(defined SPARC || defined IA32 || defined AMD64)
-  OrderAccess::fence();
-#endif
-  uint localBot = OrderAccess::load_acquire((volatile juint*)&_bottom);
-  uint n_elems = size(localBot, oldAge.top());
-  if (n_elems == 0) {
-    return false;
-  }
-
-  // g++ complains if the volatile result of the assignment is
-  // unused, so we cast the volatile away.  We cannot cast directly
-  // to void, because gcc treats that as not using the result of the
-  // assignment.  However, casting to E& means that we trigger an
-  // unused-value warning.  So, we cast the E& to void.
-  (void) const_cast<E&>(t = _elems[oldAge.top()]);
-  Age newAge(oldAge);
-  newAge.increment();
-  Age resAge = _age.cmpxchg(newAge, oldAge);
-
-  // Note that using "_bottom" here might fail, since a pop_local might
-  // have decremented it.
-  assert(dirty_size(localBot, newAge.top()) != N - 1, "sanity");
-  return resAge == oldAge;
-}
-
-template<class E, MEMFLAGS F, unsigned int N>
-GenericTaskQueue<E, F, N>::~GenericTaskQueue() {
-  FREE_C_HEAP_ARRAY(E, _elems);
-}
-
 // OverflowTaskQueue is a TaskQueue that also includes an overflow stack for
 // elements that do not fit in the TaskQueue.
 //
@@ -468,24 +346,6 @@
   overflow_t _overflow_stack;
 };
 
-template <class E, MEMFLAGS F, unsigned int N>
-bool OverflowTaskQueue<E, F, N>::push(E t)
-{
-  if (!taskqueue_t::push(t)) {
-    overflow_stack()->push(t);
-    TASKQUEUE_STATS_ONLY(stats.record_overflow(overflow_stack()->size()));
-  }
-  return true;
-}
-
-template <class E, MEMFLAGS F, unsigned int N>
-bool OverflowTaskQueue<E, F, N>::pop_overflow(E& t)
-{
-  if (overflow_empty()) return false;
-  t = overflow_stack()->pop();
-  return true;
-}
-
 class TaskQueueSetSuper {
 protected:
   static int randomParkAndMiller(int* seed0);
@@ -506,13 +366,7 @@
 public:
   typedef typename T::element_type E;
 
-  GenericTaskQueueSet(int n) : _n(n) {
-    typedef T* GenericTaskQueuePtr;
-    _queues = NEW_C_HEAP_ARRAY(GenericTaskQueuePtr, n, F);
-    for (int i = 0; i < n; i++) {
-      _queues[i] = NULL;
-    }
-  }
+  GenericTaskQueueSet(int n);
 
   bool steal_best_of_2(uint queue_num, int* seed, E& t);
 
@@ -541,40 +395,6 @@
   return _queues[i];
 }
 
-template<class T, MEMFLAGS F> bool
-GenericTaskQueueSet<T, F>::steal(uint queue_num, int* seed, E& t) {
-  for (uint i = 0; i < 2 * _n; i++) {
-    if (steal_best_of_2(queue_num, seed, t)) {
-      TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(true));
-      return true;
-    }
-  }
-  TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(false));
-  return false;
-}
-
-template<class T, MEMFLAGS F> bool
-GenericTaskQueueSet<T, F>::steal_best_of_2(uint queue_num, int* seed, E& t) {
-  if (_n > 2) {
-    uint k1 = queue_num;
-    while (k1 == queue_num) k1 = TaskQueueSetSuper::randomParkAndMiller(seed) % _n;
-    uint k2 = queue_num;
-    while (k2 == queue_num || k2 == k1) k2 = TaskQueueSetSuper::randomParkAndMiller(seed) % _n;
-    // Sample both and try the larger.
-    uint sz1 = _queues[k1]->size();
-    uint sz2 = _queues[k2]->size();
-    if (sz2 > sz1) return _queues[k2]->pop_global(t);
-    else return _queues[k1]->pop_global(t);
-  } else if (_n == 2) {
-    // Just try the other one.
-    uint k = (queue_num + 1) % 2;
-    return _queues[k]->pop_global(t);
-  } else {
-    assert(_n == 1, "can't be zero.");
-    return false;
-  }
-}
-
 template<class T, MEMFLAGS F>
 bool GenericTaskQueueSet<T, F>::peek() {
   // Try all the queues.
@@ -598,9 +418,9 @@
 
 class ParallelTaskTerminator: public StackObj {
 private:
-  int _n_threads;
+  uint _n_threads;
   TaskQueueSetSuper* _queue_set;
-  int _offered_termination;
+  uint _offered_termination;
 
 #ifdef TRACESPINNING
   static uint _total_yields;
@@ -617,7 +437,7 @@
 
   // "n_threads" is the number of threads to be terminated.  "queue_set" is a
   // queue sets of work queues of other threads.
-  ParallelTaskTerminator(int n_threads, TaskQueueSetSuper* queue_set);
+  ParallelTaskTerminator(uint n_threads, TaskQueueSetSuper* queue_set);
 
   // The current thread has no work, and is ready to terminate if everyone
   // else is.  If returns "true", all threads are terminated.  If returns
@@ -639,7 +459,7 @@
   void reset_for_reuse();
   // Same as above but the number of parallel threads is set to the
   // given number.
-  void reset_for_reuse(int n_threads);
+  void reset_for_reuse(uint n_threads);
 
 #ifdef TRACESPINNING
   static uint total_yields() { return _total_yields; }
@@ -649,65 +469,6 @@
 #endif
 };
 
-template<class E, MEMFLAGS F, unsigned int N> inline bool
-GenericTaskQueue<E, F, N>::push(E t) {
-  uint localBot = _bottom;
-  assert(localBot < N, "_bottom out of range.");
-  idx_t top = _age.top();
-  uint dirty_n_elems = dirty_size(localBot, top);
-  assert(dirty_n_elems < N, "n_elems out of range.");
-  if (dirty_n_elems < max_elems()) {
-    // g++ complains if the volatile result of the assignment is
-    // unused, so we cast the volatile away.  We cannot cast directly
-    // to void, because gcc treats that as not using the result of the
-    // assignment.  However, casting to E& means that we trigger an
-    // unused-value warning.  So, we cast the E& to void.
-    (void) const_cast<E&>(_elems[localBot] = t);
-    OrderAccess::release_store(&_bottom, increment_index(localBot));
-    TASKQUEUE_STATS_ONLY(stats.record_push());
-    return true;
-  } else {
-    return push_slow(t, dirty_n_elems);
-  }
-}
-
-template<class E, MEMFLAGS F, unsigned int N> inline bool
-GenericTaskQueue<E, F, N>::pop_local(volatile E& t) {
-  uint localBot = _bottom;
-  // This value cannot be N-1.  That can only occur as a result of
-  // the assignment to bottom in this method.  If it does, this method
-  // resets the size to 0 before the next call (which is sequential,
-  // since this is pop_local.)
-  uint dirty_n_elems = dirty_size(localBot, _age.top());
-  assert(dirty_n_elems != N - 1, "Shouldn't be possible...");
-  if (dirty_n_elems == 0) return false;
-  localBot = decrement_index(localBot);
-  _bottom = localBot;
-  // This is necessary to prevent any read below from being reordered
-  // before the store just above.
-  OrderAccess::fence();
-  // g++ complains if the volatile result of the assignment is
-  // unused, so we cast the volatile away.  We cannot cast directly
-  // to void, because gcc treats that as not using the result of the
-  // assignment.  However, casting to E& means that we trigger an
-  // unused-value warning.  So, we cast the E& to void.
-  (void) const_cast<E&>(t = _elems[localBot]);
-  // This is a second read of "age"; the "size()" above is the first.
-  // If there's still at least one element in the queue, based on the
-  // "_bottom" and "age" we've read, then there can be no interference with
-  // a "pop_global" operation, and we're done.
-  idx_t tp = _age.top();    // XXX
-  if (size(localBot, tp) > 0) {
-    assert(dirty_size(localBot, tp) != N - 1, "sanity");
-    TASKQUEUE_STATS_ONLY(stats.record_pop());
-    return true;
-  } else {
-    // Otherwise, the queue contained exactly one element; we take the slow
-    // path.
-    return pop_local_slow(localBot, _age.get());
-  }
-}
-
 typedef GenericTaskQueue<oop, mtGC>             OopTaskQueue;
 typedef GenericTaskQueueSet<OopTaskQueue, mtGC> OopTaskQueueSet;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/utilities/taskqueue.inline.hpp	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef SHARE_VM_UTILITIES_TASKQUEUE_INLINE_HPP
+#define SHARE_VM_UTILITIES_TASKQUEUE_INLINE_HPP
+
+#include "memory/allocation.inline.hpp"
+#include "oops/oop.inline.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/taskqueue.hpp"
+#include "utilities/stack.inline.hpp"
+#include "runtime/atomic.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
+
+template <class T, MEMFLAGS F>
+inline GenericTaskQueueSet<T, F>::GenericTaskQueueSet(int n) : _n(n) {
+  typedef T* GenericTaskQueuePtr;
+  _queues = NEW_C_HEAP_ARRAY(GenericTaskQueuePtr, n, F);
+  for (int i = 0; i < n; i++) {
+    _queues[i] = NULL;
+  }
+}
+
+template<class E, MEMFLAGS F, unsigned int N>
+inline void GenericTaskQueue<E, F, N>::initialize() {
+  _elems = _array_allocator.allocate(N);
+}
+
+template<class E, MEMFLAGS F, unsigned int N>
+inline GenericTaskQueue<E, F, N>::~GenericTaskQueue() {
+  FREE_C_HEAP_ARRAY(E, _elems);
+}
+
+template<class E, MEMFLAGS F, unsigned int N>
+bool GenericTaskQueue<E, F, N>::push_slow(E t, uint dirty_n_elems) {
+  if (dirty_n_elems == N - 1) {
+    // Actually means 0, so do the push.
+    uint localBot = _bottom;
+    // g++ complains if the volatile result of the assignment is
+    // unused, so we cast the volatile away.  We cannot cast directly
+    // to void, because gcc treats that as not using the result of the
+    // assignment.  However, casting to E& means that we trigger an
+    // unused-value warning.  So, we cast the E& to void.
+    (void)const_cast<E&>(_elems[localBot] = t);
+    OrderAccess::release_store(&_bottom, increment_index(localBot));
+    TASKQUEUE_STATS_ONLY(stats.record_push());
+    return true;
+  }
+  return false;
+}
+
+template<class E, MEMFLAGS F, unsigned int N> inline bool
+GenericTaskQueue<E, F, N>::push(E t) {
+  uint localBot = _bottom;
+  assert(localBot < N, "_bottom out of range.");
+  idx_t top = _age.top();
+  uint dirty_n_elems = dirty_size(localBot, top);
+  assert(dirty_n_elems < N, "n_elems out of range.");
+  if (dirty_n_elems < max_elems()) {
+    // g++ complains if the volatile result of the assignment is
+    // unused, so we cast the volatile away.  We cannot cast directly
+    // to void, because gcc treats that as not using the result of the
+    // assignment.  However, casting to E& means that we trigger an
+    // unused-value warning.  So, we cast the E& to void.
+    (void) const_cast<E&>(_elems[localBot] = t);
+    OrderAccess::release_store(&_bottom, increment_index(localBot));
+    TASKQUEUE_STATS_ONLY(stats.record_push());
+    return true;
+  } else {
+    return push_slow(t, dirty_n_elems);
+  }
+}
+
+template <class E, MEMFLAGS F, unsigned int N>
+inline bool OverflowTaskQueue<E, F, N>::push(E t)
+{
+  if (!taskqueue_t::push(t)) {
+    overflow_stack()->push(t);
+    TASKQUEUE_STATS_ONLY(stats.record_overflow(overflow_stack()->size()));
+  }
+  return true;
+}
+
+// pop_local_slow() is done by the owning thread and is trying to
+// get the last task in the queue.  It will compete with pop_global()
+// that will be used by other threads.  The tag age is incremented
+// whenever the queue goes empty which it will do here if this thread
+// gets the last task or in pop_global() if the queue wraps (top == 0
+// and pop_global() succeeds, see pop_global()).
+template<class E, MEMFLAGS F, unsigned int N>
+bool GenericTaskQueue<E, F, N>::pop_local_slow(uint localBot, Age oldAge) {
+  // This queue was observed to contain exactly one element; either this
+  // thread will claim it, or a competing "pop_global".  In either case,
+  // the queue will be logically empty afterwards.  Create a new Age value
+  // that represents the empty queue for the given value of "_bottom".  (We
+  // must also increment "tag" because of the case where "bottom == 1",
+  // "top == 0".  A pop_global could read the queue element in that case,
+  // then have the owner thread do a pop followed by another push.  Without
+  // the incrementing of "tag", the pop_global's CAS could succeed,
+  // allowing it to believe it has claimed the stale element.)
+  Age newAge((idx_t)localBot, oldAge.tag() + 1);
+  // Perhaps a competing pop_global has already incremented "top", in which
+  // case it wins the element.
+  if (localBot == oldAge.top()) {
+    // No competing pop_global has yet incremented "top"; we'll try to
+    // install new_age, thus claiming the element.
+    Age tempAge = _age.cmpxchg(newAge, oldAge);
+    if (tempAge == oldAge) {
+      // We win.
+      assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
+      TASKQUEUE_STATS_ONLY(stats.record_pop_slow());
+      return true;
+    }
+  }
+  // We lose; a completing pop_global gets the element.  But the queue is empty
+  // and top is greater than bottom.  Fix this representation of the empty queue
+  // to become the canonical one.
+  _age.set(newAge);
+  assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
+  return false;
+}
+
+template<class E, MEMFLAGS F, unsigned int N> inline bool
+GenericTaskQueue<E, F, N>::pop_local(volatile E& t) {
+  uint localBot = _bottom;
+  // This value cannot be N-1.  That can only occur as a result of
+  // the assignment to bottom in this method.  If it does, this method
+  // resets the size to 0 before the next call (which is sequential,
+  // since this is pop_local.)
+  uint dirty_n_elems = dirty_size(localBot, _age.top());
+  assert(dirty_n_elems != N - 1, "Shouldn't be possible...");
+  if (dirty_n_elems == 0) return false;
+  localBot = decrement_index(localBot);
+  _bottom = localBot;
+  // This is necessary to prevent any read below from being reordered
+  // before the store just above.
+  OrderAccess::fence();
+  // g++ complains if the volatile result of the assignment is
+  // unused, so we cast the volatile away.  We cannot cast directly
+  // to void, because gcc treats that as not using the result of the
+  // assignment.  However, casting to E& means that we trigger an
+  // unused-value warning.  So, we cast the E& to void.
+  (void) const_cast<E&>(t = _elems[localBot]);
+  // This is a second read of "age"; the "size()" above is the first.
+  // If there's still at least one element in the queue, based on the
+  // "_bottom" and "age" we've read, then there can be no interference with
+  // a "pop_global" operation, and we're done.
+  idx_t tp = _age.top();    // XXX
+  if (size(localBot, tp) > 0) {
+    assert(dirty_size(localBot, tp) != N - 1, "sanity");
+    TASKQUEUE_STATS_ONLY(stats.record_pop());
+    return true;
+  } else {
+    // Otherwise, the queue contained exactly one element; we take the slow
+    // path.
+    return pop_local_slow(localBot, _age.get());
+  }
+}
+
+template <class E, MEMFLAGS F, unsigned int N>
+bool OverflowTaskQueue<E, F, N>::pop_overflow(E& t)
+{
+  if (overflow_empty()) return false;
+  t = overflow_stack()->pop();
+  return true;
+}
+
+template<class E, MEMFLAGS F, unsigned int N>
+bool GenericTaskQueue<E, F, N>::pop_global(volatile E& t) {
+  Age oldAge = _age.get();
+  // Architectures with weak memory model require a barrier here
+  // to guarantee that bottom is not older than age,
+  // which is crucial for the correctness of the algorithm.
+#if !(defined SPARC || defined IA32 || defined AMD64)
+  OrderAccess::fence();
+#endif
+  uint localBot = OrderAccess::load_acquire((volatile juint*)&_bottom);
+  uint n_elems = size(localBot, oldAge.top());
+  if (n_elems == 0) {
+    return false;
+  }
+
+  // g++ complains if the volatile result of the assignment is
+  // unused, so we cast the volatile away.  We cannot cast directly
+  // to void, because gcc treats that as not using the result of the
+  // assignment.  However, casting to E& means that we trigger an
+  // unused-value warning.  So, we cast the E& to void.
+  (void) const_cast<E&>(t = _elems[oldAge.top()]);
+  Age newAge(oldAge);
+  newAge.increment();
+  Age resAge = _age.cmpxchg(newAge, oldAge);
+
+  // Note that using "_bottom" here might fail, since a pop_local might
+  // have decremented it.
+  assert(dirty_size(localBot, newAge.top()) != N - 1, "sanity");
+  return resAge == oldAge;
+}
+
+template<class T, MEMFLAGS F> bool
+GenericTaskQueueSet<T, F>::steal_best_of_2(uint queue_num, int* seed, E& t) {
+  if (_n > 2) {
+    uint k1 = queue_num;
+    while (k1 == queue_num) k1 = TaskQueueSetSuper::randomParkAndMiller(seed) % _n;
+    uint k2 = queue_num;
+    while (k2 == queue_num || k2 == k1) k2 = TaskQueueSetSuper::randomParkAndMiller(seed) % _n;
+    // Sample both and try the larger.
+    uint sz1 = _queues[k1]->size();
+    uint sz2 = _queues[k2]->size();
+    if (sz2 > sz1) return _queues[k2]->pop_global(t);
+    else return _queues[k1]->pop_global(t);
+  } else if (_n == 2) {
+    // Just try the other one.
+    uint k = (queue_num + 1) % 2;
+    return _queues[k]->pop_global(t);
+  } else {
+    assert(_n == 1, "can't be zero.");
+    return false;
+  }
+}
+
+template<class T, MEMFLAGS F> bool
+GenericTaskQueueSet<T, F>::steal(uint queue_num, int* seed, E& t) {
+  for (uint i = 0; i < 2 * _n; i++) {
+    if (steal_best_of_2(queue_num, seed, t)) {
+      TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(true));
+      return true;
+    }
+  }
+  TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(false));
+  return false;
+}
+
+template <unsigned int N, MEMFLAGS F>
+inline typename TaskQueueSuper<N, F>::Age TaskQueueSuper<N, F>::Age::cmpxchg(const Age new_age, const Age old_age) volatile {
+  return (size_t) Atomic::cmpxchg_ptr((intptr_t)new_age._data,
+                                      (volatile intptr_t *)&_data,
+                                      (intptr_t)old_age._data);
+}
+
+template<class E, MEMFLAGS F, unsigned int N>
+inline void GenericTaskQueue<E, F, N>::oops_do(OopClosure* f) {
+  // tty->print_cr("START OopTaskQueue::oops_do");
+  uint iters = size();
+  uint index = _bottom;
+  for (uint i = 0; i < iters; ++i) {
+    index = decrement_index(index);
+    // tty->print_cr("  doing entry %d," INTPTR_T " -> " INTPTR_T,
+    //            index, &_elems[index], _elems[index]);
+    E* t = (E*)&_elems[index];      // cast away volatility
+    oop* p = (oop*)t;
+    assert((*t)->is_oop_or_null(), err_msg("Expected an oop or NULL at " PTR_FORMAT, p2i(*t)));
+    f->do_oop(p);
+  }
+  // tty->print_cr("END OopTaskQueue::oops_do");
+}
+
+
+#endif // SHARE_VM_UTILITIES_TASKQUEUE_INLINE_HPP
--- a/hotspot/src/share/vm/utilities/workgroup.cpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/utilities/workgroup.cpp	Fri May 08 13:25:11 2015 -0400
@@ -29,8 +29,6 @@
 #include "runtime/os.hpp"
 #include "utilities/workgroup.hpp"
 
-PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
-
 // Definitions of WorkGang methods.
 
 AbstractWorkGang::AbstractWorkGang(const char* name,
@@ -155,7 +153,7 @@
   // Wait for them to be finished
   while (finished_workers() < no_of_parallel_workers) {
     if (TraceWorkGang) {
-      tty->print_cr("Waiting in work gang %s: %d/%d finished sequence %d",
+      tty->print_cr("Waiting in work gang %s: %u/%u finished sequence %d",
                     name(), finished_workers(), no_of_parallel_workers,
                     _sequence_number);
     }
@@ -163,11 +161,11 @@
   }
   _task = NULL;
   if (TraceWorkGang) {
-    tty->print_cr("\nFinished work gang %s: %d/%d sequence %d",
+    tty->print_cr("\nFinished work gang %s: %u/%u sequence %d",
                   name(), finished_workers(), no_of_parallel_workers,
                   _sequence_number);
     Thread* me = Thread::current();
-    tty->print_cr("  T: 0x%x  VM_thread: %d", me, me->is_VM_thread());
+    tty->print_cr("  T: " PTR_FORMAT "  VM_thread: %d", p2i(me), me->is_VM_thread());
   }
 }
 
@@ -190,7 +188,7 @@
   monitor()->notify_all();
   while (finished_workers() < active_workers()) {
     if (TraceWorkGang) {
-      tty->print_cr("Waiting in work gang %s: %d/%d finished",
+      tty->print_cr("Waiting in work gang %s: %u/%u finished",
                     name(), finished_workers(), active_workers());
     }
     monitor()->wait(/* no_safepoint_check */ true);
@@ -251,7 +249,7 @@
   assert(_gang != NULL, "No gang to run in");
   os::set_priority(this, NearMaxPriority);
   if (TraceWorkGang) {
-    tty->print_cr("Running gang worker for gang %s id %d",
+    tty->print_cr("Running gang worker for gang %s id %u",
                   gang()->name(), id());
   }
   // The VM thread should not execute here because MutexLocker's are used
@@ -274,7 +272,7 @@
       // in the outer loop.
       gang()->internal_worker_poll(&data);
       if (TraceWorkGang) {
-        tty->print("Polled outside for work in gang %s worker %d",
+        tty->print("Polled outside for work in gang %s worker %u",
                    gang()->name(), id());
         tty->print("  terminate: %s",
                    data.terminate() ? "true" : "false");
@@ -308,7 +306,7 @@
         gang_monitor->wait(/* no_safepoint_check */ true);
         gang()->internal_worker_poll(&data);
         if (TraceWorkGang) {
-          tty->print("Polled inside for work in gang %s worker %d",
+          tty->print("Polled inside for work in gang %s worker %u",
                      gang()->name(), id());
           tty->print("  terminate: %s",
                      data.terminate() ? "true" : "false");
@@ -325,14 +323,14 @@
       // Drop gang mutex.
     }
     if (TraceWorkGang) {
-      tty->print("Work for work gang %s id %d task %s part %d",
+      tty->print("Work for work gang %s id %u task %s part %d",
                  gang()->name(), id(), data.task()->name(), part);
     }
     assert(data.task() != NULL, "Got null task");
     data.task()->work(part);
     {
       if (TraceWorkGang) {
-        tty->print("Finish for work gang %s id %d task %s part %d",
+        tty->print("Finish for work gang %s id %u task %s part %d",
                    gang()->name(), id(), data.task()->name(), part);
       }
       // Grab the gang mutex.
--- a/hotspot/src/share/vm/utilities/workgroup.hpp	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/src/share/vm/utilities/workgroup.hpp	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -64,7 +64,7 @@
   // and may inherit this method that does nothing.  Some
   // tasks do some coordination on termination and override
   // this method to implement that coordination.
-  virtual void set_for_termination(int active_workers) {};
+  virtual void set_for_termination(uint active_workers) {};
 
   // Debugging accessor for the name.
   const char* name() const PRODUCT_RETURN_(return NULL;);
@@ -102,7 +102,7 @@
   AbstractGangTaskWOopQueues(const char* name, OopTaskQueueSet* queues) :
     AbstractGangTask(name), _queues(queues), _terminator(0, _queues) {}
   ParallelTaskTerminator* terminator() { return &_terminator; }
-  virtual void set_for_termination(int active_workers) {
+  virtual void set_for_termination(uint active_workers) {
     terminator()->reset_for_reuse(active_workers);
   }
   OopTaskQueueSet* queues() { return _queues; }
--- a/hotspot/test/Makefile	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/test/Makefile	Fri May 08 13:25:11 2015 -0400
@@ -28,8 +28,6 @@
 
 ALT_MAKE ?= closed
 
--include $(ALT_MAKE)/Makefile
-
 GETMIXEDPATH=echo
 
 # Utilities used
@@ -306,6 +304,8 @@
 endif
 JTREG_BASIC_OPTIONS += $(JTREG_KEY_OPTION)
 
+-include $(ALT_MAKE)/Makefile
+
 # Make sure jtreg exists
 $(JTREG): $(JT_HOME)
 
@@ -368,6 +368,10 @@
 	for variant in $(JVM_VARIANTS);                                           \
 	do                                                                        \
 	    $(MAKE) JAVA_ARGS="$(JAVA_ARGS) -$$variant" hotspot_$${variant}test;  \
+	    res=$$?;                                                              \
+	    if [ $$res -ne 0 ]; then                                              \
+	        exit $$res;                                                       \
+	    fi;                                                                   \
 	done
 
 PHONY_LIST += hotspot_basicvmtest
@@ -401,15 +405,6 @@
 
 ################################################################
 
-# internalvmtests (run internal unit tests inside the VM)
-
-hotspot_internalvmtests internalvmtests: prep $(PRODUCT_HOME)
-	$(PRODUCT_HOME)/bin/java $(JAVA_OPTIONS) -XX:+ExecuteInternalVMTests -version
-
-PHONY_LIST += hotspot_internalvmtests internalvmtests
-
-################################################################
-
 # Phony targets (e.g. these are not filenames)
 .PHONY: all clean prep $(PHONY_LIST)
 
--- a/hotspot/test/TEST.groups	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/test/TEST.groups	Fri May 08 13:25:11 2015 -0400
@@ -233,6 +233,7 @@
   gc/arguments/TestParallelGCThreads.java \
   gc/arguments/TestUseCompressedOopsErgo.java \
   gc/class_unloading/TestG1ClassUnloadingHWM.java \
+  gc/ergonomics/TestDynamicNumberOfGCThreads.java
   gc/g1/ \
   gc/metaspace/G1AddMetaspaceDependency.java \
   gc/metaspace/TestMetaspacePerfCounters.java \
@@ -262,6 +263,7 @@
   gc/arguments/TestMinInitialErgonomics.java \
   gc/arguments/TestParallelGCThreads.java \
   gc/arguments/TestUseCompressedOopsErgo.java \
+  gc/ergonomics/TestDynamicNumberOfGCThreads.java
   gc/metaspace/TestMetaspacePerfCounters.java \
   gc/parallelScavenge/ \
   gc/startup_warnings/TestParallelGC.java \
@@ -279,6 +281,7 @@
   gc/arguments/TestUseCompressedOopsErgo.java \
   gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java \
   gc/concurrentMarkSweep/ \
+  gc/ergonomics/TestDynamicNumberOfGCThreads.java
   gc/startup_warnings/TestCMS.java \
   gc/startup_warnings/TestDefNewCMS.java \
   gc/startup_warnings/TestParNewCMS.java
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java	Fri May 08 13:25:11 2015 -0400
@@ -145,7 +145,8 @@
 
         @Override
         protected boolean isIntrinsicSupported() {
-            return isServerVM() && Boolean.valueOf(useMathExactIntrinsics) && Platform.isX64();
+            return isServerVM() && Boolean.valueOf(useMathExactIntrinsics) &&
+                (Platform.isX64() || Platform.isPPC());
         }
 
         @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/loopopts/superword/ReductionPerf.java	Fri May 08 13:25:11 2015 -0400
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8074981
+ * @summary Add C2 x86 Superword support for scalar product reduction optimizations : int test
+ *
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+SuperWordReductions -XX:LoopUnrollLimit=250 -XX:CompileThresholdScaling=0.1 -XX:CompileCommand=exclude,ReductionPerf::main ReductionPerf
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-SuperWordReductions -XX:LoopUnrollLimit=250 -XX:CompileThresholdScaling=0.1 -XX:CompileCommand=exclude,ReductionPerf::main ReductionPerf
+ */
+
+public class ReductionPerf {
+  public static void main(String[] args) throws Exception {
+    int[] a1 = new int[8*1024];
+    int[] a2 = new int[8*1024];
+    int[] a3 = new int[8*1024];
+    long[] b1 = new long[8*1024];
+    long[] b2 = new long[8*1024];
+    long[] b3 = new long[8*1024];
+    float[] c1 = new float[8*1024];
+    float[] c2 = new float[8*1024];
+    float[] c3 = new float[8*1024];
+    double[] d1 = new double[8*1024];
+    double[] d2 = new double[8*1024];
+    double[] d3 = new double[8*1024];
+
+    ReductionInit(a1,a2,a3,b1,b2,b3,c1,c2,c3,d1,d2,d3);
+
+    int    sumIv = sumInt(a1,a2,a3);
+    long   sumLv = sumLong(b1,b2,b3);
+    float  sumFv = sumFloat(c1,c2,c3);
+    double sumDv = sumDouble(d1,d2,d3);
+    int    mulIv = prodInt(a1,a2,a3);
+    long   mulLv = prodLong(b1,b2,b3);
+    float  mulFv = prodFloat(c1,c2,c3);
+    double mulDv = prodDouble(d1,d2,d3);
+
+    int    sumI = 0;
+    long   sumL = 0;
+    float  sumF = 0.f;
+    double sumD = 0.;
+    int    mulI = 0;
+    long   mulL = 0;
+    float  mulF = 0.f;
+    double mulD = 0.;
+
+    System.out.println("Warmup ...");
+    long  start = System.currentTimeMillis();
+
+    for(int j = 0; j < 2000; j++) {
+      sumI = sumInt(a1,a2,a3);
+      sumL = sumLong(b1,b2,b3);
+      sumF = sumFloat(c1,c2,c3);
+      sumD = sumDouble(d1,d2,d3);
+      mulI = prodInt(a1,a2,a3);
+      mulL = prodLong(b1,b2,b3);
+      mulF = prodFloat(c1,c2,c3);
+      mulD = prodDouble(d1,d2,d3);
+    }
+
+    long stop = System.currentTimeMillis();
+    System.out.println(" Warmup is done in " + (stop - start) + " msec");
+
+    if (sumIv != sumI) {
+      System.out.println("sum int:    " + sumIv + " != " + sumI);
+    }
+    if (sumLv != sumL) {
+      System.out.println("sum long:   " + sumLv + " != " + sumL);
+    }
+    if (sumFv != sumF) {
+      System.out.println("sum float:  " + sumFv + " != " + sumF);
+    }
+    if (sumDv != sumD) {
+      System.out.println("sum double: " + sumDv + " != " + sumD);
+    }
+    if (mulIv != mulI) {
+      System.out.println("prod int:    " + mulIv + " != " + mulI);
+    }
+    if (mulLv != mulL) {
+      System.out.println("prod long:   " + mulLv + " != " + mulL);
+    }
+    if (mulFv != mulF) {
+      System.out.println("prod float:  " + mulFv + " != " + mulF);
+    }
+    if (mulDv != mulD) {
+      System.out.println("prod double: " + mulDv + " != " + mulD);
+    }
+
+    start = System.currentTimeMillis();
+    for (int j = 0; j < 5000; j++) {
+      sumI = sumInt(a1, a2 ,a3);
+    }
+    stop = System.currentTimeMillis();
+    System.out.println("sum int:    " + (stop - start));
+
+    start = System.currentTimeMillis();
+    for (int j = 0; j < 5000; j++) {
+      sumL = sumLong(b1, b2, b3);
+    }
+    stop = System.currentTimeMillis();
+    System.out.println("sum long:   " + (stop - start));
+
+    start = System.currentTimeMillis();
+    for (int j = 0; j < 5000; j++) {
+      sumF = sumFloat(c1, c2, c3);
+    }
+    stop = System.currentTimeMillis();
+    System.out.println("sum float:  " + (stop - start));
+
+    start = System.currentTimeMillis();
+    for (int j = 0; j < 5000; j++) {
+      sumD = sumDouble(d1, d2, d3);
+    }
+    stop = System.currentTimeMillis();
+    System.out.println("sum double: " + (stop - start));
+
+    start = System.currentTimeMillis();
+    for (int j = 0; j < 5000; j++) {
+      mulI = prodInt(a1, a2, a3);
+    }
+    stop = System.currentTimeMillis();
+    System.out.println("prod int:    " + (stop - start));
+
+    start = System.currentTimeMillis();
+    for (int j = 0; j < 5000; j++) {
+      mulL = prodLong(b1, b2 ,b3);
+    }
+    stop = System.currentTimeMillis();
+    System.out.println("prod long:   " + (stop - start));
+
+    start = System.currentTimeMillis();
+    for (int j = 0; j < 5000; j++) {
+      mulF = prodFloat(c1, c2, c3);
+    }
+    stop = System.currentTimeMillis();
+    System.out.println("prod float:  " + (stop - start));
+
+    start = System.currentTimeMillis();
+    for (int j = 0; j < 5000; j++) {
+      mulD = prodDouble(d1, d2, d3);
+    }
+    stop = System.currentTimeMillis();
+    System.out.println("prod double: " + (stop - start));
+
+  }
+
+  public static void ReductionInit(int[]    a1, int[]    a2, int[]    a3,
+                                   long[]   b1, long[]   b2, long[]   b3,
+                                   float[]  c1, float[]  c2, float[]  c3,
+                                   double[] d1, double[] d2, double[] d3 ) {
+    for(int i = 0; i < a1.length; i++) {
+      a1[i] =          (i + 0);
+      a2[i] =          (i + 1);
+      a3[i] =          (i + 2);
+      b1[i] =   (long) (i + 0);
+      b2[i] =   (long) (i + 1);
+      b3[i] =   (long) (i + 2);
+      c1[i] =  (float) (i + 0);
+      c2[i] =  (float) (i + 1);
+      c3[i] =  (float) (i + 2);
+      d1[i] = (double) (i + 0);
+      d2[i] = (double) (i + 1);
+      d3[i] = (double) (i + 2);
+    }
+  }
+
+  public static int sumInt(int[] a1, int[] a2, int[] a3) {
+    int total = 0;
+    for(int i = 0; i < a1.length; i++) {
+      total += (a1[i] * a2[i]) + (a1[i] * a3[i]) + (a2[i] * a3[i]);
+    }
+    return total;
+  }
+
+  public static long sumLong(long[] b1, long[] b2, long[] b3) {
+    long total = 0;
+    for(int i = 0; i < b1.length; i++) {
+      total += (b1[i] * b2[i]) + (b1[i] * b3[i]) + (b2[i] * b3[i]);
+    }
+    return total;
+  }
+
+  public static float sumFloat(float[] c1, float[] c2, float[] c3) {
+    float total = 0;
+    for(int i = 0; i < c1.length; i++) {
+      total += (c1[i] * c2[i]) + (c1[i] * c3[i]) + (c2[i] * c3[i]);
+    }
+    return total;
+  }
+
+  public static double sumDouble(double[] d1, double[] d2, double[] d3) {
+    double total = 0;
+    for(int i = 0; i < d1.length; i++) {
+      total += (d1[i] * d2[i]) + (d1[i] * d3[i]) + (d2[i] * d3[i]);
+    }
+    return total;
+  }
+
+  public static int prodInt(int[] a1, int[] a2, int[] a3) {
+    int total = 1;
+    for(int i = 0; i < a1.length; i++) {
+      total *= (a1[i] * a2[i]) + (a1[i] * a3[i]) + (a2[i] * a3[i]);
+    }
+    return total;
+  }
+
+  public static long prodLong(long[] b1, long[] b2, long[] b3) {
+    long total = 1;
+    for(int i = 0; i < b1.length; i++) {
+      total *= (b1[i] * b2[i]) + (b1[i] * b3[i]) + (b2[i] * b3[i]);
+    }
+    return total;
+  }
+
+  public static float prodFloat(float[] c1, float[] c2, float[] c3) {
+    float total = 1;
+    for(int i = 0; i < c1.length; i++) {
+      total *= (c1[i] * c2[i]) + (c1[i] * c3[i]) + (c2[i] * c3[i]);
+    }
+    return total;
+  }
+
+  public static double prodDouble(double[] d1, double[] d2, double[] d3) {
+    double total = 1;
+    for(int i = 0; i < d1.length; i++) {
+      total *= (d1[i] * d2[i]) + (d1[i] * d3[i]) + (d2[i] * d3[i]);
+    }
+    return total;
+  }
+}
--- a/hotspot/test/compiler/rtm/cli/RTMGenericCommandLineOptionTest.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/test/compiler/rtm/cli/RTMGenericCommandLineOptionTest.java	Fri May 08 13:25:11 2015 -0400
@@ -88,7 +88,7 @@
 
     @Override
     public void runTestCases() throws Throwable {
-        if (Platform.isX86() || Platform.isX64()) {
+        if (Platform.isX86() || Platform.isX64() || Platform.isPPC()) {
             if (Platform.isServer() && !Platform.isEmbedded()) {
                 runX86SupportedVMTestCases();
             } else {
@@ -108,7 +108,7 @@
     }
 
     /**
-     * Runs test cases on non-X86 CPU if VM does not support RTM locking.
+     * Runs test cases on X86 CPU if VM does not support RTM locking.
      * @throws Throwable
      */
     protected void runX86UnsupportedVMTestCases() throws Throwable {
--- a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java	Fri May 08 13:25:11 2015 -0400
@@ -60,7 +60,7 @@
                 "UseRTMLocking");
         String errorMessage = RTMGenericCommandLineOptionTest.RTM_INSTR_ERROR;
 
-        if (Platform.isX86() || Platform.isX64()) {
+        if (Platform.isX86() || Platform.isX64() || Platform.isPPC()) {
             String shouldFailMessage = "JVM startup should fail with option "
                     + "-XX:+UseRTMLocking on unsupported CPU";
             // verify that we get an error when use +UseRTMLocking
--- a/hotspot/test/compiler/testlibrary/rtm/predicate/SupportedCPU.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/test/compiler/testlibrary/rtm/predicate/SupportedCPU.java	Fri May 08 13:25:11 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -28,9 +28,12 @@
 
 import java.util.function.BooleanSupplier;
 
+import com.oracle.java.testlibrary.Platform;
+
 public class SupportedCPU implements BooleanSupplier {
     @Override
     public boolean getAsBoolean() {
+        if (Platform.isPPC()) { return CPUInfo.hasFeature("tcheck"); }
         return CPUInfo.hasFeature("rtm");
     }
 }
--- a/hotspot/test/gc/TestSoftReferencesBehaviorOnOOME.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/test/gc/TestSoftReferencesBehaviorOnOOME.java	Fri May 08 13:25:11 2015 -0400
@@ -28,29 +28,30 @@
  * @library /testlibrary
  * @modules java.base/sun.misc
  *          java.management
- * @ignore 8073669
  * @build TestSoftReferencesBehaviorOnOOME
  * @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 512 2k
  * @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 128k 256k
- * @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 2k 32k 10
+ * @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 2k 32k
  */
 import jdk.test.lib.Utils;
+import jdk.test.lib.Asserts;
 import java.lang.ref.SoftReference;
 import java.util.LinkedList;
 import java.util.Random;
 
 public class TestSoftReferencesBehaviorOnOOME {
 
-    private static final Random rndGenerator = Utils.getRandomInstance();
-
+    /**
+     * Test generates a lot of soft references to objects with random payloads.
+     * Then it provokes OOME and checks that all SoftReferences has been gone
+     * @param args - [minSize] [maxSize] [freq]
+     *  where
+     *  - minSize - min size of random objects
+     *  - maxSize - max size of random objects
+     */
     public static void main(String[] args) {
-        int semiRefAllocFrequency = DEFAULT_FREQUENCY;
-        long minSize = DEFAULT_MIN_SIZE,
-                maxSize = DEFAULT_MAX_SIZE;
-
-        if ( args.length >= 3 ) {
-            semiRefAllocFrequency = Integer.parseInt(args[2]);
-        }
+        long minSize = DEFAULT_MIN_SIZE;
+        long maxSize = DEFAULT_MAX_SIZE;
 
         if ( args.length >= 2) {
             maxSize = getBytesCount(args[1]);
@@ -60,46 +61,49 @@
             minSize = getBytesCount(args[0]);
         }
 
-        new TestSoftReferencesBehaviorOnOOME().softReferencesOom(minSize, maxSize, semiRefAllocFrequency);
+        new TestSoftReferencesBehaviorOnOOME().softReferencesOom(minSize, maxSize);
     }
 
     /**
      * Test that all SoftReferences has been cleared at time of OOM.
      */
-    void softReferencesOom(long minSize, long maxSize, int semiRefAllocFrequency) {
-        System.out.format( "minSize = %d, maxSize = %d, freq = %d%n", minSize, maxSize, semiRefAllocFrequency );
-        long counter = 0;
+    void softReferencesOom(long minSize, long maxSize) {
+        System.out.format( "minSize = %d, maxSize = %d%n", minSize, maxSize );
+
+        LinkedList<SoftReference> arrSoftRefs = new LinkedList();
+        staticRef = arrSoftRefs;
+        LinkedList arrObjects = new LinkedList();
+        staticRef = arrObjects;
 
         long multiplier = maxSize - minSize;
-        LinkedList<SoftReference> arrSoftRefs = new LinkedList();
-        LinkedList arrObjects = new LinkedList();
         long numberOfNotNulledObjects = 0;
-        long oomSoftArraySize = 0;
 
         try {
-            while (true) {
-                // Keep every Xth object to make sure we hit OOM pretty fast
-                if (counter % semiRefAllocFrequency != 0) {
-                    long allocationSize = ((int) (rndGenerator.nextDouble() * multiplier))
-                            + minSize;
-                    arrObjects.add(new byte[(int)allocationSize]);
-                } else {
-                    arrSoftRefs.add(new SoftReference(new Object()));
-                }
+
+            // Lets allocate as many as we can - taking size of all SoftRerefences
+            // by minimum. So it can provoke some GC but we surely will allocate enough.
+            long numSofts = (long) ((0.95 * Runtime.getRuntime().totalMemory()) / minSize);
+            System.out.println("num Soft: " + numSofts);
+
+            while (numSofts-- > 0) {
+                int allocationSize = ((int) (RND_GENERATOR.nextDouble() * multiplier))
+                            + (int)minSize;
+                arrSoftRefs.add(new SoftReference(new byte[allocationSize]));
+            }
 
-                counter++;
-                if (counter == Long.MAX_VALUE) {
-                    counter = 0;
-                }
+            System.out.println("free: " + Runtime.getRuntime().freeMemory());
+
+            // provoke OOME.
+            while (true) {
+                arrObjects.add(new byte[(int) Runtime.getRuntime().totalMemory()]);
             }
+
         } catch (OutOfMemoryError oome) {
+
             // Clear allocated ballast, so we don't get another OOM.
-
+            staticRef = null;
             arrObjects = null;
-
-            // Get the number of soft refs first, so we don't trigger
-            // another OOM.
-            oomSoftArraySize = arrSoftRefs.size();
+            long oomSoftArraySize = arrSoftRefs.size();
 
             for (SoftReference sr : arrSoftRefs) {
                 Object o = sr.get();
@@ -111,15 +115,14 @@
 
             // Make sure we clear all refs before we return failure
             arrSoftRefs = null;
-
-            if (numberOfNotNulledObjects > 0) {
-                throw new RuntimeException(numberOfNotNulledObjects + " out of "
-                        + oomSoftArraySize + " SoftReferences was not "
-                        + "null at time of OutOfMemoryError");
-            }
+            Asserts.assertFalse(numberOfNotNulledObjects > 0,
+                    "" + numberOfNotNulledObjects + " out of "
+                    + oomSoftArraySize + " SoftReferences was not "
+                    + "null at time of OutOfMemoryError"
+            );
         } finally {
-            arrSoftRefs = null;
-            arrObjects = null;
+            Asserts.assertTrue(arrObjects == null, "OOME hasn't been provoked");
+            Asserts.assertTrue(arrSoftRefs == null, "OOME hasn't been provoked");
         }
     }
 
@@ -128,9 +131,7 @@
         long mod = 1;
 
         if (arg.trim().length() >= 2) {
-            mod = postfixes.indexOf(
-                    arg.trim().charAt(arg.length() - 1)
-            );
+            mod = postfixes.indexOf(arg.trim().charAt(arg.length() - 1));
 
             if (mod != -1) {
                 mod = (long) Math.pow(1024, mod+1);
@@ -143,7 +144,8 @@
         return Long.parseLong(arg) * mod;
     }
 
+    private static final Random RND_GENERATOR = Utils.getRandomInstance();
     private static final long DEFAULT_MIN_SIZE = 512;
     private static final long DEFAULT_MAX_SIZE = 1024;
-    private static final int DEFAULT_FREQUENCY = 4;
+    private static Object staticRef; // to prevent compile optimisations
 }
--- a/hotspot/test/gc/ergonomics/TestDynamicNumberOfGCThreads.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/test/gc/ergonomics/TestDynamicNumberOfGCThreads.java	Fri May 08 13:25:11 2015 -0400
@@ -44,14 +44,24 @@
   }
 
   private static void verifyDynamicNumberOfGCThreads(OutputAnalyzer output) {
+    output.shouldHaveExitValue(0); // test should run succesfully
     output.shouldContain("new_active_workers");
-    output.shouldHaveExitValue(0);
   }
 
   private static void testDynamicNumberOfGCThreads(String gcFlag) throws Exception {
     // UseDynamicNumberOfGCThreads and TraceDynamicGCThreads enabled
-    ProcessBuilder pb_enabled =
-      ProcessTools.createJavaProcessBuilder("-XX:+" + gcFlag, "-Xmx10M", "-XX:+PrintGCDetails",  "-XX:+UseDynamicNumberOfGCThreads", "-XX:+TraceDynamicGCThreads", GCTest.class.getName());
+    String[] baseArgs = {"-XX:+" + gcFlag, "-Xmx10M", "-XX:+PrintGCDetails",  "-XX:+UseDynamicNumberOfGCThreads", "-XX:+TraceDynamicGCThreads", GCTest.class.getName()};
+
+    // Base test with gc and +UseDynamicNumberOfGCThreads:
+    ProcessBuilder pb_enabled = ProcessTools.createJavaProcessBuilder(baseArgs);
+    verifyDynamicNumberOfGCThreads(new OutputAnalyzer(pb_enabled.start()));
+
+    // Ensure it also works on uniprocessors or if user specifies -XX:ParallelGCThreads=1:
+    String[] extraArgs = {"-XX:+UnlockDiagnosticVMOptions", "-XX:+ForceDynamicNumberOfGCThreads", "-XX:ParallelGCThreads=1"};
+    String[] finalArgs = new String[baseArgs.length + extraArgs.length];
+    System.arraycopy(extraArgs, 0, finalArgs, 0,                extraArgs.length);
+    System.arraycopy(baseArgs,  0, finalArgs, extraArgs.length, baseArgs.length);
+    pb_enabled = ProcessTools.createJavaProcessBuilder(finalArgs);
     verifyDynamicNumberOfGCThreads(new OutputAnalyzer(pb_enabled.start()));
   }
 
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData.java	Fri May 08 13:25:11 2015 -0400
@@ -76,7 +76,6 @@
         printTestInfo(maxCacheSize);
 
         vmOpts.add("-XX:G1ConcRSLogCacheSize=" + hotCardTableSize);
-        vmOpts.addAll(Arrays.asList(Utils.getTestJavaOpts()));
 
         // for 32 bits ObjectAlignmentInBytes is not a option
         if (Platform.is32bit()) {
@@ -98,7 +97,7 @@
 
     private void performTest(List<String> opts) throws Exception {
         ProcessBuilder pb
-                = ProcessTools.createJavaProcessBuilder(
+                = ProcessTools.createJavaProcessBuilder(true,
                         opts.toArray(new String[opts.size()])
                 );
 
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData05.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData05.java	Fri May 08 13:25:11 2015 -0400
@@ -23,7 +23,7 @@
 
 /**
  * @test TestShrinkAuxiliaryData05
- * @bug 8038423 8061715
+ * @bug 8038423 8061715 8078405
  * @summary Checks that decommitment occurs for JVM with different
  * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
  * @requires vm.gc=="G1" | vm.gc=="null"
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData10.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData10.java	Fri May 08 13:25:11 2015 -0400
@@ -23,7 +23,7 @@
 
 /**
  * @test TestShrinkAuxiliaryData10
- * @bug 8038423 8061715
+ * @bug 8038423 8061715 8078405
  * @summary Checks that decommitment occurs for JVM with different
  * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
  * @requires vm.gc=="G1" | vm.gc=="null"
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData15.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData15.java	Fri May 08 13:25:11 2015 -0400
@@ -23,7 +23,7 @@
 
 /**
  * @test TestShrinkAuxiliaryData15
- * @bug 8038423 8061715
+ * @bug 8038423 8061715 8078405
  * @summary Checks that decommitment occurs for JVM with different
  * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
  * @requires vm.gc=="G1" | vm.gc=="null"
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData20.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData20.java	Fri May 08 13:25:11 2015 -0400
@@ -23,7 +23,7 @@
 
 /**
  * @test TestShrinkAuxiliaryData20
- * @bug 8038423 8061715
+ * @bug 8038423 8061715 8078405
  * @summary Checks that decommitment occurs for JVM with different
  * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
  * @requires vm.gc=="G1" | vm.gc=="null"
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData25.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData25.java	Fri May 08 13:25:11 2015 -0400
@@ -23,7 +23,7 @@
 
 /**
  * @test TestShrinkAuxiliaryData25
- * @bug 8038423 8061715
+ * @bug 8038423 8061715 8078405
  * @summary Checks that decommitment occurs for JVM with different
  * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
  * @requires vm.gc=="G1" | vm.gc=="null"
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData30.java	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData30.java	Fri May 08 13:25:11 2015 -0400
@@ -23,7 +23,7 @@
 
 /**
  * @test TestShrinkAuxiliaryData30
- * @bug 8038423 8061715
+ * @bug 8038423 8061715 8078405
  * @summary Checks that decommitment occurs for JVM with different
  * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
  * @requires vm.gc=="G1" | vm.gc=="null"
--- a/hotspot/test/test_env.sh	Tue May 05 16:09:30 2015 -0400
+++ b/hotspot/test/test_env.sh	Fri May 08 13:25:11 2015 -0400
@@ -188,6 +188,10 @@
 if [ $? = 0 ]
 then
   VM_CPU="ppc"
+  if [ $VM_BITS = "64" ]
+  then
+    VM_CPU="ppc64"
+  fi
 fi
 grep "ia64" vm_version.out > ${NULL}
 if [ $? = 0 ]