8154483: update IGV with improvements from Graal
authornever
Fri, 29 Apr 2016 12:56:27 -0700
changeset 38224 ebbdfe0f6869
parent 38223 8d40a26addb9
child 38225 1e9db94426bd
8154483: update IGV with improvements from Graal Reviewed-by: kvn
hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/FolderNode.java
hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java
hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/ImportAction.java
hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/SaveAllAction.java
hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/layer.xml
hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/GraphDocument.java
hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java
hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Properties.java
hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java
hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/InputGraphProvider.java
hotspot/src/share/tools/IdealGraphVisualizer/Graph/nbproject/project.xml
hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Slot.java
hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java
hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorInputGraphProvider.java
hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java
hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/NodeQuickSearch.java
hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/layer.xml
hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/LineWidget.java
hotspot/src/share/tools/IdealGraphVisualizer/nbproject/project.properties
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/FolderNode.java	Fri Apr 29 14:32:19 2016 +0200
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/FolderNode.java	Fri Apr 29 12:56:27 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * 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,13 @@
 
 import com.sun.hotspot.igv.coordinator.actions.RemoveCookie;
 import com.sun.hotspot.igv.data.*;
+import com.sun.hotspot.igv.util.PropertiesSheet;
 import java.awt.Image;
 import java.util.List;
 import org.openide.nodes.AbstractNode;
 import org.openide.nodes.Children;
 import org.openide.nodes.Node;
+import org.openide.nodes.Sheet;
 import org.openide.util.ImageUtilities;
 import org.openide.util.lookup.AbstractLookup;
 import org.openide.util.lookup.InstanceContent;
@@ -75,6 +77,16 @@
     }
 
     @Override
+    protected Sheet createSheet() {
+        Sheet s = super.createSheet();
+        if (children.folder instanceof Properties.Entity) {
+            Properties.Entity p = (Properties.Entity) children.folder;
+            PropertiesSheet.initializeSheet(p.getProperties(), s);
+        }
+        return s;
+    }
+
+    @Override
     public Image getIcon(int i) {
         return ImageUtilities.loadImage("com/sun/hotspot/igv/coordinator/images/folder.png");
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java	Fri Apr 29 14:32:19 2016 +0200
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java	Fri Apr 29 12:56:27 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -124,6 +124,8 @@
 
     public void clear() {
         document.clear();
+        root = new FolderNode(document);
+        manager.setRootContext(root);
     }
 
     @Override
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/ImportAction.java	Fri Apr 29 14:32:19 2016 +0200
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/ImportAction.java	Fri Apr 29 12:56:27 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * 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,31 +31,47 @@
 import com.sun.hotspot.igv.data.serialization.ParseMonitor;
 import com.sun.hotspot.igv.data.serialization.Parser;
 import com.sun.hotspot.igv.settings.Settings;
-import java.awt.event.InputEvent;
-import java.awt.event.KeyEvent;
+import java.awt.event.ActionEvent;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.nio.channels.FileChannel;
 import java.nio.file.StandardOpenOption;
-import javax.swing.Action;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 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.util.Exceptions;
+import org.openide.util.RequestProcessor;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionReferences;
+import org.openide.awt.ActionRegistration;
 import org.openide.util.HelpCtx;
 import org.openide.util.NbBundle;
-import org.openide.util.RequestProcessor;
-import org.openide.util.actions.CallableSystemAction;
+import org.openide.util.actions.SystemAction;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
-public final class ImportAction extends CallableSystemAction {
+
+@ActionID(
+        category = "File",
+        id = "com.sun.hotspot.igv.coordinator.actions.ImportAction"
+)
+@ActionRegistration(
+        iconBase = "com/sun/hotspot/igv/coordinator/images/import.png",
+        displayName = "#CTL_ImportAction"
+)
+@ActionReferences({
+    @ActionReference(path = "Menu/File", position = 0),
+    @ActionReference(path = "Shortcuts", name = "C-O")
+})
+public final class ImportAction extends SystemAction {
     private static final int WORKUNITS = 10000;
 
     public static FileFilter getFileFilter() {
@@ -74,74 +90,77 @@
     }
 
     @Override
-    public void performAction() {
-
+    public void actionPerformed(ActionEvent e) {
         JFileChooser fc = new JFileChooser();
         fc.setFileFilter(ImportAction.getFileFilter());
         fc.setCurrentDirectory(new File(Settings.get().get(Settings.DIRECTORY, Settings.DIRECTORY_DEFAULT)));
+        fc.setMultiSelectionEnabled(true);
 
         if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
-            File file = fc.getSelectedFile();
-
-            File dir = file;
-            if (!dir.isDirectory()) {
-                dir = dir.getParentFile();
-            }
+            for (final File file : fc.getSelectedFiles()) {
+                File dir = file;
+                if (!dir.isDirectory()) {
+                    dir = dir.getParentFile();
+                }
 
-            Settings.get().put(Settings.DIRECTORY, dir.getAbsolutePath());
-            try {
-                final FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.READ);
-                final ProgressHandle handle = ProgressHandleFactory.createHandle("Opening file " + file.getName());
-                handle.start(WORKUNITS);
-                final long start = channel.size();
-                ParseMonitor monitor = new ParseMonitor() {
-                    @Override
-                    public void updateProgress() {
-                        try {
-                            int prog = (int) (WORKUNITS * (double) channel.position() / (double) start);
-                            handle.progress(prog);
-                        } catch (IOException ex) {
-                        }
-                    }
-                    @Override
-                    public void setState(String state) {
-                        updateProgress();
-                        handle.progress(state);
+                Settings.get().put(Settings.DIRECTORY, dir.getAbsolutePath());
+                try {
+                    final FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.READ);
+                    final ProgressHandle handle = ProgressHandleFactory.createHandle("Opening file " + file.getName());
+                    handle.start(WORKUNITS);
+                    final long startTime = System.currentTimeMillis();
+                    final long start = channel.size();
+                    ParseMonitor monitor = new ParseMonitor() {
+                            @Override
+                            public void updateProgress() {
+                                try {
+                                    int prog = (int) (WORKUNITS * (double) channel.position() / (double) start);
+                                    handle.progress(prog);
+                                } catch (IOException ex) {
+                                }
+                            }
+                            @Override
+                            public void setState(String state) {
+                                updateProgress();
+                                handle.progress(state);
+                            }
+                        };
+                    final GraphParser parser;
+                    final OutlineTopComponent component = OutlineTopComponent.findInstance();
+                    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;
                     }
-                };
-                final GraphParser parser;
-                final OutlineTopComponent component = OutlineTopComponent.findInstance();
-                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() {
+                                try {
+                                    final GraphDocument document = parser.parse();
+                                    if (document != null) {
+                                        SwingUtilities.invokeLater(new Runnable(){
+                                                @Override
+                                                public void run() {
+                                                    component.requestActive();
+                                                    component.getDocument().addGraphDocument(document);
+                                                }
+                                            });
+                                    }
+                                } catch (IOException ex) {
+                                    Exceptions.printStackTrace(ex);
+                                }
+                                handle.finish();
+                                long stop = System.currentTimeMillis();
+                                Logger.getLogger(getClass().getName()).log(Level.INFO, "Loaded in " + file + " in " + ((stop - startTime) / 1000.0) + " seconds");
+                            }
+                        });
+                } catch (FileNotFoundException ex) {
+                    Exceptions.printStackTrace(ex);
+                } catch (IOException ex) {
+                    Exceptions.printStackTrace(ex);
                 }
-                RequestProcessor.getDefault().post(new Runnable() {
-                    @Override
-                    public void run() {
-                        try {
-                            final GraphDocument document = parser.parse();
-                            if (document != null) {
-                                SwingUtilities.invokeLater(new Runnable(){
-                                    @Override
-                                    public void run() {
-                                        component.requestActive();
-                                        component.getDocument().addGraphDocument(document);
-                                    }
-                                });
-                            }
-                        } catch (IOException ex) {
-                            Exceptions.printStackTrace(ex);
-                        }
-                        handle.finish();
-                    }
-                });
-            } catch (FileNotFoundException ex) {
-                Exceptions.printStackTrace(ex);
-            } catch (IOException ex) {
-                Exceptions.printStackTrace(ex);
             }
         }
     }
@@ -151,11 +170,6 @@
         return NbBundle.getMessage(ImportAction.class, "CTL_ImportAction");
     }
 
-    public ImportAction() {
-        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.png";
@@ -165,9 +179,4 @@
     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/SaveAllAction.java	Fri Apr 29 14:32:19 2016 +0200
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/SaveAllAction.java	Fri Apr 29 12:56:27 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
  * 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,30 @@
 import java.awt.event.KeyEvent;
 import javax.swing.Action;
 import javax.swing.KeyStroke;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionReferences;
+import org.openide.awt.ActionRegistration;
 import org.openide.util.HelpCtx;
 import org.openide.util.NbBundle;
+import org.openide.util.NbBundle.Messages;
 import org.openide.util.actions.CallableSystemAction;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
+@ActionID(
+        category = "File",
+        id = "com.sun.hotspot.igv.coordinator.actions.SaveAllAction"
+)
+@ActionRegistration(
+        displayName = "#CTL_SaveAllAction"
+)
+@ActionReferences({
+    @ActionReference(path = "Menu/File", position = 0),
+    @ActionReference(path = "Shortcuts", name = "C-S")
+})
 public final class SaveAllAction extends CallableSystemAction {
 
     @Override
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/layer.xml	Fri Apr 29 14:32:19 2016 +0200
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/layer.xml	Fri Apr 29 12:56:27 2016 -0700
@@ -18,6 +18,8 @@
     
     <folder name="Menu">
         <folder name="File">
+            <file name="Export_hidden"/>
+            <file name="Import_hidden"/>
             <file name="Separator2.instance_hidden"/>
             <file name="Separator3.instance_hidden"/>
             <file name="SeparatorOpen.instance_hidden"/>
@@ -43,11 +45,11 @@
             </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" />
+                <attr name="position" intvalue="400"/>
             </file>
             <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" />
+                <attr name="position" intvalue="500"/>
             </file>
             
             <!-- Hidden menu entries from other modules -->
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/GraphDocument.java	Fri Apr 29 14:32:19 2016 +0200
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/GraphDocument.java	Fri Apr 29 12:56:27 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,11 +51,13 @@
     }
 
     public void addGraphDocument(GraphDocument document) {
-        for (FolderElement e : document.elements) {
-            e.setParent(this);
-            this.addElement(e);
+        if (document != this) {
+            for (FolderElement e : document.elements) {
+                e.setParent(this);
+                this.addElement(e);
+            }
+            document.clear();
         }
-        document.clear();
         getChangedEvent().fire();
     }
 
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java	Fri Apr 29 14:32:19 2016 +0200
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java	Fri Apr 29 12:56:27 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * 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,7 +90,9 @@
     public void addNode(int id) {
         InputNode node = graph.getNode(id);
         assert node != null;
-        assert !nodes.contains(node) : "duplicate : " + node;
+        // nodes.contains(node) is too expensive for large graphs so
+        // just make sure the Graph doesn't know it yet.
+        assert graph.getBlock(id) == null : "duplicate : " + node;
         graph.setBlock(node, this);
         nodes.add(node);
     }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Properties.java	Fri Apr 29 14:32:19 2016 +0200
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Properties.java	Fri Apr 29 12:56:27 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * 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,9 @@
 package com.sun.hotspot.igv.data;
 
 import java.io.Serializable;
+import java.lang.ref.WeakReference;
 import java.util.*;
+import java.util.Map.Entry;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
@@ -36,7 +38,7 @@
 public class Properties implements Serializable, Iterable<Property> {
 
     public static final long serialVersionUID = 1L;
-    private String[] map = new String[4];
+    protected String[] map = new String[4];
 
     public Properties() {
     }
@@ -102,6 +104,59 @@
         System.arraycopy(p.map, 0, map, 0, p.map.length);
     }
 
+    protected Properties(String[] map) {
+        this.map = map;
+    }
+
+    static class SharedProperties extends Properties {
+        int hashCode;
+
+        SharedProperties(String[] map) {
+            super(map);
+            this.hashCode = Arrays.hashCode(map);
+        }
+
+        @Override
+        protected void setPropertyInternal(String name, String value) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (this == other) {
+                return true;
+            }
+            if (!(other instanceof SharedProperties)) {
+                return super.equals(other);
+            }
+            SharedProperties props2 = (SharedProperties) other;
+            return Arrays.equals(map, props2.map);
+        }
+
+        @Override
+        public int hashCode() {
+            return hashCode;
+        }
+    }
+
+    private static class PropertyCache {
+        static WeakHashMap<SharedProperties, WeakReference<SharedProperties>> immutableCache = new WeakHashMap<>();
+
+        static synchronized SharedProperties intern(Properties properties) {
+            String[] map = properties.map;
+            SharedProperties key = new SharedProperties(map);
+            WeakReference<SharedProperties> entry = immutableCache.get(key);
+            if (entry != null) {
+                SharedProperties props = entry.get();
+                if (props != null) {
+                    return props;
+                }
+            }
+            immutableCache.put(key, new WeakReference<>(key));
+            return key;
+        }
+    }
+
     public static class Entity implements Provider {
 
         private Properties properties;
@@ -118,6 +173,10 @@
         public Properties getProperties() {
             return properties;
         }
+
+        public void internProperties() {
+            properties = PropertyCache.intern(properties);
+        }
     }
 
     public interface PropertyMatcher {
@@ -322,8 +381,8 @@
     public void setProperty(String name, String value) {
         setPropertyInternal(name.intern(), value != null ? value.intern() : null);
     }
-    private void setPropertyInternal(String name, String value) {
 
+    protected 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];
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java	Fri Apr 29 14:32:19 2016 +0200
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java	Fri Apr 29 12:56:27 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * 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.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.channels.ReadableByteChannel;
+import java.nio.charset.Charset;
 import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -68,6 +69,8 @@
 
     private static final String NO_BLOCK = "noBlock";
 
+    private static final Charset utf8 = Charset.forName("UTF-8");
+
     private final GroupCallback callback;
     private final List<Object> constantPool;
     private final ByteBuffer buffer;
@@ -275,28 +278,36 @@
         hashStack = new LinkedList<>();
         this.monitor = monitor;
         try {
-            this.digest = MessageDigest.getInstance("SHA-256");
+            this.digest = MessageDigest.getInstance("SHA-1");
         } catch (NoSuchAlgorithmException e) {
         }
     }
 
     private void fill() throws IOException {
+        // All the data between lastPosition and position has been
+        // used so add it to the digest.
+        int position = buffer.position();
+        buffer.position(lastPosition);
+        byte[] remaining = new byte[position - buffer.position()];
+        buffer.get(remaining);
+        digest.update(remaining);
+        assert position == buffer.position();
+
         buffer.compact();
         if (channel.read(buffer) < 0) {
             throw new EOFException();
         }
         buffer.flip();
+        lastPosition = buffer.position();
     }
 
     private void ensureAvailable(int i) throws IOException {
+        if (i > buffer.capacity()) {
+            throw new IllegalArgumentException(String.format("Can not request %d bytes: buffer capacity is %d", i, buffer.capacity()));
+        }
         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 {
@@ -330,12 +341,7 @@
     }
 
     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();
+        return new String(readBytes(), utf8).intern();
     }
 
     private byte[] readBytes() throws IOException {
@@ -343,10 +349,15 @@
         if (len < 0) {
             return null;
         }
-        ensureAvailable(len);
-        byte[] data = new byte[len];
-        buffer.get(data);
-        return data;
+        byte[] b = new byte[len];
+        int bytesRead = 0;
+        while (bytesRead < b.length) {
+            int toRead = Math.min(b.length - bytesRead, buffer.capacity());
+            ensureAvailable(toRead);
+            buffer.get(b, bytesRead, toRead);
+            bytesRead += toRead;
+        }
+        return b;
     }
 
     private String readIntsToString() throws IOException {
@@ -643,6 +654,7 @@
         int bci = readInt();
         Group group = new Group(parent);
         group.getProperties().setProperty("name", name);
+        parseProperties(group.getProperties());
         if (method != null) {
             InputMethod inMethod = new InputMethod(group, method.name, shortName, bci);
             inMethod.setBytecodes("TODO");
@@ -651,13 +663,25 @@
         return group;
     }
 
+    int lastPosition = 0;
+
     private InputGraph parseGraph() throws IOException {
         if (monitor != null) {
             monitor.updateProgress();
         }
         String title = readPoolObject(String.class);
         digest.reset();
+        lastPosition = buffer.position();
         InputGraph graph = parseGraph(title);
+
+        int position = buffer.position();
+        buffer.position(lastPosition);
+        byte[] remaining = new byte[position - buffer.position()];
+        buffer.get(remaining);
+        digest.update(remaining);
+        assert position == buffer.position();
+        lastPosition = buffer.position();
+
         byte[] d = digest.digest();
         byte[] hash = hashStack.peek();
         if (hash != null && Arrays.equals(hash, d)) {
@@ -669,11 +693,24 @@
         return graph;
     }
 
+    private void parseProperties(Properties properties) throws IOException {
+        int propCount = readShort();
+        for (int j = 0; j < propCount; j++) {
+            String key = readPoolObject(String.class);
+            Object value = readPropertyObject();
+            properties.setProperty(key, value != null ? value.toString() : "null");
+        }
+    }
+
     private InputGraph parseGraph(String title) throws IOException {
         InputGraph graph = new InputGraph(title);
+        parseProperties(graph.getProperties());
         parseNodes(graph);
         parseBlocks(graph);
         graph.ensureNodesInBlocks();
+        for (InputNode node : graph.getNodes()) {
+            node.internProperties();
+        }
         return graph;
     }
 
@@ -822,9 +859,10 @@
         }
     }
 
+    static final Pattern templatePattern = Pattern.compile("\\{(p|i)#([a-zA-Z0-9$_]+)(/(l|m|s))?\\}");
+
     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);
+        Matcher m = templatePattern.matcher(template);
         StringBuffer sb = new StringBuffer();
         while (m.find()) {
             String name = m.group(2);
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/InputGraphProvider.java	Fri Apr 29 14:32:19 2016 +0200
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/InputGraphProvider.java	Fri Apr 29 12:56:27 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
  * 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,4 +37,14 @@
     InputGraph getGraph();
 
     void setSelectedNodes(Set<InputNode> nodes);
+
+    /**
+     * @return an iterator walking forward through the {@link InputGraph}s following the {@link #getGraph()}
+     */
+    Iterable<InputGraph> searchForward();
+
+    /**
+     * @return an iterator walking backward through the {@link InputGraph}s preceeding the {@link #getGraph()}
+     */
+    Iterable<InputGraph> searchBackward();
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/nbproject/project.xml	Fri Apr 29 14:32:19 2016 +0200
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/nbproject/project.xml	Fri Apr 29 12:56:27 2016 -0700
@@ -22,6 +22,14 @@
                         <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>
             </module-dependencies>
             <public-packages>
                 <package>com.sun.hotspot.igv.graph</package>
--- a/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Slot.java	Fri Apr 29 14:32:19 2016 +0200
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Slot.java	Fri Apr 29 12:56:27 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
 import com.sun.hotspot.igv.data.Source;
 import com.sun.hotspot.igv.layout.Port;
 import com.sun.hotspot.igv.layout.Vertex;
+import com.sun.hotspot.igv.util.StringUtils;
 import java.awt.Color;
 import java.awt.Font;
 import java.awt.FontMetrics;
@@ -141,7 +142,7 @@
         sb.append(text);
 
         for (InputNode n : getSource().getSourceNodes()) {
-            sb.append("Node (ID=" + n.getId() + "): " + n.getProperties().get("name"));
+            sb.append(StringUtils.escapeHTML("Node (ID=" + n.getId() + "): " + n.getProperties().get("name")));
             sb.append("<br>");
         }
 
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java	Fri Apr 29 14:32:19 2016 +0200
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java	Fri Apr 29 12:56:27 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -445,5 +445,48 @@
     void close() {
         filterChain.getChangedEvent().removeListener(filterChainChangedListener);
         sequenceFilterChain.getChangedEvent().removeListener(filterChainChangedListener);
+    }
+
+    Iterable<InputGraph> getGraphsForward() {
+        return new Iterable<InputGraph>() {
+
+            @Override
+            public Iterator<InputGraph> iterator() {
+                return new Iterator<InputGraph>() {
+                    int index = getFirstPosition();
+
+                    @Override
+                    public boolean hasNext() {
+                        return index + 1 < graphs.size();
+                    }
+
+                    @Override
+                    public InputGraph next() {
+                        return graphs.get(++index);
+                    }
+                };
+            }
+        };
+    }
+
+    Iterable<InputGraph> getGraphsBackward() {
+        return new Iterable<InputGraph>() {
+            @Override
+            public Iterator<InputGraph> iterator() {
+                return new Iterator<InputGraph>() {
+                    int index = getFirstPosition();
+
+                    @Override
+                    public boolean hasNext() {
+                        return index - 1 > 0;
+                    }
+
+                    @Override
+                    public InputGraph next() {
+                        return graphs.get(--index);
+                    }
+                };
+            }
+        };
+    }
 }
-}
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorInputGraphProvider.java	Fri Apr 29 14:32:19 2016 +0200
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorInputGraphProvider.java	Fri Apr 29 12:56:27 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,4 +50,14 @@
     public void setSelectedNodes(Set<InputNode> nodes) {
         editor.setSelectedNodes(nodes);
     }
+
+    @Override
+    public Iterable<InputGraph> searchBackward() {
+        return editor.getDiagramModel().getGraphsBackward();
+    }
+
+    @Override
+    public Iterable<InputGraph> searchForward() {
+        return editor.getDiagramModel().getGraphsForward();
+    }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java	Fri Apr 29 14:32:19 2016 +0200
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java	Fri Apr 29 12:56:27 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -289,7 +289,10 @@
             quicksearch = (Component) quicksearch.getClass().getConstructor(KeyStroke.class).newInstance(new Object[]{null});
         } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) {
         }
-        quicksearch.setMinimumSize(quicksearch.getPreferredSize()); // necessary for GTK LAF
+        Dimension preferredSize = quicksearch.getPreferredSize();
+        preferredSize = new Dimension((int) preferredSize.getWidth() * 2, (int) preferredSize.getHeight());
+        quicksearch.setMinimumSize(preferredSize); // necessary for GTK LAF
+        quicksearch.setPreferredSize(preferredSize);
         toolBar.add(quicksearch);
 
         centerPanel = new JPanel();
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/NodeQuickSearch.java	Fri Apr 29 14:32:19 2016 +0200
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/NodeQuickSearch.java	Fri Apr 29 12:56:27 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * 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;
 
+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.RegexpPropertyMatcher;
@@ -81,57 +82,67 @@
 
         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)"
-                );
+            InputGraph matchGraph = p.getGraph();
+            // Search the current graph
+            List<InputNode> matches = findMatches(name, value, p.getGraph(), response);
+            if (matches == null) {
+                // See if the it hits in a later graph
+                for (InputGraph graph : p.searchForward()) {
+                    matches = findMatches(name, value, graph, response);
+                    if (matches != null) {
+                        matchGraph = graph;
+                        break;
+                    }
+                }
+            }
+            if (matches == null) {
+                // See if it hits in a earlier graph
+                for (InputGraph graph : p.searchBackward()) {
+                    matches = findMatches(name, value, graph, response);
+                    if (matches != null) {
+                        matchGraph = graph;
+                        break;
+                    }
+                }
             }
 
             if (matches != null) {
                 final Set<InputNode> set = new HashSet<>(matches);
+                final InputGraph theGraph = p.getGraph() != matchGraph ? matchGraph : null;
                 response.addResult(new Runnable() {
                     @Override
-                        public void run() {
-                            final EditorTopComponent comp = EditorTopComponent.getActive();
-                            if (comp != null) {
-                                comp.setSelectedNodes(set);
-                                comp.requestActive();
+                    public void run() {
+                        final EditorTopComponent comp = EditorTopComponent.getActive();
+                        if (comp != null) {
+                            if (theGraph != null) {
+                                comp.getDiagramModel().selectGraph(theGraph);
                             }
+                            comp.setSelectedNodes(set);
+                            comp.requestActive();
                         }
-                    },
-                    "All " + matches.size() + " matching nodes (" + name + "=" + value + ")"
+                    }
+                },
+                        "All " + matches.size() + " matching nodes (" + name + "=" + value + ")" + (theGraph != null ? " in " + theGraph.getName() : "")
                 );
 
                 // 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();
+                        public void run() {
+                            final EditorTopComponent comp = EditorTopComponent.getActive();
+                            if (comp != null) {
+                                final Set<InputNode> tmpSet = new HashSet<>();
+                                tmpSet.add(n);
+                                if (theGraph != null) {
+                                    comp.getDiagramModel().selectGraph(theGraph);
                                 }
+                                comp.setSelectedNodes(tmpSet);
+                                comp.requestActive();
                             }
-                        },
-                        n.getProperties().get(name) + " (" + n.getId() + " " + n.getProperties().get("name") + ")"
+                        }
+                    },
+                            n.getProperties().get(name) + " (" + n.getId() + " " + n.getProperties().get("name") + ")" + (theGraph != null ? " in " + theGraph.getName() : "")
                     );
                 }
             }
@@ -139,4 +150,27 @@
             System.out.println("no input graph provider!");
         }
     }
+
+    private List<InputNode> findMatches(String name, String value, InputGraph inputGraph, SearchResponse response) {
+        try {
+            RegexpPropertyMatcher matcher = new RegexpPropertyMatcher(name, value, Pattern.CASE_INSENSITIVE);
+            Properties.PropertySelector<InputNode> selector = new Properties.PropertySelector<>(inputGraph.getNodes());
+            List<InputNode> matches = selector.selectMultiple(matcher);
+            return matches.size() == 0 ? null : matches;
+        } 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)"
+            );
+        }
+        return null;
+    }
 }
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/layer.xml	Fri Apr 29 14:32:19 2016 +0200
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/layer.xml	Fri Apr 29 12:56:27 2016 -0700
@@ -61,14 +61,26 @@
                 <attr name="position" intvalue="710"/>
             </file>
         </folder>
+        <folder name="Window">
+            <file name="Tools_hidden"/>
+            <file name="Web_hidden"/>
+            <file name="org-netbeans-modules-tasks-ui-DashboardTopComponent.shadow_hidden"/>
+        </folder>
     </folder>
 
     <folder name="QuickSearch">
+        <file name="Actions_hidden"/>
+        <file name="GoToOption_hidden"/>
+        <file name="GoToSymbol_hidden"/>
+        <file name="GoToType_hidden"/>
+        <file name="Help_hidden"/>
+        <file name="Hudson_hidden"/>
         <folder name="Nodes">
             <attr name="command" stringvalue="n"/>
             <attr name="position" intvalue="0"/>
             <file name="com-sun-hotspot-igv-view-NodeQuickSearch.instance"/>
         </folder>
+        <file name="Projects_hidden"/>
     </folder>
     
     <folder name="QuickSearchShadow">
--- a/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/LineWidget.java	Fri Apr 29 14:32:19 2016 +0200
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/LineWidget.java	Fri Apr 29 12:56:27 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * 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 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.util.StringUtils;
 import com.sun.hotspot.igv.view.DiagramScene;
 import java.awt.*;
 import java.awt.geom.Line2D;
@@ -148,7 +149,7 @@
     private String generateToolTipText(List<Connection> conn) {
         StringBuilder sb = new StringBuilder();
         for (Connection c : conn) {
-            sb.append(c.getToolTipText());
+            sb.append(StringUtils.escapeHTML(c.getToolTipText()));
             sb.append("<br>");
         }
         return sb.toString();
--- a/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/project.properties	Fri Apr 29 14:32:19 2016 +0200
+++ b/hotspot/src/share/tools/IdealGraphVisualizer/nbproject/project.properties	Fri Apr 29 12:56:27 2016 -0700
@@ -48,5 +48,5 @@
 
 # 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
+run.args.extra = -J-server -J-da:org.openide.util.RequestProcessor -J-Xms2g -J-Xmx8g -J-Djava.lang.Integer.IntegerCache.high=200000
 debug.args.extra = -J-server -J-da:org.openide.util.RequestProcessor